shithub: scc

ref: 5ae4a720c0f1a1b07cbb3236903a08b71fe33e00
dir: /decl.c/

View raw version
#include <assert.h>
#include <stddef.h>
#include <string.h>

#include "sizes.h"
#include "cc.h"
#include "tokens.h"
#include "syntax.h"
#include "symbol.h"

char parser_out_home;

static struct symbol *cursym;
static void declarator(struct ctype *tp);

static void
newiden(struct ctype *tp)
{
	register unsigned char sns, ns;

	ns = tp->c_type ? NS_TYPEDEF : NS_IDEN;
	sns = yyval.sym->ns;

	if (sns == NS_ANY) {     /* First appearence of the symbol */
		yyval.sym->ns = ns;
		cursym = yyval.sym;
		return;
	} else if (ns == sns) {  /* Duplicated symbol */
		if (yyval.sym->ctx == curctx)
			error("redeclaration of '%s'", yytext);
	}
	cursym = lookup(yytext, ns);
}

static void
dirdcl(register struct ctype *tp)
{
	if (accept('(')) {
		declarator(tp);
		expect(')');
	} else if (yytoken == IDEN) {
		newiden(tp);
		next();
	} else {
		error("expected '(' or identifier before of '%s'", yytext);
	}

	for (;;) {
		if (accept('(')) {
			next();
			pushtype(FTN);
			if (accept(')'))
				; /* TODO: k&r function */
			else
				/* TODO: prototyped function */;
			continue;
		} else if (accept('[')) {
			unsigned len;

			if (accept(']')) {
				len = 0;
			} else {
				expect(CONSTANT);
				len = yyval.sym->val;
				expect(']');
			}
			pushtype(len);
			pushtype(ARY);
			continue;
		} else {
			return;
		}
	}
}

struct ctype *
spec(void)
{
	unsigned char sign, type;
	register struct ctype *tp = NULL;

	for (type = sign = 0; ; next()) {
		switch (yytoken) {
		case TYPEDEF:  case EXTERN: case STATIC: case AUTO:
		case REGISTER: case CONST:  case VOLATILE:
			tp = storage(tp, yytoken);
			break;
		case UNSIGNED: case SIGNED:
			if (sign == yytoken)
				error("duplicated '%s'", yytext);
			if (sign)
				error("both 'signed' and 'unsigned' in declaration specifiers");
			switch (type) {
			case FLOAT: case DOUBLE: case LDOUBLE: case BOOL:
				goto invalid_sign;
			}
			if (!tp)
				tp = newctype();
			if ((type = sign = yytoken) == UNSIGNED)
				tp->c_unsigned = 1;
			break;
		case FLOAT: case DOUBLE: case BOOL:
			if (sign)
				goto invalid_sign;
		case VOID: case CHAR: case SHORT: case INT: case LONG:
			tp = btype(tp, yytoken);
			type = tp->type;
			break;
		case STRUCT:    /* TODO */
		case UNION:	/* TODO */
		case ENUM:	/* TODO */
		case IDEN: {
			struct symbol *sym;

			if ((sym = find(yytext, NS_TYPEDEF)) && !type) {
				register unsigned char tok = ahead();

				if (tok != ';' && tok != ',')  {
					(tp = sym->ctype)->refcnt++;
					next();
				}
			}
			}
		default:
			if (tp && !tp->type && sign)
				tp->type = INT;
			return tp;
		}
	}
invalid_sign:
	error("invalid sign modifier");
}

static void
declarator(struct ctype *tp)
{
	unsigned char qlf[NR_DECLARATORS];
	register unsigned char *bp, *lim;

	lim = &qlf[NR_DECLARATORS];
	for (bp = qlf; yytoken == '*' && bp != lim; ) {
		next();
		*bp++ = PTR;
		while (bp != lim) {
			switch (yytoken) {
			case CONST: case VOLATILE: case RESTRICT:
				*bp++ = yytoken;
				next();
				break;
			default:
				goto continue_outer;
			}
		}
	continue_outer: ;
	}
	if (bp == lim)
		error("Too much type declarators");

	dirdcl(tp);

	for (lim = bp - 1, bp = qlf; bp < lim; ++bp)
		pushtype(*bp);
}

static struct node *
initializer(register struct ctype *tp)
{
	register struct node *np;

	if (accept('{')) {
		np = nodecomp();
		addstmt(np, initializer(tp));
		while (accept(',')) {
			if (accept('}'))
				return np;
			addstmt(np, initializer(tp));
		}
		expect('}');
	} else {
		np = expr();
	}
	return np;
}

static struct node *
listdcl(struct ctype *base)
{
	struct node *lp = nodecomp();

	do {
		struct node *sp, *np;
		register struct ctype *tp;

		declarator(tp);
		tp = decl_type(base);
		if (!tp->type) {
			warning_error(options.implicit,
				      "type defaults to 'int' in declaration of '%s'",
				      yytext);
		}
		(cursym->ctype = tp)->refcnt++;
		sp = nodesym(cursym);
		if (tp->type == FTN && yytoken == '{') {
			np  = node2(ODEF, sp, function(cursym));
			return addstmt(lp, np);
		}
		np = node2(ODEF, sp, accept('=') ? initializer(tp) : NULL);
		lp = addstmt(lp, np);
	} while (accept(','));
	expect(';');

	return lp;
}

struct node *
decl(void)
{
	register struct ctype *tp;
	register struct node *np = NULL;

	while (accept(';'))
		/* nothing */;
	if (!(tp = spec())) {
		if (curctx != CTX_OUTER)
			goto end;
		warning("data definition has no type or storage class");
	}
	if (accept(';')) {
		warning_error(options.useless,
			      "useless type name in empty declaration");
		delctype(tp);
	} else {
		np = listdcl(tp);
	}

end:	return np;
}

void
type_name()
{

}