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

📄 decl.c

📁 lcc,一个可变目标c语言编译器的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
#include "c.h"static char rcsid[] = "$Id: decl.c,v 1.1 2002/08/28 23:12:42 drh Exp $";#define add(x,n) (x > inttype->u.sym->u.limits.max.i-(n) ? (overflow=1,x) : x+(n))#define chkoverflow(x,n) ((void)add(x,n))#define bits2bytes(n) (((n) + 7)/8)static int regcount;static List autos, registers;Symbol cfunc;		/* current function */Symbol retv;		/* return value location for structs */static void checkref(Symbol, void *);static Symbol dclglobal(int, char *, Type, Coordinate *);static Symbol dcllocal(int, char *, Type, Coordinate *);static Symbol dclparam(int, char *, Type, Coordinate *);static Type dclr(Type, char **, Symbol **, int);static Type dclr1(char **, Symbol **, int);static void decl(Symbol (*)(int, char *, Type, Coordinate *));extern void doconst(Symbol, void *);static void doglobal(Symbol, void *);static void doextern(Symbol, void *);static void exitparams(Symbol []);static void fields(Type);static void funcdefn(int, char *, Type, Symbol [], Coordinate);static void initglobal(Symbol, int);static void oldparam(Symbol, void *);static Symbol *parameters(Type);static Type specifier(int *);static Type structdcl(int);static Type tnode(int, Type);void program(void) {	int n;		level = GLOBAL;	for (n = 0; t != EOI; n++)		if (kind[t] == CHAR || kind[t] == STATIC		|| t == ID || t == '*' || t == '(') {			decl(dclglobal);			deallocate(STMT);			if (!(glevel >= 3 || xref))			deallocate(FUNC);		} else if (t == ';') {			warning("empty declaration\n");			t = gettok();		} else {			error("unrecognized declaration\n");			t = gettok();		}	if (n == 0)		warning("empty input file\n");}static Type specifier(int *sclass) {	int cls, cons, sign, size, type, vol;	Type ty = NULL;	cls = vol = cons = sign = size = type = 0;	if (sclass == NULL)		cls = AUTO;	for (;;) {		int *p, tt = t;		switch (t) {		case AUTO:		case REGISTER: if (level <= GLOBAL && cls == 0)		               	error("invalid use of `%k'\n", t);		               p = &cls;  t = gettok();      break;		case STATIC: case EXTERN:		case TYPEDEF:  p = &cls;  t = gettok();      break;		case CONST:    p = &cons; t = gettok();      break;		case VOLATILE: p = &vol;  t = gettok();      break;		case SIGNED:		case UNSIGNED: p = &sign; t = gettok();      break;		case LONG:     if (size == LONG) {		                       size = 0;		                       tt = LONG+LONG;		               }		               p = &size; t = gettok();      break;		case SHORT:    p = &size; t = gettok();      break;		case VOID: case CHAR: case INT: case FLOAT:		case DOUBLE:   p = &type; ty = tsym->type;		                          t = gettok();      break;		case ENUM:     p = &type; ty = enumdcl();    break;		case STRUCT:		case UNION:    p = &type; ty = structdcl(t); break;		case ID:			if (istypename(t, tsym) && type == 0			&& sign == 0 && size == 0) {				use(tsym, src);				ty = tsym->type;				if (isqual(ty)				&& ty->size != ty->type->size) {					ty = unqual(ty);					if (isconst(tsym->type))						ty = qual(CONST, ty);					if (isvolatile(tsym->type))						ty = qual(VOLATILE, ty);					tsym->type = ty;				}				p = &type;				t = gettok();			} else				p = NULL;			break;		default: p = NULL;		}		if (p == NULL)			break;		if (*p)			error("invalid use of `%k'\n", tt);		*p = tt;	}	if (sclass)		*sclass = cls;	if (type == 0) {		type = INT;		ty = inttype;	}	if (size == SHORT     && type != INT	||  size == LONG+LONG && type != INT	||  size == LONG      && type != INT && type != DOUBLE	||  sign && type != INT && type != CHAR)		error("invalid type specification\n");	if (type == CHAR && sign)		ty = sign == UNSIGNED ? unsignedchar : signedchar;	else if (size == SHORT)		ty = sign == UNSIGNED ? unsignedshort : shorttype;	else if (size == LONG && type == DOUBLE)		ty = longdouble;	else if (size == LONG+LONG) {		ty = sign == UNSIGNED ? unsignedlonglong : longlong;		if (Aflag >= 1)			warning("`%t' is a non-ANSI type\n", ty);	} else if (size == LONG)		ty = sign == UNSIGNED ? unsignedlong : longtype;	else if (sign == UNSIGNED && type == INT)		ty = unsignedtype;	if (cons == CONST)		ty = qual(CONST, ty);	if (vol  == VOLATILE)		ty = qual(VOLATILE, ty);	return ty;}static void decl(Symbol (*dcl)(int, char *, Type, Coordinate *)) {	int sclass;	Type ty, ty1;	static char stop[] = { CHAR, STATIC, ID, 0 };	ty = specifier(&sclass);	if (t == ID || t == '*' || t == '(' || t == '[') {		char *id;		Coordinate pos;		id = NULL;		pos = src;		if (level == GLOBAL) {			Symbol *params = NULL;			ty1 = dclr(ty, &id, &params, 0);			if (params && id && isfunc(ty1)			    && (t == '{' || istypename(t, tsym)			    || (kind[t] == STATIC && t != TYPEDEF))) {				if (sclass == TYPEDEF) {					error("invalid use of `typedef'\n");					sclass = EXTERN;				}				if (ty1->u.f.oldstyle)					exitscope();				funcdefn(sclass, id, ty1, params, pos);				return;			} else if (params)				exitparams(params);		} else			ty1 = dclr(ty, &id, NULL, 0);		for (;;) {			if (Aflag >= 1 && !hasproto(ty1))				warning("missing prototype\n");			if (id == NULL)				error("missing identifier\n");			else if (sclass == TYPEDEF)				{					Symbol p = lookup(id, identifiers);					if (p && p->scope == level)						error("redeclaration of `%s'\n", id);					p = install(id, &identifiers, level,						level < LOCAL ? PERM : FUNC);					p->type = ty1;					p->sclass = TYPEDEF;					p->src = pos;				}			else				(void)(*dcl)(sclass, id, ty1, &pos);			if (t != ',')				break;			t = gettok();			id = NULL;			pos = src;			ty1 = dclr(ty, &id, NULL, 0);		}	} else if (ty == NULL	|| !(isenum(ty) ||	     isstruct(ty) && (*unqual(ty)->u.sym->name < '1' || *unqual(ty)->u.sym->name > '9')))		error("empty declaration\n");	test(';', stop);}static Symbol dclglobal(int sclass, char *id, Type ty, Coordinate *pos) {	Symbol p;	if (sclass == 0)		sclass = AUTO;	else if (sclass != EXTERN && sclass != STATIC) {		error("invalid storage class `%k' for `%t %s'\n",			sclass, ty, id);		sclass = AUTO;	}	p = lookup(id, identifiers);	if (p && p->scope == GLOBAL) {		if (p->sclass != TYPEDEF && eqtype(ty, p->type, 1))			ty = compose(ty, p->type);		else			error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src);		if (!isfunc(ty) && p->defined && t == '=')			error("redefinition of `%s' previously defined at %w\n", p->name, &p->src);		if (p->sclass == EXTERN && sclass == STATIC		||  p->sclass == STATIC && sclass == AUTO		||  p->sclass == AUTO   && sclass == STATIC)			warning("inconsistent linkage for `%s' previously declared at %w\n", p->name, &p->src);	}	if (p == NULL || p->scope != GLOBAL) {		Symbol q = lookup(id, externals);		if (q) {			if (sclass == STATIC || !eqtype(ty, q->type, 1))				warning("declaration of `%s' does not match previous declaration at %w\n", id, &q->src);			p = relocate(id, externals, globals);			p->sclass = sclass;		} else {			p = install(id, &globals, GLOBAL, PERM);			p->sclass = sclass;			(*IR->defsymbol)(p);		}		if (p->sclass != STATIC) {			static int nglobals;			nglobals++;			if (Aflag >= 2 && nglobals == 512)				warning("more than 511 external identifiers\n");		}	} else if (p->sclass == EXTERN)		p->sclass = sclass;	p->type = ty;	p->src = *pos;	if (t == '=' && isfunc(p->type)) {		error("illegal initialization for `%s'\n", p->name);		t = gettok();		initializer(p->type, 0);	} else if (t == '=') {		initglobal(p, 0);		if (glevel > 0 && IR->stabsym) {			(*IR->stabsym)(p); swtoseg(p->u.seg); }	} else if (p->sclass == STATIC && !isfunc(p->type)	&& p->type->size == 0)		error("undefined size for `%t %s'\n", p->type, p->name);	return p;}static void initglobal(Symbol p, int flag) {	Type ty;	if (t == '=' || flag) {		if (p->sclass == STATIC) {			for (ty = p->type; isarray(ty); ty = ty->type)				;			defglobal(p, isconst(ty) ? LIT : DATA);		} else			defglobal(p, DATA);		if (t == '=')			t = gettok();		ty = initializer(p->type, 0);		if (isarray(p->type) && p->type->size == 0)			p->type = ty;		if (p->sclass == EXTERN)			p->sclass = AUTO;	}}void defglobal(Symbol p, int seg) {	p->u.seg = seg;	swtoseg(p->u.seg);	if (p->sclass != STATIC)		(*IR->export)(p);	(*IR->global)(p);	p->defined = 1;}static Type dclr(Type basety, char **id, Symbol **params, int abstract) {	Type ty = dclr1(id, params, abstract);	for ( ; ty; ty = ty->type)		switch (ty->op) {		case POINTER:			basety = ptr(basety);			break;		case FUNCTION:			basety = func(basety, ty->u.f.proto,				ty->u.f.oldstyle);			break;		case ARRAY:			basety = array(basety, ty->size, 0);			break;		case CONST: case VOLATILE:			basety = qual(ty->op, basety);			break;		default: assert(0);		}	if (Aflag >= 2 && basety->size > 32767)		warning("more than 32767 bytes in `%t'\n", basety);	return basety;}static Type tnode(int op, Type type) {	Type ty;	NEW0(ty, STMT);	ty->op = op;	ty->type = type;	return ty;}static Type dclr1(char **id, Symbol **params, int abstract) {	Type ty = NULL;	switch (t) {	case ID:                if (id)					*id = token;				else					error("extraneous identifier `%s'\n", token);				t = gettok(); break;	case '*': t = gettok(); if (t == CONST || t == VOLATILE) {					Type ty1;					ty1 = ty = tnode(t, NULL);					while ((t = gettok()) == CONST || t == VOLATILE)						ty1 = tnode(t, ty1);					ty->type = dclr1(id, params, abstract);					ty = ty1;				} else					ty = dclr1(id, params, abstract);				ty = tnode(POINTER, ty); break;	case '(': t = gettok(); if (abstract				&& (t == REGISTER || istypename(t, tsym) || t == ')')) {					Symbol *args;					ty = tnode(FUNCTION, ty);					enterscope();					if (level > PARAM)						enterscope();					args = parameters(ty);					exitparams(args);				} else {					ty = dclr1(id, params, abstract);					expect(')');					if (abstract && ty == NULL					&& (id == NULL || *id == NULL))						return tnode(FUNCTION, NULL);				} break;	case '[': break;	default:  return ty;	}	while (t == '(' || t == '[')		switch (t) {		case '(': t = gettok(); { Symbol *args;					  ty = tnode(FUNCTION, ty);					  enterscope();					  if (level > PARAM)					  	enterscope();					  args = parameters(ty);					  if (params && *params == NULL)					  	*params = args;					  else					  	exitparams(args); }		          break;		case '[': t = gettok(); { int n = 0;					  if (kind[t] == ID) {					  	n = intexpr(']', 1);					  	if (n <= 0) {					  		error("`%d' is an illegal array size\n", n);					  		n = 1;					  	}					  } else					  	expect(']');					  ty = tnode(ARRAY, ty);					  ty->size = n; } break;

⌨️ 快捷键说明

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