fixed bugs, added dynamic buffer allocation
This commit is contained in:
parent
5ffd738802
commit
f9fadbf045
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)){
|
||||||
|
@ -326,12 +333,12 @@ do_define()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* there is a formal parameter list if the identifier is
|
/* there is a formal parameter list if the identifier is
|
||||||
followed immediately by a '('.
|
followed immediately by a '('.
|
||||||
*/
|
*/
|
||||||
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) {
|
UnGetChar();
|
||||||
/* Treat `#define something' as `#define something ""'
|
repl_text = get_text((nformals > 0) ? formals : 0, &length);
|
||||||
*/
|
|
||||||
repl_text = Malloc(1);
|
|
||||||
*repl_text = '\0';
|
|
||||||
length = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
UnGetChar();
|
|
||||||
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[];
|
||||||
|
@ -614,101 +614,111 @@ get_text(formals, length)
|
||||||
substituting each formal parameter by a special character
|
substituting each formal parameter by a special character
|
||||||
(non-ascii: 0200 & (order-number in the formal parameter
|
(non-ascii: 0200 & (order-number in the formal parameter
|
||||||
list)) in order to substitute this character later by the
|
list)) in order to substitute this character later by the
|
||||||
actual parameter. The replacement text is copied into
|
actual parameter. The replacement text is copied into
|
||||||
itself because the copied text will contain fewer or the
|
itself because the copied text will contain fewer or the
|
||||||
same amount of characters. The length of the replacement
|
same amount of characters. The length of the replacement
|
||||||
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++)
|
else {
|
||||||
/* EMPTY */ ;
|
idp = id_buf;
|
||||||
pos--;
|
while (*idp) add2repl(repl, *idp++);
|
||||||
}
|
}
|
||||||
}
|
} else if (class(c) == STNUM) {
|
||||||
else {
|
add2repl(repl, c);
|
||||||
if (pos+1 >= text_size)
|
if (c == '.') {
|
||||||
text = Realloc(text, text_size <<= 1);
|
c = GetChar();
|
||||||
text[pos++] = c;
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
add2repl(repl, c);
|
||||||
c = GetChar();
|
c = GetChar();
|
||||||
}
|
}
|
||||||
|
blank = 0;
|
||||||
}
|
}
|
||||||
text[pos++] = '\0';
|
*length = repl->r_ptr - repl->r_text;
|
||||||
text = Realloc(text, pos);
|
return Realloc(repl->r_text, repl->r_ptr - repl->r_text + 1);
|
||||||
*length = pos - 1;
|
|
||||||
return text;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
||||||
blanks (spaces and tabs).
|
blanks (spaces and tabs).
|
||||||
*/
|
*/
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,33 +78,47 @@ 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";
|
||||||
|
|
||||||
do_line(lineno, fn);
|
do_line(lineno, fn);
|
||||||
|
|
||||||
while(*p) {
|
while(*p) {
|
||||||
echo(*p++);
|
echo(*p++);
|
||||||
}
|
}
|
||||||
while ((c = GetChar()) != EOI) {
|
while ((c = GetChar()) != EOI) {
|
||||||
if (class(c) == STNL) break;
|
if (class(c) == STNL) break;
|
||||||
echo(c);
|
echo(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 ')';
|
||||||
}
|
}
|
||||||
UnGetChar();
|
if (ch != '/') {
|
||||||
stash(repl, ' ', !nostashraw);
|
UnGetChar();
|
||||||
|
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,38 +701,67 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
stash(repl, ch, stashraw)
|
/* The following routine is also called from domacro.c.
|
||||||
struct repl *repl;
|
*/
|
||||||
register int ch;
|
add2repl(repl, ch)
|
||||||
int stashraw;
|
register struct repl *repl;
|
||||||
|
int ch;
|
||||||
{
|
{
|
||||||
/* Stash characters into the macro expansion buffer.
|
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)
|
||||||
|
struct repl *repl;
|
||||||
|
register int ch;
|
||||||
|
int stashraw;
|
||||||
|
{
|
||||||
|
/* 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]))
|
|
||||||
fatal("macro argument buffer overflow");
|
if (stashraw >= 0) {
|
||||||
*args->a_expptr++ = ch;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue