bool undef;
};
+#define ULAS_MACROPARAMMAX 9
+
struct ulas_preproc {
struct ulas_ppdef *defs;
size_t defslen;
struct ulas_str tok;
struct ulas_str line;
+
+ // macro parameter buffers
+ struct ulas_str macroparam[ULAS_MACROPARAMMAX];
+ // macro expansion buffer
+ struct ulas_str macrobuf;
};
/**
// consumed or -1 on error
// returns 0 when no more tokens can be read
int ulas_tok(struct ulas_str *dst, const char **out_line, size_t n);
+int ulas_tokuntil(struct ulas_str *dst, char c, const char **out_line,
+ size_t n);
/**
* str
ulas_strfree(&dst); \
}
+#define assert_tokuntil(line, c, ...) \
+ { \
+ const char *expect[] = __VA_ARGS__; \
+ size_t n = strlen(line); \
+ struct ulas_str dst = ulas_str(n); \
+ memset(dst.buf, 0, n); \
+ int i = 0; \
+ const char *pline = line; \
+ while (ulas_tokuntil(&dst, c, &pline, n)) { \
+ assert(expect[i]); \
+ assert(strcmp(dst.buf, expect[i]) == 0); \
+ i++; \
+ } \
+ size_t expect_n = 0; \
+ for (expect_n = 0; expect[expect_n]; expect_n++) { \
+ } \
+ assert(i == expect_n); \
+ ulas_strfree(&dst); \
+ }
+
void test_tok(void) {
TESTBEGIN("tok");
{"test", "tokens", "with", ",", "line", "/", "*", "+", "-", ",",
";", "$1", NULL});
+ assert_tokuntil(" this is a, test for tok , until", ',',
+ {" this is a", " test for tok ", " until", NULL});
+
TESTEND("tok");
}
assert_preproc("this is a 123 for defs", 0,
" #define test 123\nthis is a test for defs");
assert_preproc(" line 1\n line 2\n line 3\n", 0,
- "#macro test\n line 1\n line 2\n line 3\n#endmacro\ntest");
+ "#macro test\n line $1 1\n line $2 2\n line $3 3 $0\n#endmacro\ntest p1, p2, p3");
TESTEND("preproc");
}
return 1;
}
+#define WELD_TOKISTERM write
+#define WELD_TOKCOND (i < n && write < n && line[i])
+
int ulas_tok(struct ulas_str *dst, const char **out_line, size_t n) {
const char *line = *out_line;
ulas_strensr(dst, n + 1);
int i = 0;
int write = 0;
-#define WELD_TOKISTERM write
-#define WELD_TOKCOND (i < n && write < n && line[i])
-
// always skip leading terminators
while (WELD_TOKCOND && isspace(line[i])) {
i++;
i++;
}
tokdone:
-#undef WELD_TOKCOND
-#undef WLED_TOKISTERM
dst->buf[write] = '\0';
return i;
}
+// tokenize until the char c is seen
+// this will also consume c and out_line will point to the next valid char
+// this is useful if the next expected token is well defined and we want to
+// capture everything between
+int ulas_tokuntil(struct ulas_str *dst, char c, const char **out_line,
+ size_t n) {
+ const char *line = *out_line;
+ ulas_strensr(dst, n + 1);
+
+ int i = 0;
+ int write = 0;
+
+ while (WELD_TOKCOND && line[i] != c) {
+ dst->buf[write++] = line[i++];
+ }
+
+ if (line[i] == c) {
+ i++;
+ }
+
+ dst->buf[write] = '\0';
+
+ *out_line += i;
+ return i;
+}
+
+#undef WELD_TOKCOND
+#undef WLED_TOKISTERM
+
struct ulas_str ulas_str(size_t n) {
struct ulas_str str = {malloc(n), n};
return str;
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");
+ case ULAS_PPMACRO: {
+ // 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;
+ size_t linelne = strlen(praw_line);
+ // clear all params from previous attempt
+ for (size_t i = 0; i < ULAS_MACROPARAMMAX; i++) {
+ pp->macroparam[i].buf[0] = '\0';
+ }
- break;
+ // loop until 9 args are found or the line ends
+ int paramc = 0;
+ while (paramc < ULAS_MACROPARAMMAX &&
+ ulas_tokuntil(&pp->macroparam[i], ',', &praw_line, *n) > 0) {
+ paramc++;
+ }
+
+ // now tokenize the macro's value and look for $0-$9
+ // and replace those instances
+ // eveyrthing else will just be copied as is
+
+ goto end;
+ }
}
goto found;
continue;
}
+end:
*n = strlen(pp->line.buf);
return pp->line.buf;
}
int rc = 0;
struct ulas_preproc pp = {NULL, 0, ulas_str(1), ulas_str(1)};
+ for (size_t i = 0; i < ULAS_MACROPARAMMAX; i++) {
+ pp.macroparam[i] = ulas_str(8);
+ }
+ pp.macrobuf = ulas_str(8);
while ((rc = ulas_preprocnext(&pp, dst, src, buf, ULAS_LINEMAX)) > 0) {
}
free(pp.defs[i].value);
}
}
+
+ for (size_t i = 0; i < ULAS_MACROPARAMMAX; i++) {
+ ulas_strfree(&pp.macroparam[i]);
+ }
+ ulas_strfree(&pp.macrobuf);
+
if (pp.defs) {
free(pp.defs);
}