lexical.c, update to master status (remove line length limit)

This commit is contained in:
h_vogt 2016-10-18 21:53:31 +02:00
parent 227c383c92
commit aab806b149
1 changed files with 109 additions and 80 deletions

View File

@ -41,8 +41,6 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#endif #endif
#endif #endif
#define NEW_BSIZE_SP 2*BSIZE_SP
#include "ngspice/fteinput.h" #include "ngspice/fteinput.h"
#include "lexical.h" #include "lexical.h"
@ -65,7 +63,7 @@ static int numeofs = 0;
/* Return a list of words, with backslash quoting and '' quoting done. /* 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 * 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, * 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 * 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. * 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) \ #define append(word) \
wl_append_word(&wlist, &cw, word) wl_append_word(&wlist, &wlist_tail, word)
#define newword \ #define newword \
do { \ do { \
append(copy(buf)); \ append(copy_substring(buf.s, buf.s + buf.i)); \
bzero(buf, NEW_BSIZE_SP); \ buf.i = 0; \
i = 0; \
} while(0) } while(0)
@ -123,9 +138,9 @@ wordlist *
cp_lexer(char *string) cp_lexer(char *string)
{ {
int c, d; int c, d;
int i, j; int i;
wordlist *wlist = NULL, *cw = NULL; wordlist *wlist, *wlist_tail;
char buf[NEW_BSIZE_SP], linebuf[NEW_BSIZE_SP]; struct cp_lexer_buf buf, linebuf;
int paren; int paren;
if (!cp_inp_cur) if (!cp_inp_cur)
@ -137,16 +152,24 @@ cp_lexer(char *string)
prompt(); prompt();
} }
wlist = wlist_tail = NULL;
buf.sz = 0;
buf.s = NULL;
linebuf.sz = 0;
linebuf.s = NULL;
nloop: nloop:
wlist = cw = NULL; if (wlist)
i = 0; wl_free(wlist);
j = 0; wlist = wlist_tail = NULL;
buf.i = 0;
linebuf.i = 0;
paren = 0; paren = 0;
bzero(linebuf, NEW_BSIZE_SP);
bzero(buf, NEW_BSIZE_SP);
for (;;) { for (;;) {
/* if string, read from string, else read from stdin */
c = cp_readchar(&string, cp_inp_cur); c = cp_readchar(&string, cp_inp_cur);
gotchar: gotchar:
@ -155,110 +178,110 @@ nloop:
continue; continue;
if ((c != EOF) && (c != ESCAPE)) if ((c != EOF) && (c != ESCAPE))
linebuf[j++] = (char) c; push(&linebuf, c);
if (c != EOF) if (c != EOF)
numeofs = 0; 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. */ if (c != EOF) /* Don't need to do this really. */
c = strip(c); c = strip(c);
/* if '\' or '^', add following character to linebuf */
if ((c == '\\' && DIR_TERM != '\\') || (c == '\026') /* ^V */ ) { if ((c == '\\' && DIR_TERM != '\\') || (c == '\026') /* ^V */ ) {
c = quote(cp_readchar(&string, cp_inp_cur)); 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) if ((c == '\n') && cp_bqflag)
c = ' '; c = ' ';
if ((c == EOF) && cp_bqflag) if ((c == EOF) && cp_bqflag)
c = '\n'; c = '\n';
if ((c == cp_hash) && !cp_interactive && (j == 1)) { /* '#' as the first character in a line,
wl_free(wlist); starts a comment line, drop it */
wlist = cw = NULL; if ((c == cp_hash) && !cp_interactive && (linebuf.i == 1)) {
if (string) if (string) {
wl_free(wlist);
tfree(buf.s);
tfree(linebuf.s);
return NULL; return NULL;
}
while (((c = cp_readchar(&string, cp_inp_cur)) != '\n') && (c != EOF)) while (((c = cp_readchar(&string, cp_inp_cur)) != '\n') && (c != EOF))
; ;
goto nloop; 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++; paren++;
else if ((c == ')') || (c == ']')) else if ((c == ')') || (c == ']'))
paren--; paren--;
/* What else has to be decided, depending on c ? */
switch (c) { switch (c) {
/* new word to wordlist, when space or tab follow */
case ' ': case ' ':
case '\t': case '\t':
if (i > 0) if (buf.i > 0)
newword; newword;
break; break;
/* new word to wordlist, when \n follows */
case '\n': case '\n':
if (i) { if (buf.i)
buf[i] = '\0';
newword; newword;
} if (!wlist_tail)
if (!cw)
append(NULL); append(NULL);
goto done; goto done;
/* if ' read until next ' is hit, will form a new word,
but without the ' */
case '\'': case '\'':
while (((c = cp_readchar(&string, cp_inp_cur)) != '\'') && while ((c = cp_readchar(&string, cp_inp_cur)) != '\'')
(i < NEW_BSIZE_SP - 1))
{ {
if ((c == '\n') || (c == EOF) || (c == ESCAPE)) if ((c == '\n') || (c == EOF) || (c == ESCAPE))
goto gotchar; goto gotchar;
buf[i++] = (char) quote(c); push(&buf, quote(c));
linebuf[j++] = (char) c; push(&linebuf, c);
} }
linebuf[j++] = '\''; push(&linebuf, '\'');
break; 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 '"':
case '`': case '`':
d = c; d = c;
buf[i++] = (char) d; push(&buf, d);
while (((c = cp_readchar(&string, cp_inp_cur)) != d) && while ((c = cp_readchar(&string, cp_inp_cur)) != d)
(i < NEW_BSIZE_SP - 2))
{ {
if ((c == '\n') || (c == EOF) || (c == ESCAPE)) if ((c == '\n') || (c == EOF) || (c == ESCAPE))
goto gotchar; goto gotchar;
if (c == '\\') { if (c == '\\') {
linebuf[j++] = (char) c; push(&linebuf, c);
c = cp_readchar(&string, cp_inp_cur); c = cp_readchar(&string, cp_inp_cur);
buf[i++] = (char) quote(c); push(&buf, quote(c));
linebuf[j++] = (char) c; push(&linebuf, c);
} else { } else {
buf[i++] = (char) c; push(&buf, c);
linebuf[j++] = (char) c; push(&linebuf, c);
} }
} }
buf[i++] = (char) d; push(&buf, d);
linebuf[j++] = (char) d; push(&linebuf, d);
break; break;
case '\004': case '\004':
case EOF: case EOF:
/* upon command completion, not used actually */
if (cp_interactive && !cp_nocc && !string) { if (cp_interactive && !cp_nocc && !string) {
if (j == 0) { if (linebuf.i == 0) {
if (cp_ignoreeof && (numeofs++ < 23)) { if (cp_ignoreeof && (numeofs++ < 23)) {
fputs("Use \"quit\" to quit.\n", stdout); fputs("Use \"quit\" to quit.\n", stdout);
} else { } else {
@ -269,18 +292,19 @@ nloop:
goto done; goto done;
} }
push(&buf, '\0');
push(&linebuf, '\0');
// cp_ccom doesn't mess wlist, read only access to wlist->wl_word // cp_ccom doesn't mess wlist, read only access to wlist->wl_word
cp_ccom(wlist, buf, FALSE); cp_ccom(wlist, buf.s, FALSE);
wl_free(wlist);
(void) fputc('\r', cp_out); (void) fputc('\r', cp_out);
prompt(); prompt();
for (j = 0; linebuf[j]; j++) for (i = 0; linebuf.s[i]; i++)
#ifdef TIOCSTI #ifdef TIOCSTI
(void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); (void) ioctl(fileno(cp_out), TIOCSTI, linebuf.s + i);
#else #else
fputc(linebuf[j], cp_out); /* But you can't edit */ fputc(linebuf.s[i], cp_out); /* But you can't edit */
#endif #endif
wlist = cw = NULL;
goto nloop; goto nloop;
} }
@ -293,28 +317,31 @@ nloop:
} }
wl_free(wlist); wl_free(wlist);
tfree(buf.s);
tfree(linebuf.s);
return NULL; return NULL;
case ESCAPE: case ESCAPE:
/* upon command completion, not used actually */
if (cp_interactive && !cp_nocc) { if (cp_interactive && !cp_nocc) {
push(&buf, '\0');
push(&linebuf, '\0');
fputs("\b\b \b\b\r", cp_out); fputs("\b\b \b\b\r", cp_out);
prompt(); prompt();
for (j = 0; linebuf[j]; j++) for (i = 0; linebuf.s[i]; i++)
#ifdef TIOCSTI #ifdef TIOCSTI
(void) ioctl(fileno(cp_out), TIOCSTI, linebuf + j); (void) ioctl(fileno(cp_out), TIOCSTI, linebuf.s + i);
#else #else
fputc(linebuf[j], cp_out); /* But you can't edit */ fputc(linebuf.s[i], cp_out); /* But you can't edit */
#endif #endif
// cp_ccom doesn't mess wlist, read only access to wlist->wl_word // cp_ccom doesn't mess wlist, read only access to wlist->wl_word
cp_ccom(wlist, buf, TRUE); cp_ccom(wlist, buf.s, TRUE);
wl_free(wlist);
wlist = cw = NULL;
goto nloop; goto nloop;
} }
goto ldefault; goto ldefault;
case ',': case ',':
if ((paren < 1) && (i > 0)) { if ((paren < 1) && (buf.i > 0)) {
newword; newword;
break; break;
} }
@ -322,14 +349,14 @@ nloop:
case ';': /* CDHW semicolon inside parentheses is part of expression */ case ';': /* CDHW semicolon inside parentheses is part of expression */
if (paren > 0) { if (paren > 0) {
buf[i++] = (char) c; push(&buf, c);
break; break;
} }
goto ldefault; goto ldefault;
case '&': /* va: $&name is one word */ case '&': /* va: $&name is one word */
if ((i >= 1) && (buf[i-1] == '$') && (c == '&')) { if ((buf.i >= 1) && (buf.s[buf.i - 1] == '$')) {
buf[i++] = (char) c; push(&buf, c);
break; break;
} }
goto ldefault; goto ldefault;
@ -337,8 +364,8 @@ nloop:
case '<': case '<':
case '>': /* va: <=, >= are unbreakable words */ case '>': /* va: <=, >= are unbreakable words */
if (string) if (string)
if ((i == 0) && (*string == '=')) { if ((buf.i == 0) && (*string == '=')) {
buf[i++] = (char) c; push(&buf, c);
break; break;
} }
goto ldefault; goto ldefault;
@ -348,12 +375,12 @@ nloop:
* here * here
*/ */
ldefault: ldefault:
if ((cp_chars[c] & CPC_BRL) && (i > 0)) if ((cp_chars[c] & CPC_BRL) && (buf.i > 0))
if ((c != '<') || (buf[i-1] != '$')) if ((c != '<') || (buf.s[buf.i - 1] != '$'))
newword; newword;
buf[i++] = (char) c; push(&buf, c);
if (cp_chars[c] & CPC_BRR) if (cp_chars[c] & CPC_BRR)
if ((c != '<') || (i < 2) || (buf[i-2] != '$')) if ((c != '<') || (buf.i < 2) || (buf.s[buf.i - 2] != '$'))
newword; newword;
} }
} }
@ -361,6 +388,8 @@ nloop:
done: done:
if (wlist->wl_word) if (wlist->wl_word)
pwlist_echo(wlist, "Command>"); pwlist_echo(wlist, "Command>");
tfree(buf.s);
tfree(linebuf.s);
return wlist; return wlist;
} }