shithub: scc

Download patch

ref: 9347ef0944f6076bd5f016e85b2627f519bd51a9
parent: 928508eccd9699691f7ef41f508b669953e60b06
parent: 8b47bd6c54891baebf6a1083c7b1f6fa0402b8e4
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon Sep 28 06:32:18 EDT 2015

Merge remote-tracking branch 'origin/master'

Conflicts:
	cc1/tests/test001.c
	cc1/tests/test004.c
	cc1/tests/test005.c
	cc1/tests/test006.c
	cc1/tests/test007.c
	cc1/tests/test008.c
	cc1/tests/test009.c
	cc1/tests/test010.c
	cc1/tests/test011.c
	cc1/tests/test012.c
	cc1/tests/test017.c
	cc1/tests/test018.c

--- a/Makefile
+++ b/Makefile
@@ -4,8 +4,7 @@
 
 SUBDIRS  = \
 	lib \
-	cc1 \
-	cc2
+	cc1
 
 all clean:
 	@echo scc build options:
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -416,4 +416,5 @@
             *ushortype,   *shortype,
             *longtype,    *ulongtype,
             *ullongtype,  *llongtype,
-            *floattype,   *doubletype,  *ldoubletype;
+            *floattype,   *doubletype,  *ldoubletype,
+            *ellipsistype;
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -359,9 +359,11 @@
 
 	n = sym->type->n.elem;
 	for (sp = sym->u.pars; n-- > 0; ++sp) {
+		if ((sym = *sp) == NULL)
+			continue;
 		/* enable non used warnings in parameters */
-		(*sp)->flags &= ~ISUSED;
-		emit(ODECL, *sp);
+		sym->flags &= ~ISUSED;
+		emit(ODECL, sym);
 	}
 	puts("\\");
 }
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -26,13 +26,7 @@
 static Symbol *
 defmacro(char *s)
 {
-	Symbol *sym;
-
-	strcpy(yytext, s);
-	sym = lookup(NS_CPP, yytext);
-	/* FIXME: We have a problem here */
-	sym->flags |= ISDECLARED;
-	return sym;
+	return install(NS_CPP, lookup(NS_CPP, s));
 }
 
 void
@@ -73,6 +67,8 @@
 	if (yylen + 1 > arglen)
 		error("argument overflow invoking macro \"%s\"",
 		      macroname);
+	if (yytoken == IDEN)
+		yylval.sym->flags |= ISUSED;
 	memcpy(argp, yytext, yylen);
 	argp += yylen;
 	*argp++ = ' ';
@@ -253,6 +249,7 @@
 getpars(Symbol *args[NR_MACROARG])
 {
 	int n = -1;
+	Symbol *sym;
 
 	if (!accept('('))
 		return n;
@@ -269,7 +266,9 @@
 			cpperror("macro arguments must be identifiers");
 			return NR_MACROARG;
 		}
-		args[n++] = yylval.sym;
+		sym = install(NS_IDEN, yylval.sym);
+		sym->flags |= ISUSED;
+		args[n++] = sym;
 		next();
 	} while (accept(','));
 	expect(')');
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -126,9 +126,6 @@
 
 	sym->type = tp;
 
-	if (n == -1)
-		error("'void' must be the only parameter");
-
 	switch (dcl->sclass) {
 	case STATIC:
 	case EXTERN:
@@ -145,32 +142,31 @@
 
 	switch (tp->op) {
 	case VOID:
-		if (n != 0)
-			error("incorrect void parameter");
-		if (dcl->sclass)
-			error("void as unique parameter may not be qualified");
+		if (n != 0) {
+			errorp("incorrect void parameter");
+			return NULL;
+		}
 		funtp->n.elem = -1;
+		if (dcl->sclass)
+			errorp("void as unique parameter may not be qualified");
 		return NULL;
 	case ARY:
 		tp = mktype(tp->type, PTR, 0, NULL);
 		break;
 	case FTN:
-		error("incorrect function type for a function parameter");
+		errorp("incorrect function type for a function parameter");
+		return NULL;
 	}
 
 	if (name) {
-		if ((sym = install(NS_IDEN, sym)) == NULL)
-			error("redefinition of parameter '%s'", name);
+		if ((sym = install(NS_IDEN, sym)) == NULL) {
+			errorp("redefinition of parameter '%s'", name);
+			return NULL;
+		}
 	}
 	sym->type = tp;
 	sym->flags |= ISUSED;    /* avoid non used warnings in prototypes */
 
-	if (n == NR_FUNPARAM)
-		error("too much parameters in function definition");
-	funtp->p.pars = xrealloc(funtp->p.pars, ++n * sizeof(Type *));
-	funtp->p.pars[n-1] = tp;
-	funtp->n.elem = n;
-
 	return sym;
 }
 
@@ -182,27 +178,62 @@
 static void
 fundcl(struct declarators *dp)
 {
-	Type type = {.n = {.elem = -1}, .p = {.pars= NULL}};
-	Symbol *syms[NR_FUNPARAM], **sp;
+	Type type, *types[NR_FUNPARAM], *tp;
+	Symbol *syms[NR_FUNPARAM], *sym;
 	TINT size;
-	Symbol *pars = NULL;
+	Symbol *pars;
+	int toomany = 0, toovoid = 0;
 
 	pushctx();
 	expect('(');
+	type.n.elem = 0;
 
-	if (!accept(')')) {
-		type.n.elem = 0;
-		sp = syms;
-		do
-			*sp++ = dodcl(0, parameter, NS_IDEN, &type);
-		while (accept(','));
+	if (yytoken == ')') {
+		++type.n.elem;
+		syms[0] = NULL;
+		types[0] = ellipsistype;
+		goto end_params;
+	}
+	do {
+		if (type.n.elem == -1) {
+			if (!toovoid)
+				errorp("'void' must be the only parameter");
+			toovoid = 1;
+		}
+		if (!accept(ELLIPSIS)) {
+			sym = dodcl(0, parameter, NS_IDEN, &type);
+			if (!sym)
+				continue;
+			tp = sym->type;
+		} else {
+			if (type.n.elem == 0)
+				errorp("a named argument is requiered before '...'");
+			tp = ellipsistype;
+			sym = NULL;
+		}
+		if (type.n.elem == NR_FUNPARAM) {
+			if (toomany)
+				continue;
+			errorp("too much parameters in function definition");
+			toomany = 1;
+		} else if (type.n.elem >= 0) {
+			syms[type.n.elem] = sym;
+			types[type.n.elem] = tp;
+			++type.n.elem;
+		}
+	} while (tp != ellipsistype && accept(','));
 
-		expect(')');
+end_params:
+	expect(')');
 
-		if (type.n.elem != -1) {
-			size = type.n.elem * sizeof(Symbol *);
-			pars = memcpy(xmalloc(size), syms, size);
-		}
+	if (type.n.elem > 0) {
+		size = type.n.elem * sizeof(Symbol *);
+		pars = memcpy(xmalloc(size), syms, size);
+		size = type.n.elem * sizeof(Type *);
+		type.p.pars = memcpy(xmalloc(size), types, size);
+	} else {
+		pars = NULL;
+		type.p.pars = NULL;
 	}
 	push(dp, FTN, type.n.elem, type.p.pars, pars);
 }
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -535,7 +535,7 @@
 	int toomany;;
 	TINT n;
 	Node *par = NULL, *arg;
-	Type **targs, *tp = np->type;
+	Type *argtype, **targs, *tp = np->type;
 
 	if (tp->op == PTR && tp->type->op == FTN) {
 		np = content(OPTR, np);
@@ -554,21 +554,40 @@
 
 	do {
 		arg = decay(assign());
-		if (--n < 0 && !toomany) {
-			errorp("too many arguments in function call");
+		argtype = *targs;
+		if (argtype == ellipsistype) {
+			n = 0;
+			switch (arg->type->op) {
+			case INT:
+				arg = promote(arg);
+				break;
+			case FLOAT:
+				if (arg->type == floattype)
+					arg = convert(arg, doubletype, 1);
+				break;
+			}
+			if (arg->type->op == INT)
+				arg = promote(arg);
+			par = node(OPAR, arg->type, par, arg);
+			continue;
+		}
+		if (--n < 0) {
+			if (!toomany)
+				errorp("too many arguments in function call");
 			toomany = 1;
 			continue;
 		}
-		if ((arg = convert(arg, *targs++, 0)) != NULL) {
+		++targs;
+		if ((arg = convert(arg, argtype, 0)) != NULL) {
 			par = node(OPAR, arg->type, par, arg);
 			continue;
 		}
 		errorp("incompatible type for argument %d in function call",
-		      tp->n.elem - n + 1);
+		       tp->n.elem - n + 1);
 	} while (accept(','));
 
 no_pars:
-	if (n > 0)
+	if (n > 0 && *targs != ellipsistype)
 		errorp("too few arguments in function call");
 
 	expect(')');
@@ -1071,17 +1090,19 @@
 		}
 		switch (tp->op) {
 		case ARY:
-			if (tp->defined && n >= tp->n.elem && !toomany) {
+			if (tp->defined && n >= tp->n.elem) {
+				if (!toomany)
+					warn("excess elements in array initializer");
 				toomany = 1;
-				warn("excess elements in array initializer");
 				sym = NULL;
 			}
 			newtp = tp->type;
 			break;
 		case STRUCT:
-			if (n >= tp->n.elem && !toomany) {
+			if (n >= tp->n.elem) {
+				if (!toomany)
+					warn("excess elements in struct initializer");
 				toomany = 1;
-				warn("excess elements in struct initializer");
 				sym = NULL;
 			} else {
 				sym = tp->p.fields[n];
@@ -1091,9 +1112,11 @@
 		default:
 			newtp = tp;
 			warn("braces around scalar initializer");
-			if (n > 0 && !toomany) {
+			if (n > 0) {
+				if (!toomany)
+					warn("excess elements in scalar initializer");
 				toomany = 1;
-				warn("excess elements in scalar initializer");
+				sym = NULL;
 			}
 			break;
 		}
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -29,15 +29,15 @@
 			continue;
 		fprintf(stderr, "%d", (int) (bp - htab));
 		for (sym = *bp; sym; sym = sym->hash)
-			fprintf(stderr, "->[%d,%d:%s]",
-			        sym->ns, sym->ctx, sym->name);
+			fprintf(stderr, "->[%d,%d:'%s'=%p]",
+			        sym->ns, sym->ctx, sym->name, (void *) sym);
 		putc('\n', stderr);
 	}
 	fputs("head:", stderr);
 	for (sym = head; sym; sym = sym->next) {
-		fprintf(stderr, "->[%d,%d:'%s']",
+		fprintf(stderr, "->[%d,%d:'%s'=%p]",
 		        sym->ns, sym->ctx,
-		        (sym->name) ? sym->name : "");
+		        (sym->name) ? sym->name : "", (void *) sym);
 	}
 	putc('\n', stderr);
 }
@@ -58,6 +58,8 @@
 {
 	Symbol **h, *p, *prev;
 
+	if ((sym->flags & ISDECLARED) == 0)
+		return;
 	h = &htab[hash(sym->name)];
 	for (prev = p = *h; p != sym; prev = p, p = p->hash)
 		/* nothing */;
@@ -248,9 +250,7 @@
 		if (sns == NS_KEYWORD || sns == NS_CPP || sns == ns)
 			return sym;
 	}
-	sym = allocsym(ns, name);
-
-	return sym;
+	return allocsym(ns, name);
 }
 
 void
@@ -279,9 +279,9 @@
 	for (p = sym->hash; p; p = p->hash) {
 		t = p->name;
 		if (c == *t && !strcmp(s, t))
-			return sym;
+			return p;
 	}
-	return linkhash(allocsym(ns, s));
+	return allocsym(ns, s);
 }
 
 Symbol *
--- a/cc1/tests/test001.c
+++ b/cc1/tests/test001.c
@@ -2,7 +2,7 @@
 name: TEST001
 description: Basic hello world test
 output:
-F3	I	P
+F3	I	P	E
 X4	F3	printf
 F5	I
 G6	F5	main
@@ -13,7 +13,7 @@
 }
 */
 
-int printf(char *fmt);
+int printf(char *fmt, ...);
 
 int
 main(void)
--- a/cc1/tests/test004.c
+++ b/cc1/tests/test004.c
@@ -2,7 +2,7 @@
 name: TEST004
 description: Test integer operations
 output:
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test005.c
+++ b/cc1/tests/test005.c
@@ -2,7 +2,7 @@
 name: TEST005
 description: Test unary integer operations
 output:
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test006.c
+++ b/cc1/tests/test006.c
@@ -6,7 +6,7 @@
 test006.c:8: warning: conditional expression is constant
 test006.c:11: warning: conditional expression is constant
 G1	K	c
-F2	I
+F2	I	E
 G3	F2	main
 {
 \
--- a/cc1/tests/test007.c
+++ b/cc1/tests/test007.c
@@ -2,7 +2,7 @@
 name: TEST007
 description: basic while test
 output:
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test008.c
+++ b/cc1/tests/test008.c
@@ -2,7 +2,7 @@
 name: TEST008
 description: Basic do while loop
 output:
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test009.c
+++ b/cc1/tests/test009.c
@@ -2,7 +2,7 @@
 name: TEST009
 description: Basic test for loops
 output:
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test010.c
+++ b/cc1/tests/test010.c
@@ -5,7 +5,7 @@
 test010.c:9: warning: conditional expression is constant
 test010.c:11: warning: conditional expression is constant
 test010.c:31: warning: conditional expression is constant
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test011.c
+++ b/cc1/tests/test011.c
@@ -4,7 +4,7 @@
 output:
 test011.c:14: warning: 'foo' defined but not used
 test011.c:14: warning: 'start' defined but not used
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test012.c
+++ b/cc1/tests/test012.c
@@ -3,7 +3,7 @@
 description: Basic switch test
 output:
 test012.c:39: warning: 'foo' defined but not used
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- a/cc1/tests/test017.c
+++ b/cc1/tests/test017.c
@@ -2,7 +2,7 @@
 name: TEST017
 description: Basic test about pointers and structs
 output:
-F9	I
+F9	I	E
 G10	F9	main
 {
 \
--- a/cc1/tests/test018.c
+++ b/cc1/tests/test018.c
@@ -2,7 +2,7 @@
 name: TEST018
 description: Basic test for arrays
 output:
-F1	I
+F1	I	E
 G2	F1	main
 {
 \
--- /dev/null
+++ b/cc1/tests/test025.c
@@ -1,0 +1,64 @@
+
+/*
+name: TEST025
+descritpion: Test of ifdef and ifndef
+output:
+G1	I	a
+G2	I	b
+G3	I	c
+G4	I	d
+G5	I	_1
+G6	I	_2
+G7	I	e_
+G8	I	f_
+G9	I	h
+G10	I	i
+*/
+
+#define FOO
+
+#ifdef FOO
+	int a;
+	int b;
+	#undef FOO
+	#ifndef FOO
+		int c;
+		int d;
+	#else
+		int e;
+		int f;
+	#endif
+	int _1;
+	int _2;
+	#ifdef FOO
+		int c_;
+		int d_;
+	#else
+		int e_;
+		int f_;
+	#endif
+	int h;
+	int i;
+#else
+	int j;
+	int k;
+	#ifdef FOO
+		int l;
+		int m;
+	#else
+		int n;
+		int o;
+	#endif
+	int p;
+	int q;
+	#ifndef FOO
+		int r;
+		int s;
+	#else
+		int t;
+		int u;
+	#endif
+	int v;
+	int w;
+#endif
+
--- /dev/null
+++ b/cc1/tests/test026.c
@@ -1,0 +1,37 @@
+
+/*
+name: TEST026
+descritpion: Test of predefined cpp macros
+output:
+F2	I
+G3	F2	main
+{
+\
+A4	I	y
+A6	P	p
+	A6	"746573743032362E63	'P	:P
+	A4	#I1E	:I
+	A4	#I1	:I
+	A4	#I1	:I
+	A4	#I1	:I
+	A4	#I1	:I
+}
+*/
+
+#define x(y)  (y)
+
+int
+main(void)
+{
+	int y;
+	char *p;
+
+	p = __FILE__;
+	y = __LINE__;
+/*	p = __DATE__;   __DATE__ generates  different value each time */
+	y = __STDC__;
+/*	p = __TIME__;   __TIME__ generates  different value each time */
+	y = __STDC_HOSTED__;
+	y = __SCC__;
+	y = x(1);
+}
--- /dev/null
+++ b/cc1/tests/test027.c
@@ -1,0 +1,26 @@
+
+/*
+name: TEST027
+description: Test of cpp stringizer
+output:
+F2	I
+G3	F2	main
+{
+\
+A5	P	p
+	A5	"68656C6C6F20697320626574746572207468616E20627965	'P	:P
+	r	A5	@K	gK
+}
+*/
+
+#define x(y) #y
+
+int
+main(void)
+{
+	char *p;
+	p = x(hello)  " is better than bye";
+
+	return *p;
+}
+
--- /dev/null
+++ b/cc1/tests/test028.c
@@ -1,0 +1,22 @@
+
+/*
+name: TEST028
+description: Test of reinterpretation in define
+output:
+F5	P
+G6	F5	foo
+{
+\
+	r	"6869	'P
+}
+*/
+
+
+#define M(x) x
+#define A(a,b) a(b)
+
+char *
+foo(void)
+{
+	return A(M,"hi");
+}
--- /dev/null
+++ b/cc1/tests/test029.c
@@ -1,0 +1,36 @@
+
+/*
+name: TEST029
+description: Test of nested expansion and refusing macro without arguments
+comments: f(2) will expand to 2*g, which will expand to 2*f, and in this
+          moment f will not be expanded because the macro definition is
+          a function alike macro, and in this case there is no arguments.
+output:
+test029.c:34: error: redefinition of 'f1'
+F2	I
+G3	F2	f1
+{
+\
+A4	I	f
+	A4	#I2	*I
+}
+test029.c:35: error: 'f' undeclared
+*/
+
+
+#define f(a) a*g
+#define g f
+
+int
+f1(void)
+{
+	int f;
+
+	f(2);
+}
+
+int
+f1(void)
+{
+	f(2);
+}
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -241,6 +241,12 @@
 		.align = 1,
 		.n.rank = RANK_UINT,
 		.printed = 1
+	},
+	{      /* 18 = ellipsis */
+		.op = ELLIPSIS,
+		.letter = L_ELLIPSIS,
+		.defined = 1,
+		.printed = 1
 	}
 };
 
@@ -252,7 +258,8 @@
 	*longtype = &types[10], *ulongtype = &types[11],
 	*ullongtype = &types[12], *llongtype = &types[13],
 	*floattype = &types[14], *doubletype = &types[15],
-	*ldoubletype = &types[16], *sizettype = &types[17];
+	*ldoubletype = &types[16], *sizettype = &types[17],
+	*ellipsistype = &types[18];
 
 static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
               dummy1 = {.u.i = 1, .type = &types[9]};
--- a/inc/cc.h
+++ b/inc/cc.h
@@ -21,6 +21,7 @@
 #define L_UINT16    'N'
 #define L_UINT32    'Z'
 #define L_UINT64    'O'
+#define L_ELLIPSIS  'E'
 
 #define L_VOID      '0'
 #define L_POINTER   'P'