From aab806b149d0bd05230f320be5e2d46adc2ee92d Mon Sep 17 00:00:00 2001 From: h_vogt Date: Tue, 18 Oct 2016 21:53:31 +0200 Subject: [PATCH] lexical.c, update to master status (remove line length limit) --- src/frontend/parser/lexical.c | 189 ++++++++++++++++++++-------------- 1 file changed, 109 insertions(+), 80 deletions(-) diff --git a/src/frontend/parser/lexical.c b/src/frontend/parser/lexical.c index e40528da9..1de18b67d 100644 --- a/src/frontend/parser/lexical.c +++ b/src/frontend/parser/lexical.c @@ -41,8 +41,6 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #endif #endif -#define NEW_BSIZE_SP 2*BSIZE_SP - #include "ngspice/fteinput.h" #include "lexical.h" @@ -65,7 +63,7 @@ static int numeofs = 0; /* Return a list of words, with backslash quoting and '' quoting done. - * Strings en(void) closed in "" or `` are made single words and returned, + * Strings enclosed in "" or `` are made single words and returned, * but with the "" or `` still present. For the \ and '' cases, the * 8th bit is turned on (as in csh) to prevent them from being recognized, * and stripped off once all processing is done. We also have to deal with @@ -74,15 +72,32 @@ static int numeofs = 0; * have no business being in the string. */ +struct cp_lexer_buf +{ + int i, sz; + char *s; +}; + + +static inline void +push(struct cp_lexer_buf *buf, int c) +{ + if (buf->sz <= buf->i) { + buf->sz += MAX(64, buf->sz); + buf->s = TREALLOC(char, buf->s, buf->sz); + } + buf->s[buf->i++] = (char) c; +} + + #define append(word) \ - wl_append_word(&wlist, &cw, word) + wl_append_word(&wlist, &wlist_tail, word) -#define newword \ - do { \ - append(copy(buf)); \ - bzero(buf, NEW_BSIZE_SP); \ - i = 0; \ +#define newword \ + do { \ + append(copy_substring(buf.s, buf.s + buf.i)); \ + buf.i = 0; \ } while(0) @@ -123,9 +138,9 @@ wordlist * cp_lexer(char *string) { int c, d; - int i, j; - wordlist *wlist = NULL, *cw = NULL; - char buf[NEW_BSIZE_SP], linebuf[NEW_BSIZE_SP]; + int i; + wordlist *wlist, *wlist_tail; + struct cp_lexer_buf buf, linebuf; int paren; if (!cp_inp_cur) @@ -137,16 +152,24 @@ cp_lexer(char *string) prompt(); } + wlist = wlist_tail = NULL; + + buf.sz = 0; + buf.s = NULL; + linebuf.sz = 0; + linebuf.s = NULL; + nloop: - wlist = cw = NULL; - i = 0; - j = 0; + if (wlist) + wl_free(wlist); + wlist = wlist_tail = NULL; + buf.i = 0; + linebuf.i = 0; paren = 0; - bzero(linebuf, NEW_BSIZE_SP); - bzero(buf, NEW_BSIZE_SP); for (;;) { + /* if string, read from string, else read from stdin */ c = cp_readchar(&string, cp_inp_cur); gotchar: @@ -155,110 +178,110 @@ nloop: continue; if ((c != EOF) && (c != ESCAPE)) - linebuf[j++] = (char) c; + push(&linebuf, c); if (c != EOF) numeofs = 0; - if (i == NEW_BSIZE_SP - 1) { - fprintf(cp_err, "Warning: word too long.\n"); - c = ' '; - } - - if (j == NEW_BSIZE_SP - 1) { - fprintf(cp_err, "Warning: line too long.\n"); - if (cp_bqflag) - c = EOF; - else - c = '\n'; - } - if (c != EOF) /* Don't need to do this really. */ c = strip(c); + /* if '\' or '^', add following character to linebuf */ if ((c == '\\' && DIR_TERM != '\\') || (c == '\026') /* ^V */ ) { c = quote(cp_readchar(&string, cp_inp_cur)); - linebuf[j++] = (char) strip(c); + push(&linebuf, strip(c)); } + /* if reading from fcn backeval() for backquote subst. */ if ((c == '\n') && cp_bqflag) c = ' '; if ((c == EOF) && cp_bqflag) c = '\n'; - if ((c == cp_hash) && !cp_interactive && (j == 1)) { - wl_free(wlist); - wlist = cw = NULL; - if (string) + /* '#' as the first character in a line, + starts a comment line, drop it */ + if ((c == cp_hash) && !cp_interactive && (linebuf.i == 1)) { + if (string) { + wl_free(wlist); + tfree(buf.s); + tfree(linebuf.s); return NULL; + } while (((c = cp_readchar(&string, cp_inp_cur)) != '\n') && (c != EOF)) ; goto nloop; } - if ((c == '(') || (c == '[')) /* MW. Nedded by parse() */ + /* check if we are inside of parens during reading: + if we are and ',' or ';' occur: no new line */ + if ((c == '(') || (c == '[')) paren++; else if ((c == ')') || (c == ']')) paren--; + /* What else has to be decided, depending on c ? */ switch (c) { + /* new word to wordlist, when space or tab follow */ case ' ': case '\t': - if (i > 0) + if (buf.i > 0) newword; break; + /* new word to wordlist, when \n follows */ case '\n': - if (i) { - buf[i] = '\0'; + if (buf.i) newword; - } - if (!cw) + if (!wlist_tail) append(NULL); goto done; + /* if ' read until next ' is hit, will form a new word, + but without the ' */ case '\'': - while (((c = cp_readchar(&string, cp_inp_cur)) != '\'') && - (i < NEW_BSIZE_SP - 1)) + while ((c = cp_readchar(&string, cp_inp_cur)) != '\'') { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; - buf[i++] = (char) quote(c); - linebuf[j++] = (char) c; + push(&buf, quote(c)); + push(&linebuf, c); } - linebuf[j++] = '\''; + push(&linebuf, '\''); break; + /* if " or `, read until next " or ` is hit, will form a new word, + including the quotes. + In case of \, the next character gets the eights bit set. */ case '"': case '`': d = c; - buf[i++] = (char) d; - while (((c = cp_readchar(&string, cp_inp_cur)) != d) && - (i < NEW_BSIZE_SP - 2)) + push(&buf, d); + while ((c = cp_readchar(&string, cp_inp_cur)) != d) { if ((c == '\n') || (c == EOF) || (c == ESCAPE)) goto gotchar; if (c == '\\') { - linebuf[j++] = (char) c; + push(&linebuf, c); c = cp_readchar(&string, cp_inp_cur); - buf[i++] = (char) quote(c); - linebuf[j++] = (char) c; + push(&buf, quote(c)); + push(&linebuf, c); } else { - buf[i++] = (char) c; - linebuf[j++] = (char) c; + push(&buf, c); + push(&linebuf, c); } } - buf[i++] = (char) d; - linebuf[j++] = (char) d; + push(&buf, d); + push(&linebuf, d); break; case '\004': case EOF: + /* upon command completion, not used actually */ if (cp_interactive && !cp_nocc && !string) { - if (j == 0) { + if (linebuf.i == 0) { if (cp_ignoreeof && (numeofs++ < 23)) { fputs("Use \"quit\" to quit.\n", stdout); } else { @@ -269,18 +292,19 @@ nloop: goto done; } + push(&buf, '\0'); + push(&linebuf, '\0'); + // cp_ccom doesn't mess wlist, read only access to wlist->wl_word - cp_ccom(wlist, buf, FALSE); - wl_free(wlist); + cp_ccom(wlist, buf.s, FALSE); (void) fputc('\r', cp_out); prompt(); - for (j = 0; linebuf[j]; j++) + for (i = 0; linebuf.s[i]; i++) #ifdef TIOCSTI - (void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); + (void) ioctl(fileno(cp_out), TIOCSTI, linebuf.s + i); #else - fputc(linebuf[j], cp_out); /* But you can't edit */ + fputc(linebuf.s[i], cp_out); /* But you can't edit */ #endif - wlist = cw = NULL; goto nloop; } @@ -293,28 +317,31 @@ nloop: } wl_free(wlist); + tfree(buf.s); + tfree(linebuf.s); return NULL; case ESCAPE: + /* upon command completion, not used actually */ if (cp_interactive && !cp_nocc) { + push(&buf, '\0'); + push(&linebuf, '\0'); fputs("\b\b \b\b\r", cp_out); prompt(); - for (j = 0; linebuf[j]; j++) + for (i = 0; linebuf.s[i]; i++) #ifdef TIOCSTI - (void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); + (void) ioctl(fileno(cp_out), TIOCSTI, linebuf.s + i); #else - fputc(linebuf[j], cp_out); /* But you can't edit */ + fputc(linebuf.s[i], cp_out); /* But you can't edit */ #endif // cp_ccom doesn't mess wlist, read only access to wlist->wl_word - cp_ccom(wlist, buf, TRUE); - wl_free(wlist); - wlist = cw = NULL; + cp_ccom(wlist, buf.s, TRUE); goto nloop; } goto ldefault; case ',': - if ((paren < 1) && (i > 0)) { + if ((paren < 1) && (buf.i > 0)) { newword; break; } @@ -322,14 +349,14 @@ nloop: case ';': /* CDHW semicolon inside parentheses is part of expression */ if (paren > 0) { - buf[i++] = (char) c; + push(&buf, c); break; } goto ldefault; case '&': /* va: $&name is one word */ - if ((i >= 1) && (buf[i-1] == '$') && (c == '&')) { - buf[i++] = (char) c; + if ((buf.i >= 1) && (buf.s[buf.i - 1] == '$')) { + push(&buf, c); break; } goto ldefault; @@ -337,8 +364,8 @@ nloop: case '<': case '>': /* va: <=, >= are unbreakable words */ if (string) - if ((i == 0) && (*string == '=')) { - buf[i++] = (char) c; + if ((buf.i == 0) && (*string == '=')) { + push(&buf, c); break; } goto ldefault; @@ -348,12 +375,12 @@ nloop: * here */ ldefault: - if ((cp_chars[c] & CPC_BRL) && (i > 0)) - if ((c != '<') || (buf[i-1] != '$')) + if ((cp_chars[c] & CPC_BRL) && (buf.i > 0)) + if ((c != '<') || (buf.s[buf.i - 1] != '$')) newword; - buf[i++] = (char) c; + push(&buf, c); if (cp_chars[c] & CPC_BRR) - if ((c != '<') || (i < 2) || (buf[i-2] != '$')) + if ((c != '<') || (buf.i < 2) || (buf.s[buf.i - 2] != '$')) newword; } } @@ -361,6 +388,8 @@ nloop: done: if (wlist->wl_word) pwlist_echo(wlist, "Command>"); + tfree(buf.s); + tfree(linebuf.s); return wlist; }