scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit edba8c3a91301b4fcf0ecd0260bd56fa285038d4
parent 5207a71d38e39164095f0f2c5e3da71901c00335
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 10 Sep 2017 17:18:21 +0200

[as] Improve field splitter

This new vesion of the splitter allows character constants and
strings. It also fixes several bugs found in the original splitter.

Diffstat:
as/parser.c | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 62 insertions(+), 23 deletions(-)

diff --git a/as/parser.c b/as/parser.c @@ -63,31 +63,70 @@ wrong_operand: return args; } -int -extract(char *p, struct line *linep) +static char * +field(char **oldp) { - linep->label = p; - linep->op = NULL; - linep->args = NULL; + char *s, *begin; + int c; - if ((p = strchr(p, '\t')) == NULL) - return 0; - *p++ = '\0'; - - linep->op = p; - if ((p = strchr(p, '\t')) == NULL) - return 1; - *p++ = '\0'; - - linep->args = p; - if ((p = strchr(p, '\t')) == NULL) - return 2; - *p = '\0'; - return 3; + if ((begin = *oldp) == NULL) + return NULL; + + for (s = begin; ; s++) { + switch (c = *s) { + case '\t': + *s++ = '\0'; + *oldp = s; + goto out_loop; + case ';': + *s = '\0'; + case '\0': + *oldp = NULL; + goto out_loop; + case '\'': + if (*++s == '\0' || *++s != '\'') + error("invalid character constant"); + break; + case '"': + while ((c = *++s) && c != '"') + /* nothing */; + if (c == '\0') + error("unterminated string"); + break; + default: + *s = toupper(c); + break; + } + } + +out_loop: + return (*begin != '\0') ? begin : NULL; +} + +static int +extract(char *s, struct line *lp) +{ + int r = 0; + + if (lp->label = field(&s)) + r++; + if (lp->op = field(&s)) + r++; + if (lp->args = field(&s)) + r++; + + if (s) { + while (isspace(*s)) + ++s; + if (*s != '\0' && *s != ';') + error("trailing characters at the end of the line"); + } + + return r; } int -next(FILE *fp, struct line *linep) +next(FILE *fp, struct line *lp) { size_t n; static char buff[MAXLINE]; @@ -97,14 +136,14 @@ repeat: return 0; n = strlen(buff); - if (n == 0 || buff[0] == ';') + if (n == 0) goto repeat; if (buff[n-1] != '\n') { - error("buff too long"); + error("line too long"); goto repeat; } buff[n-1] = '\0'; - if (extract(buff, linep) == 0) + if (extract(buff, lp) == 0) goto repeat; return 1; }