+++ /dev/null
-#ifndef PREPROC_H_
-#define PREPROC_H_
-
-#include <stdbool.h>
-#include <stdio.h>
-
-/*
- * Preprocessor
- */
-
-enum ulas_ppdirs {
- ULAS_PPDIR_NONE = 0,
- ULAS_PPDIR_DEF,
- ULAS_PPDIR_MACRO,
- ULAS_PPDIR_ENDMACRO,
- ULAS_PPDIR_IFDEF,
- ULAS_PPDIR_IFNDEF,
- ULAS_PPDIR_ENDIF
-};
-
-enum ulas_ppdefs {
- ULAS_PP_DEF,
- ULAS_PP_MACRO,
-};
-
-struct ulas_ppdef {
- enum ulas_ppdefs type;
- bool undef;
-};
-
-struct ulas_preproc {
- struct ulas_ppdef *defs;
- size_t defslen;
-
- const char *srcname;
- const char *dstname;
-};
-
-/**
- * Tokenize and apply the preprocessor
- */
-int ulas_preproc(FILE *dst, const char *dstname, FILE *src,
- const char *srcname);
-
-// expand preproc into dst line
-char *ulas_preprocexpand(char *line, size_t linemax, const char *raw_line, size_t *n);
-
-#endif
bool verbose;
};
+/**
+ * str
+ */
+struct ulas_str {
+ char *buf;
+ size_t maxlen;
+};
+
/**
* Assembly context
*/
size_t strslen;
};
+/**
+ * Preproc
+ */
+
+enum ulas_ppdirs {
+ ULAS_PPDIR_NONE = 0,
+ ULAS_PPDIR_DEF,
+ ULAS_PPDIR_MACRO,
+ ULAS_PPDIR_ENDMACRO,
+ ULAS_PPDIR_IFDEF,
+ ULAS_PPDIR_IFNDEF,
+ ULAS_PPDIR_ENDIF
+};
+
+enum ulas_ppdefs {
+ ULAS_PP_DEF,
+ ULAS_PP_MACRO,
+};
+
+struct ulas_ppdef {
+ enum ulas_ppdefs type;
+ bool undef;
+};
+
+struct ulas_preproc {
+ struct ulas_ppdef *defs;
+ size_t defslen;
+
+ const char *srcname;
+ const char *dstname;
+
+ struct ulas_str tok;
+ struct ulas_str line;
+};
+
/**
* Tokens
*/
// returns the amount of bytes of line that were
// consumed or -1 on error
// returns 0 when no more tokens can be read
-int ulas_tok(char *dst, const char *line, size_t n, ulas_tokrule rule);
+int ulas_tok(struct ulas_str *dst, const char *line, size_t n,
+ ulas_tokrule rule);
// smae as ulas_tok but modifies line
-int ulas_tokline(char *dst, const char **line, size_t n, ulas_tokrule rule);
+int ulas_tokline(struct ulas_str *dst, const char **line, size_t n,
+ ulas_tokrule rule);
+
+/**
+ * str
+ */
+
+// create a string buffer
+struct ulas_str ulas_str(size_t n);
+
+// ensure the string buffer is at least n bytes long, if not realloc
+struct ulas_str ulas_strensr(struct ulas_str *s, size_t maxlen);
+
+void ulas_strfree(struct ulas_str *s);
+
+/*
+ * Preprocessor
+ */
+
+/**
+ * Tokenize and apply the preprocessor
+ */
+int ulas_preproc(FILE *dst, const char *dstname, FILE *src,
+ const char *srcname);
+
+// expand preproc into dst line
+char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line,
+ size_t *n);
#endif
BIN_INSTALL_DIR=/usr/local/bin
MAN_INSTALL_DIR=/usr/local/man
-_OBJ = $(MAIN) ulas.o preproc.o
+_OBJ = $(MAIN) ulas.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
all: bin test
+++ /dev/null
-#include "preproc.h"
-#include "ulas.h"
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <assert.h>
-
-char *ulas_preprocexpand(char *line, size_t linemax, const char *raw_line,
- size_t *n) {
- assert(*n <= linemax);
- const char *praw_line = raw_line;
-
- char tok[ULAS_TOKMAX];
-
- // go through all tokens, see if a define matches the token,
- // if so expand it
- // only expand macros if they match toks[0] though!
- // otherwise memcpy the read bytes 1:1 into the new string
- while (ulas_tokline(tok, &praw_line, ULAS_TOKMAX, isalnum)) {
- }
-
- // TODO: actually expand here...
- strncpy(line, raw_line, *n);
- *n = strlen(line);
- return line;
-}
-
-int ulas_preprocline(struct ulas_preproc *pp, FILE *dst, const char *raw_line,
- size_t n) {
- if (n > ULAS_LINEMAX) {
- ULASERR("%s: line exceeds %d (LINEMAX)\n", raw_line, ULAS_LINEMAX);
- return -1;
- }
- assert(n <= ULAS_LINEMAX);
- char line[ULAS_LINEMAX];
- const char *pline = line;
-
- ulas_preprocexpand(line, ULAS_LINEMAX, raw_line, &n);
- const char *dirstrs[] = {"#define", "#macro", "#ifdef", "#ifndef",
- "#endif", "#endmacro", NULL};
- enum ulas_ppdirs dirs[] = {ULAS_PPDIR_DEF, ULAS_PPDIR_MACRO,
- ULAS_PPDIR_IFDEF, ULAS_PPDIR_IFNDEF,
- ULAS_PPDIR_ENDIF, ULAS_PPDIR_ENDMACRO};
-
- enum ulas_ppdirs found_dir = ULAS_PPDIR_NONE;
-
- char tok[ULAS_TOKMAX];
-
- // check if the first token is any of the valid preproc directives
- if (ulas_tokline(tok, &pline, ULAS_TOKMAX, isspace)) {
- // not a preproc directive...
- if (tok[0] != ULAS_TOK_PREPROC_BEGIN) {
- goto found;
- }
- for (size_t i = 0; dirstrs[i]; i++) {
- if (strncmp(dirstrs[i], tok, ULAS_TOKMAX) == 0) {
- found_dir = dirs[i];
- goto found;
- }
- }
-
- ULASPANIC("Unknown preprocessor directive: %s\n", line);
- return -1;
- }
-found:
-
- if (found_dir) {
- // TODO: process directive
- printf("%s preproc directive!\n", tok);
- fputc('\0', dst);
- } else {
- assert(fwrite(line, 1, n, dst) == n);
- }
-
- return 0;
-}
-
-int ulas_preproc(FILE *dst, const char *dstname, FILE *src,
- const char *srcname) {
- char buf[ULAS_LINEMAX];
- memset(buf, 0, ULAS_LINEMAX);
- int rc = 0;
-
- if (!dst || !src) {
- ULASERR("[%s] Unable to read from dst or write to src!\n", srcname);
- return -1;
- }
-
- struct ulas_preproc pp = {NULL, 0, srcname, dstname};
-
- while (fgets(buf, ULAS_LINEMAX, src) != NULL) {
- if (ulas_preprocline(&pp, dst, buf, strlen(buf)) == -1) {
- rc = -1;
- goto fail;
- }
- }
-
-fail:
- return rc;
-}
#include <ctype.h>
#include <stdio.h>
#include <assert.h>
-#include "preproc.h"
#define TESTBEGIN(name) printf("[test %s]\n", (name));
#define TESTEND(name) printf("[%s ok]\n", (name));
#define assert_tok(expected_tok, expected_ret, line, rule) \
{ \
- char buf[ULAS_TOKMAX]; \
- memset(buf, 0, ULAS_TOKMAX); \
- assert(ulas_tok(buf, (line), ULAS_TOKMAX, (rule)) == (expected_ret)); \
- assert(strcmp(buf, expected_tok) == 0); \
+ struct ulas_str dst = ulas_str(ULAS_TOKMAX); \
+ memset(dst.buf, 0, ULAS_TOKMAX); \
+ assert(ulas_tok(&dst, (line), ULAS_TOKMAX, (rule)) == (expected_ret)); \
+ assert(strcmp(dst.buf, expected_tok) == 0); \
+ ulas_strfree(&dst); \
}
#define assert_tokline(expected_n, line, rule, ...) \
{ \
const char *expect[] = __VA_ARGS__; \
size_t n = ULAS_TOKMAX; \
- char buf[n]; \
- memset(buf, 0, n); \
+ struct ulas_str dst = ulas_str(n); \
+ memset(dst.buf, 0, n); \
int i = 0; \
const char *pline = line; \
- while (ulas_tokline(buf, &pline, n, rule)) { \
- assert(strcmp(buf, expect[i]) == 0); \
+ while (ulas_tokline(&dst, &pline, n, rule)) { \
+ assert(strcmp(dst.buf, expect[i]) == 0); \
i++; \
} \
assert(i == expected_n); \
+ ulas_strfree(&dst); \
}
void test_tok(void) {
TESTEND("tok");
}
+void test_strbuf(void) {
+ TESTBEGIN("strbuf");
+
+ struct ulas_str s = ulas_str(5);
+ assert(s.maxlen == 5);
+ assert(s.buf);
+
+ s = ulas_strensr(&s, 10);
+ assert(s.maxlen == 10);
+ assert(s.buf);
+
+ ulas_strfree(&s);
+
+ TESTEND("strbuf");
+}
+
#define assert_preproc(expect_dst, expect_ret, input) \
{ \
char dstbuf[ULAS_LINEMAX]; \
}*/
test_tok();
+ test_strbuf();
test_preproc();
return 0;
#include <ctype.h>
#include <errno.h>
#include <string.h>
+#include <assert.h>
FILE *ulasin = NULL;
FILE *ulasout = NULL;
return 0;
}
-int ulas_tok(char *dst, const char *line, size_t n, ulas_tokrule rule) {
- if (!dst || !line || n == 0) {
+int ulas_tok(struct ulas_str *dst, const char *line, size_t n,
+ ulas_tokrule rule) {
+ if (!dst->buf || !line || n == 0) {
return -1;
}
+ ulas_strensr(dst, n + 1);
int i = 0;
int write = 0;
-#define weld_tokcond (i < n - 1 && write < n - 1 && line[i])
+#define weld_tokcond (i < n && write < n && line[i])
// always skip leading terminators
while (weld_tokcond && rule(line[i])) {
if (rule(line[i])) {
break;
}
- dst[write] = line[i];
+ dst->buf[write] = line[i];
i++;
write++;
}
#undef weld_tokcond
- dst[write] = '\0';
+ dst->buf[write] = '\0';
return i;
}
-int ulas_tokline(char *dst, const char **line, size_t n, ulas_tokrule rule) {
+int ulas_tokline(struct ulas_str *dst, const char **line, size_t n,
+ ulas_tokrule rule) {
int rc = ulas_tok(dst, *line, n, rule);
if (rc == -1) {
return -1;
*line += rc;
return rc;
}
+
+struct ulas_str ulas_str(size_t n) {
+ struct ulas_str str = {malloc(n), n};
+ return str;
+}
+
+struct ulas_str ulas_strensr(struct ulas_str *s, size_t maxlen) {
+ if (s->maxlen < maxlen) {
+ char *c = realloc(s->buf, maxlen);
+ if (!c) {
+ ULASPANIC("%s\n", strerror(errno));
+ }
+ s->maxlen = maxlen;
+ s->buf = c;
+ }
+
+ return *s;
+}
+
+void ulas_strfree(struct ulas_str *s) {
+ if (s->buf) {
+ free(s->buf);
+ }
+}
+
+char *ulas_preprocexpand(struct ulas_preproc *pp, const char *raw_line,
+ size_t *n) {
+ const char *praw_line = raw_line;
+ ulas_strensr(&pp->line, (*n) + 1);
+
+ // go through all tokens, see if a define matches the token,
+ // if so expand it
+ // only expand macros if they match toks[0] though!
+ // otherwise memcpy the read bytes 1:1 into the new string
+ while (ulas_tokline(&pp->tok, &praw_line, ULAS_TOKMAX, isalnum)) {
+ }
+
+ // TODO: actually expand here...
+ strncpy(pp->line.buf, raw_line, (*n) + 1);
+ *n = strlen(pp->line.buf);
+ return pp->line.buf;
+}
+
+int ulas_preprocline(struct ulas_preproc *pp, FILE *dst, const char *raw_line,
+ size_t n) {
+ if (n > ULAS_LINEMAX) {
+ ULASERR("%s: line exceeds %d (LINEMAX)\n", raw_line, ULAS_LINEMAX);
+ return -1;
+ }
+
+ char *line = ulas_preprocexpand(pp, raw_line, &n);
+ const char *pline = line;
+
+ const char *dirstrs[] = {"#define", "#macro", "#ifdef", "#ifndef",
+ "#endif", "#endmacro", NULL};
+ enum ulas_ppdirs dirs[] = {ULAS_PPDIR_DEF, ULAS_PPDIR_MACRO,
+ ULAS_PPDIR_IFDEF, ULAS_PPDIR_IFNDEF,
+ ULAS_PPDIR_ENDIF, ULAS_PPDIR_ENDMACRO};
+
+ enum ulas_ppdirs found_dir = ULAS_PPDIR_NONE;
+
+ // check if the first token is any of the valid preproc directives
+ if (ulas_tokline(&pp->tok, &pline, ULAS_TOKMAX, isspace)) {
+ // not a preproc directive...
+ if (pp->tok.buf[0] != ULAS_TOK_PREPROC_BEGIN) {
+ goto found;
+ }
+ for (size_t i = 0; dirstrs[i]; i++) {
+ if (strncmp(dirstrs[i], pp->tok.buf, ULAS_TOKMAX) == 0) {
+ found_dir = dirs[i];
+ goto found;
+ }
+ }
+
+ ULASPANIC("Unknown preprocessor directive: %s\n", line);
+ return -1;
+ }
+found:
+
+ if (found_dir) {
+ // TODO: process directive
+ printf("%s preproc directive!\n", pp->tok.buf);
+ fputc('\0', dst);
+ } else {
+ assert(fwrite(line, 1, n, dst) == n);
+ }
+
+ return 0;
+}
+
+int ulas_preproc(FILE *dst, const char *dstname, FILE *src,
+ const char *srcname) {
+ char buf[ULAS_LINEMAX];
+ memset(buf, 0, ULAS_LINEMAX);
+ int rc = 0;
+
+ if (!dst || !src) {
+ ULASERR("[%s] Unable to read from dst or write to src!\n", srcname);
+ return -1;
+ }
+
+ struct ulas_preproc pp = {NULL, 0, srcname, dstname};
+
+ pp.line = ulas_str(1);
+ pp.tok = ulas_str(1);
+
+ while (fgets(buf, ULAS_LINEMAX, src) != NULL) {
+ if (ulas_preprocline(&pp, dst, buf, strlen(buf)) == -1) {
+ rc = -1;
+ goto fail;
+ }
+ }
+
+fail:
+ ulas_strfree(&pp.line);
+ ulas_strfree(&pp.tok);
+ return rc;
+}