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