Made checking for single-character words faster. The testing now also uses less memory and works for 8-bit characters, which would have previously caused buffer overruns. It is also more modular and has additional documentation.

This commit is contained in:
Jim Monte 2019-12-09 19:09:39 -05:00
parent 987cf14542
commit b39e5d9507
3 changed files with 60 additions and 29 deletions

View File

@ -12,10 +12,6 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "variable.h"
char cp_chars[128]; /* used in fcn cp_lexer() from lexical.c */
static char *singlec = "<>;&";
void
cp_init(void)
/* called from ft_cpinit() in cpitf.c.
@ -25,13 +21,6 @@ cp_init(void)
cp_curin, cp_curout, cp_curerr (defined in streams.c)
*/
{
char *s;
memset(cp_chars, 0, 128);
for (s = singlec; *s; s++)
/* break word to right or left of characters <>;&*/
cp_chars[(int) *s] = (CPC_BRR | CPC_BRL);
cp_vset("history", CP_NUM, &cp_maxhistlength);
cp_curin = stdin;

View File

@ -7,6 +7,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
* Initial lexer.
*/
#include "ngspice/defines.h"
#include "ngspice/ngspice.h"
#include "ngspice/cpdefs.h"
@ -44,6 +45,23 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "ngspice/fteinput.h"
#include "lexical.h"
/** Constants related to characters that form their own words.
** These expressions will be resolved at compile time */
#define ID_SOLO_CHAR 1 /* Identifier for special chars */
/* Largest of the special chars */
#define MAX_SOLO_CHAR1 ('<' > '>' ? '<' : '>')
#define MAX_SOLO_CHAR2 (MAX_SOLO_CHAR1 > ';' ? MAX_SOLO_CHAR1 : ';')
#define MAX_SOLO_CHAR (MAX_SOLO_CHAR2 > '&' ? MAX_SOLO_CHAR2 : '&')
/* Smallest of the special chars */
#define MIN_SOLO_CHAR1 ('<' < '>' ? '<' : '>')
#define MIN_SOLO_CHAR2 (MIN_SOLO_CHAR1 < ';' ? MIN_SOLO_CHAR1 : ';')
#define MIN_SOLO_CHAR (MIN_SOLO_CHAR2 < '&' ? MIN_SOLO_CHAR2 : '&')
/* Largest index of solo char array */
#define MAX_INDEX_SOLO_CHAR (MAX_SOLO_CHAR - MIN_SOLO_CHAR)
static void prompt(void);
extern bool cp_echo; /* For CDHW patches: defined in variable.c */
@ -370,19 +388,48 @@ nloop:
goto ldefault;
default:
/* We have to remember the special case $<
* here
*/
ldefault:
if ((cp_chars[c] & CPC_BRL) && (buf.i > 0))
if ((c != '<') || (buf.s[buf.i - 1] != '$'))
newword;
push(&buf, c);
if (cp_chars[c] & CPC_BRR)
if ((c != '<') || (buf.i < 2) || (buf.s[buf.i - 2] != '$'))
newword;
}
}
/* $< is a special case where the '<' is not treated
* as a character forming its own word */
ldefault: {
/* Lookup table for "solo" chars forming their own word */
static const char id_solo_chars[MAX_INDEX_SOLO_CHAR + 1] = {
['<' - MIN_SOLO_CHAR] = ID_SOLO_CHAR,
['>' - MIN_SOLO_CHAR] = ID_SOLO_CHAR,
[';' - MIN_SOLO_CHAR] = ID_SOLO_CHAR,
['&' - MIN_SOLO_CHAR] = ID_SOLO_CHAR
};
/* Find index into solo chars table */
const unsigned int index_char =
(unsigned int) c - (unsigned int) MIN_SOLO_CHAR;
/* Flag that the current character c is a solo character */
const bool f_solo_char = index_char <= MAX_INDEX_SOLO_CHAR &&
id_solo_chars[index_char];
bool f_is_dollar_lt = FALSE;
if (f_solo_char && buf.i > 0) {
/* The current char is a character forming its own word,
* unless it is "$<" */
if (c == '<' && buf.s[buf.i - 1] == '$') { /* is "$<" */
f_is_dollar_lt = TRUE; /* set flag that "$<" found */
}
else {
/* not "$<", so terminate current word and start
* another one */
newword;
}
}
push(&buf, c); /* Add the current char to the current word */
if (f_solo_char && !f_is_dollar_lt) {
/* Split into a new word if this char forms its own word */
newword;
}
} /* end of ldefault block */
} /* end of switch over character value */
} /* end of loop over characters */
done:
if (wlist->wl_word)

View File

@ -84,11 +84,6 @@ struct alias {
struct alias *al_prev;
} ;
/* The current record of what characters are special. */
#define CPC_BRR 004 /* Break word to right of character. */
#define CPC_BRL 010 /* Break word to left of character. */
#define CT_ALIASES 1
#define CT_LABEL 15