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

📄 c02.c

📁 unix v7是最后一个广泛发布的研究型UNIX版本
💻 C
字号:
#/* C compiler * * */#include "c0.h"/* * Process a single external definition */extdef(){	register o;	int sclass, scflag, *cb;	struct hshtab typer;	register struct hshtab *ds;	if(((o=symbol())==EOFC) || o==SEMI)		return;	peeksym = o;	sclass = 0;	blklev = 0;	if (getkeywords(&sclass, &typer)==0) {		sclass = EXTERN;		if (peeksym!=NAME)			goto syntax;	}	scflag = 0;	if (sclass==DEFXTRN) {		scflag++;		sclass = EXTERN;	}	if (sclass!=EXTERN && sclass!=STATIC && sclass!=TYPEDEF)		error("Illegal storage class");	do {		defsym = 0;		paraml = 0;		parame = 0;		if (sclass==TYPEDEF) {			decl1(TYPEDEF, &typer, 0, NULL);			continue;		}		decl1(EXTERN, &typer, 0, NULL);		if ((ds=defsym)==0)			return;		funcsym = ds;		if ((ds->type&XTYPE)==FUNC) {			if ((peeksym=symbol())==LBRACE || peeksym==KEYW			 || (peeksym==NAME && csym->hclass==TYPEDEF)) {				funcblk.type = decref(ds->type);				funcblk.strp = ds->strp;				setinit(ds);				outcode("BS", SYMDEF, sclass==EXTERN?ds->name:"");				cfunc();				return;			}			if (paraml)				error("Inappropriate parameters");		} else if ((o=symbol())==COMMA || o==SEMI) {			peeksym = o;			o = (length(ds)+ALIGN) & ~ALIGN;			if (sclass==STATIC) {				setinit(ds);				outcode("BSBBSBN", SYMDEF, "", BSS, NLABEL, ds->name, SSPACE, o);			} else if (scflag)				outcode("BSN", CSPACE, ds->name, o);		} else {			if (o!=ASSIGN)				peeksym = o;			setinit(ds);			if (sclass==EXTERN)				outcode("BS", SYMDEF, ds->name);			outcode("BBS", DATA, NLABEL, ds->name);			cb = funcbase;			if (cinit(ds, 1, sclass) & ALIGN)				outcode("B", EVEN);			if (maxdecl > cb)				cb = maxdecl;			funcbase = cb;		}	} while ((o=symbol())==COMMA);	if (o==SEMI)		return;syntax:	if (o==RBRACE) {		error("Too many }'s");		peeksym = 0;		return;	}	error("External definition syntax");	errflush(o);	statement();}/* * Process a function definition. */cfunc(){	register int *cb;	register sloc;	sloc = isn;	isn =+ 2;	outcode("BBS", PROG, RLABEL, funcsym->name);	if (proflg)		outcode("BN", PROFIL, isn++);	cb = curbase;	regvar = 5;	autolen = STAUTO;	maxauto = STAUTO;	blklev = 1;	declist(ARG);	outcode("B", SAVE);	funchead();	branch(sloc);	label(sloc+1);	retlab = isn++;	blklev = 0;	if ((peeksym = symbol()) != LBRACE)		error("Compound statement required");	statement();	outcode("BNB", LABEL, retlab, RETRN);	label(sloc);	outcode("BN", SETSTK, -maxauto);	branch(sloc+1);	if (cb < maxdecl)		cb = maxdecl;	curbase = funcbase = cb;}/* * Process the initializers for an external definition. */cinit(anp, flex, sclass)struct hshtab *anp;{	register struct phshtab *np;	register nel, ninit;	int width, isarray, o, brace, realtype, *cb;	struct tnode *s;	cb = funcbase;	np = gblock(sizeof(*np));	funcbase = curbase;	cpysymb(np, anp);	realtype = np->type;	isarray = 0;	if ((realtype&XTYPE) == ARRAY)		isarray++;	else		flex = 0;	width = length(np);	nel = 1;	/*	 * If it's an array, find the number of elements.	 * temporarily modify to look like kind of thing it's	 * an array of.	 */	if (sclass==AUTO)		if (isarray || realtype==STRUCT)			error("No auto. aggregate initialization");	if (isarray) {		np->type = decref(realtype);		np->subsp++;		if (width==0 && flex==0)			error("0-length row: %.8s", anp->name);		o = length(np);		/* nel = ldiv(0, width, o); */		nel = (unsigned)width/o;		width = o;	}	brace = 0;	if ((peeksym=symbol())==LBRACE && (isarray || np->type!=STRUCT)) {		peeksym = -1;		brace++;	}	ninit = 0;	do {		if ((o=symbol())==RBRACE)			break;		peeksym = o;		if (o==STRING && realtype==ARRAY+CHAR) {			if (sclass==AUTO)				error("No strings in automatic");			peeksym = -1;			putstr(0, flex?10000:nel);			ninit =+ nchstr;			o = symbol();			break;		} else if (np->type==STRUCT) {			strinit(np, sclass);		} else if ((np->type&ARRAY)==ARRAY || peeksym==LBRACE)			cinit(np, 0, sclass);		else {			initflg++;			s = tree();			initflg = 0;			if (np->hflag&FFIELD)				error("No field initialization");			*cp++ = nblock(np);			*cp++ = s;			build(ASSIGN);			if (sclass==AUTO||sclass==REG)				rcexpr(*--cp);			else if (sclass==ENUMCON) {				if (s->op!=CON)					error("Illegal enum constant for %.8s", anp->name);				anp->hoffset = s->value;			} else				rcexpr(block(INIT,np->type,NULL,NULL,(*--cp)->tr2));		}		ninit++;		if ((ninit&077)==0 && sclass==EXTERN)			outcode("BS", SYMDEF, "");	} while ((o=symbol())==COMMA && (ninit<nel || brace || flex));	if (brace==0 || o!=RBRACE)		peeksym = o;	/*	 * If there are too few initializers, allocate	 * more storage.	 * If there are too many initializers, extend	 * the declared size for benefit of "sizeof"	 */	if (ninit<nel && sclass!=AUTO)		outcode("BN", SSPACE, (nel-ninit)*width);	else if (ninit>nel) {		if (flex && nel==0) {			np->subsp[-1] = ninit;		} else			error("Too many initializers: %.8s", anp->name);		nel = ninit;	}	curbase = funcbase = cb;	return(nel*width);}/* * Initialize a structure */strinit(np, sclass)struct tnode *np;{	register struct hshtab **mlp;	static zerloc;	register int o, brace;	if ((mlp = np->strp->memlist)==NULL) {		mlp = &zerloc;		error("Undefined structure initialization");	}	brace = 0;	if ((o = symbol()) == LBRACE)		brace++;	else		peeksym = o;	do {		if ((o=symbol()) == RBRACE)			break;		peeksym = o;		if (*mlp==0) {			error("Too many structure initializers");			cinit(&funcblk, 0, sclass);		} else			cinit(*mlp++, 0, sclass);		if (*mlp ==  &structhole) {			outcode("B", EVEN);			mlp++;		}	} while ((o=symbol())==COMMA && (*mlp || brace));	if (sclass!=AUTO && sclass!=REG) {		if (*mlp)			outcode("BN", SSPACE, np->strp->ssize - (*mlp)->hoffset);		outcode("B", EVEN);	}	if (o!=RBRACE || brace==0)		peeksym = o;}/* * Mark already initialized */setinit(anp)struct hshtab *anp;{	register struct hshtab *np;	np = anp;	if (np->hflag&FINIT)		error("%s multiply defined", np->name);	np->hflag =| FINIT;}/* * Process one statement in a function. */statement(){	register o, o1, o2;	int o3;	struct tnode *np;	int sauto, sreg;stmt:	switch(o=symbol()) {	case EOFC:		error("Unexpected EOF");	case SEMI:		return;	case LBRACE:		sauto = autolen;		sreg = regvar;		blockhead();		while (!eof) {			if ((o=symbol())==RBRACE) {				autolen = sauto;				if (sreg!=regvar)					outcode("BN", SETREG, sreg);				regvar = sreg;				blkend();				return;			}			peeksym = o;			statement();		}		error("Missing '}'");		return;	case KEYW:		switch(cval) {		case GOTO:			if (o1 = simplegoto())				branch(o1);			else 				dogoto();			goto semi;		case RETURN:			doret();			goto semi;		case IF:			np = pexpr();			o2 = 0;			if ((o1=symbol())==KEYW) switch (cval) {			case GOTO:				if (o2=simplegoto())					goto simpif;				cbranch(np, o2=isn++, 0);				dogoto();				label(o2);				goto hardif;			case RETURN:				if (nextchar()==';') {					o2 = retlab;					goto simpif;				}				cbranch(np, o1=isn++, 0);				doret();				label(o1);				o2++;				goto hardif;			case BREAK:				o2 = brklab;				goto simpif;			case CONTIN:				o2 = contlab;			simpif:				chconbrk(o2);				cbranch(np, o2, 1);			hardif:				if ((o=symbol())!=SEMI)					goto syntax;				if ((o1=symbol())==KEYW && cval==ELSE) 					goto stmt;				peeksym = o1;				return;			}			peeksym = o1;			cbranch(np, o1=isn++, 0);			statement();			if ((o=symbol())==KEYW && cval==ELSE) {				o2 = isn++;				branch(o2);				label(o1);				statement();				label(o2);				return;			}			peeksym = o;			label(o1);			return;		case WHILE:			o1 = contlab;			o2 = brklab;			label(contlab = isn++);			cbranch(pexpr(), brklab=isn++, 0);			statement();			branch(contlab);			label(brklab);			contlab = o1;			brklab = o2;			return;		case BREAK:			chconbrk(brklab);			branch(brklab);			goto semi;		case CONTIN:			chconbrk(contlab);			branch(contlab);			goto semi;		case DO:			o1 = contlab;			o2 = brklab;			contlab = isn++;			brklab = isn++;			label(o3 = isn++);			statement();			label(contlab);			contlab = o1;			if ((o=symbol())==KEYW && cval==WHILE) {				cbranch(tree(), o3, 1);				label(brklab);				brklab = o2;				goto semi;			}			goto syntax;		case CASE:			o1 = conexp();			if ((o=symbol())!=COLON)				goto syntax;			if (swp==0) {				error("Case not in switch");				goto stmt;			}			if(swp>=swtab+SWSIZ) {				error("Switch table overflow");			} else {				swp->swlab = isn;				(swp++)->swval = o1;				label(isn++);			}			goto stmt;		case SWITCH:			o1 = brklab;			brklab = isn++;			np = pexpr();			chkw(np, -1);			rcexpr(block(RFORCE,0,NULL,NULL,np));			pswitch();			brklab = o1;			return;		case DEFAULT:			if (swp==0)				error("Default not in switch");			if (deflab)				error("More than 1 'default'");			if ((o=symbol())!=COLON)				goto syntax;			label(deflab = isn++);			goto stmt;		case FOR:			o1 = contlab;			o2 = brklab;			contlab = isn++;			brklab = isn++;			if (o=forstmt())				goto syntax;			label(brklab);			contlab = o1;			brklab = o2;			return;		case ELSE:			error("Inappropriate 'else'");			statement();			return;		}		error("Unknown keyword");		goto syntax;	case NAME:		if (nextchar()==':') {			peekc = 0;			o1 = csym;			if (o1->hclass>0) {				if (o1->hblklev==0) {					pushdecl(o1);					o1->hoffset = 0;				} else {					defsym = o1;					redec();					goto stmt;				}			}			o1->hclass = STATIC;			o1->htype = ARRAY;			o1->hflag =| FLABL;			if (o1->hoffset==0)				o1->hoffset = isn++;			label(o1->hoffset);			goto stmt;		}	}	peeksym = o;	rcexpr(tree());semi:	if ((o=symbol())==SEMI)		return;syntax:	error("Statement syntax");	errflush(o);}/* * Process a for statement. */forstmt(){	register int l, o, sline;	int sline1, *ss;	struct tnode *st;	if ((o=symbol()) != LPARN)		return(o);	if ((o=symbol()) != SEMI) {		/* init part */		peeksym = o;		rcexpr(tree());		if ((o=symbol()) != SEMI)			return(o);	}	label(contlab);	if ((o=symbol()) != SEMI) {		/* test part */		peeksym = o;		cbranch(tree(), brklab, 0);		if ((o=symbol()) != SEMI)			return(o);	}	if ((peeksym=symbol()) == RPARN) {	/* incr part */		peeksym = -1;		statement();		branch(contlab);		return(0);	}	l = contlab;	contlab = isn++;	st = tree();	sline = line;	if ((o=symbol()) != RPARN)		return(o);	ss = funcbase;	funcbase = curbase;	statement();	sline1 = line;	line = sline;	label(contlab);	rcexpr(st);	line = sline1;	if (ss < maxdecl)		ss = maxdecl;	curbase = funcbase = ss;	branch(l);	return(0);}/* * A parenthesized expression, * as after "if". */struct tnode *pexpr(){	register o, t;	if ((o=symbol())!=LPARN)		goto syntax;	t = tree();	if ((o=symbol())!=RPARN)		goto syntax;	return(t);syntax:	error("Statement syntax");	errflush(o);	return(0);}/* * The switch statement, which involves collecting the * constants and labels for the cases. */pswitch(){	register struct swtab *cswp, *sswp;	int dl, swlab;	cswp = sswp = swp;	if (swp==0)		cswp = swp = swtab;	branch(swlab=isn++);	dl = deflab;	deflab = 0;	statement();	branch(brklab);	label(swlab);	if (deflab==0)		deflab = brklab;	outcode("BNN", SWIT, deflab, line);	for (; cswp < swp; cswp++)		outcode("NN", cswp->swlab, cswp->swval);	outcode("0");	label(brklab);	deflab = dl;	swp = sswp;}/* * funchead is called at the start of each function * to process the arguments, which have been linked in a list. * This list is necessary because in * f(a, b) float b; int a; ... * the names are seen before the types. *//* * Structure resembling a block for a register variable. */struct	hshtab	hreg	{ REG, 0, 0, NULL, NULL, 0 };struct	tnode	areg	{ NAME, 0, NULL, NULL, &hreg};funchead(){	register pl;	register struct hshtab *cs;	struct tnode *bstack[2];	pl = STARG;	while(paraml) {		parame->hoffset = 0;		cs = paraml;		paraml = paraml->hoffset;		if (cs->htype==FLOAT)			cs->htype = DOUBLE;		cs->hoffset = pl;		if ((cs->htype&XTYPE) == ARRAY) {			cs->htype =- (ARRAY-PTR);	/* set ptr */			cs->subsp++;		/* pop dims */		}		pl =+ rlength(cs);		if (cs->hclass==AREG && (hreg.hoffset=goodreg(cs))>=0) {			bstack[0] = &areg;			bstack[1] = nblock(cs);			cp = &bstack[2];			areg.type = cs->htype;			cs->hclass = AUTO;			build(ASSIGN);			rcexpr(bstack[0]);			cs->hoffset = hreg.hoffset;			cs->hclass = REG;		} else			cs->hclass = AUTO;		prste(cs);	}	for (cs=hshtab; cs<hshtab+HSHSIZ; cs++) {		if (cs->name[0] == '\0')			continue;		if (cs->hclass == ARG || cs->hclass==AREG)			error("Not an argument: %.8s", cs->name);	}	outcode("BN", SETREG, regvar);}blockhead(){	register r;	r = regvar;	blklev++;	declist(0);	if (r != regvar)		outcode("BN", SETREG, regvar);}/* * After the end of a block, delete local * symbols; save those that are external. * Also complain about undefined labels. */blkend(){	register struct hshtab *cs, *ncs;	struct hshtab *endcs;	register i;	blklev--;	for (cs=hshtab; cs->name[0] && cs<hshtab+HSHSIZ-1; ++cs)		;	endcs = cs;	do  if (cs->name[0]) {		if (cs->hblklev <= blklev)			continue;		if ((cs->hclass!=EXTERN || blklev!=0)		 && ((cs->hflag&FLABL)==0 || blklev==0)) {			if (cs->hclass==0)				error("%.8s undefined", cs->name);			if ((ncs = cs->hpdown)==NULL) {				cs->name[0] = '\0';				hshused--;				cs->hflag =& FKEYW;			} else {				cpysymb(cs, ncs);			}			continue;		}		/*		 * Retained name; must rehash.		 */		for (i=0; i<NCPS; i++)			symbuf[i] = cs->name[i];		mossym = cs->hflag&FMOS;		lookup();		if ((ncs=csym) != cs) {			cs->name[0] = '\0';			hshused--;			i = ncs->hflag;			cpysymb(ncs, cs);			ncs->hflag =| i&FKEYW;			cs->hflag =& FKEYW;		}		if (ncs->hblklev>1 || (ncs->hblklev>0 && ncs->hclass==EXTERN))			ncs->hblklev--;	} while ((cs = (cs<&hshtab[HSHSIZ-1])? ++cs: hshtab) != endcs);}/* * write out special definitions of local symbols for * benefit of the debugger.  None of these are used * by the assembler except to save them. */prste(acs)struct hshtab *acs;{	register struct hshtab *cs;	register nkind;	cs = acs;	switch (cs->hclass) {	case REG:		nkind = RNAME;		break;	case AUTO:		nkind = ANAME;		break;	case STATIC:		nkind = SNAME;		break;	default:		return;	}	outcode("BSN", nkind, cs->name, cs->hoffset);}/* * In case of error, skip to the next * statement delimiter. */errflush(ao){	register o;	o = ao;	while(o>RBRACE)	/* ; { } */		o = symbol();	peeksym  = o;}

⌨️ 快捷键说明

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