⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpp.c

📁 LSI C-86 compiler,小日本写的C语言编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 *	cpp.c	- c compiler preprocessor
 *
 *	23-Jun-87	include
 *	24-Jun-87	define, ifdef, ifndef, else, endif
 *	25-Jun-87	if, elif, undef, -d option, -s option, line, #, ##
 *	27-Jun-87	add __eval__
 *	14-Jul-87	debug lineadj
 *	 5-Sep-87	automatic directory search
 *	17-Sep-87	add -i
 *	29-Sep-87	long computation in #if
 *	30-Sep-87	add -w
 *	25-Dec-87	debug lineadj
 *	08-Jan-88	debug error
 *	18-Feb-88	debug recursive death
 *			add __TIME__, __DATE__
 *	22-Feb-88	edit error messages
 *	23-Feb-88	add Japanese messages
 *	02-Mar-88	bug fix: character value
 *	03-Nov-1988 02:36	add -c option (allows nested comment)
 *	22-Dec-1988 17:29	add -y option (select character set)
 *	06-Feb-1989 22:21	add code to check the validity of #endif
 *	07-Feb-1989 16:53	...
 *	07-Feb-1989 17:50	add code to remove trailing blanks
 *					from macro parameter
 *	07-Feb-1989 18:09	add code to remove comments in #pragma
 *	08-Feb-1989 17:23	tako
 *	18-Apr-1989 14:56	change value of FILENEST: 6 -> 8
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <setjmp.h>
#include <time.h>

#pragma	nonrec

typedef	char	bool, tiny;
typedef	unsigned nat;
#define	YES	1
#define	NO	0


#define	MAXBUFF	10000
#define	MAXPARM	200
#define	FILENEST	8
#define	IFNEST		8
#define	MACNEST	100



bool	Debug[26];
bool	NoSharp;
bool	NoWarn;
bool	Jap;
bool	CommNest;
bool	BCPL_comment;
#if 0
bool	Keep_comment;
#endif
char	Charcode = '0';

#define	Case	break; case
#define	Default	break; default



#define	MACFLAG	0x7F



#undef	MAXDIR
#define	MAXDIR	10
char	*Incdir[MAXDIR + 1];



typedef	struct	{
	FILE	*fp;
	char	name[80];
	int	lineno;
} FILEST;

FILEST	FileStack[FILENEST];
FILEST	*FileSp = FileStack - 1;

FILE	*Ofp;
int	Lineno;
int	Errcode = 0;


FILEST	IfStack[IFNEST];
int	Ifnest = 0;


/*
 *	error messages
 */

char	MSG_cntopnX[]	=	"can't open: %s: %s\0"
		"僼傽僀儖 %s 偑僆乕僾儞偱偒側偄 (%s)";
char	MSG_cntwrt[]	=	"can't write\0"
		"僨傿僗僋偑堦攖";
char	MSG_incnst[]	=	"#include too nested\0"
		"#include 偺僱僗僩偑怺偡偓傞";
char	MSG_outmem[]	=	"out of memory\0"
		"儊儌儕偑懌傝側偄";
char	MSG_bigmac[]	=	"too big macro\0"
		"儅僋儘掕媊偑戝偒偡偓傞";
char	MSG_unxeof[]	=	"unexpected EOF\0"
		"婜懸偟側偄僼傽僀儖偺廔傝";
char	MSG_opencomm[]	=	"missing */\0"
		"僐儊儞僩偑暵偠偰偄側偄";
char	MSG_Xmisopn[]	=	"%s: missing '('\0"
		"儅僋儘 %s 偺 ( 偑側偄";
char	MSG_Xmiscls[]	=	"%s: missing ')'\0"
		"儅僋儘 %s 偺 ) 偑側偄";
char	MSG_Xnumpar[]	=	"%s: conflicting # of parameters\0"
		"儅僋儘 %s 偺僷儔儊僞偺悢偑崌傢側偄";
char	MSG_macnst[]	=	"macro too nested\0"
		"儅僋儘偺僱僗僩偑怺偡偓傞";
char	MSG_incmisquo[]	=	"#include: missing \"\0"
		"#include 偺 \" 偑側偄";
char	MSG_incmisbra[]	=	"#include: missing >\0"
		"#include 偺 > 偑側偄";
char	MSG_incmisfil[]	=	"#include: missing filename\0"
		"#include 偺僼傽僀儖柤偑側偄";
char	MSG_defmisnam[]	=	"#define: missing macro name\0"
		"#define 偺儅僋儘柤偑側偄";
char	MSG_defbadpar[]	=	"#define: bad macro parameter\0"
		"#define 偺儅僋儘偺僷儔儊僞掕媊偵岆傝偑偁傞";
char	MSG_undmisnam[]	=	"#undef: missing macro name\0"
		"#undef 偵柤慜偑側偄";
char	MSG_misif[]	=	"missing #if\0"
		"#if 偑側偄";
char	MSG_misendif[]	=	"missing #endif\0"
		"#endif 偑側偄";
char	MSG_ifnst[]	=	"#if/#ifdef too nested\0"
		"#if/#ifdef 偺僱僗僩偑怺偡偓傞";
char	MSG_ifsynX[]	=	"#if/#elif: syntax error near %s\0"
		"#if 傑偨偼 #elif 拞偺 %s 偺嬤偔偵岆傝偑偁傞";
char	MSG_badnum[]	=	"bad number '%s'\0"
		"%s 偼晄惓側悢";
char	MSG_ifdmisnam[]	=	"#ifdef: missing identifier\0"
		"#ifdef 偵柤慜偑側偄";
char	MSG_linmisnum[]	=	"#line: missing number\0"
		"#line 偵峴斣崋偑側偄";
char	MSG_badstmX[]	=	"undefined stmt: #%s\0"
		"#%s 偲偄偆僾儕僾儘僙僢僒暥偼側偄";
char	MSG_undefmacX[]	=	"undefined macro: %s\0"
		"儅僋儘 %s 偑枹掕媊";

char	MSG_errordir[] =	"#error: %s\0"
		"#error: %s";

char	MSG_Xredef[]	=	"Warning: macro '%s' redefined\0"
		"寈崘: 儅僋儘 %s 偼俀偮偺堎側傞掕媊傪傕偮";



char	*chooseMsg(char *s)
{
	return (Jap ? s + strlen(s) + 1: s);
}


void	warn(char *msg, char *s)
{
	if (NoWarn)
		return;
	if (FileSp >= FileStack)
		fprintf(stderr, "%s %d: ", FileSp->name, FileSp->lineno);
	fprintf(stderr, chooseMsg(msg), s);
	putc('\n', stderr);
	if (Errcode != 1)
		Errcode = 2;
}


void	error1(char *msg, char *s, char *file, int lineno)
{
	if (file != NULL)
		fprintf(stderr, "%s %d: ", file, lineno);
	fprintf(stderr, chooseMsg(msg), s, strerror(errno));
	putc('\n', stderr);
	Errcode = 1;
}


void	error(char *msg, char *s)
{
	if (FileSp >= FileStack)
		error1(msg, s, FileSp->name, FileSp->lineno);
	else if ((FileSp + 1)->lineno != 0)
		error1(msg, s, (FileSp + 1)->name, (FileSp + 1)->lineno);
	else
		error1(msg, s, NULL, 0);
}


void	bug(char *msg)
{
	if (FileSp >= FileStack)
		fprintf(stderr, "%s %d: ", FileSp->name, FileSp->lineno);
	fprintf(stderr, "cpp error (%s)\n", msg);
	exit(1);
}



void	lineadj()
{
	int	n;

	if ((n = FileSp->lineno) != Lineno)
		if (Lineno < 0 || n < Lineno) {
			Lineno = FileSp->lineno;
			if (!NoSharp)
				fprintf(Ofp, "# %d \"%s\"\n",
						Lineno, FileSp->name);
		} else {
			while (Lineno < n)
				putc('\n', Ofp), Lineno++;
		}
}



void	put(char c)
{
	if (c == MACFLAG)
		bug("put");
	putc(c, Ofp);
	if (c == '\n')
		Lineno++;
}



void	fput(char *s)
{
	char	c;

	while (c = *s++)
		put(c);
}



FILE	*efopen(char *file, char *mode)
{
	FILE	*fp;

	if ((fp = fopen(file, mode)) == NULL)
		error(MSG_cntopnX, file), exit(1);
	return (fp);
}


void	efclose(FILE *fp)
{
	if (ferror(fp) || fclose(fp))
		error(MSG_cntwrt, NULL), exit(1);
}


char	*directory(char *buf, char *s)
{
	char	*p, *r, c;

	r = p = buf;
	while (c = *s++) {
		*p++ = c;
		if (c == ':' || c == '/' || c == '\\')
			r = p;
	}
	*r = '\0';
	return (buf);
}



char	*appendsl(char *buf, char *s)
{
	char	c;

	strcpy(buf, s);
	if (buf[0] != '\0') {
		c = buf[strlen(buf) - 1];
		if (c != ':' && c != '/' && c != '\\')
			strcat(buf, "\\");
	}
	return (buf);
}



void	pushFile(char *file, char tag, FILE *fp)
{
	char	fn[100];
	int	i;

	if (FileSp >= FileStack + FILENEST - 1) {
		error(MSG_incnst, NULL);
		return;
	}
	if (fp != NULL)
		;
	else if (tag == '"' && FileSp >= FileStack &&
		(fp = fopen(strcat(directory(fn, FileSp->name), file), "r"))
			!= NULL)
		file = fn;
	else {
		fp = NULL;
		if (tag != ' ')
			for (i = 0; Incdir[i] != NULL; i++)
				if ((fp = fopen(strcat(appendsl(fn, Incdir[i]),
						file), "r")) != NULL)
					break;
		if (fp == NULL && (fp = fopen(file, "r")) == NULL) {
			error(MSG_cntopnX, file);
			return;
		}
	}
	FileSp++;
	FileSp->fp = fp;
	strcpy(FileSp->name, file);
	FileSp->lineno = 1;
	Lineno = -1;
	lineadj();
}



void	*rawnew(nat s)
{
	void	*p;

	if ((p = sbrk(s)) == (void *)-1)
		error(MSG_outmem, NULL), exit(1);
	setmem(p, s, 0);
	return (p);
}

#define	new(t, n)	((t *)rawnew(sizeof(t) * (n)))


char	*copy(char *s)
{
	return (strcpy(new(char, strlen(s) + 1), s));
}








typedef	struct macro	{
	struct macro	*next;
	char		*name;
	union	{
		char	*body;
		void	(*func)();
	}		u;
	char		flags;
#define	DEFINED	001
#define	ISFUNC	002
	int		nparms;
} MACRO;

#define	HASHSIZE	1024

MACRO	*HashTbl[HASHSIZE];



char	Pool[MAXBUFF];
MACRO	*SleepStack[MACNEST];
MACRO	**Sleep = SleepStack;

char	*Ungetp = Pool + MAXBUFF;
char	*Token = Pool;
char	*Tail;
char	Lex, EvalLex;


bool	DirectiveMode = NO;

bool	Undeferr;




void	checkPool(char *p)
{
	if (p + 1 >= Ungetp)
		error(MSG_bigmac, NULL), exit(1);
}


void	unget(char c)
{
	if (c != 0) {
		checkPool(Token);
		if ((*--Ungetp = c) == '\n')
			FileSp->lineno--;
	}
}

void	ungets(char *s)
{
	char	*q;

	for (q = s + strlen(s); --q >= s; )
		unget(*q);
}







char	get1()
{
	int	c;
	bool	fc;

	if (Ungetp < Pool + MAXBUFF)
		c = *Ungetp++;
	else {
		fc = NO;
		for (;;) {
			if (FileSp < FileStack)
				return (0);
			while ((c = getc(FileSp->fp)) == MACFLAG)
				;
			if (c != EOF)
				break;
			efclose(FileSp->fp);
			Lineno = -2;
			fc = YES;
			FileSp--;
		}
		if (fc)
			lineadj();
	}
	if (c == '\n')
		FileSp->lineno++;
	return (c);
}


char	geteof()
{
	char	c;

	if (DirectiveMode) {
		while ((c = get1()) == '\\')
			if ((c = get1()) != '\n') {
				unget(c);
				c = '\\';
				break;
			}
	} else
		c = get1();
	return (c);
}

char	get()
{
	char	c;

	if ((c = geteof()) == 0)
		error(MSG_unxeof, NULL), exit(1);
	return (c);
}






#define	NAME	'a'
#define	NUMBER	'0'

#define	SHR	'b'
#define	SHL	'c'
#define	LE	'd'
#define	GE	'e'
#define	NE	'f'
#define	EQ	'g'
#define	AND	'h'
#define	OR	'i'



#define	isletter(c)	(isalpha(c) || (c) == '_')
#define	iswhite(c)	((c) == ' ' || (c) == '\t' || (c) == '\f' || (c) == '\v')

bool	is2byte(char c)
{
	switch (Charcode) {
	Default:
		return (NO);
	Case '0':
		return (0x81 <= c && c <= 0x9F || 0xE0 <= c && c <= 0xFC);
	Case '1':
		return (0x81 <= c && c <= 0xFC);
	Case '2':
		return (0x81 <= c && c <= 0xFD);
	}
}

char	gettok_eof()
{
	char	c, d;
	char	*p;

	if ((c = geteof()) == '/') {
		c = geteof();
		if (c == '*') {
			/* skip comment & change it to ' ' */
			FILEST	*fsave = FileSp;
			int	cc, lsave = fsave->lineno;

			c = 0;
			cc = 1;
			for (;;) {
				d = c;
				c = geteof();
				if (c == 0) {
					error1(MSG_opencomm, NULL, fsave->name, lsave);
					exit(1);
				}
				if (d == '*' && c == '/') {
					if (--cc == 0)
						break;
					c = 0;
				}
				if (CommNest && d == '/' && c == '*') {
					cc++;
					c = 0;
				}
			}
			c = ' ';
		} else if (BCPL_comment && c == '/') {
			/* skip C++ comment (originally BCPL style) */
			while ((c = geteof()) != '\n' && c != 0)
				;
		} else {
			unget(c);
			c = '/';
		}
	}
	d = c;
	p = Token;
	if (isletter(c) || isdigit(c)) {
		d = isdigit(c) ? NUMBER : NAME;
		while (isletter(c) || isdigit(c)) {
			*p++ = c;
			c = geteof();
		}
		unget(c);
	} else if (c == '"' || c == '\'') {
		*p++ = c;
		while (c = get(), c != d && c != '\n' && c != '\0') {
			*p++ = c;
			if (c == '\\' || is2byte(c))
				*p++ = get();
		}
		if (c == '\n')
			unget(c);
		else
			*p++ = c;
	} else
		*p++ = c;
	*p = '\0';
	checkPool(p);
	Tail = p;
	return (Lex = d);
}



char	gettok()
{
	char	c;

	if ((c = gettok_eof()) == 0)
		error(MSG_unxeof, NULL), exit(1);
	return (c);
}



char	skip_gettok()
{
	char	t;

	while (t = gettok(), iswhite(t))
		;
	return (t);
}



nat	hash(char *s)
{
	nat	v;
	char	c;

	v = 0;
	while (c = *s++)
		v = v * 257 + c;
	return (v % HASHSIZE);
}


MACRO	*roomfor(char *name)
{
	MACRO	*p, **r;

	r = &HashTbl[hash(name)];
	for (p = *r; p != NULL; p = p->next)
		if (strcmp(p->name, name) == 0)
			break;
	if (p == NULL) {
		p = new(MACRO, 1);
		p->name = copy(name);
		p->next = *r;
		*r = p;
	}
	return (p);
}


MACRO	*lookup(char *name)
{
	MACRO	*p;

	for (p = HashTbl[hash(name)]; p != NULL; p = p->next)
		if (strcmp(p->name, name) == 0)
			return (p->flags & DEFINED ? p : NULL);
	return (NULL);
}


void	installf(char *name, void (*func)())
{
	MACRO	*p;

	p = roomfor(name);
	p->u.func = func;
	p->flags = DEFINED | ISFUNC;
	p->nparms = -1;
}


void	install(char *name, char *body, int nparms)
{
	MACRO	*p;

	p = roomfor(name);
	if (p->flags & DEFINED &&
		(p->flags & ISFUNC || strcmp(p->u.body, body) != 0))
		warn(MSG_Xredef, name);
	p->u.body = copy(body);
	p->flags = DEFINED;
	p->nparms = nparms;
	if (Debug['d'-'a'])
		fprintf(stderr, "[debug] %s(%d) = {%s}\n",
					p->name, p->nparms, p->u.body);
}



char	skip_egettok(void);
char	egettok(void);
long	eval0(tiny);

void	macFile()
{
	/* replaced by current filename */
	unget('"');
	ungets(FileSp->name);
	unget('"');
}

void	macLine()
{
	/* replaced by current line# */
	char	buff[10];

	sprintf(buff, "%d", FileSp->lineno);
	ungets(buff);
}


struct	tm	*Timep;

void	macTime()
{
	/* replaced by current time */
	char	buff[12];

	sprintf(buff, "\"%02d:%02d:%02d\"",
			Timep->tm_hour, Timep->tm_min, Timep->tm_sec);
	ungets(buff);
}


void	macDate()
{
	/* replaced by current date */
	static	char	*moname[] = {
		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
	};
	char	buff[14];

	sprintf(buff, "\"%s %02d %04d\"",
		moname[Timep->tm_mon], Timep->tm_mday, 1900 + Timep->tm_year);
	ungets(buff);
}


recursive
void	macEval()
{
	/* replaced by evaluated value */
	char	buff[12];
	bool undeferr;

	if (skip_egettok() != '(') {
		error(MSG_Xmisopn, "__eval__");
		ungets(Token);
		return;
	}
	undeferr = Undeferr;
	Undeferr = YES;
	sprintf(buff, "%ld", eval0(0));
	Undeferr = undeferr;
	if (EvalLex != ')')
		error(MSG_Xmiscls, "__eval__");
	ungets(buff);
}


recursive
char	egettok_eof()
{
	char	t;
	MACRO	*p;
	char	*Parms[MAXPARM];
	int	i, nest;
	char	*save, *q, *s;
	FILEST	*fsave;
	int	lsave;

	for (;;) {
		if ((t = gettok_eof()) == MACFLAG) {
			/* wake up sleeping macro */
			if (Sleep <= SleepStack)
				bug("egettok");
			(*--Sleep)->flags |= DEFINED;
			continue;
		}
		if (t != NAME || (p = lookup(Token)) == NULL)
			break;
		if (p->flags & ISFUNC) {
			/* built-in macro */
			(*p->u.func)();
			continue;
		}
		/* replaced by macro body */
		save = Token;
		fsave = FileSp;
		lsave = fsave->lineno;
		if (p->nparms >= 0) {
			/* expecting parameters */
			if ((t = skip_gettok()) != '(') {
#if	0
/* delete 24-Jul-1989 */
				error(MSG_Xmisopn, p->name);
				return (t);
#endif
				ungets(Token);
				unget(' ');
				ungets(p->name);
				return (gettok());
			}
			t = skip_egettok();
			for (i = 0; t != ')'; i++) {
				/* get a parameter */
				if (t == 0) {
					FileSp = fsave;
					fsave->lineno = lsave;
					error(MSG_Xmiscls, p->name);
					exit(1);
				}
				if (i >= MAXPARM) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -