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

📄 c00.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
字号:
#/* C compiler * * * * Called from cc: *   c0 source temp1 temp2 [ profileflag ] * temp1 gets most of the intermediate code; * strings are put on temp2, which c1 reads after temp1. */#include "c0.h"int	isn	1;int	peeksym	-1;int	line	1;struct	tnode	funcblk { NAME, 0, NULL, NULL, NULL, NULL };struct kwtab {	char	*kwname;	int	kwval;} kwtab[]{	"int",		INT,	"char",		CHAR,	"float",	FLOAT,	"double",	DOUBLE,	"struct",	STRUCT,	"long",		LONG,	"unsigned",	UNSIGN,	"union",	UNION,	"short",	INT,	"auto",		AUTO,	"extern",	EXTERN,	"static",	STATIC,	"register",	REG,	"goto",		GOTO,	"return",	RETURN,	"if",		IF,	"while",	WHILE,	"else",		ELSE,	"switch",	SWITCH,	"case",		CASE,	"break",	BREAK,	"continue",	CONTIN,	"do",		DO,	"default",	DEFAULT,	"for",		FOR,	"sizeof",	SIZEOF,	"typedef",	TYPEDEF,	"enum",		ENUM,	0,		0,};main(argc, argv)char *argv[];{	register char *sp;	register i;	register struct kwtab *ip;	if(argc<4) {		error("Arg count");		exit(1);	}	if (freopen(argv[1], "r", stdin)==NULL) {		error("Can't find %s", argv[1]);		exit(1);	}	if (freopen(argv[2], "w", stdout)==NULL || (sbufp=fopen(argv[3],"w"))==NULL) {		error("Can't create temp");		exit(1);	}	setbuf(sbufp, sbuf);	if (argc>4)		proflg++;	/*	 * The hash table locations of the keywords	 * are marked; if an identifier hashes to one of	 * these locations, it is looked up in in the keyword	 * table first.	 */	for (ip=kwtab; (sp = ip->kwname); ip++) {		i = 0;		while (*sp)			i =+ *sp++;		hshtab[i%HSHSIZ].hflag = FKEYW;	}	coremax = funcbase = curbase = sbrk(0);	while(!eof)		extdef();	outcode("B", EOFC);	strflg++;	outcode("B", EOFC);	exit(nerror!=0);}/* * Look up the identifier in symbuf in the symbol table. * If it hashes to the same spot as a keyword, try the keyword table * first.  An initial "." is ignored in the hash. * Return is a ptr to the symbol table entry. */lookup(){	int ihash;	register struct hshtab *rp;	register char *sp, *np;	ihash = 0;	sp = symbuf;	while (sp<symbuf+NCPS)		ihash =+ *sp++&0177;	rp = &hshtab[ihash%HSHSIZ];	if (rp->hflag&FKEYW)		if (findkw())			return(KEYW);	while (*(np = rp->name)) {		for (sp=symbuf; sp<symbuf+NCPS;)			if (*np++ != *sp++)				goto no;		if (mossym != (rp->hflag&FMOS))			goto no;		csym = rp;		return(NAME);	no:		if (++rp >= &hshtab[HSHSIZ])			rp = hshtab;	}	if(++hshused >= HSHSIZ) {		error("Symbol table overflow");		exit(1);	}	rp->hclass = 0;	rp->htype = 0;	rp->hoffset = 0;	rp->subsp = NULL;	rp->strp = NULL;	rp->hpdown = NULL;	rp->hblklev = blklev;	rp->hflag =| mossym;	sp = symbuf;	for (np=rp->name; sp<symbuf+NCPS;)		*np++ = *sp++;	csym = rp;	return(NAME);}/* * Search the keyword table. * Ignore initial "." to avoid member-of-structure * problems. */findkw(){	register struct kwtab *kp;	register char *p1, *p2;	char *wp;	int firstc;	wp = symbuf;	firstc = *wp;	for (kp=kwtab; (p2 = kp->kwname); kp++) {		p1 = wp;		while (*p1 == *p2++)			if (*p1++ == '\0') {				cval = kp->kwval;				return(1);			}	}	*wp = firstc;	return(0);}/* * Return the next symbol from the input. * peeksym is a pushed-back symbol, peekc is a pushed-back * character (after peeksym). * mosflg means that the next symbol, if an identifier, * is a member of structure or a structure tag, and it * gets a "." prepended to it to distinguish * it from other identifiers. */symbol() {	register c;	register char *sp;	register tline;	if (peeksym>=0) {		c = peeksym;		peeksym = -1;		if (c==NAME)			mosflg = 0;		return(c);	}	if (peekc) {		c = peekc;		peekc = 0;	} else		if (eof)			return(EOFC);		else			c = getchar();loop:	if (c==EOF) {		eof++;		return(EOFC);	}	switch(ctab[c]) {	case SHARP:		if ((c=symbol())!=CON) {			error("Illegal #");			return(c);		}		tline = cval;		while (ctab[peekc]==SPACE)			peekc = getchar();		if (peekc=='"') {			sp = filename;			while ((c = mapch('"')) >= 0)				*sp++ = c;			*sp++ = 0;			peekc = getchar();		}		if (peekc != '\n') {			error("Illegal #");			while (getchar()!='\n' && eof==0)				;		}		peekc = 0;		line = tline;		return(symbol());	case INSERT:		/* ignore newlines */		inhdr = 1;		c = getchar();		goto loop;	case NEWLN:		if (!inhdr)			line++;		inhdr = 0;	case SPACE:		c = getchar();		goto loop;	case PLUS:		return(subseq(c,PLUS,INCBEF));	case MINUS:		return(subseq(c,subseq('>',MINUS,ARROW),DECBEF));	case ASSIGN:		c = spnextchar();		peekc = 0;		if (c=='=')			return(EQUAL);		if (c==' ')			return(ASSIGN);		if (c=='<' || c=='>') {			if (spnextchar() != c) {				peeksym = ctab[c];				return(ASSIGN);			}			peekc = 0;			return(c=='<'? ASLSH: ASRSH);		}		if (ctab[c]>=PLUS && ctab[c]<=EXOR) {			if (spnextchar() != ' '			 && (c=='-' || c=='&' || c=='*')) {				error("Warning: %c= operator assumed", c);				nerror--;			}			c = ctab[c];			return(c+ASPLUS-PLUS);		}		peekc = c;		return(ASSIGN);	case LESS:		if (subseq(c,0,1)) return(LSHIFT);		return(subseq('=',LESS,LESSEQ));	case GREAT:		if (subseq(c,0,1)) return(RSHIFT);		return(subseq('=',GREAT,GREATEQ));	case EXCLA:		return(subseq('=',EXCLA,NEQUAL));	case BSLASH:		if (subseq('/', 0, 1))			return(MAX);		goto unkn;	case DIVIDE:		if (subseq('\\', 0, 1))			return(MIN);		if (subseq('*',1,0))			return(DIVIDE);		while ((c = spnextchar()) != EOFC) {			peekc = 0;			if (c=='*') {				if (spnextchar() == '/') {					peekc = 0;					c = getchar();					goto loop;				}			}		}		eof++;		error("Nonterminated comment");		return(0);	case PERIOD:	case DIGIT:		peekc = c;		return(getnum());	case DQUOTE:		cval = isn++;		return(STRING);	case SQUOTE:		return(getcc());	case LETTER:		sp = symbuf;		while(ctab[c]==LETTER || ctab[c]==DIGIT) {			if (sp<symbuf+NCPS)				*sp++ = c;			c = getchar();		}		while(sp<symbuf+NCPS)			*sp++ = '\0';		mossym = 0;		if (mosflg) {			mossym = FMOS;			mosflg = 0;		}		peekc = c;		if ((c=lookup())==KEYW && cval==SIZEOF)			c = SIZEOF;		return(c);	case AND:		return(subseq('&', AND, LOGAND));	case OR:		return(subseq('|', OR, LOGOR));	case UNKN:	unkn:		error("Unknown character");		c = getchar();		goto loop;	}	return(ctab[c]);}/* * Read a number.  Return kind. */getnum(){	register char *np;	register c, base;	int expseen, sym, ndigit;	char *nsyn;	int maxdigit;	nsyn = "Number syntax";	lcval = 0;	base = 10;	maxdigit = 0;	np = numbuf;	ndigit = 0;	sym = CON;	expseen = 0;	if ((c=spnextchar()) == '0')		base = 8;	for (;; c = getchar()) {		*np++ = c;		if (ctab[c]==DIGIT || (base==16) && ('a'<=c&&c<='f'||'A'<=c&&c<='F')) {			if (base==8)				lcval =<< 3;			else if (base==10)				lcval = ((lcval<<2) + lcval)<<1;			else				lcval =<< 4;			if (ctab[c]==DIGIT)				c =- '0';			else if (c>='a')				c =- 'a'-10;			else				c =- 'A'-10;			lcval =+ c;			ndigit++;			if (c>maxdigit)				maxdigit = c;			continue;		}		if (c=='.') {			if (base==16 || sym==FCON)				error(nsyn);			sym = FCON;			base = 10;			continue;		}		if (ndigit==0) {			sym = DOT;			break;		}		if ((c=='e'||c=='E') && expseen==0) {			expseen++;			sym = FCON;			if (base==16 || maxdigit>=10)				error(nsyn);			base = 10;			*np++ = c = getchar();			if (c!='+' && c!='-' && ctab[c]!=DIGIT)				break;		} else if (c=='x' || c=='X') {			if (base!=8 || lcval!=0 || sym!=CON)				error(nsyn);			base = 16;		} else if ((c=='l' || c=='L') && sym==CON) {			c = getchar();			sym = LCON;			break;		} else			break;	}	peekc = c;	if (maxdigit >= base)		error(nsyn);	if (sym==FCON) {		np[-1] = 0;		cval = np-numbuf;		return(FCON);	}	if (sym==CON && (lcval<0 || lcval>MAXINT&&base==10 || (lcval>>1)>MAXINT)) {		sym = LCON;	}	cval = lcval;	return(sym);}/* * If the next input character is c, return b and advance. * Otherwise push back the character and return a. */subseq(c,a,b){	if (spnextchar() != c)		return(a);	peekc = 0;	return(b);}/* * Write out a string, either in-line * or in the string temp file labelled by * lab. */putstr(lab, amax){	register int c, max;	nchstr = 0;	max = amax;	if (lab) {		strflg++;		outcode("BNB", LABEL, lab, BDATA);		max = 10000;	} else		outcode("B", BDATA);	while ((c = mapch('"')) >= 0) {		if (nchstr < max) {			nchstr++;			if (nchstr%15 == 0)				outcode("0B", BDATA);			outcode("1N", c & 0377);		}	}	if (nchstr < max) {		nchstr++;		outcode("10");	}	outcode("0");	strflg = 0;}/* * read a single-quoted character constant. * The routine is sensitive to the layout of * characters in a word. */getcc(){	register int c, cc;	register char *ccp;	char realc;	cval = 0;	ccp = &cval;	cc = 0;	while((c=mapch('\'')) >= 0)		if(cc++ < LNCPW)			*ccp++ = c;	if (cc>LNCPW)		error("Long character constant");	if (cc==1) {		realc = cval;		cval = realc;	}	return(CON);}/* * Read a character in a string or character constant, * detecting the end of the string. * It implements the escape sequences. */mapch(ac){	register int a, c, n;	static mpeek;	c = ac;	if (a = mpeek)		mpeek = 0;	else		a = getchar();loop:	if (a==c)		return(-1);	switch(a) {	case '\n':	case '\0':		error("Nonterminated string");		peekc = a;		return(-1);	case '\\':		switch (a=getchar()) {		case 't':			return('\t');		case 'n':			return('\n');		case 'b':			return('\b');		case 'f':			return('\014');		case 'v':			return('\013');		case '0': case '1': case '2': case '3':		case '4': case '5': case '6': case '7':			n = 0;			c = 0;			while (++c<=3 && '0'<=a && a<='7') {				n =<< 3;				n =+ a-'0';				a = getchar();			}			mpeek = a;			return(n);		case 'r':			return('\r');		case '\n':			if (!inhdr)				line++;			inhdr = 0;			a = getchar();			goto loop;		}	}	return(a);}/* * Read an expression and return a pointer to its tree. * It's the classical bottom-up, priority-driven scheme. * The initflg prevents the parse from going past * "," or ":" because those delimiters are special * in initializer (and some other) expressions. */struct tnode *tree(){	int *op, opst[SSIZE], *pp, prst[SSIZE];	register int andflg, o;	register struct hshtab *cs;	int p, ps, os;	struct tnode *cmst[CMSIZ];	struct lnode *lcp;	curbase = funcbase;	op = opst;	pp = prst;	cp = cmst;	*op = SEOF;	*pp = 06;	andflg = 0;advanc:	switch (o=symbol()) {	case NAME:		cs = csym;		if (cs->hclass==TYPEDEF)			goto atype;		if (cs->hclass==ENUMCON) {			*cp++ = cblock(cs->hoffset);			goto tand;		}		if (cs->hclass==0 && cs->htype==0)			if(nextchar()=='(') {				/* set function */				cs->hclass = EXTERN;				cs->htype = FUNC;			} else {				cs->hclass = STATIC;				error("%.8s undefined; func. %.8s", cs->name, funcsym->name);				if (initflg) {					cs->hclass = EXTERN;					error("(Warning only)");					nerror =- 2;				}			}		*cp++ = nblock(cs);		goto tand;	case FCON:		*cp++ = fblock(DOUBLE, copnum(cval));		goto tand;	case LCON:		cs = gblock(sizeof(*lcp));		cs->op = LCON;		cs->type = LONG;		cs->lvalue = lcval;		*cp++ = cs;		goto tand;	case CON:		*cp++ = cblock(cval);		goto tand;	/* fake a static char array */	case STRING:		putstr(cval, 0);		cs = gblock(sizeof(*cs));		cs->hclass = STATIC;		cs->hoffset = cval;		*cp++ = block(NAME, ARRAY+CHAR, &nchstr, NULL, cs);	tand:		if(cp>=cmst+CMSIZ) {			error("Expression overflow");			exit(1);		}		if (andflg)			goto syntax;		andflg = 1;		goto advanc;	case KEYW:	atype:		if (*op != LPARN || andflg)			goto syntax;		peeksym = o;		*cp++ = xprtype(gblock(sizeof(*xprtype())));		if ((o=symbol()) != RPARN)			goto syntax;		o = CAST;		--op;		--pp;		if (*op == SIZEOF) {			andflg = 1;			*pp = 100;			goto advanc;		}		goto oponst;	case INCBEF:	case DECBEF:		if (andflg)			o =+ 2;		goto oponst;	case COMPL:	case EXCLA:	case SIZEOF:		if (andflg)			goto syntax;		goto oponst;	case MINUS:		if (!andflg)			o = NEG;		andflg = 0;		goto oponst;	case AND:	case TIMES:		if (andflg)			andflg = 0;		else if (o==AND)			o = AMPER;		else			o = STAR;		goto oponst;	case LPARN:		if (andflg) {			o = symbol();			if (o==RPARN)				o = MCALL;			else {				peeksym = o;				o = CALL;				andflg = 0;			}		}		goto oponst;	case RBRACK:	case RPARN:		if (!andflg)			goto syntax;		goto oponst;	case DOT:	case ARROW:		mosflg++;		break;	case ASSIGN:		if (andflg==0 && PLUS<=*op && *op<=EXOR) {			o = *op-- + ASPLUS - PLUS;			pp--;			goto oponst;		}		break;	}	/* binaries */	if (andflg==0)		goto syntax;	andflg = 0;oponst:	p = (opdope[o]>>9) & 077;opon1:	ps = *pp;	if (p>ps || p==ps && (opdope[o]&RASSOC)!=0) {		switch (o) {		case INCAFT:		case DECAFT:			p = 37;			break;		case LPARN:		case LBRACK:		case CALL:			p = 04;		}		if (initflg) {			if ((o==COMMA && *op!=LPARN && *op!=CALL)			 || (o==COLON && *op!=QUEST)) {				p = 00;				goto opon1;			}		}		if (op >= &opst[SSIZE-1]) {			error("expression overflow");			exit(1);		}		*++op = o;		*++pp = p;		goto advanc;	}	--pp;	switch (os = *op--) {	case SEOF:		peeksym = o;		build(0);		/* flush conversions */		return(*--cp);	case COMMA:		if (*op != CALL)			os = SEQNC;		break;	case CALL:		if (o!=RPARN)			goto syntax;		build(os);		goto advanc;	case MCALL:		*cp++ = NULL;	/* empty arglist */		os = CALL;		break;	case INCBEF:	case INCAFT:	case DECBEF:	case DECAFT:		*cp++ = cblock(1);		break;	case LPARN:		if (o!=RPARN)			goto syntax;		goto advanc;	case LBRACK:		if (o!=RBRACK)			goto syntax;		build(LBRACK);		goto advanc;	}	build(os);	goto opon1;syntax:	error("Expression syntax");	errflush(o);	return(0);}struct hshtab *xprtype(atyb)struct hshtab *atyb;{	register struct hshtab *tyb;	struct hshtab typer;	int sc;	register char *md, *fb;	struct tnode *scp;	tyb = atyb;	fb = funcbase;	md = maxdecl;	scp = cp;	funcbase = curbase;	sc = DEFXTRN;		/* will cause error if class mentioned */	getkeywords(&sc, &typer);	tyb->hclass = 0;	tyb->hblklev = 0;	decl1(&sc, &typer, 0, tyb);	funcbase = fb;	maxdecl = md;	cp = scp;	tyb->op = ETYPE;	return(tyb);}char *copnum(len){	register char *s1, *s2, *s3;	s1 = s2 = gblock((len+LNCPW-1) & ~(LNCPW-1));	s3 = numbuf;	while (*s2++ = *s3++);	return(s1);}

⌨️ 快捷键说明

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