456 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			456 lines
		
	
	
	
		
			8.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
 | 
						|
 * See the copyright notice in the ACK home directory, in the file "Copyright".
 | 
						|
 */
 | 
						|
/* $Header$ */
 | 
						|
/* PREPROCESSOR DRIVER */
 | 
						|
 | 
						|
#include	<system.h>
 | 
						|
#include	<alloc.h>
 | 
						|
#include	"input.h"
 | 
						|
#include	"obufsize.h"
 | 
						|
#include	"arith.h"
 | 
						|
#include	"LLlex.h"
 | 
						|
#include	"class.h"
 | 
						|
#include	"macro.h"
 | 
						|
#include	"idf.h"
 | 
						|
#include	"idfsize.h"
 | 
						|
#include	"bits.h"
 | 
						|
#include	"ln_prefix.h"
 | 
						|
#include	"textsize.h"
 | 
						|
 | 
						|
char	_obuf[OBUFSIZE];
 | 
						|
#ifdef DOBITS
 | 
						|
char	bits[128];
 | 
						|
#endif
 | 
						|
extern int InputLevel;
 | 
						|
 | 
						|
Xflush()
 | 
						|
{
 | 
						|
	sys_write(STDOUT, _obuf, OBUFSIZE);
 | 
						|
}
 | 
						|
 | 
						|
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;
 | 
						|
};
 | 
						|
static struct prag_info *pragma_tab;
 | 
						|
static int pragma_nr;
 | 
						|
 | 
						|
do_pragma()
 | 
						|
{
 | 
						|
	register int size = ITEXTSIZE;
 | 
						|
	char *cur_line = Malloc(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) {
 | 
						|
			cur_line = Realloc(cur_line, (unsigned)(size + ITEXTSIZE));
 | 
						|
			c_ptr = cur_line + size - 1;
 | 
						|
			size += ITEXTSIZE;
 | 
						|
		}
 | 
						|
		if (delim) {
 | 
						|
			if (c == delim) {
 | 
						|
				delim = 0;
 | 
						|
			}
 | 
						|
			else if (c == '\\') {
 | 
						|
				*c_ptr++ = c;
 | 
						|
				c = GetChar();
 | 
						|
				if (c == '\n') break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else if (c == '\'' || c == '"') {
 | 
						|
			delim = c;
 | 
						|
		}
 | 
						|
		else if (c == '/') {
 | 
						|
			if ((c = GetChar()) != '*' || InputLevel) {
 | 
						|
				*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 (delim) {
 | 
						|
		error("unclosed opening %c", delim);
 | 
						|
	}
 | 
						|
	pragma_tab[pragma_nr].pr_linnr = LineNumber;
 | 
						|
	pragma_tab[pragma_nr].pr_fil = FileName;
 | 
						|
	pragma_tab[pragma_nr].pr_text = cur_line;
 | 
						|
	pragma_nr++;
 | 
						|
	LineNumber++;
 | 
						|
}
 | 
						|
 | 
						|
char Xbuf[256];
 | 
						|
 | 
						|
preprocess(fn)
 | 
						|
	char *fn;
 | 
						|
{
 | 
						|
	register int c;
 | 
						|
	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')
 | 
						|
 | 
						|
	if (!options['P']) {
 | 
						|
		/* Generate a line directive communicating the
 | 
						|
		   source filename
 | 
						|
		*/
 | 
						|
		register char *p = Xbuf;
 | 
						|
 | 
						|
		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,			\
 | 
						|
					LineNumber,			\
 | 
						|
					FileName);			\
 | 
						|
				op--;					\
 | 
						|
				while (op >= _obuf			\
 | 
						|
				       && (class(*op) == STSKIP		\
 | 
						|
					   || *op == '\n')) op--;	\
 | 
						|
				op++;					\
 | 
						|
				newline();				\
 | 
						|
				while (*p) {				\
 | 
						|
					echo(*p++);			\
 | 
						|
				}					\
 | 
						|
			}						\
 | 
						|
		}
 | 
						|
 | 
						|
	for (;;) {
 | 
						|
		LineNumber++;
 | 
						|
		lineno++;
 | 
						|
		startline = 1;
 | 
						|
		c = GetChar();
 | 
						|
		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++;
 | 
						|
			}
 | 
						|
			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;
 | 
						|
				}
 | 
						|
				UnGetChar();
 | 
						|
				c = '/';
 | 
						|
			    }
 | 
						|
			    break;
 | 
						|
			}
 | 
						|
			echo(c);
 | 
						|
			c = GetChar();
 | 
						|
		    }
 | 
						|
 | 
						|
		    if (c == '#') {
 | 
						|
			domacro();
 | 
						|
			lineno++;
 | 
						|
			newline();
 | 
						|
			c = GetChar();
 | 
						|
		    } else startline = 0;
 | 
						|
		}
 | 
						|
		do_line_dir(lineno, fn);
 | 
						|
		for (;;) {
 | 
						|
 | 
						|
			/* illegal character */
 | 
						|
			if (c & 0200)  {
 | 
						|
				if (c == EOI) {
 | 
						|
					newline();
 | 
						|
					flush((int)(op-_obuf));
 | 
						|
					return;
 | 
						|
				}
 | 
						|
				fatal("non-ascii character read");
 | 
						|
			}
 | 
						|
 | 
						|
			/* comments */
 | 
						|
			if (c == '/' && !InputLevel) {
 | 
						|
				c = GetChar();
 | 
						|
				if (c == '*') {
 | 
						|
					op = SkipComment(op, &lineno);
 | 
						|
					if (!op) return;
 | 
						|
					if (!options['C']) { echo(' '); }
 | 
						|
					c = GetChar();
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				echo('/');
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			/* switch on character */
 | 
						|
			switch(class(c)) {
 | 
						|
			case STNL:
 | 
						|
				newline();
 | 
						|
				break;
 | 
						|
			case STSTR:
 | 
						|
			case STCHAR:
 | 
						|
				{
 | 
						|
				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 == '\\') {
 | 
						|
						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 == '.') {
 | 
						|
					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;
 | 
						|
					}
 | 
						|
					tg = buf;
 | 
						|
					while (*tg) {
 | 
						|
						echo(*tg++);
 | 
						|
					}
 | 
						|
					c = GetChar();
 | 
						|
					if (in_idf(c)) { echo(' '); }
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
			nomac:
 | 
						|
				*tg = '\0';
 | 
						|
				tg = buf;
 | 
						|
				while (*tg) {
 | 
						|
					echo(*tg++);
 | 
						|
				}
 | 
						|
				c = GetChar();
 | 
						|
				while (in_idf(c)) {
 | 
						|
					echo(c);
 | 
						|
					c = GetChar();
 | 
						|
				}
 | 
						|
				continue;
 | 
						|
				}
 | 
						|
			case STMSPEC:
 | 
						|
				if (InputLevel) {
 | 
						|
					echo(' ');	/* seperate tokens */
 | 
						|
					c = GetChar();
 | 
						|
					continue;
 | 
						|
				}
 | 
						|
				/* else fallthrough */
 | 
						|
			default:
 | 
						|
			    	echo(c);
 | 
						|
			    	c = GetChar();
 | 
						|
			    	continue;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	/*NOTREACHED*/
 | 
						|
}
 | 
						|
 | 
						|
static char *
 | 
						|
SkipComment(op, lineno)
 | 
						|
char *op;
 | 
						|
int *lineno;
 | 
						|
{
 | 
						|
	char *ob = &_obuf[OBUFSIZE];
 | 
						|
	register int c, oldc = '\0';
 | 
						|
 | 
						|
	NoUnstack++;
 | 
						|
	if (options['C']) {
 | 
						|
		echo('/');
 | 
						|
		echo('*');
 | 
						|
	}
 | 
						|
	c = GetChar();
 | 
						|
	for(;;) {
 | 
						|
		if (c == EOI) {
 | 
						|
			newline();
 | 
						|
			flush((int)(op - _obuf));
 | 
						|
			op = 0;
 | 
						|
			break;
 | 
						|
		}
 | 
						|
		if (options['C']) {
 | 
						|
			echo(c);
 | 
						|
		}
 | 
						|
		if (c == '\n') {
 | 
						|
			++LineNumber;
 | 
						|
			++*lineno;
 | 
						|
			if (!options['C']) {
 | 
						|
				echo(c);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (c == '*') {
 | 
						|
			c = GetChar();
 | 
						|
			if (c == '/') {
 | 
						|
				if (options['C']) {
 | 
						|
					echo(c);
 | 
						|
				}
 | 
						|
				break;			/* for(;;) */
 | 
						|
			} else if (oldc == '/') {
 | 
						|
				warning("comment inside comment ?");
 | 
						|
			}
 | 
						|
			oldc = '*';
 | 
						|
		} else {
 | 
						|
			oldc = c;
 | 
						|
			c = GetChar();
 | 
						|
		}
 | 
						|
	}
 | 
						|
	NoUnstack--;
 | 
						|
	return op;
 | 
						|
}
 |