From eb3bad2ed98288a2cdb25e8230178aa105f9c1bc Mon Sep 17 00:00:00 2001 From: Lukas Krickl Date: Fri, 17 Nov 2023 18:35:54 +0100 Subject: [PATCH] Fixed switch indentation --- makefile | 2 +- src/main.c | 48 ++-- src/ulas.c | 758 ++++++++++++++++++++++++++--------------------------- 3 files changed, 402 insertions(+), 406 deletions(-) diff --git a/makefile b/makefile index 6c44940..1772663 100644 --- a/makefile +++ b/makefile @@ -57,7 +57,7 @@ tags: .PHONY: format format: - VERSION_CONTROL=none indent -kr -ci2 -cli2 -i2 -l80 -nut -brf -par src/*.c $(IDIR)/*.h + VERSION_CONTROL=none indent -kr -ci2 -cli2 -i2 -l80 -nut -brf -par -cli0 -cbi0 src/*.c $(IDIR)/*.h .PHONY: lint lint: diff --git a/src/main.c b/src/main.c index 72dbe51..d07fe3a 100644 --- a/src/main.c +++ b/src/main.c @@ -34,30 +34,30 @@ void ulas_getopt(int argc, char **argv, struct ulas_config *cfg) { int c = 0; while ((c = getopt(argc, argv, ULAS_OPTS ULAS_OPTS_ARG)) != -1) { switch (c) { - case 'h': - ulas_help(); - exit(0); - break; - case 'V': - ulas_version(); - exit(0); - break; - case 'v': - cfg->verbose = 1; - break; - case 'o': - cfg->output_path = strndup(optarg, ULAS_PATHMAX); - break; - case 'p': - cfg->preproc_only = 1; - break; - case '?': - break; - default: - printf("%s: invalid option '%c'\nTry '%s -h' for more information.\n", - ULAS_NAME, c, ULAS_NAME); - exit(-1); - break; + case 'h': + ulas_help(); + exit(0); + break; + case 'V': + ulas_version(); + exit(0); + break; + case 'v': + cfg->verbose = 1; + break; + case 'o': + cfg->output_path = strndup(optarg, ULAS_PATHMAX); + break; + case 'p': + cfg->preproc_only = 1; + break; + case '?': + break; + default: + printf("%s: invalid option '%c'\nTry '%s -h' for more information.\n", + ULAS_NAME, c, ULAS_NAME); + exit(-1); + break; } } diff --git a/src/ulas.c b/src/ulas.c index 197915d..a6a02ea 100644 --- a/src/ulas.c +++ b/src/ulas.c @@ -145,37 +145,37 @@ int ulas_tok(struct ulas_str *dst, const char **out_line, unsigned long n) { char c = line[i]; switch (c) { - case ',': - case '+': - case '-': - case '*': - case '/': - case '\\': - case ULAS_TOK_COMMENT: - if (WELD_TOKISTERM) { - goto tokdone; - } - // single char tokens - dst->buf[write++] = line[i++]; + case ',': + case '+': + case '-': + case '*': + case '/': + case '\\': + case ULAS_TOK_COMMENT: + if (WELD_TOKISTERM) { goto tokdone; - case '$': - if (WELD_TOKISTERM) { - goto tokdone; - } - // special var for preprocessor - // make sure we have enough space in buffer - ulas_strensr(dst, write + 2); - // escape char tokens - dst->buf[write++] = line[i++]; - dst->buf[write++] = line[i++]; + } + // single char tokens + dst->buf[write++] = line[i++]; + goto tokdone; + case '$': + if (WELD_TOKISTERM) { goto tokdone; - default: - if (isspace(line[i])) { - goto tokdone; - } - dst->buf[write] = line[i]; - write++; - break; + } + // special var for preprocessor + // make sure we have enough space in buffer + ulas_strensr(dst, write + 2); + // escape char tokens + dst->buf[write++] = line[i++]; + dst->buf[write++] = line[i++]; + goto tokdone; + default: + if (isspace(line[i])) { + goto tokdone; + } + dst->buf[write] = line[i]; + write++; + break; } i++; } @@ -220,28 +220,28 @@ int ulas_tokuntil(struct ulas_str *dst, char c, const char **out_line, int ulas_unescape(char c, int *rc) { switch (c) { - case '\'': - case '\\': - case '"': - return c; - case 'n': - return '\n'; - case 'a': - return '\a'; - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'r': - return '\r'; - case '?': - return '\?'; - case '0': - return '\0'; - default: - ULASERR("Unexpected esxcape sequence: \\%c\n", c); - *rc = -1; - break; + case '\'': + case '\\': + case '"': + return c; + case 'n': + return '\n'; + case 'a': + return '\a'; + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'r': + return '\r'; + case '?': + return '\?'; + case '0': + return '\0'; + default: + ULASERR("Unexpected esxcape sequence: \\%c\n", c); + *rc = -1; + break; } return '\0'; @@ -260,97 +260,97 @@ struct ulas_tok ulas_totok(char *buf, unsigned long n, int *rc) { buf++; switch (first) { - case '+': - case '-': - case '*': - case '/': - case '!': - case '~': - case '|': - case '&': - case '%': - case '(': - case ')': - case '[': - case ']': - case ',': - case ';': - // single char tokens - tok.type = first; + case '+': + case '-': + case '*': + case '/': + case '!': + case '~': + case '|': + case '&': + case '%': + case '(': + case ')': + case '[': + case ']': + case ',': + case ';': + // single char tokens + tok.type = first; + goto end; + case '"': + // string + tok.type = ULAS_TOKLITERAL; + tok.lit.type = ULAS_STR; + + // FIXME: this likely mallocs a few extra bytes + // but honestly its probably fine + tok.lit.val.strv = malloc(n * sizeof(char) + 1); + memset(tok.lit.val.strv, 0, n); + + long i = 0; + while (*buf && *buf != '\"') { + if (*buf == '\\') { + buf++; + tok.lit.val.strv[i] = ulas_unescape(*buf, rc); + } else { + tok.lit.val.strv[i] = *buf; + } + i++; + buf++; + } + tok.lit.val.strv[i] = '\0'; + + if (*buf != '\"') { + *rc = -1; + ULASERR("Unterminated string sequence\n"); goto end; - case '"': - // string + } + buf++; + break; + default: + if (isdigit(first)) { + // integer tok.type = ULAS_TOKLITERAL; - tok.lit.type = ULAS_STR; + tok.lit.type = ULAS_INT; - // FIXME: this likely mallocs a few extra bytes - // but honestly its probably fine - tok.lit.val.strv = malloc(n * sizeof(char) + 1); - memset(tok.lit.val.strv, 0, n); - - long i = 0; - while (*buf && *buf != '\"') { - if (*buf == '\\') { - buf++; - tok.lit.val.strv[i] = ulas_unescape(*buf, rc); - } else { - tok.lit.val.strv[i] = *buf; - } - i++; + // 0b prefix is not supported in strtol... so we implement it by hand + if (*buf == 'b') { buf++; + tok.lit.val.intv = (int) strtol(buf, &buf, 2); + } else { + tok.lit.val.intv = (int) strtol(buf - 1, &buf, 0); } - tok.lit.val.strv[i] = '\0'; - - if (*buf != '\"') { - *rc = -1; - ULASERR("Unterminated string sequence\n"); - goto end; - } - buf++; - break; - default: - if (isdigit(first)) { - // integer - tok.type = ULAS_TOKLITERAL; - tok.lit.type = ULAS_INT; - - // 0b prefix is not supported in strtol... so we implement it by hand - if (*buf == 'b') { - buf++; - tok.lit.val.intv = (int) strtol(buf, &buf, 2); - } else { - tok.lit.val.intv = (int) strtol(buf - 1, &buf, 0); - } - } else if (first == '\'') { - tok.type = ULAS_TOKLITERAL; - tok.lit.type = ULAS_INT; - if (*buf == '\\') { - buf++; - tok.lit.val.intv = ulas_unescape(*buf, rc); - } else { - tok.lit.val.intv = (int) *buf; - } - buf++; - if (*buf != '\'') { - *rc = -1; - ULASERR("Unterminated character sequence\n"); - goto end; - } + } else if (first == '\'') { + tok.type = ULAS_TOKLITERAL; + tok.lit.type = ULAS_INT; + if (*buf == '\\') { buf++; - break; - } else if (ulas_isname(buf, n)) { - // literal. we can resolve it now - // because literals need to be able to be resolved - // for every line, unless they are a label! - // TODO: read and unescape striing between " and " - tok.type = ULAS_TOKSYMBOL; - tok.lit.type = ULAS_STR; + tok.lit.val.intv = ulas_unescape(*buf, rc); } else { - ULASERR("Unexpected token: %s\n", buf); + tok.lit.val.intv = (int) *buf; + } + buf++; + if (*buf != '\'') { *rc = -1; + ULASERR("Unterminated character sequence\n"); goto end; } + buf++; break; + } else if (ulas_isname(buf, n)) { + // literal. we can resolve it now + // because literals need to be able to be resolved + // for every line, unless they are a label! + // TODO: read and unescape striing between " and " + tok.type = ULAS_TOKSYMBOL; + tok.lit.type = ULAS_STR; + } else { + ULASERR("Unexpected token: %s\n", buf); + *rc = -1; + goto end; + } + break; } end: @@ -453,130 +453,128 @@ char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line, if (def) { // if so... expand now and leave switch (def->type) { - case ULAS_PPDEF:{ - unsigned long val_len = strlen(def->value); - int wsi = ulas_preproclws(pp, praw_line - read, *n); - if (val_len) { - // make sure to include leading white space - // adjust total length - *n -= strlen(pp->tok.buf); - *n += val_len; - ulas_strensr(&pp->line, (*n) + 1 + wsi); - - // only remove the first white space char if the lenght of value - // is greater than 1, otherwise just leave it be... - if (val_len > 1) { - strncat(pp->line.buf, def->value + 1, val_len - 1); - } else { - strncat(pp->line.buf, def->value, val_len); - } - } - break; + case ULAS_PPDEF:{ + unsigned long val_len = strlen(def->value); + int wsi = ulas_preproclws(pp, praw_line - read, *n); + if (val_len) { + // make sure to include leading white space + // adjust total length + *n -= strlen(pp->tok.buf); + *n += val_len; + ulas_strensr(&pp->line, (*n) + 1 + wsi); + + // only remove the first white space char if the lenght of value + // is greater than 1, otherwise just leave it be... + if (val_len > 1) { + strncat(pp->line.buf, def->value + 1, val_len - 1); + } else { + strncat(pp->line.buf, def->value, val_len); } - case ULAS_PPMACRO:{ - // TODO: i am sure we can optimize the resize of line buffers here... - - // get 9 comma separated values. - // $1-$9 will reference the respective arg - // $0 will reference the entire line after the macro name - // there can be more than 9 args, but anything after the 9th arg can - // only be accessed via $0 - const char *line = praw_line; - unsigned long linelen = strlen(praw_line); - // clear all params from previous attempt - for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) { - pp->macroparam[i].buf[0] = '\0'; - } + } + break; + } + case ULAS_PPMACRO:{ + // TODO: i am sure we can optimize the resize of line buffers here... + + // get 9 comma separated values. + // $1-$9 will reference the respective arg + // $0 will reference the entire line after the macro name + // there can be more than 9 args, but anything after the 9th arg can + // only be accessed via $0 + const char *line = praw_line; + unsigned long linelen = strlen(praw_line); + // clear all params from previous attempt + for (unsigned long i = 0; i < ULAS_MACROPARAMMAX; i++) { + pp->macroparam[i].buf[0] = '\0'; + } + + // loop until 9 args are found or the line ends + int paramc = 0; + while (paramc < ULAS_MACROPARAMMAX && + ulas_tokuntil(&pp->macroparam[paramc], ',', &praw_line, *n) > + 0) { + // trim new lines from the end of macro params + ulas_trimend('\n', pp->macroparam[paramc].buf, + strlen(pp->macroparam[paramc].buf)); + paramc++; + } + ulas_strensr(&pp->line, strlen(def->value) + 2); + + const char *macro_argname[ULAS_MACROPARAMMAX] = { + "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9" + }; + + const char *val = def->value; + unsigned long vallen = strlen(def->value); + unsigned long valread = 0; + + // the pointer to tocat will be the variable's value if any + // exists + const char *tocat = NULL; + unsigned long tocatlen = 0; + + // now tokenize the macro's value and look for $0-$9 + // and replace those instances + // eveyrthing else will just be copied as is + while ((valread = ulas_tok(&pp->macrobuf, &val, vallen)) > 0) { + tocat = NULL; + char numbuf[128]; + + // decide what tocat should be + for (unsigned long mi = 0; mi < ULAS_MACROPARAMMAX; mi++) { + const char *name = macro_argname[mi]; + if (pp->macroparam[mi].buf[0] && + strncmp((name), pp->macrobuf.buf, pp->macrobuf.maxlen) == 0) { + ulas_strensr(&pp->line, + strnlen(pp->line.buf, + pp->line.maxlen) + + strnlen(pp->macroparam[mi].buf, + pp->macroparam[mi].maxlen) + 1); + + tocat = pp->macroparam[mi].buf; + tocatlen = pp->macroparam[mi].maxlen; - // loop until 9 args are found or the line ends - int paramc = 0; - while (paramc < ULAS_MACROPARAMMAX && - ulas_tokuntil(&pp->macroparam[paramc], ',', &praw_line, *n) > - 0) { - // trim new lines from the end of macro params - ulas_trimend('\n', pp->macroparam[paramc].buf, - strlen(pp->macroparam[paramc].buf)); - paramc++; + break; } - ulas_strensr(&pp->line, strlen(def->value) + 2); - - const char *macro_argname[ULAS_MACROPARAMMAX] = { - "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9" - }; - - const char *val = def->value; - unsigned long vallen = strlen(def->value); - unsigned long valread = 0; - - // the pointer to tocat will be the variable's value if any - // exists - const char *tocat = NULL; - unsigned long tocatlen = 0; - - // now tokenize the macro's value and look for $0-$9 - // and replace those instances - // eveyrthing else will just be copied as is - while ((valread = ulas_tok(&pp->macrobuf, &val, vallen)) > 0) { - tocat = NULL; - char numbuf[128]; - - // decide what tocat should be - for (unsigned long mi = 0; mi < ULAS_MACROPARAMMAX; mi++) { - const char *name = macro_argname[mi]; - if (pp->macroparam[mi].buf[0] && - strncmp((name), pp->macrobuf.buf, - pp->macrobuf.maxlen) == 0) { - ulas_strensr(&pp->line, - strnlen(pp->line.buf, - pp->line.maxlen) + - strnlen(pp->macroparam[mi].buf, - pp->macroparam[mi].maxlen) + 1); - - tocat = pp->macroparam[mi].buf; - tocatlen = pp->macroparam[mi].maxlen; - - break; - } - } - - if (linelen && - strncmp("$0", pp->macrobuf.buf, pp->macrobuf.maxlen) == 0) { - ulas_strensr(&pp->line, - strnlen(pp->line.buf, - pp->line.maxlen) + linelen + 1); - - if (linelen > 1) { - // this skips the separating token which is usually a space - // all further spaces are included though! - tocat = line + 1; - tocatlen = linelen - 1; - } else { - // do not do this if the line is literally empty! - tocat = line; - tocatlen = linelen; - } - } else if (linelen && strncmp("$$", pp->macrobuf.buf, - pp->macrobuf.maxlen) == 0) { - sprintf(numbuf, "%x", ulas_icntr()); - ulas_strensr(&pp->line, - strnlen(pp->line.buf, pp->line.maxlen) + 128 + 1); - tocat = numbuf; - tocatlen = 128; - } - - if (!tocat) { - ulas_strensr(&pp->line, valread + 1); - strncat(pp->line.buf, val - valread, valread); - } else { - // make sure to include leading white space - int wsi = ulas_preproclws(pp, val - valread, vallen); - ulas_strensr(&pp->line, strnlen(pp->line.buf, pp->line.maxlen) + - tocatlen + wsi + 1); - strncat(pp->line.buf, tocat, tocatlen); - } + } + + if (linelen && + strncmp("$0", pp->macrobuf.buf, pp->macrobuf.maxlen) == 0) { + ulas_strensr(&pp->line, + strnlen(pp->line.buf, pp->line.maxlen) + linelen + 1); + + if (linelen > 1) { + // this skips the separating token which is usually a space + // all further spaces are included though! + tocat = line + 1; + tocatlen = linelen - 1; + } else { + // do not do this if the line is literally empty! + tocat = line; + tocatlen = linelen; } - goto end; + } else if (linelen && strncmp("$$", pp->macrobuf.buf, + pp->macrobuf.maxlen) == 0) { + sprintf(numbuf, "%x", ulas_icntr()); + ulas_strensr(&pp->line, + strnlen(pp->line.buf, pp->line.maxlen) + 128 + 1); + tocat = numbuf; + tocatlen = 128; } + + if (!tocat) { + ulas_strensr(&pp->line, valread + 1); + strncat(pp->line.buf, val - valread, valread); + } else { + // make sure to include leading white space + int wsi = ulas_preproclws(pp, val - valread, vallen); + ulas_strensr(&pp->line, strnlen(pp->line.buf, pp->line.maxlen) + + tocatlen + wsi + 1); + strncat(pp->line.buf, tocat, tocatlen); + } + } + goto end; + } } } else { @@ -648,135 +646,133 @@ found: if (found_dir != ULAS_PPDIR_NONE) { ulas_trimend('\n', line, strlen(line)); switch (found_dir) { - case ULAS_PPDIR_DEF:{ - // next token is a name - // and then the entire remainder of the line is a value - if (ulas_tok(&pp->tok, &pline, n) == 0) { - ULASERR("Expected name for #define\n"); - return -1; - } - - if (!ulas_isname(pp->tok.buf, strlen(pp->tok.buf))) { - ULASERR("'%s' is not a valid #define name!\n", pp->tok.buf); - return -1; - } - - struct ulas_ppdef def = - { ULAS_PPDEF, strdup(pp->tok.buf), strdup(pline), - 0 - }; - ulas_preprocdef(pp, def); - // define short-circuits the rest of the logic - // because it just takes the entire rest of the line as a value! - goto dirdone; - } - case ULAS_PPDIR_MACRO:{ - // get a name, ensure no more tokens come after - // and then consume lines until ENDMACRO is seen - if (ulas_tok(&pp->tok, &pline, n) == 0) { - ULASERR("Expected name for #macro\n"); - return -1; - } - - if (!ulas_isname(pp->tok.buf, strlen(pp->tok.buf))) { - ULASERR("'%s' is not a valid #macro name!\n", pp->tok.buf); - return -1; - } - char *name = strdup(pp->tok.buf); - - struct ulas_str val = ulas_str(32); - memset(val.buf, 0, 32); - - char buf[ULAS_LINEMAX]; - memset(buf, 0, ULAS_LINEMAX); - - // consume lines until #endmacro is read - // if reaching end of input without #endmacro we have an unterminated - // macro. pass NULL as dst to consume lines that are being read instead of - // echoing them back - int rc = 0; - while ((rc = ulas_preprocnext(pp, NULL, src, buf, ULAS_LINEMAX)) > 0) { - if (rc == ULAS_PPDIR_ENDMACRO) { - // we need to clear the line buffer to now echo back - // the #endmacro directive - pp->line.buf[0] = '\0'; - break; - } + case ULAS_PPDIR_DEF:{ + // next token is a name + // and then the entire remainder of the line is a value + if (ulas_tok(&pp->tok, &pline, n) == 0) { + ULASERR("Expected name for #define\n"); + return -1; + } - unsigned long len = strnlen(pp->line.buf, pp->line.maxlen); - ulas_strensr(&val, strnlen(val.buf, val.maxlen) + len + 1); - strncat(val.buf, pp->line.buf, val.maxlen); - } + if (!ulas_isname(pp->tok.buf, strlen(pp->tok.buf))) { + ULASERR("'%s' is not a valid #define name!\n", pp->tok.buf); + return -1; + } - if (rc != ULAS_PPDIR_ENDMACRO) { - ULASERR("Unterminated macro directive\n"); - ulas_strfree(&val); - free(name); - return -1; - } - // we leak the str's buffer into the def now - // this is ok because we call free for it later anyway - struct ulas_ppdef def = { ULAS_PPMACRO, name, val.buf, 0 }; - ulas_preprocdef(pp, def); + struct ulas_ppdef def = { ULAS_PPDEF, strdup(pp->tok.buf), strdup(pline), + 0 + }; + ulas_preprocdef(pp, def); + // define short-circuits the rest of the logic + // because it just takes the entire rest of the line as a value! + goto dirdone; + } + case ULAS_PPDIR_MACRO:{ + // get a name, ensure no more tokens come after + // and then consume lines until ENDMACRO is seen + if (ulas_tok(&pp->tok, &pline, n) == 0) { + ULASERR("Expected name for #macro\n"); + return -1; + } - goto dirdone; + if (!ulas_isname(pp->tok.buf, strlen(pp->tok.buf))) { + ULASERR("'%s' is not a valid #macro name!\n", pp->tok.buf); + return -1; + } + char *name = strdup(pp->tok.buf); + + struct ulas_str val = ulas_str(32); + memset(val.buf, 0, 32); + + char buf[ULAS_LINEMAX]; + memset(buf, 0, ULAS_LINEMAX); + + // consume lines until #endmacro is read + // if reaching end of input without #endmacro we have an unterminated + // macro. pass NULL as dst to consume lines that are being read instead of + // echoing them back + int rc = 0; + while ((rc = ulas_preprocnext(pp, NULL, src, buf, ULAS_LINEMAX)) > 0) { + if (rc == ULAS_PPDIR_ENDMACRO) { + // we need to clear the line buffer to now echo back + // the #endmacro directive + pp->line.buf[0] = '\0'; + break; } - case ULAS_PPDIR_ENDIF: - case ULAS_PPDIR_ENDMACRO: - break; - case ULAS_PPDIR_IFDEF: - case ULAS_PPDIR_IFNDEF:{ - // get the name - // get a name, ensure no more tokens come after - // and then consume lines until ENDMACRO is seen - if (ulas_tok(&pp->tok, &pline, n) == 0) { - ULASERR("Expected name for #if(n)def\n"); - return -1; - } - struct ulas_ppdef *def = - ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen); - char buf[ULAS_LINEMAX]; - memset(buf, 0, ULAS_LINEMAX); + unsigned long len = strnlen(pp->line.buf, pp->line.maxlen); + ulas_strensr(&val, strnlen(val.buf, val.maxlen) + len + 1); + strncat(val.buf, pp->line.buf, val.maxlen); + } - FILE *defdst = NULL; - if ((def && found_dir == ULAS_PPDIR_IFDEF) || - (!def && found_dir == ULAS_PPDIR_IFNDEF)) { - defdst = dst; - } - // loop until end of line or endif - int rc = 0; - while ((rc = - ulas_preprocnext(pp, defdst, src, buf, ULAS_LINEMAX)) > 0) { - if (rc == ULAS_PPDIR_ENDIF) { - // we need to clear the line buffer to now echo back - // the #endif directive - pp->line.buf[0] = '\0'; - break; - } - } + if (rc != ULAS_PPDIR_ENDMACRO) { + ULASERR("Unterminated macro directive\n"); + ulas_strfree(&val); + free(name); + return -1; + } + // we leak the str's buffer into the def now + // this is ok because we call free for it later anyway + struct ulas_ppdef def = { ULAS_PPMACRO, name, val.buf, 0 }; + ulas_preprocdef(pp, def); - if (rc != ULAS_PPDIR_ENDIF) { - ULASERR("Unterminated if(n)def directive\n"); - return -1; - } - goto dirdone; - } - case ULAS_PPDIR_UNDEF:{ - if (ulas_tok(&pp->tok, &pline, n) == 0) { - ULASERR("Expected name for #undef\n"); - return -1; - } - struct ulas_ppdef *def = NULL; - while ((def = ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen))) { - def->undef = 1; - } + goto dirdone; + } + case ULAS_PPDIR_ENDIF: + case ULAS_PPDIR_ENDMACRO: + break; + case ULAS_PPDIR_IFDEF: + case ULAS_PPDIR_IFNDEF:{ + // get the name + // get a name, ensure no more tokens come after + // and then consume lines until ENDMACRO is seen + if (ulas_tok(&pp->tok, &pline, n) == 0) { + ULASERR("Expected name for #if(n)def\n"); + return -1; + } + struct ulas_ppdef *def = + ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen); + char buf[ULAS_LINEMAX]; + memset(buf, 0, ULAS_LINEMAX); + + FILE *defdst = NULL; + if ((def && found_dir == ULAS_PPDIR_IFDEF) || + (!def && found_dir == ULAS_PPDIR_IFNDEF)) { + defdst = dst; + } + // loop until end of line or endif + int rc = 0; + while ((rc = ulas_preprocnext(pp, defdst, src, buf, ULAS_LINEMAX)) > 0) { + if (rc == ULAS_PPDIR_ENDIF) { + // we need to clear the line buffer to now echo back + // the #endif directive + pp->line.buf[0] = '\0'; break; } - default: - // this should not happen! - break; + } + + if (rc != ULAS_PPDIR_ENDIF) { + ULASERR("Unterminated if(n)def directive\n"); + return -1; + } + goto dirdone; + } + case ULAS_PPDIR_UNDEF:{ + if (ulas_tok(&pp->tok, &pline, n) == 0) { + ULASERR("Expected name for #undef\n"); + return -1; + } + struct ulas_ppdef *def = NULL; + while ((def = ulas_preprocgetdef(pp, pp->tok.buf, pp->tok.maxlen))) { + def->undef = 1; + } + + break; + } + default: + // this should not happen! + break; } dirdone: @@ -979,18 +975,18 @@ int ulas_asmline(FILE *dst, FILE *src, const char *line, unsigned long n) { } switch (dir) { - case ULAS_ASMDIR_NONE: - case ULAS_ASMDIR_ORG: - ulas.address = ulas_intexpr(&line, strnlen(start, n), &rc); - break; - case ULAS_ASMDIR_SET: - case ULAS_ASMDIR_BYTE: - case ULAS_ASMDIR_STR: - case ULAS_ASMDIR_FILL: - case ULAS_ASMDIR_PAD: - case ULAS_ASMDIR_INCBIN: - ULASPANIC("asmdir not implemented\n"); - break; + case ULAS_ASMDIR_NONE: + case ULAS_ASMDIR_ORG: + ulas.address = ulas_intexpr(&line, strnlen(start, n), &rc); + break; + case ULAS_ASMDIR_SET: + case ULAS_ASMDIR_BYTE: + case ULAS_ASMDIR_STR: + case ULAS_ASMDIR_FILL: + case ULAS_ASMDIR_PAD: + case ULAS_ASMDIR_INCBIN: + ULASPANIC("asmdir not implemented\n"); + break; } } else { -- 2.30.2