X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2FSDCC.y;h=2ef823c93c0e07a1a29af9226af9f376b788dc58;hb=529c3d57ef4bc2112d786e82d961691b803484ec;hp=42dd761bc380e383ea7114db71efaa467c707bf9;hpb=91b0931c40c5cad20cf18aa66303f9cb850f5dbc;p=fw%2Fsdcc diff --git a/src/SDCC.y b/src/SDCC.y index 42dd761b..2ef823c9 100644 --- a/src/SDCC.y +++ b/src/SDCC.y @@ -34,6 +34,7 @@ #include "port.h" #include "newalloc.h" #include "SDCCerr.h" +#include "SDCCutil.h" extern int yyerror (char *); extern FILE *yyin; @@ -56,6 +57,7 @@ STACK_DCL(swStk ,ast *,MAX_NEST_LEVEL) STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3) value *cenum = NULL ; /* current enumeration type chain*/ +bool uselessDecl = TRUE; %} %expect 6 @@ -64,17 +66,17 @@ value *cenum = NULL ; /* current enumeration type chain*/ symbol *sym ; /* symbol table pointer */ structdef *sdef; /* structure definition */ char yychar[SDCC_NAME_MAX+1]; - sym_link *lnk ; /* declarator or specifier */ + sym_link *lnk ; /* declarator or specifier */ int yyint; /* integer value returned */ value *val ; /* for integer constant */ initList *ilist; /* initial list */ - char *yyinline; /* inlined assembler code */ - ast *asts; /* expression tree */ + const char *yyinline; /* inlined assembler code */ + ast *asts; /* expression tree */ } %token IDENTIFIER TYPE_NAME %token CONSTANT STRING_LITERAL -%token SIZEOF +%token SIZEOF TYPEOF %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP %token MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN @@ -85,12 +87,13 @@ value *cenum = NULL ; /* current enumeration type chain*/ %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT %token STRUCT UNION ENUM ELIPSIS RANGE FAR %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN -%token NAKED +%token NAKED JAVANATIVE OVERLAY %token INLINEASM %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE %token RRC RLC %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT +%token DUMMY_READ_VOLATILE %type Interrupt_storage %type identifier declarator declarator2 enumerator_list enumerator @@ -176,32 +179,31 @@ function_attribute function_attributes : USING CONSTANT { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; FUNC_REGBANK($$) = (int) floatFromVal($2); - //FUNC_RBANK($$) = 1; } - | REENTRANT { $$ = newLink (); - $$->class = SPECIFIER ; + | REENTRANT { $$ = newLink (SPECIFIER); FUNC_ISREENT($$)=1; } - | CRITICAL { $$ = newLink (); - $$->class = SPECIFIER ; + | CRITICAL { $$ = newLink (SPECIFIER); FUNC_ISCRITICAL($$) = 1; } - | NAKED { $$ = newLink (); - $$->class = SPECIFIER ; + | NAKED { $$ = newLink (SPECIFIER); FUNC_ISNAKED($$)=1; } - | NONBANKED {$$ = newLink (); - $$->class = SPECIFIER ; + | JAVANATIVE { $$ = newLink (SPECIFIER); + FUNC_ISJAVANATIVE($$)=1; + } + | OVERLAY { $$ = newLink (SPECIFIER); + FUNC_ISOVERLAY($$)=1; + } + | NONBANKED {$$ = newLink (SPECIFIER); FUNC_NONBANKED($$) = 1; if (FUNC_BANKED($$)) { werror(W_BANKED_WITH_NONBANKED); } } - | BANKED {$$ = newLink (); - $$->class = SPECIFIER ; + | BANKED {$$ = newLink (SPECIFIER); FUNC_BANKED($$) = 1; if (FUNC_NONBANKED($$)) { werror(W_BANKED_WITH_NONBANKED); @@ -212,8 +214,7 @@ function_attributes } | Interrupt_storage { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; FUNC_INTNO($$) = $1 ; FUNC_ISISR($$) = 1; } @@ -279,6 +280,7 @@ unary_expr | unary_operator cast_expr { $$ = newNode($1,$2,NULL) ; } | SIZEOF unary_expr { $$ = newNode(SIZEOF,NULL,$2); } | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); } + | TYPEOF unary_expr { $$ = newNode(TYPEOF,NULL,$2); } ; unary_operator @@ -398,34 +400,34 @@ assignment_expr $$ = newNode($2,$1,$3); break; case MUL_ASSIGN: - $$ = newNode('=',$1,newNode('*',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3)); break; case DIV_ASSIGN: - $$ = newNode('=',$1,newNode('/',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3)); break; case MOD_ASSIGN: - $$ = newNode('=',$1,newNode('%',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3)); break; case ADD_ASSIGN: - $$ = newNode('=',$1,newNode('+',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3)); break; case SUB_ASSIGN: - $$ = newNode('=',$1,newNode('-',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3)); break; case LEFT_ASSIGN: - $$ = newNode('=',$1,newNode(LEFT_OP,copyAst($1),$3)); + $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3)); break; case RIGHT_ASSIGN: - $$ = newNode('=',$1,newNode(RIGHT_OP,copyAst($1),$3)); + $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3)); break; case AND_ASSIGN: - $$ = newNode('=',$1,newNode('&',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3)); break; case XOR_ASSIGN: - $$ = newNode('=',$1,newNode('^',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3)); break; case OR_ASSIGN: - $$ = newNode('=',$1,newNode('|',copyAst($1),$3)); + $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); break; default : $$ = NULL; @@ -458,7 +460,13 @@ constant_expr ; declaration - : declaration_specifiers ';' { $$ = NULL ; } + : declaration_specifiers ';' + { + if (uselessDecl) + werror(W_USELESS_DECL); + uselessDecl = TRUE; + $$ = NULL ; + } | declaration_specifiers init_declarator_list ';' { /* add the specifier list to the id */ @@ -471,6 +479,7 @@ declaration addDecl (sym,0,lnk) ; } + uselessDecl = TRUE; $$ = sym1 ; } ; @@ -484,11 +493,11 @@ declaration_specifiers sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next, yytext); + lnk->next = mergeSpec($1,lnk->next, "storage_class_specifier declaration_specifiers - skipped"); $$ = $2 ; } else - $$ = mergeSpec($1,$2, yytext); + $$ = mergeSpec($1,$2, "storage_class_specifier declaration_specifiers"); } | type_specifier { $$ = $1; } | type_specifier declaration_specifiers { @@ -498,11 +507,11 @@ declaration_specifiers sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next, yytext); + lnk->next = mergeSpec($1,lnk->next, "type_specifier declaration_specifiers - skipped"); $$ = $2 ; } else - $$ = mergeSpec($1,$2, yytext); + $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers"); } ; @@ -519,34 +528,39 @@ init_declarator storage_class_specifier : TYPEDEF { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_TYPEDEF($$) = 1 ; } | EXTERN { - $$ = newLink(); - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER); SPEC_EXTR($$) = 1 ; } | STATIC { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_STAT($$) = 1 ; } | AUTO { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_AUTO ; } | REGISTER { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_REGISTER ; } ; Interrupt_storage - : INTERRUPT CONSTANT { $$ = (int) floatFromVal($2) ; } + : INTERRUPT { $$ = INTNO_UNSPEC ; } + | INTERRUPT CONSTANT + { int intno = (int) floatFromVal($2); + if ((intno >= 0) && (intno <= INTNO_MAX)) + $$ = intno; + else + { + werror(E_INT_BAD_INTNO, intno); + $$ = INTNO_UNSPEC; + } + } ; type_specifier @@ -562,97 +576,84 @@ type_specifier type_specifier2 : CHAR { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_CHAR ; } | SHORT { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); $$->select.s._short = 1 ; } | INT { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_INT ; } | LONG { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_LONG($$) = 1 ; } | SIGNED { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); $$->select.s._signed = 1; } | UNSIGNED { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_USIGN($$) = 1 ; } | VOID { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_VOID ; } | CONST { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_CONST($$) = 1; } | VOLATILE { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_VOLATILE($$) = 1 ; } | FLOAT { - $$=newLink(); + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_FLOAT; - $$->class = SPECIFIER ; } | XDATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_XDATA ; } | CODE { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_CODE ; } | EEPROM { - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_SCLS($$) = S_EEPROM ; } | DATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_DATA ; } | IDATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_IDATA ; } | PDATA { - $$ = newLink (); - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER); SPEC_SCLS($$) = S_PDATA ; } | BIT { - $$=newLink(); - $$->class = SPECIFIER ; + $$=newLink(SPECIFIER); SPEC_NOUN($$) = V_BIT ; SPEC_SCLS($$) = S_BIT ; SPEC_BLEN($$) = 1; SPEC_BSTR($$) = 0; } - | struct_or_union_specifier + | struct_or_union_specifier { + uselessDecl = FALSE; + $$ = $1 ; + } | enum_specifier { cenum = NULL ; + uselessDecl = FALSE; $$ = $1 ; } | TYPE_NAME @@ -668,14 +669,12 @@ type_specifier2 sfr_reg_bit : SBIT { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_SBIT; SPEC_SCLS($$) = S_SBIT; } | SFR { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_CHAR; SPEC_SCLS($$) = S_SFR ; SPEC_USIGN($$) = 1 ; @@ -686,22 +685,31 @@ struct_or_union_specifier : struct_or_union opt_stag '{' struct_declaration_list '}' { structdef *sdef ; + symbol *sym, *dsym; + + // check for duplicate structure members + for (sym=$4; sym; sym=sym->next) { + for (dsym=sym->next; dsym; dsym=dsym->next) { + if (strcmp(sym->name, dsym->name)==0) { + werror(E_DUPLICATE_MEMBER, + $1==STRUCT ? "struct" : "union", sym->name); + } + } + } - /* Create a structdef */ + /* Create a structdef */ sdef = $2 ; sdef->fields = reverseSyms($4) ; /* link the fields */ sdef->size = compStructSize($1,sdef); /* update size of */ /* Create the specifier */ - $$ = newLink () ; - $$->class = SPECIFIER ; + $$ = newLink (SPECIFIER) ; SPEC_NOUN($$) = V_STRUCT; SPEC_STRUCT($$)= sdef ; } | struct_or_union stag { - $$ = newLink() ; - $$->class = SPECIFIER ; + $$ = newLink(SPECIFIER) ; SPEC_NOUN($$) = V_STRUCT; SPEC_STRUCT($$) = $2 ; } @@ -735,11 +743,12 @@ struct_declaration_list : struct_declaration | struct_declaration_list struct_declaration { - symbol *sym = $2; - /* go to the end of the chain */ - while (sym->next) sym = sym->next; + symbol *sym=$2; + /* go to the end of the chain */ + while (sym->next) sym=sym->next; sym->next = $1 ; + $$ = $2; } ; @@ -760,7 +769,7 @@ struct_declaration sym->etype = getSpec(sym->type); } else - addDecl (sym,0,cloneSpec($1)); + addDecl (sym,0,copyLinkChain($1)); /* make sure the type is complete and sane */ checkTypeSanity(sym->etype, sym->name); } @@ -779,52 +788,87 @@ struct_declarator_list struct_declarator : declarator - | ':' constant_expr { + | ':' constant_expr { + int bitsize; $$ = newSymbol (genSymName(NestLevel),NestLevel) ; - $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE)); + bitsize= (int) floatFromVal(constExprValue($2,TRUE)); + if (bitsize > (port->s.int_size * 8)) { + bitsize = port->s.int_size * 8; + werror(E_BITFLD_SIZE, bitsize); + } + if (!bitsize) + bitsize = BITVAR_PAD; + $$->bitVar = bitsize; } | declarator ':' constant_expr - { - $1->bitVar = (int) floatFromVal(constExprValue($3,TRUE)); + { + int bitsize; + bitsize= (int) floatFromVal(constExprValue($3,TRUE)); + if (bitsize > (port->s.int_size * 8)) { + bitsize = port->s.int_size * 8; + werror(E_BITFLD_SIZE, bitsize); + } + if (!bitsize) { + $$ = newSymbol (genSymName(NestLevel),NestLevel) ; + $$->bitVar = BITVAR_PAD; + werror(W_BITFLD_NAMED); + } + else + $1->bitVar = bitsize; } ; enum_specifier : ENUM '{' enumerator_list '}' { - addSymChain ($3); - allocVariables(reverseSyms($3)) ; - $$ = copyLinkChain(cenum->type); - } + symbol *sym, *dsym; + char _error=0; + + // check for duplicate enums + for (sym=$3; sym; sym=sym->next) { + for (dsym=sym->next; dsym; dsym=dsym->next) { + if (strcmp(sym->name, dsym->name)==0) { + werror(E_DUPLICATE_MEMBER, "enum", sym->name); + _error++; + } + } + } + if (_error==0) { + $$ = copyLinkChain(cenum->type); + } else { + $$ = newIntLink(); + SPEC_NOUN($$)=0; + } + } + | ENUM identifier '{' enumerator_list '}' { - symbol *csym ; - - $2->type = copyLinkChain(cenum->type); - $2->etype = getSpec($2->type); - /* add this to the enumerator table */ - if (!(csym=findSym(enumTab,$2,$2->name)) && - (csym && csym->level == $2->level)) - werror(E_DUPLICATE_TYPEDEF,csym->name); - - addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); - addSymChain ($4); - allocVariables (reverseSyms($4)); - $$ = copyLinkChain(cenum->type); - SPEC_SCLS(getSpec($$)) = 0 ; - } + symbol *csym ; + + $2->type = copyLinkChain(cenum->type); + $2->etype = getSpec($2->type); + /* add this to the enumerator table */ + if (!(csym=findSym(enumTab,$2,$2->name)) && + (csym && csym->level == $2->level)) + werror(E_DUPLICATE_TYPEDEF,csym->name); + + addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0); + //addSymChain ($4); + //allocVariables (reverseSyms($4)); + $$ = copyLinkChain(cenum->type); + SPEC_SCLS(getSpec($$)) = 0 ; + } | ENUM identifier { - symbol *csym ; - - /* check the enumerator table */ - if ((csym = findSym(enumTab,$2,$2->name))) - $$ = copyLinkChain(csym->type); - else { - $$ = newLink() ; - $$->class = SPECIFIER ; - SPEC_NOUN($$) = V_INT ; - } - - SPEC_SCLS(getSpec($$)) = 0 ; - } + symbol *csym ; + + /* check the enumerator table */ + if ((csym = findSym(enumTab,$2,$2->name))) + $$ = copyLinkChain(csym->type); + else { + $$ = newLink(SPECIFIER) ; + SPEC_NOUN($$) = V_INT ; + } + + SPEC_SCLS(getSpec($$)) = 0 ; + } ; enumerator_list @@ -838,15 +882,17 @@ enumerator_list ; enumerator - : identifier opt_assign_expr { - /* make the symbol one level up */ - $1->level-- ; - $1->type = copyLinkChain($2->type); - $1->etype= getSpec($1->type); - SPEC_ENUM($1->etype) = 1; - $$ = $1 ; - - } + : identifier opt_assign_expr + { + /* make the symbol one level up */ + $1->level-- ; + $1->type = copyLinkChain($2->type); + $1->etype= getSpec($1->type); + SPEC_ENUM($1->etype) = 1; + $$ = $1 ; + // do this now, so we can use it for the next enums in the list + addSymChain($1); + } ; opt_assign_expr @@ -858,11 +904,13 @@ opt_assign_expr } | { if (cenum) { - sprintf(lbuff,"%d",(int) floatFromVal(cenum)+1); + SNPRINTF(lbuff, sizeof(lbuff), + "%d",(int) floatFromVal(cenum)+1); $$ = cenum = constVal(lbuff); } else { - sprintf(lbuff,"%d",0); + SNPRINTF(lbuff, sizeof(lbuff), + "%d",0); $$ = cenum = constVal(lbuff); } } @@ -880,22 +928,32 @@ declarator declarator2_function_attributes : declarator2 { $$ = $1 ; } | declarator2 function_attribute { - // do the functionAttributes (not the args and hasVargs !!) - sym_link *funcType=$1->etype; - struct value *args=FUNC_ARGS(funcType); - unsigned hasVargs=FUNC_HASVARARGS(funcType); - - memcpy (&funcType->funcAttrs, &$2->funcAttrs, - sizeof($2->funcAttrs)); - - FUNC_ARGS(funcType)=args; - FUNC_HASVARARGS(funcType)=hasVargs; - - // just to be sure - memset (&$2->funcAttrs, 0, - sizeof($2->funcAttrs)); - - addDecl ($1,0,$2); + if ((! $1) || (! IS_FUNC($1->etype))) + { + // function_attribute is only allowed if declarator2 was + // an actual function + werror(E_FUNC_ATTR); + $$=$1; + } + else + { + // copy the functionAttributes (not the args and hasVargs !!) + sym_link *funcType=$1->etype; + struct value *args=FUNC_ARGS(funcType); + unsigned hasVargs=FUNC_HASVARARGS(funcType); + + memcpy (&funcType->funcAttrs, &$2->funcAttrs, + sizeof($2->funcAttrs)); + + FUNC_ARGS(funcType)=args; + FUNC_HASVARARGS(funcType)=hasVargs; + + // just to be sure + memset (&$2->funcAttrs, 0, + sizeof($2->funcAttrs)); + + addDecl ($1,0,$2); + } } ; @@ -906,7 +964,7 @@ declarator2 { sym_link *p; - p = newLink (); + p = newLink (DECLARATOR); DCL_TYPE(p) = ARRAY ; DCL_ELEM(p) = 0 ; addDecl($1,0,p); @@ -921,7 +979,7 @@ declarator2 if ( SPEC_SCLS(p) != S_LITERAL) werror(E_CONST_EXPECTED) ; else { - p = newLink (); + p = newLink (DECLARATOR); DCL_TYPE(p) = ARRAY ; DCL_ELEM(p) = (int) floatFromVal(tval) ; addDecl($1,0,p); @@ -969,12 +1027,14 @@ pointer { $$ = $1 ; DCL_TSPEC($1) = $2; + DCL_PTR_CONST($1) = SPEC_CONST($2); + DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2); } | unqualified_pointer pointer { $$ = $1 ; $$->next = $2 ; - DCL_TYPE($2)=GPOINTER; + DCL_TYPE($2)=port->unqualified_pointer; } | unqualified_pointer type_specifier_list pointer { @@ -996,14 +1056,15 @@ pointer DCL_TYPE($3) = POINTER ; break; case S_CODE: - DCL_PTR_CONST($3) = 1; DCL_TYPE($3) = CPOINTER ; break; case S_EEPROM: DCL_TYPE($3) = EEPPOINTER; break; default: - werror(W_PTR_TYPE_INVALID); + // this could be just "constant" + // werror(W_PTR_TYPE_INVALID); + ; } } else @@ -1015,7 +1076,7 @@ pointer unqualified_pointer : '*' { - $$ = newLink(); + $$ = newLink(DECLARATOR); DCL_TYPE($$)=UPOINTER; } ; @@ -1030,11 +1091,11 @@ type_specifier_list sym_link *lnk = $2 ; while (lnk && !IS_SPEC(lnk->next)) lnk = lnk->next; - lnk->next = mergeSpec($1,lnk->next, "type_specifier_list"); + lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped"); $$ = $2 ; } else - $$ = mergeSpec($1,$2, "type_specifier_list"); + $$ = mergeSpec($1,$2, "type_specifier_list type_specifier"); } ; @@ -1090,33 +1151,40 @@ type_name /* go to the end of the list */ sym_link *p; pointerTypes($2,$1); - for ( p = $2 ; p->next ; p=p->next); - p->next = $1 ; - $$ = $2 ; + for ( p = $2 ; p && p->next ; p=p->next); + if (!p) { + werror(E_SYNTAX_ERROR, yytext); + } else { + p->next = $1 ; + } + $$ = $2 ; } ; abstract_declarator : pointer { $$ = reverseLink($1); } | abstract_declarator2 - | pointer abstract_declarator2 { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;} + | pointer abstract_declarator2 { $1 = reverseLink($1); $1->next = $2 ; $$ = $1; + if (IS_PTR($1) && IS_FUNC($2)) + DCL_TYPE($1) = CPOINTER; + } ; abstract_declarator2 : '(' abstract_declarator ')' { $$ = $2 ; } | '[' ']' { - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = 0 ; } | '[' constant_expr ']' { value *val ; - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE)); } | abstract_declarator2 '[' ']' { - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = 0 ; $$->next = $1 ; @@ -1124,7 +1192,7 @@ abstract_declarator2 | abstract_declarator2 '[' constant_expr ']' { value *val ; - $$ = newLink (); + $$ = newLink (DECLARATOR); DCL_TYPE($$) = ARRAY ; DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE)); $$->next = $1 ; @@ -1133,21 +1201,33 @@ abstract_declarator2 | '(' parameter_type_list ')' { $$ = NULL;} | abstract_declarator2 '(' ')' { // $1 must be a pointer to a function - sym_link *p=newLink(); + sym_link *p=newLink(DECLARATOR); DCL_TYPE(p) = FUNCTION; + if (!$1) { + // ((void (code *) ()) 0) () + $1=newLink(DECLARATOR); + DCL_TYPE($1)=CPOINTER; + $$ = $1; + } $1->next=p; } - | abstract_declarator2 '(' parameter_type_list ')' { - if (!IS_VOID($3->type)) { - // this is nonsense, so let's just burp something - werror(E_TOO_FEW_PARMS); - } else { - // $1 must be a pointer to a function - sym_link *p=newLink(); + | abstract_declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')' { + sym_link *p=newLink(DECLARATOR); DCL_TYPE(p) = FUNCTION; - $1->next=p; - } + + FUNC_HASVARARGS(p) = IS_VARG($4); + FUNC_ARGS(p) = reverseVal($4); + + /* nest level was incremented to take care of the parms */ + NestLevel-- ; + currBlockno--; + p->next = $1; + $$ = p; + + // remove the symbol args (if any) + cleanUpLevel(SymbolTab,NestLevel+1); } + ; initializer : assignment_expr { $$ = newiList(INIT_NODE,$1); } @@ -1169,8 +1249,7 @@ statement | jump_statement | INLINEASM ';' { ast *ex = newNode(INLINEASM,NULL,NULL); - ex->values.inlineasm = malloc(strlen($1)+1); - strcpy(ex->values.inlineasm,$1); + ex->values.inlineasm = strdup($1); $$ = ex; } ; @@ -1264,7 +1343,8 @@ selection_statement ex->values.switchVals.swNum = swLabel ; /* now create the label */ - sprintf(lbuff,"_swBrk_%d",swLabel++); + SNPRINTF(lbuff, sizeof(lbuff), + "_swBrk_%d",swLabel++); $$ = newSymbol(lbuff,NestLevel); /* put label in the break stack */ STACK_PUSH(breakStack,$$); @@ -1280,45 +1360,49 @@ selection_statement while : WHILE { /* create and push the continue , break & body labels */ static int Lblnum = 0 ; /* continue */ - sprintf (lbuff,"_whilecontinue_%d",Lblnum); + SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum); STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); /* break */ - sprintf (lbuff,"_whilebreak_%d",Lblnum); + SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum); STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); /* body */ - sprintf (lbuff,"_whilebody_%d",Lblnum++); + SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++); $$ = newSymbol(lbuff,NestLevel); } + ; do : DO { /* create and push the continue , break & body Labels */ static int Lblnum = 0 ; /* continue */ - sprintf(lbuff,"_docontinue_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum); STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); /* break */ - sprintf (lbuff,"_dobreak_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum); STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); /* do body */ - sprintf (lbuff,"_dobody_%d",Lblnum++); + SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++); $$ = newSymbol (lbuff,NestLevel); } + ; + for : FOR { /* create & push continue, break & body labels */ static int Lblnum = 0 ; /* continue */ - sprintf (lbuff,"_forcontinue_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum); STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel)); /* break */ - sprintf (lbuff,"_forbreak_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum); STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel)); /* body */ - sprintf (lbuff,"_forbody_%d",Lblnum); + SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum); $$ = newSymbol(lbuff,NestLevel); /* condition */ - sprintf (lbuff,"_forcond_%d",Lblnum++); + SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++); STACK_PUSH(forStack,newSymbol(lbuff,NestLevel)); } + ; iteration_statement : while '(' expr ')' statement