From 7f5abdd670cc769142d957e393b28ae29e7a06ef Mon Sep 17 00:00:00 2001 From: eck Date: Fri, 13 Jul 1990 10:18:27 +0000 Subject: [PATCH] fixed int to unsigned conversions, declarations, pp-list initialization --- lang/cem/cemcom.ansi/LLlex.c | 9 +-- lang/cem/cemcom.ansi/conversion.c | 8 +++ lang/cem/cemcom.ansi/declar.g | 95 ++++++++++++++++++++----------- lang/cem/cemcom.ansi/decspecs.c | 82 ++++++++++---------------- lang/cem/cemcom.ansi/decspecs.str | 1 + lang/cem/cemcom.ansi/options.c | 15 ++--- lang/cem/cemcom.ansi/tokenname.c | 18 ++++-- lang/cem/cemcom.ansi/type.c | 9 +-- 8 files changed, 128 insertions(+), 109 deletions(-) diff --git a/lang/cem/cemcom.ansi/LLlex.c b/lang/cem/cemcom.ansi/LLlex.c index a0fe5e780..14838cbad 100644 --- a/lang/cem/cemcom.ansi/LLlex.c +++ b/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; } diff --git a/lang/cem/cemcom.ansi/conversion.c b/lang/cem/cemcom.ansi/conversion.c index 934498449..22e86912c 100644 --- a/lang/cem/cemcom.ansi/conversion.c +++ b/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(); diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g index 92c8bae81..4848cbb0d 100644 --- a/lang/cem/cemcom.ansi/declar.g +++ b/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) | diff --git a/lang/cem/cemcom.ansi/decspecs.c b/lang/cem/cemcom.ansi/decspecs.c index c3944dd45..167ea2bab 100644 --- a/lang/cem/cemcom.ansi/decspecs.c +++ b/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); } diff --git a/lang/cem/cemcom.ansi/decspecs.str b/lang/cem/cemcom.ansi/decspecs.str index 59bc24fd3..0895f9720 100644 --- a/lang/cem/cemcom.ansi/decspecs.str +++ b/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 */ diff --git a/lang/cem/cemcom.ansi/options.c b/lang/cem/cemcom.ansi/options.c index bef33f245..0e9b1358e 100644 --- a/lang/cem/cemcom.ansi/options.c +++ b/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; } } diff --git a/lang/cem/cemcom.ansi/tokenname.c b/lang/cem/cemcom.ansi/tokenname.c index 1610f6b9f..ffaa488b0 100644 --- a/lang/cem/cemcom.ansi/tokenname.c +++ b/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"}, diff --git a/lang/cem/cemcom.ansi/type.c b/lang/cem/cemcom.ansi/type.c index 208166163..d29b8f97e 100644 --- a/lang/cem/cemcom.ansi/type.c +++ b/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; -- 2.34.1