1 /*-----------------------------------------------------------------------
2 
3   SDCC.y - parser definition file for sdcc :
4           Written By : Sandeep Dutta . sandeep.dutta@usa.net (1997)
5 
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10 
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15 
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 
20    In other words, you are welcome to use, share and improve this program.
21    You are forbidden to forbid anyone else to use, share and improve
22    what you give them.   Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
24 %{
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include "SDCCglobl.h"
29 #include "SDCCsymt.h"
30 #include "SDCChasht.h"
31 #include "SDCCval.h"
32 #include "SDCCmem.h"
33 #include "SDCCast.h"
34 #include "port.h"
35 #include "newalloc.h"
36 #include "SDCCerr.h"
37 #include "SDCCutil.h"
38 #include "SDCCbtree.h"
39 #include "SDCCopt.h"
40 
41 extern int yyerror (char *);
42 extern FILE     *yyin;
43 long NestLevel = 0;     /* current NestLevel       */
44 int stackPtr  = 1;      /* stack pointer           */
45 int xstackPtr = 0;      /* xstack pointer          */
46 int reentrant = 0;
47 int blockNo   = 0;      /* sequential block number  */
48 int currBlockno=0;
49 int inCriticalFunction = 0;
50 int inCriticalBlock = 0;
51 int seqPointNo= 1;      /* sequence point number */
52 int ignoreTypedefType=0;
53 extern int yylex();
54 int yyparse(void);
55 extern int noLineno;
56 char lbuff[1024];       /* local buffer */
57 char function_name[256] = {0};
58 
59 /* break & continue stacks */
60 STACK_DCL(continueStack  ,symbol *,MAX_NEST_LEVEL)
61 STACK_DCL(breakStack  ,symbol *,MAX_NEST_LEVEL)
62 STACK_DCL(forStack  ,symbol *,MAX_NEST_LEVEL)
63 STACK_DCL(swStk   ,ast   *,MAX_NEST_LEVEL)
64 STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3)
65 
66 value *cenum = NULL;        /* current enumeration  type chain*/
67 bool uselessDecl = TRUE;
68 
69 #define YYDEBUG 1
70 
71 %}
72 %expect 11
73 
74 %union {
75     symbol     *sym;        /* symbol table pointer                   */
76     structdef  *sdef;       /* structure definition                   */
77     char       yychar[SDCC_NAME_MAX+1];
78     sym_link   *lnk;        /* declarator  or specifier               */
79     int        yyint;       /* integer value returned                 */
80     value      *val;        /* for integer constant                   */
81     initList   *ilist;      /* initial list                           */
82     designation*dsgn;       /* designator                             */
83     const char *yystr;      /* pointer to dynamicaly allocated string */
84     ast        *asts;       /* expression tree                        */
85 }
86 
87 %token <yychar> IDENTIFIER TYPE_NAME ADDRSPACE_NAME
88 %token <val> CONSTANT
89 %token SIZEOF ALIGNOF TYPEOF OFFSETOF
90 %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
91 %token AND_OP OR_OP
92 %token ATTRIBCOLON
93 %token <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
94 %token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
95 %token <yyint> XOR_ASSIGN OR_ASSIGN
96 %token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR SFR16 SFR32 ADDRESSMOD STATIC_ASSERT
97 %token AT SBIT REENTRANT USING  XDATA DATA IDATA PDATA VAR_ARGS CRITICAL
98 %token NONBANKED BANKED SHADOWREGS SD_WPARAM
99 %token SD_BOOL SD_CHAR SD_SHORT SD_INT SD_LONG SIGNED UNSIGNED SD_FLOAT DOUBLE FIXED16X16 SD_CONST VOLATILE SD_VOID BIT
100 %token STRUCT UNION ENUM RANGE SD_FAR
101 %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
102 %token NAKED JAVANATIVE OVERLAY TRAP
103 %token <yystr> STRING_LITERAL INLINEASM
104 %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT GETABIT GETBYTE GETWORD
105 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
106 %token RRC RLC
107 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
108 %token DUMMY_READ_VOLATILE ENDCRITICAL SWAP INLINE NORETURN RESTRICT SMALLC PRESERVES_REGS Z88DK_FASTCALL Z88DK_CALLEE ALIGNAS Z88DK_SHORTCALL Z88DK_PARAMS_OFFSET
109 %token GENERIC GENERIC_ASSOC_LIST GENERIC_ASSOCIATION
110 %token ASM
111 
112 %type <yyint> Interrupt_storage
113 %type <sym> identifier declarator declarator2 direct_declarator array_declarator enumerator_list enumerator
114 %type <sym> member_declarator function_declarator
115 %type <sym> member_declarator_list member_declaration member_declaration_list
116 %type <sym> declaration init_declarator_list init_declarator
117 %type <sym> declaration_list identifier_list
118 %type <sym> declaration_after_statement
119 %type <sym> declarator2_function_attributes while do for critical
120 %type <sym> addressmod
121 %type <lnk> pointer type_specifier_list type_specifier_list_ type_specifier type_qualifier_list type_qualifier type_name
122 %type <lnk> storage_class_specifier struct_or_union_specifier function_specifier alignment_specifier
123 %type <lnk> declaration_specifiers declaration_specifiers_ sfr_reg_bit sfr_attributes
124 %type <lnk> function_attribute function_attributes enum_specifier
125 %type <lnk> abstract_declarator direct_abstract_declarator array_abstract_declarator function_abstract_declarator
126 %type <lnk> unqualified_pointer
127 %type <val> parameter_type_list parameter_list parameter_declaration opt_assign_expr
128 %type <sdef> stag opt_stag
129 %type <asts> primary_expr
130 %type <asts> postfix_expr unary_expr offsetof_member_designator cast_expr multiplicative_expr
131 %type <asts> additive_expr shift_expr relational_expr equality_expr
132 %type <asts> and_expr exclusive_or_expr inclusive_or_expr logical_or_expr
133 %type <asts> logical_and_expr conditional_expr assignment_expr constant_expr
134 %type <asts> expr argument_expr_list function_definition expr_opt
135 %type <asts> statement_list statement labeled_statement compound_statement
136 %type <asts> expression_statement selection_statement iteration_statement
137 %type <asts> jump_statement function_body else_statement string_literal_val
138 %type <asts> critical_statement asm_statement label
139 %type <asts> generic_selection generic_assoc_list generic_association
140 %type <asts> implicit_block statements_and_implicit block_item_list
141 %type <dsgn> designator designator_list designation designation_opt
142 %type <ilist> initializer initializer_list
143 %type <yyint> unary_operator assignment_operator struct_or_union
144 %type <yystr> asm_string_literal
145 
146 %start file
147 
148 %%
149 
150    /* C2X A.2.1 Expressions */
151 
152 primary_expr
153    : identifier      { $$ = newAst_VALUE (symbolVal ($1)); }
154    | CONSTANT        { $$ = newAst_VALUE ($1); }
155    | string_literal_val
156    | '(' expr ')'    { $$ = $2; }
157    | generic_selection
158    ;
159 
160 generic_selection
161    : GENERIC '(' assignment_expr ',' generic_assoc_list ')' { $$ = newNode (GENERIC, $3, $5); }
162    ;
163 
164 generic_assoc_list
165    : generic_association { $$ = newNode  (GENERIC_ASSOC_LIST, NULL, $1); }
166    | generic_assoc_list ',' generic_association { $$ = newNode  (GENERIC_ASSOC_LIST, $1, $3); }
167    ;
168 
169 generic_association
170    : type_name ':' assignment_expr { $$ = newNode  (GENERIC_ASSOCIATION, newAst_LINK($1), $3); }
171    | DEFAULT ':' assignment_expr { $$ = newNode  (GENERIC_ASSOCIATION,NULL,$3); }
172    ;
173 
174 postfix_expr
175    : primary_expr
176    | postfix_expr '[' expr ']'          { $$ = newNode  ('[', $1, $3); }
177    | postfix_expr '(' ')'               { $$ = newNode  (CALL,$1,NULL);
178                                           $$->left->funcName = 1;}
179    | postfix_expr '(' argument_expr_list ')'
180           {
181             $$ = newNode  (CALL,$1,$3); $$->left->funcName = 1;
182           }
183    | postfix_expr '.' { ignoreTypedefType = 1; } identifier
184                       {
185                         ignoreTypedefType = 0;
186                         $4 = newSymbol($4->name,NestLevel);
187                         $4->implicit = 1;
188                         $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($4)));
189                       }
190    | postfix_expr PTR_OP { ignoreTypedefType = 1; } identifier
191                       {
192                         ignoreTypedefType = 0;
193                         $4 = newSymbol($4->name,NestLevel);
194                         $4->implicit = 1;
195                         $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($4)));
196                       }
197    | postfix_expr INC_OP
198                       { $$ = newNode(INC_OP,$1,NULL);}
199    | postfix_expr DEC_OP
200                       { $$ = newNode(DEC_OP,$1,NULL); }
201    | '(' type_name ')' '{' initializer_list '}'
202                       {
203                         /* if (!options.std_c99) */
204                           werror(E_COMPOUND_LITERALS_C99);
205 
206                         /* TODO: implement compound literals (C99) */
207                       }
208    | '(' type_name ')' '{' initializer_list ',' '}'
209                       {
210                         /* if (!options.std_c99) */
211                           werror(E_COMPOUND_LITERALS_C99);
212 
213                         /* TODO: implement compound literals (C99) */
214                       }
215    ;
216 
217 argument_expr_list
218    : assignment_expr
219    | assignment_expr ',' argument_expr_list { $$ = newNode(PARAM,$1,$3); }
220    ;
221 
222 unary_expr
223    : postfix_expr
224    | INC_OP unary_expr        { $$ = newNode (INC_OP, NULL, $2); }
225    | DEC_OP unary_expr        { $$ = newNode (DEC_OP, NULL, $2); }
226    | unary_operator cast_expr
227        {
228          if ($1 == '&' && IS_AST_OP ($2) && $2->opval.op == '*' && $2->right == NULL)
229            $$ = $2->left;
230          else if ($1 == '*' && IS_AST_OP ($2) && $2->opval.op == '&' && $2->right == NULL)
231            $$ = $2->left;
232          else
233            $$ = newNode ($1, $2, NULL);
234        }
235    | SIZEOF unary_expr        { $$ = newNode (SIZEOF, NULL, $2); }
236    | SIZEOF '(' type_name ')' { $$ = newAst_VALUE (sizeofOp ($3)); }
237    | ALIGNOF '(' type_name ')'{ $$ = newAst_VALUE (alignofOp ($3)); }
238    | TYPEOF unary_expr        { $$ = newNode (TYPEOF, NULL, $2); }
239    | OFFSETOF '(' type_name ',' offsetof_member_designator ')' { $$ = offsetofOp($3, $5); }
240    ;
241 
242 unary_operator
243    : '&'    { $$ = '&';}
244    | '*'    { $$ = '*';}
245    | '+'    { $$ = '+';}
246    | '-'    { $$ = '-';}
247    | '~'    { $$ = '~';}
248    | '!'    { $$ = '!';}
249    ;
250 
251 cast_expr
252    : unary_expr
253    | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst_LINK($2),$4); }
254    ;
255 
256 multiplicative_expr
257    : cast_expr
258    | multiplicative_expr '*' cast_expr { $$ = newNode('*',$1,$3);}
259    | multiplicative_expr '/' cast_expr { $$ = newNode('/',$1,$3);}
260    | multiplicative_expr '%' cast_expr { $$ = newNode('%',$1,$3);}
261    ;
262 
263 additive_expr
264    : multiplicative_expr
265    | additive_expr '+' multiplicative_expr { $$=newNode('+',$1,$3);}
266    | additive_expr '-' multiplicative_expr { $$=newNode('-',$1,$3);}
267    ;
268 
269 shift_expr
270    : additive_expr
271    | shift_expr LEFT_OP additive_expr  { $$ = newNode(LEFT_OP,$1,$3); }
272    | shift_expr RIGHT_OP additive_expr { $$ = newNode(RIGHT_OP,$1,$3); }
273    ;
274 
275 relational_expr
276    : shift_expr
277    | relational_expr '<' shift_expr   { $$ = newNode('<',  $1,$3);}
278    | relational_expr '>' shift_expr   { $$ = newNode('>',  $1,$3);}
279    | relational_expr LE_OP shift_expr { $$ = newNode(LE_OP,$1,$3);}
280    | relational_expr GE_OP shift_expr { $$ = newNode(GE_OP,$1,$3);}
281    ;
282 
283 equality_expr
284    : relational_expr
285    | equality_expr EQ_OP relational_expr { $$ = newNode(EQ_OP,$1,$3);}
286    | equality_expr NE_OP relational_expr { $$ = newNode(NE_OP,$1,$3);}
287    ;
288 
289 and_expr
290    : equality_expr
291    | and_expr '&' equality_expr  { $$ = newNode('&',$1,$3);}
292    ;
293 
294 exclusive_or_expr
295    : and_expr
296    | exclusive_or_expr '^' and_expr { $$ = newNode('^',$1,$3);}
297    ;
298 
299 inclusive_or_expr
300    : exclusive_or_expr
301    | inclusive_or_expr '|' exclusive_or_expr { $$ = newNode('|',$1,$3);}
302    ;
303 
304 logical_and_expr
305    : inclusive_or_expr
306    | logical_and_expr AND_OP { seqPointNo++;} inclusive_or_expr
307                                  { $$ = newNode(AND_OP,$1,$4);}
308    ;
309 
310 logical_or_expr
311    : logical_and_expr
312    | logical_or_expr OR_OP { seqPointNo++;} logical_and_expr
313                                  { $$ = newNode(OR_OP,$1,$4); }
314    ;
315 
316 conditional_expr
317    : logical_or_expr
318    | logical_or_expr '?' { seqPointNo++;} expr ':' conditional_expr
319                      {
320                         $$ = newNode(':',$4,$6);
321                         $$ = newNode('?',$1,$$);
322                      }
323    ;
324 
325 assignment_expr
326    : conditional_expr
327    | cast_expr assignment_operator assignment_expr
328                      {
329 
330                              switch ($2) {
331                              case '=':
332                                      $$ = newNode($2,$1,$3);
333                                      break;
334                              case MUL_ASSIGN:
335                                      $$ = createRMW($1, '*', $3);
336                                      break;
337                              case DIV_ASSIGN:
338                                      $$ = createRMW($1, '/', $3);
339                                      break;
340                              case MOD_ASSIGN:
341                                      $$ = createRMW($1, '%', $3);
342                                      break;
343                              case ADD_ASSIGN:
344                                      $$ = createRMW($1, '+', $3);
345                                      break;
346                              case SUB_ASSIGN:
347                                      $$ = createRMW($1, '-', $3);
348                                      break;
349                              case LEFT_ASSIGN:
350                                      $$ = createRMW($1, LEFT_OP, $3);
351                                      break;
352                              case RIGHT_ASSIGN:
353                                      $$ = createRMW($1, RIGHT_OP, $3);
354                                      break;
355                              case AND_ASSIGN:
356                                      $$ = createRMW($1, '&', $3);
357                                      break;
358                              case XOR_ASSIGN:
359                                      $$ = createRMW($1, '^', $3);
360                                      break;
361                              case OR_ASSIGN:
362                                      $$ = createRMW($1, '|', $3);
363                                      break;
364                              default :
365                                      $$ = NULL;
366                              }
367 
368                      }
369 ;
370 
371 assignment_operator
372    : '='             { $$ = '=';}
373    | MUL_ASSIGN
374    | DIV_ASSIGN
375    | MOD_ASSIGN
376    | ADD_ASSIGN
377    | SUB_ASSIGN
378    | LEFT_ASSIGN
379    | RIGHT_ASSIGN
380    | AND_ASSIGN
381    | XOR_ASSIGN
382    | OR_ASSIGN
383    ;
384 
385 expr
386    : assignment_expr
387    | expr ',' { seqPointNo++;} assignment_expr { $$ = newNode(',',$1,$4);}
388    ;
389 
390 expr_opt
391    :                 { $$ = NULL; seqPointNo++; }
392    | expr            { $$ = $1; seqPointNo++; }
393    ;
394 
395 constant_expr
396    : conditional_expr
397    ;
398 
399    /* C2X A.2.2 Declarations */
400 
401 declaration
402    : declaration_specifiers ';'
403       {
404          /* Special case: if incomplete struct/union declared without name, */
405          /* make sure an incomplete type for it exists in the current scope */
406          if (IS_STRUCT($1))
407            {
408              structdef *sdef = SPEC_STRUCT($1);
409              structdef *osdef;
410              osdef = findSymWithBlock (StructTab, sdef->tagsym, currBlockno, NestLevel);
411              if (osdef && osdef->block != currBlockno)
412                {
413                  sdef = newStruct(osdef->tagsym->name);
414                  sdef->level = NestLevel;
415                  sdef->block = currBlockno;
416                  sdef->tagsym = newSymbol (osdef->tagsym->name, NestLevel);
417                  addSym (StructTab, sdef, sdef->tag, sdef->level, currBlockno, 0);
418                  uselessDecl = FALSE;
419                }
420            }
421          if (uselessDecl)
422            werror(W_USELESS_DECL);
423          uselessDecl = TRUE;
424          $$ = NULL;
425       }
426    | declaration_specifiers init_declarator_list ';'
427       {
428          /* add the specifier list to the id */
429          symbol *sym , *sym1;
430 
431          for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) {
432              sym_link *lnk = copyLinkChain($1);
433              sym_link *l0 = NULL, *l1 = NULL, *l2 = NULL;
434              /* check illegal declaration */
435              for (l0 = sym->type; l0 != NULL; l0 = l0->next)
436                if (IS_PTR (l0))
437                  break;
438              /* check if creating intances of structs with flexible arrays */
439              for (l1 = lnk; l1 != NULL; l1 = l1->next)
440                if (IS_STRUCT (l1) && SPEC_STRUCT (l1)->b_flexArrayMember)
441                  break;
442              if (!options.std_c99 && l0 == NULL && l1 != NULL && SPEC_EXTR($1) != 1)
443                werror (W_FLEXARRAY_INSTRUCT, sym->name);
444              /* check if creating intances of function type */
445              for (l1 = lnk; l1 != NULL; l1 = l1->next)
446                if (IS_FUNC (l1))
447                  break;
448              for (l2 = lnk; l2 != NULL; l2 = l2->next)
449                if (IS_PTR (l2))
450                  break;
451              if (l0 == NULL && l2 == NULL && l1 != NULL)
452                werrorfl(sym->fileDef, sym->lineDef, E_TYPE_IS_FUNCTION, sym->name);
453              /* do the pointer stuff */
454              pointerTypes(sym->type,lnk);
455              addDecl (sym,0,lnk);
456          }
457 
458          uselessDecl = TRUE;
459          $$ = sym1;
460       }
461    | static_assert_declaration
462       {
463          $$ = NULL;
464       }
465    | attribute_declaration
466       {
467          $$ = NULL;
468       }
469    ;
470 
471 declaration_specifiers : declaration_specifiers_ { $$ = finalizeSpec($1); };
472 
473 declaration_specifiers_
474    : storage_class_specifier                         { $$ = $1; }
475    | storage_class_specifier declaration_specifiers_ {
476      /* if the decl $2 is not a specifier */
477      /* find the spec and replace it      */
478      $$ = mergeDeclSpec($1, $2, "storage_class_specifier declaration_specifiers - skipped");
479    }
480    | type_specifier                                 { $$ = $1; }
481    | type_specifier declaration_specifiers_         {
482      /* if the decl $2 is not a specifier */
483      /* find the spec and replace it      */
484      $$ = mergeDeclSpec($1, $2, "type_specifier declaration_specifiers - skipped");
485    }
486    | function_specifier                             { $$ = $1; }
487    | function_specifier declaration_specifiers_     {
488      /* if the decl $2 is not a specifier */
489      /* find the spec and replace it      */
490      $$ = mergeDeclSpec($1, $2, "function_specifier declaration_specifiers - skipped");
491    }
492    | alignment_specifier                            { $$ = $1; }
493    | alignment_specifier declaration_specifiers_    {
494      /* if the decl $2 is not a specifier */
495      /* find the spec and replace it      */
496      $$ = mergeDeclSpec($1, $2, "alignment_specifier declaration_specifiers - skipped");
497    }
498    ;
499 
500 init_declarator_list
501    : init_declarator
502    | init_declarator_list ',' init_declarator      { $3->next = $1; $$ = $3;}
503    ;
504 
505 init_declarator
506    : declarator                  { $1->ival = NULL; }
507    | declarator '=' initializer  { $1->ival = $3; seqPointNo++; }
508    ;
509 
510 attribute_declaration
511    : attribute_specifier_sequence ';'
512    ;
513 
514 storage_class_specifier
515    : TYPEDEF   {
516                   $$ = newLink (SPECIFIER);
517                   SPEC_TYPEDEF($$) = 1;
518                }
519    | EXTERN    {
520                   $$ = newLink(SPECIFIER);
521                   SPEC_EXTR($$) = 1;
522                }
523    | STATIC    {
524                   $$ = newLink (SPECIFIER);
525                   SPEC_STAT($$) = 1;
526                }
527    | AUTO      {
528                   $$ = newLink (SPECIFIER);
529                   SPEC_SCLS($$) = S_AUTO;
530                }
531    | REGISTER  {
532                   $$ = newLink (SPECIFIER);
533                   SPEC_SCLS($$) = S_REGISTER;
534                }
535    ;
536 
537 type_specifier
538    : type_qualifier { $$ = $1; }
539    | SD_BOOL   {
540                   $$=newLink(SPECIFIER);
541                   SPEC_NOUN($$) = V_BOOL;
542                   ignoreTypedefType = 1;
543                }
544    | SD_CHAR   {
545                   $$=newLink(SPECIFIER);
546                   SPEC_NOUN($$) = V_CHAR;
547                   ignoreTypedefType = 1;
548                }
549    | SD_SHORT  {
550                   $$=newLink(SPECIFIER);
551                   SPEC_SHORT($$) = 1;
552                   ignoreTypedefType = 1;
553                }
554    | SD_INT    {
555                   $$=newLink(SPECIFIER);
556                   SPEC_NOUN($$) = V_INT;
557                   ignoreTypedefType = 1;
558                }
559    | SD_LONG   {
560                   $$=newLink(SPECIFIER);
561                   SPEC_LONG($$) = 1;
562                   ignoreTypedefType = 1;
563                }
564    | SIGNED    {
565                   $$=newLink(SPECIFIER);
566                   $$->select.s.b_signed = 1;
567                   ignoreTypedefType = 1;
568                }
569    | UNSIGNED  {
570                   $$=newLink(SPECIFIER);
571                   SPEC_USIGN($$) = 1;
572                   ignoreTypedefType = 1;
573                }
574    | SD_VOID   {
575                   $$=newLink(SPECIFIER);
576                   SPEC_NOUN($$) = V_VOID;
577                   ignoreTypedefType = 1;
578                }
579    | SD_FLOAT  {
580                   $$=newLink(SPECIFIER);
581                   SPEC_NOUN($$) = V_FLOAT;
582                   ignoreTypedefType = 1;
583                }
584    | FIXED16X16 {
585                   $$=newLink(SPECIFIER);
586                   SPEC_NOUN($$) = V_FIXED16X16;
587                   ignoreTypedefType = 1;
588                }
589    | BIT       {
590                   $$=newLink(SPECIFIER);
591                   SPEC_NOUN($$) = V_BIT;
592                   SPEC_SCLS($$) = S_BIT;
593                   SPEC_BLEN($$) = 1;
594                   SPEC_BSTR($$) = 0;
595                   ignoreTypedefType = 1;
596                }
597    | AT constant_expr {
598                   $$=newLink(SPECIFIER);
599                   /* add this to the storage class specifier  */
600                   SPEC_ABSA($$) = 1;   /* set the absolute addr flag */
601                   /* now get the abs addr from value */
602                   SPEC_ADDR($$) = (unsigned int) ulFromVal(constExprValue($2,TRUE));
603                }
604    | struct_or_union_specifier  {
605                                    uselessDecl = FALSE;
606                                    $$ = $1;
607                                    ignoreTypedefType = 1;
608                                 }
609    | enum_specifier     {
610                            cenum = NULL;
611                            uselessDecl = FALSE;
612                            ignoreTypedefType = 1;
613                            $$ = $1;
614                         }
615    | TYPE_NAME
616          {
617             symbol *sym;
618             sym_link *p;
619             sym = findSym(TypedefTab,NULL,$1);
620             $$ = p = copyLinkChain(sym ? sym->type : NULL);
621             SPEC_TYPEDEF(getSpec(p)) = 0;
622             ignoreTypedefType = 1;
623          }
624    | sfr_reg_bit
625    ;
626 
627 struct_or_union_specifier
628    : struct_or_union opt_stag
629         {
630           structdef *sdef;
631 
632           if (! $2->tagsym)
633             {
634               /* no tag given, so new struct def for current scope */
635               addSym (StructTab, $2, $2->tag, $2->level, currBlockno, 0);
636             }
637           else
638             {
639               sdef = findSymWithBlock (StructTab, $2->tagsym, currBlockno, NestLevel);
640               if (sdef)
641                 {
642                   /* Error if a complete type already defined in this scope */
643                   if (sdef->block == currBlockno)
644                     {
645                       if (sdef->fields)
646                         {
647                           werror(E_STRUCT_REDEF, $2->tag);
648                           werrorfl(sdef->tagsym->fileDef, sdef->tagsym->lineDef, E_PREVIOUS_DEF);
649                         }
650                       else
651                         {
652                           $2 = sdef; /* We are completing an incomplete type */
653                         }
654                     }
655                   else
656                     {
657                       /* There is an existing struct def in an outer scope. */
658                       /* Create new struct def for current scope */
659                       addSym (StructTab, $2, $2->tag, $2->level, currBlockno, 0);
660                     }
661                 }
662               else
663                {
664                  /* There is no existing struct def at all. */
665                  /* Create new struct def for current scope */
666                  addSym (StructTab, $2, $2->tag, $2->level, currBlockno, 0);
667                }
668             }
669 
670           if (!$2->type)
671             {
672               $2->type = $1;
673             }
674           else
675             {
676               if ($2->type != $1)
677                   werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union");
678             }
679         }
680    '{' member_declaration_list '}'
681         {
682           structdef *sdef;
683           symbol *sym, *dsym;
684 
685           // check for errors in structure members
686           for (sym=$5; sym; sym=sym->next)
687             {
688               if (IS_ABSOLUTE(sym->etype))
689                 {
690                   werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "'at'");
691                   SPEC_ABSA(sym->etype) = 0;
692                 }
693               if (IS_SPEC(sym->etype) && SPEC_SCLS(sym->etype))
694                 {
695                   werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "storage class");
696                   printTypeChainRaw (sym->type, NULL);
697                   SPEC_SCLS(sym->etype) = 0;
698                 }
699               for (dsym=sym->next; dsym; dsym=dsym->next)
700                 {
701                   if (*dsym->name && strcmp(sym->name, dsym->name)==0)
702                     {
703                       werrorfl(sym->fileDef, sym->lineDef, E_DUPLICATE_MEMBER,
704                                $1==STRUCT ? "struct" : "union", sym->name);
705                       werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF);
706                     }
707                 }
708             }
709 
710           /* Create a structdef   */
711           sdef = $2;
712           sdef->fields = reverseSyms($5);        /* link the fields */
713           sdef->size = compStructSize($1, sdef); /* update size of  */
714           promoteAnonStructs ($1, sdef);
715 
716           /* Create the specifier */
717           $$ = newLink (SPECIFIER);
718           SPEC_NOUN($$) = V_STRUCT;
719           SPEC_STRUCT($$)= sdef;
720         }
721    | struct_or_union stag
722         {
723           structdef *sdef;
724 
725           sdef = findSymWithBlock (StructTab, $2->tagsym, currBlockno, NestLevel);
726 
727           if (sdef)
728             $2 = sdef;
729           else
730             {
731               /* new struct def for current scope */
732               addSym (StructTab, $2, $2->tag, $2->level, currBlockno, 0);
733             }
734           $$ = newLink(SPECIFIER);
735           SPEC_NOUN($$) = V_STRUCT;
736           SPEC_STRUCT($$) = $2;
737 
738           if (!$2->type)
739             {
740               $2->type = $1;
741             }
742           else
743             {
744               if ($2->type != $1)
745                   werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union");
746             }
747         }
748    ;
749 
750 struct_or_union
751    : STRUCT          { $$ = STRUCT; ignoreTypedefType = 1; }
752    | UNION           { $$ = UNION; ignoreTypedefType = 1; }
753    ;
754 
755 member_declaration_list
756    : member_declaration
757    | member_declaration_list member_declaration
758         {
759           symbol *sym = $2;
760 
761           /* go to the end of the chain */
762           while (sym->next) sym = sym->next;
763           sym->next = $1;
764 
765            $$ = $2;
766         }
767    ;
768 
769 member_declaration
770    : type_specifier_list member_declarator_list ';'
771         {
772           /* add this type to all the symbols */
773           symbol *sym;
774           for ( sym = $2; sym != NULL; sym = sym->next )
775             {
776               sym_link *btype = copyLinkChain($1);
777 
778               pointerTypes(sym->type, btype);
779               if (!sym->type)
780                 {
781                   sym->type = btype;
782                   sym->etype = getSpec(sym->type);
783                 }
784               else
785                   addDecl (sym, 0, btype);
786               /* make sure the type is complete and sane */
787               checkTypeSanity(sym->etype, sym->name);
788             }
789           ignoreTypedefType = 0;
790           $$ = $2;
791         }
792    ;
793 
794 member_declarator_list
795    : member_declarator
796    | member_declarator_list ',' member_declarator
797         {
798           $3->next  = $1;
799           $$ = $3;
800         }
801    ;
802 
803 member_declarator
804    : declarator
805    | ':' constant_expr
806         {
807           unsigned int bitsize;
808           $$ = newSymbol (genSymName(NestLevel), NestLevel);
809           bitsize = (unsigned int) ulFromVal(constExprValue($2, TRUE));
810           if (!bitsize)
811               bitsize = BITVAR_PAD;
812           $$->bitVar = bitsize;
813           $$->bitUnnamed = 1;
814         }
815    | declarator ':' constant_expr
816         {
817           unsigned int bitsize;
818           bitsize = (unsigned int) ulFromVal(constExprValue($3, TRUE));
819 
820           if (!bitsize)
821             {
822               $$ = newSymbol (genSymName(NestLevel), NestLevel);
823               $$->bitVar = BITVAR_PAD;
824               werror(W_BITFLD_NAMED);
825             }
826           else
827               $1->bitVar = bitsize;
828         }
829    | { $$ = newSymbol ("", NestLevel); }
830    ;
831 
832 enum_specifier
833    : ENUM '{' enumerator_list '}'
834         {
835           $$ = newEnumType ($3);
836           SPEC_SCLS(getSpec($$)) = 0;
837         }
838    | ENUM identifier '{' enumerator_list '}'
839         {
840           symbol *csym;
841           sym_link *enumtype;
842 
843           csym = findSymWithLevel(enumTab, $2);
844           if ((csym && csym->level == $2->level))
845             {
846               werrorfl($2->fileDef, $2->lineDef, E_DUPLICATE_TYPEDEF, csym->name);
847               werrorfl(csym->fileDef, csym->lineDef, E_PREVIOUS_DEF);
848             }
849 
850           enumtype = newEnumType ($4);
851           SPEC_SCLS(getSpec(enumtype)) = 0;
852           $2->type = enumtype;
853 
854           /* add this to the enumerator table */
855           if (!csym)
856               addSym (enumTab, $2, $2->name, $2->level, $2->block, 0);
857           $$ = copyLinkChain(enumtype);
858         }
859    | ENUM identifier
860         {
861           symbol *csym;
862 
863           /* check the enumerator table */
864           if ((csym = findSymWithLevel(enumTab, $2)))
865               $$ = copyLinkChain(csym->type);
866           else
867             {
868               $$ = newLink(SPECIFIER);
869               SPEC_NOUN($$) = V_INT;
870             }
871         }
872    ;
873 
874 enumerator_list
875    : enumerator
876    | enumerator_list ','
877    | enumerator_list ',' enumerator
878         {
879           $3->next = $1;
880           $$ = $3;
881         }
882    ;
883 
884 enumerator
885    : identifier opt_assign_expr
886         {
887           symbol *sym;
888 
889           // check if the symbol at the same level already exists
890           if ((sym = findSymWithLevel (SymbolTab, $1)) && sym->level == $1->level)
891             {
892               werrorfl ($1->fileDef, $1->lineDef, E_DUPLICATE_MEMBER, "enum", $1->name);
893               werrorfl (sym->fileDef, sym->lineDef, E_PREVIOUS_DEF);
894             }
895           $1->type = copyLinkChain ($2->type);
896           $1->etype = getSpec ($1->type);
897           SPEC_ENUM ($1->etype) = 1;
898           $$ = $1;
899           // do this now, so we can use it for the next enums in the list
900           addSymChain (&$1);
901         }
902    ;
903 
904 type_qualifier
905    : SD_CONST  {
906                   $$=newLink(SPECIFIER);
907                   SPEC_CONST($$) = 1;
908                }
909    | RESTRICT  {
910                   $$=newLink(SPECIFIER);
911                   SPEC_RESTRICT($$) = 1;
912                }
913    | VOLATILE  {
914                   $$=newLink(SPECIFIER);
915                   SPEC_VOLATILE($$) = 1;
916                }
917    | ADDRSPACE_NAME {
918                   $$=newLink(SPECIFIER);
919                   SPEC_ADDRSPACE($$) = findSym (AddrspaceTab, 0, $1);
920                }
921    | XDATA     {
922                   $$ = newLink (SPECIFIER);
923                   SPEC_SCLS($$) = S_XDATA;
924                }
925    | CODE      {
926                   $$ = newLink (SPECIFIER);
927                   SPEC_SCLS($$) = S_CODE;
928                }
929    | EEPROM    {
930                   $$ = newLink (SPECIFIER);
931                   SPEC_SCLS($$) = S_EEPROM;
932                }
933    | DATA      {
934                   $$ = newLink (SPECIFIER);
935                   SPEC_SCLS($$) = S_DATA;
936                }
937    | IDATA     {
938                   $$ = newLink (SPECIFIER);
939                   SPEC_SCLS($$) = S_IDATA;
940                }
941    | PDATA     {
942                   $$ = newLink (SPECIFIER);
943                   SPEC_SCLS($$) = S_PDATA;
944                }
945    ;
946 
947 function_specifier
948    : INLINE    {
949                   $$ = newLink (SPECIFIER);
950                   SPEC_INLINE($$) = 1;
951                }
952    | NORETURN  {
953                   $$ = newLink (SPECIFIER);
954                   SPEC_NORETURN($$) = 1;
955                }
956    ;
957 
958 alignment_specifier
959    : ALIGNAS '(' type_name ')'
960               {
961                  checkTypeSanity ($3, "(_Alignas)");
962                  $$ = newLink (SPECIFIER);
963                  SPEC_ALIGNAS($$) = 1;
964               }
965    | ALIGNAS '(' constant_expr ')'
966               {
967                  value *val = constExprValue ($3, TRUE);
968                  $$ = newLink (SPECIFIER);
969                  SPEC_ALIGNAS($$) = 0;
970                  if (!val)
971                    werror (E_CONST_EXPECTED);
972                  else if (ulFromVal (val) == 0 || isPowerOf2 (ulFromVal (val)) && ulFromVal (val) <= port->mem.maxextalign)
973                    SPEC_ALIGNAS($$) = ulFromVal(val);
974                  else
975                    werror (E_ALIGNAS, ulFromVal(val));
976               }
977    ;
978 
979 declarator
980    : direct_declarator                        { $$ = $1; }
981    | pointer direct_declarator
982          {
983              addDecl ($2,0,reverseLink($1));
984              $$ = $2;
985          }
986    ;
987 
988 direct_declarator
989    : identifier
990    | '(' declarator ')'     { $$ = $2; }
991    | array_declarator
992    | declarator2_function_attributes
993    ;
994 
995 declarator2
996    : identifier
997    | '(' declarator ')'     { $$ = $2; }
998    | array_declarator
999    ;
1000 
1001 array_declarator:
1002    direct_declarator '[' ']'
1003          {
1004             sym_link   *p;
1005 
1006             p = newLink (DECLARATOR);
1007             DCL_TYPE(p) = ARRAY;
1008             DCL_ELEM(p) = 0;
1009             addDecl($1,0,p);
1010          }
1011    | direct_declarator '[' type_qualifier_list ']'
1012          {
1013             sym_link *p, *n;
1014 
1015             if (!options.std_c99)
1016               werror (E_QUALIFIED_ARRAY_PARAM_C99);
1017 
1018             p = newLink (DECLARATOR);
1019             DCL_TYPE(p) = ARRAY;
1020             DCL_ELEM(p) = 0;
1021             DCL_PTR_CONST(p) = SPEC_CONST ($3);
1022             DCL_PTR_RESTRICT(p) = SPEC_RESTRICT ($3);
1023             DCL_PTR_VOLATILE(p) = SPEC_VOLATILE ($3);
1024             DCL_PTR_ADDRSPACE(p) = SPEC_ADDRSPACE ($3);
1025             addDecl($1,0,p);
1026             n = newLink (SPECIFIER);
1027             SPEC_NEEDSPAR(n) = 1;
1028             addDecl($1,0,n);
1029          }
1030    | direct_declarator '[' constant_expr ']'
1031          {
1032             sym_link *p;
1033             value *tval;
1034             int size;
1035 
1036             tval = constExprValue($3, TRUE);
1037             /* if it is not a constant then Error  */
1038             p = newLink (DECLARATOR);
1039             DCL_TYPE(p) = ARRAY;
1040 
1041             if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
1042               {
1043                 werror(E_CONST_EXPECTED);
1044                 /* Assume a single item array to limit the cascade */
1045                 /* of additional errors. */
1046                 size = 1;
1047               }
1048             else
1049               {
1050                 if ((size = (int) ulFromVal(tval)) < 0)
1051                   {
1052                     werror(E_NEGATIVE_ARRAY_SIZE, $1->name);
1053                     size = 1;
1054                   }
1055               }
1056             DCL_ELEM(p) = size;
1057             addDecl($1, 0, p);
1058          }
1059   | direct_declarator '[' STATIC constant_expr ']'
1060          {
1061             sym_link *p, *n;
1062             value *tval;
1063             int size;
1064 
1065             if (!options.std_c99)
1066               werror (E_STATIC_ARRAY_PARAM_C99);
1067 
1068             tval = constExprValue($4, TRUE);
1069             /* if it is not a constant then Error  */
1070             p = newLink (DECLARATOR);
1071             DCL_TYPE(p) = ARRAY;
1072 
1073             if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
1074               {
1075                 werror(E_CONST_EXPECTED);
1076                 /* Assume a single item array to limit the cascade */
1077                 /* of additional errors. */
1078                 size = 1;
1079               }
1080             else
1081               {
1082                 if ((size = (int) ulFromVal(tval)) < 0)
1083                   {
1084                     werror(E_NEGATIVE_ARRAY_SIZE, $1->name);
1085                     size = 1;
1086                   }
1087               }
1088             DCL_ELEM(p) = size;
1089             addDecl($1, 0, p);
1090             n = newLink (SPECIFIER);
1091             SPEC_NEEDSPAR(n) = 1;
1092             addDecl($1,0,n);
1093          }
1094   | direct_declarator '[' type_qualifier_list constant_expr ']'
1095          {
1096             sym_link *p, *n;
1097             value *tval;
1098             int size;
1099 
1100             if (!options.std_c99)
1101               werror (E_QUALIFIED_ARRAY_PARAM_C99);
1102 
1103             tval = constExprValue($4, TRUE);
1104             /* if it is not a constant then Error  */
1105             p = newLink (DECLARATOR);
1106             DCL_TYPE(p) = ARRAY;
1107 
1108             if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
1109               {
1110                 werror(E_CONST_EXPECTED);
1111                 /* Assume a single item array to limit the cascade */
1112                 /* of additional errors. */
1113                 size = 1;
1114               }
1115             else
1116               {
1117                 if ((size = (int) ulFromVal(tval)) < 0)
1118                   {
1119                     werror(E_NEGATIVE_ARRAY_SIZE, $1->name);
1120                     size = 1;
1121                   }
1122               }
1123             DCL_ELEM(p) = size;
1124             DCL_PTR_CONST(p) = SPEC_CONST ($3);
1125             DCL_PTR_RESTRICT(p) = SPEC_RESTRICT ($3);
1126             DCL_PTR_VOLATILE(p) = SPEC_VOLATILE ($3);
1127             DCL_PTR_ADDRSPACE(p) = SPEC_ADDRSPACE ($3);
1128             addDecl($1, 0, p);
1129             n = newLink (SPECIFIER);
1130             SPEC_NEEDSPAR(n) = 1;
1131             addDecl($1,0,n);
1132          }
1133    | direct_declarator '[' STATIC type_qualifier_list constant_expr ']'
1134          {
1135             sym_link *p, *n;
1136             value *tval;
1137             int size;
1138 
1139             if (!options.std_c99)
1140               {
1141                 werror (E_STATIC_ARRAY_PARAM_C99);
1142                 werror (E_QUALIFIED_ARRAY_PARAM_C99);
1143               }
1144 
1145             tval = constExprValue($5, TRUE);
1146             /* if it is not a constant then Error  */
1147             p = newLink (DECLARATOR);
1148             DCL_TYPE(p) = ARRAY;
1149 
1150             if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
1151               {
1152                 werror(E_CONST_EXPECTED);
1153                 /* Assume a single item array to limit the cascade */
1154                 /* of additional errors. */
1155                 size = 1;
1156               }
1157             else
1158               {
1159                 if ((size = (int) ulFromVal(tval)) < 0)
1160                   {
1161                     werror(E_NEGATIVE_ARRAY_SIZE, $1->name);
1162                     size = 1;
1163                   }
1164               }
1165             DCL_ELEM(p) = size;
1166             DCL_PTR_CONST(p) = SPEC_CONST ($4);
1167             DCL_PTR_RESTRICT(p) = SPEC_RESTRICT ($4);
1168             DCL_PTR_VOLATILE(p) = SPEC_VOLATILE ($4);
1169             DCL_PTR_ADDRSPACE(p) = SPEC_ADDRSPACE ($4);
1170             addDecl($1, 0, p);
1171             n = newLink (SPECIFIER);
1172             SPEC_NEEDSPAR(n) = 1;
1173             addDecl($1,0,n);
1174          }
1175    | direct_declarator '[' type_qualifier_list STATIC constant_expr ']'
1176          {
1177             sym_link *p, *n;
1178             value *tval;
1179             int size;
1180 
1181             if (!options.std_c99)
1182               {
1183                 werror (E_QUALIFIED_ARRAY_PARAM_C99);
1184                 werror (E_STATIC_ARRAY_PARAM_C99);
1185               }
1186 
1187             tval = constExprValue($5, TRUE);
1188             /* if it is not a constant then Error  */
1189             p = newLink (DECLARATOR);
1190             DCL_TYPE(p) = ARRAY;
1191 
1192             if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
1193               {
1194                 werror(E_CONST_EXPECTED);
1195                 /* Assume a single item array to limit the cascade */
1196                 /* of additional errors. */
1197                 size = 1;
1198               }
1199             else
1200               {
1201                 if ((size = (int) ulFromVal(tval)) < 0)
1202                   {
1203                     werror(E_NEGATIVE_ARRAY_SIZE, $1->name);
1204                     size = 1;
1205                   }
1206               }
1207             DCL_ELEM(p) = size;
1208             DCL_PTR_CONST(p) = SPEC_CONST ($3);
1209             DCL_PTR_RESTRICT(p) = SPEC_RESTRICT ($3);
1210             DCL_PTR_VOLATILE(p) = SPEC_VOLATILE ($3);
1211             DCL_PTR_ADDRSPACE(p) = SPEC_ADDRSPACE ($3);
1212             addDecl($1, 0, p);
1213             n = newLink (SPECIFIER);
1214             SPEC_NEEDSPAR(n) = 1;
1215             addDecl($1,0,n);
1216          }
1217    ;
1218 
1219 declarator2_function_attributes
1220    : function_declarator                 { $$ = $1; }
1221    | function_declarator function_attribute  {
1222            // copy the functionAttributes (not the args and hasVargs !!)
1223            struct value *args;
1224            unsigned hasVargs;
1225            sym_link *funcType=$1->type;
1226 
1227            while (funcType && !IS_FUNC(funcType))
1228              funcType = funcType->next;
1229 
1230            if (!funcType)
1231              werror (E_FUNC_ATTR);
1232            else
1233              {
1234                args=FUNC_ARGS(funcType);
1235                hasVargs=FUNC_HASVARARGS(funcType);
1236 
1237                memcpy (&funcType->funcAttrs, &$2->funcAttrs,
1238                    sizeof($2->funcAttrs));
1239 
1240                FUNC_ARGS(funcType)=args;
1241                FUNC_HASVARARGS(funcType)=hasVargs;
1242 
1243                // just to be sure
1244                memset (&$2->funcAttrs, 0,
1245                    sizeof($2->funcAttrs));
1246 
1247                addDecl ($1,0,$2);
1248              }
1249    }
1250    ;
1251 
1252 function_declarator
1253    : declarator2 '('  ')'
1254         {
1255           addDecl ($1, FUNCTION, NULL);
1256         }
1257    | declarator2 '('
1258         {
1259           NestLevel += LEVEL_UNIT;
1260           STACK_PUSH(blockNum, currBlockno);
1261           btree_add_child(currBlockno, ++blockNo);
1262           currBlockno = blockNo;
1263           seqPointNo++; /* not a true sequence point, but helps resolve scope */
1264         }
1265      parameter_type_list ')'
1266         {
1267           sym_link *funcType;
1268 
1269           addDecl ($1, FUNCTION, NULL);
1270 
1271           funcType = $1->type;
1272           while (funcType && !IS_FUNC(funcType))
1273               funcType = funcType->next;
1274 
1275           assert (funcType);
1276 
1277           FUNC_HASVARARGS(funcType) = IS_VARG($4);
1278           FUNC_ARGS(funcType) = reverseVal($4);
1279 
1280           /* nest level was incremented to take care of the parms  */
1281           NestLevel -= LEVEL_UNIT;
1282           currBlockno = STACK_POP(blockNum);
1283           seqPointNo++; /* not a true sequence point, but helps resolve scope */
1284 
1285           // if this was a pointer (to a function)
1286           if (!IS_FUNC($1->type))
1287               cleanUpLevel(SymbolTab, NestLevel + LEVEL_UNIT);
1288 
1289           $$ = $1;
1290         }
1291    | declarator2 '(' identifier_list ')'
1292         {
1293           werror(E_OLD_STYLE,$1->name);
1294           /* assume it returns an int */
1295           $1->type = $1->etype = newIntLink();
1296           $$ = $1;
1297         }
1298    ;
1299 
1300 pointer
1301    : unqualified_pointer { $$ = $1;}
1302    | unqualified_pointer AT constant_expr /* Special case to allow __at at the end */
1303          {
1304              sym_link *n = newLink(SPECIFIER);
1305              /* add this to the storage class specifier  */
1306              SPEC_ABSA(n) = 1;   /* set the absolute addr flag */
1307              /* now get the abs addr from value */
1308              SPEC_ADDR(n) = (unsigned int) ulFromVal(constExprValue($3,TRUE));
1309              n->next = $1;
1310              $$ = n;
1311          }
1312    | unqualified_pointer type_qualifier_list
1313          {
1314              $$ = $1;
1315              if (IS_SPEC($2)) {
1316                  DCL_TSPEC($1) = $2;
1317                  DCL_PTR_CONST($1) = SPEC_CONST($2);
1318                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
1319                  DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
1320                  DCL_PTR_ADDRSPACE($1) = SPEC_ADDRSPACE($2);
1321              }
1322              else
1323                  werror (W_PTR_TYPE_INVALID);
1324          }
1325    | unqualified_pointer type_qualifier_list AT constant_expr /* Special case to allow __at at the end */
1326          {
1327              if (IS_SPEC($2)) {
1328                  DCL_TSPEC($1) = $2;
1329                  DCL_PTR_CONST($1) = SPEC_CONST($2);
1330                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
1331                  DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
1332                  DCL_PTR_ADDRSPACE($1) = SPEC_ADDRSPACE($2);
1333              }
1334              else
1335                  werror (W_PTR_TYPE_INVALID);
1336 
1337              sym_link *n = newLink(SPECIFIER);
1338              /* add this to the storage class specifier  */
1339              SPEC_ABSA(n) = 1;   /* set the absolute addr flag */
1340              /* now get the abs addr from value */
1341              SPEC_ADDR(n) = (unsigned int) ulFromVal(constExprValue($4,TRUE));
1342              n->next = $1;
1343              $$ = n;
1344          }
1345    | unqualified_pointer pointer
1346          {
1347              $$ = $1;
1348              $$->next = $2;
1349              DCL_TYPE($2)=port->unqualified_pointer;
1350          }
1351    | unqualified_pointer type_qualifier_list pointer
1352          {
1353              $$ = $1;
1354              if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
1355                  DCL_PTR_CONST($1) = SPEC_CONST($2);
1356                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
1357                  DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
1358                  DCL_PTR_ADDRSPACE($1) = SPEC_ADDRSPACE($2);
1359                  switch (SPEC_SCLS($2)) {
1360                  case S_XDATA:
1361                      DCL_TYPE($3) = FPOINTER;
1362                      break;
1363                  case S_IDATA:
1364                      DCL_TYPE($3) = IPOINTER;
1365                      break;
1366                  case S_PDATA:
1367                      DCL_TYPE($3) = PPOINTER;
1368                      break;
1369                  case S_DATA:
1370                      DCL_TYPE($3) = POINTER;
1371                      break;
1372                  case S_CODE:
1373                      DCL_TYPE($3) = CPOINTER;
1374                      break;
1375                  case S_EEPROM:
1376                      DCL_TYPE($3) = EEPPOINTER;
1377                      break;
1378                  default:
1379                    // this could be just "constant"
1380                    // werror(W_PTR_TYPE_INVALID);
1381                      ;
1382                  }
1383              }
1384              else
1385                  werror (W_PTR_TYPE_INVALID);
1386              $$->next = $3;
1387          }
1388    ;
1389 
1390 unqualified_pointer
1391    :  '*'
1392       {
1393         $$ = newLink(DECLARATOR);
1394         DCL_TYPE($$)=UPOINTER;
1395       }
1396    ;
1397 
1398 type_qualifier_list
1399   : type_qualifier
1400   | type_qualifier_list type_qualifier
1401                {
1402                  $$ = mergeDeclSpec($1, $2, "type_qualifier_list type_qualifier skipped");
1403                }
1404   ;
1405 
1406 parameter_type_list
1407         : parameter_list
1408         | parameter_list ',' VAR_ARGS { $1->vArgs = 1;}
1409         ;
1410 
1411 parameter_list
1412    : parameter_declaration
1413    | parameter_list ',' parameter_declaration
1414          {
1415             $3->next = $1;
1416             $$ = $3;
1417          }
1418    ;
1419 
1420 parameter_declaration
1421    : declaration_specifiers declarator
1422         {
1423           symbol *loop;
1424 
1425           if (IS_SPEC ($1) && !IS_VALID_PARAMETER_STORAGE_CLASS_SPEC ($1))
1426             {
1427               werror (E_STORAGE_CLASS_FOR_PARAMETER, $2->name);
1428             }
1429           pointerTypes ($2->type, $1);
1430           if (IS_SPEC ($2->etype))
1431             SPEC_NEEDSPAR($2->etype) = 0;
1432           addDecl ($2, 0, $1);
1433           for (loop = $2; loop; loop->_isparm = 1, loop = loop->next)
1434             ;
1435           $$ = symbolVal ($2);
1436           ignoreTypedefType = 0;
1437         }
1438    | type_name
1439         {
1440           $$ = newValue ();
1441           $$->type = $1;
1442           $$->etype = getSpec ($$->type);
1443           ignoreTypedefType = 0;
1444          }
1445    ;
1446 
1447 abstract_declarator
1448    : pointer { $$ = reverseLink($1); }
1449    | direct_abstract_declarator
1450    | pointer direct_abstract_declarator   { $1 = reverseLink($1); $2->next = $1; $$ = $2;
1451           if (IS_PTR($1) && IS_FUNC($2))
1452             DCL_TYPE($1) = CPOINTER;
1453         }
1454    ;
1455 
1456 direct_abstract_declarator
1457    : '(' abstract_declarator ')'    { $$ = $2; }
1458    | array_abstract_declarator
1459    | function_abstract_declarator
1460    ;
1461 
1462 array_abstract_declarator
1463    : '[' ']'                        {
1464                                        $$ = newLink (DECLARATOR);
1465                                        DCL_TYPE($$) = ARRAY;
1466                                        DCL_ELEM($$) = 0;
1467                                     }
1468    | '[' constant_expr ']'          {
1469                                        value *val;
1470                                        $$ = newLink (DECLARATOR);
1471                                        DCL_TYPE($$) = ARRAY;
1472                                        DCL_ELEM($$) = (int) ulFromVal(val = constExprValue($2,TRUE));
1473                                     }
1474    | direct_abstract_declarator '[' ']'   {
1475                                        $$ = newLink (DECLARATOR);
1476                                        DCL_TYPE($$) = ARRAY;
1477                                        DCL_ELEM($$) = 0;
1478                                        $$->next = $1;
1479                                     }
1480    | direct_abstract_declarator '[' constant_expr ']'
1481                                     {
1482                                        value *val;
1483                                        $$ = newLink (DECLARATOR);
1484                                        DCL_TYPE($$) = ARRAY;
1485                                        DCL_ELEM($$) = (int) ulFromVal(val = constExprValue($3,TRUE));
1486                                        $$->next = $1;
1487                                     }
1488    ;
1489 
1490 function_abstract_declarator
1491    : '(' ')'                        { $$ = NULL;}
1492    | '(' parameter_type_list ')'    { $$ = NULL;}
1493    | direct_abstract_declarator '(' ')' {
1494      // $1 must be a pointer to a function
1495      sym_link *p=newLink(DECLARATOR);
1496      DCL_TYPE(p) = FUNCTION;
1497      if (!$1) {
1498        // ((void (code *) ()) 0) ()
1499        $1=newLink(DECLARATOR);
1500        DCL_TYPE($1)=CPOINTER;
1501        $$ = $1;
1502      }
1503      $1->next=p;
1504    }
1505    | direct_abstract_declarator '('
1506         {
1507           NestLevel += LEVEL_UNIT;
1508           STACK_PUSH(blockNum, currBlockno);
1509           btree_add_child(currBlockno, ++blockNo);
1510           currBlockno = blockNo;
1511         }
1512      parameter_type_list ')'
1513         {
1514           sym_link *p = newLink(DECLARATOR), *q;
1515           DCL_TYPE(p) = FUNCTION;
1516 
1517           FUNC_HASVARARGS(p) = IS_VARG($4);
1518           FUNC_ARGS(p) = reverseVal($4);
1519 
1520           /* nest level was incremented to take care of the parms  */
1521           NestLevel -= LEVEL_UNIT;
1522           currBlockno = STACK_POP(blockNum);
1523           if (!$1)
1524             {
1525               /* ((void (code *) (void)) 0) () */
1526               $1 = newLink(DECLARATOR);
1527               DCL_TYPE($1) = CPOINTER;
1528               $$ = $1;
1529             }
1530           for (q = $1; q && q->next; q = q->next);
1531           q->next = p;
1532         }
1533    ;
1534 
1535 initializer
1536    : assignment_expr                { $$ = newiList(INIT_NODE,$1); }
1537    | '{'  initializer_list '}'      { $$ = newiList(INIT_DEEP,revinit($2)); }
1538    | '{'  initializer_list ',' '}'  { $$ = newiList(INIT_DEEP,revinit($2)); }
1539    ;
1540 
1541 initializer_list
1542    : designation_opt initializer    { $2->designation = $1; $$ = $2; }
1543    | initializer_list ',' designation_opt initializer
1544                                     {
1545                                        $4->designation = $3;
1546                                        $4->next = $1;
1547                                        $$ = $4;
1548                                     }
1549    ;
1550 
1551 designation_opt
1552    :                             { $$ = NULL; }
1553    | designation
1554    ;
1555 
1556 designation
1557    : designator_list '='         { $$ = revDesignation($1); }
1558    ;
1559 
1560 designator_list
1561    : designator
1562    | designator_list designator  { $2->next = $1; $$ = $2; }
1563    ;
1564 
1565 designator
1566    : '[' constant_expr ']'
1567          {
1568             value *tval;
1569             int elemno;
1570 
1571             tval = constExprValue($2, TRUE);
1572             /* if it is not a constant then Error  */
1573             if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
1574               {
1575                 werror (E_CONST_EXPECTED);
1576                 elemno = 0; /* arbitrary fixup */
1577               }
1578             else
1579               {
1580                 if ((elemno = (int) ulFromVal(tval)) < 0)
1581                   {
1582                     werror (E_BAD_DESIGNATOR);
1583                     elemno = 0; /* arbitrary fixup */
1584                   }
1585               }
1586             $$ = newDesignation(DESIGNATOR_ARRAY, &elemno);
1587          }
1588    | '.' identifier              { $$ = newDesignation(DESIGNATOR_STRUCT,$2); }
1589    ;
1590 
1591 static_assert_declaration
1592    : STATIC_ASSERT '(' constant_expr ',' STRING_LITERAL ')' ';'
1593                                     {
1594                                        value *val = constExprValue ($3, TRUE);
1595                                        if (!val)
1596                                          werror (E_CONST_EXPECTED);
1597                                        else if (!ulFromVal(val))
1598                                          werror (W_STATIC_ASSERTION, $5);
1599                                     }
1600    | STATIC_ASSERT '(' constant_expr ')' ';'
1601                                     {
1602                                        value *val = constExprValue ($3, TRUE);
1603                                        if (!options.std_c2x)
1604                                          werror (E_STATIC_ASSERTION_C2X);
1605                                        if (!val)
1606                                          werror (E_CONST_EXPECTED);
1607                                        else if (!ulFromVal(val))
1608                                          werror (W_STATIC_ASSERTION_2);
1609                                     }
1610    ;
1611 
1612 attribute_specifier_sequence
1613    : attribute_specifier_sequence attribute_specifier
1614    | attribute_specifier
1615    ;
1616 
1617 attribute_specifier_sequence_opt
1618    : /* empty */
1619    | attribute_specifier_sequence
1620    ;
1621 
1622 attribute_specifier
1623    : '[' '[' attribute_list ']' ']'
1624      {
1625        if (!options.std_c2x)
1626          werror(E_ATTRIBUTE_C2X);
1627      }
1628    ;
1629 
1630 attribute_list
1631    : /* empty */
1632    | attribute
1633    | attribute_list ','
1634    | attribute_list ',' attribute
1635    ;
1636 
1637 attribute
1638    : attribute_token
1639    | attribute_token attribute_argument_clause
1640    ;
1641 
1642 attribute_token
1643    : identifier
1644    | identifier ATTRIBCOLON identifier
1645    ;
1646 
1647 attribute_argument_clause
1648    : '(' ')'
1649    | '(' balanced_token_sequence ')'
1650    ;
1651 
1652 balanced_token_sequence
1653    : balanced_token
1654    | balanced_token_sequence balanced_token
1655    ;
1656 
1657 balanced_token
1658    : identifier
1659    | STRING_LITERAL
1660    ;
1661 
1662    /* C2X A.2.3 Statements */
1663 
1664 statement
1665    : labeled_statement
1666    | expression_statement
1667    | attribute_specifier_sequence_opt compound_statement
1668      {
1669        $$ = $2;
1670      }
1671    | attribute_specifier_sequence_opt selection_statement
1672      {
1673        $$ = $2;
1674      }
1675    | attribute_specifier_sequence_opt iteration_statement
1676      {
1677        $$ = $2;
1678      }
1679    | attribute_specifier_sequence_opt jump_statement
1680      {
1681        $$ = $2;
1682      }
1683    | critical_statement
1684    | asm_statement
1685    ;
1686 
1687 labeled_statement
1688    : label statement  { if ($1) {$$ = $1; $1->right = $2;} else $$ = newNode (BLOCK, NULL, NULL); }
1689    | attribute_specifier_sequence label statement  { if ($2) {$$ = $2; $2->right = $3;} else $$ = newNode (BLOCK, NULL, NULL); }
1690    | label '}'
1691      { /* Support a label without a statement at the end of a */
1692        /* compound statement as a SDCC extension. Include the */
1693        /* closing brace as part of the rule to avoid an */
1694        /* unacceptably large number of shift/reduce conflicts */
1695        /* and then reinsert it to be parsed a second time. */
1696        werror(W_LABEL_WITHOUT_STATEMENT);
1697        $$ = $1;
1698        yychar = '}';
1699      }
1700     ;
1701 
1702 label
1703    : identifier ':'                    {  $$ = createLabel($1,NULL);
1704                                           $1->isitmp = 0;  }
1705    | CASE constant_expr ':'
1706      {
1707        if (STACK_EMPTY(swStk))
1708          $$ = createCase(NULL,$2,NULL);
1709        else
1710          $$ = createCase(STACK_PEEK(swStk),$2,NULL);
1711      }
1712    | DEFAULT { $<asts>$ = newNode(DEFAULT,NULL,NULL); } ':'
1713      {
1714        if (STACK_EMPTY(swStk))
1715          $$ = createDefault(NULL,$<asts>2,NULL);
1716        else
1717          $$ = createDefault(STACK_PEEK(swStk),$<asts>2,NULL);
1718      }
1719    ;
1720 
1721 start_block
1722    : '{'
1723         {
1724           NestLevel += LEVEL_UNIT;
1725           STACK_PUSH(blockNum, currBlockno);
1726           btree_add_child(currBlockno, ++blockNo);
1727           currBlockno = blockNo;
1728           ignoreTypedefType = 0;
1729         }
1730    ;
1731 
1732 end_block
1733    : '}'
1734         {
1735           NestLevel -= LEVEL_UNIT;
1736           currBlockno = STACK_POP(blockNum);
1737         }
1738    ;
1739 
1740 compound_statement
1741    : start_block end_block                    { $$ = createBlock(NULL, NULL); }
1742    | start_block block_item_list end_block
1743      {
1744        $$ = $2;
1745        cleanUpLevel(StructTab, NestLevel + LEVEL_UNIT);
1746      }
1747    | error ';'                                { $$ = NULL; }
1748    ;
1749 
1750 block_item_list
1751    : statements_and_implicit                  { $$ = createBlock(NULL, $1); }
1752    | declaration_list                         { $$ = createBlock($1, NULL); }
1753    | declaration_list statements_and_implicit { $$ = createBlock($1, $2); }
1754    ;
1755 
1756 expression_statement
1757    : expr_opt ';'
1758    | attribute_specifier_sequence expr ';'           { $$ = $2; seqPointNo++;}
1759    ;
1760 
1761 selection_statement
1762    : IF '(' expr ')' { seqPointNo++;} statement else_statement
1763                            {
1764                               noLineno++;
1765                               $$ = createIf ($3, $6, $7 );
1766                               $$->lineno = $3->lineno;
1767                               $$->filename = $3->filename;
1768                               noLineno--;
1769                            }
1770    | SWITCH '(' expr ')'   {
1771                               ast *ex;
1772                               static   int swLabel = 0;
1773 
1774                               seqPointNo++;
1775                               /* create a node for expression  */
1776                               ex = newNode(SWITCH,$3,NULL);
1777                               STACK_PUSH(swStk,ex);   /* save it in the stack */
1778                               ex->values.switchVals.swNum = swLabel;
1779 
1780                               /* now create the label */
1781                               SNPRINTF(lbuff, sizeof(lbuff),
1782                                        "_swBrk_%d",swLabel++);
1783                               $<sym>$  =  newSymbol(lbuff,NestLevel);
1784                               /* put label in the break stack  */
1785                               STACK_PUSH(breakStack,$<sym>$);
1786                            }
1787      statement             {
1788                               /* get back the switch form the stack  */
1789                               $$ = STACK_POP(swStk);
1790                               $$->right = newNode (NULLOP,$6,createLabel($<sym>5,NULL));
1791                               STACK_POP(breakStack);
1792                            }
1793         ;
1794 
1795 iteration_statement
1796    : while '(' expr ')' { seqPointNo++;}  statement
1797                          {
1798                            noLineno++;
1799                            $$ = createWhile ( $1, STACK_POP(continueStack),
1800                                               STACK_POP(breakStack), $3, $6 );
1801                            $$->lineno = $1->lineDef;
1802                            $$->filename = $1->fileDef;
1803                            noLineno--;
1804                          }
1805    | do statement   WHILE '(' expr ')' ';'
1806                         {
1807                           seqPointNo++;
1808                           noLineno++;
1809                           $$ = createDo ( $1 , STACK_POP(continueStack),
1810                                           STACK_POP(breakStack), $5, $2);
1811                           $$->lineno = $1->lineDef;
1812                           $$->filename = $1->fileDef;
1813                           noLineno--;
1814                         }
1815    | for '(' expr_opt   ';' expr_opt ';' expr_opt ')'  statement
1816                         {
1817                           noLineno++;
1818 
1819                           $$ = newNode(FOR,$9,NULL);
1820                           AST_FOR($$,trueLabel) = $1;
1821                           AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
1822                           AST_FOR($$,falseLabel) = STACK_POP(breakStack);
1823                           AST_FOR($$,condLabel)  = STACK_POP(forStack);
1824                           AST_FOR($$,initExpr)   = $3;
1825                           AST_FOR($$,condExpr)   = $5;
1826                           AST_FOR($$,loopExpr)   = $7;
1827 
1828                           /* This continue label is not at the correct location, */
1829                           /* but we need to create it now for proper binding. The */
1830                           /* code that handles the FOR node will move it to the */
1831                           /* proper location inside the for loop. */
1832                           if (AST_FOR($$,continueLabel)->isref)
1833                             $$->right = createLabel(AST_FOR($$,continueLabel),NULL);
1834                           $$ = newNode(NULLOP,$$,createLabel(AST_FOR($$,falseLabel),NULL));
1835                           noLineno--;
1836 
1837                           NestLevel -= LEVEL_UNIT;
1838                           currBlockno = STACK_POP(blockNum);
1839                         }
1840    | for '(' declaration expr_opt ';' expr_opt ')'
1841                         {
1842                           if (!options.std_c99)
1843                             werror (E_FOR_INITAL_DECLARATION_C99);
1844 
1845                           if ( $3 && IS_TYPEDEF($3->etype))
1846                             allocVariables ($3);
1847                           ignoreTypedefType = 0;
1848                           addSymChain(&$3);
1849                         }
1850    statement
1851                         {
1852 
1853                           noLineno++;
1854 
1855                           $$ = newNode(FOR,$9,NULL);
1856                           AST_FOR($$,trueLabel) = $1;
1857                           AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
1858                           AST_FOR($$,falseLabel) = STACK_POP(breakStack);
1859                           AST_FOR($$,condLabel)  = STACK_POP(forStack);
1860                           AST_FOR($$,initExpr)   = 0;
1861                           AST_FOR($$,condExpr)   = $4;
1862                           AST_FOR($$,loopExpr)   = $6;
1863 
1864                           /* This continue label is not at the correct location, */
1865                           /* but we need to create it now for proper binding. The */
1866                           /* code that handles the FOR node will move it to the */
1867                           /* proper location inside the for loop. */
1868                           if (AST_FOR($$,continueLabel)->isref)
1869                             $$->right = createLabel(AST_FOR($$,continueLabel),NULL);
1870                           $$ = createBlock($3, newNode(NULLOP,$$,createLabel(AST_FOR($$,falseLabel),NULL)));
1871                           cleanUpLevel(StructTab, NestLevel + LEVEL_UNIT);
1872                           noLineno--;
1873 
1874                           NestLevel -= LEVEL_UNIT;
1875                           currBlockno = STACK_POP(blockNum);
1876                         }
1877    ;
1878 
1879 jump_statement
1880    : GOTO identifier ';'   {
1881                               if (inCriticalBlock) {
1882                                 werror(E_INVALID_CRITICAL);
1883                                 $$ = NULL;
1884                               } else {
1885                                 $2->islbl = 1;
1886                                 $$ = newAst_VALUE(symbolVal($2));
1887                                 $$ = newNode(GOTO,$$,NULL);
1888                               }
1889                            }
1890    | CONTINUE ';'          {
1891        /* make sure continue is in context */
1892        if (STACK_EMPTY(continueStack) || STACK_PEEK(continueStack) == NULL) {
1893            werror(E_BREAK_CONTEXT);
1894            $$ = NULL;
1895        }
1896        else {
1897            $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack)));
1898            $$ = newNode(GOTO,$$,NULL);
1899            /* mark the continue label as referenced */
1900            STACK_PEEK(continueStack)->isref = 1;
1901        }
1902    }
1903    | BREAK ';'             {
1904        if (STACK_EMPTY(breakStack) || STACK_PEEK(breakStack) == NULL) {
1905            werror(E_BREAK_CONTEXT);
1906            $$ = NULL;
1907        } else {
1908            $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack)));
1909            $$ = newNode(GOTO,$$,NULL);
1910            STACK_PEEK(breakStack)->isref = 1;
1911        }
1912    }
1913    | RETURN ';'            {
1914        seqPointNo++;
1915        if (inCriticalBlock) {
1916            werror(E_INVALID_CRITICAL);
1917            $$ = NULL;
1918        } else {
1919            $$ = newNode(RETURN,NULL,NULL);
1920        }
1921    }
1922    | RETURN expr ';'       {
1923        seqPointNo++;
1924        if (inCriticalBlock) {
1925            werror(E_INVALID_CRITICAL);
1926            $$ = NULL;
1927        } else {
1928            $$ = newNode(RETURN,NULL,$2);
1929        }
1930    }
1931    ;
1932 
1933    /* C2X A.2.4 External definitions */
1934 
1935 translation_unit
1936    : external_declaration
1937    | translation_unit external_declaration
1938    ;
1939 
1940 external_declaration
1941    : function_definition
1942         {
1943           // blockNo = 0;
1944         }
1945    | declaration
1946         {
1947           ignoreTypedefType = 0;
1948           if ($1 && $1->type && IS_FUNC($1->type))
1949             {
1950               /* The only legal storage classes for
1951                * a function prototype (declaration)
1952                * are extern and static. extern is the
1953                * default. Thus, if this function isn't
1954                * explicitly marked static, mark it
1955                * extern.
1956                */
1957               if ($1->etype && IS_SPEC($1->etype) && !SPEC_STAT($1->etype))
1958                 {
1959                   SPEC_EXTR($1->etype) = 1;
1960                 }
1961             }
1962           addSymChain (&$1);
1963           allocVariables ($1);
1964           cleanUpLevel (SymbolTab, 1);
1965         }
1966    | addressmod
1967         {
1968           /* These empty braces here are apparently required by some version of GNU bison on MS Windows. See bug #2858. */
1969         }
1970    ;
1971 
1972 function_definition
1973    : declarator
1974         {   /* function type not specified */
1975             /* assume it to be 'int'       */
1976             addDecl($1,0,newIntLink());
1977             $1 = createFunctionDecl($1);
1978             if ($1)
1979                 {
1980                     if (FUNC_ISCRITICAL ($1->type))
1981                         inCriticalFunction = 1;
1982                     strncpy (function_name, $1->name, sizeof (function_name) - 4);
1983                     memset (function_name + sizeof (function_name) - 4, 0x00, 4);
1984                 }
1985         }
1986    function_body
1987         {
1988             $$ = createFunction($1,$3);
1989             if ($1 && FUNC_ISCRITICAL ($1->type))
1990                 inCriticalFunction = 0;
1991         }
1992    | declaration_specifiers declarator
1993         {
1994             sym_link *p = copyLinkChain($1);
1995             pointerTypes($2->type,p);
1996             addDecl($2,0,p);
1997             $2 = createFunctionDecl($2);
1998             if ($2)
1999                 {
2000                     if (FUNC_ISCRITICAL ($2->type))
2001                         inCriticalFunction = 1;
2002                     // warn for loss of calling convention for inlined functions.
2003                     if (FUNC_ISINLINE ($2->type) &&
2004                         ( FUNC_ISZ88DK_CALLEE ($2->type) || FUNC_ISZ88DK_FASTCALL ($2->type) ||
2005                           FUNC_BANKED ($2->type)         || FUNC_REGBANK ($2->type)          ||
2006                           FUNC_ISOVERLAY ($2->type)      || FUNC_ISISR ($2->type) ))
2007                         werror (W_INLINE_FUNCATTR, $2->name);
2008                     strncpy (function_name, $2->name, sizeof (function_name) - 4);
2009                     memset (function_name + sizeof (function_name) - 4, 0x00, 4);
2010                 }
2011         }
2012    function_body
2013         {
2014             $$ = createFunction($2,$4);
2015             if ($2 && FUNC_ISCRITICAL ($2->type))
2016                 inCriticalFunction = 0;
2017         }
2018    ;
2019 
2020 function_body
2021    : compound_statement
2022    | declaration_list compound_statement
2023                      {
2024                        werror (E_OLD_STYLE, ($1 ? $1->name: ""));
2025                        exit (1);
2026                      }
2027    ;
2028 
2029    /* SDCC-specific stuff */
2030 
2031 file
2032    : /* empty */
2033         {
2034           werror(W_EMPTY_SOURCE_FILE);
2035         }
2036    | translation_unit
2037    ;
2038 
2039 
2040 
2041 
2042 function_attribute
2043    : function_attributes
2044    | function_attributes function_attribute { $$ = mergeSpec($1,$2,"function_attribute"); }
2045    ;
2046 
2047 function_attributes
2048    :  USING constant_expr {
2049                         $$ = newLink(SPECIFIER);
2050                         FUNC_REGBANK($$) = (int) ulFromVal(constExprValue($2,TRUE));
2051                      }
2052    |  REENTRANT      {  $$ = newLink (SPECIFIER);
2053                         FUNC_ISREENT($$)=1;
2054                      }
2055    |  CRITICAL       {  $$ = newLink (SPECIFIER);
2056                         FUNC_ISCRITICAL($$) = 1;
2057                      }
2058    |  NAKED          {  $$ = newLink (SPECIFIER);
2059                         FUNC_ISNAKED($$)=1;
2060                      }
2061    |  JAVANATIVE     {  $$ = newLink (SPECIFIER);
2062                         FUNC_ISJAVANATIVE($$)=1;
2063                      }
2064    |  OVERLAY        {  $$ = newLink (SPECIFIER);
2065                         FUNC_ISOVERLAY($$)=1;
2066                      }
2067    |  NONBANKED      {$$ = newLink (SPECIFIER);
2068                         FUNC_NONBANKED($$) = 1;
2069                         if (FUNC_BANKED($$)) {
2070                             werror(W_BANKED_WITH_NONBANKED);
2071                         }
2072                      }
2073    |  SHADOWREGS     {$$ = newLink (SPECIFIER);
2074                         FUNC_ISSHADOWREGS($$) = 1;
2075                      }
2076    |  SD_WPARAM      {$$ = newLink (SPECIFIER);
2077                         FUNC_ISWPARAM($$) = 1;
2078                      }
2079    |  BANKED         {$$ = newLink (SPECIFIER);
2080                         FUNC_BANKED($$) = 1;
2081                         if (FUNC_NONBANKED($$)) {
2082                             werror(W_BANKED_WITH_NONBANKED);
2083                         }
2084                      }
2085    |  Interrupt_storage
2086                      {
2087                         $$ = newLink (SPECIFIER);
2088                         FUNC_INTNO($$) = $1;
2089                         FUNC_ISISR($$) = 1;
2090                      }
2091    |  TRAP
2092                      {
2093                         $$ = newLink (SPECIFIER);
2094                         FUNC_INTNO($$) = INTNO_TRAP;
2095                         FUNC_ISISR($$) = 1;
2096                      }
2097    |  SMALLC         {  $$ = newLink (SPECIFIER);
2098                         FUNC_ISSMALLC($$) = 1;
2099                      }
2100    |  Z88DK_FASTCALL {  $$ = newLink (SPECIFIER);
2101                         FUNC_ISZ88DK_FASTCALL($$) = 1;
2102                      }
2103    |  Z88DK_CALLEE   {  $$ = newLink (SPECIFIER);
2104                         FUNC_ISZ88DK_CALLEE($$) = 1;
2105                      }
2106    |  Z88DK_PARAMS_OFFSET '(' constant_expr ')'
2107                      {
2108                         value *offset_v = constExprValue ($3, TRUE);
2109                         int    offset = 0;
2110                         $$ = newLink(SPECIFIER);
2111                         if  ( offset_v )
2112                           offset = ulFromVal(offset_v);
2113                         $$->funcAttrs.z88dk_params_offset = offset;
2114                      }
2115    |  Z88DK_SHORTCALL '(' constant_expr ',' constant_expr ')'
2116                      {
2117                         value *rst_v = constExprValue ($3, TRUE);
2118                         value *value_v = constExprValue ($5, TRUE);
2119                         int rst = -1, value = -1;
2120                         $$ = newLink(SPECIFIER);
2121 
2122                         if  ( rst_v )
2123                           rst = ulFromVal(rst_v);
2124                         if  ( value_v )
2125                           value = ulFromVal(value_v);
2126 
2127                         if ( rst < 0 || rst > 56 || ( rst % 8 ) )
2128                           {
2129                             werror(E_SHORTCALL_INVALID_VALUE, "rst", rst);
2130                           }
2131                         if ( value < 0 || value > 0xfff )
2132                           {
2133                             werror(E_SHORTCALL_INVALID_VALUE, "value", value);
2134                           }
2135                         $$->funcAttrs.z88dk_shortcall_rst = rst;
2136                         $$->funcAttrs.z88dk_shortcall_val = value;
2137                         FUNC_ISZ88DK_SHORTCALL($$) = 1;
2138                      }
2139    |  PRESERVES_REGS '(' identifier_list ')'
2140                      {
2141                         const struct symbol *regsym;
2142                         $$ = newLink (SPECIFIER);
2143 
2144                         for(regsym = $3; regsym; regsym = regsym->next)
2145                           {
2146                             int regnum;
2147 
2148                             if (!port->getRegByName || ((regnum = port->getRegByName(regsym->name)) < 0))
2149                               werror (W_UNKNOWN_REG, regsym->name);
2150                             else
2151                               $$->funcAttrs.preserved_regs[regnum] = TRUE;
2152                           }
2153                      }
2154    ;
2155 
2156 offsetof_member_designator
2157    : identifier      { $$ = newAst_VALUE (symbolVal ($1)); }
2158    | offsetof_member_designator '.' { ignoreTypedefType = 1; } identifier
2159                      {
2160                        ignoreTypedefType = 0;
2161                        $4 = newSymbol ($4->name, NestLevel);
2162                        $4->implicit = 1;
2163                        $$ = newNode ('.', $1, newAst_VALUE (symbolVal ($4)));
2164                      }
2165    | offsetof_member_designator '[' expr ']'
2166                      {
2167                        $$ = newNode ('[', $1, $3);
2168                      }
2169    ;
2170 
2171 string_literal_val
2172    : STRING_LITERAL {
2173                        int cnt = 1;
2174                        int max = 253, min = 1;
2175                        char fb[256];
2176                        /* refer to support/cpp/libcpp/macro.c for details */
2177                        while ((((int) ($1[cnt] & 0xff)) & 0xff) == 0xff)
2178                          cnt++;
2179 
2180                        if (cnt <= max)
2181                          {
2182                            $$ = newAst_VALUE (strVal ($1));
2183                          }
2184                        else
2185                          {
2186                            memset (fb, 0x00, sizeof (fb));
2187                            fb[0] = '"';
2188                            strncpy (fb + 1, function_name, max - min + 1);
2189                            fb[max + 1] = '"';
2190                            fb[max + 2] = 0;
2191                            fb[strlen (fb)] = '"';
2192                            fb[strlen (fb) + 1] = 0;
2193                            $$ = newAst_VALUE (strVal (fb));
2194                          }
2195                      }
2196     ;
2197 
2198 Interrupt_storage
2199    : INTERRUPT { $$ = INTNO_UNSPEC; }
2200    | INTERRUPT constant_expr
2201         {
2202           value *val = constExprValue($2,TRUE);
2203           int intno = (int) ulFromVal(val);
2204           if (val && (intno >= 0) && (intno <= INTNO_MAX))
2205             $$ = intno;
2206           else
2207             {
2208               werror(E_INT_BAD_INTNO, intno);
2209               $$ = INTNO_UNSPEC;
2210             }
2211         }
2212    ;
2213 
2214 sfr_reg_bit
2215    :  SBIT  {
2216                $$ = newLink(SPECIFIER);
2217                SPEC_NOUN($$) = V_SBIT;
2218                SPEC_SCLS($$) = S_SBIT;
2219                SPEC_BLEN($$) = 1;
2220                SPEC_BSTR($$) = 0;
2221                ignoreTypedefType = 1;
2222             }
2223    |  sfr_attributes
2224    ;
2225 
2226 sfr_attributes
2227    : SFR    {
2228                $$ = newLink(SPECIFIER);
2229                FUNC_REGBANK($$) = 0;
2230                SPEC_NOUN($$)    = V_CHAR;
2231                SPEC_SCLS($$)    = S_SFR;
2232                SPEC_USIGN($$)   = 1;
2233                ignoreTypedefType = 1;
2234             }
2235    | SFR BANKED {
2236                $$ = newLink(SPECIFIER);
2237                FUNC_REGBANK($$) = 1;
2238                SPEC_NOUN($$)    = V_CHAR;
2239                SPEC_SCLS($$)    = S_SFR;
2240                SPEC_USIGN($$)   = 1;
2241                ignoreTypedefType = 1;
2242             }
2243    ;
2244 
2245 sfr_attributes
2246    : SFR16  {
2247                $$ = newLink(SPECIFIER);
2248                FUNC_REGBANK($$) = 0;
2249                SPEC_NOUN($$)    = V_INT;
2250                SPEC_SCLS($$)    = S_SFR;
2251                SPEC_USIGN($$)   = 1;
2252                ignoreTypedefType = 1;
2253             }
2254    ;
2255 
2256 sfr_attributes
2257    : SFR32  {
2258                $$ = newLink(SPECIFIER);
2259                FUNC_REGBANK($$) = 0;
2260                SPEC_NOUN($$)    = V_INT;
2261                SPEC_SCLS($$)    = S_SFR;
2262                SPEC_LONG($$)    = 1;
2263                SPEC_USIGN($$)   = 1;
2264                ignoreTypedefType = 1;
2265             }
2266    ;
2267 
2268 opt_stag
2269    : stag
2270    |    {  /* synthesize a name add to structtable */
2271           ignoreTypedefType = 0;
2272           $$ = newStruct(genSymName(NestLevel));
2273           $$->level = NestLevel;
2274           $$->block = currBlockno;
2275           $$->tagsym = NULL;
2276           //addSym (StructTab, $$, $$->tag, $$->level, currBlockno, 0);
2277         }
2278    ;
2279 
2280 stag
2281    : identifier
2282         {  /* add name to structure table */
2283           ignoreTypedefType = 0;
2284           $$ = newStruct($1->name);
2285           $$->level = NestLevel;
2286           $$->block = currBlockno;
2287           $$->tagsym = $1;
2288           //$$ = findSymWithBlock (StructTab, $1, currBlockno);
2289           //if (! $$ )
2290           //  {
2291           //    $$ = newStruct($1->name);
2292           //    $$->level = NestLevel;
2293           //    $$->tagsym = $1;
2294           //    //addSym (StructTab, $$, $$->tag, $$->level, currBlockno, 0);
2295           //  }
2296         }
2297    ;
2298 
2299 opt_assign_expr
2300    : '=' constant_expr
2301         {
2302           value *val;
2303 
2304           val = constExprValue($2, TRUE);
2305           if (!IS_INT(val->type) && !IS_CHAR(val->type) && !IS_BOOL(val->type))
2306             {
2307               werror(E_ENUM_NON_INTEGER);
2308               SNPRINTF(lbuff, sizeof(lbuff), "%d", (int) ulFromVal(val));
2309               val = constVal(lbuff);
2310             }
2311           $$ = cenum = val;
2312         }
2313    |    {
2314           if (cenum)
2315             {
2316               SNPRINTF(lbuff, sizeof(lbuff), "%d", (int) ulFromVal(cenum)+1);
2317               $$ = cenum = constVal(lbuff);
2318             }
2319           else
2320             {
2321               $$ = cenum = constCharVal(0);
2322             }
2323         }
2324    ;
2325 
2326 type_specifier_list : type_specifier_list_ { $$ = finalizeSpec($1); };
2327 
2328 type_specifier_list_
2329    : type_specifier
2330    //| type_specifier_list_ type_specifier         {  $$ = mergeSpec ($1,$2, "type_specifier_list"); }
2331    | type_specifier_list_ type_specifier {
2332      /* if the decl $2 is not a specifier */
2333      /* find the spec and replace it      */
2334      $$ = mergeDeclSpec($1, $2, "type_specifier_list type_specifier skipped");
2335    }
2336    ;
2337 
2338 identifier_list
2339    : identifier
2340    | identifier_list ',' identifier
2341          {
2342            $3->next = $1;
2343            $$ = $3;
2344          }
2345    ;
2346 
2347 type_name
2348    : declaration_specifiers
2349         {
2350           if (IS_SPEC ($1) && !IS_VALID_PARAMETER_STORAGE_CLASS_SPEC ($1))
2351             {
2352               werror (E_STORAGE_CLASS_FOR_PARAMETER, "type name");
2353             }
2354           $$ = $1; ignoreTypedefType = 0;
2355         }
2356    | declaration_specifiers abstract_declarator
2357         {
2358           /* go to the end of the list */
2359           sym_link *p;
2360 
2361           if (IS_SPEC ($1) && !IS_VALID_PARAMETER_STORAGE_CLASS_SPEC ($1))
2362             {
2363               werror (E_STORAGE_CLASS_FOR_PARAMETER, "type name");
2364             }
2365           pointerTypes ($2,$1);
2366           for (p = $2; p && p->next; p = p->next)
2367             ;
2368           if (!p)
2369             {
2370               werror(E_SYNTAX_ERROR, yytext);
2371             }
2372           else
2373             {
2374               p->next = $1;
2375             }
2376           $$ = $2;
2377           ignoreTypedefType = 0;
2378         }
2379    ;
2380 
2381 critical
2382    : CRITICAL   {
2383                    if (inCriticalFunction || inCriticalBlock)
2384                      werror(E_INVALID_CRITICAL);
2385                    inCriticalBlock = 1;
2386                    STACK_PUSH(continueStack,NULL);
2387                    STACK_PUSH(breakStack,NULL);
2388                    $$ = NULL;
2389                 }
2390    ;
2391 
2392 critical_statement
2393    : critical statement  {
2394                    STACK_POP(breakStack);
2395                    STACK_POP(continueStack);
2396                    $$ = newNode(CRITICAL,$2,NULL);
2397                    inCriticalBlock = 0;
2398                 }
2399    ;
2400 
2401 statements_and_implicit
2402    : statement_list
2403    | statement_list implicit_block
2404      {
2405        $$ = newNode(NULLOP, $1, $2);
2406        if (!options.std_c99)
2407          werror(E_DECL_AFTER_STATEMENT_C99);
2408      }
2409    ;
2410 
2411 declaration_after_statement
2412    : {
2413        NestLevel += SUBLEVEL_UNIT;
2414        STACK_PUSH(blockNum, currBlockno);
2415        btree_add_child(currBlockno, ++blockNo);
2416        currBlockno = blockNo;
2417        ignoreTypedefType = 0;
2418      }
2419      declaration_list                         { $$ = $2; }
2420    ;
2421 
2422 implicit_block
2423    : declaration_after_statement statements_and_implicit
2424      {
2425        NestLevel -= SUBLEVEL_UNIT;
2426        currBlockno = STACK_POP(blockNum);
2427        $$ = createBlock($1, $2);
2428        cleanUpLevel(StructTab, NestLevel + SUBLEVEL_UNIT);
2429      }
2430    | declaration_after_statement
2431      {
2432        NestLevel -= SUBLEVEL_UNIT;
2433        currBlockno = STACK_POP(blockNum);
2434        $$ = createBlock($1, NULL);
2435        cleanUpLevel(StructTab, NestLevel + SUBLEVEL_UNIT);
2436      }
2437    ;
2438 
2439 declaration_list
2440    : declaration
2441      {
2442        /* if this is typedef declare it immediately */
2443        if ( $1 && IS_TYPEDEF($1->etype)) {
2444          allocVariables ($1);
2445          $$ = NULL;
2446        }
2447        else
2448          $$ = $1;
2449        ignoreTypedefType = 0;
2450        addSymChain(&$1);
2451      }
2452 
2453    | declaration_list declaration
2454      {
2455        symbol   *sym;
2456 
2457        /* if this is a typedef */
2458        if ($2 && IS_TYPEDEF($2->etype)) {
2459          allocVariables ($2);
2460          $$ = $1;
2461        }
2462        else {
2463          /* get to the end of the previous decl */
2464          if ( $1 ) {
2465            $$ = sym = $1;
2466            while (sym->next)
2467              sym = sym->next;
2468            sym->next = $2;
2469          }
2470          else
2471            $$ = $2;
2472        }
2473        ignoreTypedefType = 0;
2474        addSymChain(&$2);
2475      }
2476    ;
2477 
2478 statement_list
2479    : statement
2480    | statement_list statement          {  $$ = newNode(NULLOP,$1,$2);}
2481    ;
2482 
2483 else_statement
2484    :  ELSE  statement   { $$ = $2; }
2485    |                    { $$ = NULL; }
2486    ;
2487 
2488 
2489 
2490 while : WHILE  {  /* create and push the continue , break & body labels */
2491                   static int Lblnum = 0;
2492                   /* continue */
2493                   SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum);
2494                   STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
2495                   /* break */
2496                   SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum);
2497                   STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
2498                   /* body */
2499                   SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++);
2500                   $$ = newSymbol(lbuff,NestLevel);
2501                }
2502    ;
2503 
2504 do : DO {  /* create and push the continue , break & body Labels */
2505            static int Lblnum = 0;
2506 
2507            /* continue */
2508            SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum);
2509            STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
2510            /* break */
2511            SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum);
2512            STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
2513            /* do body */
2514            SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++);
2515            $$ = newSymbol (lbuff,NestLevel);
2516         }
2517    ;
2518 
2519 for : FOR { /* create & push continue, break & body labels */
2520             static int Lblnum = 0;
2521 
2522            NestLevel += LEVEL_UNIT;
2523            STACK_PUSH(blockNum, currBlockno);
2524            btree_add_child(currBlockno, ++blockNo);
2525            currBlockno = blockNo;
2526            ignoreTypedefType = 0;
2527 
2528             /* continue */
2529             SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum);
2530             STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
2531             /* break    */
2532             SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum);
2533             STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
2534             /* body */
2535             SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum);
2536             $$ = newSymbol(lbuff,NestLevel);
2537             /* condition */
2538             SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++);
2539             STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
2540           }
2541    ;
2542 
2543 asm_string_literal
2544    : STRING_LITERAL
2545    ;
2546 
2547 asm_statement
2548    : ASM '(' asm_string_literal ')' ';'
2549       {
2550         ast *ex;
2551 
2552         seqPointNo++;
2553         ex = newNode(INLINEASM, NULL, NULL);
2554         ex->values.inlineasm = strdup(copyStr ($3, NULL));
2555         seqPointNo++;
2556         $$ = ex;
2557      }
2558    | INLINEASM ';'
2559       {
2560         ast *ex;
2561 
2562         seqPointNo++;
2563         ex = newNode(INLINEASM, NULL, NULL);
2564         ex->values.inlineasm = strdup($1);
2565         seqPointNo++;
2566         $$ = ex;
2567       }
2568    ;
2569 
2570 addressmod
2571    : ADDRESSMOD identifier identifier ';' {
2572      symbol *sym;
2573      if ((sym = findSymWithLevel (AddrspaceTab, $3)) && sym->level == $3->level)
2574        werrorfl (sym->fileDef, sym->lineDef, E_PREVIOUS_DEF);
2575      if (!findSymWithLevel (SymbolTab, $2))
2576        werror (E_ID_UNDEF, $2->name);
2577      addSym (AddrspaceTab, $3, $3->name, $3->level, $3->block, 0);
2578      sym = findSymWithLevel (AddrspaceTab, $3);
2579      sym->addressmod[0] = findSymWithLevel (SymbolTab, $2);
2580      sym->addressmod[1] = 0;
2581    }
2582    | ADDRESSMOD identifier SD_CONST identifier ';' {
2583      symbol *sym;
2584      sym_link *type;
2585      if ((sym = findSymWithLevel (AddrspaceTab, $4)) && sym->level == $4->level)
2586        werrorfl (sym->fileDef, sym->lineDef, E_PREVIOUS_DEF);
2587      if (!findSymWithLevel (SymbolTab, $2))
2588        werror (E_ID_UNDEF, $2->name);
2589      addSym (AddrspaceTab, $4, $4->name, $4->level, $4->block, 0);
2590      sym = findSymWithLevel (AddrspaceTab, $4);
2591      sym->addressmod[0] = findSymWithLevel (SymbolTab, $2);
2592      sym->addressmod[1] = 0;
2593      type = newLink (SPECIFIER);
2594      SPEC_CONST(type) = 1;
2595      sym->type = sym->etype = type;
2596    }
2597    ;
2598 
2599 identifier
2600    : IDENTIFIER   { $$ = newSymbol ($1, NestLevel); }
2601    ;
2602 %%
2603