Selaa lähdekoodia

fixed bugs, added dynamic buffer allocation

eck 35 vuotta sitten
vanhempi
commit
a1b292bb31

+ 1 - 1
lang/cem/cpp.ansi/LLmessage.c

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

+ 3 - 4
lang/cem/cpp.ansi/Makefile

@@ -65,8 +65,8 @@ STRSRC = macro.str replace.str
 GSTRSRC = macro.h replace.h
 
 # .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
-GHSRC =	errout.h idfsize.h ifdepth.h lapbuf.h \
-	nparams.h numsize.h obufsize.h argbuf.h \
+GHSRC =	errout.h idfsize.h ifdepth.h macbuf.h \
+	nparams.h numsize.h obufsize.h \
 	parbufsize.h pathlength.h strsize.h textsize.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: obufsize.h
 replace.o: LLlex.h
-replace.o: argbuf.h
 replace.o: class.h
 replace.o: file_info.h
 replace.o: idf.h
 replace.o: idfsize.h
 replace.o: input.h
 replace.o: inputtype.h
-replace.o: lapbuf.h
+replace.o: macbuf.h
 replace.o: macro.h
 replace.o: nparams.h
 replace.o: numsize.h

+ 3 - 6
lang/cem/cpp.ansi/Parameters

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

+ 110 - 99
lang/cem/cpp.ansi/domacro.c

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

+ 82 - 54
lang/cem/cpp.ansi/preprocess.c

@@ -28,6 +28,9 @@ Xflush()
 	sys_write(STDOUT, _obuf, OBUFSIZE);
 }
 
+static char *SkipComment();
+extern char options[];
+
 preprocess(fn)
 	char *fn;
 {
@@ -36,7 +39,7 @@ preprocess(fn)
 	register char *ob = &_obuf[OBUFSIZE];
 	char Xbuf[256];
 	int lineno = 0;
-	extern char options[];
+	int startline;
 
 #define flush(X)	(sys_write(STDOUT,_obuf,X))
 #define echo(ch) 	if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
@@ -75,33 +78,47 @@ preprocess(fn)
 	for (;;) {
 		LineNumber++;
 		lineno++;
+		startline = 1;
 		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);
 			c = GetChar();
-		}
+		    }
 
-		while (c == '#') {
+		    if (c == '#') {
 			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) {
-					echo(*p++);
-				}
-				while ((c = GetChar()) != EOI) {
-					if (class(c) == STNL) break;
-					echo(c);
-				}
+			    while(*p) {
+				echo(*p++);
+			    }
+			    while ((c = GetChar()) != EOI) {
+				if (class(c) == STNL) break;
+				echo(c);
+			    }
 			}
 			lineno++;
 			newline();
 			c = GetChar();
-			while (class(c) == STSKIP) {
-				echo(c);
-				c = GetChar();
-			}
+		    } else startline = 0;
 		}
 		do_line(lineno, fn);
 		for (;;) {
@@ -120,43 +137,9 @@ preprocess(fn)
 			if (c == '/' && !InputLevel) {
 				c = GetChar();
 				if (c == '*') {
-					NoUnstack++;
-					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--;
+					op = SkipComment(op, &lineno);
+					if (!op) return;
+					if (!options['C']) echo(' ');
 					c = GetChar();
 					continue;
 				}
@@ -329,3 +312,48 @@ preprocess(fn)
 	}
 	/*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;
+}

+ 148 - 84
lang/cem/cpp.ansi/replace.c

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

+ 9 - 7
lang/cem/cpp.ansi/replace.str

@@ -10,8 +10,9 @@ struct repl {
 	struct	idf *r_idf;		/* name of the macro */
 	struct	args *r_args;		/* replacement parameters */
 	int	r_level;		/* level of insertion */
-	char	*r_ptr;			/* replacement text pointer */
-	char	r_text[LAPBUF];		/* replacement text */
+	int	r_size;			/* current size of replacement buffer */
+	char	*r_ptr;			/* replacement text index pointer */
+	char	*r_text;		/* replacement text */
 };
 
 /* ALLOCDEF "repl" 4 */
@@ -34,15 +35,16 @@ struct repl {
 	operator, and an expanded one as argument for h().
 */
 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_expbuf[ARGBUF];	/* expanded argument buffer space */
-	char	*a_rawptr;		/* raw argument pointer */
+	char	*a_rawptr;		/* raw argument index 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_rawbuf[ARGBUF];	/* raw argument buffer space */
 };
 
 /* ALLOCDEF "args" 2 */
 
 #define NO_ARGS		(struct args *)0
-

+ 5 - 6
lang/cem/cpp.ansi/skip.c

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