Browse Source

fixed int to unsigned conversions, declarations, pp-list initialization

eck 34 years ago
parent
commit
7f5abdd670

+ 5 - 4
lang/cem/cemcom.ansi/LLlex.c

@@ -342,10 +342,11 @@ garbage:
 		}
 #endif NOPP
 		ptok->tk_symb = (
-			idef->id_reserved ? idef->id_reserved
-			: idef->id_def && idef->id_def->df_sc == TYPEDEF ?
-				TYPE_IDENTIFIER
-			: IDENTIFIER
+			idef->id_reserved
+			    ? idef->id_reserved
+			    : idef->id_def && idef->id_def->df_sc == TYPEDEF
+				? TYPE_IDENTIFIER
+				: IDENTIFIER
 		);
 		return IDENTIFIER;
 	}

+ 8 - 0
lang/cem/cemcom.ansi/conversion.c

@@ -56,6 +56,14 @@ conversion(from_type, to_type)
 				C_cii();
 				from_size = word_size;
 			}
+			/* 3.2.1.2 */
+			if (to_cnvtype == T_UNSIGNED
+			    && (int)from_size < (int)to_size) {
+				C_loc(from_size);
+				C_loc(to_size);
+				C_cii();
+				from_size = to_size;
+			}
 			C_loc(from_size);
 			C_loc(to_size);
 			if (to_cnvtype == T_UNSIGNED) C_ciu();

+ 61 - 34
lang/cem/cemcom.ansi/declar.g

@@ -67,28 +67,43 @@ declaration
 		short typedef yepp;
 	makes all hope of writing a specific grammar for typedefs illusory.
 */
+/*	We do not accept the whole of the grammar, since when we see
+	something like 'unsigned plain' (where plain is a typedef) is
+	illegal if 'plain' is a typedef.  Therefore, we assume that
+	'plain' is the identifier of a declarator.  Unfortunately, this
+	causes declarations like 'unsigned plain x;' to be rejected on the
+	grounds of syntax, even though it is syntactically right.  This may
+	cause a lot of extra messages.
+	To do this, decl_specifiers is divided into:
+	1: normal specifiers == storage class specifiers + type_qualifiers
+	2: special specifiers == short + long + signed + unsigned
+	3: basic types == void + char + int + float + double
+	4: single type specifiers == struct or union specifiers
+				    + enum specifiers + typedef names
 
+ */
 decl_specifiers	/* non-empty */ (register struct decspecs *ds;)
 	/*	Reads a non-empty decl_specifiers and fills the struct
 		decspecs *ds.
 	*/
 :
-[
-	other_specifier(ds)+
-	[%if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
-		/* the thin ice in R.M. 11.1 */
-		single_type_specifier(ds) other_specifier(ds)*
-	|
-		empty
-	]
+[ %if (AHEAD == IDENTIFIER)			/* like: register i; */
+	normal_specifier(ds)
 |
-	single_type_specifier(ds) other_specifier(ds)*
+	normal_specifier(ds)*
+	[	special_specifier(ds)
+	|	basic_type(ds)
+	|	single_type_specifier(ds)
+	]
+	[	normal_specifier(ds)
+	|	special_specifier(ds)
+	|	basic_type(ds)
+	]*
 ]
 	{do_decspecs(ds);}
 ;
 
-/* 3.5.1 & 3.5.2 (partially) & 3.5.3 (partially) */
-other_specifier(register struct decspecs *ds;)
+normal_specifier(register struct decspecs *ds;)
 :
 	[ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
 	{	if (ds->ds_sc_given)
@@ -96,18 +111,6 @@ other_specifier(register struct decspecs *ds;)
 		ds->ds_sc_given = 1;
 		ds->ds_sc = DOT;
 	}
-|
-	[ SHORT | LONG ]
-	{	if (ds->ds_size)
-			error("repeated size specifier");
-		ds->ds_size = DOT;
-	}
-|
-	[ SIGNED | UNSIGNED ]
-	{	if (ds->ds_unsigned != 0)
-			error("repeated sign specifier");
-		ds->ds_unsigned = DOT;
-	}
 |
 	/*	This qualifier applies to the top type.
 		E.g. volatile float * is a pointer to volatile float.
@@ -129,6 +132,21 @@ other_specifier(register struct decspecs *ds;)
 	}
 ;
 
+special_specifier(register struct decspecs *ds;)
+:
+	[ SHORT | LONG ]
+	{	if (ds->ds_size)
+			error("repeated size specifier");
+		ds->ds_size = DOT;
+	}
+|
+	[ SIGNED | UNSIGNED ]
+	{	if (ds->ds_unsigned != 0)
+			error("repeated sign specifier");
+		ds->ds_unsigned = DOT;
+	}
+;
+
 /* 3.5.2 */
 type_specifier(struct type **tpp;)
 	/*	Used in struct/union declarations and in casts; only the
@@ -146,9 +164,20 @@ type_specifier(struct type **tpp;)
 	{*tpp = Ds.ds_type;}
 ;
 
+basic_type(register struct decspecs *ds;):
+	[ VOID | CHAR | INT | FLOAT | DOUBLE ]
+	{
+		idf2type(dot.tk_idf, &ds->ds_type);
+		ds->ds_typedef = 0;
+	}
+;
+
 single_type_specifier(register struct decspecs *ds;):
 	%default TYPE_IDENTIFIER	/* this includes INT, CHAR, etc. */
-	{idf2type(dot.tk_idf, &ds->ds_type);}
+	{
+		idf2type(dot.tk_idf, &ds->ds_type);
+		ds->ds_typedef = 1;
+	}
 |
 	IDENTIFIER
 	{
@@ -283,7 +312,7 @@ declarator(register struct declarator *dc;)
 		|
 			formal_list(&fm)
 		|
-			empty
+			/* empty */
 		]
 		')'
 		{	add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl);
@@ -308,6 +337,7 @@ arrayer(arith *sizep;)
 	{ struct expr *expr; }
 :
 	'['
+		{ *sizep = (arith)-1; }
 		[
 			constant_expression(&expr)
 			{
@@ -315,10 +345,7 @@ arrayer(arith *sizep;)
 				*sizep = expr->VL_VALUE;
 				free_expression(expr);
 			}
-		|
-			empty
-			{ *sizep = (arith)-1; }
-		]
+		]?
 	']'
 ;
 
@@ -358,7 +385,7 @@ enum_specifier(register struct type **tpp;)
 			enumerator_pack(*tpp, &l)
 		|
 			{apply_struct(ENUM, idf, tpp);}
-			empty
+			/* empty */
 		]
 	]
 ;
@@ -433,7 +460,7 @@ struct_or_union_specifier(register struct type **tpp;)
 			  if (DOT == ';') declare_struct(fund, idf, tpp);
 			  else apply_struct(fund, idf, tpp);
 			}
-			empty
+			/* empty */
 		]
 	]
 ;
@@ -533,7 +560,7 @@ abstract_declarator(register struct declarator *dc;)
 		[
 			parameter_type_list(&pl)
 		|
-			empty
+			/* empty */
 		]
 		')'
 		{add_decl_unary(dc, FUNCTION, 0, (arith)0, NO_PARAMS, pl);}
@@ -551,7 +578,7 @@ abstract_declarator(register struct declarator *dc;)
 primary_abstract_declarator(struct declarator *dc;)
 :
 [%if (AHEAD == ')' || first_of_parameter_type_list(AHEAD))
-	empty
+	/* empty */
 |
 	'(' abstract_declarator(dc) ')'
 ]
@@ -663,7 +690,7 @@ primary_parameter_declarator(register struct declarator *dc;)
 :
 [%if (AHEAD == ')' || first_of_parameter_type_list(AHEAD)
 				    && (AHEAD != IDENTIFIER))
-	empty
+	/* empty */
 |
 	identifier(&dc->dc_idf)
 |

+ 31 - 51
lang/cem/cemcom.ansi/decspecs.c

@@ -71,62 +71,42 @@ do_decspecs(ds)
 		ds->ds_notypegiven = 1;
 		tp = int_type;
 	}
-	switch (ds->ds_size)	{
-	case SHORT:
-		if (tp == int_type)
-			tp = short_type;
-		else
-			error("short with illegal type");
-		break;
-	case LONG:
-		if (tp == int_type)
-			tp = long_type;
-		else
-		if (tp == double_type)
+	if (ds->ds_size) {
+		register int ds_isshort = (ds->ds_size == SHORT);
+
+		if (ds->ds_typedef) goto SIZE_ERROR;		/* yes */
+		if (tp == int_type) {
+			if (ds_isshort) tp = short_type;
+			else tp = long_type;
+		} else if (tp == double_type && !ds_isshort ) {
 			tp = lngdbl_type;
-		else
-			error("long with illegal type");
-		break;
-	}
-	if (ds->ds_unsigned == UNSIGNED) {
-		switch (tp->tp_fund)	{
-		case CHAR:
-			tp = uchar_type;
-			break;
-		case SHORT:
-			tp = ushort_type;
-			break;
-		case INT:
-			tp = uint_type;
-			break;
-		case LONG:
-			tp = ulong_type;
-			break;
-		default:
-			error("unsigned with illegal type");
-			break;
+		} else {
+	SIZE_ERROR:
+			error("%s with illegal type",symbol2str(ds->ds_size));
 		}
 	}
-	if (ds->ds_unsigned == SIGNED) {
-		switch (tp->tp_fund) {
-		case CHAR:
-			tp = schar_type;
-			break;
-		case SHORT:
-			tp = short_type;
-			break;
-		case INT:
-			tp = int_type;
-			break;
-		case LONG:
-			tp = long_type;
-			break;
-		default:
-			error("signed with illegal type");
-			break;
+	if (ds->ds_unsigned) {
+		register int ds_isunsigned = (ds->ds_unsigned == UNSIGNED);
+
+		if (ds->ds_typedef) goto SIGN_ERROR;		/* yes */
+		/*
+		 * All integral types are signed by default (char too),
+		 * so the case that ds->ds_unsigned == SIGNED can be ignored.
+		 */
+		if (tp == schar_type) {
+			if (ds_isunsigned) tp = uchar_type;
+		} else if (tp == short_type) {
+			if (ds_isunsigned) tp = ushort_type;
+		} else if (tp == int_type) {
+			if (ds_isunsigned) tp = uint_type;
+		} else if (tp == long_type) {
+			if (ds_isunsigned) tp = ulong_type;
+		} else {
+	SIGN_ERROR:
+			error("%s with illegal type"
+				, symbol2str(ds->ds_unsigned));
 		}
 	}
-
 	ds->ds_type = qualifier_type(tp, ds->ds_typequal);
 }
 

+ 1 - 0
lang/cem/cemcom.ansi/decspecs.str

@@ -9,6 +9,7 @@ struct decspecs	{
 	struct decspecs *next;
 	struct type *ds_type;	/* single type */
 	int ds_notypegiven;	/* set if type not given explicitly */
+	int ds_typedef;		/* 1 if type was a user typedef */
 	int ds_sc_given;	/* 1 if the st. class is explicitly given */
 	int ds_sc;		/* storage class, given or implied */
 	int ds_size;		/* LONG, SHORT or 0 */

+ 4 - 11
lang/cem/cemcom.ansi/options.c

@@ -175,21 +175,14 @@ deleted, is now a debug-flag
 			register char *new = text;
 			
 			if (++inc_total > inc_max) {
-				char **n = (char **)
-				   Malloc((10+inc_max)*sizeof(char *));
-				for (i = 0; i < inc_max; i++) {
-					n[i] = inctable[i];
-				}
-				free((char *) inctable);
-				inctable = n;
-				inc_max += 10;
+				inctable = (char **)
+				   Realloc(inctable,(inc_max+=10)*sizeof(char *));
 			}
 				
-			i = inc_pos++;
-			while (new)	{
+			for (i = inc_pos++; i<= inc_total ; i++) {
 				char *tmp = inctable[i];
 				
-				inctable[i++] = new;
+				inctable[i] = new;
 				new = tmp;
 			}
 		}

+ 13 - 5
lang/cem/cemcom.ansi/tokenname.c

@@ -91,18 +91,26 @@ struct tokenname tkidf[] =	{	/* names of the identifier tokens */
 	{UNSIGNED, "unsigned"},
 	{VOLATILE, "volatile"},
 	{WHILE, "while"},
-	{0, ""}
-};
 
-#ifdef	____
-struct tokenname tkfunny[] =	{	/* internal keywords */
+	{VOID, "void"},
 	{CHAR, "char"},
 	{INT, "int"},
 	{FLOAT, "float"},
 	{DOUBLE, "double"},
+	{0, ""}
+};
+
+#ifdef	____
+struct tokenname tkfunny[] =	{	/* internal keywords */
+/* The following may be removed after testing:
+	{Q_VOID, "void"},
+	{Q_CHAR, "char"},
+	{Q_INT, "int"},
+	{Q_FLOAT, "float"},
+	{Q_DOUBLE, "double"},
+*/
 	{LNGDBL, "long double"},
 	{ULONG, "unsigned long"},
-	{VOID, "void"},
 
 	{ARRAY, "array"},
 	{FUNCTION, "function"},

+ 5 - 4
lang/cem/cemcom.ansi/type.c

@@ -249,13 +249,14 @@ idf2type(idf, tpp)
 	struct idf *idf;
 	struct type **tpp;
 {
-	/*	Decoding  a typedef-ed identifier: if the size is yet
-		unknown we have to make copy of the type descriptor to
-		prevent garbage at the initialisation of arrays with
-		unknown size.
+	/*	Decoding  a typedef-ed identifier or basic type: if the
+		size is yet unknown we have to make copy of the type
+		descriptor to prevent garbage at the initialisation of
+		arrays with unknown size.
 	*/
 	register struct type *tp = idf->id_def->df_type;
 
+	if (*tpp) error("multiple types in declaration");
 	if (	tp->tp_size < (arith)0 && tp->tp_fund == ARRAY)	{
 		*tpp = new_type();
 		**tpp = *tp;