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

📄 decl.c

📁 LCC4.2 C编译器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		default: assert(0);
		}
	return ty;
}
static Symbol *parameters(Type fty) {
	List list = NULL;
	Symbol *params;

	if (kind[t] == STATIC || istypename(t, tsym)) {
		int n = 0;
		Type ty1 = NULL;
		for (;;) {
			Type ty;
			int sclass = 0;
			char *id = NULL;
			if (ty1 && t == ELLIPSIS) {
				static struct symbol sentinel;
				if (sentinel.type == NULL) {
					sentinel.type = voidtype;
					sentinel.defined = 1;
				}
				if (ty1 == voidtype)
					error("illegal formal parameter types\n");
				list = append(&sentinel, list);
				t = gettok();
				break;
			}
			if (!istypename(t, tsym) && t != REGISTER)
				error("missing parameter type\n");
			n++;
			ty = dclr(specifier(&sclass), &id, NULL, 1);
			if ( ty == voidtype && (ty1 || id)
			||  ty1 == voidtype)
				error("illegal formal parameter types\n");
			if (id == NULL)
				id = stringd(n);
			if (ty != voidtype)
				list = append(dclparam(sclass, id, ty, &src), list);
			if (Aflag >= 1 && !hasproto(ty))
				warning("missing prototype\n");
			if (ty1 == NULL)
				ty1 = ty;
			if (t != ',')
				break;
			t = gettok();
		}
		fty->u.f.proto = newarray(length(list) + 1,
			sizeof (Type *), PERM);
		params = ltov(&list, FUNC);
		for (n = 0; params[n]; n++)
			fty->u.f.proto[n] = params[n]->type;
		fty->u.f.proto[n] = NULL;
		fty->u.f.oldstyle = 0;
	} else {
		if (t == ID)
			for (;;) {
				Symbol p;
				if (t != ID) {
					error("expecting an identifier\n");
					break;
				}
				p = dclparam(0, token, inttype, &src);
				p->defined = 0;
				list = append(p, list);
				t = gettok();
				if (t != ',')
					break;
				t = gettok();
			}
		params = ltov(&list, FUNC);
		fty->u.f.proto = NULL;
		fty->u.f.oldstyle = 1;
	}
	if (t != ')') {
		static char stop[] = { CHAR, STATIC, IF, ')', 0 };
		expect(')');
		skipto('{', stop);
	}
	if (t == ')')
		t = gettok();
	return params;
}
static void exitparams(Symbol params[]) {
	assert(params);
	if (params[0] && !params[0]->defined)
		error("extraneous old-style parameter list\n");
	if (level > PARAM)
		exitscope();
	exitscope();
}

static Symbol dclparam(int sclass, char *id, Type ty, Coordinate *pos) {
	Symbol p;

	if (isfunc(ty))
		ty = ptr(ty);
	else if (isarray(ty))
		ty = atop(ty);
	if (sclass == 0)
		sclass = AUTO;
	else if (sclass != REGISTER) {
		error("invalid storage class `%k' for `%t%s\n",
			sclass, ty, stringf(id ? " %s'" : "' parameter", id));
		sclass = AUTO;
	} else if (isvolatile(ty) || isstruct(ty)) {
		warning("register declaration ignored for `%t%s\n",
			ty, stringf(id ? " %s'" : "' parameter", id));
		sclass = AUTO;
	}

	p = lookup(id, identifiers);
	if (p && p->scope == level)
		error("duplicate declaration for `%s' previously declared at %w\n", id, &p->src);

	else
		p = install(id, &identifiers, level, FUNC);
	p->sclass = sclass;
	p->src = *pos;
	p->type = ty;
	p->defined = 1;
	if (t == '=') {
		error("illegal initialization for parameter `%s'\n", id);
		t = gettok();
		(void)expr1(0);
	}
	return p;
}
static Type structdcl(int op) {
	char *tag;
	Type ty;
	Symbol p;
	Coordinate pos;

	t = gettok();
	pos = src;
	if (t == ID) {
		tag = token;
		t = gettok();
	} else
		tag = "";
	if (t == '{') {
		static char stop[] = { IF, ',', 0 };
		ty = newstruct(op, tag);
		ty->u.sym->src = pos;
		ty->u.sym->defined = 1;
		t = gettok();
		if (istypename(t, tsym))
			fields(ty);
		else
			error("invalid %k field declarations\n", op);
		test('}', stop);
	}
	else if (*tag && (p = lookup(tag, types)) != NULL
	&& p->type->op == op) {
		ty = p->type;
		if (t == ';' && p->scope < level)
			ty = newstruct(op, tag);
	}
	else {
		if (*tag == 0)
			error("missing %k tag\n", op);
		ty = newstruct(op, tag);
	}
	if (*tag && xref)
		use(ty->u.sym, pos);
	return ty;
}
static void fields(Type ty) {
	{ int n = 0;
	  while (istypename(t, tsym)) {
	  	static char stop[] = { IF, CHAR, '}', 0 };
	  	Type ty1 = specifier(NULL);
	  	for (;;) {
	  		Field p;
	  		char *id = NULL;
	  		Type fty = dclr(ty1, &id, NULL, 0);
			p = newfield(id, ty, fty);
			if (Aflag >= 1 && !hasproto(p->type))
				warning("missing prototype\n");
			if (t == ':') {
				if (unqual(p->type) != inttype
				&&  unqual(p->type) != unsignedtype) {
					error("`%t' is an illegal bit-field type\n",
						p->type);
					p->type = inttype;
				}
				t = gettok();
				p->bitsize = intexpr(0, 0);
				if (p->bitsize > 8*inttype->size || p->bitsize < 0) {
					error("`%d' is an illegal bit-field size\n",
						p->bitsize);
					p->bitsize = 8*inttype->size;
				} else if (p->bitsize == 0 && id) {
					warning("extraneous 0-width bit field `%t %s' ignored\n", p->type, id);

					p->name = stringd(genlabel(1));
				}
				p->lsb = 1;
			}
			else {
				if (id == NULL)
					error("field name missing\n");
				else if (isfunc(p->type))
					error("`%t' is an illegal field type\n", p->type);
				else if (p->type->size == 0)
					error("undefined size for field `%t %s'\n",
						p->type, id);
			}
			if (isconst(p->type))
				ty->u.sym->u.s.cfields = 1;
			if (isvolatile(p->type))
				ty->u.sym->u.s.vfields = 1;
	  		n++;
	  		if (Aflag >= 2 && n == 128)
	  			warning("more than 127 fields in `%t'\n", ty);
	  		if (t != ',')
	  			break;
	  		t = gettok();
	  	}
	  	test(';', stop);
	  } }
	{ int bits = 0, off = 0, overflow = 0;
	  Field p, *q = &ty->u.sym->u.s.flist;
	  ty->align = IR->structmetric.align;
	  for (p = *q; p; p = p->link) {
	  	int a = p->type->align ? p->type->align : 1;
		if (p->lsb)
			a = unsignedtype->align;
		if (ty->op == UNION)
			off = bits = 0;
		else if (p->bitsize == 0 || bits == 0
		|| bits - 1 + p->bitsize > 8*unsignedtype->size) {
			off = add(off, bits2bytes(bits-1));
			bits = 0;
			chkoverflow(off, a - 1);
			off = roundup(off, a);
		}
		if (a > ty->align)
			ty->align = a;
		p->offset = off;

		if (p->lsb) {
			if (bits == 0)
				bits = 1;
			if (IR->little_endian)
				p->lsb = bits;
			else
				p->lsb = 8*unsignedtype->size - bits + 1
					- p->bitsize + 1;
			bits += p->bitsize;
		} else
			off = add(off, p->type->size);
		if (off + bits2bytes(bits-1) > ty->size)
			ty->size = off + bits2bytes(bits-1);
	  	if (p->name == NULL
	  	|| !('1' <= *p->name && *p->name <= '9')) {
	  		*q = p;
	  		q = &p->link;
	  	}
	  }
	  *q = NULL;
	  chkoverflow(ty->size, ty->align - 1);
	  ty->size = roundup(ty->size, ty->align);
	  if (overflow) {
	  	error("size of `%t' exceeds %d bytes\n", ty, inttype->u.sym->u.limits.max.i);
	  	ty->size = inttype->u.sym->u.limits.max.i&(~(ty->align - 1));
	  } }
}
static void funcdefn(int sclass, char *id, Type ty, Symbol params[], Coordinate pt) {
	int i, n;
	Symbol *callee, *caller, p;
	Type rty = freturn(ty);

	if (isstruct(rty) && rty->size == 0)
		error("illegal use of incomplete type `%t'\n", rty);
	for (n = 0; params[n]; n++)
		;
	if (n > 0 && params[n-1]->name == NULL)
		params[--n] = NULL;
	if (Aflag >= 2 && n > 31)
		warning("more than 31 parameters in function `%s'\n", id);
	if (ty->u.f.oldstyle) {
		if (Aflag >= 1)
			warning("old-style function definition for `%s'\n", id);
		caller = params;
		callee = newarray(n + 1, sizeof *callee, FUNC);
		memcpy(callee, caller, (n+1)*sizeof *callee);
		enterscope();
		assert(level == PARAM);
		while (kind[t] == STATIC || istypename(t, tsym))
			decl(dclparam);
		foreach(identifiers, PARAM, oldparam, callee);

		for (i = 0; (p = callee[i]) != NULL; i++) {
			if (!p->defined)
				callee[i] = dclparam(0, p->name, inttype, &p->src);
			*caller[i] = *p;
			caller[i]->sclass = AUTO;
			caller[i]->type = promote(p->type);
		}
		p = lookup(id, identifiers);
		if (p && p->scope == GLOBAL && isfunc(p->type)
		&& p->type->u.f.proto) {
			Type *proto = p->type->u.f.proto;
			for (i = 0; caller[i] && proto[i]; i++) {
				Type ty = unqual(proto[i]);
				if (eqtype(isenum(ty) ? ty->type : ty,
					unqual(caller[i]->type), 1) == 0)
					break;
				else if (isenum(ty) && !isenum(unqual(caller[i]->type)))
					warning("compatibility of `%t' and `%t' is compiler dependent\n",
						proto[i], caller[i]->type);
			}
			if (proto[i] || caller[i])
				error("conflicting argument declarations for function `%s'\n", id);

		}
		else {
			Type *proto = newarray(n + 1, sizeof *proto, PERM);
			if (Aflag >= 1)
				warning("missing prototype for `%s'\n", id);
			for (i = 0; i < n; i++)
				proto[i] = caller[i]->type;
			proto[i] = NULL;
			ty = func(rty, proto, 1);
		}
	} else {
		callee = params;
		caller = newarray(n + 1, sizeof *caller, FUNC);
		for (i = 0; (p = callee[i]) != NULL && p->name; i++) {
			NEW(caller[i], FUNC);
			*caller[i] = *p;
			if (isint(p->type))
				caller[i]->type = promote(p->type);
			caller[i]->sclass = AUTO;
			if ('1' <= *p->name && *p->name <= '9')
				error("missing name for parameter %d to function `%s'\n", i + 1, id);

		}
		caller[i] = NULL;
	}
	for (i = 0; (p = callee[i]) != NULL; i++)
		if (p->type->size == 0) {
			error("undefined size for parameter `%t %s'\n",
				p->type, p->name);
			caller[i]->type = p->type = inttype;
		}
	if (Aflag >= 2 && sclass != STATIC && strcmp(id, "main") == 0) {
		if (ty->u.f.oldstyle)
			warning("`%t %s()' is a non-ANSI definition\n", rty, id);
		else if (!(rty == inttype
			&& (n == 0 && callee[0] == NULL
			||  n == 2 && callee[0]->type == inttype
			&& isptr(callee[1]->type) && callee[1]->type->type == charptype
			&& !variadic(ty))))
			warning("`%s' is a non-ANSI definition\n", typestring(ty, id));
	}
	p = lookup(id, identifiers);
	if (p && isfunc(p->type) && p->defined)
		error("redefinition of `%s' previously defined at %w\n",
			p->name, &p->src);
	cfunc = dclglobal(sclass, id, ty, &pt);
	cfunc->u.f.label = genlabel(1);
	cfunc->u.f.callee = callee;
	cfunc->u.f.pt = src;
	cfunc->defined = 1;
	if (xref)
		use(cfunc, cfunc->src);
	if (Pflag)
		printproto(cfunc, cfunc->u.f.callee);
	if (ncalled >= 0)
		ncalled = findfunc(cfunc->name, pt.file);
	labels   = table(NULL, LABELS);
	stmtlabs = table(NULL, LABELS);
	refinc = 1.0;
	regcount = 0;
	codelist = &codehead;
	codelist->next = NULL;
	if (!IR->wants_callb && isstruct(rty))
		retv = genident(AUTO, ptr(unqual(rty)), PARAM);
	compound(0, NULL, 0);

	definelab(cfunc->u.f.label);
	if (events.exit)
		apply(events.exit, cfunc, NULL);
	walk(NULL, 0, 0);
	exitscope();
	assert(level == PARAM);

⌨️ 快捷键说明

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