Merge from default.
This commit is contained in:
		
						commit
						ee328a0572
					
				
					 28 changed files with 2054 additions and 4025 deletions
				
			
		
							
								
								
									
										15
									
								
								.drone.yml
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								.drone.yml
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
clone:
 | 
			
		||||
    depth: 10
 | 
			
		||||
build:
 | 
			
		||||
        image: teaci/msys32
 | 
			
		||||
        pull: true
 | 
			
		||||
        shell: $$arch
 | 
			
		||||
        commands:
 | 
			
		||||
          - if [ $$arch = sh ]; then apt update; apt install build-essential bison flex; fi
 | 
			
		||||
          - make PREFIX=/tmp/acki +ack
 | 
			
		||||
 | 
			
		||||
matrix:
 | 
			
		||||
    arch:
 | 
			
		||||
      - sh
 | 
			
		||||
      #- msys32
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										4
									
								
								Makefile
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -15,8 +15,8 @@ ACK_TEMP_DIR = /tmp
 | 
			
		|||
# install it and just want to run the ACK from the build directory
 | 
			
		||||
# (/tmp/ack-build/staging, by default), leave this as $(INSDIR).
 | 
			
		||||
 | 
			
		||||
#PREFIX = /usr/local
 | 
			
		||||
PREFIX = $(INSDIR)
 | 
			
		||||
PREFIX = /usr/local
 | 
			
		||||
#PREFIX = $(INSDIR)
 | 
			
		||||
 | 
			
		||||
# Where do you want to put the object files used when building?
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,10 +111,6 @@
 | 
			
		|||
#define INP_READ_IN_ONE	1	/* read input file in one	*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
!File: nopp.h
 | 
			
		||||
/*#define NOPP		1	/* if NOT defined, use built-int preprocessor */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
!File: nobitfield.h
 | 
			
		||||
/*#define NOBITFIELD	1	/* if NOT defined, implement bitfields	*/
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -43,12 +43,6 @@ extern struct token dot, ahead, aside;
 | 
			
		|||
extern int token_nmb;			/* number of the ahead token */
 | 
			
		||||
extern int tk_nmb_at_last_syn_err;	/* token number at last syntax error */
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
extern int ReplaceMacros;	/* "LLlex.c"	*/
 | 
			
		||||
extern int AccDefined;		/* "LLlex.c"	*/
 | 
			
		||||
extern int Unstacked;		/* "LLlex.c"	*/
 | 
			
		||||
extern int UnknownIdIsZero;	/* "LLlex.c"	*/
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
extern int EoiForNewline;	/* "LLlex.c"	*/
 | 
			
		||||
extern int AccFileSpecifier;	/* "LLlex.c"	*/
 | 
			
		||||
extern int File_Inserted;	/* "LLlex.c"	*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,10 +111,6 @@
 | 
			
		|||
/*#define INP_READ_IN_ONE	1	/* read input file in one	*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
!File: nopp.h
 | 
			
		||||
#define NOPP		1	/* if NOT defined, use built-int preprocessor */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
!File: nobitfield.h
 | 
			
		||||
/*#define NOBITFIELD	1	/* if NOT defined, implement bitfields	*/
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,7 +111,6 @@ cprogram {
 | 
			
		|||
		"./field.c",
 | 
			
		||||
		"./fltcstoper.c",
 | 
			
		||||
		"./idf.c",
 | 
			
		||||
		"./init.c",
 | 
			
		||||
		"./input.c",
 | 
			
		||||
		"./l_comment.c",
 | 
			
		||||
		"./l_ev_ord.c",
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +123,6 @@ cprogram {
 | 
			
		|||
		"./options.c",
 | 
			
		||||
		"./pragma.c",
 | 
			
		||||
		"./proto.c",
 | 
			
		||||
		"./replace.c",
 | 
			
		||||
		"./skip.c",
 | 
			
		||||
		"./stab.c",
 | 
			
		||||
		"./stack.c",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,811 +5,41 @@
 | 
			
		|||
/* $Id$ */
 | 
			
		||||
/* PREPROCESSOR: CONTROLLINE INTERPRETER */
 | 
			
		||||
 | 
			
		||||
#include	<assert.h>
 | 
			
		||||
#include	<stdlib.h>
 | 
			
		||||
#include	<string.h>
 | 
			
		||||
#include	"parameters.h"
 | 
			
		||||
#include    "idf.h"
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"LLlex.h"
 | 
			
		||||
#include	"Lpars.h"
 | 
			
		||||
#include	"input.h"
 | 
			
		||||
#include    "replace.h"
 | 
			
		||||
#include <assert.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include "parameters.h"
 | 
			
		||||
#include "idf.h"
 | 
			
		||||
#include "arith.h"
 | 
			
		||||
#include "LLlex.h"
 | 
			
		||||
#include "Lpars.h"
 | 
			
		||||
#include "input.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include	"class.h"
 | 
			
		||||
#include	"macro.h"
 | 
			
		||||
#ifdef DBSYMTAB
 | 
			
		||||
#include	<stb.h>
 | 
			
		||||
#include	<em.h>
 | 
			
		||||
int		IncludeLevel = 0;
 | 
			
		||||
#include <stb.h>
 | 
			
		||||
#include <em.h>
 | 
			
		||||
int IncludeLevel = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern char options[];
 | 
			
		||||
extern	char **inctable;	/* list of include directories		*/
 | 
			
		||||
extern	char *getwdir();
 | 
			
		||||
char ifstack[IFDEPTH];	/* if-stack: the content of an entry is	*/
 | 
			
		||||
				/* 1 if a corresponding ELSE has been	*/
 | 
			
		||||
				/* encountered.				*/
 | 
			
		||||
 | 
			
		||||
int	nestlevel = -1;
 | 
			
		||||
 | 
			
		||||
void macro_def();
 | 
			
		||||
void do_define();
 | 
			
		||||
 | 
			
		||||
struct idf *
 | 
			
		||||
GetIdentifier(skiponerr)
 | 
			
		||||
	int skiponerr;		/* skip the rest of the line on error */
 | 
			
		||||
struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */
 | 
			
		||||
{
 | 
			
		||||
	/*	returns a pointer to the descriptor of the identifier that is
 | 
			
		||||
		read from the input stream. When the input doe not contain
 | 
			
		||||
		an identifier, the rest of the line is skipped when
 | 
			
		||||
		skiponerr is on, and a null-pointer is returned.
 | 
			
		||||
		The substitution of macros is disabled.
 | 
			
		||||
	*/
 | 
			
		||||
	int tmp = UnknownIdIsZero;
 | 
			
		||||
	int tok;
 | 
			
		||||
	struct token tk;
 | 
			
		||||
 | 
			
		||||
	UnknownIdIsZero = ReplaceMacros = 0;
 | 
			
		||||
	tok = GetToken(&tk);
 | 
			
		||||
	ReplaceMacros = 1;
 | 
			
		||||
	UnknownIdIsZero = tmp;
 | 
			
		||||
	if (tok != IDENTIFIER) {
 | 
			
		||||
		if (skiponerr && tok != EOI) SkipToNewLine();
 | 
			
		||||
		return (struct idf *)0;
 | 
			
		||||
	}
 | 
			
		||||
	return tk.tk_idf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*	domacro() is the control line interpreter. The '#' has already
 | 
			
		||||
	been read by the lexical analyzer by which domacro() is called.
 | 
			
		||||
	The token appearing directly after the '#' is obtained by calling
 | 
			
		||||
	the basic lexical analyzing function GetToken() and is interpreted
 | 
			
		||||
	to perform the action belonging to that token.
 | 
			
		||||
	An error message is produced when the token is not recognized,
 | 
			
		||||
	i.e. it is not one of "define" .. "undef" , integer or newline.
 | 
			
		||||
*/
 | 
			
		||||
domacro()
 | 
			
		||||
{
 | 
			
		||||
	struct token tk;	/* the token itself			*/
 | 
			
		||||
	int toknum;
 | 
			
		||||
 | 
			
		||||
	EoiForNewline = 1;
 | 
			
		||||
	ReplaceMacros = 0;
 | 
			
		||||
	toknum = GetToken(&tk);
 | 
			
		||||
	ReplaceMacros = 1;
 | 
			
		||||
	switch(toknum) {		/* select control line action	*/
 | 
			
		||||
	case IDENTIFIER:		/* is it a macro keyword?	*/
 | 
			
		||||
		switch (tk.tk_idf->id_resmac) {
 | 
			
		||||
		case K_DEFINE:				/* "define"	*/
 | 
			
		||||
			do_define();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ELIF:				/* "elif"	*/
 | 
			
		||||
			do_elif();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ELSE:				/* "else"	*/
 | 
			
		||||
			do_else();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ENDIF:				/* "endif"	*/
 | 
			
		||||
			do_endif();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_IF:				/* "if"		*/
 | 
			
		||||
			do_if();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_IFDEF:				/* "ifdef"	*/
 | 
			
		||||
			do_ifdef(1);
 | 
			
		||||
			break;
 | 
			
		||||
		case K_IFNDEF:				/* "ifndef"	*/
 | 
			
		||||
			do_ifdef(0);
 | 
			
		||||
			break;
 | 
			
		||||
		case K_INCLUDE:				/* "include"	*/
 | 
			
		||||
			do_include();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_LINE:				/* "line"	*/
 | 
			
		||||
			/*	set LineNumber and FileName according to
 | 
			
		||||
				the arguments.
 | 
			
		||||
			*/
 | 
			
		||||
			if (GetToken(&tk) != INTEGER) {
 | 
			
		||||
				lexerror("bad #line syntax");
 | 
			
		||||
				SkipToNewLine();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				do_line((unsigned int)tk.tk_ival);
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ERROR:				/* "error"	*/
 | 
			
		||||
			do_error();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_PRAGMA:				/* "pragma"	*/
 | 
			
		||||
			do_pragma();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_UNDEF:				/* "undef"	*/
 | 
			
		||||
			do_undef((struct idf *) 0);
 | 
			
		||||
			break;
 | 
			
		||||
		default:
 | 
			
		||||
			/* invalid word seen after the '#'	*/
 | 
			
		||||
			lexerror("%s: unknown control", tk.tk_idf->id_text);
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	case INTEGER:		/* # <integer> [<filespecifier>]?	*/
 | 
			
		||||
		do_line((unsigned int)tk.tk_ival);
 | 
			
		||||
		break;
 | 
			
		||||
	case EOI:	/* only `#' on this line: do nothing, ignore	*/
 | 
			
		||||
		break;
 | 
			
		||||
	default:	/* invalid token following '#'		*/
 | 
			
		||||
		lexerror("illegal # line");
 | 
			
		||||
		SkipToNewLine();
 | 
			
		||||
	}
 | 
			
		||||
	EoiForNewline = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef LINT
 | 
			
		||||
int lint_skip_comment;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
skip_block(to_endif)
 | 
			
		||||
int to_endif;
 | 
			
		||||
{
 | 
			
		||||
	/*	skip_block() skips the input from
 | 
			
		||||
		1)	a false #if, #ifdef, #ifndef or #elif until the
 | 
			
		||||
			corresponding #elif (resulting in true), #else or
 | 
			
		||||
			#endif is read.
 | 
			
		||||
		2)	a #else corresponding to a true #if, #ifdef,
 | 
			
		||||
			#ifndef or #elif until the corresponding #endif is
 | 
			
		||||
			seen.
 | 
			
		||||
	*/
 | 
			
		||||
	register int ch;
 | 
			
		||||
	register int skiplevel = nestlevel; /* current nesting level	*/
 | 
			
		||||
	struct token tk;
 | 
			
		||||
	int toknum;
 | 
			
		||||
 | 
			
		||||
#ifdef LINT
 | 
			
		||||
	lint_skip_comment++;
 | 
			
		||||
#endif
 | 
			
		||||
	NoUnstack++;
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		ch = GetChar();	/* read first character after newline	*/
 | 
			
		||||
		while (class(ch) == STSKIP)
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
		if (ch != '#') {
 | 
			
		||||
			if (ch == EOI) {
 | 
			
		||||
				NoUnstack--;
 | 
			
		||||
#ifdef LINT
 | 
			
		||||
				lint_skip_comment--;
 | 
			
		||||
#endif
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			/* A possible '/' is not pushed back */
 | 
			
		||||
			if (ch == '/') {
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
				if (ch != '*') UnGetChar();
 | 
			
		||||
				else {
 | 
			
		||||
					skipcomment();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			} else UnGetChar();
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		ReplaceMacros = 0;
 | 
			
		||||
		toknum = GetToken(&tk);
 | 
			
		||||
		ReplaceMacros = 1;
 | 
			
		||||
		if (toknum != IDENTIFIER) {
 | 
			
		||||
			if (toknum != INTEGER) {
 | 
			
		||||
				lexerror("illegal # line");
 | 
			
		||||
			}
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		/*	an IDENTIFIER: look for #if, #ifdef and #ifndef
 | 
			
		||||
			without interpreting them.
 | 
			
		||||
			Interpret #else, #elif and #endif if they occur
 | 
			
		||||
			on the same level.
 | 
			
		||||
		*/
 | 
			
		||||
		switch(tk.tk_idf->id_resmac) {
 | 
			
		||||
		default:
 | 
			
		||||
		case K_UNKNOWN:
 | 
			
		||||
			/* invalid word seen after the '#'      */
 | 
			
		||||
			lexwarning("%s: unknown control", tk.tk_idf->id_text);
 | 
			
		||||
			/* fallthrough */
 | 
			
		||||
		case K_DEFINE:
 | 
			
		||||
		case K_ERROR:
 | 
			
		||||
		case K_INCLUDE:
 | 
			
		||||
		case K_LINE:
 | 
			
		||||
		case K_PRAGMA:
 | 
			
		||||
		case K_UNDEF:
 | 
			
		||||
		case K_FILE:
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_IF:
 | 
			
		||||
		case K_IFDEF:
 | 
			
		||||
		case K_IFNDEF:
 | 
			
		||||
			push_if();
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ELIF:
 | 
			
		||||
			if (ifstack[nestlevel])
 | 
			
		||||
				lexerror("#elif after #else");
 | 
			
		||||
			if (!to_endif && nestlevel == skiplevel) {
 | 
			
		||||
				nestlevel--;
 | 
			
		||||
				push_if();
 | 
			
		||||
				if (ifexpr()) {
 | 
			
		||||
					NoUnstack--;
 | 
			
		||||
#ifdef LINT
 | 
			
		||||
					lint_skip_comment--;
 | 
			
		||||
#endif
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else SkipToNewLine();	/* otherwise done in ifexpr() */
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ELSE:
 | 
			
		||||
			if (ifstack[nestlevel])
 | 
			
		||||
				lexerror("#else after #else");
 | 
			
		||||
			++(ifstack[nestlevel]);
 | 
			
		||||
			if (!to_endif && nestlevel == skiplevel) {
 | 
			
		||||
				if (SkipToNewLine()) {
 | 
			
		||||
					if (!options['o'])
 | 
			
		||||
						lexstrict("garbage following #else");
 | 
			
		||||
				}
 | 
			
		||||
				NoUnstack--;
 | 
			
		||||
#ifdef LINT
 | 
			
		||||
				lint_skip_comment--;
 | 
			
		||||
#endif
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			else SkipToNewLine();
 | 
			
		||||
			break;
 | 
			
		||||
		case K_ENDIF:
 | 
			
		||||
			assert(nestlevel > nestlow);
 | 
			
		||||
			if (nestlevel == skiplevel) {
 | 
			
		||||
				if (SkipToNewLine()) {
 | 
			
		||||
					if (!options['o'])
 | 
			
		||||
						lexstrict("garbage following #endif");
 | 
			
		||||
				}
 | 
			
		||||
				nestlevel--;
 | 
			
		||||
				NoUnstack--;
 | 
			
		||||
#ifdef LINT
 | 
			
		||||
				lint_skip_comment--;
 | 
			
		||||
#endif
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			else SkipToNewLine();
 | 
			
		||||
			nestlevel--;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
ifexpr()
 | 
			
		||||
{
 | 
			
		||||
	/*	ifexpr() returns whether the restricted constant
 | 
			
		||||
		expression following #if or #elif evaluates to true.  This
 | 
			
		||||
		is done by calling the LLgen generated subparser for
 | 
			
		||||
		constant expressions.  The result of this expression will
 | 
			
		||||
		be given in the extern long variable "ifval".
 | 
			
		||||
	*/
 | 
			
		||||
	extern arith ifval;
 | 
			
		||||
	int errors = err_occurred;
 | 
			
		||||
 | 
			
		||||
	ifval = (arith)0;
 | 
			
		||||
	AccDefined = 1;
 | 
			
		||||
	UnknownIdIsZero = 1;
 | 
			
		||||
	PushLex();	/* NEW parser */
 | 
			
		||||
	If_expr();	/* invoke constant expression parser	*/
 | 
			
		||||
	PopLex();	/* OLD parser */
 | 
			
		||||
	AccDefined = 0;
 | 
			
		||||
	UnknownIdIsZero = 0;
 | 
			
		||||
	return (errors == err_occurred) && (ifval != (arith)0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_include()
 | 
			
		||||
{
 | 
			
		||||
	/*	do_include() performs the inclusion of a file.
 | 
			
		||||
	*/
 | 
			
		||||
	char *filenm;
 | 
			
		||||
	char *result;
 | 
			
		||||
	int tok;
 | 
			
		||||
	struct token tk;
 | 
			
		||||
 | 
			
		||||
	AccFileSpecifier = 1;
 | 
			
		||||
	if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
 | 
			
		||||
		filenm = tk.tk_bts;
 | 
			
		||||
	else {
 | 
			
		||||
		lexerror("bad include syntax");
 | 
			
		||||
		filenm = (char *)0;
 | 
			
		||||
	}
 | 
			
		||||
	AccFileSpecifier = 0;
 | 
			
		||||
	if (SkipToNewLine()) {
 | 
			
		||||
		lexerror("bad include syntax");
 | 
			
		||||
	}
 | 
			
		||||
	inctable[0] = WorkingDir;
 | 
			
		||||
	if (filenm) {
 | 
			
		||||
		if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
 | 
			
		||||
			lexerror("cannot open include file \"%s\"", filenm);
 | 
			
		||||
			add_dependency(filenm);
 | 
			
		||||
			free(filenm);
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			add_dependency(result);
 | 
			
		||||
			WorkingDir = getwdir(result);
 | 
			
		||||
			File_Inserted = 1;
 | 
			
		||||
			FileName = result;
 | 
			
		||||
			LineNumber = 0;
 | 
			
		||||
			nestlow = nestlevel;
 | 
			
		||||
#ifdef DBSYMTAB
 | 
			
		||||
			IncludeLevel++;
 | 
			
		||||
			if (options['g']) {
 | 
			
		||||
				C_ms_stb_cst(FileName, N_BINCL, 0, (arith) 0);
 | 
			
		||||
			}
 | 
			
		||||
#endif /* DBSYMTAB */
 | 
			
		||||
			if (result != filenm) free(filenm);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
do_define()
 | 
			
		||||
{
 | 
			
		||||
	/*	do_define() interprets a #define control line.
 | 
			
		||||
	*/
 | 
			
		||||
	struct idf *id;		/* the #defined identifier's descriptor	*/
 | 
			
		||||
	int nformals = -1;	/* keep track of the number of formals	*/
 | 
			
		||||
	char *formals[NPARAMS];	/* pointers to the names of the formals	*/
 | 
			
		||||
	char parbuf[PARBUFSIZE];		/* names of formals	*/
 | 
			
		||||
	char *repl_text;	/* start of the replacement text	*/
 | 
			
		||||
	int length;		/* length of the replacement text	*/
 | 
			
		||||
	register ch;
 | 
			
		||||
	char *get_text();
 | 
			
		||||
 | 
			
		||||
	/* read the #defined macro's name	*/
 | 
			
		||||
	if (!(id = GetIdentifier(1))) {
 | 
			
		||||
		lexerror("illegal #define line");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	/*	there is a formal parameter list if the identifier is
 | 
			
		||||
		followed immediately by a '('.
 | 
			
		||||
	*/
 | 
			
		||||
	ch = GetChar();
 | 
			
		||||
	if (ch == '(') {
 | 
			
		||||
		if ((nformals = getparams(formals, parbuf)) == -1) {
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
			return;	/* an error occurred	*/
 | 
			
		||||
		}
 | 
			
		||||
		ch = GetChar();
 | 
			
		||||
	}
 | 
			
		||||
	/* read the replacement text if there is any			*/
 | 
			
		||||
	ch = skipspaces(ch,0);	/* find first character of the text	*/
 | 
			
		||||
	assert(ch != EOI);
 | 
			
		||||
	/* UnGetChar() is not right when replacement starts with a '/' */
 | 
			
		||||
	ChPushBack(ch);
 | 
			
		||||
	repl_text = get_text((nformals > 0) ? formals : 0, &length);
 | 
			
		||||
	macro_def(id, repl_text, nformals, length, NOFLAG);
 | 
			
		||||
	LineNumber++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
push_if()
 | 
			
		||||
{
 | 
			
		||||
	if (nestlevel >= IFDEPTH)
 | 
			
		||||
		fatal("too many nested #if/#ifdef/#ifndef");
 | 
			
		||||
	else
 | 
			
		||||
		ifstack[++nestlevel] = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_elif()
 | 
			
		||||
{
 | 
			
		||||
	if (nestlevel <= nestlow) {
 | 
			
		||||
		lexerror("#elif without corresponding #if");
 | 
			
		||||
		SkipToNewLine();
 | 
			
		||||
	}
 | 
			
		||||
	else {		/* restart at this level as if a #if is detected.  */
 | 
			
		||||
		if (ifstack[nestlevel]) {
 | 
			
		||||
			lexerror("#elif after #else");
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
		}
 | 
			
		||||
		nestlevel--;
 | 
			
		||||
		push_if();
 | 
			
		||||
		skip_block(1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_else()
 | 
			
		||||
{
 | 
			
		||||
	if (SkipToNewLine())
 | 
			
		||||
		if (!options['o'])
 | 
			
		||||
			lexstrict("garbage following #else");
 | 
			
		||||
	if (nestlevel <= nestlow)
 | 
			
		||||
		lexerror("#else without corresponding #if");
 | 
			
		||||
	else {	/* mark this level as else-d */
 | 
			
		||||
		if (ifstack[nestlevel]) {
 | 
			
		||||
			lexerror("#else after #else");
 | 
			
		||||
		}
 | 
			
		||||
		++(ifstack[nestlevel]);
 | 
			
		||||
		skip_block(1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_endif()
 | 
			
		||||
{
 | 
			
		||||
	if (SkipToNewLine()) {
 | 
			
		||||
		if (!options['o'])
 | 
			
		||||
			lexstrict("garbage following #endif");
 | 
			
		||||
	}
 | 
			
		||||
	if (nestlevel <= nestlow)	{
 | 
			
		||||
		lexerror("#endif without corresponding #if");
 | 
			
		||||
	}
 | 
			
		||||
	else	nestlevel--;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_if()
 | 
			
		||||
{
 | 
			
		||||
	push_if();
 | 
			
		||||
	if (!ifexpr())	/* a false #if/#elif expression */
 | 
			
		||||
		skip_block(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_ifdef(how)
 | 
			
		||||
{
 | 
			
		||||
	register struct idf *id;
 | 
			
		||||
 | 
			
		||||
	/*	how == 1 : ifdef; how == 0 : ifndef
 | 
			
		||||
	*/
 | 
			
		||||
	push_if();
 | 
			
		||||
	if (!(id = GetIdentifier(1)))
 | 
			
		||||
		lexerror("illegal #ifdef construction");
 | 
			
		||||
	else if (SkipToNewLine())
 | 
			
		||||
		if (!options['o'])
 | 
			
		||||
			lexstrict("garbage following #%s <identifier>",
 | 
			
		||||
				  how ? "ifdef" : "ifndef");
 | 
			
		||||
 | 
			
		||||
	/* The next test is a shorthand for:
 | 
			
		||||
		(how && !id->id_macro) || (!how && id->id_macro)
 | 
			
		||||
	*/
 | 
			
		||||
	if (how ^ (id && id->id_macro != 0))
 | 
			
		||||
		skip_block(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* argidf != NULL when the undef came from a -U option */
 | 
			
		||||
do_undef(argidf)
 | 
			
		||||
	struct idf *argidf;
 | 
			
		||||
{
 | 
			
		||||
	register struct idf *id = argidf;
 | 
			
		||||
 | 
			
		||||
	/* Forget a macro definition.	*/
 | 
			
		||||
	if (id || (id = GetIdentifier(1))) {
 | 
			
		||||
		if (id->id_macro) { /* forget the macro */
 | 
			
		||||
			if (id->id_macro->mc_flag & NOUNDEF) {
 | 
			
		||||
				lexerror("it is not allowed to undef %s", id->id_text);
 | 
			
		||||
			} else {
 | 
			
		||||
				free(id->id_macro->mc_text);
 | 
			
		||||
				free_macro(id->id_macro);
 | 
			
		||||
				id->id_macro = (struct macro *) 0;
 | 
			
		||||
			}
 | 
			
		||||
		} /* else: don't complain */
 | 
			
		||||
		if (!argidf) {
 | 
			
		||||
			if (SkipToNewLine())
 | 
			
		||||
				if (!options['o'])
 | 
			
		||||
					lexstrict("garbage following #undef");
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		lexerror("illegal #undef construction");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
do_error()
 | 
			
		||||
{
 | 
			
		||||
	int len;
 | 
			
		||||
	char *get_text();
 | 
			
		||||
	char *bp = get_text((char **) 0, &len);
 | 
			
		||||
 | 
			
		||||
	lexerror("user error: %s", bp);
 | 
			
		||||
	free(bp);
 | 
			
		||||
	LineNumber++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
getparams(buf, parbuf)
 | 
			
		||||
	char *buf[];
 | 
			
		||||
	char parbuf[];
 | 
			
		||||
{
 | 
			
		||||
	/*	getparams() reads the formal parameter list of a macro
 | 
			
		||||
		definition.
 | 
			
		||||
		The number of parameters is returned.
 | 
			
		||||
		As a formal parameter list is expected when calling this
 | 
			
		||||
		routine, -1 is returned if an error is detected, for
 | 
			
		||||
		example:
 | 
			
		||||
			#define one(1), where 1 is not an identifier.
 | 
			
		||||
		Note that the '(' has already been eaten.
 | 
			
		||||
		The names of the formal parameters are stored into parbuf.
 | 
			
		||||
	*/
 | 
			
		||||
	register char **pbuf = &buf[0];
 | 
			
		||||
	register int c;
 | 
			
		||||
	register char *ptr = &parbuf[0];
 | 
			
		||||
	register char **pbuf2;
 | 
			
		||||
 | 
			
		||||
	c = GetChar();
 | 
			
		||||
	c = skipspaces(c,0);
 | 
			
		||||
	if (c == ')') {		/* no parameters: #define name()	*/
 | 
			
		||||
		*pbuf = (char *) 0;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	for (;;) {		/* eat the formal parameter list	*/
 | 
			
		||||
		if (class(c) != STIDF && class(c) != STELL) {
 | 
			
		||||
			lexerror("#define: bad formal parameter");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		*pbuf = ptr;	/* name of the formal	*/
 | 
			
		||||
		*ptr++ = c;
 | 
			
		||||
		if (ptr >= &parbuf[PARBUFSIZE])
 | 
			
		||||
			fatal("formal parameter buffer overflow");
 | 
			
		||||
		do {			/* eat the identifier name	*/
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
			*ptr++ = c;
 | 
			
		||||
			if (ptr >= &parbuf[PARBUFSIZE])
 | 
			
		||||
				fatal("formal parameter buffer overflow");
 | 
			
		||||
		} while (in_idf(c));
 | 
			
		||||
		*(ptr - 1) = '\0';	/* mark end of the name		*/
 | 
			
		||||
 | 
			
		||||
		/*	Check if this formal parameter is already used.
 | 
			
		||||
			Usually, macros do not have many parameters, so ...
 | 
			
		||||
		*/
 | 
			
		||||
		for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
 | 
			
		||||
			if (!strcmp(*pbuf2, *pbuf)) {
 | 
			
		||||
				lexerror("formal parameter \"%s\" already used",
 | 
			
		||||
					*pbuf);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		pbuf++;
 | 
			
		||||
		c = skipspaces(c,0);
 | 
			
		||||
		if (c == ')') {	/* end of the formal parameter list	*/
 | 
			
		||||
			*pbuf = (char *) 0;
 | 
			
		||||
			return pbuf - buf;
 | 
			
		||||
		}
 | 
			
		||||
		if (c != ',') {
 | 
			
		||||
			lexerror("#define: bad formal parameter list");
 | 
			
		||||
			return -1;
 | 
			
		||||
		}
 | 
			
		||||
		c = GetChar();
 | 
			
		||||
		c = skipspaces(c,0);
 | 
			
		||||
	}
 | 
			
		||||
	/*NOTREACHED*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
macro_def(id, text, nformals, length, flags)
 | 
			
		||||
	register struct idf *id;
 | 
			
		||||
	char *text;
 | 
			
		||||
{
 | 
			
		||||
	register struct macro *newdef = id->id_macro;
 | 
			
		||||
 | 
			
		||||
	/*	macro_def() puts the contents and information of a macro
 | 
			
		||||
		definition into a structure and stores it into the symbol
 | 
			
		||||
		table entry belonging to the name of the macro.
 | 
			
		||||
		An error is given if there was already a definition
 | 
			
		||||
	*/
 | 
			
		||||
	if (newdef) {		/* is there a redefinition?	*/
 | 
			
		||||
		if (newdef->mc_flag & NOUNDEF) {
 | 
			
		||||
			lexerror("it is not allowed to redefine %s", id->id_text);
 | 
			
		||||
		} else if (!macroeq(newdef->mc_text, text))
 | 
			
		||||
			lexerror("illegal redefine of \"%s\"", id->id_text);
 | 
			
		||||
		free(text);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	id->id_macro = newdef = new_macro();
 | 
			
		||||
	newdef->mc_text = text;		/* replacement text	*/
 | 
			
		||||
	newdef->mc_nps  = nformals;	/* nr of formals	*/
 | 
			
		||||
	newdef->mc_length = length;	/* length of repl. text	*/
 | 
			
		||||
	newdef->mc_flag = flags;	/* special flags	*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
find_name(nm, index)
 | 
			
		||||
	char *nm, *index[];
 | 
			
		||||
{
 | 
			
		||||
	/*	find_name() returns the index of "nm" in the namelist
 | 
			
		||||
		"index" if it can be found there. 0 is returned if it is
 | 
			
		||||
		not there.
 | 
			
		||||
	*/
 | 
			
		||||
	register char **ip = &index[0];
 | 
			
		||||
 | 
			
		||||
	while (*ip)
 | 
			
		||||
		if (strcmp(nm, *ip++) == 0)
 | 
			
		||||
			return ip - &index[0];
 | 
			
		||||
	/* arrived here, nm is not in the name list.	*/
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define	BLANK(ch)	((ch == ' ') || (ch == '\t'))
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
get_text(formals, length)
 | 
			
		||||
	char *formals[];
 | 
			
		||||
	int *length;
 | 
			
		||||
{
 | 
			
		||||
	/*	get_text() copies the replacement text of a macro
 | 
			
		||||
		definition with zero, one or more parameters, thereby
 | 
			
		||||
		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
 | 
			
		||||
		itself because the copied text will contain fewer or the
 | 
			
		||||
		same amount of characters. The length of the replacement
 | 
			
		||||
		text is returned.
 | 
			
		||||
 | 
			
		||||
		Implementation:
 | 
			
		||||
		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;
 | 
			
		||||
	struct repl repls;
 | 
			
		||||
	register struct repl *repl = &repls;
 | 
			
		||||
	int blank = 0;
 | 
			
		||||
 | 
			
		||||
	c = GetChar();
 | 
			
		||||
 | 
			
		||||
	repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
 | 
			
		||||
	*repl->r_ptr = '\0';
 | 
			
		||||
	while ((c != EOI) && (class(c) != STNL)) {
 | 
			
		||||
		if (BLANK(c)) {
 | 
			
		||||
			blank++;
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (c == '\'' || c == '"') {
 | 
			
		||||
			register int delim = c;
 | 
			
		||||
 | 
			
		||||
			if (blank) {
 | 
			
		||||
				blank = 0;
 | 
			
		||||
				add2repl(repl, ' ');
 | 
			
		||||
			}
 | 
			
		||||
			do {
 | 
			
		||||
			    add2repl(repl, c);
 | 
			
		||||
			    if (c == '\\') add2repl(repl, GetChar());
 | 
			
		||||
			    c = GetChar();
 | 
			
		||||
			} while (c != delim && c != EOI && class(c) != STNL);
 | 
			
		||||
			if (c == EOI || class(c) == STNL) {
 | 
			
		||||
				lexstrict("unclosed opening %c", delim);
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
			add2repl(repl, c);
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
		} else if (c == '/') {
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
			if (c == '*') {
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				blank++;
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				continue;
 | 
			
		||||
			} 
 | 
			
		||||
			if (blank) {
 | 
			
		||||
				blank = 0;
 | 
			
		||||
				add2repl(repl, ' ');
 | 
			
		||||
			}
 | 
			
		||||
			add2repl(repl, '/');
 | 
			
		||||
		} else if (formals
 | 
			
		||||
			    && (class(c) == STIDF || class(c) == STELL)) {
 | 
			
		||||
			char id_buf[IDFSIZE + 1];
 | 
			
		||||
			register char *idp = id_buf;
 | 
			
		||||
			int n;
 | 
			
		||||
 | 
			
		||||
			/* read identifier: it may be a formal parameter */
 | 
			
		||||
			*idp++ = c;
 | 
			
		||||
			do {
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				if (idp <= &id_buf[IDFSIZE])
 | 
			
		||||
					*idp++ = c;
 | 
			
		||||
			} while (in_idf(c));
 | 
			
		||||
			*--idp = '\0';
 | 
			
		||||
 | 
			
		||||
			if (blank) {
 | 
			
		||||
				blank = 0;
 | 
			
		||||
				add2repl(repl, ' ');
 | 
			
		||||
			}
 | 
			
		||||
			/* construct the formal parameter mark or identifier */
 | 
			
		||||
			if (n = find_name(id_buf, formals))
 | 
			
		||||
			    add2repl(repl, FORMALP | (char) n);
 | 
			
		||||
			else {
 | 
			
		||||
			    idp = id_buf;
 | 
			
		||||
			    while (*idp) add2repl(repl, *idp++);
 | 
			
		||||
			}
 | 
			
		||||
		} else if (class(c) == STNUM) {
 | 
			
		||||
			if (blank) {
 | 
			
		||||
				blank = 0;
 | 
			
		||||
				add2repl(repl, ' ');
 | 
			
		||||
			}
 | 
			
		||||
			add2repl(repl, c);
 | 
			
		||||
			if (c == '.') {
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				if (class(c) != STNUM) {
 | 
			
		||||
					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 {
 | 
			
		||||
			if (blank) {
 | 
			
		||||
				blank = 0;
 | 
			
		||||
				add2repl(repl, ' ');
 | 
			
		||||
			}
 | 
			
		||||
			add2repl(repl, c);
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	*length = repl->r_ptr - repl->r_text;
 | 
			
		||||
	return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text +1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*	macroeq() decides whether two macro replacement texts are
 | 
			
		||||
	identical.  This version compares the texts, which occur
 | 
			
		||||
	as strings, without taking care of the leading and trailing
 | 
			
		||||
	blanks (spaces and tabs).
 | 
			
		||||
*/
 | 
			
		||||
macroeq(s, t)
 | 
			
		||||
	register char *s, *t;
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	/* skip leading spaces	*/
 | 
			
		||||
	while (BLANK(*s)) s++;
 | 
			
		||||
	while (BLANK(*t)) t++;
 | 
			
		||||
	/* first non-blank encountered in both strings	*/
 | 
			
		||||
	/* The actual comparison loop:			*/
 | 
			
		||||
	while (*s && *s == *t)
 | 
			
		||||
		s++, t++;
 | 
			
		||||
	/* two cases are possible when arrived here:	*/
 | 
			
		||||
	if (*s == '\0')	{	/* *s == '\0'		*/
 | 
			
		||||
		while (BLANK(*t)) t++;
 | 
			
		||||
		return *t == '\0';
 | 
			
		||||
	}
 | 
			
		||||
	else	{		/* *s != *t		*/
 | 
			
		||||
		while (BLANK(*s)) s++;
 | 
			
		||||
		while (BLANK(*t)) t++;
 | 
			
		||||
		return (*s == '\0') && (*t == '\0');
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#else /* NOPP */
 | 
			
		||||
 | 
			
		||||
struct idf *
 | 
			
		||||
GetIdentifier(skiponerr)
 | 
			
		||||
	int skiponerr;		/* skip the rest of the line on error */
 | 
			
		||||
{
 | 
			
		||||
	/*	returns a pointer to the descriptor of the identifier that is
 | 
			
		||||
		read from the input stream. When the input does not contain
 | 
			
		||||
		an identifier, the rest of the line is skipped when
 | 
			
		||||
		skiponerr is on, and a null-pointer is returned.
 | 
			
		||||
		The substitution of macros is disabled.
 | 
			
		||||
	    read from the input stream. When the input does not contain
 | 
			
		||||
	    an identifier, the rest of the line is skipped when
 | 
			
		||||
	    skiponerr is on, and a null-pointer is returned.
 | 
			
		||||
	    The substitution of macros is disabled.
 | 
			
		||||
	*/
 | 
			
		||||
	int tok;
 | 
			
		||||
	struct token tk;
 | 
			
		||||
 | 
			
		||||
	tok = GetToken(&tk);
 | 
			
		||||
	if (tok != IDENTIFIER) {
 | 
			
		||||
		if (skiponerr && tok != EOI) SkipToNewLine();
 | 
			
		||||
		return (struct idf *)0;
 | 
			
		||||
	if (tok != IDENTIFIER)
 | 
			
		||||
	{
 | 
			
		||||
		if (skiponerr && tok != EOI)
 | 
			
		||||
			SkipToNewLine();
 | 
			
		||||
		return (struct idf*)0;
 | 
			
		||||
	}
 | 
			
		||||
	return tk.tk_idf;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -820,14 +50,18 @@ domacro()
 | 
			
		|||
	struct token tk;
 | 
			
		||||
 | 
			
		||||
	EoiForNewline = 1;
 | 
			
		||||
	if ((tok = GetToken(&tk)) == IDENTIFIER) {
 | 
			
		||||
		if (! strcmp(tk.tk_idf->id_text, "pragma")) {
 | 
			
		||||
	if ((tok = GetToken(&tk)) == IDENTIFIER)
 | 
			
		||||
	{
 | 
			
		||||
		if (!strcmp(tk.tk_idf->id_text, "pragma"))
 | 
			
		||||
		{
 | 
			
		||||
			do_pragma();
 | 
			
		||||
			EoiForNewline = 0;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	} else if (tok == INTEGER) {
 | 
			
		||||
		do_line((unsigned int) tk.tk_ival);
 | 
			
		||||
	}
 | 
			
		||||
	else if (tok == INTEGER)
 | 
			
		||||
	{
 | 
			
		||||
		do_line((unsigned int)tk.tk_ival);
 | 
			
		||||
		EoiForNewline = 0;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -835,24 +69,24 @@ domacro()
 | 
			
		|||
	EoiForNewline = 0;
 | 
			
		||||
	SkipToNewLine();
 | 
			
		||||
}
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
do_line(l)
 | 
			
		||||
	unsigned int l;
 | 
			
		||||
do_line(l) unsigned int l;
 | 
			
		||||
{
 | 
			
		||||
	struct token tk;
 | 
			
		||||
	int t = GetToken(&tk);
 | 
			
		||||
 | 
			
		||||
	if (t != EOI) SkipToNewLine();
 | 
			
		||||
	LineNumber = l;		/* the number of the next input line */
 | 
			
		||||
	if (t == STRING) {	/* is there a filespecifier? */
 | 
			
		||||
		/*
 | 
			
		||||
		 * Do not attempt to free the old string, since it might
 | 
			
		||||
		 * be used in a def structure.
 | 
			
		||||
		 */
 | 
			
		||||
	if (t != EOI)
 | 
			
		||||
		SkipToNewLine();
 | 
			
		||||
	LineNumber = l; /* the number of the next input line */
 | 
			
		||||
	if (t == STRING)
 | 
			
		||||
	{ /* is there a filespecifier? */
 | 
			
		||||
/*
 | 
			
		||||
 * Do not attempt to free the old string, since it might
 | 
			
		||||
 * be used in a def structure.
 | 
			
		||||
 */
 | 
			
		||||
#ifdef DBSYMTAB
 | 
			
		||||
		if (options['g'] && strcmp(FileName, tk.tk_bts) != 0) {
 | 
			
		||||
		if (options['g'] && strcmp(FileName, tk.tk_bts) != 0)
 | 
			
		||||
		{
 | 
			
		||||
			C_ms_std(tk.tk_bts, N_SOL, 0);
 | 
			
		||||
		}
 | 
			
		||||
#endif /* DBSYMTAB */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,15 +106,6 @@ dumpidf(idf, opt)
 | 
			
		|||
	
 | 
			
		||||
	if (!idf)
 | 
			
		||||
		return;
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	if ((opt&1) && idf->id_macro)	{
 | 
			
		||||
		if (!started++)	{
 | 
			
		||||
			newline();
 | 
			
		||||
			print("%s:", idf->id_text);
 | 
			
		||||
		}
 | 
			
		||||
		print(" macro");
 | 
			
		||||
	}
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
	if ((opt&2) && idf->id_reserved)	{
 | 
			
		||||
		if (!started++)	{
 | 
			
		||||
			newline();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,10 +8,6 @@
 | 
			
		|||
#include	"parameters.h"
 | 
			
		||||
 | 
			
		||||
struct id_u {
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	struct macro *idd_macro;
 | 
			
		||||
	int idd_resmac;		/* if nonzero: keyword of macroproc. 	*/
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
	int idd_reserved;	/* non-zero for reserved words		*/
 | 
			
		||||
	char *idd_file;		/* file containing the occurrence	*/
 | 
			
		||||
	unsigned int idd_line;	/* line number of the occurrence	*/
 | 
			
		||||
| 
						 | 
				
			
			@ -36,14 +32,5 @@ struct id_u {
 | 
			
		|||
 | 
			
		||||
#include <idf_pkg.spec>
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
struct dependency	{
 | 
			
		||||
	struct dependency *next;
 | 
			
		||||
	struct idf *dep_idf;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ALLOCDEF "dependency" 10 */
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
extern int level;
 | 
			
		||||
extern struct idf *gen_idf();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,99 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
/* $Id$ */
 | 
			
		||||
/* PREPROCESSOR: INITIALIZATION ROUTINES */
 | 
			
		||||
 | 
			
		||||
#include	<stdlib.h>
 | 
			
		||||
#include	<string.h>
 | 
			
		||||
#include        <time.h>
 | 
			
		||||
#include	"parameters.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
#include	<system.h>
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include	<time.h>
 | 
			
		||||
#include    "idf.h"
 | 
			
		||||
#include	"class.h"
 | 
			
		||||
#include	"macro.h"
 | 
			
		||||
 | 
			
		||||
extern char *sprint();
 | 
			
		||||
 | 
			
		||||
struct mkey	{
 | 
			
		||||
	char *mk_reserved;
 | 
			
		||||
	int mk_key;
 | 
			
		||||
} mkey[] =	{
 | 
			
		||||
	{"define",	K_DEFINE},
 | 
			
		||||
	{"elif",	K_ELIF},
 | 
			
		||||
	{"else",	K_ELSE},
 | 
			
		||||
	{"endif",	K_ENDIF},
 | 
			
		||||
	{"error",	K_ERROR},
 | 
			
		||||
	{"if",		K_IF},
 | 
			
		||||
	{"ifdef",	K_IFDEF},
 | 
			
		||||
	{"ifndef",	K_IFNDEF},
 | 
			
		||||
	{"include",	K_INCLUDE},
 | 
			
		||||
	{"line",	K_LINE},
 | 
			
		||||
	{"pragma",	K_PRAGMA},
 | 
			
		||||
	{"undef",	K_UNDEF},
 | 
			
		||||
	{0,		K_UNKNOWN}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
init_pp()
 | 
			
		||||
{
 | 
			
		||||
	static char *months[12] = {
 | 
			
		||||
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
 | 
			
		||||
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
 | 
			
		||||
	};
 | 
			
		||||
	time_t clock;
 | 
			
		||||
	static char dbuf[30];
 | 
			
		||||
	static char tbuf[30];
 | 
			
		||||
	struct tm  *tp;
 | 
			
		||||
 | 
			
		||||
	/*	Initialise the control line keywords (if, include, define, etc)
 | 
			
		||||
		Although the lexical analyzer treats them as identifiers, the
 | 
			
		||||
		control line handler can recognize them as keywords by the
 | 
			
		||||
		id_resmac field of the identifier.
 | 
			
		||||
	*/
 | 
			
		||||
	{
 | 
			
		||||
		register struct mkey *mk = &mkey[0];
 | 
			
		||||
 | 
			
		||||
		while (mk->mk_reserved)	{
 | 
			
		||||
			register struct idf *idf = str2idf(mk->mk_reserved, 0);
 | 
			
		||||
			
 | 
			
		||||
			if (idf->id_resmac)
 | 
			
		||||
				fatal("maximum identifier length insufficient");
 | 
			
		||||
			idf->id_resmac = mk->mk_key;
 | 
			
		||||
			mk++;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*	Initialize __LINE__, __FILE__, __DATE__, __TIME__,
 | 
			
		||||
		and __STDC__ macro definitions.
 | 
			
		||||
	*/
 | 
			
		||||
	clock = time(NULL);
 | 
			
		||||
	tp = localtime(&clock);
 | 
			
		||||
 | 
			
		||||
	/* __DATE__ */
 | 
			
		||||
	sprint(dbuf, "\"%s %02d %d\"", months[tp->tm_mon],
 | 
			
		||||
			tp->tm_mday, tp->tm_year+1900);
 | 
			
		||||
	if (tp->tm_mday < 10) dbuf[5] = ' ';		/* hack */
 | 
			
		||||
	macro_def(str2idf("__DATE__", 0), dbuf, -1, strlen(dbuf), NOUNDEF);
 | 
			
		||||
 | 
			
		||||
	/* __TIME__ */
 | 
			
		||||
	sprint(tbuf, "\"%02d:%02d:%02d\"", tp->tm_hour, tp->tm_min, tp->tm_sec);
 | 
			
		||||
	macro_def(str2idf("__TIME__", 0), tbuf, -1, strlen(tbuf), NOUNDEF);
 | 
			
		||||
 | 
			
		||||
	/* __LINE__	*/
 | 
			
		||||
	macro_def(str2idf("__LINE__", 0), "0", -1, 1, NOUNDEF | FUNC);
 | 
			
		||||
 | 
			
		||||
	/* __FILE__	*/
 | 
			
		||||
	macro_def(str2idf("__FILE__", 0), "", -1, 1, NOUNDEF | FUNC);
 | 
			
		||||
 | 
			
		||||
	/* __STDC__ */
 | 
			
		||||
	macro_def(str2idf("__STDC__", 0), "1", -1, 1, NOUNDEF);
 | 
			
		||||
 | 
			
		||||
	/* defined(??) */
 | 
			
		||||
	macro_def(str2idf("defined", 0), "", 1, 1, NOUNDEF | FUNC);
 | 
			
		||||
}
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
| 
						 | 
				
			
			@ -18,50 +18,10 @@ struct file_info	finfo;
 | 
			
		|||
#include <inp_pkg.body>
 | 
			
		||||
#include <alloc.h>
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
#ifdef DBSYMTAB
 | 
			
		||||
#include <stb.h>
 | 
			
		||||
#include <em.h>
 | 
			
		||||
extern int      IncludeLevel;
 | 
			
		||||
extern char	options[];
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
getwdir(fn)
 | 
			
		||||
	register char *fn;
 | 
			
		||||
{
 | 
			
		||||
	register char *p;
 | 
			
		||||
	char *strrchr();
 | 
			
		||||
 | 
			
		||||
	p = strrchr(fn, '/');
 | 
			
		||||
	while (p && *(p + 1) == '\0') {	/* remove trailing /'s */
 | 
			
		||||
		*p = '\0';
 | 
			
		||||
		p = strrchr(fn, '/');
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
 | 
			
		||||
		return "";
 | 
			
		||||
	if (p) {
 | 
			
		||||
		*p = '\0';
 | 
			
		||||
		fn = Salloc(fn,(unsigned) (p - &fn[0] + 1));
 | 
			
		||||
		*p = '/';
 | 
			
		||||
		return fn;
 | 
			
		||||
	}
 | 
			
		||||
	return "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int	InputLevel;
 | 
			
		||||
extern int		nestlevel;
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
int	NoUnstack;
 | 
			
		||||
 | 
			
		||||
AtEoIT()
 | 
			
		||||
{
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	InputLevel--;
 | 
			
		||||
	unstackrepl();
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,22 +29,6 @@ extern char *source;
 | 
			
		|||
 | 
			
		||||
AtEoIF()
 | 
			
		||||
{
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	if (nestlevel != nestlow) lexwarning("missing #endif");
 | 
			
		||||
	else
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
	if (NoUnstack) lexerror("unexpected EOF");
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	nestlevel = nestlow;
 | 
			
		||||
#ifdef DBSYMTAB
 | 
			
		||||
	if (options['g'] && IncludeLevel > 0) {
 | 
			
		||||
		C_ms_stb_cst(FileName, N_EINCL, 0, (arith) 0);
 | 
			
		||||
	}
 | 
			
		||||
	IncludeLevel--;
 | 
			
		||||
#endif
 | 
			
		||||
	/* We don't free WorkingDir and FileName here because the rest of the
 | 
			
		||||
	 * compiler may be holding pointers to them for displaying error messages.
 | 
			
		||||
	 */
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,47 +6,3 @@
 | 
			
		|||
/* PREPROCESSOR: DEFINITION OF MACRO DESCRIPTOR */
 | 
			
		||||
 | 
			
		||||
#include	"parameters.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
/*	The flags of the mc_flag field of the macro structure. Note that
 | 
			
		||||
	these flags can be set simultaneously.
 | 
			
		||||
*/
 | 
			
		||||
#define	NOFLAG		0		/* no special flags	*/
 | 
			
		||||
#define	FUNC		0x1		/* function attached    */
 | 
			
		||||
#define	NOUNDEF		0x2		/* reserved macro	*/
 | 
			
		||||
#define	NOREPLACE	0x4		/* prevent recursion	*/
 | 
			
		||||
 | 
			
		||||
#define	FORMALP 0200	/* mask for creating macro formal parameter	*/
 | 
			
		||||
 | 
			
		||||
/*	The macro descriptor is very simple, except the fact that the
 | 
			
		||||
	mc_text, which points to the replacement text, contains the
 | 
			
		||||
	non-ascii characters \201, \202, etc, indicating the position of a
 | 
			
		||||
	formal parameter in this text.
 | 
			
		||||
*/
 | 
			
		||||
struct macro	{
 | 
			
		||||
	struct macro *next;
 | 
			
		||||
	char *	mc_text;	/* the replacement text		*/
 | 
			
		||||
	int	mc_nps;		/* number of formal parameters	*/
 | 
			
		||||
	int	mc_length;	/* length of replacement text	*/
 | 
			
		||||
	char	mc_flag;	/* marking this macro		*/
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ALLOCDEF "macro" 20 */
 | 
			
		||||
 | 
			
		||||
/* `token' numbers of keywords of command-line processor
 | 
			
		||||
*/
 | 
			
		||||
#define	K_UNKNOWN	0
 | 
			
		||||
#define	K_DEFINE	1
 | 
			
		||||
#define	K_ELIF		2
 | 
			
		||||
#define	K_ELSE		3
 | 
			
		||||
#define	K_ENDIF		4
 | 
			
		||||
#define	K_ERROR		5
 | 
			
		||||
#define	K_IF		6
 | 
			
		||||
#define	K_IFDEF		7
 | 
			
		||||
#define	K_IFNDEF	8
 | 
			
		||||
#define	K_INCLUDE	9
 | 
			
		||||
#define	K_LINE		10
 | 
			
		||||
#define	K_PRAGMA	11
 | 
			
		||||
#define	K_UNDEF		12
 | 
			
		||||
#define K_FILE          100     /* for dependency generator */
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,19 +29,6 @@ extern struct tokenname tkidf[];
 | 
			
		|||
extern char *symbol2str();
 | 
			
		||||
extern char options[128];
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
int inc_pos = 1;			/* place where next -I goes */
 | 
			
		||||
int inc_total = 0;
 | 
			
		||||
int inc_max;
 | 
			
		||||
char **inctable;
 | 
			
		||||
 | 
			
		||||
extern int do_dependencies;
 | 
			
		||||
extern char *dep_file;
 | 
			
		||||
static File *dep_fd = STDOUT;
 | 
			
		||||
 | 
			
		||||
extern char *getwdir();
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
struct sp_id special_ids[] =	{
 | 
			
		||||
	{"__setjmp", SP_SETJMP},	/* non-local goto's are registered */
 | 
			
		||||
	{0, 0}
 | 
			
		||||
| 
						 | 
				
			
			@ -74,10 +61,6 @@ int
 | 
			
		|||
	union_align = AL_UNION;
 | 
			
		||||
#endif /* NOCROSS */
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
arith ifval;	/* ifval will contain the result of the #if expression	*/
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
char *prog_name;
 | 
			
		||||
 | 
			
		||||
main(argc, argv)
 | 
			
		||||
| 
						 | 
				
			
			@ -86,17 +69,6 @@ main(argc, argv)
 | 
			
		|||
	/* parse and interpret the command line options	*/
 | 
			
		||||
	prog_name = argv[0];
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	inctable = (char **) Malloc(10 * sizeof(char *));
 | 
			
		||||
	inctable[0] = "";
 | 
			
		||||
	inctable[1] = 0;
 | 
			
		||||
	inctable[2] = 0;
 | 
			
		||||
	inc_total = 3;
 | 
			
		||||
	inc_max = 10;
 | 
			
		||||
 | 
			
		||||
	init_pp();	/* initialise the preprocessor macros	*/
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
	/*	Note: source file "-" indicates that the source is supplied
 | 
			
		||||
		as standard input.  This is only allowed if INP_READ_IN_ONE is
 | 
			
		||||
		not defined!
 | 
			
		||||
| 
						 | 
				
			
			@ -122,83 +94,10 @@ main(argc, argv)
 | 
			
		|||
	if (options['m']) Info();
 | 
			
		||||
#endif	/* DEBUG */
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	if (do_dependencies) {
 | 
			
		||||
	    extern char *source;
 | 
			
		||||
 | 
			
		||||
	    list_dependencies(source);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	sys_stop(err_occurred ? S_EXIT : S_END);
 | 
			
		||||
	/*NOTREACHED*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
 | 
			
		||||
struct dependency    *file_head;
 | 
			
		||||
extern char *strrchr();
 | 
			
		||||
 | 
			
		||||
list_dependencies(source)
 | 
			
		||||
char *source;
 | 
			
		||||
{
 | 
			
		||||
    register struct dependency *p = file_head;
 | 
			
		||||
 | 
			
		||||
    if (source) {
 | 
			
		||||
	register char *s = strrchr(source, '.');
 | 
			
		||||
 | 
			
		||||
	if (s && *(s+1)) {
 | 
			
		||||
	    s++;
 | 
			
		||||
	    *s++ = 'o';
 | 
			
		||||
	    *s = '\0';
 | 
			
		||||
	    /* the source may be in another directory than the
 | 
			
		||||
	     * object generated, so don't include the pathname
 | 
			
		||||
	     * leading to it.
 | 
			
		||||
             */
 | 
			
		||||
            if (s = strrchr(source, '/')) {
 | 
			
		||||
		source = s + 1;
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	else source = 0;
 | 
			
		||||
    }
 | 
			
		||||
    if (dep_file && !sys_open(dep_file, OP_WRITE, &dep_fd)) {
 | 
			
		||||
	fatal("could not open %s", dep_file);
 | 
			
		||||
    }
 | 
			
		||||
    while (p) {
 | 
			
		||||
	dependency(p->dep_idf->id_text, source);
 | 
			
		||||
	p = p->next;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
add_dependency(s)
 | 
			
		||||
char *s;
 | 
			
		||||
{
 | 
			
		||||
    register struct idf *p = str2idf(s, 1);
 | 
			
		||||
 | 
			
		||||
    if (! p->id_resmac) {
 | 
			
		||||
	register struct dependency *q = new_dependency();
 | 
			
		||||
 | 
			
		||||
	p->id_resmac = K_FILE;
 | 
			
		||||
	q->dep_idf = p;
 | 
			
		||||
	q->next = file_head;
 | 
			
		||||
	file_head = q;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
dependency(s, source)
 | 
			
		||||
char *s, *source;
 | 
			
		||||
{
 | 
			
		||||
    if (options['i'] && !strncmp(s, "/usr/include/", 13)) {
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
    if (options['m'] && source) {
 | 
			
		||||
	fprint(dep_fd, "%s: %s\n", source, s);
 | 
			
		||||
    }
 | 
			
		||||
    else    fprint(dep_fd, "%s\n", s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
char *source = 0;
 | 
			
		||||
 | 
			
		||||
#ifdef GEN_NM_LIST
 | 
			
		||||
| 
						 | 
				
			
			@ -213,19 +112,10 @@ compile(argc, argv)
 | 
			
		|||
	register char *destination = 0;
 | 
			
		||||
#endif	/* LINT */
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	int pp_only = options['E'] || options['P'] || options['C'];
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	switch (argc) {
 | 
			
		||||
	case 1:
 | 
			
		||||
#ifndef	LINT
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
		if (!pp_only)
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
#endif
 | 
			
		||||
			fatal("%s: destination file not specified", prog_name);
 | 
			
		||||
#endif	/* LINT */
 | 
			
		||||
| 
						 | 
				
			
			@ -277,20 +167,7 @@ compile(argc, argv)
 | 
			
		|||
			: 0);
 | 
			
		||||
#endif	/* LINT */
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	WorkingDir = getwdir(source);
 | 
			
		||||
	PushLex();			/* initialize lex machine */
 | 
			
		||||
#else /* NOPP */
 | 
			
		||||
	GetToken(&ahead);
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	if (pp_only) /* run the preprocessor as if it is stand-alone	*/
 | 
			
		||||
		preprocess();
 | 
			
		||||
	else
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
#endif /* DEBUG */
 | 
			
		||||
	{
 | 
			
		||||
		/* compile the source text			*/
 | 
			
		||||
		C_program();
 | 
			
		||||
| 
						 | 
				
			
			@ -311,9 +188,6 @@ compile(argc, argv)
 | 
			
		|||
			dumpidftab("end of main", options['f'] ? 7 : 0);
 | 
			
		||||
#endif	/* DEBUG */
 | 
			
		||||
	}
 | 
			
		||||
#ifndef	NOPP
 | 
			
		||||
	PopLex();
 | 
			
		||||
#endif	/* NOPP */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
init()
 | 
			
		||||
| 
						 | 
				
			
			@ -395,76 +269,6 @@ init_specials(si)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
preprocess()
 | 
			
		||||
{
 | 
			
		||||
	/*	preprocess() is the "stand-alone" preprocessor which
 | 
			
		||||
		consecutively calls the lexical analyzer LLlex() to get
 | 
			
		||||
		the tokens and prints them in a suitable way.
 | 
			
		||||
	*/
 | 
			
		||||
	static unsigned int lastlineno = 0;
 | 
			
		||||
	static char *lastfilenm = "";
 | 
			
		||||
 | 
			
		||||
	while (LLlex() !=  EOI)	{
 | 
			
		||||
		if (lastlineno != dot.tk_line)	{
 | 
			
		||||
			if (strcmp(lastfilenm, dot.tk_file) == 0)	{
 | 
			
		||||
				if (dot.tk_line - lastlineno <= 1)	{
 | 
			
		||||
					lastlineno++;
 | 
			
		||||
					print("\n");
 | 
			
		||||
				}
 | 
			
		||||
				else	{
 | 
			
		||||
					lastlineno = dot.tk_line;
 | 
			
		||||
					if (!options['P'])
 | 
			
		||||
						print("\n#line %ld \"%s\"\n",
 | 
			
		||||
							lastlineno,
 | 
			
		||||
							lastfilenm
 | 
			
		||||
						);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else	{
 | 
			
		||||
				lastfilenm = dot.tk_file;
 | 
			
		||||
				lastlineno = dot.tk_line;
 | 
			
		||||
				if (!options['P'])
 | 
			
		||||
					print("\n#line %ld \"%s\"\n",
 | 
			
		||||
						lastlineno, lastfilenm);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (strcmp(lastfilenm, dot.tk_file) != 0)	{
 | 
			
		||||
			lastfilenm = dot.tk_file;
 | 
			
		||||
			if (!options['P'])
 | 
			
		||||
				print("\n#line %ld \"%s\"\n",
 | 
			
		||||
					lastlineno, lastfilenm);
 | 
			
		||||
		}
 | 
			
		||||
		switch (DOT)	{
 | 
			
		||||
		case IDENTIFIER:
 | 
			
		||||
		case TYPE_IDENTIFIER:
 | 
			
		||||
			print("%s ", dot.tk_idf->id_text);
 | 
			
		||||
			break;
 | 
			
		||||
		case STRING:
 | 
			
		||||
		{
 | 
			
		||||
			char sbuf[1024];	/* a transient buffer */
 | 
			
		||||
 | 
			
		||||
			print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len -
 | 
			
		||||
			1, sbuf));
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		case INTEGER:
 | 
			
		||||
			print("%ld ", dot.tk_ival);
 | 
			
		||||
			break;
 | 
			
		||||
		case FLOATING:
 | 
			
		||||
			print("%s ", dot.tk_fval);
 | 
			
		||||
			break;
 | 
			
		||||
		case EOI:
 | 
			
		||||
		case EOF:
 | 
			
		||||
			return;
 | 
			
		||||
		default:	/* very expensive...	*/
 | 
			
		||||
			print("%s ", symbol2str(DOT));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
Info()
 | 
			
		||||
{
 | 
			
		||||
	extern int cnt_string_cst, cnt_formal,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,16 +16,6 @@
 | 
			
		|||
#include	"sizes.h"
 | 
			
		||||
#include	"align.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
extern char **inctable;
 | 
			
		||||
extern int inc_pos;
 | 
			
		||||
extern int inc_max;
 | 
			
		||||
extern int inc_total;
 | 
			
		||||
int do_dependencies = 0;
 | 
			
		||||
char *dep_file = 0;
 | 
			
		||||
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
char options[128];			/* one for every char	*/
 | 
			
		||||
#ifdef	LINT
 | 
			
		||||
char loptions[128];			/* one for every char	*/
 | 
			
		||||
| 
						 | 
				
			
			@ -60,18 +50,6 @@ next_option:			/* to allow combined one-char options */
 | 
			
		|||
		goto next_option;
 | 
			
		||||
 | 
			
		||||
#ifndef LINT
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
        case 'A' :      /* Amake dependency generation */
 | 
			
		||||
                do_dependencies = 1;
 | 
			
		||||
                if (*text) {
 | 
			
		||||
                        dep_file = text;
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
        case 'i':
 | 
			
		||||
        case 'm':
 | 
			
		||||
             	options[opt] = 1;
 | 
			
		||||
            	break;
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
#endif /* LINT */
 | 
			
		||||
#ifdef DBSYMTAB
 | 
			
		||||
	case 'g':	/* symbol table for debugger */
 | 
			
		||||
| 
						 | 
				
			
			@ -110,64 +88,6 @@ next_option:			/* to allow combined one-char options */
 | 
			
		|||
		goto next_option;
 | 
			
		||||
#endif	/* LINT */
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	case 'D' :	{	/* -Dname :	predefine name		*/
 | 
			
		||||
		register char *cp = text, *name, *mactext;
 | 
			
		||||
		unsigned maclen;
 | 
			
		||||
 | 
			
		||||
		if (class(*cp) != STIDF && class(*cp) != STELL) {
 | 
			
		||||
			error("identifier missing in -D%s", text);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		name = cp;
 | 
			
		||||
 | 
			
		||||
		while (*cp && in_idf(*cp)) {
 | 
			
		||||
			++cp;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!*cp) {			/* -Dname */
 | 
			
		||||
			maclen = 1;
 | 
			
		||||
			mactext = Salloc("1", 2);
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		if (*cp == '=')	{		/* -Dname=text	*/
 | 
			
		||||
			*cp++ = '\0';		/* end of name	*/
 | 
			
		||||
			maclen = (unsigned) strlen(cp);
 | 
			
		||||
			mactext = Salloc(cp, maclen + 1);
 | 
			
		||||
		}
 | 
			
		||||
		else	{			/* -Dname?? */
 | 
			
		||||
			error("malformed option -D%s", text);
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		macro_def(str2idf(name, 0), mactext, -1, (int)maclen, NOFLAG);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	case 'I' :	/* -Ipath : insert "path" into include list	*/
 | 
			
		||||
		if (*text)	{
 | 
			
		||||
			int i;
 | 
			
		||||
			register char *new = text;
 | 
			
		||||
			
 | 
			
		||||
			if (inc_total >= inc_max) {
 | 
			
		||||
				inctable = (char **)
 | 
			
		||||
				   Realloc((char *)inctable,
 | 
			
		||||
					   (unsigned)((inc_max+=10)*sizeof(char *)));
 | 
			
		||||
			}
 | 
			
		||||
				
 | 
			
		||||
			for (i = inc_pos++; i < inc_total ; i++) {
 | 
			
		||||
				char *tmp = inctable[i];
 | 
			
		||||
				
 | 
			
		||||
				inctable[i] = new;
 | 
			
		||||
				new = tmp;
 | 
			
		||||
			}
 | 
			
		||||
			inc_total++;
 | 
			
		||||
		}
 | 
			
		||||
		else inctable[inc_pos] = 0;
 | 
			
		||||
		break;
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
	case 'M':	/* maximum identifier length */
 | 
			
		||||
		idfsize = txt2int(&text);
 | 
			
		||||
		if (*text || idfsize <= 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -197,12 +117,6 @@ next_option:			/* to allow combined one-char options */
 | 
			
		|||
		break;
 | 
			
		||||
	}
 | 
			
		||||
		
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
	case 'U' :		/* -Uname :	undefine predefined	*/
 | 
			
		||||
		if (*text) do_undef(str2idf(text, 0));
 | 
			
		||||
		break;
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
#ifndef	LINT
 | 
			
		||||
#ifndef NOCROSS
 | 
			
		||||
	case 'V' :	/* set object sizes and alignment requirements	*/
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,10 +61,6 @@
 | 
			
		|||
#include	"l_lint.h"
 | 
			
		||||
#endif	/* LINT */
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
extern arith ifval;
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
extern error();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -75,14 +71,6 @@ control_if_expression
 | 
			
		|||
:
 | 
			
		||||
	constant_expression(&exprX)
 | 
			
		||||
		{
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
			register struct expr *expr = exprX;
 | 
			
		||||
			if (expr->ex_flags & EX_SIZEOF)
 | 
			
		||||
				expr_error(expr,
 | 
			
		||||
					"sizeof not allowed in preprocessor");
 | 
			
		||||
			ifval = expr->VL_VALUE;
 | 
			
		||||
			free_expression(expr);
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
		}
 | 
			
		||||
;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,808 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
/* $Id$ */
 | 
			
		||||
/*  M A C R O   R E P L A C E M E N T */
 | 
			
		||||
 | 
			
		||||
#include	<assert.h>
 | 
			
		||||
#include	<stdlib.h>
 | 
			
		||||
#include	<string.h>
 | 
			
		||||
#include	"parameters.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
 | 
			
		||||
#include	<ack_string.h>
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include    "idf.h"
 | 
			
		||||
#include	"input.h"
 | 
			
		||||
#include	"macro.h"
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"LLlex.h"
 | 
			
		||||
#include	"class.h"
 | 
			
		||||
#include	"replace.h"
 | 
			
		||||
 | 
			
		||||
extern struct idf *GetIdentifier();
 | 
			
		||||
extern int InputLevel;
 | 
			
		||||
struct repl *ReplaceList;	/* list of currently active macros */
 | 
			
		||||
 | 
			
		||||
void macro2buffer();
 | 
			
		||||
void getactuals();
 | 
			
		||||
void expand_defined();
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
replace(idf)
 | 
			
		||||
	register struct idf *idf;
 | 
			
		||||
{
 | 
			
		||||
	/*	replace is called by the lexical analyzer to perform
 | 
			
		||||
		macro replacement. The routine actualy functions as a
 | 
			
		||||
		higher interface to the real thing: expand_macro().
 | 
			
		||||
	*/
 | 
			
		||||
	struct repl *repl;
 | 
			
		||||
 | 
			
		||||
	if (!(idf->id_macro)) return 0;
 | 
			
		||||
	if (idf->id_macro->mc_flag & NOREPLACE)
 | 
			
		||||
		return 0;
 | 
			
		||||
	repl = new_repl();
 | 
			
		||||
	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))
 | 
			
		||||
		return 0;
 | 
			
		||||
	InputLevel++;
 | 
			
		||||
	InsertText(repl->r_text, (int)(repl->r_ptr - repl->r_text));
 | 
			
		||||
	idf->id_macro->mc_flag |= NOREPLACE;
 | 
			
		||||
	repl->r_level = InputLevel;
 | 
			
		||||
	repl->next = ReplaceList;
 | 
			
		||||
	ReplaceList = repl;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
	assert(Unstacked > 0);
 | 
			
		||||
	while(r) {
 | 
			
		||||
		struct repl *nxt = r->next;
 | 
			
		||||
 | 
			
		||||
		if (r->r_level > InputLevel) {
 | 
			
		||||
			r->r_idf->id_macro->mc_flag &= ~NOREPLACE;
 | 
			
		||||
			if (!prev) ReplaceList = nxt;
 | 
			
		||||
			else prev->next = nxt;
 | 
			
		||||
			free(r->r_text);
 | 
			
		||||
			freeargs(r->r_args);
 | 
			
		||||
			free_repl(r);
 | 
			
		||||
		}
 | 
			
		||||
		else prev = r;
 | 
			
		||||
		r = nxt;
 | 
			
		||||
	}
 | 
			
		||||
	Unstacked = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expand_macro(repl, idf)
 | 
			
		||||
	register struct repl *repl;
 | 
			
		||||
	register struct idf *idf;
 | 
			
		||||
{
 | 
			
		||||
	/*	expand_macro() does the actual macro replacement.
 | 
			
		||||
		"idf" is a description of the identifier which
 | 
			
		||||
		caused the replacement.
 | 
			
		||||
		If the identifier represents a function-like macro
 | 
			
		||||
		call, the number of actual parameters is checked
 | 
			
		||||
		against the number of formal parameters. Note that
 | 
			
		||||
		in ANSI C the parameters are expanded first;
 | 
			
		||||
		this is done by calling getactuals().
 | 
			
		||||
		When the possible parameters are expanded, the replace-
 | 
			
		||||
		ment list associated with "idf" is expanded.
 | 
			
		||||
		expand_macro() returns 1 if the replacement succeeded
 | 
			
		||||
		and 0 if some error occurred.
 | 
			
		||||
 | 
			
		||||
		A special case is "defined". This acts as a unary operator
 | 
			
		||||
		on a single, unexpanded identifier, which may be surrounded
 | 
			
		||||
		by parenthesis. The function expand_defined() handles this.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct macro *mac = idf->id_macro;
 | 
			
		||||
	struct args *args = repl->r_args;
 | 
			
		||||
	register int ch;
 | 
			
		||||
 | 
			
		||||
	if (mac->mc_nps != -1) {	/* with parameter list	*/
 | 
			
		||||
		if (mac->mc_flag & FUNC) {
 | 
			
		||||
			/* the following assertion won't compile:
 | 
			
		||||
			assert(!strcmp("defined", idf->id_text));
 | 
			
		||||
			expand the assert macro by hand (??? dirty, temporary)
 | 
			
		||||
			*/
 | 
			
		||||
#ifdef	DEBUG
 | 
			
		||||
			if (strcmp("defined", idf->id_text))
 | 
			
		||||
				crash("in %s, %u: assertion %s failed",
 | 
			
		||||
					__FILE__, __LINE__ - 2,
 | 
			
		||||
					"strcmp(\"defined\", idf->id_text)");
 | 
			
		||||
#endif
 | 
			
		||||
			if (!AccDefined) return 0;
 | 
			
		||||
			expand_defined(repl);
 | 
			
		||||
			return 1;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ch = GetChar();
 | 
			
		||||
		ch = skipspaces(ch,1);
 | 
			
		||||
		if (ch != '(') {	/* no replacement if no () */
 | 
			
		||||
			ChPushBack(ch);
 | 
			
		||||
			return 0;
 | 
			
		||||
		} else
 | 
			
		||||
			getactuals(repl, idf);
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (mac->mc_flag & FUNC) /* this macro leads to special action */
 | 
			
		||||
		macro_func(idf);
 | 
			
		||||
 | 
			
		||||
	macro2buffer(repl, idf, args);
 | 
			
		||||
 | 
			
		||||
	/*	According to the ANSI definition:
 | 
			
		||||
 | 
			
		||||
			#define	a +
 | 
			
		||||
			a+b; --> + + b ;
 | 
			
		||||
 | 
			
		||||
		'a' must be substituded, but the result should be
 | 
			
		||||
		three tokens: + + ID. Therefore a token separator is
 | 
			
		||||
		inserted after the replacement.
 | 
			
		||||
	*/
 | 
			
		||||
	if (repl->r_text == repl->r_ptr || *(repl->r_ptr - 1) != TOKSEP) {
 | 
			
		||||
		add2repl(repl, TOKSEP);
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
expand_defined(repl)
 | 
			
		||||
	register struct repl *repl;
 | 
			
		||||
{
 | 
			
		||||
	register int ch = GetChar();
 | 
			
		||||
	struct idf *id;
 | 
			
		||||
	int parens = 0;
 | 
			
		||||
 | 
			
		||||
	ch = skipspaces(ch, 0);
 | 
			
		||||
 | 
			
		||||
	if (ch == '(') {
 | 
			
		||||
		parens++;
 | 
			
		||||
		ch = GetChar();
 | 
			
		||||
		ch = skipspaces(ch, 0);
 | 
			
		||||
	}
 | 
			
		||||
	if ((class(ch) != STIDF) && (class(ch) != STELL)) {
 | 
			
		||||
		error("identifier missing");
 | 
			
		||||
		if (parens && ch != ')') error(") missing");
 | 
			
		||||
		if (!parens || ch != ')') ChPushBack(ch);
 | 
			
		||||
		add2repl(repl, '0');
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	ChPushBack(ch);
 | 
			
		||||
	id = GetIdentifier(0);
 | 
			
		||||
	assert(id || class(ch) == STELL);
 | 
			
		||||
	ch = GetChar();
 | 
			
		||||
	ch = skipspaces(ch, 0);
 | 
			
		||||
	if (parens && ch != ')') error(") missing");
 | 
			
		||||
	if (!parens || ch != ')') ChPushBack(ch);
 | 
			
		||||
	add2repl(repl, (id && id->id_macro) ? '1' : '0');
 | 
			
		||||
	add2repl(repl, ' ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
getactuals(repl, idf)
 | 
			
		||||
	struct repl *repl;
 | 
			
		||||
	register struct idf *idf;
 | 
			
		||||
{
 | 
			
		||||
	/*	Get the actual parameters from the input stream.
 | 
			
		||||
		The hard part is done by actual(), only comma's and
 | 
			
		||||
		other syntactic trivialities are checked here.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct args *args = repl->r_args;
 | 
			
		||||
	register int nps = idf->id_macro->mc_nps;
 | 
			
		||||
	register int argcnt;
 | 
			
		||||
	register int ch;
 | 
			
		||||
 | 
			
		||||
	argcnt = 0;
 | 
			
		||||
	newarg(args);
 | 
			
		||||
	if ((ch = GetChar()) != ')') {
 | 
			
		||||
		UnGetChar();
 | 
			
		||||
		while ((ch = actual(repl)) != ')' ) {
 | 
			
		||||
			if (ch != ',') {
 | 
			
		||||
				lexerror("illegal macro call");
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
			stash(repl, '\0', 1);
 | 
			
		||||
			args->a_expvec[argcnt] = args->a_expbuf;
 | 
			
		||||
			args->a_rawvec[argcnt] = args->a_rawbuf;
 | 
			
		||||
			++argcnt;
 | 
			
		||||
			if (argcnt == STDC_NPARAMS)
 | 
			
		||||
				lexstrict("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)
 | 
			
		||||
		lexerror("too few macro arguments");
 | 
			
		||||
	else if (argcnt > nps)
 | 
			
		||||
		lexerror("too many macro arguments");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
saveraw(repl)
 | 
			
		||||
struct repl *repl;
 | 
			
		||||
{
 | 
			
		||||
	register struct repl *nrepl = ReplaceList;
 | 
			
		||||
	register struct args *ap = nrepl->r_args;
 | 
			
		||||
	register char *p;
 | 
			
		||||
 | 
			
		||||
	/* stash identifier name */
 | 
			
		||||
	for (p = nrepl->r_idf->id_text; *p != '\0'; p++)
 | 
			
		||||
		stash(repl, *p, -1);
 | 
			
		||||
 | 
			
		||||
	/*	The following code deals with expanded function
 | 
			
		||||
		like macro calls. It makes the following code
 | 
			
		||||
		work:
 | 
			
		||||
 | 
			
		||||
			#define	def(a,b)	x(a,b)
 | 
			
		||||
			#define	glue(a,b)	a ## b
 | 
			
		||||
 | 
			
		||||
			glue(abc,def(a,b))
 | 
			
		||||
 | 
			
		||||
		Results in:
 | 
			
		||||
 | 
			
		||||
			abcdef(a,b);
 | 
			
		||||
	*/
 | 
			
		||||
	if (ap->a_rawvec[0]) {
 | 
			
		||||
		/* stash arguments */
 | 
			
		||||
		register int i;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
 | 
			
		||||
			if (i == 0) stash(repl, '(', -1);
 | 
			
		||||
			else stash(repl, ',', -1);
 | 
			
		||||
			for (p = ap->a_rawvec[i]; *p != '\0'; p++)
 | 
			
		||||
				stash(repl, *p, -1);
 | 
			
		||||
		}
 | 
			
		||||
		stash(repl, ')', -1);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
actual(repl)
 | 
			
		||||
	struct repl *repl;
 | 
			
		||||
{
 | 
			
		||||
	/*	This routine deals with the scanning of an actual parameter.
 | 
			
		||||
		It keeps in account the opening and closing brackets,
 | 
			
		||||
		preprocessor numbers, strings and character constants.
 | 
			
		||||
	*/
 | 
			
		||||
	register int ch = 0;
 | 
			
		||||
	register int level = 0, nostashraw = 0;
 | 
			
		||||
	int lastch;
 | 
			
		||||
	static int Unstacked_missed;
 | 
			
		||||
 | 
			
		||||
	while (1) {
 | 
			
		||||
		lastch = ch;
 | 
			
		||||
		ch = GetChar();
 | 
			
		||||
 | 
			
		||||
		if (nostashraw 
 | 
			
		||||
		    && nostashraw >= Unstacked_missed) {
 | 
			
		||||
			nostashraw -= Unstacked_missed;
 | 
			
		||||
			Unstacked_missed = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if (Unstacked) {
 | 
			
		||||
			nostashraw -= Unstacked;
 | 
			
		||||
			if (nostashraw < 0) {
 | 
			
		||||
				Unstacked_missed = -nostashraw;
 | 
			
		||||
				nostashraw = 0;
 | 
			
		||||
			}
 | 
			
		||||
			EnableMacros();
 | 
			
		||||
		}
 | 
			
		||||
		if (class(ch) == STIDF || class(ch) == STELL) {
 | 
			
		||||
			/*	Scan a preprocessor identifier token. If the
 | 
			
		||||
				token is a macro, it is expanded first.
 | 
			
		||||
			*/
 | 
			
		||||
			char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
 | 
			
		||||
			register char *p = buf;
 | 
			
		||||
			register struct idf *idef;
 | 
			
		||||
			register int pos = -1;
 | 
			
		||||
			extern int idfsize;
 | 
			
		||||
			int NoExpandMacro;
 | 
			
		||||
 | 
			
		||||
			if (ch == NOEXPM) {
 | 
			
		||||
				NoExpandMacro= 1;
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
			} else NoExpandMacro = 0;
 | 
			
		||||
 | 
			
		||||
			do {
 | 
			
		||||
				if (++pos < idfsize) {
 | 
			
		||||
					*p++ = ch;
 | 
			
		||||
				}
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
			} while (in_idf(ch));
 | 
			
		||||
			*p++ = '\0';
 | 
			
		||||
			ch = '\0';	/* It could be an unstashed TOKSEP */
 | 
			
		||||
			UnGetChar();
 | 
			
		||||
 | 
			
		||||
			/*	When the identifier has an associated macro
 | 
			
		||||
				replacement list, it's expanded.
 | 
			
		||||
			*/
 | 
			
		||||
			idef = findidf(buf);
 | 
			
		||||
			if (!idef || NoExpandMacro || !replace(idef)) {
 | 
			
		||||
				if (NoExpandMacro
 | 
			
		||||
				    || (idef && idef->id_macro
 | 
			
		||||
				        && (idef->id_macro->mc_flag & NOREPLACE)))
 | 
			
		||||
					stash(repl, NOEXPM, !nostashraw);
 | 
			
		||||
				for (p = buf; *p != '\0'; p++)
 | 
			
		||||
					stash(repl, *p, !nostashraw);
 | 
			
		||||
			} else {
 | 
			
		||||
				if (!nostashraw) saveraw(repl);
 | 
			
		||||
				nostashraw++;
 | 
			
		||||
			}
 | 
			
		||||
		} else if (class(ch) == STNUM) {
 | 
			
		||||
			/*	a preprocessing number has the following
 | 
			
		||||
				regular expression:
 | 
			
		||||
				    [0-9|"."[0-9]]{[0-9"."a-zA-Z_]|{[Ee][+-]}}*
 | 
			
		||||
			*/
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
			if (ch == '.') {
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
				if (class(ch) != STNUM) {
 | 
			
		||||
					ch = '\0';	/* It could be an unstashed TOKSEP */
 | 
			
		||||
					UnGetChar();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				else stash(repl, ch, !nostashraw);
 | 
			
		||||
			}
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			while (in_idf(ch) || ch == '.') {
 | 
			
		||||
				stash(repl, ch, !nostashraw);
 | 
			
		||||
				if ((ch = GetChar()) == 'e' || ch == 'E') {
 | 
			
		||||
					stash(repl, ch, !nostashraw);
 | 
			
		||||
					ch = GetChar();
 | 
			
		||||
					if (ch == '+' || ch == '-') {
 | 
			
		||||
						stash(repl, ch, !nostashraw);
 | 
			
		||||
						ch = GetChar();
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			ch = '\0';	/* It could be an unstashed TOKSEP */
 | 
			
		||||
			UnGetChar();
 | 
			
		||||
		} else if (ch == '(') {
 | 
			
		||||
			/* a comma may occur between parentheses */
 | 
			
		||||
			level++;
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
		} else if (ch == ')') {
 | 
			
		||||
			level--;
 | 
			
		||||
			/* closing parenthesis of macro call */
 | 
			
		||||
			if (level < 0) return ')';
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
		} else if (ch == ',') {
 | 
			
		||||
			if (level <= 0) { /* comma separator for next argument */
 | 
			
		||||
				if (level)
 | 
			
		||||
					lexerror("unbalanced parenthesis");
 | 
			
		||||
				if (!nostashraw)
 | 
			
		||||
					return ',';	/* ??? */
 | 
			
		||||
			}
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
		} else if (ch == '\n') {
 | 
			
		||||
			/* newlines are accepted as white spaces */
 | 
			
		||||
			LineNumber++;
 | 
			
		||||
			/*	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(
 | 
			
		||||
					/_* comment *_/ #include phone_number
 | 
			
		||||
					,2);
 | 
			
		||||
				in which case the include must be handled
 | 
			
		||||
				interpreted as such.
 | 
			
		||||
			*/
 | 
			
		||||
 | 
			
		||||
a_new_line:		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();
 | 
			
		||||
				/* Clear File_Inserted since domacro could
 | 
			
		||||
				 * be called again, which calls GetToken().
 | 
			
		||||
				 */
 | 
			
		||||
				File_Inserted = 0;
 | 
			
		||||
				goto a_new_line;
 | 
			
		||||
			} else if (ch == EOI) {
 | 
			
		||||
				lexerror("unterminated macro call");
 | 
			
		||||
				return ')';
 | 
			
		||||
			}
 | 
			
		||||
			if (ch != '/') {
 | 
			
		||||
				UnGetChar();
 | 
			
		||||
				ch = ' ';
 | 
			
		||||
				stash(repl, ' ', !nostashraw);
 | 
			
		||||
			}
 | 
			
		||||
		} else if (ch == '/') {
 | 
			
		||||
			/* comments are treated as one white space token */
 | 
			
		||||
			if ((ch = GetChar()) == '*' && !InputLevel) {
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				stash(repl, ' ', !nostashraw);
 | 
			
		||||
			} else {
 | 
			
		||||
				UnGetChar();
 | 
			
		||||
				ch = '/';
 | 
			
		||||
				stash(repl, '/', !nostashraw);
 | 
			
		||||
			}
 | 
			
		||||
		} else if (ch == '\'' || ch == '"') {
 | 
			
		||||
			/*	Strings are considered as ONE token, thus no
 | 
			
		||||
				replacement within strings.
 | 
			
		||||
			*/
 | 
			
		||||
			register int match = ch;
 | 
			
		||||
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
			while ((ch = GetChar()) != EOI) {
 | 
			
		||||
				if (ch == match)
 | 
			
		||||
					break;
 | 
			
		||||
				if (ch == '\\') {
 | 
			
		||||
					stash(repl, ch, !nostashraw);
 | 
			
		||||
					ch = GetChar();
 | 
			
		||||
				} else if (ch == '\n') {
 | 
			
		||||
					lexerror("newline in string");
 | 
			
		||||
					LineNumber++;
 | 
			
		||||
					stash(repl, match, !nostashraw);
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				stash(repl, ch, !nostashraw);
 | 
			
		||||
			}
 | 
			
		||||
			if (ch != match) {
 | 
			
		||||
				lexerror("unterminated macro call");
 | 
			
		||||
				return ')';
 | 
			
		||||
			}
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (lastch == TOKSEP && ch == TOKSEP) continue;
 | 
			
		||||
			stash(repl, ch, !nostashraw);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
macro_func(idef)
 | 
			
		||||
	register struct idf *idef;
 | 
			
		||||
{
 | 
			
		||||
	/*	macro_func() performs the special actions needed with some
 | 
			
		||||
		macros. These macros are __FILE__ and __LINE__ which
 | 
			
		||||
		replacement texts must be evaluated at the time they are
 | 
			
		||||
		used.
 | 
			
		||||
	*/
 | 
			
		||||
	register struct macro *mac = idef->id_macro;
 | 
			
		||||
	static char FilNamBuf[PATHLENGTH];
 | 
			
		||||
 | 
			
		||||
	switch (idef->id_text[2]) {
 | 
			
		||||
	case 'F':			/* __FILE__	*/
 | 
			
		||||
		FilNamBuf[0] = '"';
 | 
			
		||||
		strcpy(&FilNamBuf[1], FileName);
 | 
			
		||||
		strcat(FilNamBuf, "\"");
 | 
			
		||||
		mac->mc_text = FilNamBuf;
 | 
			
		||||
		mac->mc_length = strlen(FilNamBuf);
 | 
			
		||||
		break;
 | 
			
		||||
	case 'L':			/* __LINE__	*/
 | 
			
		||||
		mac->mc_text = long2str((long)LineNumber, 10);
 | 
			
		||||
		mac->mc_length = strlen(mac->mc_text);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		crash("(macro_func)");
 | 
			
		||||
		/*NOTREACHED*/
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
macro2buffer(repl, idf, args)
 | 
			
		||||
	register struct repl *repl;
 | 
			
		||||
	register struct idf *idf;
 | 
			
		||||
	register struct args *args;
 | 
			
		||||
{
 | 
			
		||||
	/*	macro2buffer expands the replacement list and places the
 | 
			
		||||
		result onto the replacement buffer. It deals with the #
 | 
			
		||||
		and ## operators, and inserts the actual parameters.
 | 
			
		||||
		The argument buffer contains the raw argument (needed
 | 
			
		||||
		for the ## operator), and the expanded argument (for
 | 
			
		||||
		all other parameter substitutions).
 | 
			
		||||
 | 
			
		||||
		The grammar of the replacement list is:
 | 
			
		||||
 | 
			
		||||
			repl_list:	TOKEN repl_list
 | 
			
		||||
				|	PARAMETER repl_list
 | 
			
		||||
				|	'#' PARAMETER
 | 
			
		||||
				|	TOKEN '##' TOKEN
 | 
			
		||||
				|	PARAMETER '##' TOKEN
 | 
			
		||||
				|	TOKEN '##' PARAMETER
 | 
			
		||||
				|	PARAMETER '##' PARAMETER
 | 
			
		||||
				;
 | 
			
		||||
 | 
			
		||||
		As the grammar indicates, we could make a DFA and
 | 
			
		||||
		use this finite state machine for the replacement
 | 
			
		||||
		list parsing (inserting the arguments, etc.).
 | 
			
		||||
 | 
			
		||||
		Currently we go through the replacement list in a
 | 
			
		||||
		linear fashion. This is VERY expensive, something
 | 
			
		||||
		smarter should be done (but even a DFA is O(|s|)).
 | 
			
		||||
	*/
 | 
			
		||||
	register char *ptr = idf->id_macro->mc_text;
 | 
			
		||||
	int err = 0;
 | 
			
		||||
	int func = idf->id_macro->mc_nps != -1;
 | 
			
		||||
	char *stringify();
 | 
			
		||||
 | 
			
		||||
	assert(ptr[idf->id_macro->mc_length] == '\0');
 | 
			
		||||
	while (*ptr) {
 | 
			
		||||
	    if (*ptr == '\'' || *ptr == '"') {
 | 
			
		||||
		register int delim = *ptr;
 | 
			
		||||
 | 
			
		||||
		do {
 | 
			
		||||
		    add2repl(repl, *ptr);
 | 
			
		||||
		    if (*ptr == '\\')
 | 
			
		||||
			add2repl(repl, *++ptr);
 | 
			
		||||
		    if (*ptr == '\0') {
 | 
			
		||||
			lexerror("unterminated string");
 | 
			
		||||
			return;
 | 
			
		||||
		    }
 | 
			
		||||
		    ptr++;
 | 
			
		||||
		} while (*ptr != delim || *ptr == '\0');
 | 
			
		||||
		add2repl(repl, *ptr++);
 | 
			
		||||
	    } else if (*ptr == '#' && (func || *(ptr+1) == '#')) {
 | 
			
		||||
		if (*++ptr == '#') {
 | 
			
		||||
		    register int tmpindex;
 | 
			
		||||
			/* ## - paste operator */
 | 
			
		||||
		    ptr++;
 | 
			
		||||
 | 
			
		||||
			/* trim the actual replacement list */
 | 
			
		||||
		    --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.
 | 
			
		||||
		     */
 | 
			
		||||
		    if (repl->r_ptr < repl->r_text) {
 | 
			
		||||
			err = 1;
 | 
			
		||||
			break;
 | 
			
		||||
		    }
 | 
			
		||||
 | 
			
		||||
		    if (repl->r_ptr >= repl->r_text
 | 
			
		||||
			    && *repl->r_ptr == TOKSEP)
 | 
			
		||||
			--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))
 | 
			
		||||
			    ptr++;
 | 
			
		||||
 | 
			
		||||
		    /*	## occurred at the end of the replacement list.
 | 
			
		||||
		     */
 | 
			
		||||
		    if (*ptr & FORMALP) {
 | 
			
		||||
			register int n = *ptr++ & 0177;
 | 
			
		||||
			register char *p;
 | 
			
		||||
 | 
			
		||||
			assert(n > 0);
 | 
			
		||||
			p = args->a_rawvec[n-1];
 | 
			
		||||
			if (p) {	/* else macro argument missing */
 | 
			
		||||
			    while (is_wsp(*p)) p++;
 | 
			
		||||
			    if (*p == NOEXPM) p++;
 | 
			
		||||
			    while (*p)
 | 
			
		||||
				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)) {
 | 
			
		||||
				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 */
 | 
			
		||||
			ptr = stringify(repl, ptr, args);
 | 
			
		||||
		}
 | 
			
		||||
	    } else if (*ptr & FORMALP) {
 | 
			
		||||
		/* insert actual parameter */
 | 
			
		||||
		register int n = *ptr++ & 0177;
 | 
			
		||||
		register char *p, *q;
 | 
			
		||||
 | 
			
		||||
		assert(n > 0);
 | 
			
		||||
 | 
			
		||||
		/*	This is VERY dirty, we look ahead for the
 | 
			
		||||
			## operator. If it's found we use the raw
 | 
			
		||||
			argument buffer instead of the expanded
 | 
			
		||||
			one.
 | 
			
		||||
		*/
 | 
			
		||||
		for (p = ptr; (*p & FORMALP) == 0 && is_wsp(*p); p++)
 | 
			
		||||
			/* EMPTY */;
 | 
			
		||||
		if (*p == '#' && p[1] == '#')
 | 
			
		||||
			q = args->a_rawvec[n-1];
 | 
			
		||||
		else
 | 
			
		||||
			q = args->a_expvec[n-1];
 | 
			
		||||
 | 
			
		||||
		if (q)			/* else macro argument missing */
 | 
			
		||||
		    while (*q)
 | 
			
		||||
			add2repl(repl, *q++);
 | 
			
		||||
 | 
			
		||||
		if (repl->r_text == repl->r_ptr || *(repl->r_ptr - 1) != TOKSEP)
 | 
			
		||||
			add2repl(repl, TOKSEP);
 | 
			
		||||
	    } else {
 | 
			
		||||
		add2repl(repl, *ptr++);
 | 
			
		||||
	    }
 | 
			
		||||
	}
 | 
			
		||||
	if (err)
 | 
			
		||||
		lexerror("illegal use of the ## operator");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char *
 | 
			
		||||
stringify(repl, ptr, args)
 | 
			
		||||
	register struct repl *repl;
 | 
			
		||||
	register char *ptr;
 | 
			
		||||
	register struct args *args;
 | 
			
		||||
{
 | 
			
		||||
	/*	If a parameter is immediately preceded by a # token
 | 
			
		||||
		both are replaced by a single string literal that
 | 
			
		||||
		contains the spelling of the token sequence for the
 | 
			
		||||
		corresponding argument.
 | 
			
		||||
		Each occurrence of white space between the argument's
 | 
			
		||||
		tokens become a single space character in the string
 | 
			
		||||
		literal. White spaces before the first token and after
 | 
			
		||||
		the last token comprising the argument are deleted.
 | 
			
		||||
		To retain the original spelling we insert backslashes
 | 
			
		||||
		as appropriate. We only escape backslashes if they
 | 
			
		||||
		occure within string tokens.
 | 
			
		||||
	*/
 | 
			
		||||
	register int space = 1;		/* skip leading spaces */
 | 
			
		||||
	register int delim = 0;		/* string or character constant delim */
 | 
			
		||||
	register int backslash = 0;	/* last character was a \ */
 | 
			
		||||
 | 
			
		||||
	/* skip spaces macro replacement list */
 | 
			
		||||
	while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
 | 
			
		||||
		ptr++;
 | 
			
		||||
 | 
			
		||||
	if (*ptr & FORMALP) {
 | 
			
		||||
		register int n = *ptr++ & 0177;
 | 
			
		||||
		register char *p;
 | 
			
		||||
 | 
			
		||||
		assert(n != 0);
 | 
			
		||||
		p = args->a_rawvec[n-1];
 | 
			
		||||
		add2repl(repl, '"');
 | 
			
		||||
		while (*p) {
 | 
			
		||||
			if (is_wsp(*p)) {
 | 
			
		||||
				if (!space) {
 | 
			
		||||
					space = 1;
 | 
			
		||||
					add2repl(repl, ' ');
 | 
			
		||||
				}
 | 
			
		||||
				p++;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			space = 0;
 | 
			
		||||
 | 
			
		||||
			if (!delim && (*p == '"' || *p == '\''))
 | 
			
		||||
				delim = *p;
 | 
			
		||||
			else if (*p == delim && !backslash)
 | 
			
		||||
				delim = 0;
 | 
			
		||||
			backslash = *p == '\\';
 | 
			
		||||
			if (*p == '"' || (delim && *p == '\\'))
 | 
			
		||||
				add2repl(repl, '\\');
 | 
			
		||||
			if (*p == TOKSEP || *p == NOEXPM) 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;		/* oops, one to far */
 | 
			
		||||
		add2repl(repl, '"');
 | 
			
		||||
	} else
 | 
			
		||||
		error("illegal use of # operator");
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	assert(index < repl->r_size);
 | 
			
		||||
	if (index + 2 >= repl->r_size) {
 | 
			
		||||
		repl->r_text = Realloc(repl->r_text, (unsigned) (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 int index = args->a_expptr - args->a_expbuf;
 | 
			
		||||
 | 
			
		||||
	if (stashraw >= 0) {
 | 
			
		||||
		assert(index < args->a_expsize);
 | 
			
		||||
		if (index + 1 >= args->a_expsize) {
 | 
			
		||||
			args->a_expbuf = Realloc(args->a_expbuf,
 | 
			
		||||
						    (unsigned) (args->a_expsize <<= 1));
 | 
			
		||||
			args->a_expptr = args->a_expbuf + index;
 | 
			
		||||
		}
 | 
			
		||||
		*args->a_expptr++ = ch;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (stashraw) {
 | 
			
		||||
		index = args->a_rawptr - args->a_rawbuf;
 | 
			
		||||
		assert(index < args->a_rawsize);
 | 
			
		||||
		if (index + 1 >= args->a_rawsize) {
 | 
			
		||||
			args->a_rawbuf = Realloc(args->a_rawbuf,
 | 
			
		||||
						    (unsigned)(args->a_rawsize <<= 1));
 | 
			
		||||
			args->a_rawptr = args->a_rawbuf + index;
 | 
			
		||||
		}
 | 
			
		||||
		*args->a_rawptr++ = ch;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
| 
						 | 
				
			
			@ -1,51 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
			
		||||
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
			
		||||
 */
 | 
			
		||||
/* $Id$ */
 | 
			
		||||
/*	DEFINITIONS FOR THE MACRO REPLACEMENT ROUTINES		*/
 | 
			
		||||
 | 
			
		||||
struct repl {
 | 
			
		||||
	struct	repl *next;
 | 
			
		||||
	struct	idf *r_idf;		/* name of the macro */
 | 
			
		||||
	struct	args *r_args;		/* replacement parameters */
 | 
			
		||||
	int	r_level;		/* level of insertion */
 | 
			
		||||
	int	r_size;			/* current size of replacement buffer */
 | 
			
		||||
	char	*r_ptr;			/* replacement text index pointer */
 | 
			
		||||
	char	*r_text;		/* replacement text */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ALLOCDEF "repl" 4 */
 | 
			
		||||
 | 
			
		||||
#define NO_REPL		(struct repl *)0
 | 
			
		||||
 | 
			
		||||
/*	The implementation of the ## operator is currently very clumsy.
 | 
			
		||||
	When the the ## operator is used the arguments are taken from
 | 
			
		||||
	the raw buffer; this buffer contains a precise copy of the
 | 
			
		||||
	original argument. The fully expanded copy is in the arg buffer.
 | 
			
		||||
	The two copies are here explicitely because:
 | 
			
		||||
 | 
			
		||||
		#define ABC	f()
 | 
			
		||||
		#define	ABCD	2
 | 
			
		||||
		#define	g(x, y)	x ## y + h(x)
 | 
			
		||||
 | 
			
		||||
		g(ABC, D);		// gives: 2 + h(f()) 
 | 
			
		||||
 | 
			
		||||
	In this case we need two copies: one raw copy for the pasting
 | 
			
		||||
	operator, and an expanded one as argument for h().
 | 
			
		||||
*/
 | 
			
		||||
struct args {
 | 
			
		||||
	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_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 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* ALLOCDEF "args" 2 */
 | 
			
		||||
 | 
			
		||||
#define NO_ARGS		(struct args *)0
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -5,100 +5,23 @@
 | 
			
		|||
/* $Id$ */
 | 
			
		||||
/* PREPROCESSOR: INPUT SKIP FUNCTIONS */
 | 
			
		||||
 | 
			
		||||
#include	"parameters.h"
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"LLlex.h"
 | 
			
		||||
#include	"class.h"
 | 
			
		||||
#include	"input.h"
 | 
			
		||||
#include "parameters.h"
 | 
			
		||||
#include "arith.h"
 | 
			
		||||
#include "LLlex.h"
 | 
			
		||||
#include "class.h"
 | 
			
		||||
#include "input.h"
 | 
			
		||||
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
extern int InputLevel;
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
skipspaces(ch, skipnl)
 | 
			
		||||
	register int ch;
 | 
			
		||||
{
 | 
			
		||||
	/*	skipspaces() skips any white space and returns the first
 | 
			
		||||
		non-space character.
 | 
			
		||||
	*/
 | 
			
		||||
	register int nlseen = 0;
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
		while (class(ch) == STSKIP)
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
		if (skipnl && class(ch) == STNL) {
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			LineNumber++;
 | 
			
		||||
			nlseen++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (ch == TOKSEP && InputLevel) {
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* \\\n are handled by trigraph */
 | 
			
		||||
 | 
			
		||||
		if (ch == '/') {
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			if (ch == '*' && !InputLevel) {
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
			}
 | 
			
		||||
			else	{
 | 
			
		||||
				UnGetChar();
 | 
			
		||||
				return '/';
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if (nlseen && ch == '#') {
 | 
			
		||||
			domacro();
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
		} else
 | 
			
		||||
			return ch;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
#endif /* NOPP */
 | 
			
		||||
 | 
			
		||||
SkipToNewLine()
 | 
			
		||||
{
 | 
			
		||||
	register int ch;
 | 
			
		||||
	register int garbage = 0;
 | 
			
		||||
#ifndef	NOPP
 | 
			
		||||
	register int delim = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	while ((ch = GetChar()) != '\n') {
 | 
			
		||||
#ifndef NOPP
 | 
			
		||||
		if (delim) {
 | 
			
		||||
			if (ch == '\\') {
 | 
			
		||||
				if (GetChar() == '\n') break;
 | 
			
		||||
			} else if (ch == delim) {
 | 
			
		||||
				delim = 0;
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch == '\'' || ch == '\"') {
 | 
			
		||||
			delim = ch;
 | 
			
		||||
			garbage = 1;
 | 
			
		||||
		} else if (ch == '/') {
 | 
			
		||||
			if (GetChar() == '*'
 | 
			
		||||
			    && !InputLevel
 | 
			
		||||
			) {
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			else UnGetChar();
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch == TOKSEP && InputLevel) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
	while ((ch = GetChar()) != '\n')
 | 
			
		||||
	{
 | 
			
		||||
		if (!is_wsp(ch))
 | 
			
		||||
			garbage = 1;
 | 
			
		||||
	}
 | 
			
		||||
#ifndef	NOPP
 | 
			
		||||
	if (delim) strict("unclosed opening %c", delim);
 | 
			
		||||
#endif
 | 
			
		||||
	++LineNumber;
 | 
			
		||||
	return garbage;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -5,92 +5,113 @@
 | 
			
		|||
/* $Id$ */
 | 
			
		||||
/* PREPROCESSOR DRIVER */
 | 
			
		||||
 | 
			
		||||
#include    <stdlib.h>
 | 
			
		||||
#include    <stdio.h>
 | 
			
		||||
#include	<system.h>
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include	"input.h"
 | 
			
		||||
#include	"parameters.h"
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"LLlex.h"
 | 
			
		||||
#include	"class.h"
 | 
			
		||||
#include	"macro.h"
 | 
			
		||||
#include	"idf.h"
 | 
			
		||||
#include	"bits.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <system.h>
 | 
			
		||||
#include <alloc.h>
 | 
			
		||||
#include "input.h"
 | 
			
		||||
#include "parameters.h"
 | 
			
		||||
#include "arith.h"
 | 
			
		||||
#include "LLlex.h"
 | 
			
		||||
#include "class.h"
 | 
			
		||||
#include "macro.h"
 | 
			
		||||
#include "idf.h"
 | 
			
		||||
#include "bits.h"
 | 
			
		||||
 | 
			
		||||
char	_obuf[OBUFSIZE];
 | 
			
		||||
char _obuf[OBUFSIZE];
 | 
			
		||||
#ifdef DOBITS
 | 
			
		||||
char	bits[128];
 | 
			
		||||
char bits[128];
 | 
			
		||||
#endif
 | 
			
		||||
extern int InputLevel;
 | 
			
		||||
 | 
			
		||||
extern char *sprint();
 | 
			
		||||
extern char* sprint();
 | 
			
		||||
 | 
			
		||||
Xflush()
 | 
			
		||||
{
 | 
			
		||||
	sys_write(STDOUT, _obuf, OBUFSIZE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *SkipComment();
 | 
			
		||||
static char* SkipComment();
 | 
			
		||||
extern char options[];
 | 
			
		||||
 | 
			
		||||
/* #pragma directives are saved here and passed to the compiler later on.
 | 
			
		||||
 */
 | 
			
		||||
struct prag_info {
 | 
			
		||||
	int	pr_linnr;
 | 
			
		||||
	char	*pr_fil;
 | 
			
		||||
	char	*pr_text;
 | 
			
		||||
struct prag_info
 | 
			
		||||
{
 | 
			
		||||
	int pr_linnr;
 | 
			
		||||
	char* pr_fil;
 | 
			
		||||
	char* pr_text;
 | 
			
		||||
};
 | 
			
		||||
static struct prag_info *pragma_tab;
 | 
			
		||||
static struct prag_info* pragma_tab;
 | 
			
		||||
static int pragma_nr;
 | 
			
		||||
 | 
			
		||||
do_pragma()
 | 
			
		||||
{
 | 
			
		||||
	register int size = ITEXTSIZE;
 | 
			
		||||
	char *cur_line = Malloc((unsigned)size);
 | 
			
		||||
	register char *c_ptr = cur_line;
 | 
			
		||||
	char* cur_line = Malloc((unsigned)size);
 | 
			
		||||
	register char* c_ptr = cur_line;
 | 
			
		||||
	register int c = GetChar();
 | 
			
		||||
	register int delim = 0;
 | 
			
		||||
 | 
			
		||||
	while(c != '\n') {
 | 
			
		||||
		if (c_ptr + 1 - cur_line == size) {
 | 
			
		||||
	while (c != '\n')
 | 
			
		||||
	{
 | 
			
		||||
		if (c_ptr + 1 - cur_line == size)
 | 
			
		||||
		{
 | 
			
		||||
			cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
 | 
			
		||||
			c_ptr = cur_line + size - 1;
 | 
			
		||||
			size += ITEXTSIZE;
 | 
			
		||||
		}
 | 
			
		||||
		if (delim) {
 | 
			
		||||
			if (c == delim) {
 | 
			
		||||
		if (delim)
 | 
			
		||||
		{
 | 
			
		||||
			if (c == delim)
 | 
			
		||||
			{
 | 
			
		||||
				delim = 0;
 | 
			
		||||
			}
 | 
			
		||||
			else if (c == '\\') {
 | 
			
		||||
			else if (c == '\\')
 | 
			
		||||
			{
 | 
			
		||||
				*c_ptr++ = c;
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				if (c == '\n') break;
 | 
			
		||||
				if (c == '\n')
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if (c == '\'' || c == '"') {
 | 
			
		||||
		else if (c == '\'' || c == '"')
 | 
			
		||||
		{
 | 
			
		||||
			delim = c;
 | 
			
		||||
		}
 | 
			
		||||
		else if (c == '/') {
 | 
			
		||||
			if ((c = GetChar()) != '*' || InputLevel) {
 | 
			
		||||
		else if (c == '/')
 | 
			
		||||
		{
 | 
			
		||||
			if (!InputLevel)
 | 
			
		||||
			{
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				if (c == '*')
 | 
			
		||||
				{
 | 
			
		||||
					skipcomment();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				else if (c == '/')
 | 
			
		||||
				{
 | 
			
		||||
					skiplinecomment();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				*c_ptr++ = '/';
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		*c_ptr++ = c;
 | 
			
		||||
		c = GetChar();
 | 
			
		||||
	}
 | 
			
		||||
	*c_ptr = '\0';
 | 
			
		||||
	if (!pragma_nr) {
 | 
			
		||||
		pragma_tab = (struct prag_info *)Malloc(sizeof(struct prag_info));
 | 
			
		||||
	} else {
 | 
			
		||||
		pragma_tab = (struct prag_info *)Realloc((char *)pragma_tab
 | 
			
		||||
				    , (unsigned)(sizeof(struct prag_info) * (pragma_nr+1)));
 | 
			
		||||
	if (!pragma_nr)
 | 
			
		||||
	{
 | 
			
		||||
		pragma_tab = (struct prag_info*)Malloc(sizeof(struct prag_info));
 | 
			
		||||
	}
 | 
			
		||||
	if (delim) {
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		pragma_tab = (struct prag_info*)Realloc(
 | 
			
		||||
		    (char*)pragma_tab, (unsigned)(sizeof(struct prag_info) * (pragma_nr + 1)));
 | 
			
		||||
	}
 | 
			
		||||
	if (delim)
 | 
			
		||||
	{
 | 
			
		||||
		error("unclosed opening %c", delim);
 | 
			
		||||
	}
 | 
			
		||||
	pragma_tab[pragma_nr].pr_linnr = LineNumber;
 | 
			
		||||
| 
						 | 
				
			
			@ -102,138 +123,188 @@ do_pragma()
 | 
			
		|||
 | 
			
		||||
char Xbuf[256];
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
preprocess(fn)
 | 
			
		||||
	char *fn;
 | 
			
		||||
void preprocess(fn) char* fn;
 | 
			
		||||
{
 | 
			
		||||
	register int c;
 | 
			
		||||
	register char *op = _obuf;
 | 
			
		||||
	register char *ob = &_obuf[OBUFSIZE];
 | 
			
		||||
	register char* op = _obuf;
 | 
			
		||||
	register char* ob = &_obuf[OBUFSIZE];
 | 
			
		||||
	int lineno = 0;
 | 
			
		||||
	int startline;
 | 
			
		||||
 | 
			
		||||
#define flush(X)	(sys_write(STDOUT,_obuf,X))
 | 
			
		||||
#define echo(ch) 	if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch);
 | 
			
		||||
#define newline()	op--; while (op >= _obuf && (*op == ' ' || *op == '\t')) op--; op++; echo('\n')
 | 
			
		||||
#define flush(X) (sys_write(STDOUT, _obuf, X))
 | 
			
		||||
#define echo(ch)                                                                                   \
 | 
			
		||||
	if (op == ob)                                                                                  \
 | 
			
		||||
	{                                                                                              \
 | 
			
		||||
		Xflush();                                                                                  \
 | 
			
		||||
		op = _obuf;                                                                                \
 | 
			
		||||
	}                                                                                              \
 | 
			
		||||
	*op++ = (ch);
 | 
			
		||||
#define newline()                                                                                  \
 | 
			
		||||
	op--;                                                                                          \
 | 
			
		||||
	while (op >= _obuf && (*op == ' ' || *op == '\t'))                                             \
 | 
			
		||||
		op--;                                                                                      \
 | 
			
		||||
	op++;                                                                                          \
 | 
			
		||||
	echo('\n')
 | 
			
		||||
 | 
			
		||||
	if (!options['P']) {
 | 
			
		||||
	if (!options['P'])
 | 
			
		||||
	{
 | 
			
		||||
		/* Generate a line directive communicating the
 | 
			
		||||
		   source filename
 | 
			
		||||
		*/
 | 
			
		||||
		register char *p = Xbuf;
 | 
			
		||||
		register char* p = Xbuf;
 | 
			
		||||
 | 
			
		||||
		sprint(p, "%s 1 \"%s\"\n",
 | 
			
		||||
			LINE_PREFIX,
 | 
			
		||||
			FileName);
 | 
			
		||||
		while (*p) {
 | 
			
		||||
		sprint(p, "%s 1 \"%s\"\n", LINE_PREFIX, FileName);
 | 
			
		||||
		while (*p)
 | 
			
		||||
		{
 | 
			
		||||
			echo(*p++);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define	do_line_dir(lineno, fn)						\
 | 
			
		||||
		if (lineno != LineNumber || fn != FileName) {		\
 | 
			
		||||
			fn = FileName;					\
 | 
			
		||||
			lineno = LineNumber;				\
 | 
			
		||||
			if (! options['P']) {				\
 | 
			
		||||
				register char *p = Xbuf;		\
 | 
			
		||||
				sprint(Xbuf, "%s %d \"%s\"\n",		\
 | 
			
		||||
					LINE_PREFIX,			\
 | 
			
		||||
					(int)LineNumber,		\
 | 
			
		||||
					FileName);			\
 | 
			
		||||
				op--;					\
 | 
			
		||||
				while (op >= _obuf			\
 | 
			
		||||
				       && (class(*op) == STSKIP		\
 | 
			
		||||
					   || *op == '\n')) op--;	\
 | 
			
		||||
				op++;					\
 | 
			
		||||
				newline();				\
 | 
			
		||||
				while (*p) {				\
 | 
			
		||||
					echo(*p++);			\
 | 
			
		||||
				}					\
 | 
			
		||||
			}						\
 | 
			
		||||
		}
 | 
			
		||||
#define do_line_dir(lineno, fn)                                                                    \
 | 
			
		||||
	if (lineno != LineNumber || fn != FileName)                                                    \
 | 
			
		||||
	{                                                                                              \
 | 
			
		||||
		fn = FileName;                                                                             \
 | 
			
		||||
		lineno = LineNumber;                                                                       \
 | 
			
		||||
		if (!options['P'])                                                                         \
 | 
			
		||||
		{                                                                                          \
 | 
			
		||||
			register char* p = Xbuf;                                                               \
 | 
			
		||||
			sprint(Xbuf, "%s %d \"%s\"\n", LINE_PREFIX, (int)LineNumber, FileName);                \
 | 
			
		||||
			op--;                                                                                  \
 | 
			
		||||
			while (op >= _obuf && (class(*op) == STSKIP || *op == '\n'))                           \
 | 
			
		||||
				op--;                                                                              \
 | 
			
		||||
			op++;                                                                                  \
 | 
			
		||||
			newline();                                                                             \
 | 
			
		||||
			while (*p)                                                                             \
 | 
			
		||||
			{                                                                                      \
 | 
			
		||||
				echo(*p++);                                                                        \
 | 
			
		||||
			}                                                                                      \
 | 
			
		||||
		}                                                                                          \
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
	for (;;)
 | 
			
		||||
	{
 | 
			
		||||
		LineNumber++;
 | 
			
		||||
		lineno++;
 | 
			
		||||
		startline = 1;
 | 
			
		||||
		c = GetChar();
 | 
			
		||||
		while (startline) {
 | 
			
		||||
		    /* first flush the saved pragma's */
 | 
			
		||||
		    if (pragma_nr) {
 | 
			
		||||
		while (startline)
 | 
			
		||||
		{
 | 
			
		||||
			/* first flush the saved pragma's */
 | 
			
		||||
			if (pragma_nr)
 | 
			
		||||
			{
 | 
			
		||||
				register int i = 0;
 | 
			
		||||
				int LiNo = LineNumber;
 | 
			
		||||
				char *FiNam = FileName;
 | 
			
		||||
	
 | 
			
		||||
				while (i < pragma_nr) {
 | 
			
		||||
				    register char *c_ptr = "#pragma";
 | 
			
		||||
	
 | 
			
		||||
				    LineNumber = pragma_tab[i].pr_linnr;
 | 
			
		||||
				    FileName = pragma_tab[i].pr_fil;
 | 
			
		||||
				    do_line_dir(lineno, fn);
 | 
			
		||||
				    while (*c_ptr) { echo(*c_ptr++); }
 | 
			
		||||
				    c_ptr = pragma_tab[i].pr_text;
 | 
			
		||||
				    while (*c_ptr) { echo(*c_ptr++); }
 | 
			
		||||
				    newline(); lineno++;
 | 
			
		||||
				    free(pragma_tab[i].pr_text);
 | 
			
		||||
				    i++;
 | 
			
		||||
				char* FiNam = FileName;
 | 
			
		||||
 | 
			
		||||
				while (i < pragma_nr)
 | 
			
		||||
				{
 | 
			
		||||
					register char* c_ptr = "#pragma";
 | 
			
		||||
 | 
			
		||||
					LineNumber = pragma_tab[i].pr_linnr;
 | 
			
		||||
					FileName = pragma_tab[i].pr_fil;
 | 
			
		||||
					do_line_dir(lineno, fn);
 | 
			
		||||
					while (*c_ptr)
 | 
			
		||||
					{
 | 
			
		||||
						echo(*c_ptr++);
 | 
			
		||||
					}
 | 
			
		||||
					c_ptr = pragma_tab[i].pr_text;
 | 
			
		||||
					while (*c_ptr)
 | 
			
		||||
					{
 | 
			
		||||
						echo(*c_ptr++);
 | 
			
		||||
					}
 | 
			
		||||
					newline();
 | 
			
		||||
					lineno++;
 | 
			
		||||
					free(pragma_tab[i].pr_text);
 | 
			
		||||
					i++;
 | 
			
		||||
				}
 | 
			
		||||
				free((char *) pragma_tab);
 | 
			
		||||
				pragma_tab = (struct prag_info *)0;
 | 
			
		||||
				free((char*)pragma_tab);
 | 
			
		||||
				pragma_tab = (struct prag_info*)0;
 | 
			
		||||
				pragma_nr = 0;
 | 
			
		||||
				LineNumber = LiNo;
 | 
			
		||||
				FileName = FiNam;
 | 
			
		||||
				do_line_dir(lineno, fn);
 | 
			
		||||
		    }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		    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;
 | 
			
		||||
			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;
 | 
			
		||||
						}
 | 
			
		||||
						else if (c == '/')
 | 
			
		||||
						{
 | 
			
		||||
							skiplinecomment();
 | 
			
		||||
							c = GetChar();
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
						UnGetChar();
 | 
			
		||||
						c = '/';
 | 
			
		||||
					}
 | 
			
		||||
					UnGetChar();
 | 
			
		||||
					c = '/';
 | 
			
		||||
				    }
 | 
			
		||||
				    break;
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				echo(c);
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
		    }
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		    if (c == '#') {
 | 
			
		||||
			if (c == '#')
 | 
			
		||||
			{
 | 
			
		||||
				domacro();
 | 
			
		||||
				lineno++;
 | 
			
		||||
				newline();
 | 
			
		||||
				do_line_dir(lineno, fn);
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
		    } else startline = 0;
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				startline = 0;
 | 
			
		||||
		}
 | 
			
		||||
		do_line_dir(lineno, fn);
 | 
			
		||||
		for (;;) {
 | 
			
		||||
		for (;;)
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
			/* illegal character */
 | 
			
		||||
			if (c & 0200)  {
 | 
			
		||||
				if (c == EOI) {
 | 
			
		||||
			if (c & 0200)
 | 
			
		||||
			{
 | 
			
		||||
				if (c == EOI)
 | 
			
		||||
				{
 | 
			
		||||
					newline();
 | 
			
		||||
					flush((int)(op-_obuf));
 | 
			
		||||
					flush((int)(op - _obuf));
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
				fatal("non-ascii character read");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			/* comments */
 | 
			
		||||
			if (c == '/' && !InputLevel) {
 | 
			
		||||
			if (c == '/' && !InputLevel)
 | 
			
		||||
			{
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				if (c == '*') {
 | 
			
		||||
				if (c == '*')
 | 
			
		||||
				{
 | 
			
		||||
					op = SkipComment(op, &lineno);
 | 
			
		||||
					if (!op) return;
 | 
			
		||||
					if (!options['C']) { echo(' '); }
 | 
			
		||||
					if (!op)
 | 
			
		||||
						return;
 | 
			
		||||
					if (!options['C'])
 | 
			
		||||
					{
 | 
			
		||||
						echo(' ');
 | 
			
		||||
					}
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				else if (c == '/')
 | 
			
		||||
				{
 | 
			
		||||
					skiplinecomment();
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -242,164 +313,221 @@ preprocess(fn)
 | 
			
		|||
			}
 | 
			
		||||
 | 
			
		||||
			/* switch on character */
 | 
			
		||||
			switch(class(c)) {
 | 
			
		||||
			case STNL:
 | 
			
		||||
				newline();
 | 
			
		||||
				break;
 | 
			
		||||
			case STSTR:
 | 
			
		||||
			case STCHAR:
 | 
			
		||||
			switch (class(c))
 | 
			
		||||
			{
 | 
			
		||||
				case STNL:
 | 
			
		||||
					newline();
 | 
			
		||||
					break;
 | 
			
		||||
				case STSTR:
 | 
			
		||||
				case STCHAR:
 | 
			
		||||
				{
 | 
			
		||||
				register int stopc = c;
 | 
			
		||||
				int escaped;
 | 
			
		||||
					register int stopc = c;
 | 
			
		||||
					int escaped;
 | 
			
		||||
 | 
			
		||||
				do {
 | 
			
		||||
					escaped = 0;
 | 
			
		||||
					echo(c);
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					if (c == '\n') {
 | 
			
		||||
					/* the compiler will complain */
 | 
			
		||||
						break;
 | 
			
		||||
					}
 | 
			
		||||
					else if (c == EOI) {
 | 
			
		||||
						newline();
 | 
			
		||||
						flush((int)(op-_obuf));
 | 
			
		||||
						return;
 | 
			
		||||
					}
 | 
			
		||||
					if (c == '\\') {
 | 
			
		||||
					do
 | 
			
		||||
					{
 | 
			
		||||
						escaped = 0;
 | 
			
		||||
						echo(c);
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
						if (c == '\n') {
 | 
			
		||||
							++LineNumber;
 | 
			
		||||
							lineno++;
 | 
			
		||||
						} else escaped = 1;
 | 
			
		||||
					}
 | 
			
		||||
				} while (escaped || c != stopc);
 | 
			
		||||
				echo(c);
 | 
			
		||||
				if (c == '\n')
 | 
			
		||||
					break;	/* Don't eat # */
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				continue;
 | 
			
		||||
				}
 | 
			
		||||
			case STNUM:
 | 
			
		||||
			/* The following code is quit ugly. This because
 | 
			
		||||
			 * ..3 == . .3 , whereas ...3 == ... 3
 | 
			
		||||
			 */
 | 
			
		||||
				echo(c);
 | 
			
		||||
				if (c == '.') {
 | 
			
		||||
						if (c == '\n')
 | 
			
		||||
						{
 | 
			
		||||
							/* the compiler will complain */
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						else if (c == EOI)
 | 
			
		||||
						{
 | 
			
		||||
							newline();
 | 
			
		||||
							flush((int)(op - _obuf));
 | 
			
		||||
							return;
 | 
			
		||||
						}
 | 
			
		||||
						if (c == '\\')
 | 
			
		||||
						{
 | 
			
		||||
							echo(c);
 | 
			
		||||
							c = GetChar();
 | 
			
		||||
							if (c == '\n')
 | 
			
		||||
							{
 | 
			
		||||
								++LineNumber;
 | 
			
		||||
								lineno++;
 | 
			
		||||
							}
 | 
			
		||||
							else
 | 
			
		||||
								escaped = 1;
 | 
			
		||||
						}
 | 
			
		||||
					} while (escaped || c != stopc);
 | 
			
		||||
					echo(c);
 | 
			
		||||
					if (c == '\n')
 | 
			
		||||
						break; /* Don't eat # */
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					if (c == '.') {
 | 
			
		||||
						if ((c = GetChar()) == '.') {
 | 
			
		||||
							echo('.'); echo('.');
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				case STNUM:
 | 
			
		||||
					/* The following code is quit ugly. This because
 | 
			
		||||
					 * ..3 == . .3 , whereas ...3 == ... 3
 | 
			
		||||
					 */
 | 
			
		||||
					echo(c);
 | 
			
		||||
					if (c == '.')
 | 
			
		||||
					{
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
						if (c == '.')
 | 
			
		||||
						{
 | 
			
		||||
							if ((c = GetChar()) == '.')
 | 
			
		||||
							{
 | 
			
		||||
								echo('.');
 | 
			
		||||
								echo('.');
 | 
			
		||||
								c = GetChar();
 | 
			
		||||
								continue;
 | 
			
		||||
							}
 | 
			
		||||
							UnGetChar();
 | 
			
		||||
							c = '.';
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
						else if (!is_dig(c))
 | 
			
		||||
						{
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							echo(c);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					while (in_idf(c) || c == '.')
 | 
			
		||||
					{
 | 
			
		||||
						echo(c);
 | 
			
		||||
						if (c == 'e' || c == 'E')
 | 
			
		||||
						{
 | 
			
		||||
							c = GetChar();
 | 
			
		||||
							if (c == '+' || c == '-')
 | 
			
		||||
							{
 | 
			
		||||
								echo(c);
 | 
			
		||||
								c = GetChar();
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
							c = GetChar();
 | 
			
		||||
					}
 | 
			
		||||
					continue;
 | 
			
		||||
				case STELL:
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					UnGetChar();
 | 
			
		||||
					if (c == '"' || c == '\'')
 | 
			
		||||
					{
 | 
			
		||||
						echo('L');
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
					c = 'L';
 | 
			
		||||
				case STIDF:
 | 
			
		||||
				{
 | 
			
		||||
					extern int idfsize; /* ??? */
 | 
			
		||||
					char buf[IDFSIZE + 1];
 | 
			
		||||
					register char* tg = &buf[0];
 | 
			
		||||
					register char* maxpos = &buf[idfsize];
 | 
			
		||||
					register struct idf* idef;
 | 
			
		||||
					int NoExpandNext = 0;
 | 
			
		||||
 | 
			
		||||
#define tstmac(bx)                                                                                 \
 | 
			
		||||
	if (!(bits[c] & bx))                                                                           \
 | 
			
		||||
	goto nomac
 | 
			
		||||
#define cpy *tg++ = c
 | 
			
		||||
#define load                                                                                       \
 | 
			
		||||
	c = GetChar();                                                                                 \
 | 
			
		||||
	if (!in_idf(c))                                                                                \
 | 
			
		||||
	goto endidf
 | 
			
		||||
 | 
			
		||||
					/* unstack macro's when allowed. */
 | 
			
		||||
					if (Unstacked)
 | 
			
		||||
						EnableMacros();
 | 
			
		||||
					if (c == NOEXPM)
 | 
			
		||||
					{
 | 
			
		||||
						NoExpandNext = 1;
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
#ifdef DOBITS
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit0);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit1);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit2);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit3);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit4);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit5);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit6);
 | 
			
		||||
					load;
 | 
			
		||||
					cpy;
 | 
			
		||||
					tstmac(bit7);
 | 
			
		||||
					load;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
					for (;;)
 | 
			
		||||
					{
 | 
			
		||||
						if (tg < maxpos)
 | 
			
		||||
						{
 | 
			
		||||
							cpy;
 | 
			
		||||
						}
 | 
			
		||||
						load;
 | 
			
		||||
					}
 | 
			
		||||
				endidf:
 | 
			
		||||
					if (c != EOF)
 | 
			
		||||
						UnGetChar();
 | 
			
		||||
					*tg = '\0'; /* mark the end of the identifier */
 | 
			
		||||
					if ((idef = findidf(buf)) && idef->id_macro && ReplaceMacros && !NoExpandNext)
 | 
			
		||||
					{
 | 
			
		||||
						if (replace(idef))
 | 
			
		||||
						{
 | 
			
		||||
							echo(' ');
 | 
			
		||||
							c = GetChar();
 | 
			
		||||
							continue;
 | 
			
		||||
						}
 | 
			
		||||
						UnGetChar();
 | 
			
		||||
						c = '.';
 | 
			
		||||
						continue;
 | 
			
		||||
					} else if (!is_dig(c)) {
 | 
			
		||||
						continue;
 | 
			
		||||
					} else { echo(c); }
 | 
			
		||||
				}
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				while (in_idf(c) || c == '.') {
 | 
			
		||||
					echo(c);
 | 
			
		||||
					if (c == 'e' || c == 'E') {
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
						if (c == '+' || c == '-') {
 | 
			
		||||
							echo(c);
 | 
			
		||||
							c = GetChar();
 | 
			
		||||
						tg = buf;
 | 
			
		||||
						while (*tg)
 | 
			
		||||
						{
 | 
			
		||||
							echo(*tg++);
 | 
			
		||||
						}
 | 
			
		||||
					} else	c = GetChar();
 | 
			
		||||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
			case STELL:
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				UnGetChar();
 | 
			
		||||
				if (c == '"' || c == '\'') {
 | 
			
		||||
					echo('L');
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				c = 'L';
 | 
			
		||||
			case STIDF: {
 | 
			
		||||
				extern int idfsize;		/* ??? */
 | 
			
		||||
				char buf[IDFSIZE + 1];
 | 
			
		||||
				register char *tg = &buf[0];
 | 
			
		||||
				register char *maxpos = &buf[idfsize];
 | 
			
		||||
				register struct idf *idef;
 | 
			
		||||
				int NoExpandNext = 0;
 | 
			
		||||
 | 
			
		||||
#define tstmac(bx)	if (!(bits[c] & bx)) goto nomac
 | 
			
		||||
#define cpy		*tg++ = c
 | 
			
		||||
#define load		c = GetChar(); if (!in_idf(c)) goto endidf
 | 
			
		||||
 | 
			
		||||
				/* unstack macro's when allowed. */
 | 
			
		||||
				if (Unstacked)
 | 
			
		||||
					EnableMacros();
 | 
			
		||||
				if (c == NOEXPM) {
 | 
			
		||||
					NoExpandNext = 1;
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
#ifdef DOBITS
 | 
			
		||||
				cpy; tstmac(bit0); load;
 | 
			
		||||
				cpy; tstmac(bit1); load;
 | 
			
		||||
				cpy; tstmac(bit2); load;
 | 
			
		||||
				cpy; tstmac(bit3); load;
 | 
			
		||||
				cpy; tstmac(bit4); load;
 | 
			
		||||
				cpy; tstmac(bit5); load;
 | 
			
		||||
				cpy; tstmac(bit6); load;
 | 
			
		||||
				cpy; tstmac(bit7); load;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
				for(;;) {
 | 
			
		||||
					if (tg < maxpos) {
 | 
			
		||||
						cpy;
 | 
			
		||||
					}
 | 
			
		||||
					load;
 | 
			
		||||
				}
 | 
			
		||||
			endidf:
 | 
			
		||||
				if (c != EOF) UnGetChar();
 | 
			
		||||
				*tg = '\0';	/* mark the end of the identifier */
 | 
			
		||||
				if ((idef = findidf(buf))
 | 
			
		||||
				    && idef->id_macro
 | 
			
		||||
				    && ReplaceMacros && !NoExpandNext) {
 | 
			
		||||
					if (replace(idef)) {
 | 
			
		||||
						echo(' ');
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
						if (in_idf(c))
 | 
			
		||||
						{
 | 
			
		||||
							echo(' ');
 | 
			
		||||
						}
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
				nomac:
 | 
			
		||||
					*tg = '\0';
 | 
			
		||||
					tg = buf;
 | 
			
		||||
					while (*tg) {
 | 
			
		||||
					while (*tg)
 | 
			
		||||
					{
 | 
			
		||||
						echo(*tg++);
 | 
			
		||||
					}
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					if (in_idf(c)) { echo(' '); }
 | 
			
		||||
					while (in_idf(c))
 | 
			
		||||
					{
 | 
			
		||||
						echo(c);
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
					}
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			nomac:
 | 
			
		||||
				*tg = '\0';
 | 
			
		||||
				tg = buf;
 | 
			
		||||
				while (*tg) {
 | 
			
		||||
					echo(*tg++);
 | 
			
		||||
				}
 | 
			
		||||
				c = GetChar();
 | 
			
		||||
				while (in_idf(c)) {
 | 
			
		||||
				case STMSPEC:
 | 
			
		||||
					if (InputLevel)
 | 
			
		||||
					{
 | 
			
		||||
						echo(' '); /* seperate tokens */
 | 
			
		||||
						c = GetChar();
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
				/* else fallthrough */
 | 
			
		||||
				default:
 | 
			
		||||
					echo(c);
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
				}
 | 
			
		||||
			case STMSPEC:
 | 
			
		||||
				if (InputLevel) {
 | 
			
		||||
					echo(' ');	/* seperate tokens */
 | 
			
		||||
					c = GetChar();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				/* else fallthrough */
 | 
			
		||||
			default:
 | 
			
		||||
			    	echo(c);
 | 
			
		||||
			    	c = GetChar();
 | 
			
		||||
			    	continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -407,49 +535,60 @@ preprocess(fn)
 | 
			
		|||
	/*NOTREACHED*/
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
SkipComment(op, lineno)
 | 
			
		||||
char *op;
 | 
			
		||||
int *lineno;
 | 
			
		||||
static char* SkipComment(op, lineno) char* op;
 | 
			
		||||
int* lineno;
 | 
			
		||||
{
 | 
			
		||||
	char *ob = &_obuf[OBUFSIZE];
 | 
			
		||||
	char* ob = &_obuf[OBUFSIZE];
 | 
			
		||||
	register int c, oldc = '\0';
 | 
			
		||||
 | 
			
		||||
	NoUnstack++;
 | 
			
		||||
	if (options['C']) {
 | 
			
		||||
	if (options['C'])
 | 
			
		||||
	{
 | 
			
		||||
		echo('/');
 | 
			
		||||
		echo('*');
 | 
			
		||||
	}
 | 
			
		||||
	c = GetChar();
 | 
			
		||||
	for(;;) {
 | 
			
		||||
		if (c == EOI) {
 | 
			
		||||
	for (;;)
 | 
			
		||||
	{
 | 
			
		||||
		if (c == EOI)
 | 
			
		||||
		{
 | 
			
		||||
			newline();
 | 
			
		||||
			flush((int)(op - _obuf));
 | 
			
		||||
			op = 0;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		if (options['C']) {
 | 
			
		||||
		if (options['C'])
 | 
			
		||||
		{
 | 
			
		||||
			echo(c);
 | 
			
		||||
		}
 | 
			
		||||
		if (c == '\n') {
 | 
			
		||||
		if (c == '\n')
 | 
			
		||||
		{
 | 
			
		||||
			++LineNumber;
 | 
			
		||||
			++*lineno;
 | 
			
		||||
			if (!options['C']) {
 | 
			
		||||
			if (!options['C'])
 | 
			
		||||
			{
 | 
			
		||||
				echo(c);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if (c == '*') {
 | 
			
		||||
		if (c == '*')
 | 
			
		||||
		{
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
			if (c == '/') {
 | 
			
		||||
				if (options['C']) {
 | 
			
		||||
			if (c == '/')
 | 
			
		||||
			{
 | 
			
		||||
				if (options['C'])
 | 
			
		||||
				{
 | 
			
		||||
					echo(c);
 | 
			
		||||
				}
 | 
			
		||||
				break;			/* for(;;) */
 | 
			
		||||
			} else if (oldc == '/') {
 | 
			
		||||
				break; /* for(;;) */
 | 
			
		||||
			}
 | 
			
		||||
			else if (oldc == '/')
 | 
			
		||||
			{
 | 
			
		||||
				warning("comment inside comment ?");
 | 
			
		||||
			}
 | 
			
		||||
			oldc = '*';
 | 
			
		||||
		} else {
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			oldc = c;
 | 
			
		||||
			c = GetChar();
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,53 +5,64 @@
 | 
			
		|||
/* $Id$ */
 | 
			
		||||
/* PREPROCESSOR: INPUT SKIP FUNCTIONS */
 | 
			
		||||
 | 
			
		||||
#include	"arith.h"
 | 
			
		||||
#include	"LLlex.h"
 | 
			
		||||
#include	"class.h"
 | 
			
		||||
#include	"input.h"
 | 
			
		||||
#include "arith.h"
 | 
			
		||||
#include "LLlex.h"
 | 
			
		||||
#include "class.h"
 | 
			
		||||
#include "input.h"
 | 
			
		||||
 | 
			
		||||
extern int InputLevel;
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
skipspaces(ch, skipnl)
 | 
			
		||||
	register int ch;
 | 
			
		||||
int skipspaces(ch, skipnl) register int ch;
 | 
			
		||||
{
 | 
			
		||||
	/*	skipspaces() skips any white space and returns the first
 | 
			
		||||
		non-space character.
 | 
			
		||||
	    non-space character.
 | 
			
		||||
	*/
 | 
			
		||||
	register int nlseen = 0;
 | 
			
		||||
 | 
			
		||||
	for (;;) {
 | 
			
		||||
	for (;;)
 | 
			
		||||
	{
 | 
			
		||||
		while (class(ch) == STSKIP)
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
		if (skipnl && class(ch) == STNL) {
 | 
			
		||||
		if (skipnl && class(ch) == STNL)
 | 
			
		||||
		{
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			LineNumber++;
 | 
			
		||||
			nlseen++;
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (ch == TOKSEP && InputLevel) {
 | 
			
		||||
		if (ch == TOKSEP && InputLevel)
 | 
			
		||||
		{
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		/* \\\n are handled by trigraph */
 | 
			
		||||
 | 
			
		||||
		if (ch == '/') {
 | 
			
		||||
		if (ch == '/')
 | 
			
		||||
		{
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
			if (ch == '*' && !InputLevel) {
 | 
			
		||||
			if (ch == '*' && !InputLevel)
 | 
			
		||||
			{
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
			}
 | 
			
		||||
			else	{
 | 
			
		||||
			else if (ch == '/' && !InputLevel)
 | 
			
		||||
			{
 | 
			
		||||
				skiplinecomment();
 | 
			
		||||
				ch = GetChar();
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				UnGetChar();
 | 
			
		||||
				return '/';
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if (nlseen && ch == '#') {
 | 
			
		||||
		else if (nlseen && ch == '#')
 | 
			
		||||
		{
 | 
			
		||||
			domacro();
 | 
			
		||||
			ch = GetChar();
 | 
			
		||||
		} else
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
			return ch;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -62,31 +73,54 @@ SkipToNewLine()
 | 
			
		|||
	register int garbage = 0;
 | 
			
		||||
	register int delim = 0;
 | 
			
		||||
 | 
			
		||||
	while ((ch = GetChar()) != '\n') {
 | 
			
		||||
		if (delim) {
 | 
			
		||||
			if (ch == '\\') {
 | 
			
		||||
				if (GetChar() == '\n') break;
 | 
			
		||||
			} else if (ch == delim) {
 | 
			
		||||
	while ((ch = GetChar()) != '\n')
 | 
			
		||||
	{
 | 
			
		||||
		if (delim)
 | 
			
		||||
		{
 | 
			
		||||
			if (ch == '\\')
 | 
			
		||||
			{
 | 
			
		||||
				if (GetChar() == '\n')
 | 
			
		||||
					break;
 | 
			
		||||
			}
 | 
			
		||||
			else if (ch == delim)
 | 
			
		||||
			{
 | 
			
		||||
				delim = 0;
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		} else if (ch == '\'' || ch == '\"') {
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch == '\'' || ch == '\"')
 | 
			
		||||
		{
 | 
			
		||||
			delim = ch;
 | 
			
		||||
			garbage = 1;
 | 
			
		||||
		} else if (ch == '/') {
 | 
			
		||||
			if (GetChar() == '*' && !InputLevel) {
 | 
			
		||||
				skipcomment();
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			else UnGetChar();
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch == TOKSEP && InputLevel) {
 | 
			
		||||
		else if (ch == '/')
 | 
			
		||||
		{
 | 
			
		||||
			if (!InputLevel)
 | 
			
		||||
			{
 | 
			
		||||
				int nch = GetChar();
 | 
			
		||||
				if (nch == '*')
 | 
			
		||||
				{
 | 
			
		||||
					skipcomment();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				else if (nch == '/')
 | 
			
		||||
				{
 | 
			
		||||
					skiplinecomment();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					UnGetChar();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if (ch == TOKSEP && InputLevel)
 | 
			
		||||
		{
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
		if (!is_wsp(ch))
 | 
			
		||||
			garbage = 1;
 | 
			
		||||
	}
 | 
			
		||||
	if (delim) strict("unclosed opening %c", delim);
 | 
			
		||||
	if (delim)
 | 
			
		||||
		strict("unclosed opening %c", delim);
 | 
			
		||||
	++LineNumber;
 | 
			
		||||
	return garbage;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,8 +15,8 @@ int __funccnt = 0;
 | 
			
		|||
void exit(int status)
 | 
			
		||||
{
 | 
			
		||||
	/* "Called in reversed order of their registration" */
 | 
			
		||||
	while (__funccnt >= 0)
 | 
			
		||||
		(*__functab[__funccnt])();
 | 
			
		||||
	while (__funccnt)
 | 
			
		||||
		(*__functab[--__funccnt])();
 | 
			
		||||
 | 
			
		||||
	_exit(status);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								lib/descr/fe
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								lib/descr/fe
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -72,18 +72,8 @@ name cem
 | 
			
		|||
	mapflag -V* CEM_F={CEM_F?} -V*
 | 
			
		||||
	rts .c
 | 
			
		||||
	need .c
 | 
			
		||||
	prep always
 | 
			
		||||
	args \
 | 
			
		||||
		{CPP_F?} \
 | 
			
		||||
		-D__{ARCH} -D__{PLATFORM} \
 | 
			
		||||
		-D__ACK \
 | 
			
		||||
		{SYSINCLUDES?} \
 | 
			
		||||
		{C_INCLUDES} \
 | 
			
		||||
		{INCLUDES?} \
 | 
			
		||||
		({ANSI_C?.xx}:.xx=-D{ARCH} \
 | 
			
		||||
		-DEM_WSIZE={w} -DEM_PSIZE={p} \
 | 
			
		||||
		-DEM_SSIZE={s} -DEM_LSIZE={l} -DEM_FSIZE={f} -DEM_DSIZE={d}) \
 | 
			
		||||
		-D_EM_WSIZE={w} -D_EM_PSIZE={p} \
 | 
			
		||||
		-D_EM_SSIZE={s} -D_EM_LSIZE={l} -D_EM_FSIZE={f} -D_EM_DSIZE={d} \
 | 
			
		||||
		-Vw{w}.{wa}i{w}.{wa}p{p}.{pa}f{f}.{fa}s{s}.{sa}l{l}.{la}d{d}.{da}x{x}.{xa} \
 | 
			
		||||
		{CC_ALIGN?} \
 | 
			
		||||
		{CEM_F?} {LFLAG?} < >
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -340,6 +340,28 @@ InsertText(text, length)
 | 
			
		|||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define RAWLOAD(dest) \
 | 
			
		||||
	((void)((dest = *_ipp++) || (dest = loadbuf())))
 | 
			
		||||
 | 
			
		||||
/*  Reads the next character, converting CRLF into LF. */
 | 
			
		||||
int
 | 
			
		||||
loadchar(void)
 | 
			
		||||
{
 | 
			
		||||
	int ch;
 | 
			
		||||
	RAWLOAD(ch);
 | 
			
		||||
	if (ch == '\r')
 | 
			
		||||
	{
 | 
			
		||||
		RAWLOAD(ch);
 | 
			
		||||
		if (ch != '\n')
 | 
			
		||||
		{
 | 
			
		||||
			/* Oops, this isn't a CRLF; put back the char we just read. */
 | 
			
		||||
			ChPushBack(ch);
 | 
			
		||||
		}
 | 
			
		||||
		ch = '\n';
 | 
			
		||||
	}
 | 
			
		||||
	return ch;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*	loadbuf() is called if LoadChar meets a '\0' character
 | 
			
		||||
	which may be the end-of-buffer mark of the current input
 | 
			
		||||
	buffer.  The '\0' could be genuine although not likely.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@
 | 
			
		|||
 | 
			
		||||
/* INPUT PRIMITIVES */
 | 
			
		||||
 | 
			
		||||
#define	LoadChar(dest)	((void)((dest = *_ipp++) || (dest = loadbuf())))
 | 
			
		||||
#define	LoadChar(dest)	(dest = loadchar())
 | 
			
		||||
#define	PushBack()	(--_ipp)
 | 
			
		||||
#define ChPushBack(ch)	(*--_ipp = (ch))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
 | 
			
		||||
extern char *_ipp;
 | 
			
		||||
 | 
			
		||||
_PROTOTYPE(int loadchar, (void));
 | 
			
		||||
_PROTOTYPE(int loadbuf, (void));
 | 
			
		||||
_PROTOTYPE(int AtEoIT, (void));
 | 
			
		||||
_PROTOTYPE(int AtEoIF, (void));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,14 @@ struct timeb {			/* non-existing; we use an ad-hoc definition */
 | 
			
		|||
#include	"warn.h"
 | 
			
		||||
#include	"mem.h"
 | 
			
		||||
 | 
			
		||||
/* Detect supported system calls. */
 | 
			
		||||
 | 
			
		||||
#if !defined __CYGWIN__
 | 
			
		||||
#define HAS_ACCT 1
 | 
			
		||||
#else
 | 
			
		||||
#define HAS_ACCT 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define	INPUT		0
 | 
			
		||||
#define	OUTPUT		1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -914,15 +922,22 @@ moncall()
 | 
			
		|||
	case 51:			/* Acct */
 | 
			
		||||
 | 
			
		||||
		dsp1 = pop_ptr();
 | 
			
		||||
		if (!savestr(0, dsp1) || acct(buf[0]) == -1) {
 | 
			
		||||
		#if HAS_ACCT
 | 
			
		||||
			if (!savestr(0, dsp1) || acct(buf[0]) == -1) {
 | 
			
		||||
				push_err();
 | 
			
		||||
				LOG(("@m4 Acct: failed, dsp1 = %lu, errno = %d",
 | 
			
		||||
					dsp1, errno));
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				push_int(0);
 | 
			
		||||
				LOG(("@m9 Acct: succeeded, dsp1 = %lu", dsp1));
 | 
			
		||||
			}
 | 
			
		||||
		#else
 | 
			
		||||
			einval(WMPXIMP);
 | 
			
		||||
			push_err();
 | 
			
		||||
			LOG(("@m4 Acct: failed, dsp1 = %lu, errno = %d",
 | 
			
		||||
				dsp1, errno));
 | 
			
		||||
		}
 | 
			
		||||
		else {
 | 
			
		||||
			push_int(0);
 | 
			
		||||
			LOG(("@m9 Acct: succeeded, dsp1 = %lu", dsp1));
 | 
			
		||||
		}
 | 
			
		||||
			LOG(("@m4 Acct: failed, request = %d, dsp1 = %lu, errno = %d",
 | 
			
		||||
				request, dsp1, errno));
 | 
			
		||||
		#endif
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case 54:			/* Ioctl */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue