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

📄 decl.c

📁 LCC4.2 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 + -