Buffer overflow hunt: removing strcpy, strcat, sprintf
[fw/sdcc] / src / SDCC.y
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
38 extern int yyerror (char *);
39 extern FILE     *yyin;
40 int NestLevel = 0 ;     /* current NestLevel       */
41 int stackPtr  = 1 ;     /* stack pointer           */
42 int xstackPtr = 0 ;     /* xstack pointer          */
43 int reentrant = 0 ; 
44 int blockNo   = 0 ;     /* sequential block number  */
45 int currBlockno=0 ;
46 extern int yylex();
47 int yyparse(void);
48 extern int noLineno ;
49 char lbuff[1024];      /* local buffer */
50
51 /* break & continue stacks */
52 STACK_DCL(continueStack  ,symbol *,MAX_NEST_LEVEL)
53 STACK_DCL(breakStack  ,symbol *,MAX_NEST_LEVEL)
54 STACK_DCL(forStack  ,symbol *,MAX_NEST_LEVEL)
55 STACK_DCL(swStk   ,ast   *,MAX_NEST_LEVEL)
56 STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3)
57
58 value *cenum = NULL  ;  /* current enumeration  type chain*/
59
60 %}
61 %expect 6
62
63 %union {
64     symbol     *sym ;      /* symbol table pointer       */
65     structdef  *sdef;      /* structure definition       */
66     char       yychar[SDCC_NAME_MAX+1];
67     sym_link       *lnk ;      /* declarator  or specifier   */
68     int        yyint;      /* integer value returned     */
69     value      *val ;      /* for integer constant       */
70     initList   *ilist;     /* initial list               */
71     char       *yyinline; /* inlined assembler code */
72     ast       *asts;     /* expression tree            */
73 }
74
75 %token <yychar> IDENTIFIER TYPE_NAME
76 %token <val>   CONSTANT   STRING_LITERAL
77 %token SIZEOF TYPEOF 
78 %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
79 %token AND_OP OR_OP 
80 %token <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
81 %token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
82 %token <yyint> XOR_ASSIGN OR_ASSIGN
83 %token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT
84 %token REENTRANT USING  XDATA DATA IDATA PDATA VAR_ARGS CRITICAL NONBANKED BANKED
85 %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT
86 %token STRUCT UNION ENUM ELIPSIS RANGE FAR
87 %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
88 %token NAKED JAVANATIVE OVERLAY
89 %token <yyinline> INLINEASM
90 %token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT
91 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
92 %token RRC RLC 
93 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
94
95 %type <yyint>  Interrupt_storage
96 %type <sym> identifier  declarator  declarator2 enumerator_list enumerator
97 %type <sym> struct_declarator
98 %type <sym> struct_declarator_list  struct_declaration   struct_declaration_list
99 %type <sym> declaration init_declarator_list init_declarator
100 %type <sym> declaration_list identifier_list parameter_identifier_list
101 %type <sym> declarator2_function_attributes while do for
102 %type <lnk> pointer type_specifier_list type_specifier type_name
103 %type <lnk> storage_class_specifier struct_or_union_specifier
104 %type <lnk> declaration_specifiers  sfr_reg_bit type_specifier2
105 %type <lnk> function_attribute function_attributes enum_specifier
106 %type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
107 %type <val> parameter_type_list parameter_list parameter_declaration opt_assign_expr
108 %type <sdef> stag opt_stag
109 %type <asts> primary_expr
110 %type <asts> postfix_expr unary_expr cast_expr multiplicative_expr
111 %type <asts> additive_expr shift_expr relational_expr equality_expr
112 %type <asts> and_expr exclusive_or_expr inclusive_or_expr logical_or_expr
113 %type <asts> logical_and_expr conditional_expr assignment_expr constant_expr
114 %type <asts> expr argument_expr_list function_definition expr_opt
115 %type <asts> statement_list statement labeled_statement compound_statement
116 %type <asts> expression_statement selection_statement iteration_statement
117 %type <asts> jump_statement function_body else_statement string_literal
118 %type <ilist> initializer initializer_list
119 %type <yyint> unary_operator  assignment_operator struct_or_union
120
121 %start file
122
123 %%
124
125 file
126    : external_definition       
127    | file external_definition
128    ;
129
130 external_definition
131    : function_definition     { 
132                                blockNo=0;
133                              }
134    | declaration             { 
135                                if ($1 && $1->type
136                                 && IS_FUNC($1->type))
137                                {
138                                    /* The only legal storage classes for 
139                                     * a function prototype (declaration)
140                                     * are extern and static. extern is the
141                                     * default. Thus, if this function isn't
142                                     * explicitly marked static, mark it
143                                     * extern.
144                                     */
145                                    if ($1->etype 
146                                     && IS_SPEC($1->etype)
147                                     && !SPEC_STAT($1->etype))
148                                    {
149                                         SPEC_EXTR($1->etype) = 1;
150                                    }
151                                }
152                                addSymChain ($1);
153                                allocVariables ($1) ;
154                                cleanUpLevel (SymbolTab,1);
155                              }
156    ;
157
158 function_definition
159    : declarator function_body  {   /* function type not specified */
160                                    /* assume it to be 'int'       */
161                                    addDecl($1,0,newIntLink());
162                                    $$ = createFunction($1,$2); 
163                                } 
164    | declaration_specifiers declarator function_body  
165                                 {   
166                                     pointerTypes($2->type,copyLinkChain($1));
167                                     addDecl($2,0,$1); 
168                                     $$ = createFunction($2,$3);   
169                                 }
170    ;
171
172 function_attribute
173    : function_attributes
174    | function_attributes function_attribute { $$ = mergeSpec($1,$2,"function_attribute"); }
175    ;
176
177 function_attributes
178    :  USING CONSTANT {
179                         $$ = newLink() ;
180                         $$->class = SPECIFIER   ;
181                         FUNC_REGBANK($$) = (int) floatFromVal($2);
182                      }
183    |  REENTRANT      {  $$ = newLink ();
184                         $$->class = SPECIFIER   ;
185                         FUNC_ISREENT($$)=1;
186                      }
187    |  CRITICAL       {  $$ = newLink ();
188                         $$->class = SPECIFIER   ;
189                         FUNC_ISCRITICAL($$) = 1;
190                      }
191    |  NAKED          {  $$ = newLink ();
192                         $$->class = SPECIFIER   ;
193                         FUNC_ISNAKED($$)=1;
194                      }
195    |  JAVANATIVE     {  $$ = newLink ();
196                         $$->class = SPECIFIER   ;
197                         FUNC_ISJAVANATIVE($$)=1;
198                      }
199    |  OVERLAY        {  $$ = newLink ();
200                         $$->class = SPECIFIER   ;
201                         FUNC_ISOVERLAY($$)=1;
202                      }
203    |  NONBANKED      {$$ = newLink ();
204                         $$->class = SPECIFIER   ;
205                         FUNC_NONBANKED($$) = 1;
206                         if (FUNC_BANKED($$)) {
207                             werror(W_BANKED_WITH_NONBANKED);
208                         }
209                      }
210    |  BANKED         {$$ = newLink ();
211                         $$->class = SPECIFIER   ;
212                         FUNC_BANKED($$) = 1;
213                         if (FUNC_NONBANKED($$)) {
214                             werror(W_BANKED_WITH_NONBANKED);
215                         }
216                         if (SPEC_STAT($$)) {
217                             werror(W_BANKED_WITH_STATIC);
218                         }
219                      }
220    |  Interrupt_storage
221                      {
222                         $$ = newLink () ;
223                         $$->class = SPECIFIER ;
224                         FUNC_INTNO($$) = $1 ;
225                         FUNC_ISISR($$) = 1;
226                      }
227    ;
228
229 function_body
230    : compound_statement                   
231    | declaration_list compound_statement
232          {
233             werror(E_OLD_STYLE,($1 ? $1->name: "")) ;
234             exit(1);
235          }
236    ;
237
238 primary_expr
239    : identifier      {  $$ = newAst_VALUE(symbolVal($1));  }
240    | CONSTANT        {  $$ = newAst_VALUE($1);  }
241    | string_literal  
242    | '(' expr ')'    {  $$ = $2 ;                   }
243    ;
244          
245 string_literal
246     : STRING_LITERAL                    { $$ = newAst_VALUE($1); }
247     ;
248
249 postfix_expr
250    : primary_expr
251    | postfix_expr '[' expr ']'          { $$ = newNode  ('[', $1, $3) ; }
252    | postfix_expr '(' ')'               { $$ = newNode  (CALL,$1,NULL); 
253                                           $$->left->funcName = 1;}
254    | postfix_expr '(' argument_expr_list ')'
255           {        
256             $$ = newNode  (CALL,$1,$3) ; $$->left->funcName = 1;
257           }
258    | postfix_expr '.' identifier       
259                       {    
260                         $3 = newSymbol($3->name,NestLevel);
261                         $3->implicit = 1;
262                         $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($3)));
263 /*                      $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($3))) ;                   */
264                       }
265    | postfix_expr PTR_OP identifier    
266                       { 
267                         $3 = newSymbol($3->name,NestLevel);
268                         $3->implicit = 1;                       
269                         $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($3)));
270                       }
271    | postfix_expr INC_OP   
272                       { $$ = newNode(INC_OP,$1,NULL);}
273    | postfix_expr DEC_OP
274                       { $$ = newNode(DEC_OP,$1,NULL); }
275    ;
276
277 argument_expr_list
278    : assignment_expr 
279    | assignment_expr ',' argument_expr_list { $$ = newNode(PARAM,$1,$3); }
280    ;
281
282 unary_expr
283    : postfix_expr
284    | INC_OP unary_expr        { $$ = newNode(INC_OP,NULL,$2);  }
285    | DEC_OP unary_expr        { $$ = newNode(DEC_OP,NULL,$2);  }
286    | unary_operator cast_expr { $$ = newNode($1,$2,NULL)    ;  }
287    | SIZEOF unary_expr        { $$ = newNode(SIZEOF,NULL,$2);  }
288    | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); }
289    | TYPEOF unary_expr        { $$ = newNode(TYPEOF,NULL,$2);  }
290    ;
291               
292 unary_operator
293    : '&'    { $$ = '&' ;}
294    | '*'    { $$ = '*' ;}
295    | '+'    { $$ = '+' ;}
296    | '-'    { $$ = '-' ;}
297    | '~'    { $$ = '~' ;}
298    | '!'    { $$ = '!' ;}
299    ;
300
301 cast_expr
302    : unary_expr
303    | '(' type_name ')' cast_expr { $$ = newNode(CAST,newAst_LINK($2),$4); }
304    ;
305
306 multiplicative_expr
307    : cast_expr
308    | multiplicative_expr '*' cast_expr { $$ = newNode('*',$1,$3);}
309    | multiplicative_expr '/' cast_expr { $$ = newNode('/',$1,$3);}
310    | multiplicative_expr '%' cast_expr { $$ = newNode('%',$1,$3);}
311    ;
312
313 additive_expr
314    : multiplicative_expr
315    | additive_expr '+' multiplicative_expr { $$=newNode('+',$1,$3);}
316    | additive_expr '-' multiplicative_expr { $$=newNode('-',$1,$3);}
317    ;
318
319 shift_expr
320    : additive_expr
321    | shift_expr LEFT_OP additive_expr  { $$ = newNode(LEFT_OP,$1,$3); }
322    | shift_expr RIGHT_OP additive_expr { $$ = newNode(RIGHT_OP,$1,$3); }
323    ;
324
325 relational_expr
326    : shift_expr
327    | relational_expr '<' shift_expr    { 
328         $$ = (port->lt_nge ? 
329               newNode('!',newNode(GE_OP,$1,$3),NULL) :
330               newNode('<', $1,$3));
331    }
332    | relational_expr '>' shift_expr    { 
333            $$ = (port->gt_nle ? 
334                  newNode('!',newNode(LE_OP,$1,$3),NULL) :
335                  newNode('>',$1,$3));
336    }
337    | relational_expr LE_OP shift_expr  { 
338            $$ = (port->le_ngt ? 
339                  newNode('!', newNode('>', $1 , $3 ), NULL) :
340                  newNode(LE_OP,$1,$3));
341    }
342    | relational_expr GE_OP shift_expr  { 
343            $$ = (port->ge_nlt ? 
344                  newNode('!', newNode('<', $1 , $3 ), NULL) :
345                  newNode(GE_OP,$1,$3));
346    }
347    ;
348
349 equality_expr
350    : relational_expr
351    | equality_expr EQ_OP relational_expr  { 
352     $$ = (port->eq_nne ? 
353           newNode('!',newNode(NE_OP,$1,$3),NULL) : 
354           newNode(EQ_OP,$1,$3));
355    }
356    | equality_expr NE_OP relational_expr { 
357        $$ = (port->ne_neq ? 
358              newNode('!', newNode(EQ_OP,$1,$3), NULL) : 
359              newNode(NE_OP,$1,$3));
360    }       
361    ;
362
363 and_expr
364    : equality_expr
365    | and_expr '&' equality_expr  { $$ = newNode('&',$1,$3);}
366    ;
367
368 exclusive_or_expr
369    : and_expr
370    | exclusive_or_expr '^' and_expr { $$ = newNode('^',$1,$3);}
371    ;
372
373 inclusive_or_expr
374    : exclusive_or_expr
375    | inclusive_or_expr '|' exclusive_or_expr { $$ = newNode('|',$1,$3);}
376    ;
377
378 logical_and_expr
379    : inclusive_or_expr
380    | logical_and_expr AND_OP inclusive_or_expr 
381                                  { $$ = newNode(AND_OP,$1,$3);}
382    ;
383
384 logical_or_expr
385    : logical_and_expr
386    | logical_or_expr OR_OP logical_and_expr  
387                                  { $$ = newNode(OR_OP,$1,$3); }
388    ;
389
390 conditional_expr
391    : logical_or_expr
392    | logical_or_expr '?' logical_or_expr ':' conditional_expr  
393                      {
394                         $$ = newNode(':',$3,$5) ;
395                         $$ = newNode('?',$1,$$) ;
396                      }                        
397    ;
398
399 assignment_expr
400    : conditional_expr
401    | unary_expr assignment_operator assignment_expr   
402                      { 
403                                  
404                              switch ($2) {
405                              case '=':
406                                      $$ = newNode($2,$1,$3);
407                                      break;
408                              case MUL_ASSIGN:
409                                      $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3));
410                                      break;
411                              case DIV_ASSIGN:
412                                      $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3));
413                                      break;
414                              case MOD_ASSIGN:
415                                      $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3));
416                                      break;
417                              case ADD_ASSIGN:
418                                      $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3));
419                                      break;
420                              case SUB_ASSIGN:
421                                      $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3));
422                                      break;
423                              case LEFT_ASSIGN:
424                                      $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3));
425                                      break;
426                              case RIGHT_ASSIGN:
427                                      $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3));
428                                      break;
429                              case AND_ASSIGN:
430                                      $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3));
431                                      break;
432                              case XOR_ASSIGN:
433                                      $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3));
434                                      break;
435                              case OR_ASSIGN:
436                                      $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3));
437                                      break;
438                              default :
439                                      $$ = NULL;
440                              }
441                                      
442                      }
443 ;
444
445 assignment_operator
446    : '='             { $$ = '=' ;}
447    | MUL_ASSIGN
448    | DIV_ASSIGN
449    | MOD_ASSIGN
450    | ADD_ASSIGN
451    | SUB_ASSIGN
452    | LEFT_ASSIGN
453    | RIGHT_ASSIGN
454    | AND_ASSIGN
455    | XOR_ASSIGN
456    | OR_ASSIGN
457    ;
458
459 expr
460    : assignment_expr
461    | expr ',' assignment_expr { $$ = newNode(',',$1,$3);}
462    ;
463
464 constant_expr
465    : conditional_expr 
466    ;
467
468 declaration
469    : declaration_specifiers ';'  { $$ = NULL ; }
470    | declaration_specifiers init_declarator_list ';'
471       {
472          /* add the specifier list to the id */
473          symbol *sym , *sym1;
474
475          for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) {
476              sym_link *lnk = copyLinkChain($1);
477              /* do the pointer stuff */
478              pointerTypes(sym->type,lnk);
479              addDecl (sym,0,lnk) ;
480          }
481         
482          $$ = sym1 ;
483       }
484    ;
485
486 declaration_specifiers
487    : storage_class_specifier                                            { $$ = $1; }
488    | storage_class_specifier declaration_specifiers { 
489      /* if the decl $2 is not a specifier */
490      /* find the spec and replace it      */
491      if ( !IS_SPEC($2)) {
492        sym_link *lnk = $2 ;
493        while (lnk && !IS_SPEC(lnk->next))
494          lnk = lnk->next;
495        lnk->next = mergeSpec($1,lnk->next, yytext);
496        $$ = $2 ;
497      }
498      else
499        $$ = mergeSpec($1,$2, yytext);
500    }
501    | type_specifier                                 { $$ = $1; }
502    | type_specifier declaration_specifiers          { 
503      /* if the decl $2 is not a specifier */
504      /* find the spec and replace it      */
505      if ( !IS_SPEC($2)) {
506        sym_link *lnk = $2 ;
507        while (lnk && !IS_SPEC(lnk->next))
508          lnk = lnk->next;
509        lnk->next = mergeSpec($1,lnk->next, yytext);
510        $$ = $2 ;
511      }
512      else
513        $$ = mergeSpec($1,$2, yytext);
514    }
515    ;
516
517 init_declarator_list
518    : init_declarator
519    | init_declarator_list ',' init_declarator      { $3->next = $1 ; $$ = $3;}
520    ;
521
522 init_declarator
523    : declarator                  { $1->ival = NULL ; }
524    | declarator '=' initializer  { $1->ival = $3   ; }
525    ;
526
527
528 storage_class_specifier
529    : TYPEDEF   {
530                   $$ = newLink () ;
531                   $$->class = SPECIFIER ;
532                   SPEC_TYPEDEF($$) = 1 ;
533                }
534    | EXTERN    {
535                   $$ = newLink();
536                   $$->class = SPECIFIER ;
537                   SPEC_EXTR($$) = 1 ;
538                }
539    | STATIC    {
540                   $$ = newLink ();
541                   $$->class = SPECIFIER ;
542                   SPEC_STAT($$) = 1 ;
543                }
544    | AUTO      {
545                   $$ = newLink () ;
546                   $$->class = SPECIFIER ;
547                   SPEC_SCLS($$) = S_AUTO  ;
548                }
549    | REGISTER  {
550                   $$ = newLink ();
551                   $$->class = SPECIFIER ;
552                   SPEC_SCLS($$) = S_REGISTER ;
553                }
554    ;
555
556 Interrupt_storage
557    : INTERRUPT CONSTANT  { $$ = (int) floatFromVal($2) ;  }
558    ;
559
560 type_specifier
561    : type_specifier2
562    | type_specifier2 AT constant_expr
563         {
564            /* add this to the storage class specifier  */
565            SPEC_ABSA($1) = 1;   /* set the absolute addr flag */
566            /* now get the abs addr from value */
567            SPEC_ADDR($1) = (int) floatFromVal(constExprValue($3,TRUE)) ;
568         }
569    ;
570
571 type_specifier2
572    : CHAR   {
573                $$=newLink();
574                $$->class = SPECIFIER   ;
575                SPEC_NOUN($$) = V_CHAR  ;
576             }
577    | SHORT  {
578                $$=newLink();
579                $$->class = SPECIFIER   ;
580                $$->select.s._short = 1 ;
581             }
582    | INT    {
583                $$=newLink();
584                $$->class = SPECIFIER   ;
585                SPEC_NOUN($$) = V_INT   ;
586             }
587    | LONG   {
588                $$=newLink();
589                $$->class = SPECIFIER   ;
590                SPEC_LONG($$) = 1       ;
591             }
592    | SIGNED {
593                $$=newLink();
594                $$->class = SPECIFIER   ;
595                $$->select.s._signed = 1;
596             }
597    | UNSIGNED  {
598                $$=newLink();
599                $$->class = SPECIFIER   ;
600                SPEC_USIGN($$) = 1      ;
601             }
602    | VOID   {
603                $$=newLink();
604                $$->class = SPECIFIER   ;
605                SPEC_NOUN($$) = V_VOID  ;
606             }
607    | CONST  {
608                $$=newLink();
609                $$->class = SPECIFIER ;
610                SPEC_CONST($$) = 1;
611             }
612    | VOLATILE  {
613                $$=newLink();
614                $$->class = SPECIFIER ;
615                SPEC_VOLATILE($$) = 1 ;
616             }
617    | FLOAT  {
618                $$=newLink();
619                SPEC_NOUN($$) = V_FLOAT;
620                $$->class = SPECIFIER ;
621             }
622    | XDATA     {
623                   $$ = newLink ();
624                   $$->class = SPECIFIER ;
625                   SPEC_SCLS($$) = S_XDATA  ;
626                }
627    | CODE      {
628                   $$ = newLink () ;
629                   $$->class = SPECIFIER  ;
630                   SPEC_SCLS($$) = S_CODE ;                 
631                }
632    | EEPROM      {
633                   $$ = newLink () ;
634                   $$->class = SPECIFIER  ;
635                   SPEC_SCLS($$) = S_EEPROM ;
636                }
637    | DATA      {
638                   $$ = newLink ();
639                   $$->class = SPECIFIER ;
640                   SPEC_SCLS($$) = S_DATA   ;
641                }
642    | IDATA     {
643                   $$ = newLink ();
644                   $$->class = SPECIFIER ;
645                   SPEC_SCLS($$) = S_IDATA  ;
646                }
647    | PDATA     { 
648                   $$ = newLink ();
649                   $$->class = SPECIFIER ;
650                   SPEC_SCLS($$) = S_PDATA  ;
651                }
652    | BIT    {
653                $$=newLink();
654                $$->class = SPECIFIER   ;
655                SPEC_NOUN($$) = V_BIT   ;
656                SPEC_SCLS($$) = S_BIT   ;
657                SPEC_BLEN($$) = 1;
658                SPEC_BSTR($$) = 0;
659             }
660
661    | struct_or_union_specifier
662    | enum_specifier     {                           
663                            cenum = NULL ;
664                            $$ = $1 ;                              
665                         }
666    | TYPE_NAME    
667          {
668             symbol *sym;
669             sym_link   *p  ;
670             sym = findSym(TypedefTab,NULL,$1) ;
671             $$ = p = copyLinkChain(sym->type);
672             SPEC_TYPEDEF(getSpec(p)) = 0;
673          }
674    | sfr_reg_bit
675    ;
676
677 sfr_reg_bit
678    :  SBIT  {
679                $$ = newLink() ;
680                $$->class = SPECIFIER ;
681                SPEC_NOUN($$) = V_SBIT;
682                SPEC_SCLS($$) = S_SBIT;
683             }
684    |  SFR   {
685                $$ = newLink() ;
686                $$->class = SPECIFIER ;
687                SPEC_NOUN($$) = V_CHAR;
688                SPEC_SCLS($$) = S_SFR ;
689                SPEC_USIGN($$) = 1 ;
690             }
691    ;
692
693 struct_or_union_specifier
694    : struct_or_union opt_stag '{' struct_declaration_list '}'
695         {
696            structdef *sdef ;
697
698            /* Create a structdef   */
699            sdef = $2 ;
700            sdef->fields   = reverseSyms($4) ;   /* link the fields */
701            sdef->size  = compStructSize($1,sdef);   /* update size of  */
702
703            /* Create the specifier */
704            $$ = newLink () ;
705            $$->class = SPECIFIER   ;
706            SPEC_NOUN($$) = V_STRUCT;
707            SPEC_STRUCT($$)= sdef ;
708         }
709    | struct_or_union stag
710          {
711             $$ = newLink() ;
712             $$->class = SPECIFIER   ;
713             SPEC_NOUN($$) = V_STRUCT;
714             SPEC_STRUCT($$) = $2 ;
715          }
716    ;
717
718 struct_or_union
719    : STRUCT          { $$ = STRUCT ; }
720    | UNION           { $$ = UNION  ; }
721    ;
722
723 opt_stag
724 : stag
725 |  {  /* synthesize a name add to structtable */
726      $$ = newStruct(genSymName(NestLevel)) ;
727      $$->level = NestLevel ;
728      addSym (StructTab, $$, $$->tag,$$->level,currBlockno, 0);
729 };
730
731 stag
732 :  identifier  {  /* add name to structure table */
733      $$ = findSymWithBlock (StructTab,$1,currBlockno);
734      if (! $$ ) {
735        $$ = newStruct($1->name) ;
736        $$->level = NestLevel ;
737        addSym (StructTab, $$, $$->tag,$$->level,currBlockno,0);
738      }
739 };
740
741
742 struct_declaration_list
743    : struct_declaration
744    | struct_declaration_list struct_declaration
745        {
746            symbol *sym = $2;
747            /* go to the end of the chain */
748            while (sym->next) sym = sym->next;
749
750            sym->next = $1 ;
751            $$ = $2;
752        }
753    ;
754
755 struct_declaration
756    : type_specifier_list struct_declarator_list ';'
757        {
758            /* add this type to all the symbols */
759            symbol *sym ;
760            for ( sym = $2 ; sym != NULL ; sym = sym->next ) {
761                
762                /* make the symbol one level up */
763                sym->level-- ;
764
765                pointerTypes(sym->type,copyLinkChain($1));
766                if (!sym->type) {
767                    sym->type = copyLinkChain($1);
768                    sym->etype = getSpec(sym->type);
769                }
770                else
771                    addDecl (sym,0,cloneSpec($1));              
772                /* make sure the type is complete and sane */
773                checkTypeSanity(sym->etype, sym->name);
774            }
775            $$ = $2;
776        }
777    ;
778
779 struct_declarator_list
780    : struct_declarator
781    | struct_declarator_list ',' struct_declarator
782        {
783            $3->next  = $1 ;
784            $$ = $3 ;
785        }
786    ;
787
788 struct_declarator
789    : declarator 
790    | ':' constant_expr  {  
791                            $$ = newSymbol (genSymName(NestLevel),NestLevel) ; 
792                            $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE));
793                         }                        
794    | declarator ':' constant_expr 
795                         { 
796                           $1->bitVar = (int) floatFromVal(constExprValue($3,TRUE));                     
797                         }
798    ;
799
800 enum_specifier
801    : ENUM            '{' enumerator_list '}' {
802                                                 //addSymChain ($3);
803                                                 //allocVariables(reverseSyms($3)) ;
804                                                 $$ = copyLinkChain(cenum->type);
805                                              }
806    | ENUM identifier '{' enumerator_list '}' {
807                                                 symbol *csym ;
808
809                                                 $2->type = copyLinkChain(cenum->type);
810                                                 $2->etype = getSpec($2->type);
811                                                 /* add this to the enumerator table */
812                                                 if (!(csym=findSym(enumTab,$2,$2->name)) && 
813                                                     (csym && csym->level == $2->level))
814                                                    werror(E_DUPLICATE_TYPEDEF,csym->name);
815
816                                                 addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
817                                                 //addSymChain ($4);
818                                                 //allocVariables (reverseSyms($4));
819                                                 $$ = copyLinkChain(cenum->type);
820                                                 SPEC_SCLS(getSpec($$)) = 0 ;
821                                              }
822    | ENUM identifier                         {
823                                                 symbol *csym ;
824
825                                                 /* check the enumerator table */
826                                                 if ((csym = findSym(enumTab,$2,$2->name)))
827                                                    $$ = copyLinkChain(csym->type);
828                                                 else  {
829                                                    $$ = newLink() ;
830                                                    $$->class = SPECIFIER   ;
831                                                    SPEC_NOUN($$) = V_INT   ;
832                                                 }
833
834                                                 SPEC_SCLS(getSpec($$)) = 0 ;
835                                              }
836    ;
837
838 enumerator_list
839    : enumerator
840    | enumerator_list ',' {
841                          }
842    | enumerator_list ',' enumerator {
843                                        $3->next = $1 ;
844                                        $$ = $3  ;
845                                     }
846    ;
847
848 enumerator
849    : identifier opt_assign_expr  
850      {
851        /* make the symbol one level up */
852        $1->level-- ;
853        $1->type = copyLinkChain($2->type); 
854        $1->etype= getSpec($1->type);
855        SPEC_ENUM($1->etype) = 1;
856        $$ = $1 ;
857        // do this now, so we can use it for the next enums in the list
858        addSymChain($1);
859      }
860    ;
861
862 opt_assign_expr
863    :  '='   constant_expr  {
864                               value *val ;
865                                                         
866                               val = constExprValue($2,TRUE);                         
867                               $$ = cenum = val ;
868                            }                           
869    |                       {                              
870                               if (cenum)  {
871                                  sprintf(lbuff,"%d",(int) floatFromVal(cenum)+1);
872                                  $$ = cenum = constVal(lbuff);
873                               }
874                               else {
875                                  sprintf(lbuff,"%d",0);
876                                  $$ = cenum = constVal(lbuff);
877                               }   
878                            }
879    ;
880
881 declarator
882    : declarator2_function_attributes    { $$ = $1; }
883    | pointer declarator2_function_attributes
884          {
885              addDecl ($2,0,reverseLink($1));
886              $$ = $2 ;
887          }
888    ;
889
890 declarator2_function_attributes
891    : declarator2                  { $$ = $1 ; } 
892    | declarator2 function_attribute  { 
893        // copy the functionAttributes (not the args and hasVargs !!)
894        sym_link *funcType=$1->etype;
895        struct value *args=FUNC_ARGS(funcType);
896        unsigned hasVargs=FUNC_HASVARARGS(funcType);
897
898        memcpy (&funcType->funcAttrs, &$2->funcAttrs, 
899                sizeof($2->funcAttrs));
900
901        FUNC_ARGS(funcType)=args;
902        FUNC_HASVARARGS(funcType)=hasVargs;
903
904        // just to be sure
905        memset (&$2->funcAttrs, 0,
906                sizeof($2->funcAttrs));
907        
908        addDecl ($1,0,$2); 
909    }     
910    ;
911
912 declarator2
913    : identifier
914    | '(' declarator ')'     { $$ = $2; }
915    | declarator2 '[' ']'
916          {
917             sym_link   *p;
918
919             p = newLink ();
920             DCL_TYPE(p) = ARRAY ;
921             DCL_ELEM(p) = 0     ;
922             addDecl($1,0,p);
923          }
924    | declarator2 '[' constant_expr ']'
925          {
926             sym_link   *p ;
927                         value *tval;
928                         
929             p = (tval = constExprValue($3,TRUE))->etype;
930             /* if it is not a constant then Error  */
931             if ( SPEC_SCLS(p) != S_LITERAL)
932                werror(E_CONST_EXPECTED) ;
933             else {
934                p = newLink ();
935                DCL_TYPE(p) = ARRAY ;
936                DCL_ELEM(p) = (int) floatFromVal(tval) ;
937                addDecl($1,0,p);
938             }                           
939          }
940    | declarator2 '('  ')'       {  addDecl ($1,FUNCTION,NULL) ;   }
941    | declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')'
942          {
943            
944              addDecl ($1,FUNCTION,NULL) ;
945            
946              FUNC_HASVARARGS($1->type) = IS_VARG($4);
947              FUNC_ARGS($1->type) = reverseVal($4);
948              
949              /* nest level was incremented to take care of the parms  */
950              NestLevel-- ;
951              currBlockno--;
952
953              // if this was a pointer (to a function)
954              if (IS_PTR($1->type)) {
955                // move the args and hasVargs to the function
956                FUNC_ARGS($1->etype)=FUNC_ARGS($1->type);
957                FUNC_HASVARARGS($1->etype)=FUNC_HASVARARGS($1->type);
958                memset (&$1->type->funcAttrs, 0,
959                        sizeof($1->type->funcAttrs));
960                // remove the symbol args (if any)
961                cleanUpLevel(SymbolTab,NestLevel+1);
962              }
963              
964              $$ = $1;
965          }
966    | declarator2 '(' parameter_identifier_list ')'
967          {         
968            werror(E_OLD_STYLE,$1->name) ;         
969            
970            /* assume it returns an int */
971            $1->type = $1->etype = newIntLink();
972            $$ = $1 ;
973          }
974    ;
975
976 pointer
977    : unqualified_pointer { $$ = $1 ;}
978    | unqualified_pointer type_specifier_list   
979          {
980              $$ = $1  ;         
981              DCL_TSPEC($1) = $2;
982          }
983    | unqualified_pointer pointer         
984          {
985              $$ = $1 ;          
986              $$->next = $2 ;
987              DCL_TYPE($2)=port->unqualified_pointer;
988          }
989    | unqualified_pointer type_specifier_list pointer
990          {
991              $$ = $1 ;               
992              if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
993                  DCL_PTR_CONST($1) = SPEC_CONST($2);
994                  DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
995                  switch (SPEC_SCLS($2)) {
996                  case S_XDATA:
997                      DCL_TYPE($3) = FPOINTER;
998                      break;
999                  case S_IDATA:
1000                      DCL_TYPE($3) = IPOINTER ;
1001                      break;
1002                  case S_PDATA:
1003                      DCL_TYPE($3) = PPOINTER ;
1004                      break;
1005                  case S_DATA:
1006                      DCL_TYPE($3) = POINTER ;
1007                      break;
1008                  case S_CODE:
1009                      DCL_PTR_CONST($3) = 1;
1010                      DCL_TYPE($3) = CPOINTER ;
1011                      break;
1012                  case S_EEPROM:
1013                      DCL_TYPE($3) = EEPPOINTER;
1014                      break;
1015                  default:
1016                    // this could be just "constant" 
1017                    // werror(W_PTR_TYPE_INVALID);
1018                      ;
1019                  }
1020              }
1021              else 
1022                  werror (W_PTR_TYPE_INVALID);
1023              $$->next = $3 ;
1024          }
1025    ;
1026
1027 unqualified_pointer
1028    :  '*'   
1029       {
1030         $$ = newLink();
1031         DCL_TYPE($$)=UPOINTER;
1032       }
1033    ;
1034
1035 type_specifier_list
1036    : type_specifier
1037    //| type_specifier_list type_specifier         {  $$ = mergeSpec ($1,$2, "type_specifier_list"); }
1038    | type_specifier_list type_specifier {
1039      /* if the decl $2 is not a specifier */
1040      /* find the spec and replace it      */
1041      if ( !IS_SPEC($2)) {
1042        sym_link *lnk = $2 ;
1043        while (lnk && !IS_SPEC(lnk->next))
1044          lnk = lnk->next;
1045        lnk->next = mergeSpec($1,lnk->next, "type_specifier_list");
1046        $$ = $2 ;
1047      }
1048      else
1049        $$ = mergeSpec($1,$2, "type_specifier_list");
1050    }
1051    ;
1052
1053 parameter_identifier_list
1054    : identifier_list
1055    | identifier_list ',' ELIPSIS
1056    ;
1057
1058 identifier_list
1059    : identifier
1060    | identifier_list ',' identifier         
1061          {            
1062            $3->next = $1;
1063            $$ = $3 ;
1064          }
1065    ;
1066
1067 parameter_type_list
1068         : parameter_list
1069         | parameter_list ',' VAR_ARGS { $1->vArgs = 1;}
1070         ;
1071
1072 parameter_list
1073    : parameter_declaration 
1074    | parameter_list ',' parameter_declaration
1075          {
1076             $3->next = $1 ;
1077             $$ = $3 ;       
1078          }
1079    ;
1080
1081 parameter_declaration
1082    : type_specifier_list declarator 
1083                {        
1084                   symbol *loop ;
1085                   pointerTypes($2->type,$1);
1086                   addDecl ($2,0,$1);              
1087                   for (loop=$2;loop;loop->_isparm=1,loop=loop->next);
1088                   addSymChain ($2);
1089                   $$ = symbolVal($2);
1090                }
1091    | type_name { 
1092                   $$ = newValue() ; 
1093                   $$->type = $1;
1094                   $$->etype = getSpec($$->type);
1095                }
1096    ;
1097
1098 type_name
1099    : type_specifier_list  { $$ = $1 ;}
1100    | type_specifier_list abstract_declarator 
1101                {
1102                  /* go to the end of the list */
1103                  sym_link *p;
1104                  pointerTypes($2,$1);
1105                  for ( p = $2 ; p && p->next ; p=p->next);
1106                  if (!p) {
1107                    werror(E_SYNTAX_ERROR, yytext);
1108                  } else {
1109                    p->next = $1 ;
1110                  }
1111                  $$ = $2 ;
1112                }   
1113    ;
1114
1115 abstract_declarator
1116    : pointer { $$ = reverseLink($1); }
1117    | abstract_declarator2
1118    | pointer abstract_declarator2   { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;} 
1119    ;
1120
1121 abstract_declarator2
1122    : '(' abstract_declarator ')'    { $$ = $2 ; }
1123    | '[' ']'                        {             
1124                                        $$ = newLink ();
1125                                        DCL_TYPE($$) = ARRAY ;
1126                                        DCL_ELEM($$) = 0     ;
1127                                     }
1128    | '[' constant_expr ']'          { 
1129                                        value *val ;
1130                                        $$ = newLink ();
1131                                        DCL_TYPE($$) = ARRAY ;
1132                                        DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE));
1133                                     }
1134    | abstract_declarator2 '[' ']'   {
1135                                        $$ = newLink ();
1136                                        DCL_TYPE($$) = ARRAY ;
1137                                        DCL_ELEM($$) = 0     ;
1138                                        $$->next = $1 ;
1139                                     }
1140    | abstract_declarator2 '[' constant_expr ']'
1141                                     {
1142                                        value *val ;
1143                                        $$ = newLink ();
1144                                        DCL_TYPE($$) = ARRAY ;
1145                                        DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE));
1146                                        $$->next = $1 ;
1147                                     }
1148    | '(' ')'                        { $$ = NULL;}
1149    | '(' parameter_type_list ')'    { $$ = NULL;}   
1150    | abstract_declarator2 '(' ')' {
1151      // $1 must be a pointer to a function
1152      sym_link *p=newLink();
1153      DCL_TYPE(p) = FUNCTION;
1154      if (!$1) {
1155        // ((void (code *) ()) 0) ()
1156        $1=newLink();
1157        DCL_TYPE($1)=CPOINTER;
1158        $$ = $1;
1159      }
1160      $1->next=p;
1161    }
1162    | abstract_declarator2 '(' parameter_type_list ')' {
1163      if (!IS_VOID($3->type)) {
1164        // this is nonsense, so let's just burp something
1165        werror(E_TOO_FEW_PARMS);
1166      } else {
1167        // $1 must be a pointer to a function
1168        sym_link *p=newLink();
1169        DCL_TYPE(p) = FUNCTION;
1170        if (!$1) {
1171          // ((void (code *) (void)) 0) ()
1172          $1=newLink();
1173          DCL_TYPE($1)=CPOINTER;
1174          $$ = $1;
1175        }
1176        $1->next=p;
1177      }
1178    }
1179    ;
1180
1181 initializer
1182    : assignment_expr                { $$ = newiList(INIT_NODE,$1); }
1183    | '{'  initializer_list '}'      { $$ = newiList(INIT_DEEP,revinit($2)); }
1184    | '{'  initializer_list ',' '}'  { $$ = newiList(INIT_DEEP,revinit($2)); }
1185    ;
1186
1187 initializer_list
1188    : initializer
1189    | initializer_list ',' initializer  {  $3->next = $1; $$ = $3; }
1190    ;
1191
1192 statement
1193    : labeled_statement
1194    | compound_statement
1195    | expression_statement
1196    | selection_statement
1197    | iteration_statement
1198    | jump_statement
1199    | INLINEASM  ';'      {
1200                             ast *ex = newNode(INLINEASM,NULL,NULL);
1201                             ex->values.inlineasm = strdup($1);
1202                             $$ = ex;
1203                          } 
1204    ;
1205
1206 labeled_statement
1207 //   : identifier ':' statement          {  $$ = createLabel($1,$3);  }   
1208    : identifier ':'                    {  $$ = createLabel($1,NULL);  }   
1209    | CASE constant_expr ':' statement  {  $$ = createCase(STACK_PEEK(swStk),$2,$4); }
1210    | DEFAULT ':' statement             {  $$ = createDefault(STACK_PEEK(swStk),$3); }
1211    ;
1212
1213 start_block : '{' { STACK_PUSH(blockNum,currBlockno); currBlockno = ++blockNo ;  }
1214             ;
1215
1216 end_block   : '}'     { currBlockno = STACK_POP(blockNum); }           
1217             ;
1218
1219 compound_statement
1220    : start_block end_block                    { $$ = createBlock(NULL,NULL); }
1221    | start_block statement_list end_block     { $$ = createBlock(NULL,$2) ;  }
1222    | start_block 
1223           declaration_list                    { addSymChain($2); }
1224      end_block                                { $$ = createBlock($2,NULL) ;  }
1225    | start_block 
1226           declaration_list                    {  addSymChain ($2); }
1227           statement_list   
1228      end_block                                {$$ = createBlock($2,$4)   ;  }
1229    | error ';'                                { $$ = NULL ; }
1230    ;
1231
1232 declaration_list
1233    : declaration        
1234      {
1235        /* if this is typedef declare it immediately */
1236        if ( $1 && IS_TYPEDEF($1->etype)) {
1237          allocVariables ($1);
1238          $$ = NULL ;
1239        }
1240        else
1241          $$ = $1 ;
1242      }
1243
1244    | declaration_list declaration
1245      {
1246        symbol   *sym;
1247        
1248        /* if this is a typedef */
1249        if ($2 && IS_TYPEDEF($2->etype)) {
1250          allocVariables ($2);
1251          $$ = $1 ;
1252        }
1253        else {
1254                                 /* get to the end of the previous decl */
1255          if ( $1 ) {
1256            $$ = sym = $1 ;
1257            while (sym->next)
1258              sym = sym->next ;
1259            sym->next = $2;
1260          } 
1261          else
1262            $$ = $2 ;
1263        }
1264      }
1265    ;
1266
1267 statement_list
1268    : statement
1269    | statement_list statement          {  $$ = newNode(NULLOP,$1,$2) ;}
1270    ;
1271
1272 expression_statement
1273    : ';'                { $$ = NULL;}
1274    | expr ';' 
1275    ;
1276
1277 else_statement
1278    :  ELSE  statement   { $$ = $2  ; }
1279    |                    { $$ = NULL;}
1280    ;
1281
1282   
1283 selection_statement
1284    : IF '(' expr ')'  statement else_statement { noLineno++ ; $$ = createIf ($3, $5, $6 ); noLineno--;}
1285    | SWITCH '(' expr ')'   { 
1286                               ast *ex ;                              
1287                               static   int swLabel = 0 ;
1288
1289                               /* create a node for expression  */
1290                               ex = newNode(SWITCH,$3,NULL);
1291                               STACK_PUSH(swStk,ex);   /* save it in the stack */
1292                               ex->values.switchVals.swNum = swLabel ;
1293                                  
1294                               /* now create the label */
1295                               sprintf(lbuff,"_swBrk_%d",swLabel++);
1296                               $<sym>$  =  newSymbol(lbuff,NestLevel);
1297                               /* put label in the break stack  */
1298                               STACK_PUSH(breakStack,$<sym>$);   
1299                            }
1300      statement             {  
1301                               /* get back the switch form the stack  */
1302                               $$ = STACK_POP(swStk)  ;
1303                               $$->right = newNode (NULLOP,$6,createLabel($<sym>5,NULL));
1304                               STACK_POP(breakStack);   
1305                            }
1306         ;
1307
1308 while : WHILE  {  /* create and push the continue , break & body labels */
1309                   static int Lblnum = 0 ;
1310                   /* continue */
1311                   sprintf (lbuff,"_whilecontinue_%d",Lblnum);
1312                   STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1313                   /* break */
1314                   sprintf (lbuff,"_whilebreak_%d",Lblnum);
1315                   STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1316                   /* body */
1317                   sprintf (lbuff,"_whilebody_%d",Lblnum++);
1318                   $$ = newSymbol(lbuff,NestLevel);
1319                }
1320    ;
1321
1322 do : DO {  /* create and push the continue , break & body Labels */
1323            static int Lblnum = 0 ;
1324
1325            /* continue */
1326            sprintf(lbuff,"_docontinue_%d",Lblnum);
1327            STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1328            /* break */
1329            sprintf (lbuff,"_dobreak_%d",Lblnum);
1330            STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1331            /* do body */
1332            sprintf (lbuff,"_dobody_%d",Lblnum++);
1333            $$ = newSymbol (lbuff,NestLevel);       
1334         }
1335    ;
1336
1337 for : FOR { /* create & push continue, break & body labels */
1338             static int Lblnum = 0 ;
1339          
1340             /* continue */
1341             sprintf (lbuff,"_forcontinue_%d",Lblnum);
1342             STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
1343             /* break    */
1344             sprintf (lbuff,"_forbreak_%d",Lblnum);
1345             STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
1346             /* body */
1347             sprintf (lbuff,"_forbody_%d",Lblnum);
1348             $$ = newSymbol(lbuff,NestLevel);
1349             /* condition */
1350             sprintf (lbuff,"_forcond_%d",Lblnum++);
1351             STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
1352           }
1353    ;
1354
1355 iteration_statement  
1356    : while '(' expr ')'  statement 
1357                          { 
1358                            noLineno++ ;
1359                            $$ = createWhile ( $1, STACK_POP(continueStack),
1360                                               STACK_POP(breakStack), $3, $5 ); 
1361                            $$->lineno = $1->lineDef ;
1362                            noLineno-- ;
1363                          }
1364    | do statement   WHILE '(' expr ')' ';' 
1365                         { 
1366                           noLineno++ ; 
1367                           $$ = createDo ( $1 , STACK_POP(continueStack), 
1368                                           STACK_POP(breakStack), $5, $2);
1369                           $$->lineno = $1->lineDef ;
1370                           noLineno-- ;
1371                         }                                                 
1372    | for '(' expr_opt   ';' expr_opt ';' expr_opt ')'  statement   
1373                         {
1374                           noLineno++ ;  
1375                           
1376                           /* if break or continue statement present
1377                              then create a general case loop */
1378                           if (STACK_PEEK(continueStack)->isref ||
1379                               STACK_PEEK(breakStack)->isref) {
1380                               $$ = createFor ($1, STACK_POP(continueStack),
1381                                               STACK_POP(breakStack) ,
1382                                               STACK_POP(forStack)   ,
1383                                               $3 , $5 , $7, $9 );
1384                           } else {
1385                               $$ = newNode(FOR,$9,NULL);
1386                               AST_FOR($$,trueLabel) = $1;
1387                               AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
1388                               AST_FOR($$,falseLabel) = STACK_POP(breakStack);
1389                               AST_FOR($$,condLabel)  = STACK_POP(forStack)  ;
1390                               AST_FOR($$,initExpr)   = $3;
1391                               AST_FOR($$,condExpr)   = $5;
1392                               AST_FOR($$,loopExpr)   = $7;
1393                           }
1394                           
1395                           noLineno-- ;
1396                         }
1397 ;
1398
1399 expr_opt
1400         :                       { $$ = NULL ; }
1401         |       expr
1402         ;
1403
1404 jump_statement          
1405    : GOTO identifier ';'   { 
1406                               $2->islbl = 1;
1407                               $$ = newAst_VALUE(symbolVal($2)); 
1408                               $$ = newNode(GOTO,$$,NULL);
1409                            }
1410    | CONTINUE ';'          {  
1411        /* make sure continue is in context */
1412        if (STACK_PEEK(continueStack) == NULL) {
1413            werror(E_BREAK_CONTEXT);
1414            $$ = NULL;
1415        }
1416        else {
1417            $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack)));      
1418            $$ = newNode(GOTO,$$,NULL);
1419            /* mark the continue label as referenced */
1420            STACK_PEEK(continueStack)->isref = 1;
1421        }
1422    }
1423    | BREAK ';'             { 
1424        if (STACK_PEEK(breakStack) == NULL) {
1425            werror(E_BREAK_CONTEXT);
1426            $$ = NULL;
1427        } else {
1428            $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack)));
1429            $$ = newNode(GOTO,$$,NULL);
1430            STACK_PEEK(breakStack)->isref = 1;
1431        }
1432    }
1433    | RETURN ';'            { $$ = newNode(RETURN,NULL,NULL)    ; }
1434    | RETURN expr ';'       { $$ = newNode(RETURN,NULL,$2) ; } 
1435    ;
1436
1437 identifier
1438    : IDENTIFIER   { $$ = newSymbol ($1,NestLevel) ; }
1439    ;
1440 %%
1441