ref: 1213937bfa73b0303bd50faafcc99bf759716b4e
parent: 196b6aee42727015dac4a55161cebae401a3d852
author: Roberto E. Vargas Caballero <[email protected]>
date: Sun Sep 10 13:18:21 EDT 2017
[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.
--- a/as/parser.c
+++ b/as/parser.c
@@ -63,31 +63,70 @@
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';
+ if ((begin = *oldp) == NULL)
+ return NULL;
- linep->op = p;
- if ((p = strchr(p, '\t')) == NULL)
- return 1;
- *p++ = '\0';
+ 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;
+ }
+ }
- linep->args = p;
- if ((p = strchr(p, '\t')) == NULL)
- return 2;
- *p = '\0';
- return 3;
+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 @@
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;
}