Initial revision
This commit is contained in:
		
							parent
							
								
									ba8482c5ab
								
							
						
					
					
						commit
						1d37165575
					
				
					 35 changed files with 4101 additions and 0 deletions
				
			
		
							
								
								
									
										549
									
								
								lang/cem/cpp.ansi/LLlex.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										549
									
								
								lang/cem/cpp.ansi/LLlex.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,549 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /*		    L E X I C A L   A N A L Y Z E R			*/ | ||||||
|  | 
 | ||||||
|  | #include	"idfsize.h" | ||||||
|  | #include	"numsize.h" | ||||||
|  | #include	"strsize.h" | ||||||
|  | 
 | ||||||
|  | #include	<alloc.h> | ||||||
|  | #include	"input.h" | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"macro.h" | ||||||
|  | #include	"idf.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | #include	"Lpars.h" | ||||||
|  | #include	"class.h" | ||||||
|  | #include	"bits.h" | ||||||
|  | 
 | ||||||
|  | #define	BUFSIZ	1024 | ||||||
|  | 
 | ||||||
|  | struct token dot; | ||||||
|  | 
 | ||||||
|  | int ReplaceMacros = 1;		/* replacing macros			*/ | ||||||
|  | int AccDefined = 0;		/* accept "defined(...)"		*/ | ||||||
|  | int UnknownIdIsZero = 0;	/* interpret unknown id as integer 0	*/ | ||||||
|  | int Unstacked = 0;		/* an unstack is done			*/ | ||||||
|  | int AccFileSpecifier = 0;	/* return filespecifier <...>		*/ | ||||||
|  | int LexSave = 0;                /* last character read by GetChar       */ | ||||||
|  | extern int InputLevel;		/* # of current macro expansions	*/ | ||||||
|  | 
 | ||||||
|  | char	*string_token(); | ||||||
|  | arith	char_constant(); | ||||||
|  | #define		FLG_ESEEN	0x01	/* possibly a floating point number */ | ||||||
|  | #define		FLG_DOTSEEN	0x02	/* certainly a floating point number */ | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | LLlex() | ||||||
|  | { | ||||||
|  | 	return (DOT != EOF) ? GetToken(&dot) : EOF; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | GetToken(ptok) | ||||||
|  | 	register struct token *ptok; | ||||||
|  | { | ||||||
|  | 	/*	GetToken() is the actual token recognizer. It calls the
 | ||||||
|  | 		control line interpreter if it encounters a "\n{w}*#" | ||||||
|  | 		combination. Macro replacement is also performed if it is | ||||||
|  | 		needed. | ||||||
|  | 	*/ | ||||||
|  | 	char buf[BUFSIZ]; | ||||||
|  | 	register int ch, nch; | ||||||
|  | 
 | ||||||
|  | again:	/* rescan the input after an error or replacement	*/ | ||||||
|  | 	ch = GetChar(); | ||||||
|  | go_on:	/* rescan, the following character has been read	*/ | ||||||
|  | 	if ((ch & 0200) && ch != EOI) /* stop on non-ascii character */ | ||||||
|  | 		fatal("non-ascii '\\%03o' read", ch & 0377); | ||||||
|  | 	/* keep track of the place of the token in the file	*/ | ||||||
|  | 
 | ||||||
|  | 	switch (class(ch)) {	/* detect character class	*/ | ||||||
|  | 	case STNL:		/* newline, vertical space or formfeed	*/ | ||||||
|  | 		LineNumber++; | ||||||
|  | 		return ptok->tk_symb = EOF; | ||||||
|  | 	case STSKIP:		/* just skip the skip characters	*/ | ||||||
|  | 		goto again; | ||||||
|  | 	case STGARB:		/* garbage character			*/ | ||||||
|  | garbage: | ||||||
|  | 		if (040 < ch && ch < 0177) | ||||||
|  | 			error("garbage char %c", ch); | ||||||
|  | 		else | ||||||
|  | 			error("garbage char \\%03o", ch); | ||||||
|  | 		goto again; | ||||||
|  | 	case STSIMP:	/* a simple character, no part of compound token*/ | ||||||
|  | 		return ptok->tk_symb = ch; | ||||||
|  | 	case STCOMP:	/* maybe the start of a compound token		*/ | ||||||
|  | 		nch = GetChar();		/* character lookahead	*/ | ||||||
|  | 		switch (ch) { | ||||||
|  | 		case '!': | ||||||
|  | 			if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = NOTEQUAL; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '&': | ||||||
|  | 			if (nch == '&') | ||||||
|  | 				return ptok->tk_symb = AND; | ||||||
|  | 			else if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = ANDAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '+': | ||||||
|  | 			if (nch == '+') | ||||||
|  | 				return ptok->tk_symb = PLUSPLUS; | ||||||
|  | 			else if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = PLUSAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '-': | ||||||
|  | 			if (nch == '-') | ||||||
|  | 				return ptok->tk_symb = MINMIN; | ||||||
|  | 			else if (nch == '>') | ||||||
|  | 				return ptok->tk_symb = ARROW; | ||||||
|  | 			else if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = MINAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '<': | ||||||
|  | 			if (AccFileSpecifier) { | ||||||
|  | 				UnGetChar();	/* pushback nch */ | ||||||
|  | 				ptok->tk_str = | ||||||
|  | 					string_token("file specifier", '>'); | ||||||
|  | 				return ptok->tk_symb = FILESPECIFIER; | ||||||
|  | 			} else if (nch == '<') { | ||||||
|  | 				if ((nch = GetChar()) == '=') | ||||||
|  | 					return ptok->tk_symb = LEFTAB; | ||||||
|  | 				UnGetChar(); | ||||||
|  | 				return ptok->tk_symb = LEFT; | ||||||
|  | 			} else if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = LESSEQ; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '=': | ||||||
|  | 			if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = EQUAL; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '>': | ||||||
|  | 			if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = GREATEREQ; | ||||||
|  | 			else if (nch == '>') { | ||||||
|  | 				if ((nch = GetChar()) == '=') | ||||||
|  | 					return ptok->tk_symb = RIGHTAB; | ||||||
|  | 				UnGetChar(); | ||||||
|  | 				return ptok->tk_symb = RIGHT; | ||||||
|  | 			} | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '|': | ||||||
|  | 			if (nch == '|') | ||||||
|  | 				return ptok->tk_symb = OR; | ||||||
|  | 			else if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = ORAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '%': | ||||||
|  | 			if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = MODAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '*': | ||||||
|  | 			if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = TIMESAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '^': | ||||||
|  | 			if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = XORAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		case '/': | ||||||
|  | 			if (nch == '*' && !InputLevel) { | ||||||
|  | 				skipcomment(); | ||||||
|  | 				goto again; | ||||||
|  | 			} | ||||||
|  | 			else if (nch == '=') | ||||||
|  | 				return ptok->tk_symb = DIVAB; | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		default: | ||||||
|  | 			crash("bad class for char 0%o", ch); | ||||||
|  | 			/* NOTREACHED */ | ||||||
|  | 		} | ||||||
|  | 	case STCHAR:				/* character constant	*/ | ||||||
|  | 		ptok->tk_val = char_constant("character"); | ||||||
|  | 		return ptok->tk_symb = INTEGER; | ||||||
|  | 	case STSTR:					/* string	*/ | ||||||
|  | 		ptok->tk_str = string_token("string", '"'); | ||||||
|  | 		return ptok->tk_symb = STRING; | ||||||
|  | 	case STELL:		/* wide character constant/string prefix */ | ||||||
|  | 		nch = GetChar(); | ||||||
|  | 		if (nch == '"') { | ||||||
|  | 			ptok->tk_str = | ||||||
|  | 				string_token("wide character string", '"'); | ||||||
|  | 			return ptok->tk_symb = STRING; | ||||||
|  | 		} else if (nch == '\'') { | ||||||
|  | 			ptok->tk_val = char_constant("wide character"); | ||||||
|  | 			return ptok->tk_symb = INTEGER; | ||||||
|  | 		} | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		/* fallthrough */ | ||||||
|  | 	case STIDF: | ||||||
|  | 	{ | ||||||
|  | 		extern int idfsize;		/* ??? */ | ||||||
|  | 		register char *tg = &buf[0]; | ||||||
|  | 		register char *maxpos = &buf[idfsize]; | ||||||
|  | 		int NoExpandNext = 0; | ||||||
|  | 
 | ||||||
|  | #define tstmac(bx)	if (!(bits[ch] & bx)) goto nomac | ||||||
|  | #define cpy		*tg++ = ch | ||||||
|  | #define load		(ch = GetChar()); if (!in_idf(ch)) goto endidf | ||||||
|  | 
 | ||||||
|  | 		if (Unstacked) EnableMacros();  /* unstack macro's when allowed. */ | ||||||
|  | 		if (ch == NOEXPM)  { | ||||||
|  | 			NoExpandNext = 1; | ||||||
|  | 			ch = 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 (ch != EOI) UnGetChar();*/ | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		*tg++ = '\0';	/* mark the end of the identifier	*/ | ||||||
|  | 		if (ReplaceMacros) { | ||||||
|  | 			register struct idf *idef = findidf(buf); | ||||||
|  | 
 | ||||||
|  | 			if (idef && idef->id_macro && !NoExpandNext) { | ||||||
|  | 				if (replace(idef)) | ||||||
|  | 					goto again; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	nomac:			/* buf can already be null-terminated. soit */ | ||||||
|  | 		ch = GetChar(); | ||||||
|  | 		while (in_idf(ch)) { | ||||||
|  | 			if (tg < maxpos) *tg++ = ch; | ||||||
|  | 			ch = GetChar(); | ||||||
|  | 		} | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		*tg++ = '\0';   /* mark the end of the identifier       */ | ||||||
|  | 
 | ||||||
|  | 		NoExpandNext = 0; | ||||||
|  | 		if (UnknownIdIsZero) { | ||||||
|  | 			ptok->tk_val = (arith)0; | ||||||
|  | 			return ptok->tk_symb = INTEGER; | ||||||
|  | 		} | ||||||
|  | 		ptok->tk_str = Malloc(tg - buf); | ||||||
|  | 		strcpy(ptok->tk_str, buf); | ||||||
|  | 		return IDENTIFIER; | ||||||
|  | 	} | ||||||
|  | 	case STNUM:				/* a numeric constant	*/ | ||||||
|  | 	{			/* it may only be an integer constant */ | ||||||
|  | 		register int base = 10, val = 0, vch; | ||||||
|  | 
 | ||||||
|  | 		/* Since the preprocessor only knows integers and has
 | ||||||
|  | 		 * nothing to do with ellipsis we just return when the | ||||||
|  | 		 * pp-number starts with a '.' | ||||||
|  | 		 */ | ||||||
|  | 		if (ch == '.') { | ||||||
|  | 			return ptok->tk_symb = ch; | ||||||
|  | 		} | ||||||
|  | 		if (ch == '0') { | ||||||
|  | 			ch = GetChar(); | ||||||
|  | 			if (ch == 'x' || ch == 'X') { | ||||||
|  | 				base = 16; | ||||||
|  | 				ch = GetChar(); | ||||||
|  | 			} else { | ||||||
|  | 				base = 8; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 		} | ||||||
|  | 		while ((vch = val_in_base(ch, base)) >= 0) { | ||||||
|  | 			val = val * base + vch;		/* overflow? nah */ | ||||||
|  | 			ch = GetChar(); | ||||||
|  | 		} | ||||||
|  | 		while (ch == 'l' || ch == 'L' || ch == 'u' || ch == 'U') | ||||||
|  | 			ch = GetChar(); | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		ptok->tk_val = val; | ||||||
|  | 		return ptok->tk_symb = INTEGER; | ||||||
|  | 	} | ||||||
|  | 	case STEOI:			/* end of text on source file	*/ | ||||||
|  | 		return ptok->tk_symb = EOF; | ||||||
|  |         case STMSPEC: | ||||||
|  | 		if (!InputLevel) goto garbage; | ||||||
|  | 		if (ch == TOKSEP) goto again; | ||||||
|  | 		/* fallthrough shouldn't happen */ | ||||||
|  | 	default:				/* this cannot happen	*/ | ||||||
|  | 		crash("bad class for char 0%o", ch); | ||||||
|  | 	} | ||||||
|  | 	/*NOTREACHED*/ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | skipcomment() | ||||||
|  | { | ||||||
|  | 	/*	The last character read has been the '*' of '/_*'.  The
 | ||||||
|  | 		characters, except NL and EOI, between '/_*' and the first | ||||||
|  | 		occurring '*_/' are not interpreted. | ||||||
|  | 		NL only affects the LineNumber.  EOI is not legal. | ||||||
|  | 
 | ||||||
|  | 		Important note: it is not possible to stop skipping comment | ||||||
|  | 		beyond the end-of-file of an included file. | ||||||
|  | 		EOI is returned by LoadChar only on encountering EOF of the | ||||||
|  | 		top-level file... | ||||||
|  | 	*/ | ||||||
|  | 	register int c; | ||||||
|  | 
 | ||||||
|  | 	NoUnstack++; | ||||||
|  | 	c = GetChar(); | ||||||
|  | 	do { | ||||||
|  | 		while (c != '*') { | ||||||
|  | 			if (class(c) == STNL) { | ||||||
|  | 				++LineNumber; | ||||||
|  | 			} else if (c == EOI) { | ||||||
|  | 				NoUnstack--; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			c = GetChar(); | ||||||
|  | 		} /* last Character seen was '*' */ | ||||||
|  | 		c = GetChar(); | ||||||
|  | 	} while (c != '/'); | ||||||
|  | 	NoUnstack--; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | arith | ||||||
|  | char_constant(nm) | ||||||
|  | 	char *nm; | ||||||
|  | { | ||||||
|  | 	register arith val = 0; | ||||||
|  | 	register int ch; | ||||||
|  | 	int size = 0; | ||||||
|  | 
 | ||||||
|  | 	ch = GetChar(); | ||||||
|  | 	if (ch == '\'') | ||||||
|  | 		error("%s constant too short", nm); | ||||||
|  | 	else | ||||||
|  | 	while (ch != '\'') { | ||||||
|  | 		if (ch == '\n') { | ||||||
|  | 			error("newline in %s constant", nm); | ||||||
|  | 			LineNumber++; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (ch == '\\') | ||||||
|  | 			ch = quoted(GetChar()); | ||||||
|  | 		if (ch >= 128) ch -= 256; | ||||||
|  | 		if (size < (int)size) | ||||||
|  | 			val |= ch << 8 * size; | ||||||
|  | 		size++; | ||||||
|  | 		ch = GetChar(); | ||||||
|  | 	} | ||||||
|  | 	if (size > 1) | ||||||
|  | 		strict("%s constant includes more than one character", nm); | ||||||
|  | 	if (size > sizeof(arith)) | ||||||
|  | 		error("%s constant too long", nm); | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | string_token(nm, stop_char) | ||||||
|  | 	char *nm; | ||||||
|  | { | ||||||
|  | 	register int ch; | ||||||
|  | 	register int str_size; | ||||||
|  | 	register char *str = Malloc((unsigned) (str_size = ISTRSIZE)); | ||||||
|  | 	register int pos = 0; | ||||||
|  | 	 | ||||||
|  | 	ch = GetChar(); | ||||||
|  | 	while (ch != stop_char) { | ||||||
|  | 		if (ch == '\n') { | ||||||
|  | 			error("newline in %s", nm); | ||||||
|  | 			LineNumber++; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (ch == EOI) { | ||||||
|  | 			error("end-of-file inside %s", nm); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		if (ch == '\\' && !AccFileSpecifier) | ||||||
|  | 			ch = quoted(GetChar()); | ||||||
|  | 		str[pos++] = ch; | ||||||
|  | 		if (pos == str_size) | ||||||
|  | 			str = Realloc(str, str_size <<= 1); | ||||||
|  | 		ch = GetChar(); | ||||||
|  | 	} | ||||||
|  | 	str[pos++] = '\0'; /* for filenames etc. */ | ||||||
|  | 	str = Realloc(str, pos); | ||||||
|  | 	return str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | quoted(ch) | ||||||
|  | 	register int ch; | ||||||
|  | {	 | ||||||
|  | 	/*	quoted() replaces an escaped character sequence by the
 | ||||||
|  | 		character meant. | ||||||
|  | 	*/ | ||||||
|  | 	/* first char after backslash already in ch */ | ||||||
|  | 	if (!is_oct(ch)) {		/* a quoted char */ | ||||||
|  | 		switch (ch) { | ||||||
|  | 		case 'n': | ||||||
|  | 			ch = '\n'; | ||||||
|  | 			break; | ||||||
|  | 		case 't': | ||||||
|  | 			ch = '\t'; | ||||||
|  | 			break; | ||||||
|  | 		case 'b': | ||||||
|  | 			ch = '\b'; | ||||||
|  | 			break; | ||||||
|  | 		case 'r': | ||||||
|  | 			ch = '\r'; | ||||||
|  | 			break; | ||||||
|  | 		case 'f': | ||||||
|  | 			ch = '\f'; | ||||||
|  | 			break; | ||||||
|  | 		case 'a':		/* alert */ | ||||||
|  | 			ch = '\007'; | ||||||
|  | 			break; | ||||||
|  | 		case 'v':		/* vertical tab */ | ||||||
|  | 			ch = '\013'; | ||||||
|  | 			break; | ||||||
|  | 		case 'x':		/* quoted hex */ | ||||||
|  | 		{ | ||||||
|  | 			register int hex = 0; | ||||||
|  | 			register int vch; | ||||||
|  | 
 | ||||||
|  | 			for (;;) { | ||||||
|  | 				ch = GetChar(); | ||||||
|  | 				if (vch = val_in_base(ch, 16), vch == -1) | ||||||
|  | 					break; | ||||||
|  | 				hex = hex * 16 + vch; | ||||||
|  | 			} | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			ch = hex; | ||||||
|  | 		} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	else {				/* a quoted octal */ | ||||||
|  | 		register int oct = 0, cnt = 0; | ||||||
|  | 
 | ||||||
|  | 		do { | ||||||
|  | 			oct = oct*8 + (ch-'0'); | ||||||
|  | 			ch = GetChar(); | ||||||
|  | 		} while (is_oct(ch) && ++cnt < 3); | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		ch = oct; | ||||||
|  | 	} | ||||||
|  | 	return ch&0377; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | val_in_base(ch, base) | ||||||
|  | 	register int ch; | ||||||
|  | { | ||||||
|  | 	switch (base) { | ||||||
|  | 	case 8: | ||||||
|  | 		return (is_dig(ch) && ch < '9') ? ch - '0' : -1; | ||||||
|  | 	case 10: | ||||||
|  | 		return is_dig(ch) ? ch - '0' : -1; | ||||||
|  | 	case 16: | ||||||
|  | 		return is_dig(ch) ? ch - '0' | ||||||
|  | 			: is_hex(ch) ? (ch - 'a' + 10) & 017 | ||||||
|  | 			: -1; | ||||||
|  | 	default: | ||||||
|  | 		fatal("(val_in_base) illegal base value %d", base); | ||||||
|  | 		/* NOTREACHED */ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | GetChar() | ||||||
|  | { | ||||||
|  | 	/*	The routines GetChar and trigraph parses the trigraph
 | ||||||
|  | 		sequences and removes occurences of \\\n. | ||||||
|  | 	*/ | ||||||
|  | 	register int ch; | ||||||
|  | 
 | ||||||
|  | again: | ||||||
|  | 	LoadChar(ch); | ||||||
|  | 
 | ||||||
|  | 	/* possible trigraph sequence */ | ||||||
|  | 	if (ch == '?') | ||||||
|  | 		ch = trigraph(); | ||||||
|  | 
 | ||||||
|  | 	/* \\\n are removed from the input stream */ | ||||||
|  | 	if (ch == '\\') { | ||||||
|  | 		LoadChar(ch); | ||||||
|  | 		if (ch == '\n') { | ||||||
|  | 			++LineNumber; | ||||||
|  | 			goto again; | ||||||
|  | 		} | ||||||
|  | 		PushBack(); | ||||||
|  | 		ch = '\\'; | ||||||
|  | 	} | ||||||
|  | 	return(LexSave = ch); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | trigraph() | ||||||
|  | { | ||||||
|  | 	register int ch; | ||||||
|  | 
 | ||||||
|  | 	LoadChar(ch); | ||||||
|  | 	if (ch == '?') { | ||||||
|  | 		LoadChar(ch); | ||||||
|  | 		switch (ch) {		/* its a trigraph */ | ||||||
|  | 		case '=': | ||||||
|  | 			ch =  '#'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '(': | ||||||
|  | 			ch = '['; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '/': | ||||||
|  | 			ch = '\\'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case ')': | ||||||
|  | 			ch = ']'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '\'': | ||||||
|  | 			ch = '^'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '<': | ||||||
|  | 			ch = '{'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '!': | ||||||
|  | 			ch = '|'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '>': | ||||||
|  | 			ch = '}'; | ||||||
|  | 			return(ch); | ||||||
|  | 		case '-': | ||||||
|  | 			ch = '~'; | ||||||
|  | 			return(ch); | ||||||
|  | 		} | ||||||
|  | 		PushBack(); | ||||||
|  | 	} | ||||||
|  | 	PushBack(); | ||||||
|  | 	return('?'); | ||||||
|  | } | ||||||
							
								
								
									
										42
									
								
								lang/cem/cpp.ansi/LLlex.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								lang/cem/cpp.ansi/LLlex.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,42 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* D E F I N I T I O N S   F O R   T H E   L E X I C A L   A N A L Y Z E R */ | ||||||
|  | 
 | ||||||
|  | /*	A token from the input stream is represented by an integer,
 | ||||||
|  | 	called a "symbol", but it may have other information associated | ||||||
|  | 	to it. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /* the structure of a token:	*/ | ||||||
|  | struct token	{ | ||||||
|  | 	int tok_symb;		/* the token itself */ | ||||||
|  | 	union	{ | ||||||
|  | 		char *tok_str; | ||||||
|  | 		arith tok_val;		/* for INTEGER */ | ||||||
|  | 	} tok_data; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #include "file_info.h" | ||||||
|  | 
 | ||||||
|  | #define tk_symb	tok_symb | ||||||
|  | #define tk_str	tok_data.tok_str | ||||||
|  | #define tk_val	tok_data.tok_val | ||||||
|  | 
 | ||||||
|  | extern struct token dot; | ||||||
|  | 
 | ||||||
|  | extern int ReplaceMacros;	/* "LLlex.c"	*/ | ||||||
|  | extern int AccDefined;		/* "LLlex.c"	*/ | ||||||
|  | extern int Unstacked;		/* "LLlex.c"	*/ | ||||||
|  | extern int UnknownIdIsZero;	/* "LLlex.c"	*/ | ||||||
|  | extern int AccFileSpecifier;    /* "LLlex.c"    */ | ||||||
|  | 
 | ||||||
|  | extern int NoUnstack;		/* buffer.c	*/ | ||||||
|  | 
 | ||||||
|  | extern int err_occurred;	/* "error.c"	*/ | ||||||
|  | 
 | ||||||
|  | #define	DOT	dot.tk_symb | ||||||
|  | 
 | ||||||
|  | #define EOF	(-1) | ||||||
							
								
								
									
										25
									
								
								lang/cem/cpp.ansi/LLmessage.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lang/cem/cpp.ansi/LLmessage.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /*		PARSER ERROR ADMINISTRATION		*/ | ||||||
|  | 
 | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | #include	"Lpars.h" | ||||||
|  | 
 | ||||||
|  | extern char *symbol2str(); | ||||||
|  | 
 | ||||||
|  | LLmessage(tk)	{ | ||||||
|  | 	err_occurred = 1; | ||||||
|  | 	if (tk < 0) | ||||||
|  | 		error("garbage at end of line"); | ||||||
|  | 	else if (tk)	{ | ||||||
|  | 		error("%s missing", symbol2str(tk)); | ||||||
|  | 		if (DOT != EOF) SkipToNewLine(0); | ||||||
|  | 		DOT = EOF; | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		error("%s deleted", symbol2str(DOT)); | ||||||
|  | } | ||||||
							
								
								
									
										256
									
								
								lang/cem/cpp.ansi/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								lang/cem/cpp.ansi/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,256 @@ | ||||||
|  | # MAKEFILE FOR (STAND_ALONE) CEM PREPROCESSOR
 | ||||||
|  | 
 | ||||||
|  | EMHOME=../../.. | ||||||
|  | MODULES=$(EMHOME)/modules | ||||||
|  | MODULESLIB=$(MODULES)/lib | ||||||
|  | BIN=$(EMHOME)/lib | ||||||
|  | MANDIR=$(EMHOME)/man | ||||||
|  | 
 | ||||||
|  | # Some paths
 | ||||||
|  | 
 | ||||||
|  | # Libraries
 | ||||||
|  | SYSLIB = $(MODULESLIB)/libsystem.a | ||||||
|  | STRLIB = $(MODULESLIB)/libstring.a | ||||||
|  | PRTLIB = $(MODULESLIB)/libprint.a | ||||||
|  | ALLOCLIB = $(MODULESLIB)/liballoc.a | ||||||
|  | ASSERTLIB = $(MODULESLIB)/libassert.a | ||||||
|  | MALLOC = $(MODULESLIB)/malloc.o | ||||||
|  | LIBS = $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(ASSERTLIB) $(SYSLIB) | ||||||
|  | LIB_INCLUDES = -I$(MODULES)/h -I$(MODULES)/pkg | ||||||
|  | 
 | ||||||
|  | # Where to install the preprocessor
 | ||||||
|  | CEMPP = $(BIN)/ncpp | ||||||
|  | 
 | ||||||
|  | TABGEN	= $(EMHOME)/bin/tabgen | ||||||
|  | 
 | ||||||
|  | # What C compiler to use and how
 | ||||||
|  | CC = fcc | ||||||
|  | COPTIONS = | ||||||
|  | LDFLAGS = -i | ||||||
|  | 
 | ||||||
|  | # What parser generator to use and how
 | ||||||
|  | GEN = $(EMHOME)/bin/LLgen | ||||||
|  | GENOPTIONS = | ||||||
|  | 
 | ||||||
|  | # Special #defines during compilation
 | ||||||
|  | CDEFS =	$(LIB_INCLUDES) | ||||||
|  | CFLAGS = $(CDEFS) $(COPTIONS) -O#	# we cannot pass the COPTIONS to lint! | ||||||
|  | 
 | ||||||
|  | # Grammar files and their objects
 | ||||||
|  | LSRC =	tokenfile.g expression.g | ||||||
|  | LCSRC = tokenfile.c expression.c Lpars.c | ||||||
|  | LOBJ =	tokenfile.o expression.o Lpars.o | ||||||
|  | 
 | ||||||
|  | # Objects of hand-written C files
 | ||||||
|  | CSRC =	LLlex.c LLmessage.c ch7bin.c ch7mon.c domacro.c \
 | ||||||
|  | 	error.c idf.c init.c input.c main.c options.c \
 | ||||||
|  | 	preprocess.c replace.c skip.c tokenname.c expr.c | ||||||
|  | COBJ =	LLlex.o LLmessage.o ch7bin.o ch7mon.o domacro.o \
 | ||||||
|  | 	error.o idf.o init.o input.o main.o options.o \
 | ||||||
|  | 	preprocess.o replace.o skip.o tokenname.o next.o expr.o | ||||||
|  | 
 | ||||||
|  | PRFILES = Makefile Parameters \
 | ||||||
|  | 	make.hfiles make.tokcase make.tokfile LLlex.h bits.h file_info.h \
 | ||||||
|  | 	idf.h input.h interface.h macro.str replace.str \
 | ||||||
|  | 	class.h char.tab expression.g $(CSRC) | ||||||
|  | 
 | ||||||
|  | # Objects of other generated C files
 | ||||||
|  | GOBJ =	char.o symbol2str.o | ||||||
|  | 
 | ||||||
|  | # generated source files
 | ||||||
|  | GSRC =	char.c symbol2str.c | ||||||
|  | 
 | ||||||
|  | # .h files generated by `make.allod'
 | ||||||
|  | STRSRC = macro.str replace.str | ||||||
|  | GSTRSRC = macro.h replace.h | ||||||
|  | 
 | ||||||
|  | # .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
 | ||||||
|  | GHSRC =	errout.h idfsize.h ifdepth.h lapbuf.h \
 | ||||||
|  | 	nparams.h numsize.h obufsize.h argbuf.h \
 | ||||||
|  | 	parbufsize.h pathlength.h strsize.h textsize.h \
 | ||||||
|  | 	botch_free.h debug.h inputtype.h dobits.h line_prefix.h | ||||||
|  | 
 | ||||||
|  | # Other generated files, for 'make clean' only
 | ||||||
|  | GENERATED = tokenfile.g Lpars.h LLfiles LL.output lint.out \
 | ||||||
|  | 	Xref hfiles cfiles next.c tags Makefile.old | ||||||
|  | 
 | ||||||
|  | all:	cc | ||||||
|  | 
 | ||||||
|  | cc:	hfiles LLfiles | ||||||
|  | 	make "EMHOME="$(EMHOME) ncpp | ||||||
|  | 
 | ||||||
|  | hfiles: Parameters char.c | ||||||
|  | 	./make.hfiles Parameters | ||||||
|  | 	@touch hfiles | ||||||
|  | 
 | ||||||
|  | .SUFFIXES: .str .h | ||||||
|  | .str.h: | ||||||
|  | 	./make.allocd <$*.str >$*.h | ||||||
|  | 
 | ||||||
|  | char.c:	char.tab | ||||||
|  | 	$(TABGEN) -fchar.tab > char.c | ||||||
|  | 
 | ||||||
|  | next.c:	make.next $(STRSRC) | ||||||
|  | 	./make.next $(STRSRC) >next.c | ||||||
|  | 
 | ||||||
|  | macro.h:	make.allocd | ||||||
|  | repl.h:		make.allocd | ||||||
|  | 
 | ||||||
|  | LLfiles: $(LSRC) | ||||||
|  | 	$(GEN) $(GENOPTIONS) $(LSRC) | ||||||
|  | 	@touch LLfiles | ||||||
|  | 
 | ||||||
|  | tokenfile.g:	tokenname.c make.tokfile | ||||||
|  | 	<tokenname.c ./make.tokfile >tokenfile.g | ||||||
|  | 
 | ||||||
|  | symbol2str.c:	tokenname.c make.tokcase | ||||||
|  | 	<tokenname.c ./make.tokcase >symbol2str.c | ||||||
|  | 
 | ||||||
|  | # Objects needed for 'ncpp'
 | ||||||
|  | OBJ =	$(COBJ) $(LOBJ) $(GOBJ) | ||||||
|  | SRC =	$(CSRC) $(LCSRC) $(GSRC) | ||||||
|  | 
 | ||||||
|  | ncpp:	$(OBJ) Makefile | ||||||
|  | 	$(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(LIBS) -o ncpp  | ||||||
|  | 	-size ncpp | ||||||
|  | 
 | ||||||
|  | cfiles: hfiles LLfiles $(GSRC) $(GSTRSRC) | ||||||
|  | 	@touch cfiles | ||||||
|  | 
 | ||||||
|  | install: all | ||||||
|  | 	rm -f $(CEMPP) | ||||||
|  | 	cp ncpp $(CEMPP) | ||||||
|  | 	rm -f $(MANDIR)/ncpp.6 | ||||||
|  | 	cp ncpp.6 $(MANDIR)/ncpp.6 | ||||||
|  | 
 | ||||||
|  | cmp:	all | ||||||
|  | 	-cmp ncpp $(CEMPP) | ||||||
|  | 	-cmp ncpp.6 $(MANDIR)/ncpp.6 | ||||||
|  | 
 | ||||||
|  | pr:  | ||||||
|  | 	@pr $(PRFILES) | ||||||
|  | 
 | ||||||
|  | opr: | ||||||
|  | 	make pr | opr | ||||||
|  | 
 | ||||||
|  | tags:	cfiles | ||||||
|  | 	ctags $(SRC) | ||||||
|  | 
 | ||||||
|  | depend:	cfiles | ||||||
|  | 	sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new | ||||||
|  | 	echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>Makefile.new | ||||||
|  | 	$(EMHOME)/bin/mkdep $(SRC) | \
 | ||||||
|  | 		sed 's/\.c:/.o:/' >>Makefile.new | ||||||
|  | 	mv Makefile Makefile.old | ||||||
|  | 	mv Makefile.new Makefile | ||||||
|  | 	 | ||||||
|  | xref: | ||||||
|  | 	ctags -x `grep "\.[ch]" Files`|sed "s/).*/)/">Xref | ||||||
|  | 	 | ||||||
|  | lint:	cfiles | ||||||
|  | 	lint -bx $(CDEFS) $(SRC) >lint.out | ||||||
|  | 
 | ||||||
|  | clean: | ||||||
|  | 	rm -f $(LCSRC) $(OBJ) $(GENERATED) $(GSRC) $(GHSRC) $(GSTRSRC) ncpp Out | ||||||
|  | 
 | ||||||
|  | #AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
 | ||||||
|  | LLlex.o: LLlex.h | ||||||
|  | LLlex.o: Lpars.h | ||||||
|  | LLlex.o: arith.h | ||||||
|  | LLlex.o: bits.h | ||||||
|  | LLlex.o: class.h | ||||||
|  | LLlex.o: dobits.h | ||||||
|  | LLlex.o: file_info.h | ||||||
|  | LLlex.o: idf.h | ||||||
|  | LLlex.o: idfsize.h | ||||||
|  | LLlex.o: input.h | ||||||
|  | LLlex.o: inputtype.h | ||||||
|  | LLlex.o: macro.h | ||||||
|  | LLlex.o: numsize.h | ||||||
|  | LLlex.o: strsize.h | ||||||
|  | LLmessage.o: LLlex.h | ||||||
|  | LLmessage.o: Lpars.h | ||||||
|  | LLmessage.o: file_info.h | ||||||
|  | ch7bin.o: Lpars.h | ||||||
|  | ch7bin.o: arith.h | ||||||
|  | ch7mon.o: Lpars.h | ||||||
|  | ch7mon.o: arith.h | ||||||
|  | domacro.o: LLlex.h | ||||||
|  | domacro.o: Lpars.h | ||||||
|  | domacro.o: arith.h | ||||||
|  | domacro.o: bits.h | ||||||
|  | domacro.o: botch_free.h | ||||||
|  | domacro.o: class.h | ||||||
|  | domacro.o: dobits.h | ||||||
|  | domacro.o: file_info.h | ||||||
|  | domacro.o: idf.h | ||||||
|  | domacro.o: idfsize.h | ||||||
|  | domacro.o: ifdepth.h | ||||||
|  | domacro.o: input.h | ||||||
|  | domacro.o: inputtype.h | ||||||
|  | domacro.o: macro.h | ||||||
|  | domacro.o: nparams.h | ||||||
|  | domacro.o: parbufsize.h | ||||||
|  | domacro.o: textsize.h | ||||||
|  | error.o: LLlex.h | ||||||
|  | error.o: errout.h | ||||||
|  | error.o: file_info.h | ||||||
|  | idf.o: idf.h | ||||||
|  | init.o: class.h | ||||||
|  | init.o: idf.h | ||||||
|  | init.o: macro.h | ||||||
|  | input.o: file_info.h | ||||||
|  | input.o: input.h | ||||||
|  | input.o: inputtype.h | ||||||
|  | main.o: arith.h | ||||||
|  | main.o: file_info.h | ||||||
|  | main.o: idfsize.h | ||||||
|  | options.o: class.h | ||||||
|  | options.o: idf.h | ||||||
|  | options.o: idfsize.h | ||||||
|  | options.o: macro.h | ||||||
|  | preprocess.o: LLlex.h | ||||||
|  | preprocess.o: bits.h | ||||||
|  | preprocess.o: class.h | ||||||
|  | preprocess.o: dobits.h | ||||||
|  | preprocess.o: file_info.h | ||||||
|  | preprocess.o: idf.h | ||||||
|  | preprocess.o: idfsize.h | ||||||
|  | preprocess.o: input.h | ||||||
|  | preprocess.o: inputtype.h | ||||||
|  | preprocess.o: line_prefix.h | ||||||
|  | preprocess.o: macro.h | ||||||
|  | preprocess.o: obufsize.h | ||||||
|  | replace.o: LLlex.h | ||||||
|  | replace.o: argbuf.h | ||||||
|  | replace.o: class.h | ||||||
|  | replace.o: file_info.h | ||||||
|  | replace.o: idf.h | ||||||
|  | replace.o: idfsize.h | ||||||
|  | replace.o: input.h | ||||||
|  | replace.o: inputtype.h | ||||||
|  | replace.o: lapbuf.h | ||||||
|  | replace.o: macro.h | ||||||
|  | replace.o: nparams.h | ||||||
|  | replace.o: numsize.h | ||||||
|  | replace.o: pathlength.h | ||||||
|  | replace.o: replace.h | ||||||
|  | replace.o: strsize.h | ||||||
|  | skip.o: LLlex.h | ||||||
|  | skip.o: class.h | ||||||
|  | skip.o: file_info.h | ||||||
|  | skip.o: input.h | ||||||
|  | skip.o: inputtype.h | ||||||
|  | tokenname.o: LLlex.h | ||||||
|  | tokenname.o: Lpars.h | ||||||
|  | tokenname.o: file_info.h | ||||||
|  | tokenname.o: idf.h | ||||||
|  | expr.o: Lpars.h | ||||||
|  | tokenfile.o: Lpars.h | ||||||
|  | expression.o: LLlex.h | ||||||
|  | expression.o: Lpars.h | ||||||
|  | expression.o: arith.h | ||||||
|  | expression.o: file_info.h | ||||||
|  | Lpars.o: Lpars.h | ||||||
|  | char.o: class.h | ||||||
|  | symbol2str.o: Lpars.h | ||||||
							
								
								
									
										74
									
								
								lang/cem/cpp.ansi/Parameters
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								lang/cem/cpp.ansi/Parameters
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | ||||||
|  | !File: pathlength.h | ||||||
|  | #define PATHLENGTH	1024	/* max. length of path to file		*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: errout.h | ||||||
|  | #define	ERROUT		STDERR	/* file pointer for writing messages	*/ | ||||||
|  | #define	MAXERR_LINE	5	/* maximum number of error messages given | ||||||
|  | 					on the same input line.		*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: idfsize.h | ||||||
|  | #define	IDFSIZE	64	/* maximum significant length of an identifier	*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: numsize.h | ||||||
|  | #define	NUMSIZE	256	/* maximum length of a numeric constant		*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: nparams.h | ||||||
|  | #define	NPARAMS 32	/* maximum number of parameters of macros	*/ | ||||||
|  | #define	STDC_NPARAMS 31	/* ANSI limit on number of parameters		*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: ifdepth.h | ||||||
|  | #define	IFDEPTH	256	/* maximum number of nested if-constructions	*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: lapbuf.h | ||||||
|  | #define	LAPBUF	4096	/* size of macro actual parameter buffer	*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: argbuf.h | ||||||
|  | #define	ARGBUF	2048	/* sizeof of macro actual parameter buffer	*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: strsize.h | ||||||
|  | #define ISTRSIZE	16	/* minimum number of bytes allocated for | ||||||
|  | 					storing a string		*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: botch_free.h | ||||||
|  | #undef BOTCH_FREE	1	/* botch freed memory, as a check	*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: debug.h | ||||||
|  | #define DEBUG		1	/* perform various self-tests		*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: parbufsize.h | ||||||
|  | #define PARBUFSIZE	1024 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: textsize.h | ||||||
|  | #define ITEXTSIZE	16	/* 1st piece of memory for repl. text	*/ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: inputtype.h | ||||||
|  | #undef INP_READ_IN_ONE	1	/* read input file in one.  */ | ||||||
|  | 				/* If defined, we cannot read from a pipe */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: obufsize.h | ||||||
|  | #define OBUFSIZE	8192	/* output buffer size */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: dobits.h | ||||||
|  | #define DOBITS		1	/* use trick to reduce symboltable accesses */ | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | !File: line_prefix.h | ||||||
|  | #define LINE_PREFIX	"#"	/* prefix for generated line directives, | ||||||
|  | 				   either "#" or "#line" | ||||||
|  | 				*/ | ||||||
|  | 
 | ||||||
							
								
								
									
										18
									
								
								lang/cem/cpp.ansi/arith.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lang/cem/cpp.ansi/arith.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* COMPILER ARITHMETIC */ | ||||||
|  | 
 | ||||||
|  | /*	Normally the compiler does its internal arithmetics in longs
 | ||||||
|  | 	native to the source machine, which is always good for local | ||||||
|  | 	compilations, and generally OK too for cross compilations | ||||||
|  | 	downwards and sidewards.  For upwards cross compilation and | ||||||
|  | 	to save storage on small machines, SPECIAL_ARITHMETICS will | ||||||
|  | 	be handy. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | /*	All preprocessor arithmetic should be done in longs.
 | ||||||
|  | */ | ||||||
|  | #define	arith	long				/* dummy */ | ||||||
							
								
								
									
										18
									
								
								lang/cem/cpp.ansi/bits.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lang/cem/cpp.ansi/bits.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | #include "dobits.h" | ||||||
|  | #ifdef DOBITS | ||||||
|  | #define bit0	0x01 | ||||||
|  | #define bit1	0x02 | ||||||
|  | #define bit2	0x04 | ||||||
|  | #define bit3	0x08 | ||||||
|  | #define bit4	0x10 | ||||||
|  | #define bit5	0x20 | ||||||
|  | #define bit6	0x40 | ||||||
|  | #define bit7	0x80 | ||||||
|  | 
 | ||||||
|  | extern char bits[]; | ||||||
|  | #endif | ||||||
							
								
								
									
										80
									
								
								lang/cem/cpp.ansi/ch3bin.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								lang/cem/cpp.ansi/ch3bin.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,80 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* EVALUATION OF BINARY OPERATORS */ | ||||||
|  | 
 | ||||||
|  | #include	"Lpars.h" | ||||||
|  | #include	"arith.h" | ||||||
|  | 
 | ||||||
|  | ch7bin(pval, oper, val) | ||||||
|  | 	register arith *pval, val; | ||||||
|  | 	int oper; | ||||||
|  | { | ||||||
|  | 	switch (oper)	{ | ||||||
|  | 	case '%': | ||||||
|  | 		if (val == 0) | ||||||
|  | 			error("% by 0"); | ||||||
|  | 		else | ||||||
|  | 			*pval = *pval % val; | ||||||
|  | 		break; | ||||||
|  | 	case '/': | ||||||
|  | 		if (val == 0) | ||||||
|  | 			error("/ by 0"); | ||||||
|  | 		else | ||||||
|  | 			*pval = *pval / val; | ||||||
|  | 		break; | ||||||
|  | 	case '*': | ||||||
|  | 		*pval = *pval * val; | ||||||
|  | 		break; | ||||||
|  | 	case '+': | ||||||
|  | 		*pval = *pval + val; | ||||||
|  | 		break; | ||||||
|  | 	case '-': | ||||||
|  | 		*pval = *pval - val; | ||||||
|  | 		break; | ||||||
|  | 	case LEFT: | ||||||
|  | 		*pval = *pval << val; | ||||||
|  | 		break; | ||||||
|  | 	case RIGHT: | ||||||
|  | 		*pval = *pval >> val; | ||||||
|  | 		break; | ||||||
|  | 	case '<': | ||||||
|  | 		*pval = (*pval < val); | ||||||
|  | 		break; | ||||||
|  | 	case '>': | ||||||
|  | 		*pval = (*pval > val); | ||||||
|  | 		break; | ||||||
|  | 	case LESSEQ: | ||||||
|  | 		*pval = (*pval <= val); | ||||||
|  | 		break; | ||||||
|  | 	case GREATEREQ: | ||||||
|  | 		*pval = (*pval >= val); | ||||||
|  | 		break; | ||||||
|  | 	case EQUAL: | ||||||
|  | 		*pval = (*pval == val); | ||||||
|  | 		break; | ||||||
|  | 	case NOTEQUAL: | ||||||
|  | 		*pval = (*pval != val); | ||||||
|  | 		break; | ||||||
|  | 	case '&': | ||||||
|  | 		*pval = *pval & val; | ||||||
|  | 		break; | ||||||
|  | 	case '^': | ||||||
|  | 		*pval = *pval ^ val; | ||||||
|  | 		break; | ||||||
|  | 	case '|': | ||||||
|  | 		*pval = *pval | val; | ||||||
|  | 		break; | ||||||
|  | 	case AND: | ||||||
|  | 		*pval = (*pval && val); | ||||||
|  | 		break; | ||||||
|  | 	case OR: | ||||||
|  | 		*pval = (*pval || val); | ||||||
|  | 		break; | ||||||
|  | 	case ',': | ||||||
|  | 		*pval = val; | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										25
									
								
								lang/cem/cpp.ansi/ch3mon.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								lang/cem/cpp.ansi/ch3mon.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* EVALUATION OF MONADIC OPERATORS */ | ||||||
|  | 
 | ||||||
|  | #include	"Lpars.h" | ||||||
|  | #include	"arith.h" | ||||||
|  | 
 | ||||||
|  | ch7mon(oper, pval) | ||||||
|  | 	register arith *pval; | ||||||
|  | { | ||||||
|  | 	switch (oper)	{ | ||||||
|  | 	case '~': | ||||||
|  | 		*pval = ~(*pval); | ||||||
|  | 		break; | ||||||
|  | 	case '-': | ||||||
|  | 		*pval = -(*pval); | ||||||
|  | 		break; | ||||||
|  | 	case '!': | ||||||
|  | 		*pval = !(*pval); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										67
									
								
								lang/cem/cpp.ansi/char.tab
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								lang/cem/cpp.ansi/char.tab
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,67 @@ | ||||||
|  | % | ||||||
|  | %	CHARACTER CLASSES | ||||||
|  | % | ||||||
|  | % some general settings: | ||||||
|  | %S129 | ||||||
|  | %F	%s, | ||||||
|  | % | ||||||
|  | %	START OF TOKEN | ||||||
|  | % | ||||||
|  | %iSTGARB | ||||||
|  | STSKIP:\r \t\013\f | ||||||
|  | STNL:\n | ||||||
|  | STCOMP:-!&+<=>|*%/^ | ||||||
|  | STSIMP:(),:;?[]{}~ | ||||||
|  | STCHAR:' | ||||||
|  | STIDF:a-zA-KM-Z_\003 | ||||||
|  | STELL:L | ||||||
|  | STNUM:.0-9 | ||||||
|  | STSTR:" | ||||||
|  | STEOI:\200 | ||||||
|  | STMSPEC:\004 | ||||||
|  | %T/* character classes */ | ||||||
|  | %T#include "class.h" | ||||||
|  | %Tchar tkclass[] = { | ||||||
|  | %p | ||||||
|  | %T}; | ||||||
|  | % | ||||||
|  | %	INIDF | ||||||
|  | % | ||||||
|  | %C | ||||||
|  | 1:a-zA-Z_0-9 | ||||||
|  | %Tchar inidf[] = { | ||||||
|  | %F	%s, | ||||||
|  | %p | ||||||
|  | %T}; | ||||||
|  | % | ||||||
|  | %	ISDIG | ||||||
|  | % | ||||||
|  | %C | ||||||
|  | 1:0-9 | ||||||
|  | %Tchar isdig[] = { | ||||||
|  | %p | ||||||
|  | %T}; | ||||||
|  | % | ||||||
|  | %	ISHEX | ||||||
|  | % | ||||||
|  | %C | ||||||
|  | 1:0-9a-fA-F | ||||||
|  | %Tchar ishex[] = { | ||||||
|  | %p | ||||||
|  | %T}; | ||||||
|  | % | ||||||
|  | %	ISOCT | ||||||
|  | % | ||||||
|  | %C | ||||||
|  | 1:0-7 | ||||||
|  | %Tchar isoct[] = { | ||||||
|  | %p | ||||||
|  | %T}; | ||||||
|  | % | ||||||
|  | %	ISWSP | ||||||
|  | % | ||||||
|  | %C | ||||||
|  | 1: \t\n | ||||||
|  | %Tchar iswsp[] = { | ||||||
|  | %p | ||||||
|  | %T}; | ||||||
							
								
								
									
										48
									
								
								lang/cem/cpp.ansi/class.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								lang/cem/cpp.ansi/class.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* U S E   O F   C H A R A C T E R   C L A S S E S */ | ||||||
|  | 
 | ||||||
|  | /*	As a starter, chars are divided into classes, according to which
 | ||||||
|  | 	token they can be the start of. | ||||||
|  | 	At present such a class number is supposed to fit in 4 bits. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define	class(ch)	((tkclass)[ch]) | ||||||
|  | 
 | ||||||
|  | /*	Being the start of a token is, fortunately, a mutual exclusive
 | ||||||
|  | 	property, so, as there are less than 16 classes they can be | ||||||
|  | 	packed in 4 bits. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #define	STSKIP	0	/* spaces and so on: skipped characters		*/ | ||||||
|  | #define	STNL	1	/* newline character(s): update linenumber etc.	*/ | ||||||
|  | #define	STGARB	2	/* garbage ascii character: not allowed		*/ | ||||||
|  | #define	STSIMP	3	/* this character can occur as token		*/ | ||||||
|  | #define	STCOMP	4	/* this one can start a compound token		*/ | ||||||
|  | #define	STELL	5	/* wide character- or string- constant prefix	*/ | ||||||
|  | #define	STIDF	6	/* being the initial character of an identifier	*/ | ||||||
|  | #define	STCHAR	7	/* the starter of a character constant		*/ | ||||||
|  | #define	STSTR	8	/* the starter of a string			*/ | ||||||
|  | #define	STNUM	9	/* the starter of a numeric constant		*/ | ||||||
|  | #define	STEOI	10	/* End-Of-Information mark			*/ | ||||||
|  | #define	STMSPEC	11	/* special class for token expansion		*/ | ||||||
|  | 
 | ||||||
|  | #define	NOEXPM	'\003'	/* don't expand the next macro identifier	*/ | ||||||
|  | #define	TOKSEP	'\004'	/* the token separator				*/ | ||||||
|  | 
 | ||||||
|  | /*	But occurring inside a token is not, so we need 1 bit for each
 | ||||||
|  | 	class.  This is implemented as a collection of tables to speed up | ||||||
|  | 	the decision whether a character has a special meaning. | ||||||
|  | */ | ||||||
|  | #define	in_idf(ch)	(inidf[ch]) | ||||||
|  | #define	is_oct(ch)	(isoct[ch]) | ||||||
|  | #define	is_dig(ch)	(isdig[ch]) | ||||||
|  | #define	is_hex(ch)	(ishex[ch]) | ||||||
|  | #define	is_suf(ch)	(issuf[ch]) | ||||||
|  | #define	is_wsp(ch)	(iswsp[ch]) | ||||||
|  | 
 | ||||||
|  | extern char tkclass[]; | ||||||
|  | extern char inidf[], isoct[], isdig[], ishex[], issuf[], iswsp[]; | ||||||
							
								
								
									
										738
									
								
								lang/cem/cpp.ansi/domacro.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										738
									
								
								lang/cem/cpp.ansi/domacro.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,738 @@ | ||||||
|  | /*
 | ||||||
|  |  * (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: CONTROLLINE INTERPRETER */ | ||||||
|  | 
 | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | #include	"Lpars.h" | ||||||
|  | #include	"idf.h" | ||||||
|  | #include	"input.h" | ||||||
|  | 
 | ||||||
|  | #include	"ifdepth.h"	 | ||||||
|  | #include	"botch_free.h"	 | ||||||
|  | #include	"nparams.h"	 | ||||||
|  | #include	"parbufsize.h"	 | ||||||
|  | #include	"textsize.h"	 | ||||||
|  | #include	"idfsize.h"	 | ||||||
|  | #include	<assert.h> | ||||||
|  | #include	<alloc.h> | ||||||
|  | #include	"class.h" | ||||||
|  | #include	"macro.h" | ||||||
|  | #include	"bits.h" | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | int	svnestlevel[30] = {-1}; | ||||||
|  | int	nestcount; | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | GetIdentifier(skiponerr) | ||||||
|  | 	int skiponerr;		/* skip the rest of the line on error */ | ||||||
|  | { | ||||||
|  | 	/*	Returns a pointer to 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. | ||||||
|  | 		Remember that on end-of-line EOF is returned. | ||||||
|  | 	*/ | ||||||
|  | 	int tmp = UnknownIdIsZero; | ||||||
|  | 	int tok; | ||||||
|  | 	struct token tk; | ||||||
|  | 
 | ||||||
|  | 	UnknownIdIsZero = ReplaceMacros = 0; | ||||||
|  | 	tok = GetToken(&tk); | ||||||
|  | 	ReplaceMacros = 1; | ||||||
|  | 	UnknownIdIsZero = tmp; | ||||||
|  | 	if (tok != IDENTIFIER) { | ||||||
|  | 		if (skiponerr && tok != EOF) SkipToNewLine(0); | ||||||
|  | 		return (char *)0; | ||||||
|  | 	} | ||||||
|  | 	return tk.tk_str; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*	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. | ||||||
|  | 	Return 1 if the preprocessing directive is done. This is to leave | ||||||
|  | 	pragma's in the input. | ||||||
|  | */ | ||||||
|  | int | ||||||
|  | domacro() | ||||||
|  | { | ||||||
|  | 	struct token tk;	/* the token itself			*/ | ||||||
|  | 	register struct idf *id; | ||||||
|  | 	int toknum; | ||||||
|  | 
 | ||||||
|  | 	ReplaceMacros = 0; | ||||||
|  | 	toknum = GetToken(&tk); | ||||||
|  | 	ReplaceMacros = 1; | ||||||
|  | 	switch(toknum) {		/* select control line action	*/ | ||||||
|  | 	case IDENTIFIER:		/* is it a macro keyword?	*/ | ||||||
|  | 		id = findidf(tk.tk_str); | ||||||
|  | 		if (!id) { | ||||||
|  | 			error("%s: unknown control", tk.tk_str); | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 			free(tk.tk_str); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		free(tk.tk_str); | ||||||
|  | 		switch (id->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) { | ||||||
|  | 				error("bad #line syntax"); | ||||||
|  | 				SkipToNewLine(0); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 				do_line((unsigned int)tk.tk_val); | ||||||
|  | 			break; | ||||||
|  | 		case K_ERROR:				/* "error"	*/ | ||||||
|  | 			do_error(); | ||||||
|  | 			break; | ||||||
|  | 		case K_PRAGMA:				/* "pragma"	*/ | ||||||
|  | 			return 0;	/* this is for the compiler */ | ||||||
|  | 			break; | ||||||
|  | 		case K_UNDEF:				/* "undef"	*/ | ||||||
|  | 			do_undef(); | ||||||
|  | 			break; | ||||||
|  | 		default: | ||||||
|  | 			/* invalid word seen after the '#'	*/ | ||||||
|  | 			error("%s: unknown control", id->id_text); | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case INTEGER:		/* # <integer> [<filespecifier>]?	*/ | ||||||
|  | 		do_line((unsigned int)tk.tk_val); | ||||||
|  | 		break; | ||||||
|  | 	case EOF:	/* only `#' on this line: do nothing, ignore	*/ | ||||||
|  | 		break; | ||||||
|  | 	default:	/* invalid token following '#'		*/ | ||||||
|  | 		error("illegal # line"); | ||||||
|  | 		SkipToNewLine(0); | ||||||
|  | 	} | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 	struct idf *id; | ||||||
|  | 
 | ||||||
|  | 	NoUnstack++; | ||||||
|  | 	for (;;) { | ||||||
|  | 		ch = GetChar();	/* read first character after newline	*/ | ||||||
|  | 		while (class(ch) == STSKIP) | ||||||
|  | 			ch = GetChar(); | ||||||
|  | 		if (ch != '#') { | ||||||
|  | 			if (ch == EOI) { | ||||||
|  | 				NoUnstack--; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		ReplaceMacros = 0; | ||||||
|  | 		toknum = GetToken(&tk); | ||||||
|  | 		ReplaceMacros = 1; | ||||||
|  | 		if (toknum != IDENTIFIER) { | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 			continue; | ||||||
|  | 		} | ||||||
|  | 		/*	an IDENTIFIER: look for #if, #ifdef and #ifndef
 | ||||||
|  | 			without interpreting them. | ||||||
|  | 			Interpret #else, #elif and #endif if they occur | ||||||
|  | 			on the same level. | ||||||
|  | 		*/ | ||||||
|  | 		id = findidf(tk.tk_str); | ||||||
|  | 		free(tk.tk_str); | ||||||
|  | 		switch(id->id_resmac) { | ||||||
|  | 		default: | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 			break; | ||||||
|  | 		case K_IF: | ||||||
|  | 		case K_IFDEF: | ||||||
|  | 		case K_IFNDEF: | ||||||
|  | 			push_if(); | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 			break; | ||||||
|  | 		case K_ELIF: | ||||||
|  | 			if (ifstack[nestlevel]) | ||||||
|  | 				error("#elif after #else"); | ||||||
|  | 			if (!to_endif && nestlevel == skiplevel) { | ||||||
|  | 				nestlevel--; | ||||||
|  | 				push_if(); | ||||||
|  | 				if (ifexpr()) { | ||||||
|  | 					NoUnstack--; | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			else SkipToNewLine(0);  /* otherwise done in ifexpr() */ | ||||||
|  | 			break; | ||||||
|  | 		case K_ELSE: | ||||||
|  | 			if (ifstack[nestlevel]) | ||||||
|  | 				error("#else after #else"); | ||||||
|  | 			++(ifstack[nestlevel]); | ||||||
|  | 			if (!to_endif && nestlevel == skiplevel) { | ||||||
|  | 				if (SkipToNewLine(1)) | ||||||
|  | 					strict("garbage following #else"); | ||||||
|  | 				NoUnstack--; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			else SkipToNewLine(0); | ||||||
|  | 			break; | ||||||
|  | 		case K_ENDIF: | ||||||
|  | 			assert(nestlevel > svnestlevel[nestcount]); | ||||||
|  | 			if (nestlevel == skiplevel) { | ||||||
|  | 				if (SkipToNewLine(1)) | ||||||
|  | 					strict("garbage following #endif"); | ||||||
|  | 				nestlevel--; | ||||||
|  | 				NoUnstack--; | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			else SkipToNewLine(0); | ||||||
|  | 			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; | ||||||
|  | 	DOT = 0;	/* tricky */ | ||||||
|  | 	If_expr();	/* invoke constant expression 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_str; | ||||||
|  | 	else { | ||||||
|  | 		error("bad include syntax"); | ||||||
|  | 		filenm = (char *)0; | ||||||
|  | 	} | ||||||
|  | 	AccFileSpecifier = 0; | ||||||
|  | 	SkipToNewLine(0); | ||||||
|  | 	inctable[0] = WorkingDir; | ||||||
|  | 	if (filenm) { | ||||||
|  | 		if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){ | ||||||
|  | 			error("cannot open include file \"%s\"", filenm); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			WorkingDir = getwdir(result); | ||||||
|  | 			svnestlevel[++nestcount] = nestlevel; | ||||||
|  | 			FileName = result; | ||||||
|  | 			LineNumber = 1; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_define() | ||||||
|  | { | ||||||
|  | 	/*	do_define() interprets a #define control line.
 | ||||||
|  | 	*/ | ||||||
|  | 	register char *str;	/* 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 (!(str = GetIdentifier(1))) { | ||||||
|  | 		error("#define: illegal macro name"); | ||||||
|  | 		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(0); | ||||||
|  | 			free(str); | ||||||
|  | 			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); | ||||||
|  | 	if (class(ch) == STNL) { | ||||||
|  | 		/*	Treat `#define something' as `#define something ""'
 | ||||||
|  | 		*/ | ||||||
|  | 		repl_text = Malloc(1); | ||||||
|  | 		*repl_text = '\0'; | ||||||
|  | 		length = 0; | ||||||
|  | 	} | ||||||
|  | 	else { | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		repl_text = get_text((nformals > 0) ? formals : 0, &length); | ||||||
|  | 	} | ||||||
|  | 	macro_def(str2idf(str, 0), 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 <= svnestlevel[nestcount]) { | ||||||
|  | 		error("#elif without corresponding #if"); | ||||||
|  | 		SkipToNewLine(0); | ||||||
|  | 	} | ||||||
|  | 	else { /* restart at this level as if a #if is detected.  */ | ||||||
|  | 		if (ifstack[nestlevel]) { | ||||||
|  | 			error("#elif after #else"); | ||||||
|  | 			SkipToNewLine(0); | ||||||
|  | 		} | ||||||
|  | 		nestlevel--; | ||||||
|  | 		push_if(); | ||||||
|  | 		skip_block(1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_else() | ||||||
|  | { | ||||||
|  | 	if (SkipToNewLine(1)) | ||||||
|  | 		strict("garbage following #else"); | ||||||
|  | 	if (nestlevel <= svnestlevel[nestcount]) | ||||||
|  | 		error("#else without corresponding #if"); | ||||||
|  | 	else {	/* mark this level as else-d */ | ||||||
|  | 		if (ifstack[nestlevel]) { | ||||||
|  | 			error("#else after #else"); | ||||||
|  | 		} | ||||||
|  | 		++(ifstack[nestlevel]); | ||||||
|  | 		skip_block(1); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_endif() | ||||||
|  | { | ||||||
|  | 	if (SkipToNewLine(1)) | ||||||
|  | 		strict("garbage following #endif"); | ||||||
|  | 	if (nestlevel <= svnestlevel[nestcount])	{ | ||||||
|  | 		error("#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; | ||||||
|  | 	register char *str; | ||||||
|  | 
 | ||||||
|  | 	/*	how == 1 : ifdef; how == 0 : ifndef
 | ||||||
|  | 	*/ | ||||||
|  | 	push_if(); | ||||||
|  | 	if (!(str = GetIdentifier(1))) { | ||||||
|  | 		error("illegal #ifdef construction"); | ||||||
|  | 		id = (struct idf *)0; | ||||||
|  | 	} else { | ||||||
|  | 		id = findidf(str); | ||||||
|  | 		free(str); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/* 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); | ||||||
|  | 	else | ||||||
|  | 		SkipToNewLine(0); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_undef() | ||||||
|  | { | ||||||
|  | 	register struct idf *id; | ||||||
|  | 	register char *str; | ||||||
|  | 
 | ||||||
|  | 	/* Forget a macro definition.	*/ | ||||||
|  | 	if (str = GetIdentifier(1)) { | ||||||
|  | 		if ((id = findidf(str)) && id->id_macro) { | ||||||
|  | 			if (id->id_macro->mc_flag & NOUNDEF) { | ||||||
|  | 				error("it is not allowed to #undef %s", str); | ||||||
|  | 			} else { | ||||||
|  | 				free(id->id_macro->mc_text); | ||||||
|  | 				free_macro(id->id_macro); | ||||||
|  | 				id->id_macro = (struct macro *) 0; | ||||||
|  | 			} | ||||||
|  | 		} /* else: don't complain */ | ||||||
|  | 		free(str); | ||||||
|  | 		SkipToNewLine(0); | ||||||
|  | 	} | ||||||
|  | 	else | ||||||
|  | 		error("illegal #undef construction"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_error() | ||||||
|  | { | ||||||
|  | 	static char errbuf[512]; | ||||||
|  | 	register char *bp = errbuf; | ||||||
|  | 	register int ch; | ||||||
|  | 
 | ||||||
|  | 	while ((ch = GetChar()) != '\n') | ||||||
|  | 		*bp++ = ch; | ||||||
|  | 	*bp = '\0'; | ||||||
|  | 	UnGetChar(); | ||||||
|  | 	error("user error: %s", errbuf); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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) { | ||||||
|  | 			error("#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)) { | ||||||
|  | 				warning("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 != ',') { | ||||||
|  | 			error("#define: bad formal parameter list"); | ||||||
|  | 			return -1; | ||||||
|  | 		} | ||||||
|  | 		c = GetChar(); | ||||||
|  | 		c = skipspaces(c,0); | ||||||
|  | 	} | ||||||
|  | 	/*NOTREACHED*/ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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) { | ||||||
|  | 			error("it is not allowed to redefine %s", id->id_text); | ||||||
|  | 		} else if (!macroeq(newdef->mc_text, text)) | ||||||
|  | 			error("illegal redefine of \"%s\"", id->id_text); | ||||||
|  | 		free(text); | ||||||
|  | 		return; | ||||||
|  | 	} else { | ||||||
|  | #ifdef DOBITS | ||||||
|  | 		register char *p = id->id_text; | ||||||
|  | #define setbit(bx)      if (!*p) goto go_on; bits[*p++] |= (bx) | ||||||
|  | 		setbit(bit0); | ||||||
|  | 		setbit(bit1); | ||||||
|  | 		setbit(bit2); | ||||||
|  | 		setbit(bit3); | ||||||
|  | 		setbit(bit4); | ||||||
|  | 		setbit(bit5); | ||||||
|  | 		setbit(bit6); | ||||||
|  | 		setbit(bit7); | ||||||
|  | 
 | ||||||
|  | 	go_on: | ||||||
|  | #endif | ||||||
|  | 		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; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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 only interested in | ||||||
|  | 		identifiers, because they might be replaced by some actual | ||||||
|  | 		parameter.  Other tokens will not be seen as such. | ||||||
|  | 	*/ | ||||||
|  | 	register int c; | ||||||
|  | 	register unsigned text_size; | ||||||
|  | 	char *text = Malloc(text_size = ITEXTSIZE); | ||||||
|  | 	register int pos = 0; | ||||||
|  | 
 | ||||||
|  | 	c = GetChar(); | ||||||
|  | 
 | ||||||
|  | 	while ((c != EOI) && (class(c) != STNL)) { | ||||||
|  | 		if (c == '\'' || c == '"') { | ||||||
|  | 			register int delim = c; | ||||||
|  | 
 | ||||||
|  | 			do { | ||||||
|  | 				/* being careful, as ever */ | ||||||
|  | 				if (pos+3 >= text_size) | ||||||
|  | 					text = Srealloc(text, text_size <<= 1); | ||||||
|  | 				text[pos++] = c; | ||||||
|  | 				if (c == '\\') | ||||||
|  | 					text[pos++] = GetChar(); | ||||||
|  | 				c = GetChar(); | ||||||
|  | 			} while (c != delim && c != EOI && class(c) != STNL); | ||||||
|  | 			text[pos++] = c; | ||||||
|  | 			c = GetChar(); | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		if (c == '/') { | ||||||
|  | 			c = GetChar(); | ||||||
|  | 			if (pos+1 >= text_size) | ||||||
|  | 				text = Srealloc(text, text_size <<= 1); | ||||||
|  | 			if (c == '*') { | ||||||
|  | 				skipcomment(); | ||||||
|  | 				text[pos++] = ' '; | ||||||
|  | 				c = GetChar(); | ||||||
|  | 			} | ||||||
|  | 			else | ||||||
|  | 				text[pos++] = '/'; | ||||||
|  | 		} | ||||||
|  | 		else | ||||||
|  | 		if (formals && (class(c) == STIDF || class(c) == STELL)) { | ||||||
|  | 			char id_buf[IDFSIZE + 1]; | ||||||
|  | 			register id_size = 0; | ||||||
|  | 			register n; | ||||||
|  | 
 | ||||||
|  | 			/* read identifier: it may be a formal parameter */ | ||||||
|  | 			id_buf[id_size++] = c; | ||||||
|  | 			do { | ||||||
|  | 				c = GetChar(); | ||||||
|  | 				if (id_size <= IDFSIZE) | ||||||
|  | 					id_buf[id_size++] = c; | ||||||
|  | 			} while (in_idf(c)); | ||||||
|  | 			id_buf[--id_size] = '\0'; | ||||||
|  | 			if (n = find_name(id_buf, formals)) { | ||||||
|  | 				/* construct the formal parameter mark	*/ | ||||||
|  | 				if (pos+1 >= text_size) | ||||||
|  | 					text = Srealloc(text, | ||||||
|  | 						text_size <<= 1); | ||||||
|  | 				text[pos++] = FORMALP | (char) n; | ||||||
|  | 			} | ||||||
|  | 			else { | ||||||
|  | 				register char *ptr = &id_buf[0]; | ||||||
|  | 
 | ||||||
|  | 				while (pos + id_size >= text_size) | ||||||
|  | 					text_size <<= 1; | ||||||
|  | 				text = Realloc(text, text_size); | ||||||
|  | 				while (text[pos++] = *ptr++) | ||||||
|  | 					/* EMPTY */ ; | ||||||
|  | 				pos--; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			if (pos+1 >= text_size) | ||||||
|  | 				text = Realloc(text, text_size <<= 1); | ||||||
|  | 			text[pos++] = c; | ||||||
|  | 			c = GetChar(); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	text[pos++] = '\0'; | ||||||
|  | 	text = Realloc(text, pos); | ||||||
|  | 	*length = pos - 1; | ||||||
|  | 	return text; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #define	BLANK(ch)	((ch == ' ') || (ch == '\t')) | ||||||
|  | 
 | ||||||
|  | /*	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'); | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | do_line(l) | ||||||
|  | 	unsigned int l; | ||||||
|  | { | ||||||
|  | 	struct token tk; | ||||||
|  | 
 | ||||||
|  | 	LineNumber = l - 1;	/* the number of the next input line */ | ||||||
|  | 	if (GetToken(&tk) == STRING)	/* is there a filespecifier? */ | ||||||
|  | 		FileName = tk.tk_str; | ||||||
|  | 	SkipToNewLine(0); | ||||||
|  | } | ||||||
							
								
								
									
										106
									
								
								lang/cem/cpp.ansi/error.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								lang/cem/cpp.ansi/error.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,106 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /*	E R R O R   A N D  D I A G N O S T I C   R O U T I N E S	*/ | ||||||
|  | 
 | ||||||
|  | #include	<system.h> | ||||||
|  | #include	<varargs.h> | ||||||
|  | 
 | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"errout.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | 
 | ||||||
|  | /*	This file contains the (non-portable) error-message and diagnostic
 | ||||||
|  | 	functions.  Beware, they are called with a variable number of | ||||||
|  | 	arguments! | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | int err_occurred; | ||||||
|  | 
 | ||||||
|  | err_hdr(s) | ||||||
|  | 	char *s; | ||||||
|  | { | ||||||
|  | 	if (FileName) { | ||||||
|  | 		fprint(ERROUT, "\"%s\", line %d: %s", FileName, LineNumber, s); | ||||||
|  | 	} | ||||||
|  | 	else	fprint(ERROUT, s); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*VARARGS1*/ | ||||||
|  | error(va_alist) | ||||||
|  | 	va_dcl | ||||||
|  | { | ||||||
|  | 	char *fmt; | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	err_hdr(""); | ||||||
|  | 	va_start(ap); | ||||||
|  | 	fmt = va_arg(ap, char *); | ||||||
|  | 	doprnt(ERROUT, fmt, ap); | ||||||
|  | 	fprint(ERROUT, "\n"); | ||||||
|  | 	va_end(ap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*VARARGS1*/ | ||||||
|  | warning(va_alist) | ||||||
|  | 	va_dcl | ||||||
|  | { | ||||||
|  | 	char *fmt; | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	err_hdr("(warning) "); | ||||||
|  | 	va_start(ap); | ||||||
|  | 	fmt = va_arg(ap, char *); | ||||||
|  | 	doprnt(ERROUT, fmt, ap); | ||||||
|  | 	fprint(ERROUT, "\n"); | ||||||
|  | 	va_end(ap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*VARARGS1*/ | ||||||
|  | strict(va_alist) | ||||||
|  | 	va_dcl | ||||||
|  | { | ||||||
|  | 	char *fmt; | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	err_hdr("(strict) "); | ||||||
|  | 	va_start(ap); | ||||||
|  | 	fmt = va_arg(ap, char *); | ||||||
|  | 	doprnt(ERROUT, fmt, ap); | ||||||
|  | 	fprint(ERROUT, "\n"); | ||||||
|  | 	va_end(ap); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*VARARGS1*/ | ||||||
|  | crash(va_alist) | ||||||
|  | 	va_dcl | ||||||
|  | { | ||||||
|  | 	char *fmt; | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	err_hdr("CRASH\007 "); | ||||||
|  | 	va_start(ap); | ||||||
|  | 	fmt = va_arg(ap, char *); | ||||||
|  | 	doprnt(ERROUT, fmt, ap); | ||||||
|  | 	fprint(ERROUT, "\n"); | ||||||
|  | 	va_end(ap); | ||||||
|  | 	sys_stop(S_ABORT); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /*VARARGS1*/ | ||||||
|  | fatal(va_alist) | ||||||
|  | 	va_dcl | ||||||
|  | { | ||||||
|  | 	char *fmt; | ||||||
|  | 	va_list ap; | ||||||
|  | 
 | ||||||
|  | 	err_hdr("fatal error -- "); | ||||||
|  | 	va_start(ap); | ||||||
|  | 	fmt = va_arg(ap, char *); | ||||||
|  | 	doprnt(ERROUT, fmt, ap); | ||||||
|  | 	fprint(ERROUT, "\n"); | ||||||
|  | 	va_end(ap); | ||||||
|  | 	sys_stop(S_EXIT); | ||||||
|  | } | ||||||
							
								
								
									
										58
									
								
								lang/cem/cpp.ansi/expr.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								lang/cem/cpp.ansi/expr.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* OPERATOR HANDLING */ | ||||||
|  | 
 | ||||||
|  | #include	"Lpars.h" | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | rank_of(oper) | ||||||
|  | 	int oper; | ||||||
|  | { | ||||||
|  | 	/*	The rank of the operator oper is returned.
 | ||||||
|  | 	*/ | ||||||
|  | 	switch (oper)	{ | ||||||
|  | 	default: | ||||||
|  | 		return 0; | ||||||
|  | 	case '(': | ||||||
|  | 		return 1; | ||||||
|  | 	case '!': | ||||||
|  | 		return 2; | ||||||
|  | 	case '*': | ||||||
|  | 	case '/': | ||||||
|  | 	case '%': | ||||||
|  | 		return 3; | ||||||
|  | 	case '+': | ||||||
|  | 	case '-': | ||||||
|  | 		return 4; | ||||||
|  | 	case LEFT: | ||||||
|  | 	case RIGHT: | ||||||
|  | 		return 5; | ||||||
|  | 	case '<': | ||||||
|  | 	case '>': | ||||||
|  | 	case LESSEQ: | ||||||
|  | 	case GREATEREQ: | ||||||
|  | 		return 6; | ||||||
|  | 	case EQUAL: | ||||||
|  | 	case NOTEQUAL: | ||||||
|  | 		return 7; | ||||||
|  | 	case '&': | ||||||
|  | 		return 8; | ||||||
|  | 	case '^': | ||||||
|  | 		return 9; | ||||||
|  | 	case '|': | ||||||
|  | 		return 10; | ||||||
|  | 	case AND: | ||||||
|  | 		return 11; | ||||||
|  | 	case OR: | ||||||
|  | 		return 12; | ||||||
|  | 	case '?': | ||||||
|  | 	case ':': | ||||||
|  | 		return 13; | ||||||
|  | 	case ',': | ||||||
|  | 		return 15; | ||||||
|  | 	} | ||||||
|  | 	/*NOTREACHED*/ | ||||||
|  | } | ||||||
							
								
								
									
										129
									
								
								lang/cem/cpp.ansi/expression.g
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								lang/cem/cpp.ansi/expression.g
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,129 @@ | ||||||
|  | /* | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /*	EXPRESSION SYNTAX PARSER	*/ | ||||||
|  | 
 | ||||||
|  | %lexical	LLlex; | ||||||
|  | %start		If_expr, if_expression; | ||||||
|  | 
 | ||||||
|  | { | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | 
 | ||||||
|  | extern arith ifval; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | if_expression | ||||||
|  | : | ||||||
|  | 	constant_expression(&ifval) | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | /* 7.1 */ | ||||||
|  | primary(arith *pval;) | ||||||
|  | : | ||||||
|  | 	constant(pval) | ||||||
|  | | | ||||||
|  | 	'(' expression(pval) ')' | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | unary(arith *pval;) | ||||||
|  | 	{int oper;} | ||||||
|  | : | ||||||
|  | 	unop(&oper) | ||||||
|  | 	unary(pval) | ||||||
|  | 	{ ch7mon(oper, pval); } | ||||||
|  | | | ||||||
|  | 	primary(pval) | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | binary_expression(int maxrank; arith *pval;) | ||||||
|  | 	{int oper; arith val1;} | ||||||
|  | : | ||||||
|  | 	unary(pval) | ||||||
|  | 	[%while (rank_of(DOT) <= maxrank) | ||||||
|  | 		binop(&oper) | ||||||
|  | 		binary_expression(rank_of(oper)-1, &val1) | ||||||
|  | 		{ | ||||||
|  | 			ch7bin(pval, oper, val1); | ||||||
|  | 		} | ||||||
|  | 	]* | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | /* 7.13 */ | ||||||
|  | conditional_expression(arith *pval;) | ||||||
|  | 	{arith val1 = 0, val2 = 0;} | ||||||
|  | : | ||||||
|  | 	/* allow all binary operators */ | ||||||
|  | 	binary_expression(rank_of('?') - 1, pval) | ||||||
|  | 	[	'?' | ||||||
|  | 		expression(&val1) | ||||||
|  | 		':' | ||||||
|  | 		assignment_expression(&val2) | ||||||
|  | 		{ *pval = (*pval ? val1 : val2); } | ||||||
|  | 	]? | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | /* 7.14 */ | ||||||
|  | assignment_expression(arith *pval;) | ||||||
|  | : | ||||||
|  | 	conditional_expression(pval) | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | /* 7.15 */ | ||||||
|  | expression(arith *pval;) | ||||||
|  | 	{arith val1;} | ||||||
|  | : | ||||||
|  | 	assignment_expression(pval) | ||||||
|  | 	[	',' | ||||||
|  | 		assignment_expression(&val1) | ||||||
|  | 		{ | ||||||
|  | 			ch7bin(pval, ',', val1); | ||||||
|  | 		} | ||||||
|  | 	]* | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | unop(int *oper;) : | ||||||
|  | 	[ '-' | '!' | '~' ] | ||||||
|  | 	{*oper = DOT;} | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | multop: | ||||||
|  | 	'*' | '/' | '%' | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | addop: | ||||||
|  | 	'+' | '-' | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | shiftop: | ||||||
|  | 	LEFT | RIGHT | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | relop: | ||||||
|  | 	'<' | '>' | LESSEQ | GREATEREQ | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | eqop: | ||||||
|  | 	EQUAL | NOTEQUAL | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | arithop: | ||||||
|  | 	multop | addop | shiftop | ||||||
|  | | | ||||||
|  | 	'&' | '^' | '|' | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | binop(int *oper;) : | ||||||
|  | 	[ arithop | relop | eqop | AND | OR ] | ||||||
|  | 	{*oper = DOT;} | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | constant(arith *pval;) : | ||||||
|  | 	INTEGER | ||||||
|  | 	{*pval = dot.tk_val;} | ||||||
|  | ; | ||||||
|  | 
 | ||||||
|  | constant_expression (arith *pval;) : | ||||||
|  | 	assignment_expression(pval) | ||||||
|  | ; | ||||||
							
								
								
									
										18
									
								
								lang/cem/cpp.ansi/file_info.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lang/cem/cpp.ansi/file_info.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* F I L E   I N F O R M A T I O N   S T R U C T U R E */ | ||||||
|  | 
 | ||||||
|  | struct file_info { | ||||||
|  | 	unsigned int	fil_lino; | ||||||
|  | 	char		*fil_name; | ||||||
|  | 	char		*fil_wdir; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define LineNumber	finfo.fil_lino | ||||||
|  | #define FileName	finfo.fil_name | ||||||
|  | #define WorkingDir	finfo.fil_wdir | ||||||
|  | 
 | ||||||
|  | extern struct file_info finfo;	/* input.c */ | ||||||
							
								
								
									
										7
									
								
								lang/cem/cpp.ansi/idf.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								lang/cem/cpp.ansi/idf.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | #include "idf.h" | ||||||
|  | #include <idf_pkg.body> | ||||||
							
								
								
									
										16
									
								
								lang/cem/cpp.ansi/idf.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								lang/cem/cpp.ansi/idf.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | struct id_usr { | ||||||
|  | 	struct macro *idu_macro; | ||||||
|  | 	int idu_resmac; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | #define IDF_TYPE struct id_usr | ||||||
|  | #define IDF_HSIZE 6 | ||||||
|  | #define id_macro id_user.idu_macro | ||||||
|  | #define id_resmac id_user.idu_resmac | ||||||
|  | 
 | ||||||
|  | #include <idf_pkg.spec> | ||||||
							
								
								
									
										92
									
								
								lang/cem/cpp.ansi/init.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								lang/cem/cpp.ansi/init.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,92 @@ | ||||||
|  | /*
 | ||||||
|  |  * (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: INITIALIZATION ROUTINES */ | ||||||
|  | 
 | ||||||
|  | #include	<system.h> | ||||||
|  | #include	<alloc.h> | ||||||
|  | #include	<time.h> | ||||||
|  | #include	"class.h" | ||||||
|  | #include	"macro.h" | ||||||
|  | #include	"idf.h" | ||||||
|  | 
 | ||||||
|  | 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} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | char *strcpy(); | ||||||
|  | 
 | ||||||
|  | init_pp() | ||||||
|  | { | ||||||
|  | 	static char *months[12] = { | ||||||
|  | 		"Jan", "Feb", "Mar", "Apr", "May", "Jun", | ||||||
|  | 		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | ||||||
|  | 	}; | ||||||
|  | 	long clock, sys_time(); | ||||||
|  | 	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); | ||||||
|  | 			 | ||||||
|  | 			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 = sys_time(); | ||||||
|  | 	tp = localtime(&clock); | ||||||
|  | 
 | ||||||
|  | 	/* __DATE__ */ | ||||||
|  | 	sprintf(dbuf, "\"%.3s %.2d %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__ */ | ||||||
|  | 	sprintf(tbuf, "\"%.2d:%.2d:%.2d\"", 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); | ||||||
|  | } | ||||||
							
								
								
									
										61
									
								
								lang/cem/cpp.ansi/input.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								lang/cem/cpp.ansi/input.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,61 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | 
 | ||||||
|  | #include "file_info.h" | ||||||
|  | #include "input.h" | ||||||
|  | 
 | ||||||
|  | #define INP_PUSHBACK	3 | ||||||
|  | #define INP_TYPE	struct file_info | ||||||
|  | #define INP_VAR		finfo | ||||||
|  | struct file_info	finfo; | ||||||
|  | #include <inp_pkg.body> | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | getwdir(fn) | ||||||
|  | 	register char *fn; | ||||||
|  | { | ||||||
|  | 	register char *p; | ||||||
|  | 	char *strrindex(); | ||||||
|  | 
 | ||||||
|  | 	p = strrindex(fn, '/'); | ||||||
|  | 	while (p && *(p + 1) == '\0') {	/* remove trailing /'s */ | ||||||
|  | 		*p = '\0'; | ||||||
|  | 		p = strrindex(fn, '/'); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */ | ||||||
|  | 		return ""; | ||||||
|  | 	if (p) { | ||||||
|  | 		*p = '\0'; | ||||||
|  | 		fn = Salloc(fn, p - &fn[0] + 1); | ||||||
|  | 		*p = '/'; | ||||||
|  | 		return fn; | ||||||
|  | 	} | ||||||
|  | 	return "."; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int	NoUnstack; | ||||||
|  | int	InputLevel; | ||||||
|  | 
 | ||||||
|  | AtEoIT() | ||||||
|  | { | ||||||
|  | 	InputLevel--; | ||||||
|  | 	/* if (NoUnstack) warning("unexpected EOF"); ??? */ | ||||||
|  | 	unstackrepl(); | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | AtEoIF() | ||||||
|  | { | ||||||
|  | 	extern int nestlevel; | ||||||
|  | 	extern int nestcount; | ||||||
|  | 	extern int svnestlevel[]; | ||||||
|  | 
 | ||||||
|  | 	if (nestlevel > svnestlevel[nestcount]) warning("missing #endif"); | ||||||
|  | 	else if (NoUnstack) warning("unexpected EOF"); | ||||||
|  | 	nestlevel = svnestlevel[nestcount--]; | ||||||
|  | 	return 0; | ||||||
|  | } | ||||||
							
								
								
									
										15
									
								
								lang/cem/cpp.ansi/input.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								lang/cem/cpp.ansi/input.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,15 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | #define INP_PUSHBACK 3 | ||||||
|  | #include "inputtype.h" | ||||||
|  | #include <inp_pkg.spec> | ||||||
|  | 
 | ||||||
|  | /*	Note: The following macro only garuantees one PushBack.
 | ||||||
|  | */ | ||||||
|  | #define UnGetChar()	((LexSave != EOI) ? ChPushBack(LexSave) : 0) | ||||||
|  | 
 | ||||||
|  | extern	int LexSave;	/* last character read by GetChar		*/ | ||||||
|  | extern 	int GetChar();	/* character input, with trigraph parsing	*/ | ||||||
							
								
								
									
										56
									
								
								lang/cem/cpp.ansi/macro.str
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								lang/cem/cpp.ansi/macro.str
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,56 @@ | ||||||
|  | /* | ||||||
|  |  * (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: DEFINITION OF MACRO DESCRIPTOR */ | ||||||
|  | 
 | ||||||
|  | /*	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 */ | ||||||
|  | 
 | ||||||
|  | struct mlist { | ||||||
|  | 	struct mlist *next; | ||||||
|  | 	struct macro *m_mac; | ||||||
|  | 	char *m_repl; | ||||||
|  | 	char m_unstack; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* ALLOCDEF "mlist" 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 | ||||||
							
								
								
									
										84
									
								
								lang/cem/cpp.ansi/main.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								lang/cem/cpp.ansi/main.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* MAIN PROGRAM */ | ||||||
|  | 
 | ||||||
|  | #include	<alloc.h> | ||||||
|  | #include	<system.h> | ||||||
|  | #include 	"arith.h" | ||||||
|  | #include	"file_info.h" | ||||||
|  | #include	"idfsize.h" | ||||||
|  | 
 | ||||||
|  | extern char *symbol2str(); | ||||||
|  | extern char *getwdir(); | ||||||
|  | extern int err_occurred; | ||||||
|  | int idfsize = IDFSIZE; | ||||||
|  | 
 | ||||||
|  | arith ifval; | ||||||
|  | 
 | ||||||
|  | char *prog_name; | ||||||
|  | 
 | ||||||
|  | extern char **inctable; | ||||||
|  | extern int inc_max, inc_total; | ||||||
|  | 
 | ||||||
|  | main(argc, argv) | ||||||
|  | 	char *argv[]; | ||||||
|  | { | ||||||
|  | 	/* parse and interpret the command line options	*/ | ||||||
|  | 	prog_name = argv[0]; | ||||||
|  | 
 | ||||||
|  | 	init_idf(); | ||||||
|  | 
 | ||||||
|  | 	inctable = (char **) Malloc(10 * sizeof(char *)); | ||||||
|  | 	inc_max = 10; | ||||||
|  | 	inc_total = 2; | ||||||
|  | 	inctable[0] = "."; | ||||||
|  | 	inctable[1] = "/usr/include"; | ||||||
|  | 	init_pp();	/* initialise the preprocessor macros	*/ | ||||||
|  | 
 | ||||||
|  | 	/*	Note: source file "-" indicates that the source is supplied
 | ||||||
|  | 		as standard input.  This is only allowed if INP_READ_IN_ONE is | ||||||
|  | 		not defined! | ||||||
|  | 	*/ | ||||||
|  | 	while (argc > 1 && *argv[1] == '-' && argv[1][1] != '\0')	{ | ||||||
|  | 		char *par = &argv[1][1]; | ||||||
|  | 
 | ||||||
|  | 		if (*par == '-') | ||||||
|  | 			par++; | ||||||
|  | 		do_option(par); | ||||||
|  | 		argc--, argv++; | ||||||
|  | 	} | ||||||
|  | 	compile(argc - 1, &argv[1]); | ||||||
|  | 	sys_stop(err_occurred ? S_EXIT : S_END); | ||||||
|  | 	/*NOTREACHED*/ | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | compile(argc, argv) | ||||||
|  | 	char *argv[]; | ||||||
|  | { | ||||||
|  | 	register char *source = 0; | ||||||
|  | 	char *dummy; | ||||||
|  | 
 | ||||||
|  | 	switch (argc) { | ||||||
|  | 	case 1: | ||||||
|  | 		source = argv[0]; | ||||||
|  | 		FileName = source; | ||||||
|  | 		break; | ||||||
|  | 	case 0: | ||||||
|  | 		FileName = ""; | ||||||
|  | 		WorkingDir = 0; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		FileName = argv[0]; | ||||||
|  | 		fatal("use: %s [options] [source]", prog_name); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!InsertFile(source, (char **) 0, &dummy)) /* read the source file	*/ | ||||||
|  | 		fatal("%s: no source file %s\n", prog_name,  | ||||||
|  | 			source ? source : "stdin"); | ||||||
|  | 	if (source) WorkingDir = getwdir(dummy); | ||||||
|  | 	preprocess(source); | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								lang/cem/cpp.ansi/make.allocd
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										8
									
								
								lang/cem/cpp.ansi/make.allocd
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,8 @@ | ||||||
|  | sed -e ' | ||||||
|  | s:^.*[ 	]ALLOCDEF[ 	].*"\(.*\)"[ 	]*\([0-9][0-9]*\).*$:\ | ||||||
|  | /* allocation definitions of struct \1 */\ | ||||||
|  | extern char *st_alloc();\ | ||||||
|  | extern struct \1 *h_\1;\ | ||||||
|  | #define	new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1), \2))\ | ||||||
|  | #define	free_\1(p) st_free(p, \&h_\1, sizeof(struct \1))\ | ||||||
|  | :' | ||||||
							
								
								
									
										35
									
								
								lang/cem/cpp.ansi/make.hfiles
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										35
									
								
								lang/cem/cpp.ansi/make.hfiles
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | : Update Files from database | ||||||
|  | 
 | ||||||
|  | PATH=/bin:/usr/bin | ||||||
|  | 
 | ||||||
|  | case $# in | ||||||
|  | 1) ;; | ||||||
|  | *)	echo use: $0 file >&2 | ||||||
|  | 	exit 1 | ||||||
|  | esac | ||||||
|  | 
 | ||||||
|  | ( | ||||||
|  | IFCOMMAND="if (<\$FN) 2>/dev/null;\ | ||||||
|  | 	then	if cmp -s \$FN \$TMP;\ | ||||||
|  | 		then	rm \$TMP;\ | ||||||
|  | 		else	mv \$TMP \$FN;\ | ||||||
|  | 			echo update \$FN;\ | ||||||
|  | 		fi;\ | ||||||
|  | 	else	mv \$TMP \$FN;\ | ||||||
|  | 		echo create \$FN;\ | ||||||
|  | 	fi" | ||||||
|  | echo 'TMP=.uf$$' | ||||||
|  | echo 'FN=$TMP' | ||||||
|  | echo 'cat >$TMP <<\!EOF!' | ||||||
|  | sed -n '/^!File:/,${ | ||||||
|  | /^$/d | ||||||
|  | /^!File:[	 ]*\(.*\)$/s@@!EOF!\ | ||||||
|  | '"$IFCOMMAND"'\ | ||||||
|  | FN=\1\ | ||||||
|  | cat >$TMP <<\\!EOF!@ | ||||||
|  | p | ||||||
|  | }' $1 | ||||||
|  | echo '!EOF!' | ||||||
|  | echo $IFCOMMAND | ||||||
|  | ) | | ||||||
|  | sh | ||||||
							
								
								
									
										3
									
								
								lang/cem/cpp.ansi/make.next
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										3
									
								
								lang/cem/cpp.ansi/make.next
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,3 @@ | ||||||
|  | sed -n ' | ||||||
|  | s:^.*ALLOCDEF.*"\(.*\)".*$:struct \1 *h_\1 = 0;:p | ||||||
|  | ' $* | ||||||
							
								
								
									
										34
									
								
								lang/cem/cpp.ansi/make.tokcase
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										34
									
								
								lang/cem/cpp.ansi/make.tokcase
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,34 @@ | ||||||
|  | cat <<'--EOT--' | ||||||
|  | #include "Lpars.h" | ||||||
|  | 
 | ||||||
|  | char * | ||||||
|  | symbol2str(tok) | ||||||
|  | 	int tok; | ||||||
|  | { | ||||||
|  | 	static char buf[2] = { '\0', '\0' }; | ||||||
|  | 
 | ||||||
|  | 	if (040 <= tok && tok < 0177) { | ||||||
|  | 		buf[0] = tok; | ||||||
|  | 		buf[1] = '\0'; | ||||||
|  | 		return buf; | ||||||
|  | 	} | ||||||
|  | 	switch (tok) { | ||||||
|  | --EOT-- | ||||||
|  | sed ' | ||||||
|  | /{[A-Z]/!d | ||||||
|  | s/.*{\(.*\),.*\(".*"\).*$/	case \1 :\ | ||||||
|  | 		return \2;/ | ||||||
|  | ' | ||||||
|  | cat <<'--EOT--' | ||||||
|  | 	case '\n': | ||||||
|  | 	case '\f': | ||||||
|  | 	case '\v': | ||||||
|  | 	case '\r': | ||||||
|  | 	case '\t': | ||||||
|  | 		buf[0] = tok; | ||||||
|  | 		return buf; | ||||||
|  | 	default: | ||||||
|  | 		return "bad token"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | --EOT-- | ||||||
							
								
								
									
										6
									
								
								lang/cem/cpp.ansi/make.tokfile
									
										
									
									
									
										Executable file
									
								
							
							
						
						
									
										6
									
								
								lang/cem/cpp.ansi/make.tokfile
									
										
									
									
									
										Executable file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | sed ' | ||||||
|  | /{[A-Z]/!d | ||||||
|  | s/.*{// | ||||||
|  | s/,.*// | ||||||
|  | s/.*/%token	&;/ | ||||||
|  | ' | ||||||
							
								
								
									
										74
									
								
								lang/cem/cpp.ansi/nccp.6
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								lang/cem/cpp.ansi/nccp.6
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,74 @@ | ||||||
|  | .TH NCPP 6ACK | ||||||
|  | .ad | ||||||
|  | .SH NAME | ||||||
|  | ncpp \- New C Pre-Processor | ||||||
|  | .SH SYNOPSIS | ||||||
|  | ncpp [\-options] [ file ] | ||||||
|  | .SH DESCRIPTION | ||||||
|  | .I Ncpp | ||||||
|  | reads a file, expands macros and include | ||||||
|  | files, and writes an input file for the C compiler. | ||||||
|  | All output is to standard output. | ||||||
|  | .br | ||||||
|  | The following options are supported. | ||||||
|  | .IP -\fBI\fIdirectory\fR | ||||||
|  | .br | ||||||
|  | add this directory to the list of | ||||||
|  | directories searched for #include "..." and #include <...> | ||||||
|  | commands.  Note that there is no space between the | ||||||
|  | "-I" and the directory string.  More than one -I command | ||||||
|  | is permitted. | ||||||
|  | .IP -\fBI\fR | ||||||
|  | end the list of directories to be searched, and also do not look in | ||||||
|  | default places. | ||||||
|  | .IP -\fBD\fIname\fR=\fItext\fR | ||||||
|  | .br | ||||||
|  | define  | ||||||
|  | .I name | ||||||
|  | as a macro with | ||||||
|  | .I text | ||||||
|  | as its replacement text. | ||||||
|  | .IP -\fBD\fIname\fR | ||||||
|  | the same as -\fBD\fIname\fR=1. | ||||||
|  | .IP | ||||||
|  | .IP -\fBU\fIname\fR | ||||||
|  | .br | ||||||
|  | undefine the macro name | ||||||
|  | .IR name . | ||||||
|  | .IP -\fBC\fR | ||||||
|  | leave comments in. By default, C-comments are deleted. | ||||||
|  | .IP -\fBP\fR | ||||||
|  | do not generate line directives | ||||||
|  | .IP -\fBM\fIn\fR | ||||||
|  | set maximum identifier length to | ||||||
|  | .IR n . | ||||||
|  | .PP | ||||||
|  | The following names are always available unless undefined: | ||||||
|  | .RS | ||||||
|  | .IP __STDC__ | ||||||
|  | A decimal constant 1, indicating that this is an ANSI C conforming | ||||||
|  | implementation. | ||||||
|  | .IP __FILE__ | ||||||
|  | The input (or #include) file being compiled | ||||||
|  | (as a quoted string). | ||||||
|  | .IP __LINE__ | ||||||
|  | The line number being compiled. | ||||||
|  | .IP __DATE__ | ||||||
|  | The date of translation of the source file. This is a string | ||||||
|  | literal of the form "\fBMmm dd yyyy\fP". | ||||||
|  | .IP __TIME__ | ||||||
|  | The time of translation of the source file. This is a string | ||||||
|  | literal of the form "\fBhh:mm:ss\fP". | ||||||
|  | .RE | ||||||
|  | .SH BUGS | ||||||
|  | The output may contain extra spaces, this prevents unintended | ||||||
|  | pasting of tokens. | ||||||
|  | .SH "SEE ALSO" | ||||||
|  | L. Rosler, | ||||||
|  | .I | ||||||
|  | Draft Proposed Standard - Programming Language C, | ||||||
|  | .R | ||||||
|  | ANSI X3J11 Language Subcommittee | ||||||
|  | .SH AUTHOR | ||||||
|  | Leendert van Doorn | ||||||
|  | 
 | ||||||
							
								
								
									
										133
									
								
								lang/cem/cpp.ansi/options.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								lang/cem/cpp.ansi/options.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,133 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* USER-OPTION HANDLING */ | ||||||
|  | 
 | ||||||
|  | #include	<alloc.h> | ||||||
|  | #include	"idfsize.h" | ||||||
|  | #include	"class.h" | ||||||
|  | #include	"macro.h" | ||||||
|  | #include	"idf.h" | ||||||
|  | 
 | ||||||
|  | char	options[128];			/* one for every char	*/ | ||||||
|  | int	inc_pos = 1;			/* place where next -I goes */ | ||||||
|  | int	inc_max; | ||||||
|  | int	inc_total; | ||||||
|  | int	debug; | ||||||
|  | char	**inctable; | ||||||
|  | 
 | ||||||
|  | extern int idfsize; | ||||||
|  | int	txt2int(); | ||||||
|  | 
 | ||||||
|  | do_option(text) | ||||||
|  | 	char *text; | ||||||
|  | { | ||||||
|  | 	switch(*text++)	{ | ||||||
|  | 	case '-': | ||||||
|  | 		options[*text] = 1; | ||||||
|  | 		break; | ||||||
|  | 	default: | ||||||
|  | 		error("illegal option: %c", text[-1]); | ||||||
|  | 		break; | ||||||
|  | 	case 'C' :	/* comment output		*/ | ||||||
|  | 		options['C'] = 1; | ||||||
|  | 		break; | ||||||
|  | 	case 'D' :	/* -Dname :	predefine name		*/ | ||||||
|  | 	{ | ||||||
|  | 		register char *cp = text, *name, *mactext; | ||||||
|  | 
 | ||||||
|  | 		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 */ | ||||||
|  | 			mactext = "1"; | ||||||
|  | 		else | ||||||
|  | 		if (*cp == '=')	{		/* -Dname=text	*/ | ||||||
|  | 			*cp++ = '\0';		/* end of name	*/ | ||||||
|  | 			mactext = cp; | ||||||
|  | 		} | ||||||
|  | 		else	{			/* -Dname?? */ | ||||||
|  | 			error("malformed option -D%s", text); | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 		macro_def(str2idf(name, 0), mactext, -1, strlen(mactext), NOFLAG); | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | 	case 'I' :	/* -Ipath : insert "path" into include list	*/ | ||||||
|  | 		if (*text)	{ | ||||||
|  | 			register int i; | ||||||
|  | 			register char *new = text; | ||||||
|  | 
 | ||||||
|  | 			if (++inc_total > inc_max) { | ||||||
|  | 				char **n = (char **) | ||||||
|  | 				   Malloc((10 + inc_max) * sizeof(char *)); | ||||||
|  | 
 | ||||||
|  | 				for (i = 0; i < inc_max; i++) { | ||||||
|  | 					n[i] = inctable[i]; | ||||||
|  | 				} | ||||||
|  | 				free((char *) inctable); | ||||||
|  | 				inctable = n; | ||||||
|  | 				inc_max += 10; | ||||||
|  | 			} | ||||||
|  | 			 | ||||||
|  | 			i = inc_pos++; | ||||||
|  | 			while (new)	{ | ||||||
|  | 				register char *tmp = inctable[i]; | ||||||
|  | 				 | ||||||
|  | 				inctable[i++] = new; | ||||||
|  | 				new = tmp; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		else	inctable[inc_pos] = 0; | ||||||
|  | 		break; | ||||||
|  | 	case 'M':	/* maximum identifier length */ | ||||||
|  | 		idfsize = txt2int(&text); | ||||||
|  | 		if (*text) | ||||||
|  | 			error("malformed -M option"); | ||||||
|  | 		if (idfsize > IDFSIZE) { | ||||||
|  | 			warning("maximum identifier length is %d", IDFSIZE); | ||||||
|  | 			idfsize = IDFSIZE; | ||||||
|  | 		} | ||||||
|  | 		if (idfsize < 8) { | ||||||
|  | 			warning("minimum identifier length is 8"); | ||||||
|  | 			idfsize = 8; | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	case 'P' :	/* run preprocessor stand-alone, without #'s	*/ | ||||||
|  | 		options['P'] = 1; | ||||||
|  | 		break; | ||||||
|  | 	case 'U' :	/* -Uname :	undefine predefined	*/ | ||||||
|  | 		if (*text)	{ | ||||||
|  | 			register struct idf *idef = findidf(text); | ||||||
|  | 
 | ||||||
|  | 			if (idef && idef->id_macro) { | ||||||
|  | 				free_macro(idef->id_macro); | ||||||
|  | 				idef->id_macro = (struct macro *) 0; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		break; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int | ||||||
|  | txt2int(tp) | ||||||
|  | 	char **tp; | ||||||
|  | { | ||||||
|  | 	/*	the integer pointed to by *tp is read, while increasing
 | ||||||
|  | 		*tp; the resulting value is yielded. | ||||||
|  | 	*/ | ||||||
|  | 	register int val = 0; | ||||||
|  | 	register int ch; | ||||||
|  | 	 | ||||||
|  | 	while (ch = **tp, ch >= '0' && ch <= '9')	{ | ||||||
|  | 		val = val * 10 + ch - '0'; | ||||||
|  | 		(*tp)++; | ||||||
|  | 	} | ||||||
|  | 	return val; | ||||||
|  | } | ||||||
							
								
								
									
										326
									
								
								lang/cem/cpp.ansi/preprocess.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										326
									
								
								lang/cem/cpp.ansi/preprocess.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,326 @@ | ||||||
|  | /*
 | ||||||
|  |  * (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	"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	"line_prefix.h" | ||||||
|  | 
 | ||||||
|  | char	_obuf[OBUFSIZE]; | ||||||
|  | #ifdef DOBITS | ||||||
|  | char	bits[128]; | ||||||
|  | #endif | ||||||
|  | extern int InputLevel; | ||||||
|  | 
 | ||||||
|  | Xflush() | ||||||
|  | { | ||||||
|  | 	sys_write(STDOUT, _obuf, OBUFSIZE); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | preprocess(fn) | ||||||
|  | 	char *fn; | ||||||
|  | { | ||||||
|  | 	register int c; | ||||||
|  | 	register char *op = _obuf; | ||||||
|  | 	register char *ob = &_obuf[OBUFSIZE]; | ||||||
|  | 	char Xbuf[256]; | ||||||
|  | 	int lineno = 0; | ||||||
|  | 	extern char options[]; | ||||||
|  | 
 | ||||||
|  | #define flush(X)	(sys_write(STDOUT,_obuf,X)) | ||||||
|  | #define echo(ch) 	if (op == ob) { Xflush(); op = _obuf; } *op++ = (ch); | ||||||
|  | #define newline()	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(lineno, fn)						\ | ||||||
|  | 		if (lineno != LineNumber || fn != FileName) {		\ | ||||||
|  | 			fn = FileName;					\ | ||||||
|  | 			lineno = LineNumber;				\ | ||||||
|  | 			if (! options['P']) {				\ | ||||||
|  | 				register char *p = Xbuf;		\ | ||||||
|  | 									\ | ||||||
|  | 				sprint(p, "%s %d \"%s\"\n",		\ | ||||||
|  | 					LINE_PREFIX,			\ | ||||||
|  | 					LineNumber,			\ | ||||||
|  | 					FileName);			\ | ||||||
|  | 				while (*p) {				\ | ||||||
|  | 					echo(*p++);			\ | ||||||
|  | 				}					\ | ||||||
|  | 			}						\ | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 	for (;;) { | ||||||
|  | 		LineNumber++; | ||||||
|  | 		lineno++; | ||||||
|  | 		c = GetChar(); | ||||||
|  | 		while (class(c) == STSKIP) { | ||||||
|  | 			echo(c); | ||||||
|  | 			c = GetChar(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		while (c == '#') { | ||||||
|  | 			if (!domacro()) {	/* pass pragma's to compiler */ | ||||||
|  | 				register char *p = "#pragma"; | ||||||
|  | 
 | ||||||
|  | 				do_line(lineno, fn); | ||||||
|  | 
 | ||||||
|  | 				while(*p) { | ||||||
|  | 					echo(*p++); | ||||||
|  | 				} | ||||||
|  | 				while ((c = GetChar()) != EOI) { | ||||||
|  | 					if (class(c) == STNL) break; | ||||||
|  | 					echo(c); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			lineno++; | ||||||
|  | 			newline(); | ||||||
|  | 			c = GetChar(); | ||||||
|  | 			while (class(c) == STSKIP) { | ||||||
|  | 				echo(c); | ||||||
|  | 				c = GetChar(); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		do_line(lineno, fn); | ||||||
|  | 		for (;;) { | ||||||
|  | 
 | ||||||
|  | 			/* illegal character */ | ||||||
|  | 			if (c & 0200)  { | ||||||
|  | 				if (c == EOI) { | ||||||
|  | 					newline(); | ||||||
|  | 					flush(op-_obuf); | ||||||
|  | 					return; | ||||||
|  | 				} | ||||||
|  | 				fatal("non-ascii character read"); | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			/* comments */ | ||||||
|  | 			if (c == '/' && !InputLevel) { | ||||||
|  | 				c = GetChar(); | ||||||
|  | 				if (c == '*') { | ||||||
|  | 					NoUnstack++; | ||||||
|  | 					if (options['C']) { | ||||||
|  | 						echo('/'); | ||||||
|  | 						echo('*'); | ||||||
|  | 					} | ||||||
|  | 					for (;;) { | ||||||
|  | 						c = GetChar(); | ||||||
|  | 						if (c == '\n') { | ||||||
|  | 							++LineNumber; | ||||||
|  | 							++lineno; | ||||||
|  | 							echo(c); | ||||||
|  | 						} | ||||||
|  | 						else if (c == EOI) { | ||||||
|  | 							newline(); | ||||||
|  | 							flush(op - _obuf); | ||||||
|  | 							return; | ||||||
|  | 						} | ||||||
|  | 						else if (c == '*') { | ||||||
|  | 							if (options['C']) { | ||||||
|  | 								echo(c); | ||||||
|  | 							} | ||||||
|  | 							c = GetChar(); | ||||||
|  | 							if (c == '/') { | ||||||
|  | 							   if (options['C']) { | ||||||
|  | 								echo(c); | ||||||
|  | 							   } | ||||||
|  | 							   break; | ||||||
|  | 							} | ||||||
|  | 							else { | ||||||
|  | 								UnGetChar(); | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 						else if (options['C']) { | ||||||
|  | 							echo(c); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 					NoUnstack--; | ||||||
|  | 					c = GetChar(); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				echo('/'); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			/* switch on character */ | ||||||
|  | 			switch(class(c)) { | ||||||
|  | 			case STNL: | ||||||
|  | 				echo(c); | ||||||
|  | 				break; | ||||||
|  | 			case STSTR: | ||||||
|  | 			case STCHAR: | ||||||
|  | 				{ | ||||||
|  | 				register int stopc = c; | ||||||
|  | 				int escaped; | ||||||
|  | 
 | ||||||
|  | 				do { | ||||||
|  | 
 | ||||||
|  | 					escaped = 0; | ||||||
|  | 					echo(c); | ||||||
|  | 					c = GetChar(); | ||||||
|  | 					if (c == '\n') { | ||||||
|  | 						break; | ||||||
|  | 					} | ||||||
|  | 					else if (c == EOI) { | ||||||
|  | 						newline(); | ||||||
|  | 						flush(op-_obuf); | ||||||
|  | 						return; | ||||||
|  | 					} | ||||||
|  | 					if (c == '\\') { | ||||||
|  | 						echo(c); | ||||||
|  | 						c = GetChar(); | ||||||
|  | 						if (c == '\n') { | ||||||
|  | 							++LineNumber; | ||||||
|  | 							lineno++; | ||||||
|  | 						} | ||||||
|  | 						else if (c == '\'') escaped = 1; | ||||||
|  | 					} | ||||||
|  | 				} while (escaped || c != stopc); | ||||||
|  | 				echo(c); | ||||||
|  | 				if (c == '\n') | ||||||
|  | 					break;	/* Don't eat # */ | ||||||
|  | 				c = GetChar(); | ||||||
|  | 				continue; | ||||||
|  | 				} | ||||||
|  | 			case STNUM: | ||||||
|  | 				echo(c); | ||||||
|  | 				if (c == '.') { | ||||||
|  | 					c = GetChar(); | ||||||
|  | 					if (c == '.') { | ||||||
|  | 						if ((c = GetChar()) == '.') { | ||||||
|  | 							echo('.'); echo('.'); | ||||||
|  | 							continue; | ||||||
|  | 						} | ||||||
|  | 						UnGetChar(); | ||||||
|  | 						c = '.'; | ||||||
|  | 						continue; | ||||||
|  | 					} else if (!is_dig(c)) { | ||||||
|  | 						continue; | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 				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: | ||||||
|  | 				if (c == '"' || c == '\'') { | ||||||
|  | 					echo(c); | ||||||
|  | 					continue; | ||||||
|  | 				} | ||||||
|  | 				UnGetChar(); | ||||||
|  | 				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)) { | ||||||
|  | 						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*/ | ||||||
|  | } | ||||||
							
								
								
									
										703
									
								
								lang/cem/cpp.ansi/replace.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										703
									
								
								lang/cem/cpp.ansi/replace.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,703 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /*  M A C R O   R E P L A C E M E N T */ | ||||||
|  | 
 | ||||||
|  | #include	"pathlength.h" | ||||||
|  | #include	"strsize.h" | ||||||
|  | #include	"nparams.h" | ||||||
|  | #include	"idfsize.h" | ||||||
|  | #include	"numsize.h" | ||||||
|  | #include	<alloc.h> | ||||||
|  | #include	"idf.h" | ||||||
|  | #include	"input.h" | ||||||
|  | #include	"macro.h" | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | #include	"class.h" | ||||||
|  | #include	<assert.h> | ||||||
|  | #include	"lapbuf.h" | ||||||
|  | #include	"argbuf.h" | ||||||
|  | #include	"replace.h" | ||||||
|  | 
 | ||||||
|  | extern char *GetIdentifier(); | ||||||
|  | extern int InputLevel; | ||||||
|  | struct repl *ReplaceList;	/* list of currently active macros */ | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 	repl->r_args = new_args(); | ||||||
|  | 	repl->r_idf = idf; | ||||||
|  | 	if (!expand_macro(repl, idf)) | ||||||
|  | 		return 0; | ||||||
|  | 	InputLevel++; | ||||||
|  | 	InsertText(repl->r_text, 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++; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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_args(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)); | ||||||
|  | 			*/ | ||||||
|  | 			if (!AccDefined) return 0; | ||||||
|  | 			expand_defined(repl); | ||||||
|  | 			return 1; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		ch = GetChar(); | ||||||
|  | 		ch = skipspaces(ch,1); | ||||||
|  | 		if (ch != '(') {	/* no replacement if no () */ | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			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. Because this preprocessor is | ||||||
|  | 		character based, we have a problem. | ||||||
|  | 		For now: just insert a space after all tokens, | ||||||
|  | 		until ANSI fixes this flaw. | ||||||
|  | 		^^^^^^^^^^^^^^^^^^^^^^^^^^	tsk tsk tsk | ||||||
|  | 	*/ | ||||||
|  | 	if (*repl->r_ptr != TOKSEP) *repl->r_ptr++ = TOKSEP; | ||||||
|  | 	*repl->r_ptr = '\0'; | ||||||
|  | 
 | ||||||
|  | 	return 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | expand_defined(repl) | ||||||
|  | 	register struct repl *repl; | ||||||
|  | { | ||||||
|  | 	register int ch = GetChar(); | ||||||
|  | 	struct idf *id; | ||||||
|  | 	char *str; | ||||||
|  | 	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 != ')') UnGetChar(); | ||||||
|  | 		*repl->r_ptr++ = '0'; | ||||||
|  | 		*repl->r_ptr = '\0'; | ||||||
|  | 		return; | ||||||
|  | 	} | ||||||
|  | 	UnGetChar(); | ||||||
|  | 	str = GetIdentifier(0); | ||||||
|  | 	if (str) | ||||||
|  | 		id = str2idf(str, 0); | ||||||
|  | 	else	id = 0; | ||||||
|  | 	assert(id || class(ch) == STELL); | ||||||
|  | 	ch = GetChar(); | ||||||
|  | 	ch = skipspaces(ch, 0); | ||||||
|  | 	if (parens && ch != ')') error(") missing"); | ||||||
|  | 	if (!parens || ch != ')') UnGetChar(); | ||||||
|  | 	*repl->r_ptr++ = (id && id->id_macro) ? '1' : '0'; | ||||||
|  | 	*repl->r_ptr = '\0'; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 	args->a_expvec[0] = args->a_expptr = &args->a_expbuf[0]; | ||||||
|  | 	args->a_rawvec[0] = args->a_rawptr = &args->a_rawbuf[0]; | ||||||
|  | 	if ((ch = GetChar()) != ')') { | ||||||
|  | 		UnGetChar(); | ||||||
|  | 		while ((ch = actual(repl)) != ')' ) { | ||||||
|  | 			if (ch != ',') { | ||||||
|  | 				error("illegal macro call"); | ||||||
|  | 				return; | ||||||
|  | 			} | ||||||
|  | 			stash(repl, '\0', 1); | ||||||
|  | 			++argcnt; | ||||||
|  | 			args->a_expvec[argcnt] = args->a_expptr; | ||||||
|  | 			args->a_rawvec[argcnt] = args->a_rawptr; | ||||||
|  | 			if (argcnt == STDC_NPARAMS) | ||||||
|  | 				strict("number of parameters exceeds ANSI standard"); | ||||||
|  | 			if (argcnt >= NPARAMS) | ||||||
|  | 				fatal("argument vector overflow"); | ||||||
|  | 		} | ||||||
|  | 		stash(repl, '\0', 1); | ||||||
|  | 		++argcnt; | ||||||
|  | 	} | ||||||
|  | 	if (argcnt < nps) | ||||||
|  | 		error("too few macro arguments"); | ||||||
|  | 	else if (argcnt > nps) | ||||||
|  | 		error("too many macro arguments"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | saveraw(repl) | ||||||
|  | struct repl *repl; | ||||||
|  | { | ||||||
|  | 	register struct repl *nrepl = ReplaceList; | ||||||
|  | 	register struct args *ap = nrepl->r_args; | ||||||
|  | 	struct args *args = repl->r_args; | ||||||
|  | 	register char *p; | ||||||
|  | 
 | ||||||
|  | 	/* stash identifier name */ | ||||||
|  | 	for (p = nrepl->r_idf->id_text; *p != '\0'; p++) | ||||||
|  | 		*args->a_rawptr++ = *p; | ||||||
|  | 
 | ||||||
|  | 	/*	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; | ||||||
|  | 
 | ||||||
|  | 		*args->a_rawptr++ = '('; | ||||||
|  | 		for (i = 0; ap->a_rawvec[i] != (char *)0; i++) { | ||||||
|  | 			for (p = ap->a_rawvec[i]; *p != '\0'; p++) | ||||||
|  | 				*args->a_rawptr++ = *p; | ||||||
|  | 			*args->a_rawptr++ = ','; | ||||||
|  | 		} | ||||||
|  | 		*(args->a_rawptr-1) = ')';	/* delete last ',' */ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 	register int level = 0, nostashraw = 0; | ||||||
|  | 
 | ||||||
|  | 	while (1) { | ||||||
|  | 		ch = GetChar(); | ||||||
|  | 
 | ||||||
|  | 		if (Unstacked) { | ||||||
|  | 			nostashraw -= Unstacked; | ||||||
|  | 			if (nostashraw < 0) 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'; | ||||||
|  | 			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) { | ||||||
|  | 					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(); | ||||||
|  | 					} | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			UnGetChar(); | ||||||
|  | 		} else if (ch == '(' || ch == '[' || ch == '{') { | ||||||
|  | 			/* a comma may occur within these constructions ???
 | ||||||
|  | 			 */ | ||||||
|  | 			level++; | ||||||
|  | 			stash(repl, ch, !nostashraw); | ||||||
|  | 		} else if (ch == ')' || ch == ']' || ch == '}') { | ||||||
|  | 			level--; | ||||||
|  | 			/* clossing parenthesis of macro call */ | ||||||
|  | 			if (ch == ')' && level < 0) | ||||||
|  | 				return ')'; | ||||||
|  | 			stash(repl, ch, !nostashraw); | ||||||
|  | 		} else if (ch == ',') { | ||||||
|  | 			if (level <= 0) { /* comma separator for next argument */ | ||||||
|  | 				if (level) | ||||||
|  | 					error("unbalanced parenthesis"); | ||||||
|  | 				if (!nostashraw) | ||||||
|  | 					return ',';	/* ??? */ | ||||||
|  | 			} | ||||||
|  | 			stash(repl, ch, !nostashraw); | ||||||
|  | 		} else if (ch == '\n') { | ||||||
|  | 			/* newlines are accepted as white spaces */ | ||||||
|  | 			LineNumber++; | ||||||
|  | 			while ((ch = GetChar()), class(ch) == STSKIP) | ||||||
|  | 				/* EMPTY */; | ||||||
|  | 
 | ||||||
|  | 			/*	This piece of code needs some explanation:
 | ||||||
|  | 				consider the call of a macro defined as: | ||||||
|  | 					#define sum(a,b) (a+b) | ||||||
|  | 				in the following form: | ||||||
|  | 					sum( | ||||||
|  | 					#include phone_number | ||||||
|  | 					,2); | ||||||
|  | 				in which case the include must be handled | ||||||
|  | 				interpreted as such. | ||||||
|  | 			*/ | ||||||
|  | 			if (ch == '#') | ||||||
|  | 				domacro(); | ||||||
|  | 			else if (ch == EOI) { | ||||||
|  | 				error("unterminated macro call"); | ||||||
|  | 				return ')'; | ||||||
|  | 			} | ||||||
|  | 			UnGetChar(); | ||||||
|  | 			stash(repl, ' ', !nostashraw); | ||||||
|  | 		} else if (ch == '/') { | ||||||
|  | 			/* comments are treated as one white space token */ | ||||||
|  | 			if ((ch = GetChar()) == '*' && !InputLevel) { | ||||||
|  | 				skipcomment(); | ||||||
|  | 				stash(repl, ' ', !nostashraw); | ||||||
|  | 			} else { | ||||||
|  | 				UnGetChar(); | ||||||
|  | 				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') { | ||||||
|  | 					error("newline in string"); | ||||||
|  | 					LineNumber++; | ||||||
|  | 					stash(repl, match, !nostashraw); | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 				stash(repl, ch, !nostashraw); | ||||||
|  | 			} | ||||||
|  | 			if (ch != match) { | ||||||
|  | 				error("unterminated macro call"); | ||||||
|  | 				return ')'; | ||||||
|  | 			} | ||||||
|  | 			stash(repl, ch, !nostashraw); | ||||||
|  | 		} else | ||||||
|  | 			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]; | ||||||
|  | 	char *long2str(); | ||||||
|  | 
 | ||||||
|  | 	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*/ | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 	register char *tmpptr; | ||||||
|  | 	int err = 0; | ||||||
|  | 	char *stringify(); | ||||||
|  | 
 | ||||||
|  | 	while (*ptr) { | ||||||
|  | 	    assert(repl->r_ptr < &(repl->r_text[LAPBUF])); | ||||||
|  | 	    if (*ptr == '\'' || *ptr == '"') { | ||||||
|  | 		register int delim = *ptr; | ||||||
|  | 
 | ||||||
|  | 		do { | ||||||
|  | 		    *repl->r_ptr++ = *ptr; | ||||||
|  | 		    if (*ptr == '\\') | ||||||
|  | 			    *repl->r_ptr++ = *++ptr; | ||||||
|  | 		    if (*ptr == '\0') { | ||||||
|  | 			    error("unterminated string"); | ||||||
|  | 			    *repl->r_ptr = '\0'; | ||||||
|  | 			    return; | ||||||
|  | 		    } | ||||||
|  | 		    ptr++; | ||||||
|  | 		} while (*ptr != delim || *ptr == '\0'); | ||||||
|  | 		*repl->r_ptr++ = *ptr++; | ||||||
|  | 	    } else if (*ptr == '#') { | ||||||
|  | 		if (*++ptr == '#') { | ||||||
|  | 			/* ## - paste operator */ | ||||||
|  | 		    ptr++; | ||||||
|  | 
 | ||||||
|  | 			/* trim the actual replacement list */ | ||||||
|  | 		    --repl->r_ptr; | ||||||
|  | 		    while (is_wsp(*repl->r_ptr) | ||||||
|  | 				&& repl->r_ptr >= repl->r_text) | ||||||
|  | 			    --repl->r_ptr; | ||||||
|  | 
 | ||||||
|  | 		    /*	## occurred at the beginning of the
 | ||||||
|  | 			    replacement list. | ||||||
|  | 		    */ | ||||||
|  | 		    if (repl->r_ptr == repl->r_text | ||||||
|  | 				&& is_wsp(*repl->r_text)) { | ||||||
|  | 			    err = 1; | ||||||
|  | 			    break; | ||||||
|  | 		    } | ||||||
|  | 
 | ||||||
|  | 		    while(*repl->r_ptr == TOKSEP | ||||||
|  | 				&& repl->r_ptr >= repl->r_text) | ||||||
|  | 			    --repl->r_ptr; | ||||||
|  | 
 | ||||||
|  | 		    tmpptr = repl->r_ptr; | ||||||
|  | 		    ++repl->r_ptr; | ||||||
|  | 
 | ||||||
|  | 		    /* 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) | ||||||
|  | 				*repl->r_ptr++ = *p++; | ||||||
|  | 			} | ||||||
|  | 			if (in_idf(*tmpptr + 1)) { | ||||||
|  | 				while (in_idf(*tmpptr) | ||||||
|  | 					    && tmpptr >= repl->r_text) | ||||||
|  | 					tmpptr--; | ||||||
|  | 				if (*tmpptr == NOEXPM) *tmpptr = TOKSEP; | ||||||
|  | 			} | ||||||
|  | 		    } else if (*ptr == '\0') { | ||||||
|  | 			    err = 1; | ||||||
|  | 			    break; | ||||||
|  | 		    } else { | ||||||
|  | 			    if (in_idf(*ptr)) { | ||||||
|  | 				while (in_idf(*tmpptr) | ||||||
|  | 					    && tmpptr >= repl->r_text) | ||||||
|  | 					tmpptr--; | ||||||
|  | 				if (*tmpptr == NOEXPM) *tmpptr = TOKSEP; | ||||||
|  | 			    } | ||||||
|  | 		    } | ||||||
|  | 		} 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
 | ||||||
|  | 			## operater. 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]; | ||||||
|  | 
 | ||||||
|  | 		p = repl->r_ptr; | ||||||
|  | 		if (q)			/* else macro argument missing */ | ||||||
|  | 		    while (*q) | ||||||
|  | 			*repl->r_ptr++ = *q++; | ||||||
|  | 
 | ||||||
|  | 		if (*repl->r_ptr != TOKSEP) | ||||||
|  | 			*repl->r_ptr++ = TOKSEP; | ||||||
|  | 	    } else | ||||||
|  | 		*repl->r_ptr++ = *ptr++; | ||||||
|  | 	} | ||||||
|  | 	*repl->r_ptr = '\0'; | ||||||
|  | 	if (err) | ||||||
|  | 		error("illegal use of ## 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]; | ||||||
|  | 		*repl->r_ptr++ = '"'; | ||||||
|  | 		while (*p) { | ||||||
|  | 			if (is_wsp(*p)) { | ||||||
|  | 				if (!space) { | ||||||
|  | 					space = 1; | ||||||
|  | 					*repl->r_ptr++ = ' '; | ||||||
|  | 				} | ||||||
|  | 				p++; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 			space = 0; | ||||||
|  | 
 | ||||||
|  | 			if (!delim && (*p == '"' || *p == '\'')) | ||||||
|  | 				delim = *p; | ||||||
|  | 			else if (*p == delim && !backslash) | ||||||
|  | 				delim = 0; | ||||||
|  | 			backslash = *p == '\\'; | ||||||
|  | 			if (*p == '"' || (delim && *p == '\\')) | ||||||
|  | 				*repl->r_ptr++ = '\\'; | ||||||
|  | 			if (*p == TOKSEP || *p == NOEXPM) p++; | ||||||
|  | 			else *repl->r_ptr++ = *p++; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		/* trim spaces in the replacement list */ | ||||||
|  | 		for (--repl->r_ptr; is_wsp(*repl->r_ptr); repl->r_ptr--) | ||||||
|  | 			/* EMPTY */; | ||||||
|  | 		*++repl->r_ptr = '"'; | ||||||
|  | 		++repl->r_ptr;	/* oops, one to far */ | ||||||
|  | 	} else | ||||||
|  | 		error("illegal use of # operator"); | ||||||
|  | 	*repl->r_ptr = '\0'; | ||||||
|  | 	return ptr; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 
 | ||||||
|  | 	if (args->a_expptr >= &(args->a_expbuf[ARGBUF])) | ||||||
|  | 		fatal("macro argument buffer overflow"); | ||||||
|  | 	*args->a_expptr++ = ch; | ||||||
|  | 
 | ||||||
|  | 	if (stashraw) { | ||||||
|  | 		if (args->a_rawptr >= &(args->a_rawbuf[ARGBUF])) | ||||||
|  | 			fatal("raw macro argument buffer overflow"); | ||||||
|  | 		*args->a_rawptr++ = ch; | ||||||
|  | 	} | ||||||
|  | } | ||||||
							
								
								
									
										48
									
								
								lang/cem/cpp.ansi/replace.str
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								lang/cem/cpp.ansi/replace.str
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,48 @@ | ||||||
|  | /* | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* 	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 */ | ||||||
|  | 	char	*r_ptr;			/* replacement text pointer */ | ||||||
|  | 	char	r_text[LAPBUF];		/* 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); | ||||||
|  | 
 | ||||||
|  | 	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 pointer */ | ||||||
|  | 	char	*a_expvec[NPARAMS];	/* expanded argument vector */ | ||||||
|  | 	char	a_expbuf[ARGBUF];	/* expanded argument buffer space */ | ||||||
|  | 	char	*a_rawptr;		/* raw argument pointer */ | ||||||
|  | 	char	*a_rawvec[NPARAMS];	/* raw argument vector */ | ||||||
|  | 	char	a_rawbuf[ARGBUF];	/* raw argument buffer space */ | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* ALLOCDEF "args" 2 */ | ||||||
|  | 
 | ||||||
|  | #define NO_ARGS		(struct args *)0 | ||||||
|  | 
 | ||||||
							
								
								
									
										77
									
								
								lang/cem/cpp.ansi/skip.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								lang/cem/cpp.ansi/skip.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,77 @@ | ||||||
|  | /*
 | ||||||
|  |  * (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: INPUT SKIP FUNCTIONS */ | ||||||
|  | 
 | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | #include	"class.h" | ||||||
|  | #include	"input.h" | ||||||
|  | 
 | ||||||
|  | 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; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | SkipToNewLine(garbage) | ||||||
|  | 	int garbage; | ||||||
|  | { | ||||||
|  | 	register int ch; | ||||||
|  | 	register int pstrict = 0; | ||||||
|  | 
 | ||||||
|  | 	while ((ch = GetChar()) != '\n') { | ||||||
|  | 		if (ch == '/') { | ||||||
|  | 			if ((ch = GetChar()) == '*' && !InputLevel) { | ||||||
|  | 				skipcomment(); | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if (garbage && !is_wsp(ch)) | ||||||
|  | 			pstrict = 1; | ||||||
|  | 	} | ||||||
|  | 	++LineNumber; | ||||||
|  | 	return pstrict; | ||||||
|  | } | ||||||
							
								
								
									
										72
									
								
								lang/cem/cpp.ansi/tokenname.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								lang/cem/cpp.ansi/tokenname.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | /*
 | ||||||
|  |  * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. | ||||||
|  |  * See the copyright notice in the ACK home directory, in the file "Copyright". | ||||||
|  |  */ | ||||||
|  | /* $Header$ */ | ||||||
|  | /* TOKEN NAME DEFINITIONS */ | ||||||
|  | 
 | ||||||
|  | #include	"idf.h" | ||||||
|  | #include	"arith.h" | ||||||
|  | #include	"LLlex.h" | ||||||
|  | #include	"Lpars.h" | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | struct tokenname	{	/*	Used for defining the name of a
 | ||||||
|  | 					token as identified by its symbol | ||||||
|  | 				*/ | ||||||
|  | 	int tn_symbol; | ||||||
|  | 	char *tn_name; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /*	To centralize the declaration of %tokens, their presence in this
 | ||||||
|  | 	file is taken as their declaration. The Makefile will produce | ||||||
|  | 	a grammar file (tokenfile.g) from this file. | ||||||
|  | 	Moreover, rather than looking up a symbol in all these lists | ||||||
|  | 	to find its printable name, a fast version of symbol2str() is | ||||||
|  | 	generated from these tables. | ||||||
|  | 	Consequenty some of these tables are not referenced explicitly | ||||||
|  | 	in the C text any more.  To save space and to avoid lint confusion, | ||||||
|  | 	these have been made pseudo-invisible by #ifdefs. | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | #ifdef	____ | ||||||
|  | struct tokenname tkspec[] =	{	/* the names of the special tokens */ | ||||||
|  | 	{IDENTIFIER, "identifier"}, | ||||||
|  | 	{STRING, "string"}, | ||||||
|  | 	{FILESPECIFIER, "filespecifier"}, | ||||||
|  | 	{INTEGER, "integer"}, | ||||||
|  | 	{0, ""} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct tokenname tkcomp[] =	{	/* names of the composite tokens */ | ||||||
|  |         {PLUSAB, "+="}, | ||||||
|  |         {MINAB, "-="}, | ||||||
|  |         {TIMESAB, "*="}, | ||||||
|  |         {DIVAB, "/="}, | ||||||
|  |         {MODAB, "%="}, | ||||||
|  |         {LEFTAB, "<<="}, | ||||||
|  |         {RIGHTAB, ">>="}, | ||||||
|  |         {ANDAB, "&="}, | ||||||
|  |         {XORAB, "^="}, | ||||||
|  |         {ORAB, "|="}, | ||||||
|  | 	{NOTEQUAL, "!="}, | ||||||
|  | 	{AND, "&&"}, | ||||||
|  | 	{PLUSPLUS, "++"}, | ||||||
|  | 	{MINMIN, "--"}, | ||||||
|  | 	{ARROW, "->"}, | ||||||
|  | 	{LEFT, "<<"}, | ||||||
|  | 	{LESSEQ, "<="}, | ||||||
|  | 	{EQUAL, "=="}, | ||||||
|  | 	{GREATEREQ, ">="}, | ||||||
|  | 	{RIGHT, ">>"}, | ||||||
|  | 	{OR, "||"}, | ||||||
|  | 	{ELLIPSIS, "..."}, | ||||||
|  | 	{0, ""} | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | struct tokenname tkfunny[] =	{	/* internal keywords */ | ||||||
|  | 	{ERRONEOUS, "erroneous"}, | ||||||
|  | 	{0, ""} | ||||||
|  | }; | ||||||
|  | #endif	____ | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue