fixed bugs, added dynamic buffer allocation

This commit is contained in:
eck 1989-11-22 12:59:15 +00:00
parent 5ffd738802
commit f9fadbf045
8 changed files with 362 additions and 262 deletions

View file

@ -16,7 +16,7 @@ LLmessage(tk) {
error("garbage at end of line"); error("garbage at end of line");
else if (tk) { else if (tk) {
error("%s missing", symbol2str(tk)); error("%s missing", symbol2str(tk));
if (DOT != EOF) SkipToNewLine(0); if (DOT != EOF) SkipToNewLine();
DOT = EOF; DOT = EOF;
} }
else else

View file

@ -65,8 +65,8 @@ STRSRC = macro.str replace.str
GSTRSRC = macro.h replace.h GSTRSRC = macro.h replace.h
# .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE! # .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
GHSRC = errout.h idfsize.h ifdepth.h lapbuf.h \ GHSRC = errout.h idfsize.h ifdepth.h macbuf.h \
nparams.h numsize.h obufsize.h argbuf.h \ nparams.h numsize.h obufsize.h \
parbufsize.h pathlength.h strsize.h textsize.h \ parbufsize.h pathlength.h strsize.h textsize.h \
botch_free.h debug.h inputtype.h dobits.h line_prefix.h botch_free.h debug.h inputtype.h dobits.h line_prefix.h
@ -222,14 +222,13 @@ preprocess.o: line_prefix.h
preprocess.o: macro.h preprocess.o: macro.h
preprocess.o: obufsize.h preprocess.o: obufsize.h
replace.o: LLlex.h replace.o: LLlex.h
replace.o: argbuf.h
replace.o: class.h replace.o: class.h
replace.o: file_info.h replace.o: file_info.h
replace.o: idf.h replace.o: idf.h
replace.o: idfsize.h replace.o: idfsize.h
replace.o: input.h replace.o: input.h
replace.o: inputtype.h replace.o: inputtype.h
replace.o: lapbuf.h replace.o: macbuf.h
replace.o: macro.h replace.o: macro.h
replace.o: nparams.h replace.o: nparams.h
replace.o: numsize.h replace.o: numsize.h

View file

@ -25,12 +25,9 @@
#define IFDEPTH 256 /* maximum number of nested if-constructions */ #define IFDEPTH 256 /* maximum number of nested if-constructions */
!File: lapbuf.h !File: macbuf.h
#define LAPBUF 4096 /* size of macro actual parameter buffer */ #define LAPBUF 128 /* initial size of macro replacement buffer */
#define ARGBUF 128 /* initial size of macro parameter buffer(s) */
!File: argbuf.h
#define ARGBUF 2048 /* sizeof of macro actual parameter buffer */
!File: strsize.h !File: strsize.h

View file

@ -22,6 +22,8 @@
#include "class.h" #include "class.h"
#include "macro.h" #include "macro.h"
#include "bits.h" #include "bits.h"
#include "macbuf.h"
#include "replace.h"
extern char options[]; extern char options[];
extern char **inctable; /* list of include directories */ extern char **inctable; /* list of include directories */
@ -54,7 +56,7 @@ GetIdentifier(skiponerr)
ReplaceMacros = 1; ReplaceMacros = 1;
UnknownIdIsZero = tmp; UnknownIdIsZero = tmp;
if (tok != IDENTIFIER) { if (tok != IDENTIFIER) {
if (skiponerr && tok != EOF) SkipToNewLine(0); if (skiponerr && tok != EOF) SkipToNewLine();
return (char *)0; return (char *)0;
} }
return tk.tk_str; return tk.tk_str;
@ -85,7 +87,7 @@ domacro()
id = findidf(tk.tk_str); id = findidf(tk.tk_str);
if (!id) { if (!id) {
error("%s: unknown control", tk.tk_str); error("%s: unknown control", tk.tk_str);
SkipToNewLine(0); SkipToNewLine();
free(tk.tk_str); free(tk.tk_str);
break; break;
} }
@ -121,7 +123,7 @@ domacro()
*/ */
if (GetToken(&tk) != INTEGER) { if (GetToken(&tk) != INTEGER) {
error("bad #line syntax"); error("bad #line syntax");
SkipToNewLine(0); SkipToNewLine();
} }
else else
do_line((unsigned int)tk.tk_val); do_line((unsigned int)tk.tk_val);
@ -131,14 +133,13 @@ domacro()
break; break;
case K_PRAGMA: /* "pragma" */ case K_PRAGMA: /* "pragma" */
return 0; /* this is for the compiler */ return 0; /* this is for the compiler */
break;
case K_UNDEF: /* "undef" */ case K_UNDEF: /* "undef" */
do_undef(); do_undef();
break; break;
default: default:
/* invalid word seen after the '#' */ /* invalid word seen after the '#' */
error("%s: unknown control", id->id_text); error("%s: unknown control", id->id_text);
SkipToNewLine(0); SkipToNewLine();
} }
break; break;
case INTEGER: /* # <integer> [<filespecifier>]? */ case INTEGER: /* # <integer> [<filespecifier>]? */
@ -148,7 +149,7 @@ domacro()
break; break;
default: /* invalid token following '#' */ default: /* invalid token following '#' */
error("illegal # line"); error("illegal # line");
SkipToNewLine(0); SkipToNewLine();
} }
return 1; return 1;
} }
@ -180,15 +181,21 @@ int to_endif;
NoUnstack--; NoUnstack--;
return; return;
} }
UnGetChar(); if (ch == '/') {
SkipToNewLine(0); if (ch != '*') UnGetChar();
else {
skipcomment();
continue;
}
} else UnGetChar();
SkipToNewLine();
continue; continue;
} }
ReplaceMacros = 0; ReplaceMacros = 0;
toknum = GetToken(&tk); toknum = GetToken(&tk);
ReplaceMacros = 1; ReplaceMacros = 1;
if (toknum != IDENTIFIER) { if (toknum != IDENTIFIER) {
SkipToNewLine(0); SkipToNewLine();
continue; continue;
} }
/* an IDENTIFIER: look for #if, #ifdef and #ifndef /* an IDENTIFIER: look for #if, #ifdef and #ifndef
@ -200,13 +207,13 @@ int to_endif;
free(tk.tk_str); free(tk.tk_str);
switch(id->id_resmac) { switch(id->id_resmac) {
default: default:
SkipToNewLine(0); SkipToNewLine();
break; break;
case K_IF: case K_IF:
case K_IFDEF: case K_IFDEF:
case K_IFNDEF: case K_IFNDEF:
push_if(); push_if();
SkipToNewLine(0); SkipToNewLine();
break; break;
case K_ELIF: case K_ELIF:
if (ifstack[nestlevel]) if (ifstack[nestlevel])
@ -219,26 +226,26 @@ int to_endif;
return; return;
} }
} }
else SkipToNewLine(0); /* otherwise done in ifexpr() */ else SkipToNewLine(); /* otherwise done in ifexpr() */
break; break;
case K_ELSE: case K_ELSE:
if (ifstack[nestlevel]) if (ifstack[nestlevel])
error("#else after #else"); error("#else after #else");
++(ifstack[nestlevel]); ++(ifstack[nestlevel]);
if (!to_endif && nestlevel == skiplevel) { if (!to_endif && nestlevel == skiplevel) {
if (SkipToNewLine(1)) { if (SkipToNewLine()) {
if (!options['o']) if (!options['o'])
strict("garbage following #else"); strict("garbage following #else");
} }
NoUnstack--; NoUnstack--;
return; return;
} }
else SkipToNewLine(0); else SkipToNewLine();
break; break;
case K_ENDIF: case K_ENDIF:
assert(nestlevel > svnestlevel[nestcount]); assert(nestlevel > svnestlevel[nestcount]);
if (nestlevel == skiplevel) { if (nestlevel == skiplevel) {
if (SkipToNewLine(1)) { if (SkipToNewLine()) {
if (!options['o']) if (!options['o'])
strict("garbage following #endif"); strict("garbage following #endif");
} }
@ -246,7 +253,7 @@ int to_endif;
NoUnstack--; NoUnstack--;
return; return;
} }
else SkipToNewLine(0); else SkipToNewLine();
nestlevel--; nestlevel--;
break; break;
} }
@ -292,7 +299,7 @@ do_include()
filenm = (char *)0; filenm = (char *)0;
} }
AccFileSpecifier = 0; AccFileSpecifier = 0;
SkipToNewLine(0); SkipToNewLine();
inctable[0] = WorkingDir; inctable[0] = WorkingDir;
if (filenm) { if (filenm) {
if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){ if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
@ -331,7 +338,7 @@ do_define()
ch = GetChar(); ch = GetChar();
if (ch == '(') { if (ch == '(') {
if ((nformals = getparams(formals, parbuf)) == -1) { if ((nformals = getparams(formals, parbuf)) == -1) {
SkipToNewLine(0); SkipToNewLine();
free(str); free(str);
return; /* an error occurred */ return; /* an error occurred */
} }
@ -340,17 +347,8 @@ do_define()
/* read the replacement text if there is any */ /* read the replacement text if there is any */
ch = skipspaces(ch,0); /* find first character of the text */ ch = skipspaces(ch,0); /* find first character of the text */
assert(ch != EOI); assert(ch != EOI);
if (class(ch) == STNL) {
/* Treat `#define something' as `#define something ""'
*/
repl_text = Malloc(1);
*repl_text = '\0';
length = 0;
}
else {
UnGetChar(); UnGetChar();
repl_text = get_text((nformals > 0) ? formals : 0, &length); repl_text = get_text((nformals > 0) ? formals : 0, &length);
}
macro_def(str2idf(str, 0), repl_text, nformals, length, NOFLAG); macro_def(str2idf(str, 0), repl_text, nformals, length, NOFLAG);
LineNumber++; LineNumber++;
} }
@ -367,12 +365,12 @@ do_elif()
{ {
if (nestlevel <= svnestlevel[nestcount]) { if (nestlevel <= svnestlevel[nestcount]) {
error("#elif without corresponding #if"); error("#elif without corresponding #if");
SkipToNewLine(0); SkipToNewLine();
} }
else { /* restart at this level as if a #if is detected. */ else { /* restart at this level as if a #if is detected. */
if (ifstack[nestlevel]) { if (ifstack[nestlevel]) {
error("#elif after #else"); error("#elif after #else");
SkipToNewLine(0); SkipToNewLine();
} }
nestlevel--; nestlevel--;
push_if(); push_if();
@ -382,7 +380,7 @@ do_elif()
do_else() do_else()
{ {
if (SkipToNewLine(1)) { if (SkipToNewLine()) {
if (!options['o']) if (!options['o'])
strict("garbage following #else"); strict("garbage following #else");
} }
@ -399,7 +397,7 @@ do_else()
do_endif() do_endif()
{ {
if (SkipToNewLine(1)) { if (SkipToNewLine()) {
if (!options['o']) if (!options['o'])
strict("garbage following #endif"); strict("garbage following #endif");
} }
@ -438,7 +436,7 @@ do_ifdef(how)
if (how ^ (id && id->id_macro != 0)) if (how ^ (id && id->id_macro != 0))
skip_block(0); skip_block(0);
else else
SkipToNewLine(0); SkipToNewLine();
} }
do_undef() do_undef()
@ -458,7 +456,7 @@ do_undef()
} }
} /* else: don't complain */ } /* else: don't complain */
free(str); free(str);
SkipToNewLine(0); SkipToNewLine();
} }
else else
error("illegal #undef construction"); error("illegal #undef construction");
@ -604,6 +602,8 @@ find_name(nm, index)
return 0; return 0;
} }
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
char * char *
get_text(formals, length) get_text(formals, length)
char *formals[]; char *formals[];
@ -620,92 +620,102 @@ get_text(formals, length)
text is returned. text is returned.
Implementation: Implementation:
finite automaton : we are only interested in finite automaton : we are interested in
identifiers, because they might be replaced by some actual 1- white space, sequences must be mapped onto 1 single
parameter. Other tokens will not be seen as such. blank.
2- identifiers, since they might be replaced by some
actual parameter.
3- strings and character constants, since replacing
variables within them is illegal, and white-space is
significant.
4- comment, same as for 1
Other tokens will not be seen as such.
*/ */
register int c; register int c;
register unsigned text_size; struct repl repls;
char *text = Malloc(text_size = ITEXTSIZE); register struct repl *repl = &repls;
register int pos = 0; int blank = 0;
c = GetChar(); c = GetChar();
repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
while ((c != EOI) && (class(c) != STNL)) { while ((c != EOI) && (class(c) != STNL)) {
if (BLANK(c)) {
if (!blank++) add2repl(repl, ' ');
c = GetChar();
continue;
}
if (c == '\'' || c == '"') { if (c == '\'' || c == '"') {
register int delim = c; register int delim = c;
do { do {
/* being careful, as ever */ add2repl(repl, c);
if (pos+3 >= text_size) if (c == '\\') add2repl(repl, GetChar());
text = Srealloc(text, text_size <<= 1);
text[pos++] = c;
if (c == '\\')
text[pos++] = GetChar();
c = GetChar(); c = GetChar();
} while (c != delim && c != EOI && class(c) != STNL); } while (c != delim && c != EOI && class(c) != STNL);
text[pos++] = c; add2repl(repl, c);
c = GetChar(); c = GetChar();
} } else if (c == '/') {
else
if (c == '/') {
c = GetChar(); c = GetChar();
if (pos+1 >= text_size)
text = Srealloc(text, text_size <<= 1);
if (c == '*') { if (c == '*') {
skipcomment(); skipcomment();
text[pos++] = ' '; if (!blank++) add2repl(repl,' ');
c = GetChar(); c = GetChar();
} continue; /* skip zero'ing of blank */
else } else add2repl(repl, '/');
text[pos++] = '/'; } else if (formals
} && (class(c) == STIDF || class(c) == STELL)) {
else
if (formals && (class(c) == STIDF || class(c) == STELL)) {
char id_buf[IDFSIZE + 1]; char id_buf[IDFSIZE + 1];
register id_size = 0; register char *idp = id_buf;
register n; int n;
/* read identifier: it may be a formal parameter */ /* read identifier: it may be a formal parameter */
id_buf[id_size++] = c; *idp++ = c;
do { do {
c = GetChar(); c = GetChar();
if (id_size <= IDFSIZE) if (idp <= &id_buf[IDFSIZE])
id_buf[id_size++] = c; *idp++ = c;
} while (in_idf(c)); } while (in_idf(c));
id_buf[--id_size] = '\0'; *--idp = '\0';
if (n = find_name(id_buf, formals)) {
/* construct the formal parameter mark */
if (pos+1 >= text_size)
text = Srealloc(text,
text_size <<= 1);
text[pos++] = FORMALP | (char) n;
}
else {
register char *ptr = &id_buf[0];
while (pos + id_size >= text_size) /* construct the formal parameter mark or identifier */
text_size <<= 1; if (n = find_name(id_buf, formals))
text = Realloc(text, text_size); add2repl(repl, FORMALP | (char) n);
while (text[pos++] = *ptr++)
/* EMPTY */ ;
pos--;
}
}
else { else {
if (pos+1 >= text_size) idp = id_buf;
text = Realloc(text, text_size <<= 1); while (*idp) add2repl(repl, *idp++);
text[pos++] = c; }
} else if (class(c) == STNUM) {
add2repl(repl, c);
if (c == '.') {
c = GetChar();
if (class(c) != STNUM) {
blank = 0; continue;
}
add2repl(repl, c);
}
c = GetChar();
while(in_idf(c) || c == '.') {
add2repl(repl, c);
if((c = GetChar()) == 'e' || c == 'E') {
add2repl(repl, c);
c = GetChar();
if (c == '+' || c == '-') {
add2repl(repl, c);
c = GetChar(); c = GetChar();
} }
} }
text[pos++] = '\0';
text = Realloc(text, pos);
*length = pos - 1;
return text;
} }
} else {
#define BLANK(ch) ((ch == ' ') || (ch == '\t')) add2repl(repl, c);
c = GetChar();
}
blank = 0;
}
*length = repl->r_ptr - repl->r_text;
return Realloc(repl->r_text, repl->r_ptr - repl->r_text + 1);
}
/* macroeq() decides whether two macro replacement texts are /* macroeq() decides whether two macro replacement texts are
identical. This version compares the texts, which occur identical. This version compares the texts, which occur
@ -739,9 +749,10 @@ do_line(l)
unsigned int l; unsigned int l;
{ {
struct token tk; struct token tk;
int t = GetToken(&tk);
LineNumber = l - 1; /* the number of the next input line */ SkipToNewLine();
if (GetToken(&tk) == STRING) /* is there a filespecifier? */ LineNumber = l; /* the number of the next input line */
if (t == STRING) /* is there a filespecifier? */
FileName = tk.tk_str; FileName = tk.tk_str;
SkipToNewLine(0);
} }

View file

@ -28,6 +28,9 @@ Xflush()
sys_write(STDOUT, _obuf, OBUFSIZE); sys_write(STDOUT, _obuf, OBUFSIZE);
} }
static char *SkipComment();
extern char options[];
preprocess(fn) preprocess(fn)
char *fn; char *fn;
{ {
@ -36,7 +39,7 @@ preprocess(fn)
register char *ob = &_obuf[OBUFSIZE]; register char *ob = &_obuf[OBUFSIZE];
char Xbuf[256]; char Xbuf[256];
int lineno = 0; int lineno = 0;
extern char options[]; int startline;
#define flush(X) (sys_write(STDOUT,_obuf,X)) #define flush(X) (sys_write(STDOUT,_obuf,X))
#define echo(ch) if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch); #define echo(ch) if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
@ -75,13 +78,30 @@ preprocess(fn)
for (;;) { for (;;) {
LineNumber++; LineNumber++;
lineno++; lineno++;
startline = 1;
c = GetChar(); c = GetChar();
while (class(c) == STSKIP) { while (startline) {
while (class(c) == STSKIP || c == '/') {
if (c == '/') {
if (!InputLevel) {
c = GetChar();
if (c == '*') {
op = SkipComment(op, &lineno);
if (!op) return;
if (!options['C']) echo(' ');
c = GetChar();
continue;
}
UnGetChar();
c = '/';
}
break;
}
echo(c); echo(c);
c = GetChar(); c = GetChar();
} }
while (c == '#') { if (c == '#') {
if (!domacro()) { /* pass pragma's to compiler */ if (!domacro()) { /* pass pragma's to compiler */
register char *p = "#pragma"; register char *p = "#pragma";
@ -98,10 +118,7 @@ preprocess(fn)
lineno++; lineno++;
newline(); newline();
c = GetChar(); c = GetChar();
while (class(c) == STSKIP) { } else startline = 0;
echo(c);
c = GetChar();
}
} }
do_line(lineno, fn); do_line(lineno, fn);
for (;;) { for (;;) {
@ -120,43 +137,9 @@ preprocess(fn)
if (c == '/' && !InputLevel) { if (c == '/' && !InputLevel) {
c = GetChar(); c = GetChar();
if (c == '*') { if (c == '*') {
NoUnstack++; op = SkipComment(op, &lineno);
if (options['C']) { if (!op) return;
echo('/'); if (!options['C']) echo(' ');
echo('*');
}
for (;;) {
c = GetChar();
if (c == '\n') {
++LineNumber;
++lineno;
echo(c);
}
else if (c == EOI) {
newline();
flush(op - _obuf);
return;
}
else if (c == '*') {
if (options['C']) {
echo(c);
}
c = GetChar();
if (c == '/') {
if (options['C']) {
echo(c);
}
break;
}
else {
UnGetChar();
}
}
else if (options['C']) {
echo(c);
}
}
NoUnstack--;
c = GetChar(); c = GetChar();
continue; continue;
} }
@ -329,3 +312,48 @@ preprocess(fn)
} }
/*NOTREACHED*/ /*NOTREACHED*/
} }
static char *
SkipComment(op, lineno)
char *op;
int *lineno;
{
char *ob = &_obuf[OBUFSIZE];
register int c;
NoUnstack++;
if (options['C']) {
echo('/');
echo('*');
}
c = GetChar();
for(;;) {
if (c == EOI) {
newline();
flush(op - _obuf);
op = 0;
break;
}
if (options['C']) {
echo(c);
}
if (c == '\n') {
++LineNumber;
++*lineno;
if (!options['C']) {
echo(c);
}
}
if (c == '*') {
c = GetChar();
if (c == '/') {
if (options['C']) {
echo(c);
}
break; /* for(;;) */
}
} else c = GetChar();
}
NoUnstack--;
return op;
}

View file

@ -18,8 +18,7 @@
#include "LLlex.h" #include "LLlex.h"
#include "class.h" #include "class.h"
#include <assert.h> #include <assert.h>
#include "lapbuf.h" #include "macbuf.h"
#include "argbuf.h"
#include "replace.h" #include "replace.h"
extern char *GetIdentifier(); extern char *GetIdentifier();
@ -40,7 +39,7 @@ replace(idf)
if (idf->id_macro->mc_flag & NOREPLACE) if (idf->id_macro->mc_flag & NOREPLACE)
return 0; return 0;
repl = new_repl(); repl = new_repl();
repl->r_ptr = repl->r_text; repl->r_ptr = repl->r_text = Malloc(repl->r_size = LAPBUF);
repl->r_args = new_args(); repl->r_args = new_args();
repl->r_idf = idf; repl->r_idf = idf;
if (!expand_macro(repl, idf)) if (!expand_macro(repl, idf))
@ -59,6 +58,25 @@ unstackrepl()
Unstacked++; Unstacked++;
} }
freeargs(args)
struct args *args;
{
register int i;
/* We must don't know how many parameters were specified, so be
* prepared to free all NPARAMS parameters.
* When an expvec is !0, the rawvec will also be !0.
* When an expvec is 0, all remaining vectors will also be 0.
*/
for (i = 0; i < NPARAMS; i++) {
if (args->a_expvec[i]) {
free(args->a_expvec[i]);
free(args->a_rawvec[i]);
} else break;
}
free_args(args);
}
EnableMacros() EnableMacros()
{ {
register struct repl *r = ReplaceList, *prev = 0; register struct repl *r = ReplaceList, *prev = 0;
@ -71,7 +89,8 @@ EnableMacros()
r->r_idf->id_macro->mc_flag &= ~NOREPLACE; r->r_idf->id_macro->mc_flag &= ~NOREPLACE;
if (!prev) ReplaceList = nxt; if (!prev) ReplaceList = nxt;
else prev->next = nxt; else prev->next = nxt;
free_args(r->r_args); free(r->r_text);
freeargs(r->r_args);
free_repl(r); free_repl(r);
} }
else prev = r; else prev = r;
@ -136,15 +155,10 @@ expand_macro(repl, idf)
a+b; --> + + b ; a+b; --> + + b ;
'a' must be substituded, but the result should be 'a' must be substituded, but the result should be
three tokens: + + ID. Because this preprocessor is three tokens: + + ID. Therefore a token separator is
character based, we have a problem. inserted after the replacement.
For now: just insert a space after all tokens,
until ANSI fixes this flaw.
^^^^^^^^^^^^^^^^^^^^^^^^^^ tsk tsk tsk
*/ */
if (*repl->r_ptr != TOKSEP) *repl->r_ptr++ = TOKSEP; if (*(repl->r_ptr -1) != TOKSEP) add2repl(repl, TOKSEP);
*repl->r_ptr = '\0';
return 1; return 1;
} }
@ -167,8 +181,7 @@ expand_defined(repl)
error("identifier missing"); error("identifier missing");
if (parens && ch != ')') error(") missing"); if (parens && ch != ')') error(") missing");
if (!parens || ch != ')') UnGetChar(); if (!parens || ch != ')') UnGetChar();
*repl->r_ptr++ = '0'; add2repl(repl,'0');
*repl->r_ptr = '\0';
return; return;
} }
UnGetChar(); UnGetChar();
@ -181,8 +194,14 @@ expand_defined(repl)
ch = skipspaces(ch, 0); ch = skipspaces(ch, 0);
if (parens && ch != ')') error(") missing"); if (parens && ch != ')') error(") missing");
if (!parens || ch != ')') UnGetChar(); if (!parens || ch != ')') UnGetChar();
*repl->r_ptr++ = (id && id->id_macro) ? '1' : '0'; add2repl(repl, (id && id->id_macro) ? '1' : '0');
*repl->r_ptr = '\0'; }
newarg(args)
struct args *args;
{
args->a_expptr = args->a_expbuf = Malloc(args->a_expsize = ARGBUF);
args->a_rawptr = args->a_rawbuf = Malloc(args->a_rawsize = ARGBUF);
} }
getactuals(repl, idf) getactuals(repl, idf)
@ -199,8 +218,7 @@ getactuals(repl, idf)
register int ch; register int ch;
argcnt = 0; argcnt = 0;
args->a_expvec[0] = args->a_expptr = &args->a_expbuf[0]; newarg(args);
args->a_rawvec[0] = args->a_rawptr = &args->a_rawbuf[0];
if ((ch = GetChar()) != ')') { if ((ch = GetChar()) != ')') {
UnGetChar(); UnGetChar();
while ((ch = actual(repl)) != ')' ) { while ((ch = actual(repl)) != ')' ) {
@ -209,15 +227,18 @@ getactuals(repl, idf)
return; return;
} }
stash(repl, '\0', 1); stash(repl, '\0', 1);
args->a_expvec[argcnt] = args->a_expbuf;
args->a_rawvec[argcnt] = args->a_rawbuf;
++argcnt; ++argcnt;
args->a_expvec[argcnt] = args->a_expptr;
args->a_rawvec[argcnt] = args->a_rawptr;
if (argcnt == STDC_NPARAMS) if (argcnt == STDC_NPARAMS)
strict("number of parameters exceeds ANSI standard"); strict("number of parameters exceeds ANSI standard");
if (argcnt >= NPARAMS) if (argcnt >= NPARAMS)
fatal("argument vector overflow"); fatal("argument vector overflow");
newarg(args);
} }
stash(repl, '\0', 1); stash(repl, '\0', 1);
args->a_expvec[argcnt] = args->a_expbuf;
args->a_rawvec[argcnt] = args->a_rawbuf;
++argcnt; ++argcnt;
} }
if (argcnt < nps) if (argcnt < nps)
@ -236,7 +257,7 @@ struct repl *repl;
/* stash identifier name */ /* stash identifier name */
for (p = nrepl->r_idf->id_text; *p != '\0'; p++) for (p = nrepl->r_idf->id_text; *p != '\0'; p++)
*args->a_rawptr++ = *p; stash(repl, *p, -1);
/* The following code deals with expanded function /* The following code deals with expanded function
like macro calls. It makes the following code like macro calls. It makes the following code
@ -258,8 +279,8 @@ struct repl *repl;
*args->a_rawptr++ = '('; *args->a_rawptr++ = '(';
for (i = 0; ap->a_rawvec[i] != (char *)0; i++) { for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
for (p = ap->a_rawvec[i]; *p != '\0'; p++) for (p = ap->a_rawvec[i]; *p != '\0'; p++)
*args->a_rawptr++ = *p; stash(repl, *p, -1);
*args->a_rawptr++ = ','; stash(repl, ',', -1);
} }
*(args->a_rawptr-1) = ')'; /* delete last ',' */ *(args->a_rawptr-1) = ')'; /* delete last ',' */
} }
@ -373,27 +394,44 @@ actual(repl)
} else if (ch == '\n') { } else if (ch == '\n') {
/* newlines are accepted as white spaces */ /* newlines are accepted as white spaces */
LineNumber++; LineNumber++;
while ((ch = GetChar()), class(ch) == STSKIP)
/* EMPTY */;
/* This piece of code needs some explanation: /* This piece of code needs some explanation:
consider the call of a macro defined as: consider the call of a macro defined as:
#define sum(a,b) (a+b) #define sum(a,b) (a+b)
in the following form: in the following form:
sum( sum(
#include phone_number /_* comment *_/ #include phone_number
,2); ,2);
in which case the include must be handled in which case the include must be handled
interpreted as such. interpreted as such.
*/ */
ch = GetChar();
while (class(ch) == STSKIP || ch == '/') {
if (ch == '/') {
if ((ch = GetChar()) == '*' && !InputLevel) {
skipcomment();
stash(repl, ' ', !nostashraw);
ch = GetChar();
continue;
} else {
UnGetChar();
ch = '/';
}
stash(repl, '/', !nostashraw);
break;
} else ch = GetChar();
}
if (ch == '#') if (ch == '#')
domacro(); domacro();
else if (ch == EOI) { else if (ch == EOI) {
error("unterminated macro call"); error("unterminated macro call");
return ')'; return ')';
} }
if (ch != '/') {
UnGetChar(); UnGetChar();
stash(repl, ' ', !nostashraw); stash(repl, ' ', !nostashraw);
}
} else if (ch == '/') { } else if (ch == '/') {
/* comments are treated as one white space token */ /* comments are treated as one white space token */
if ((ch = GetChar()) == '*' && !InputLevel) { if ((ch = GetChar()) == '*' && !InputLevel) {
@ -496,53 +534,50 @@ macro2buffer(repl, idf, args)
smarter should be done (but even a DFA is O(|s|)). smarter should be done (but even a DFA is O(|s|)).
*/ */
register char *ptr = idf->id_macro->mc_text; register char *ptr = idf->id_macro->mc_text;
register char *tmpptr;
int err = 0; int err = 0;
char *stringify(); char *stringify();
while (*ptr) { while (*ptr) {
assert(repl->r_ptr < &(repl->r_text[LAPBUF]));
if (*ptr == '\'' || *ptr == '"') { if (*ptr == '\'' || *ptr == '"') {
register int delim = *ptr; register int delim = *ptr;
do { do {
*repl->r_ptr++ = *ptr; add2repl(repl, *ptr);
if (*ptr == '\\') if (*ptr == '\\')
*repl->r_ptr++ = *++ptr; add2repl(repl, *++ptr);
if (*ptr == '\0') { if (*ptr == '\0') {
error("unterminated string"); error("unterminated string");
*repl->r_ptr = '\0';
return; return;
} }
ptr++; ptr++;
} while (*ptr != delim || *ptr == '\0'); } while (*ptr != delim || *ptr == '\0');
*repl->r_ptr++ = *ptr++; add2repl(repl, *ptr++);
} else if (*ptr == '#') { } else if (*ptr == '#') {
if (*++ptr == '#') { if (*++ptr == '#') {
register int tmpindex;
/* ## - paste operator */ /* ## - paste operator */
ptr++; ptr++;
/* trim the actual replacement list */ /* trim the actual replacement list */
--repl->r_ptr; --repl->r_ptr;
while (is_wsp(*repl->r_ptr) while (repl->r_ptr >= repl->r_text
&& repl->r_ptr >= repl->r_text) && is_wsp(*repl->r_ptr))
--repl->r_ptr; --repl->r_ptr;
/* ## occurred at the beginning of the /* ## occurred at the beginning of the replacement list.
replacement list.
*/ */
if (repl->r_ptr == repl->r_text if (repl->r_ptr < repl->r_text) {
&& is_wsp(*repl->r_ptr)) {
err = 1; err = 1;
break; break;
} }
while(*repl->r_ptr == TOKSEP if (repl->r_ptr >= repl->r_text
&& repl->r_ptr >= repl->r_text) && *repl->r_ptr == TOKSEP);
--repl->r_ptr; --repl->r_ptr;
tmpptr = repl->r_ptr;
++repl->r_ptr; ++repl->r_ptr;
tmpindex = repl->r_ptr - repl->r_text;
/* tmpindex can be 0 */
/* skip space in macro replacement list */ /* skip space in macro replacement list */
while ((*ptr & FORMALP) == 0 && is_wsp(*ptr)) while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
@ -557,27 +592,29 @@ macro2buffer(repl, idf, args)
assert(n > 0); assert(n > 0);
p = args->a_rawvec[n-1]; p = args->a_rawvec[n-1];
if (p) { /* else macro argument missing */ if (p) { /* else macro argument missing */
while (is_wsp(*p)) while (is_wsp(*p)) p++;
p++;
if (*p == NOEXPM) p++; if (*p == NOEXPM) p++;
while (*p) while (*p)
*repl->r_ptr++ = *p++; add2repl(repl, *p++);
}
if (in_idf(*tmpptr + 1)) {
while (in_idf(*tmpptr)
&& tmpptr >= repl->r_text)
tmpptr--;
if (*tmpptr == NOEXPM) *tmpptr = TOKSEP;
} }
while (tmpindex > 0
&& in_idf(repl->r_text[tmpindex]))
tmpindex--;
if (tmpindex >= 0
&& repl->r_text[tmpindex] == NOEXPM)
repl->r_text[tmpindex] = TOKSEP;
} else if (*ptr == '\0') { } else if (*ptr == '\0') {
err = 1; err = 1;
break; break;
} else { } else {
if (in_idf(*ptr)) { if (in_idf(*ptr)) {
while (in_idf(*tmpptr) tmpindex--;
&& tmpptr >= repl->r_text) while (tmpindex > 0
tmpptr--; && in_idf(repl->r_text[tmpindex]))
if (*tmpptr == NOEXPM) *tmpptr = TOKSEP; tmpindex--;
if (tmpindex >= 0
&& repl->r_text[tmpindex] == NOEXPM)
repl->r_text[tmpindex] = TOKSEP;
} }
} }
} else /* # operator */ } else /* # operator */
@ -601,17 +638,15 @@ macro2buffer(repl, idf, args)
else else
q = args->a_expvec[n-1]; q = args->a_expvec[n-1];
p = repl->r_ptr;
if (q) /* else macro argument missing */ if (q) /* else macro argument missing */
while (*q) while (*q)
*repl->r_ptr++ = *q++; add2repl(repl, *q++);
if (*repl->r_ptr != TOKSEP) if (*(repl->r_ptr-1) != TOKSEP)
*repl->r_ptr++ = TOKSEP; add2repl(repl, TOKSEP);
} else } else
*repl->r_ptr++ = *ptr++; add2repl(repl, *ptr++);
} }
*repl->r_ptr = '\0';
if (err) if (err)
error("illegal use of ## operator"); error("illegal use of ## operator");
} }
@ -648,12 +683,12 @@ stringify(repl, ptr, args)
assert(n != 0); assert(n != 0);
p = args->a_rawvec[n-1]; p = args->a_rawvec[n-1];
*repl->r_ptr++ = '"'; add2repl(repl, '"');
while (*p) { while (*p) {
if (is_wsp(*p)) { if (is_wsp(*p)) {
if (!space) { if (!space) {
space = 1; space = 1;
*repl->r_ptr++ = ' '; add2repl(repl, ' ');
} }
p++; p++;
continue; continue;
@ -666,22 +701,41 @@ stringify(repl, ptr, args)
delim = 0; delim = 0;
backslash = *p == '\\'; backslash = *p == '\\';
if (*p == '"' || (delim && *p == '\\')) if (*p == '"' || (delim && *p == '\\'))
*repl->r_ptr++ = '\\'; add2repl(repl, '\\');
if (*p == TOKSEP || *p == NOEXPM) p++; if (*p == TOKSEP || *p == NOEXPM) p++;
else *repl->r_ptr++ = *p++; else add2repl(repl, *p++);
} }
/* trim spaces in the replacement list */ /* trim spaces in the replacement list */
for (--repl->r_ptr; is_wsp(*repl->r_ptr); repl->r_ptr--) for (--repl->r_ptr; is_wsp(*repl->r_ptr); repl->r_ptr--)
/* EMPTY */; /* EMPTY */;
*++repl->r_ptr = '"';
++repl->r_ptr; /* oops, one to far */ ++repl->r_ptr; /* oops, one to far */
add2repl(repl, '"');
} else } else
error("illegal use of # operator"); error("illegal use of # operator");
*repl->r_ptr = '\0';
return ptr; return ptr;
} }
/* The following routine is also called from domacro.c.
*/
add2repl(repl, ch)
register struct repl *repl;
int ch;
{
register int index = repl->r_ptr - repl->r_text;
if (index + 1 >= repl->r_size) {
repl->r_text = Realloc(repl->r_text, repl->r_size <<= 1);
repl->r_ptr = repl->r_text + index;
}
*repl->r_ptr++ = ch;
*repl->r_ptr = '\0';
}
/* If the variable stashraw is negative, we must only stash into the raw
* buffer. If the variable is zero, we must only stash into the expanded
* buffer. Otherwise, we must use both buffers.
*/
stash(repl, ch, stashraw) stash(repl, ch, stashraw)
struct repl *repl; struct repl *repl;
register int ch; register int ch;
@ -690,14 +744,24 @@ stash(repl, ch, stashraw)
/* Stash characters into the macro expansion buffer. /* Stash characters into the macro expansion buffer.
*/ */
register struct args *args = repl->r_args; register struct args *args = repl->r_args;
register int index = args->a_expptr - args->a_expbuf;
if (args->a_expptr >= &(args->a_expbuf[ARGBUF])) if (stashraw >= 0) {
fatal("macro argument buffer overflow"); if (index + 1 >= args->a_expsize) {
args->a_expbuf = Realloc(args->a_expbuf,
args->a_expsize <<= 1);
args->a_expptr = args->a_expbuf + index;
}
*args->a_expptr++ = ch; *args->a_expptr++ = ch;
}
if (stashraw) { if (stashraw) {
if (args->a_rawptr >= &(args->a_rawbuf[ARGBUF])) index = args->a_rawptr - args->a_rawbuf;
fatal("raw macro argument buffer overflow"); if (index + 1 >= args->a_rawsize) {
args->a_rawbuf = Realloc(args->a_rawbuf,
args->a_rawsize <<= 1);
args->a_rawptr = args->a_rawbuf + index;
}
*args->a_rawptr++ = ch; *args->a_rawptr++ = ch;
} }
} }

View file

@ -10,8 +10,9 @@ struct repl {
struct idf *r_idf; /* name of the macro */ struct idf *r_idf; /* name of the macro */
struct args *r_args; /* replacement parameters */ struct args *r_args; /* replacement parameters */
int r_level; /* level of insertion */ int r_level; /* level of insertion */
char *r_ptr; /* replacement text pointer */ int r_size; /* current size of replacement buffer */
char r_text[LAPBUF]; /* replacement text */ char *r_ptr; /* replacement text index pointer */
char *r_text; /* replacement text */
}; };
/* ALLOCDEF "repl" 4 */ /* ALLOCDEF "repl" 4 */
@ -34,15 +35,16 @@ struct repl {
operator, and an expanded one as argument for h(). operator, and an expanded one as argument for h().
*/ */
struct args { struct args {
char *a_expptr; /* expanded argument pointer */ char *a_expptr; /* expanded argument index pointer */
char *a_expbuf; /* expanded argument buffer pointer */
int a_expsize; /* current size of expanded buffer */
char *a_expvec[NPARAMS]; /* expanded argument vector */ char *a_expvec[NPARAMS]; /* expanded argument vector */
char a_expbuf[ARGBUF]; /* expanded argument buffer space */ char *a_rawptr; /* raw argument index pointer */
char *a_rawptr; /* raw argument pointer */ char *a_rawbuf; /* raw argument buffer pointer */
int a_rawsize; /* current size of raw buffer */
char *a_rawvec[NPARAMS]; /* raw argument vector */ char *a_rawvec[NPARAMS]; /* raw argument vector */
char a_rawbuf[ARGBUF]; /* raw argument buffer space */
}; };
/* ALLOCDEF "args" 2 */ /* ALLOCDEF "args" 2 */
#define NO_ARGS (struct args *)0 #define NO_ARGS (struct args *)0

View file

@ -56,11 +56,10 @@ skipspaces(ch, skipnl)
} }
} }
SkipToNewLine(garbage) SkipToNewLine()
int garbage;
{ {
register int ch; register int ch;
register int pstrict = 0; register int garbage = 0;
while ((ch = GetChar()) != '\n') { while ((ch = GetChar()) != '\n') {
if (ch == '/') { if (ch == '/') {
@ -69,9 +68,9 @@ SkipToNewLine(garbage)
continue; continue;
} }
} }
if (garbage && !is_wsp(ch)) if (!is_wsp(ch))
pstrict = 1; garbage = 1;
} }
++LineNumber; ++LineNumber;
return pstrict; return garbage;
} }