| 1 | #include <stdio.h> |
| 2 | #include <string.h> |
| 3 | #include <ctype.h> |
| 4 | |
| 5 | |
| 6 | static int check_defines(const char **defs, int defcount, char *tdef) |
| 7 | { |
| 8 | int i, len; |
| 9 | |
| 10 | while (isspace(*tdef)) tdef++; |
| 11 | len = strlen(tdef); |
| 12 | for (i = 0; i < len; i++) |
| 13 | if (tdef[i] == ' ' || tdef[i] == '\r' || tdef[i] == '\n') break; |
| 14 | tdef[i] = 0; |
| 15 | |
| 16 | for (i = 0; i < defcount; i++) |
| 17 | { |
| 18 | if (strcmp(defs[i], tdef) == 0) |
| 19 | return 1; |
| 20 | } |
| 21 | |
| 22 | return 0; |
| 23 | } |
| 24 | |
| 25 | |
| 26 | static void do_counters(char *str) |
| 27 | { |
| 28 | static int counter_id = -1, counter; |
| 29 | char buff[1024]; |
| 30 | char *s = str; |
| 31 | |
| 32 | while ((s = strstr(s, "@@"))) |
| 33 | { |
| 34 | if (s[2] < '0' || s[2] > '9') { s++; continue; } |
| 35 | |
| 36 | if (counter_id != s[2] - '0') { |
| 37 | counter_id = s[2] - '0'; |
| 38 | counter = 1; |
| 39 | } |
| 40 | snprintf(buff, sizeof(buff), "%i%s", counter++, s + 3); |
| 41 | strcpy(s, buff); |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | |
| 46 | int main(int argc, char *argv[]) |
| 47 | { |
| 48 | char buff[1024]; |
| 49 | FILE *fi, *fo; |
| 50 | int skip_mode = 0, ifdef_level = 0, skip_level = 0, line = 0; |
| 51 | |
| 52 | if (argc < 3) |
| 53 | { |
| 54 | printf("usage:\n%s <file_in> <file_out> [defines...]\n", argv[0]); |
| 55 | return 1; |
| 56 | } |
| 57 | |
| 58 | fi = fopen(argv[1], "r"); |
| 59 | if (fi == NULL) |
| 60 | { |
| 61 | printf("failed to open: %s\n", argv[1]); |
| 62 | return 2; |
| 63 | } |
| 64 | |
| 65 | fo = fopen(argv[2], "w"); |
| 66 | if (fo == NULL) |
| 67 | { |
| 68 | printf("failed to open: %s\n", argv[2]); |
| 69 | return 3; |
| 70 | } |
| 71 | |
| 72 | for (++line; !feof(fi); line++) |
| 73 | { |
| 74 | char *fgs; |
| 75 | |
| 76 | fgs = fgets(buff, sizeof(buff), fi); |
| 77 | if (fgs == NULL) break; |
| 78 | |
| 79 | if (buff[0] == '#') |
| 80 | { |
| 81 | /* control char */ |
| 82 | if (strncmp(buff, "#ifdef ", 7) == 0) |
| 83 | { |
| 84 | ifdef_level++; |
| 85 | if (!skip_mode && !check_defines((void *) &argv[3], argc-3, buff + 7)) |
| 86 | skip_mode = 1, skip_level = ifdef_level; |
| 87 | } |
| 88 | else if (strncmp(buff, "#ifndef ", 8) == 0) |
| 89 | { |
| 90 | ifdef_level++; |
| 91 | if (!skip_mode && check_defines((void *) &argv[3], argc-3, buff + 8)) |
| 92 | skip_mode = 1, skip_level = ifdef_level; |
| 93 | } |
| 94 | else if (strncmp(buff, "#else", 5) == 0) |
| 95 | { |
| 96 | if (!skip_mode || skip_level == ifdef_level) |
| 97 | skip_mode ^= 1, skip_level = ifdef_level; |
| 98 | } |
| 99 | else if (strncmp(buff, "#endif", 6) == 0) |
| 100 | { |
| 101 | if (skip_level == ifdef_level) |
| 102 | skip_mode = 0; |
| 103 | ifdef_level--; |
| 104 | if (ifdef_level == 0) skip_mode = 0; |
| 105 | if (ifdef_level < 0) |
| 106 | { |
| 107 | printf("%i: warning: #endif without #ifdef, ignoring\n", line); |
| 108 | ifdef_level = 0; |
| 109 | } |
| 110 | } |
| 111 | else if (strncmp(buff, "#include ", 9) == 0) |
| 112 | { |
| 113 | char *pe, *p = buff + 9; |
| 114 | FILE *ftmp; |
| 115 | if (skip_mode) continue; |
| 116 | while (*p && (*p == ' ' || *p == '\"')) p++; |
| 117 | for (pe = p + strlen(p) - 1; pe > p; pe--) |
| 118 | if (isspace(*pe) || *pe == '\"') *pe = 0; |
| 119 | else break; |
| 120 | ftmp = fopen(p, "r"); |
| 121 | if (ftmp == NULL) { |
| 122 | printf("%i: error: failed to include \"%s\"\n", line, p); |
| 123 | return 1; |
| 124 | } |
| 125 | while (!feof(ftmp)) |
| 126 | { |
| 127 | fgs = fgets(buff, sizeof(buff), ftmp); |
| 128 | if (fgs == NULL) break; |
| 129 | fputs(buff, fo); |
| 130 | } |
| 131 | fclose(ftmp); |
| 132 | continue; |
| 133 | } |
| 134 | |
| 135 | /* skip line */ |
| 136 | continue; |
| 137 | } |
| 138 | if (!skip_mode) |
| 139 | { |
| 140 | do_counters(buff); |
| 141 | fputs(buff, fo); |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | fclose(fi); |
| 146 | fclose(fo); |
| 147 | |
| 148 | return 0; |
| 149 | } |
| 150 | |