lexical.c, update to master status (remove line length limit)
This commit is contained in:
parent
227c383c92
commit
aab806b149
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue