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++;
}
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';
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:
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 {
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:
}
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 {