%token DUMMY_READ_VOLATILE ENDCRITICAL SWAP INLINE RESTRICT
%type <yyint> Interrupt_storage
-%type <sym> identifier declarator declarator2 declarator3 enumerator_list enumerator
+%type <sym> identifier identifier_or_typename declarator declarator2 declarator3
+%type <sym> enumerator_list enumerator
%type <sym> struct_declarator function_declarator function_declarator2
%type <sym> struct_declarator_list struct_declaration struct_declaration_list
%type <sym> declaration init_declarator_list init_declarator
%type <sym> declaration_list identifier_list
%type <sym> declarator2_function_attributes while do for critical
%type <lnk> pointer type_specifier_list type_specifier type_name
-%type <lnk> storage_class_specifier struct_or_union_specifier
+%type <lnk> storage_class_specifier struct_or_union_specifier function_specifier
%type <lnk> declaration_specifiers sfr_reg_bit sfr_attributes type_specifier2
%type <lnk> function_attribute function_attributes enum_specifier
%type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
else
$$ = mergeSpec($1,$2, "type_specifier declaration_specifiers");
}
+ | function_specifier { $$ = $1; }
+ | function_specifier declaration_specifiers {
+ /* if the decl $2 is not a specifier */
+ /* find the spec and replace it */
+ if ( !IS_SPEC($2)) {
+ sym_link *lnk = $2 ;
+ while (lnk && !IS_SPEC(lnk->next))
+ lnk = lnk->next;
+ lnk->next = mergeSpec($1,lnk->next, "function_specifier declaration_specifiers - skipped");
+ $$ = $2 ;
+ }
+ else
+ $$ = mergeSpec($1,$2, "function_specifier declaration_specifiers");
+ }
;
init_declarator_list
}
;
+function_specifier
+ : INLINE {
+ $$ = newLink (SPECIFIER) ;
+ SPEC_INLINE($$) = 1 ;
+ }
+ ;
+
Interrupt_storage
: INTERRUPT { $$ = INTNO_UNSPEC ; }
| INTERRUPT constant_expr
$$=newLink(SPECIFIER);
SPEC_VOLATILE($$) = 1 ;
}
+ | RESTRICT {
+ $$=newLink(SPECIFIER);
+ SPEC_RESTRICT($$) = 1 ;
+ }
| FLOAT {
$$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_FLOAT;
;
enumerator_list
- : enumerator
- | enumerator_list ',' {
- }
- | enumerator_list ',' enumerator
- {
- symbol *dsym;
-
- for (dsym=$1; dsym; dsym=dsym->next)
- {
- if (strcmp($3->name, dsym->name)==0)
- {
- werrorfl($3->fileDef, $3->lineDef, E_DUPLICATE_MEMBER, "enum", $3->name);
- werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF);
- }
- }
-
- $3->next = $1 ;
- $$ = $3 ;
- }
- ;
+ : enumerator
+ | enumerator_list ','
+ | enumerator_list ',' enumerator
+ {
+ $3->next = $1 ;
+ $$ = $3 ;
+ }
+ ;
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 ;
- // do this now, so we can use it for the next enums in the list
- addSymChain(&$1);
- }
- ;
+ : identifier opt_assign_expr
+ {
+ symbol *sym;
+
+ /* make the symbol one level up */
+ $1->level-- ;
+ // check if the symbol at the same level already exists
+ if ((sym = findSymWithLevel (SymbolTab, $1)) &&
+ sym->level == $1->level)
+ {
+ werrorfl ($1->fileDef, $1->lineDef, E_DUPLICATE_MEMBER, "enum", $1->name);
+ werrorfl (sym->fileDef, sym->lineDef, E_PREVIOUS_DEF);
+ }
+ $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
: '=' constant_expr {
DCL_TSPEC($1) = $2;
DCL_PTR_CONST($1) = SPEC_CONST($2);
DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+ DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
}
else
werror (W_PTR_TYPE_INVALID);
}
| unqualified_pointer type_specifier_list pointer
{
- $$ = $1 ;
- if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
- DCL_PTR_CONST($1) = SPEC_CONST($2);
- DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
- switch (SPEC_SCLS($2)) {
- case S_XDATA:
- DCL_TYPE($3) = FPOINTER;
- break;
- case S_IDATA:
- DCL_TYPE($3) = IPOINTER ;
- break;
- case S_PDATA:
- DCL_TYPE($3) = PPOINTER ;
- break;
- case S_DATA:
- DCL_TYPE($3) = POINTER ;
- break;
- case S_CODE:
- DCL_TYPE($3) = CPOINTER ;
- break;
- case S_EEPROM:
- DCL_TYPE($3) = EEPPOINTER;
- break;
- default:
- // this could be just "constant"
- // werror(W_PTR_TYPE_INVALID);
- ;
- }
- }
- else
- werror (W_PTR_TYPE_INVALID);
- $$->next = $3 ;
- }
+ $$ = $1 ;
+ if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
+ DCL_PTR_CONST($1) = SPEC_CONST($2);
+ DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+ DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
+ switch (SPEC_SCLS($2)) {
+ case S_XDATA:
+ DCL_TYPE($3) = FPOINTER;
+ break;
+ case S_IDATA:
+ DCL_TYPE($3) = IPOINTER ;
+ break;
+ case S_PDATA:
+ DCL_TYPE($3) = PPOINTER ;
+ break;
+ case S_DATA:
+ DCL_TYPE($3) = POINTER ;
+ break;
+ case S_CODE:
+ DCL_TYPE($3) = CPOINTER ;
+ break;
+ case S_EEPROM:
+ DCL_TYPE($3) = EEPPOINTER;
+ break;
+ default:
+ // this could be just "constant"
+ // werror(W_PTR_TYPE_INVALID);
+ ;
+ }
+ }
+ else
+ werror (W_PTR_TYPE_INVALID);
+ $$->next = $3 ;
+ }
;
unqualified_pointer
identifier
: IDENTIFIER { $$ = newSymbol ($1,NestLevel) ; }
;
+
+identifier_or_typename
+ : identifier
+ | TYPE_NAME {
+ symbol *sym;
+ sym_link *p ;
+ sym = findSym(TypedefTab,NULL,$1) ;
+ $$ = p = copyLinkChain(sym->type);
+ SPEC_TYPEDEF(getSpec(p)) = 0;
+ ignoreTypedefType = 1;
+ }
+
%%