File indexing completed on 2024-12-08 04:20:01

0001 /*
0002  Copyright (C) 2006 Justin Karneges <justin@affinix.com>
0003 
0004  Permission is hereby granted, free of charge, to any person obtaining a copy
0005  of this software and associated documentation files (the "Software"), to deal
0006  in the Software without restriction, including without limitation the rights
0007  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
0008  copies of the Software, and to permit persons to whom the Software is
0009  furnished to do so, subject to the following conditions:
0010 
0011  The above copyright notice and this permission notice shall be included in
0012  all copies or substantial portions of the Software.
0013 
0014  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0017  AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0018  AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0019  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0020 */
0021 
0022 #include <stdio.h>
0023 #include <stdlib.h>
0024 #include <string.h>
0025 
0026 static char *read_file(const char *fname)
0027 {
0028     FILE *f;
0029     char *buf;
0030     int   size;
0031 
0032     f = fopen(fname, "r");
0033     if (!f)
0034         return 0;
0035 
0036     fseek(f, 0l, SEEK_END);
0037     size = ftell(f);
0038     rewind(f);
0039     buf = malloc(size + 1);
0040     if (!buf) {
0041         fclose(f);
0042         return 0;
0043     }
0044 
0045     fread(buf, size, 1, f);
0046     buf[size] = 0;
0047     fclose(f);
0048 
0049     return buf;
0050 }
0051 
0052 static void write_file(const char *fname, const char *buf)
0053 {
0054     FILE *f;
0055 
0056     f = fopen(fname, "w");
0057     fwrite(buf, strlen(buf), 1, f);
0058     fclose(f);
0059 }
0060 
0061 static char *insert_string(char *buf, char *str, int at)
0062 {
0063     int bsize, slen;
0064     bsize = strlen(buf) + 1;
0065     slen  = strlen(str);
0066 
0067     buf = realloc(buf, bsize + slen);
0068     if (!buf)
0069         return 0;
0070     memmove(buf + at + slen, buf + at, bsize - at);
0071     memcpy(buf + at, str, slen);
0072     return buf;
0073 }
0074 
0075 static int is_include(const char *buf)
0076 {
0077     char *p, *sub;
0078     int   len;
0079 
0080     if (buf[0] != '#')
0081         return 0;
0082 
0083     p = strchr(buf, '\n');
0084     if (!p)
0085         return 0;
0086 
0087     // take the substring
0088     ++buf;
0089     len = p - buf;
0090     sub = malloc(len + 1);
0091     memcpy(sub, buf, len);
0092     sub[len] = 0;
0093 
0094     if (strstr(sub, "include")) {
0095         free(sub);
0096         return 1;
0097     }
0098     free(sub);
0099     return 0;
0100 }
0101 
0102 static const char *find_include(const char *buf)
0103 {
0104     const char *p = buf;
0105 
0106     if (p[0] == '#') {
0107         if (is_include(p))
0108             return p;
0109     }
0110 
0111     while (1) {
0112         p = strstr(p, "\n#");
0113         if (!p)
0114             break;
0115         ++p;
0116         if (is_include(p))
0117             return p;
0118     }
0119 
0120     return 0;
0121 }
0122 
0123 static const char *find_std(const char *buf)
0124 {
0125     const char *p;
0126     p = strstr(buf, "namespace std");
0127     return p;
0128 }
0129 
0130 static const char *skip_to_next_curly(const char *buf)
0131 {
0132     int n;
0133     for (n = 0; buf[n]; ++n) {
0134         if (buf[n] == '{' || buf[n] == '}')
0135             return (buf + n);
0136     }
0137     return 0;
0138 }
0139 
0140 static const char *skip_over_curlies(const char *buf)
0141 {
0142     const char *p;
0143     int         opened;
0144 
0145     p = strchr(buf, '{');
0146     if (!p)
0147         return buf;
0148 
0149     ++p;
0150     opened = 1;
0151     while (opened) {
0152         p = skip_to_next_curly(p);
0153         if (!p)
0154             return 0;
0155         if (*p == '{')
0156             ++opened;
0157         else if (*p == '}')
0158             --opened;
0159         ++p;
0160     }
0161     return p;
0162 }
0163 
0164 void do_it(char *buf, char *ns)
0165 {
0166     char        str[256], str_end[256];
0167     const char *p, *p2;
0168     int         slen, slen_end;
0169     int         at;
0170 
0171     sprintf(str, "namespace %s { // WRAPNS_LINE\n", ns);
0172     slen = strlen(str);
0173 
0174     sprintf(str_end, "} // WRAPNS_LINE\n", ns);
0175     slen_end = strlen(str_end);
0176 
0177     at = 0;
0178     while (1) {
0179         // make sure there is a line left
0180         p = strchr(buf + at, '\n');
0181         if (!p)
0182             break;
0183 
0184         // open the namespace
0185         buf = insert_string(buf, str, at);
0186         at += slen;
0187 
0188         // find an #include, "namespace std", or the end
0189         int f = 0;
0190         p     = find_include(buf + at);
0191         p2    = find_std(buf + at);
0192         if (p && (!p2 || p < p2)) {
0193             f = 1;
0194         } else if (p2) {
0195             f = 2;
0196             p = p2;
0197         }
0198 
0199         if (f == 0) {
0200             // point to the end
0201             at = strlen(buf);
0202         } else if (f == 1) {
0203             printf("found include\n");
0204             at = p - buf;
0205         } else if (f == 2) {
0206             printf("found std\n");
0207             at = p - buf;
0208         }
0209 
0210         // close it
0211         buf = insert_string(buf, str_end, at);
0212         at += slen_end;
0213 
0214         if (f == 1) {
0215             // go to next line
0216             p = strchr(buf + at, '\n');
0217             if (!p)
0218                 break;
0219             at = p - buf + 1;
0220         } else if (f == 2) {
0221             p = skip_over_curlies(buf + at);
0222             if (!p)
0223                 break;
0224             at = p - buf;
0225 
0226             // go to next line
0227             p = strchr(buf + at, '\n');
0228             if (!p)
0229                 break;
0230             at = p - buf + 1;
0231         }
0232     }
0233 }
0234 
0235 int main(int argc, char **argv)
0236 {
0237     char *buf;
0238 
0239     if (argc < 3) {
0240         printf("usage: wrapns [file] [namespace]\n\n");
0241         return 1;
0242     }
0243 
0244     buf = read_file(argv[1]);
0245     do_it(buf, argv[2]);
0246     write_file(argv[1], buf);
0247     free(buf);
0248 
0249     return 0;
0250 }