#include #include #include #include const char *yes[] = {"SENTINEL_WILL_BE_REPLACED_BY_CMDLINE"}; // "CH32X03x", etc. element 0 is filled in by command-line const char *no[] = {"CH32V10x", "CH32V30x", "CH32V20x", "CH32X03x", "CH32V003"}; char *WhitePull(const char **sti) { const char *st = *sti; int len = 0; while ((*st == ' ' || *st == '\t' || *st == '(') && *st) { st++; } const char *sts = st; while (*st != ' ' && *st != '\t' && *st != '\n' && *st != ')' && *st != '(' && *st != 0) { st++; len++; } if (*st == ')') { st++; } char *ret = malloc(len + 1); memcpy(ret, sts, len); ret[len] = 0; *sti = st; return ret; } int NYI(const char *s) { int ret = 2; char *wp = WhitePull(&s); int i; for (i = 0; i < sizeof(yes) / sizeof(yes[0]); i++) if (strcmp(yes[i], wp) == 0) ret = 1; if (ret != 1) for (i = 0; i < sizeof(no) / sizeof(no[0]); i++) if (strcmp(no[i], wp) == 0) ret = 0; free(wp); return ret; } int EvalSpec(const char *spl) { int rsofar = 0; int i; int lastv = 0; int lasto = -1; int ret = 0; cont: char *wp = WhitePull(&spl); int def = -1; if (strcmp(wp, "defined") == 0) def = 1; if (strcmp(wp, "!defined") == 0) def = 2; if (def < 0) return 2; char *wpn = WhitePull(&spl); i = NYI(wpn); // printf( "SPIN: %s/%s/%d/%d/%d\n", wp, wpn, i, def, lasto ); if (i == 2) return 2; if (def == 2) i = !i; if (lasto == 1) { ret = lastv || i; } else if (lasto == 2) ret = lastv && i; else ret = i; char *wpa = WhitePull(&spl); // printf( "WPA: \"%s\"\n", wpa ); lastv = ret; lasto = -1; // printf( "RET: %d\n", ret ); if (strcmp(wpa, "||") == 0) { lasto = 1; goto cont; } else if (strcmp(wpa, "&&") == 0) { lasto = 2; goto cont; } else return ret; } // 0 for no // 1 for yes // 2 for indeterminate int NoYesInd(const char *preprocc) { int ret; int ofs = 0; if (strncmp(preprocc, "#if ", 4) == 0) ofs = 4; if (strncmp(preprocc, "#elif ", 6) == 0) ofs = 6; if (ofs) { ret = EvalSpec(preprocc + ofs); // printf( "SPEC: %d\n", ret ); } else if (strncmp(preprocc, "#ifdef ", 7) == 0) { const char *ep = preprocc + 6; char *wp = WhitePull(&ep); ret = NYI(wp); free(wp); } else if (strncmp(preprocc, "#ifndef ", 8) == 0) { const char *ep = preprocc + 6; char *wp = WhitePull(&ep); ret = NYI(wp); if (ret < 2) ret = !ret; free(wp); } else ret = 2; // printf( "%d-> %s\n", ret, preprocc ); return ret; } const char *sslineis(const char *line, const char *match) { while (*line == ' ' || *line == '\t') line++; const char *linestart = line; while (*line && *match == *line) { line++; match++; } if (*match == 0) return linestart; else return 0; } int main(int argc, char **argv) { if (argc != 3) { fprintf(stderr, "Syntax: transition [#define to trigger on] [file to convert]\nNo'd architectures:\n"); int i; for (i = 0; i < sizeof(no) / sizeof(no[0]); i++) { fprintf(stderr, "\t%s\n", no[i]); } return -1; } yes[0] = argv[1]; FILE *f = fopen(argv[2], "r"); if (!f) { fprintf(stderr, "Error: Could not open \"%s\"\n", argv[2]); return -2; } char line[1024]; char *l; int depth = 0; // 0 = no // 1 = yes // 2 = indeterminate // 3 = super no. (I.e. after a true #if clause) int yesnoind[1024]; yesnoind[0] = 1; while (l = fgets(line, sizeof(line) - 1, f)) { const char *ss = 0; int nyi = yesnoind[depth]; int waspre = 0; if ((ss = sslineis(line, "#if ")) || (ss = sslineis(line, "#ifdef ")) || (ss = sslineis(line, "#ifndef "))) { waspre = 1; // printf( "CHECK: %d/%s\n", depth, l ); nyi = NoYesInd(ss); depth++; yesnoind[depth] = nyi; } else if ((ss = sslineis(line, "#elif "))) { if (nyi != 2) { waspre = 1; if (nyi == 1) { nyi = 3; } else { nyi = NoYesInd(ss); } // printf( "ELIF check: %s %d\n", ss, nyi ); yesnoind[depth] = nyi; } } else if ((ss = sslineis(line, "#else"))) { if (nyi != 2) { waspre = 1; if (yesnoind[depth] == 1) nyi = 3; else nyi = !yesnoind[depth]; yesnoind[depth] = nyi; } } else if ((ss = sslineis(line, "#endif"))) { waspre = 1; depth--; if (depth < 0) { fprintf(stderr, "UNTERMD IF\n"); } } int thisv = nyi; int i; for (i = 0; i <= depth; i++) { // printf( "%d", yesnoind[i] ); if (yesnoind[i] == 0 || yesnoind[i] == 3) thisv = 0; } // printf( ">>%s", l ); if (thisv != 0 && thisv != 3 && (thisv != 1 || !waspre)) { printf("%s", l); } } }