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,93 +620,103 @@ 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); } else {
*length = pos - 1; add2repl(repl, c);
return text; c = GetChar();
}
blank = 0;
}
*length = repl->r_ptr - repl->r_text;
return Realloc(repl->r_text, repl->r_ptr - repl->r_text + 1);
} }
#define BLANK(ch) ((ch == ' ') || (ch == '\t'))
/* 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
as strings, without taking care of the leading and trailing as strings, without taking care of the leading and trailing
@ -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;
} }