From: Lukas Krickl Date: Tue, 7 Nov 2023 14:30:51 +0000 (+0100) Subject: Added #define directive X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=7626cba6a18c00c1769350bab0fb46e0e639c582;p=ulas%2F.git Added #define directive --- diff --git a/include/ulas.h b/include/ulas.h index a035415..8707ebc 100644 --- a/include/ulas.h +++ b/include/ulas.h @@ -28,10 +28,12 @@ // start of preprocessor directives such as #define or #include #define ULAS_TOK_PREPROC_BEGIN '#' -#define ULASERR(...) fprintf(ulaserr, __VA_ARGS__); -#define ULASWARN(...) fprintf(ulaserr, __VA_ARGS__); +#define ULASINFO() fprintf(ulaserr, "%s:%ld ", ulas.filename, ulas.line); +#define ULASERR(...) ULASINFO() fprintf(ulaserr, __VA_ARGS__); +#define ULASWARN(...) ULASINFO() fprintf(ulaserr, __VA_ARGS__); #define ULASPANIC(...) \ { \ + ULASINFO(); \ fprintf(ulaserr, __VA_ARGS__); \ exit(-1); \ } diff --git a/src/test.c b/src/test.c index e4bb2fb..52c004d 100644 --- a/src/test.c +++ b/src/test.c @@ -71,7 +71,10 @@ void test_preproc(void) { // should just echo back line as is assert_preproc(" test line", 0, " test line"); - assert_preproc("123", 0, " #define test 123\ntest"); + assert_preproc(" 123", 0, " #define test 123\ntest"); + assert_preproc("", -1, " #define 1test 123\n"); + assert_preproc("this is a 123 for defs", 0, + " #define test 123\nthis is a test for defs"); TESTEND("preproc"); } diff --git a/src/ulas.c b/src/ulas.c index c143e74..d41af4f 100644 --- a/src/ulas.c +++ b/src/ulas.c @@ -53,6 +53,25 @@ int ulas_main(struct ulas_config cfg) { return 0; } +int ulas_isname(const char *tok, size_t n) { + if (n == 0) { + return 0; + } + + if (isdigit(tok[0])) { + return 0; + } + + for (size_t i = 0; i < n; i++) { + char c = tok[i]; + if (c != '_' && !isalnum(c)) { + return 0; + } + } + + return 1; +} + int ulas_tok(struct ulas_str *dst, const char **out_line, size_t n) { const char *line = *out_line; ulas_strensr(dst, n + 1); @@ -146,6 +165,21 @@ char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line, } // if so... expand now and leave + switch (def->type) { + case ULAS_PPDEF: + // adjust total length + *n -= strlen(pp->tok.buf); + size_t val_len = strlen(def->value); + *n += val_len; + ulas_strensr(&pp->line, (*n) + 1); + strncat(pp->line.buf, def->value, val_len); + break; + case ULAS_PPMACRO: + // TODO: Implement + ULASPANIC("PPMACRO is not implemented!\n"); + break; + } + goto found; } // if not found: copy everythin from prev to the current raw_line point - @@ -165,7 +199,7 @@ char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line, int ulas_preprocdef(struct ulas_preproc *pp, struct ulas_ppdef def) { pp->defslen++; void *defs = realloc(pp->defs, pp->defslen * sizeof(struct ulas_ppdef)); - if (defs) { + if (!defs) { ULASPANIC("%s\n", strerror(errno)); } pp->defs = defs; @@ -205,16 +239,32 @@ int ulas_preprocline(struct ulas_preproc *pp, FILE *dst, const char *raw_line, found: if (found_dir) { - // TODO: process directive - printf("%s preproc directive!\n", pp->tok.buf); - fputc('\0', dst); - switch (found_dir) { case ULAS_PPDIR_DEF: { // next token is a name // and then the entire remainder of the line is a value - struct ulas_ppdef def = {found_dir, "", "", false}; - break; + 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), + false}; + size_t val_len = strlen(def.value); + + // remove trailing new line if present + if (def.value[val_len - 1] == '\n') { + def.value[val_len - 1] = '\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! + return 0; } case ULAS_PPDIR_MACRO: case ULAS_PPDIR_ENDMACRO: @@ -231,12 +281,13 @@ found: // the end of a directive should have no further tokens! if (ulas_tok(&pp->tok, &pline, n) != 0) { - ULASERR("Stray tokens at end of preprocessor directive\n"); + ULASERR("Stray tokens '%s' at end of preprocessor directive\n", + pp->tok.buf); return -1; } } else { - assert(fwrite(line, 1, n, dst) == n); + fwrite(line, 1, n, dst); } return 0; @@ -247,12 +298,7 @@ int ulas_preproc(FILE *dst, FILE *src) { memset(buf, 0, ULAS_LINEMAX); int rc = 0; - if (!dst || !src) { - ULASERR("[%s] Unable to read from dst or write to src!\n", ulas.filename); - return -1; - } - - struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1)}; + struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1)}; while (fgets(buf, ULAS_LINEMAX, src) != NULL) { ulas.line++;