* device/lib/Makefile.in: remove abspath for PORTDIR, introduced in
[fw/sdcc] / src / SDCC.y
index c558c6c7390b131bdc5824dc1588c2f5e9ae4598..fa165cef8a7241af3357d437e5b64218ae986435 100644 (file)
@@ -7,23 +7,23 @@
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-   
+
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
    In other words, you are welcome to use, share and improve this program.
    You are forbidden to forbid anyone else to use, share and improve
-   what you give them.   Help stamp out software-hoarding!  
+   what you give them.   Help stamp out software-hoarding!
 -------------------------------------------------------------------------*/
 %{
 #include <stdio.h>
 -------------------------------------------------------------------------*/
 %{
 #include <stdio.h>
-#include <stdarg.h> 
+#include <stdarg.h>
 #include <string.h>
 #include "SDCCglobl.h"
 #include "SDCCsymt.h"
 #include <string.h>
 #include "SDCCglobl.h"
 #include "SDCCsymt.h"
 #include "SDCCutil.h"
 
 extern int yyerror (char *);
 #include "SDCCutil.h"
 
 extern int yyerror (char *);
-extern FILE    *yyin;
+extern FILE     *yyin;
 int NestLevel = 0 ;     /* current NestLevel       */
 int stackPtr  = 1 ;     /* stack pointer           */
 int xstackPtr = 0 ;     /* xstack pointer          */
 int NestLevel = 0 ;     /* current NestLevel       */
 int stackPtr  = 1 ;     /* stack pointer           */
 int xstackPtr = 0 ;     /* xstack pointer          */
-int reentrant = 0 ; 
+int reentrant = 0 ;
 int blockNo   = 0 ;     /* sequential block number  */
 int currBlockno=0 ;
 int blockNo   = 0 ;     /* sequential block number  */
 int currBlockno=0 ;
+int inCritical= 0 ;
+int seqPointNo= 1 ;     /* sequence point number */
+int ignoreTypedefType=0;
 extern int yylex();
 int yyparse(void);
 extern int noLineno ;
 extern int yylex();
 int yyparse(void);
 extern int noLineno ;
@@ -57,6 +60,9 @@ STACK_DCL(swStk   ,ast   *,MAX_NEST_LEVEL)
 STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3)
 
 value *cenum = NULL  ;  /* current enumeration  type chain*/
 STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3)
 
 value *cenum = NULL  ;  /* current enumeration  type chain*/
+bool uselessDecl = TRUE;
+
+#define YYDEBUG 1
 
 %}
 %expect 6
 
 %}
 %expect 6
@@ -65,44 +71,46 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
     symbol     *sym ;      /* symbol table pointer       */
     structdef  *sdef;      /* structure definition       */
     char       yychar[SDCC_NAME_MAX+1];
     symbol     *sym ;      /* symbol table pointer       */
     structdef  *sdef;      /* structure definition       */
     char       yychar[SDCC_NAME_MAX+1];
-    sym_link       *lnk ;      /* declarator  or specifier   */
+    sym_link   *lnk ;      /* declarator  or specifier   */
     int        yyint;      /* integer value returned     */
     value      *val ;      /* for integer constant       */
     initList   *ilist;     /* initial list               */
     int        yyint;      /* integer value returned     */
     value      *val ;      /* for integer constant       */
     initList   *ilist;     /* initial list               */
-    char       *yyinline; /* inlined assembler code */
-    ast       *asts;     /* expression tree            */
+    const char *yyinline;  /* inlined assembler code     */
+    ast        *asts;      /* expression tree            */
 }
 
 %token <yychar> IDENTIFIER TYPE_NAME
 }
 
 %token <yychar> IDENTIFIER TYPE_NAME
-%token <val>   CONSTANT   STRING_LITERAL
-%token SIZEOF TYPEOF 
+%token <val> CONSTANT STRING_LITERAL
+%token SIZEOF TYPEOF
 %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
 %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP
-%token AND_OP OR_OP 
+%token AND_OP OR_OP
 %token <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
 %token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
 %token <yyint> XOR_ASSIGN OR_ASSIGN
 %token <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
 %token <yyint> SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN
 %token <yyint> XOR_ASSIGN OR_ASSIGN
-%token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR AT SBIT
-%token REENTRANT USING  XDATA DATA IDATA PDATA VAR_ARGS CRITICAL NONBANKED BANKED
-%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID BIT
-%token STRUCT UNION ENUM ELIPSIS RANGE FAR
+%token TYPEDEF EXTERN STATIC AUTO REGISTER CODE EEPROM INTERRUPT SFR SFR16 SFR32
+%token AT SBIT REENTRANT USING  XDATA DATA IDATA PDATA VAR_ARGS CRITICAL
+%token NONBANKED BANKED SHADOWREGS WPARAM
+%token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE FIXED16X16 CONST VOLATILE VOID BIT
+%token STRUCT UNION ENUM RANGE FAR
 %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
 %token NAKED JAVANATIVE OVERLAY
 %token <yyinline> INLINEASM
 %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
 %token NAKED JAVANATIVE OVERLAY
 %token <yyinline> INLINEASM
-%token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT
+%token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT GETABIT GETBYTE GETWORD
 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
 %token BITWISEAND UNARYMINUS IPUSH IPOP PCALL  ENDFUNCTION JUMPTABLE
-%token RRC RLC 
+%token RRC RLC
 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
 %token CAST CALL PARAM NULLOP BLOCK LABEL RECEIVE SEND ARRAYINIT
+%token DUMMY_READ_VOLATILE ENDCRITICAL SWAP INLINE RESTRICT
 
 
-%type <yyint>  Interrupt_storage
-%type <sym> identifier  declarator  declarator2 enumerator_list enumerator
-%type <sym> struct_declarator
-%type <sym> struct_declarator_list  struct_declaration   struct_declaration_list
+%type <yyint> Interrupt_storage
+%type <sym> identifier declarator declarator2 declarator3 enumerator_list enumerator
+%type <sym> struct_declarator function_declarator function_declarator2
+%type <sym> struct_declarator_list struct_declaration struct_declaration_list
 %type <sym> declaration init_declarator_list init_declarator
 %type <sym> declaration init_declarator_list init_declarator
-%type <sym> declaration_list identifier_list parameter_identifier_list
-%type <sym> declarator2_function_attributes while do for
+%type <sym> declaration_list identifier_list
+%type <sym> declarator2_function_attributes while do for critical
 %type <lnk> pointer type_specifier_list type_specifier type_name
 %type <lnk> pointer type_specifier_list type_specifier type_name
-%type <lnk> storage_class_specifier struct_or_union_specifier
-%type <lnk> declaration_specifiers  sfr_reg_bit type_specifier2
+%type <lnk> storage_class_specifier struct_or_union_specifier function_specifier
+%type <lnk> declaration_specifiers sfr_reg_bit sfr_attributes type_specifier2
 %type <lnk> function_attribute function_attributes enum_specifier
 %type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
 %type <val> parameter_type_list parameter_list parameter_declaration opt_assign_expr
 %type <lnk> function_attribute function_attributes enum_specifier
 %type <lnk> abstract_declarator abstract_declarator2 unqualified_pointer
 %type <val> parameter_type_list parameter_list parameter_declaration opt_assign_expr
@@ -116,58 +124,70 @@ value *cenum = NULL  ;  /* current enumeration  type chain*/
 %type <asts> statement_list statement labeled_statement compound_statement
 %type <asts> expression_statement selection_statement iteration_statement
 %type <asts> jump_statement function_body else_statement string_literal
 %type <asts> statement_list statement labeled_statement compound_statement
 %type <asts> expression_statement selection_statement iteration_statement
 %type <asts> jump_statement function_body else_statement string_literal
+%type <asts> critical_statement
 %type <ilist> initializer initializer_list
 %type <ilist> initializer initializer_list
-%type <yyint> unary_operator  assignment_operator struct_or_union
+%type <yyint> unary_operator assignment_operator struct_or_union
 
 %start file
 
 %%
 
 file
 
 %start file
 
 %%
 
 file
-   : external_definition       
-   | file external_definition
+   : /* empty */
+        { if (!options.lessPedantic)
+                    werror(W_EMPTY_SOURCE_FILE);
+        }
+   | program
+   ;
+
+program
+   : external_definition
+   | program external_definition
    ;
 
 external_definition
    ;
 
 external_definition
-   : function_definition     { 
+   : function_definition     {
                                blockNo=0;
                              }
                                blockNo=0;
                              }
-   | declaration             { 
-                              if ($1 && $1->type
-                               && IS_FUNC($1->type))
-                              {
-                                  /* The only legal storage classes for 
-                                   * a function prototype (declaration)
-                                   * are extern and static. extern is the
-                                   * default. Thus, if this function isn't
-                                   * explicitly marked static, mark it
-                                   * extern.
-                                   */
-                                  if ($1->etype 
-                                   && IS_SPEC($1->etype)
-                                   && !SPEC_STAT($1->etype))
-                                  {
-                                       SPEC_EXTR($1->etype) = 1;
-                                  }
-                              }
-                               addSymChain ($1);
+   | declaration             {
+                               ignoreTypedefType = 0;
+                               if ($1 && $1->type
+                                && IS_FUNC($1->type))
+                               {
+                                   /* The only legal storage classes for
+                                    * a function prototype (declaration)
+                                    * are extern and static. extern is the
+                                    * default. Thus, if this function isn't
+                                    * explicitly marked static, mark it
+                                    * extern.
+                                    */
+                                   if ($1->etype
+                                    && IS_SPEC($1->etype)
+                                    && !SPEC_STAT($1->etype))
+                                   {
+                                        SPEC_EXTR($1->etype) = 1;
+                                   }
+                               }
+                               addSymChain (&$1);
                                allocVariables ($1) ;
                                allocVariables ($1) ;
-                              cleanUpLevel (SymbolTab,1);
+                               cleanUpLevel (SymbolTab,1);
                              }
    ;
 
 function_definition
                              }
    ;
 
 function_definition
-   : declarator function_body  {   /* function type not specified */
+   : function_declarator function_body  {   /* function type not specified */
                                    /* assume it to be 'int'       */
                                    addDecl($1,0,newIntLink());
                                    /* assume it to be 'int'       */
                                    addDecl($1,0,newIntLink());
-                                  $$ = createFunction($1,$2); 
-                               } 
-   | declaration_specifiers declarator function_body  
-                                {   
-                                   pointerTypes($2->type,copyLinkChain($1));
-                                   addDecl($2,0,$1); 
-                                   $$ = createFunction($2,$3);   
-                               }
+                                   $$ = createFunction($1,$2);
+                               }
+   | declaration_specifiers function_declarator function_body
+                                {
+                                    pointerTypes($2->type,copyLinkChain($1));
+                                    if (options.unsigned_char && SPEC_NOUN($1) == V_CHAR && !($1)->select.s.b_signed)
+                                      SPEC_USIGN($1) = 1;
+                                    addDecl($2,0,$1);
+                                    $$ = createFunction($2,$3);
+                                }
    ;
 
 function_attribute
    ;
 
 function_attribute
@@ -176,39 +196,45 @@ function_attribute
    ;
 
 function_attributes
    ;
 
 function_attributes
-   :  USING CONSTANT {
+   :  USING constant_expr {
                         $$ = newLink(SPECIFIER) ;
                         $$ = newLink(SPECIFIER) ;
-                       FUNC_REGBANK($$) = (int) floatFromVal($2);
+                        FUNC_REGBANK($$) = (int) ulFromVal(constExprValue($2,TRUE));
                      }
    |  REENTRANT      {  $$ = newLink (SPECIFIER);
                      }
    |  REENTRANT      {  $$ = newLink (SPECIFIER);
-                       FUNC_ISREENT($$)=1;
+                        FUNC_ISREENT($$)=1;
                      }
    |  CRITICAL       {  $$ = newLink (SPECIFIER);
                      }
    |  CRITICAL       {  $$ = newLink (SPECIFIER);
-                       FUNC_ISCRITICAL($$) = 1;
+                        FUNC_ISCRITICAL($$) = 1;
                      }
    |  NAKED          {  $$ = newLink (SPECIFIER);
                      }
    |  NAKED          {  $$ = newLink (SPECIFIER);
-                       FUNC_ISNAKED($$)=1;
+                        FUNC_ISNAKED($$)=1;
                      }
    |  JAVANATIVE     {  $$ = newLink (SPECIFIER);
                      }
    |  JAVANATIVE     {  $$ = newLink (SPECIFIER);
-                       FUNC_ISJAVANATIVE($$)=1;
+                        FUNC_ISJAVANATIVE($$)=1;
                      }
    |  OVERLAY        {  $$ = newLink (SPECIFIER);
                      }
    |  OVERLAY        {  $$ = newLink (SPECIFIER);
-                       FUNC_ISOVERLAY($$)=1;
+                        FUNC_ISOVERLAY($$)=1;
                      }
    |  NONBANKED      {$$ = newLink (SPECIFIER);
                         FUNC_NONBANKED($$) = 1;
                      }
    |  NONBANKED      {$$ = newLink (SPECIFIER);
                         FUNC_NONBANKED($$) = 1;
-                       if (FUNC_BANKED($$)) {
-                           werror(W_BANKED_WITH_NONBANKED);
-                       }
+                        if (FUNC_BANKED($$)) {
+                            werror(W_BANKED_WITH_NONBANKED);
+                        }
+                     }
+   |  SHADOWREGS     {$$ = newLink (SPECIFIER);
+                        FUNC_ISSHADOWREGS($$) = 1;
+                     }
+   |  WPARAM         {$$ = newLink (SPECIFIER);
+                        FUNC_ISWPARAM($$) = 1;
                      }
    |  BANKED         {$$ = newLink (SPECIFIER);
                         FUNC_BANKED($$) = 1;
                      }
    |  BANKED         {$$ = newLink (SPECIFIER);
                         FUNC_BANKED($$) = 1;
-                       if (FUNC_NONBANKED($$)) {
-                           werror(W_BANKED_WITH_NONBANKED);
-                       }
-                       if (SPEC_STAT($$)) {
-                           werror(W_BANKED_WITH_STATIC);
-                       }
+                        if (FUNC_NONBANKED($$)) {
+                            werror(W_BANKED_WITH_NONBANKED);
+                        }
+                        if (SPEC_STAT($$)) {
+                            werror(W_BANKED_WITH_STATIC);
+                        }
                      }
    |  Interrupt_storage
                      {
                      }
    |  Interrupt_storage
                      {
@@ -219,55 +245,57 @@ function_attributes
    ;
 
 function_body
    ;
 
 function_body
-   : compound_statement                   
+   : compound_statement
    | declaration_list compound_statement
          {
             werror(E_OLD_STYLE,($1 ? $1->name: "")) ;
    | declaration_list compound_statement
          {
             werror(E_OLD_STYLE,($1 ? $1->name: "")) ;
-           exit(1);
+            exit(1);
          }
    ;
 
 primary_expr
    : identifier      {  $$ = newAst_VALUE(symbolVal($1));  }
    | CONSTANT        {  $$ = newAst_VALUE($1);  }
          }
    ;
 
 primary_expr
    : identifier      {  $$ = newAst_VALUE(symbolVal($1));  }
    | CONSTANT        {  $$ = newAst_VALUE($1);  }
-   | string_literal  
+   | string_literal
    | '(' expr ')'    {  $$ = $2 ;                   }
    ;
    | '(' expr ')'    {  $$ = $2 ;                   }
    ;
-         
+
 string_literal
 string_literal
-    : STRING_LITERAL                   { $$ = newAst_VALUE($1); }
+    : STRING_LITERAL                    { $$ = newAst_VALUE($1); }
     ;
 
 postfix_expr
    : primary_expr
     ;
 
 postfix_expr
    : primary_expr
-   | postfix_expr '[' expr ']'          { $$ = newNode ('[', $1, $3) ; }
-   | postfix_expr '(' ')'               { $$ = newNode  (CALL,$1,NULL); 
+   | postfix_expr '[' expr ']'          { $$ = newNode  ('[', $1, $3) ; }
+   | postfix_expr '(' ')'               { $$ = newNode  (CALL,$1,NULL);
                                           $$->left->funcName = 1;}
    | postfix_expr '(' argument_expr_list ')'
                                           $$->left->funcName = 1;}
    | postfix_expr '(' argument_expr_list ')'
-          {       
-           $$ = newNode  (CALL,$1,$3) ; $$->left->funcName = 1;
-         }
-   | postfix_expr '.' identifier       
-                     {    
-                       $3 = newSymbol($3->name,NestLevel);
-                       $3->implicit = 1;
-                       $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($3)));
-/*                     $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($3))) ;                   */
-                     }
-   | postfix_expr PTR_OP identifier    
-                      { 
-                       $3 = newSymbol($3->name,NestLevel);
-                       $3->implicit = 1;                       
-                       $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($3)));
-                     }
-   | postfix_expr INC_OP   
-                      {        $$ = newNode(INC_OP,$1,NULL);}
+          {
+            $$ = newNode  (CALL,$1,$3) ; $$->left->funcName = 1;
+          }
+   | postfix_expr '.' { ignoreTypedefType = 1; } identifier
+                      {
+                        ignoreTypedefType = 0;
+                        $4 = newSymbol($4->name,NestLevel);
+                        $4->implicit = 1;
+                        $$ = newNode(PTR_OP,newNode('&',$1,NULL),newAst_VALUE(symbolVal($4)));
+/*                      $$ = newNode('.',$1,newAst(EX_VALUE,symbolVal($4))) ;                   */
+                      }
+   | postfix_expr PTR_OP { ignoreTypedefType = 1; } identifier
+                      {
+                        ignoreTypedefType = 0;
+                        $4 = newSymbol($4->name,NestLevel);
+                        $4->implicit = 1;
+                        $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($4)));
+                      }
+   | postfix_expr INC_OP
+                      { $$ = newNode(INC_OP,$1,NULL);}
    | postfix_expr DEC_OP
    | postfix_expr DEC_OP
-                      {        $$ = newNode(DEC_OP,$1,NULL); }
+                      { $$ = newNode(DEC_OP,$1,NULL); }
    ;
 
 argument_expr_list
    ;
 
 argument_expr_list
-   : assignment_expr 
+   : assignment_expr
    | assignment_expr ',' argument_expr_list { $$ = newNode(PARAM,$1,$3); }
    ;
 
    | assignment_expr ',' argument_expr_list { $$ = newNode(PARAM,$1,$3); }
    ;
 
@@ -280,7 +308,7 @@ unary_expr
    | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); }
    | TYPEOF unary_expr        { $$ = newNode(TYPEOF,NULL,$2);  }
    ;
    | SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); }
    | TYPEOF unary_expr        { $$ = newNode(TYPEOF,NULL,$2);  }
    ;
-              
+
 unary_operator
    : '&'    { $$ = '&' ;}
    | '*'    { $$ = '*' ;}
 unary_operator
    : '&'    { $$ = '&' ;}
    | '*'    { $$ = '*' ;}
@@ -316,40 +344,16 @@ shift_expr
 
 relational_expr
    : shift_expr
 
 relational_expr
    : shift_expr
-   | relational_expr '<' shift_expr    { 
-       $$ = (port->lt_nge ? 
-             newNode('!',newNode(GE_OP,$1,$3),NULL) :
-             newNode('<', $1,$3));
-   }
-   | relational_expr '>' shift_expr    { 
-          $$ = (port->gt_nle ? 
-                newNode('!',newNode(LE_OP,$1,$3),NULL) :
-                newNode('>',$1,$3));
-   }
-   | relational_expr LE_OP shift_expr  { 
-          $$ = (port->le_ngt ? 
-                newNode('!', newNode('>', $1 , $3 ), NULL) :
-                newNode(LE_OP,$1,$3));
-   }
-   | relational_expr GE_OP shift_expr  { 
-          $$ = (port->ge_nlt ? 
-                newNode('!', newNode('<', $1 , $3 ), NULL) :
-                newNode(GE_OP,$1,$3));
-   }
+   | relational_expr '<' shift_expr   { $$ = newNode('<',  $1,$3);}
+   | relational_expr '>' shift_expr   { $$ = newNode('>',  $1,$3);}
+   | relational_expr LE_OP shift_expr { $$ = newNode(LE_OP,$1,$3);}
+   | relational_expr GE_OP shift_expr { $$ = newNode(GE_OP,$1,$3);}
    ;
 
 equality_expr
    : relational_expr
    ;
 
 equality_expr
    : relational_expr
-   | equality_expr EQ_OP relational_expr  { 
-    $$ = (port->eq_nne ? 
-         newNode('!',newNode(NE_OP,$1,$3),NULL) : 
-         newNode(EQ_OP,$1,$3));
-   }
-   | equality_expr NE_OP relational_expr { 
-       $$ = (port->ne_neq ? 
-            newNode('!', newNode(EQ_OP,$1,$3), NULL) : 
-            newNode(NE_OP,$1,$3));
-   }       
+   | equality_expr EQ_OP relational_expr { $$ = newNode(EQ_OP,$1,$3);}
+   | equality_expr NE_OP relational_expr { $$ = newNode(NE_OP,$1,$3);}
    ;
 
 and_expr
    ;
 
 and_expr
@@ -369,68 +373,71 @@ inclusive_or_expr
 
 logical_and_expr
    : inclusive_or_expr
 
 logical_and_expr
    : inclusive_or_expr
-   | logical_and_expr AND_OP inclusive_or_expr 
-                                 { $$ = newNode(AND_OP,$1,$3);}
+   | logical_and_expr AND_OP { seqPointNo++;} inclusive_or_expr
+                                 { $$ = newNode(AND_OP,$1,$4);}
    ;
 
 logical_or_expr
    : logical_and_expr
    ;
 
 logical_or_expr
    : logical_and_expr
-   | logical_or_expr OR_OP logical_and_expr  
-                                 { $$ = newNode(OR_OP,$1,$3); }
+   | logical_or_expr OR_OP { seqPointNo++;} logical_and_expr
+                                 { $$ = newNode(OR_OP,$1,$4); }
    ;
 
 conditional_expr
    : logical_or_expr
    ;
 
 conditional_expr
    : logical_or_expr
-   | logical_or_expr '?' logical_or_expr ':' conditional_expr  
+   | logical_or_expr '?' { seqPointNo++;} logical_or_expr ':' conditional_expr
                      {
                      {
-                        $$ = newNode(':',$3,$5) ;
+                        $$ = newNode(':',$4,$6) ;
                         $$ = newNode('?',$1,$$) ;
                         $$ = newNode('?',$1,$$) ;
-                     }                        
+                     }
    ;
 
 assignment_expr
    : conditional_expr
    ;
 
 assignment_expr
    : conditional_expr
-   | unary_expr assignment_operator assignment_expr   
-                     { 
-                                
-                            switch ($2) {
-                            case '=':
-                                    $$ = newNode($2,$1,$3);
-                                    break;
-                            case MUL_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case DIV_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case MOD_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case ADD_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case SUB_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case LEFT_ASSIGN:
-                                    $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case RIGHT_ASSIGN:
-                                    $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case AND_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case XOR_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            case OR_ASSIGN:
-                                    $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3));
-                                    break;
-                            default :
-                                    $$ = NULL;
-                            }
-                                    
+   | cast_expr assignment_operator assignment_expr
+                     {
+
+                             switch ($2) {
+                             case '=':
+                                     $$ = newNode($2,$1,$3);
+                                     break;
+                             case MUL_ASSIGN:
+                                     $$ = createRMW($1, '*', $3);
+                                     break;
+                             case DIV_ASSIGN:
+                                     $$ = createRMW($1, '/', $3);
+                                     break;
+                             case MOD_ASSIGN:
+                                     $$ = createRMW($1, '%', $3);
+                                     break;
+                             case ADD_ASSIGN:
+                                     $$ = createRMW($1, '+', $3);
+                                     break;
+                             case SUB_ASSIGN:
+                                     $$ = createRMW($1, '-', $3);
+                                     break;
+                             case LEFT_ASSIGN:
+                                     $$ = createRMW($1, LEFT_OP, $3);
+                                     break;
+                             case RIGHT_ASSIGN:
+                                     $$ = createRMW($1, RIGHT_OP, $3);
+                                     break;
+                             case AND_ASSIGN:
+                                     $$ = createRMW($1, '&', $3);
+                                     break;
+                             case XOR_ASSIGN:
+                                     $$ = createRMW($1, '^', $3);
+                                     break;
+                             case OR_ASSIGN:
+/*                                   $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); */
+/*                                   $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+                                                      newNode('|',removePreIncDecOps(copyAst($1)),$3)); */
+                                     $$ = createRMW($1, '|', $3);
+                                     break;
+                             default :
+                                     $$ = NULL;
+                             }
+
                      }
 ;
 
                      }
 ;
 
@@ -450,60 +457,83 @@ assignment_operator
 
 expr
    : assignment_expr
 
 expr
    : assignment_expr
-   | expr ',' assignment_expr { $$ = newNode(',',$1,$3);}
+   | expr ',' { seqPointNo++;} assignment_expr { $$ = newNode(',',$1,$4);}
    ;
 
 constant_expr
    ;
 
 constant_expr
-   : conditional_expr 
+   : conditional_expr
    ;
 
 declaration
    ;
 
 declaration
-   : declaration_specifiers ';'  { $$ = NULL ; }
+   : declaration_specifiers ';'
+      {
+         if (uselessDecl)
+           werror(W_USELESS_DECL);
+         uselessDecl = TRUE;
+         $$ = NULL ;
+      }
    | declaration_specifiers init_declarator_list ';'
       {
          /* add the specifier list to the id */
          symbol *sym , *sym1;
 
          for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) {
    | declaration_specifiers init_declarator_list ';'
       {
          /* add the specifier list to the id */
          symbol *sym , *sym1;
 
          for (sym1 = sym = reverseSyms($2);sym != NULL;sym = sym->next) {
-            sym_link *lnk = copyLinkChain($1);
-            /* do the pointer stuff */
-            pointerTypes(sym->type,lnk);
-            addDecl (sym,0,lnk) ;
-        }
-        
-        $$ = sym1 ;
+             sym_link *lnk = copyLinkChain($1);
+             if (options.unsigned_char && SPEC_NOUN(lnk) == V_CHAR && !lnk->select.s.b_signed)
+               SPEC_USIGN(lnk) = 1;
+             /* do the pointer stuff */
+             pointerTypes(sym->type,lnk);
+             addDecl (sym,0,lnk) ;
+         }
+
+         uselessDecl = TRUE;
+         $$ = sym1 ;
       }
    ;
 
 declaration_specifiers
       }
    ;
 
 declaration_specifiers
-   : storage_class_specifier                                           { $$ = $1; }
-   | storage_class_specifier declaration_specifiers { 
+   : storage_class_specifier                                            { $$ = $1; }
+   | storage_class_specifier declaration_specifiers {
      /* if the decl $2 is not a specifier */
      /* find the spec and replace it      */
      if ( !IS_SPEC($2)) {
        sym_link *lnk = $2 ;
        while (lnk && !IS_SPEC(lnk->next))
      /* if the decl $2 is not a specifier */
      /* find the spec and replace it      */
      if ( !IS_SPEC($2)) {
        sym_link *lnk = $2 ;
        while (lnk && !IS_SPEC(lnk->next))
-        lnk = lnk->next;
+         lnk = lnk->next;
        lnk->next = mergeSpec($1,lnk->next, "storage_class_specifier declaration_specifiers - skipped");
        $$ = $2 ;
      }
      else
        $$ = mergeSpec($1,$2, "storage_class_specifier declaration_specifiers");
    }
        lnk->next = mergeSpec($1,lnk->next, "storage_class_specifier declaration_specifiers - skipped");
        $$ = $2 ;
      }
      else
        $$ = mergeSpec($1,$2, "storage_class_specifier declaration_specifiers");
    }
-   | type_specifier                                { $$ = $1; }
-   | type_specifier declaration_specifiers          { 
+   | type_specifier                                 { $$ = $1; }
+   | type_specifier declaration_specifiers          {
      /* if the decl $2 is not a specifier */
      /* find the spec and replace it      */
      if ( !IS_SPEC($2)) {
        sym_link *lnk = $2 ;
        while (lnk && !IS_SPEC(lnk->next))
      /* if the decl $2 is not a specifier */
      /* find the spec and replace it      */
      if ( !IS_SPEC($2)) {
        sym_link *lnk = $2 ;
        while (lnk && !IS_SPEC(lnk->next))
-        lnk = lnk->next;
+         lnk = lnk->next;
        lnk->next = mergeSpec($1,lnk->next, "type_specifier declaration_specifiers - skipped");
        $$ = $2 ;
      }
      else
        $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers");
    }
        lnk->next = mergeSpec($1,lnk->next, "type_specifier declaration_specifiers - skipped");
        $$ = $2 ;
      }
      else
        $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers");
    }
+   | function_specifier                             { $$ = $1; }
+   | function_specifier declaration_specifiers          {
+     /* if the decl $2 is not a specifier */
+     /* find the spec and replace it      */
+     if ( !IS_SPEC($2)) {
+       sym_link *lnk = $2 ;
+       while (lnk && !IS_SPEC(lnk->next))
+         lnk = lnk->next;
+       lnk->next = mergeSpec($1,lnk->next, "function_specifier declaration_specifiers - skipped");
+       $$ = $2 ;
+     }
+     else
+       $$ = mergeSpec($1,$2, "function_specifier declaration_specifiers");
+   }
    ;
 
 init_declarator_list
    ;
 
 init_declarator_list
@@ -540,8 +570,25 @@ storage_class_specifier
                }
    ;
 
                }
    ;
 
+function_specifier
+   : INLINE   {
+                  $$ = newLink (SPECIFIER) ;
+                  SPEC_INLINE($$) = 1 ;
+               }
+   ;
+
 Interrupt_storage
 Interrupt_storage
-   : INTERRUPT CONSTANT  { $$ = (int) floatFromVal($2) ;  }
+   : INTERRUPT { $$ = INTNO_UNSPEC ; }
+   | INTERRUPT constant_expr
+        { int intno = (int) ulFromVal(constExprValue($2,TRUE));
+          if ((intno >= 0) && (intno <= INTNO_MAX))
+            $$ = intno;
+          else
+            {
+              werror(E_INT_BAD_INTNO, intno);
+              $$ = INTNO_UNSPEC;
+            }
+        }
    ;
 
 type_specifier
    ;
 
 type_specifier
@@ -551,63 +598,77 @@ type_specifier
            /* add this to the storage class specifier  */
            SPEC_ABSA($1) = 1;   /* set the absolute addr flag */
            /* now get the abs addr from value */
            /* add this to the storage class specifier  */
            SPEC_ABSA($1) = 1;   /* set the absolute addr flag */
            /* now get the abs addr from value */
-           SPEC_ADDR($1) = (int) floatFromVal(constExprValue($3,TRUE)) ;
+           SPEC_ADDR($1) = (unsigned int) ulFromVal(constExprValue($3,TRUE)) ;
         }
    ;
 
 type_specifier2
         }
    ;
 
 type_specifier2
-   : CHAR   {
-               $$=newLink(SPECIFIER);
-               SPEC_NOUN($$) = V_CHAR  ;
-            }
-   | SHORT  {
-               $$=newLink(SPECIFIER);
-              $$->select.s._short = 1 ;
-            }
-   | INT    {
-               $$=newLink(SPECIFIER);
-               SPEC_NOUN($$) = V_INT   ;
-            }
-   | LONG   {
-               $$=newLink(SPECIFIER);
-              SPEC_LONG($$) = 1       ;
-            }
-   | SIGNED {
-               $$=newLink(SPECIFIER);
-               $$->select.s._signed = 1;
-            }
+   : CHAR      {
+                  $$=newLink(SPECIFIER);
+                  SPEC_NOUN($$) = V_CHAR  ;
+                  ignoreTypedefType = 1;
+               }
+   | SHORT     {
+                  $$=newLink(SPECIFIER);
+                  SPEC_SHORT($$) = 1 ;
+                  ignoreTypedefType = 1;
+               }
+   | INT       {
+                  $$=newLink(SPECIFIER);
+                  SPEC_NOUN($$) = V_INT   ;
+                  ignoreTypedefType = 1;
+               }
+   | LONG      {
+                  $$=newLink(SPECIFIER);
+                  SPEC_LONG($$) = 1       ;
+                  ignoreTypedefType = 1;
+               }
+   | SIGNED    {
+                  $$=newLink(SPECIFIER);
+                  $$->select.s.b_signed = 1;
+                  ignoreTypedefType = 1;
+               }
    | UNSIGNED  {
    | UNSIGNED  {
-               $$=newLink(SPECIFIER);
-               SPEC_USIGN($$) = 1      ;
-            }
-   | VOID   {
-               $$=newLink(SPECIFIER);
-               SPEC_NOUN($$) = V_VOID  ;
-            }
-   | CONST  {
-               $$=newLink(SPECIFIER);
-              SPEC_CONST($$) = 1;
-            }
+                  $$=newLink(SPECIFIER);
+                  SPEC_USIGN($$) = 1      ;
+                  ignoreTypedefType = 1;
+               }
+   | VOID      {
+                  $$=newLink(SPECIFIER);
+                  SPEC_NOUN($$) = V_VOID  ;
+                  ignoreTypedefType = 1;
+               }
+   | CONST     {
+                  $$=newLink(SPECIFIER);
+                  SPEC_CONST($$) = 1;
+               }
    | VOLATILE  {
    | VOLATILE  {
-               $$=newLink(SPECIFIER);
-              SPEC_VOLATILE($$) = 1 ;
-            }
-   | FLOAT  {
-               $$=newLink(SPECIFIER);
-              SPEC_NOUN($$) = V_FLOAT;
-            }
+                  $$=newLink(SPECIFIER);
+                  SPEC_VOLATILE($$) = 1 ;
+               }
+   | RESTRICT  {
+                  $$=newLink(SPECIFIER);
+                  SPEC_RESTRICT($$) = 1 ;
+               }
+   | FLOAT     {
+                  $$=newLink(SPECIFIER);
+                  SPEC_NOUN($$) = V_FLOAT;
+                  ignoreTypedefType = 1;
+               }
+   | FIXED16X16 {
+                  $$=newLink(SPECIFIER);
+                  SPEC_NOUN($$) = V_FIXED16X16;
+                  ignoreTypedefType = 1;
+               }
    | XDATA     {
                   $$ = newLink (SPECIFIER);
                   SPEC_SCLS($$) = S_XDATA  ;
                }
    | CODE      {
                   $$ = newLink (SPECIFIER) ;
    | XDATA     {
                   $$ = newLink (SPECIFIER);
                   SPEC_SCLS($$) = S_XDATA  ;
                }
    | CODE      {
                   $$ = newLink (SPECIFIER) ;
-                  SPEC_SCLS($$) = S_CODE ;                 
-                 if (port->mem.code_ro) {
-                   SPEC_CONST($$) = 1;
-                 }
+                  SPEC_SCLS($$) = S_CODE ;
                }
                }
-   | EEPROM      {
+   | EEPROM    {
                   $$ = newLink (SPECIFIER) ;
                   SPEC_SCLS($$) = S_EEPROM ;
                }
                   $$ = newLink (SPECIFIER) ;
                   SPEC_SCLS($$) = S_EEPROM ;
                }
@@ -619,30 +680,38 @@ type_specifier2
                   $$ = newLink (SPECIFIER);
                   SPEC_SCLS($$) = S_IDATA  ;
                }
                   $$ = newLink (SPECIFIER);
                   SPEC_SCLS($$) = S_IDATA  ;
                }
-   | PDATA     { 
+   | PDATA     {
                   $$ = newLink (SPECIFIER);
                   SPEC_SCLS($$) = S_PDATA  ;
                }
                   $$ = newLink (SPECIFIER);
                   SPEC_SCLS($$) = S_PDATA  ;
                }
-   | BIT    {
-               $$=newLink(SPECIFIER);
-               SPEC_NOUN($$) = V_BIT   ;
-              SPEC_SCLS($$) = S_BIT   ;
-              SPEC_BLEN($$) = 1;
-              SPEC_BSTR($$) = 0;
-            }
+   | BIT       {
+                  $$=newLink(SPECIFIER);
+                  SPEC_NOUN($$) = V_BIT   ;
+                  SPEC_SCLS($$) = S_BIT   ;
+                  SPEC_BLEN($$) = 1;
+                  SPEC_BSTR($$) = 0;
+                  ignoreTypedefType = 1;
+               }
 
 
-   | struct_or_union_specifier
-   | enum_specifier     {                           
+   | struct_or_union_specifier  {
+                                   uselessDecl = FALSE;
+                                   $$ = $1 ;
+                                   ignoreTypedefType = 1;
+                                }
+   | enum_specifier     {
                            cenum = NULL ;
                            cenum = NULL ;
-                           $$ = $1 ;                              
+                           uselessDecl = FALSE;
+                           ignoreTypedefType = 1;
+                           $$ = $1 ;
                         }
                         }
-   | TYPE_NAME    
+   | TYPE_NAME
          {
             symbol *sym;
             sym_link   *p  ;
             sym = findSym(TypedefTab,NULL,$1) ;
          {
             symbol *sym;
             sym_link   *p  ;
             sym = findSym(TypedefTab,NULL,$1) ;
-            $$ = p = copyLinkChain(sym->type);
-           SPEC_TYPEDEF(getSpec(p)) = 0;
+            $$ = p = copyLinkChain(sym ? sym->type : NULL);
+            SPEC_TYPEDEF(getSpec(p)) = 0;
+            ignoreTypedefType = 1;
          }
    | sfr_reg_bit
    ;
          }
    | sfr_reg_bit
    ;
@@ -652,24 +721,99 @@ sfr_reg_bit
                $$ = newLink(SPECIFIER) ;
                SPEC_NOUN($$) = V_SBIT;
                SPEC_SCLS($$) = S_SBIT;
                $$ = newLink(SPECIFIER) ;
                SPEC_NOUN($$) = V_SBIT;
                SPEC_SCLS($$) = S_SBIT;
+               SPEC_BLEN($$) = 1;
+               SPEC_BSTR($$) = 0;
+               ignoreTypedefType = 1;
             }
             }
-   |  SFR   {
+   |  sfr_attributes
+   ;
+
+sfr_attributes
+   : SFR    {
+               $$ = newLink(SPECIFIER) ;
+               FUNC_REGBANK($$) = 0;
+               SPEC_NOUN($$)    = V_CHAR;
+               SPEC_SCLS($$)    = S_SFR ;
+               SPEC_USIGN($$)   = 1 ;
+               ignoreTypedefType = 1;
+            }
+   | SFR BANKED {
+               $$ = newLink(SPECIFIER) ;
+               FUNC_REGBANK($$) = 1;
+               SPEC_NOUN($$)    = V_CHAR;
+               SPEC_SCLS($$)    = S_SFR ;
+               SPEC_USIGN($$)   = 1 ;
+               ignoreTypedefType = 1;
+            }
+   ;
+
+sfr_attributes
+   : SFR16  {
+               $$ = newLink(SPECIFIER) ;
+               FUNC_REGBANK($$) = 0;
+               SPEC_NOUN($$)    = V_INT;
+               SPEC_SCLS($$)    = S_SFR;
+               SPEC_USIGN($$)   = 1 ;
+               ignoreTypedefType = 1;
+            }
+   ;
+
+sfr_attributes
+   : SFR32  {
                $$ = newLink(SPECIFIER) ;
                $$ = newLink(SPECIFIER) ;
-               SPEC_NOUN($$) = V_CHAR;
-               SPEC_SCLS($$) = S_SFR ;
-              SPEC_USIGN($$) = 1 ;
+               FUNC_REGBANK($$) = 0;
+               SPEC_NOUN($$)    = V_INT;
+               SPEC_SCLS($$)    = S_SFR;
+               SPEC_LONG($$)    = 1;
+               SPEC_USIGN($$)   = 1;
+               ignoreTypedefType = 1;
             }
    ;
 
 struct_or_union_specifier
             }
    ;
 
 struct_or_union_specifier
-   : struct_or_union opt_stag '{' struct_declaration_list '}'
+   : struct_or_union opt_stag
+        {
+           if (!$2->type)
+             {
+               $2->type = $1;
+             }
+           else
+             {
+               if ($2->type != $1)
+                 werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union");
+             }
+
+        }
+           '{' struct_declaration_list '}'
         {
            structdef *sdef ;
         {
            structdef *sdef ;
+           symbol *sym, *dsym;
+
+           // check for errors in structure members
+           for (sym=$5; sym; sym=sym->next) {
+             if (IS_ABSOLUTE(sym->etype)) {
+               werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "'at'");
+               SPEC_ABSA(sym->etype) = 0;
+             }
+             if (IS_SPEC(sym->etype) && SPEC_SCLS(sym->etype)) {
+               werrorfl(sym->fileDef, sym->lineDef, E_NOT_ALLOWED, "storage class");
+               printTypeChainRaw (sym->type,NULL);
+               SPEC_SCLS(sym->etype) = 0;
+             }
+             for (dsym=sym->next; dsym; dsym=dsym->next) {
+               if (*dsym->name && strcmp(sym->name, dsym->name)==0) {
+                 werrorfl(sym->fileDef, sym->lineDef, E_DUPLICATE_MEMBER,
+                        $1==STRUCT ? "struct" : "union", sym->name);
+                 werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF);
+               }
+             }
+           }
 
            /* Create a structdef   */
            sdef = $2 ;
 
            /* Create a structdef   */
            sdef = $2 ;
-           sdef->fields   = reverseSyms($4) ;   /* link the fields */
+           sdef->fields   = reverseSyms($5) ;   /* link the fields */
            sdef->size  = compStructSize($1,sdef);   /* update size of  */
            sdef->size  = compStructSize($1,sdef);   /* update size of  */
+           promoteAnonStructs ($1, sdef);
 
            /* Create the specifier */
            $$ = newLink (SPECIFIER) ;
 
            /* Create the specifier */
            $$ = newLink (SPECIFIER) ;
@@ -680,7 +824,17 @@ struct_or_union_specifier
          {
             $$ = newLink(SPECIFIER) ;
             SPEC_NOUN($$) = V_STRUCT;
          {
             $$ = newLink(SPECIFIER) ;
             SPEC_NOUN($$) = V_STRUCT;
-            SPEC_STRUCT($$) = $2 ;
+            SPEC_STRUCT($$) = $2;
+
+           if (!$2->type)
+             {
+               $2->type = $1;
+             }
+           else
+             {
+               if ($2->type != $1)
+                 werror(E_BAD_TAG, $2->tag, $1==STRUCT ? "struct" : "union");
+             }
          }
    ;
 
          }
    ;
 
@@ -712,11 +866,12 @@ struct_declaration_list
    : struct_declaration
    | struct_declaration_list struct_declaration
        {
    : struct_declaration
    | struct_declaration_list struct_declaration
        {
-          symbol *sym = $2;
-          /* go to the end of the chain */
-          while (sym->next) sym = sym->next;
+           symbol *sym=$2;
 
 
+           /* go to the end of the chain */
+           while (sym->next) sym=sym->next;
            sym->next = $1 ;
            sym->next = $1 ;
+
            $$ = $2;
        }
    ;
            $$ = $2;
        }
    ;
@@ -727,20 +882,24 @@ struct_declaration
            /* add this type to all the symbols */
            symbol *sym ;
            for ( sym = $2 ; sym != NULL ; sym = sym->next ) {
            /* add this type to all the symbols */
            symbol *sym ;
            for ( sym = $2 ; sym != NULL ; sym = sym->next ) {
-              
-              /* make the symbol one level up */
-              sym->level-- ;
-
-              pointerTypes(sym->type,copyLinkChain($1));
-              if (!sym->type) {
-                  sym->type = copyLinkChain($1);
-                  sym->etype = getSpec(sym->type);
-              }
-              else
-                addDecl (sym,0,copyLinkChain($1));
-              /* make sure the type is complete and sane */
-              checkTypeSanity(sym->etype, sym->name);
-          }
+               sym_link *btype = copyLinkChain($1);
+               if (options.unsigned_char && SPEC_NOUN(btype) == V_CHAR && !(btype)->select.s.b_signed)
+                 SPEC_USIGN(btype) = 1;
+
+               /* make the symbol one level up */
+               sym->level-- ;
+
+               pointerTypes(sym->type,btype);
+               if (!sym->type) {
+                   sym->type = btype;
+                   sym->etype = getSpec(sym->type);
+               }
+               else
+                 addDecl (sym,0,btype);
+               /* make sure the type is complete and sane */
+               checkTypeSanity(sym->etype, sym->name);
+           }
+           ignoreTypedefType = 0;
            $$ = $2;
        }
    ;
            $$ = $2;
        }
    ;
@@ -755,134 +914,198 @@ struct_declarator_list
    ;
 
 struct_declarator
    ;
 
 struct_declarator
-   : declarator 
-   | ':' constant_expr  {  
-                           $$ = newSymbol (genSymName(NestLevel),NestLevel) ; 
-                           $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE));
-                        }                        
-   | declarator ':' constant_expr 
-                        { 
-                         $1->bitVar = (int) floatFromVal(constExprValue($3,TRUE));                     
+   : declarator
+   | ':' constant_expr  {
+                           unsigned int bitsize;
+                           $$ = newSymbol (genSymName(NestLevel),NestLevel) ;
+                           bitsize = (unsigned int) ulFromVal(constExprValue($2,TRUE));
+                           if (bitsize > (port->s.int_size * 8)) {
+                             bitsize = port->s.int_size * 8;
+                             werror(E_BITFLD_SIZE, bitsize);
+                           }
+                           if (!bitsize)
+                             bitsize = BITVAR_PAD;
+                           $$->bitVar = bitsize;
+                           $$->bitUnnamed = 1;
+                        }
+   | declarator ':' constant_expr
+                        {
+                          unsigned int bitsize;
+                          bitsize = (unsigned int) ulFromVal(constExprValue($3,TRUE));
+                          if (bitsize > (port->s.int_size * 8)) {
+                            bitsize = port->s.int_size * 8;
+                            werror(E_BITFLD_SIZE, bitsize);
+                          }
+                          if (!bitsize) {
+                            $$ = newSymbol (genSymName(NestLevel),NestLevel) ;
+                            $$->bitVar = BITVAR_PAD;
+                            werror(W_BITFLD_NAMED);
+                          }
+                          else
+                            $1->bitVar = bitsize;
                         }
                         }
+   | { $$ = newSymbol ("", NestLevel) ; }
+
    ;
 
 enum_specifier
    : ENUM            '{' enumerator_list '}' {
    ;
 
 enum_specifier
    : ENUM            '{' enumerator_list '}' {
-                                                //addSymChain ($3);
-                                                //allocVariables(reverseSyms($3)) ;
-                                                $$ = copyLinkChain(cenum->type);
-                                             }
+           $$ = newEnumType ($3);       //copyLinkChain(cenum->type);
+           SPEC_SCLS(getSpec($$)) = 0;
+         }
+
    | ENUM identifier '{' enumerator_list '}' {
    | ENUM identifier '{' enumerator_list '}' {
-                                                symbol *csym ;
-
-                                                $2->type = copyLinkChain(cenum->type);
-                                                $2->etype = getSpec($2->type);
-                                                /* add this to the enumerator table */
-                                                if (!(csym=findSym(enumTab,$2,$2->name)) && 
-                                                   (csym && csym->level == $2->level))
-                                                   werror(E_DUPLICATE_TYPEDEF,csym->name);
-
-                                                addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
-                                               //addSymChain ($4);
-                                                //allocVariables (reverseSyms($4));
-                                                $$ = copyLinkChain(cenum->type);
-                                                SPEC_SCLS(getSpec($$)) = 0 ;
-                                             }
-   | ENUM identifier                         {
-                                                symbol *csym ;
+     symbol *csym ;
+     sym_link *enumtype;
+
+     csym=findSym(enumTab,$2,$2->name);
+     if ((csym && csym->level == $2->level))
+       {
+         werrorfl($2->fileDef, $2->lineDef, E_DUPLICATE_TYPEDEF,csym->name);
+         werrorfl(csym->fileDef, csym->lineDef, E_PREVIOUS_DEF);
+       }
 
 
-                                                /* check the enumerator table */
-                                                if ((csym = findSym(enumTab,$2,$2->name)))
-                                                   $$ = copyLinkChain(csym->type);
-                                                else  {
-                                                   $$ = newLink(SPECIFIER) ;
-                                                   SPEC_NOUN($$) = V_INT   ;
-                                                }
+     enumtype = newEnumType ($4);       //copyLinkChain(cenum->type);
+     SPEC_SCLS(getSpec(enumtype)) = 0;
+     $2->type = enumtype;
 
 
-                                                SPEC_SCLS(getSpec($$)) = 0 ;
-                                             }
+     /* add this to the enumerator table */
+     if (!csym)
+       addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
+     $$ = copyLinkChain(enumtype);
+   }
+   | ENUM identifier                         {
+     symbol *csym ;
+
+     /* check the enumerator table */
+     if ((csym = findSym(enumTab,$2,$2->name)))
+       $$ = copyLinkChain(csym->type);
+     else  {
+       $$ = newLink(SPECIFIER) ;
+       SPEC_NOUN($$) = V_INT   ;
+     }
+   }
    ;
 
 enumerator_list
    ;
 
 enumerator_list
-   : enumerator
-   | enumerator_list ',' {
-                         }
-   | enumerator_list ',' enumerator {
-                                       $3->next = $1 ;
-                                       $$ = $3  ;
-                                    }
-   ;
+    : enumerator
+    | enumerator_list ','
+    | enumerator_list ',' enumerator
+      {
+        $3->next = $1 ;
+        $$ = $3  ;
+      }
+    ;
 
 enumerator
 
 enumerator
-   : identifier opt_assign_expr  
-     {
-       /* make the symbol one level up */
-       $1->level-- ;
-       $1->type = copyLinkChain($2->type); 
-       $1->etype= getSpec($1->type);
-       SPEC_ENUM($1->etype) = 1;
-       $$ = $1 ;
-       // do this now, so we can use it for the next enums in the list
-       addSymChain($1);
-     }
-   ;
+    : identifier opt_assign_expr
+      {
+        symbol *sym;
+
+        /* make the symbol one level up */
+        $1->level-- ;
+        // check if the symbol at the same level already exists
+        if ((sym = findSymWithLevel (SymbolTab, $1)) &&
+          sym->level == $1->level)
+          {
+            werrorfl ($1->fileDef, $1->lineDef, E_DUPLICATE_MEMBER, "enum", $1->name);
+            werrorfl (sym->fileDef, sym->lineDef, E_PREVIOUS_DEF);
+          }
+        $1->type = copyLinkChain ($2->type);
+        $1->etype= getSpec ($1->type);
+        SPEC_ENUM ($1->etype) = 1;
+        $$ = $1 ;
+        // do this now, so we can use it for the next enums in the list
+        addSymChain (&$1);
+      }
+    ;
 
 opt_assign_expr
    :  '='   constant_expr  {
                               value *val ;
 
 opt_assign_expr
    :  '='   constant_expr  {
                               value *val ;
-                                                       
-                              val = constExprValue($2,TRUE);                         
+
+                              val = constExprValue($2,TRUE);
+                              if (!IS_INT(val->type) && !IS_CHAR(val->type))
+                                {
+                                  werror(E_ENUM_NON_INTEGER);
+                                  SNPRINTF(lbuff, sizeof(lbuff),
+                                          "%d", (int) ulFromVal(val));
+                                  val = constVal(lbuff);
+                                }
                               $$ = cenum = val ;
                               $$ = cenum = val ;
-                           }                           
-   |                       {                              
+                           }
+   |                       {
                               if (cenum)  {
                               if (cenum)  {
-                                 SNPRINTF(lbuff, sizeof(lbuff), 
-                                         "%d",(int) floatFromVal(cenum)+1);
+                                 SNPRINTF(lbuff, sizeof(lbuff),
+                                          "%d", (int) ulFromVal(cenum)+1);
                                  $$ = cenum = constVal(lbuff);
                               }
                               else {
                                  $$ = cenum = constVal(lbuff);
                               }
                               else {
-                                 SNPRINTF(lbuff, sizeof(lbuff), 
-                                         "%d",0);
-                                 $$ = cenum = constVal(lbuff);
-                              }   
+                                 $$ = cenum = constCharVal(0);
+                              }
                            }
    ;
 
 declarator
                            }
    ;
 
 declarator
-   : declarator2_function_attributes   { $$ = $1; }
-   | pointer declarator2_function_attributes
+   : declarator3                        { $$ = $1 ; }
+   | pointer declarator3
          {
          {
-            addDecl ($2,0,reverseLink($1));
-            $$ = $2 ;
+             addDecl ($2,0,reverseLink($1));
+             $$ = $2 ;
          }
    ;
 
          }
    ;
 
-declarator2_function_attributes
-   : declarator2                 { $$ = $1 ; } 
-   | declarator2 function_attribute  { 
-       // copy the functionAttributes (not the args and hasVargs !!)
-       sym_link *funcType=$1->etype;
-       struct value *args=FUNC_ARGS(funcType);
-       unsigned hasVargs=FUNC_HASVARARGS(funcType);
-
-       memcpy (&funcType->funcAttrs, &$2->funcAttrs, 
-              sizeof($2->funcAttrs));
+declarator3
+   : declarator2_function_attributes    { $$ = $1 ; }
+   | declarator2                        { $$ = $1 ; }
+   ;
 
 
-       FUNC_ARGS(funcType)=args;
-       FUNC_HASVARARGS(funcType)=hasVargs;
+function_declarator
+   : declarator2_function_attributes    { $$ = $1; }
+   | pointer declarator2_function_attributes
+         {
+             addDecl ($2,0,reverseLink($1));
+             $$ = $2 ;
+         }
+   ;
 
 
-       // just to be sure
-       memset (&$2->funcAttrs, 0,
-              sizeof($2->funcAttrs));
-       
-       addDecl ($1,0,$2); 
-   }     
+declarator2_function_attributes
+   : function_declarator2                 { $$ = $1 ; }
+   | function_declarator2 function_attribute  {
+           // copy the functionAttributes (not the args and hasVargs !!)
+           struct value *args;
+           unsigned hasVargs;
+           sym_link *funcType=$1->type;
+
+           while (funcType && !IS_FUNC(funcType))
+             funcType = funcType->next;
+
+           if (!funcType)
+             werror (E_FUNC_ATTR);
+           else
+             {
+               args=FUNC_ARGS(funcType);
+               hasVargs=FUNC_HASVARARGS(funcType);
+
+               memcpy (&funcType->funcAttrs, &$2->funcAttrs,
+                   sizeof($2->funcAttrs));
+
+               FUNC_ARGS(funcType)=args;
+               FUNC_HASVARARGS(funcType)=hasVargs;
+
+               // just to be sure
+               memset (&$2->funcAttrs, 0,
+                   sizeof($2->funcAttrs));
+
+               addDecl ($1,0,$2);
+             }
+   }
    ;
 
 declarator2
    : identifier
    | '(' declarator ')'     { $$ = $2; }
    ;
 
 declarator2
    : identifier
    | '(' declarator ')'     { $$ = $2; }
-   | declarator2 '[' ']'
+   | declarator3 '[' ']'
          {
             sym_link   *p;
 
          {
             sym_link   *p;
 
@@ -891,114 +1114,137 @@ declarator2
             DCL_ELEM(p) = 0     ;
             addDecl($1,0,p);
          }
             DCL_ELEM(p) = 0     ;
             addDecl($1,0,p);
          }
-   | declarator2 '[' constant_expr ']'
+   | declarator3 '[' constant_expr ']'
          {
          {
-            sym_link   *p ;
-                       value *tval;
-                       
-            p = (tval = constExprValue($3,TRUE))->etype;
+            sym_link *p;
+            value *tval;
+            int size;
+
+            tval = constExprValue($3, TRUE);
             /* if it is not a constant then Error  */
             /* if it is not a constant then Error  */
-            if ( SPEC_SCLS(p) != S_LITERAL)
-               werror(E_CONST_EXPECTED) ;
-            else {
-               p = newLink (DECLARATOR);
-               DCL_TYPE(p) = ARRAY ;
-               DCL_ELEM(p) = (int) floatFromVal(tval) ;
-               addDecl($1,0,p);
-            }                          
+            p = newLink (DECLARATOR);
+            DCL_TYPE(p) = ARRAY;
+
+            if (!tval || (SPEC_SCLS(tval->etype) != S_LITERAL))
+              {
+                werror(E_CONST_EXPECTED);
+                /* Assume a single item array to limit the cascade */
+                /* of additional errors. */
+                size = 1;
+              }
+            else
+              {
+                if ((size = (int) ulFromVal(tval)) < 0)
+                  {
+                    werror(E_NEGATIVE_ARRAY_SIZE, $1->name);
+                    size = 1;
+                  }
+              }
+            DCL_ELEM(p) = size;
+            addDecl($1, 0, p);
          }
          }
-   | declarator2 '('  ')'      {  addDecl ($1,FUNCTION,NULL) ;   }
-   | declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')'
+   ;
+
+function_declarator2
+   : declarator2 '('  ')'       {  addDecl ($1,FUNCTION,NULL) ;   }
+   | declarator2 '('            { NestLevel++ ; currBlockno++;  }
+                     parameter_type_list ')'
          {
          {
-          
-            addDecl ($1,FUNCTION,NULL) ;
-          
-            FUNC_HASVARARGS($1->type) = IS_VARG($4);
-            FUNC_ARGS($1->type) = reverseVal($4);
-            
-            /* nest level was incremented to take care of the parms  */
-            NestLevel-- ;
-            currBlockno--;
-
-            // if this was a pointer (to a function)
-            if (IS_PTR($1->type)) {
-              // move the args and hasVargs to the function
-              FUNC_ARGS($1->etype)=FUNC_ARGS($1->type);
-              FUNC_HASVARARGS($1->etype)=FUNC_HASVARARGS($1->type);
-              memset (&$1->type->funcAttrs, 0,
-                      sizeof($1->type->funcAttrs));
-              // remove the symbol args (if any)
-              cleanUpLevel(SymbolTab,NestLevel+1);
-            }
-            
-            $$ = $1;
+             sym_link *funcType;
+
+             addDecl ($1,FUNCTION,NULL) ;
+
+             funcType = $1->type;
+             while (funcType && !IS_FUNC(funcType))
+               funcType = funcType->next;
+
+             assert (funcType);
+
+             FUNC_HASVARARGS(funcType) = IS_VARG($4);
+             FUNC_ARGS(funcType) = reverseVal($4);
+
+             /* nest level was incremented to take care of the parms  */
+             NestLevel-- ;
+             currBlockno--;
+
+             // if this was a pointer (to a function)
+             if (!IS_FUNC($1->type))
+               cleanUpLevel(SymbolTab,NestLevel+1);
+
+             $$ = $1;
          }
          }
-   | declarator2 '(' parameter_identifier_list ')'
-         {        
-          werror(E_OLD_STYLE,$1->name) ;         
-          
-          /* assume it returns an int */
-          $1->type = $1->etype = newIntLink();
-          $$ = $1 ;
+   | declarator2 '(' identifier_list ')'
+         {
+           werror(E_OLD_STYLE,$1->name) ;
+           /* assume it returns an int */
+           $1->type = $1->etype = newIntLink();
+           $$ = $1 ;
          }
    ;
 
 pointer
    : unqualified_pointer { $$ = $1 ;}
          }
    ;
 
 pointer
    : unqualified_pointer { $$ = $1 ;}
-   | unqualified_pointer type_specifier_list   
+   | unqualified_pointer type_specifier_list
          {
          {
-            $$ = $1  ;         
-            DCL_TSPEC($1) = $2;
-        }
-   | unqualified_pointer pointer         
+             $$ = $1  ;
+             if (IS_SPEC($2)) {
+                 DCL_TSPEC($1) = $2;
+                 DCL_PTR_CONST($1) = SPEC_CONST($2);
+                 DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+                 DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
+             }
+             else
+                 werror (W_PTR_TYPE_INVALID);
+         }
+   | unqualified_pointer pointer
          {
          {
-            $$ = $1 ;          
-            $$->next = $2 ;
-            DCL_TYPE($2)=port->unqualified_pointer;
-        }
+             $$ = $1 ;
+             $$->next = $2 ;
+             DCL_TYPE($2)=port->unqualified_pointer;
+         }
    | unqualified_pointer type_specifier_list pointer
          {
    | unqualified_pointer type_specifier_list pointer
          {
-            $$ = $1 ;               
-            if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
-                DCL_PTR_CONST($1) = SPEC_CONST($2);
-                DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
-                switch (SPEC_SCLS($2)) {
-                case S_XDATA:
-                    DCL_TYPE($3) = FPOINTER;
-                    break;
-                case S_IDATA:
-                    DCL_TYPE($3) = IPOINTER ;
-                    break;
-                case S_PDATA:
-                    DCL_TYPE($3) = PPOINTER ;
-                    break;
-                case S_DATA:
-                    DCL_TYPE($3) = POINTER ;
-                    break;
-                case S_CODE:
-                    DCL_PTR_CONST($3) = 1;
-                    DCL_TYPE($3) = CPOINTER ;
-                    break;
-                case S_EEPROM:
-                    DCL_TYPE($3) = EEPPOINTER;
-                    break;
-                default:
-                  // this could be just "constant" 
-                  // werror(W_PTR_TYPE_INVALID);
-                    ;
-                }
-            }
-            else 
-                werror (W_PTR_TYPE_INVALID);
-            $$->next = $3 ;
-        }
+             $$ = $1 ;
+             if (IS_SPEC($2) && DCL_TYPE($3) == UPOINTER) {
+                 DCL_PTR_CONST($1) = SPEC_CONST($2);
+                 DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+                 DCL_PTR_RESTRICT($1) = SPEC_RESTRICT($2);
+                 switch (SPEC_SCLS($2)) {
+                 case S_XDATA:
+                     DCL_TYPE($3) = FPOINTER;
+                     break;
+                 case S_IDATA:
+                     DCL_TYPE($3) = IPOINTER ;
+                     break;
+                 case S_PDATA:
+                     DCL_TYPE($3) = PPOINTER ;
+                     break;
+                 case S_DATA:
+                     DCL_TYPE($3) = POINTER ;
+                     break;
+                 case S_CODE:
+                     DCL_TYPE($3) = CPOINTER ;
+                     break;
+                 case S_EEPROM:
+                     DCL_TYPE($3) = EEPPOINTER;
+                     break;
+                 default:
+                   // this could be just "constant"
+                   // werror(W_PTR_TYPE_INVALID);
+                     ;
+                 }
+             }
+             else
+                 werror (W_PTR_TYPE_INVALID);
+             $$->next = $3 ;
+         }
    ;
 
 unqualified_pointer
    ;
 
 unqualified_pointer
-   :  '*'   
+   :  '*'
       {
       {
-       $$ = newLink(DECLARATOR);
-       DCL_TYPE($$)=UPOINTER;
+        $$ = newLink(DECLARATOR);
+        DCL_TYPE($$)=UPOINTER;
       }
    ;
 
       }
    ;
 
@@ -1011,7 +1257,7 @@ type_specifier_list
      if ( !IS_SPEC($2)) {
        sym_link *lnk = $2 ;
        while (lnk && !IS_SPEC(lnk->next))
      if ( !IS_SPEC($2)) {
        sym_link *lnk = $2 ;
        while (lnk && !IS_SPEC(lnk->next))
-        lnk = lnk->next;
+         lnk = lnk->next;
        lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped");
        $$ = $2 ;
      }
        lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped");
        $$ = $2 ;
      }
@@ -1020,86 +1266,91 @@ type_specifier_list
    }
    ;
 
    }
    ;
 
-parameter_identifier_list
-   : identifier_list
-   | identifier_list ',' ELIPSIS
-   ;
-
 identifier_list
    : identifier
 identifier_list
    : identifier
-   | identifier_list ',' identifier         
-         {            
-          $3->next = $1;
-          $$ = $3 ;
+   | identifier_list ',' identifier
+         {
+           $3->next = $1;
+           $$ = $3 ;
          }
    ;
 
 parameter_type_list
          }
    ;
 
 parameter_type_list
-       : parameter_list
-       | parameter_list ',' VAR_ARGS { $1->vArgs = 1;}
-       ;
+        : parameter_list
+        | parameter_list ',' VAR_ARGS { $1->vArgs = 1;}
+        ;
 
 parameter_list
 
 parameter_list
-   : parameter_declaration 
+   : parameter_declaration
    | parameter_list ',' parameter_declaration
          {
             $3->next = $1 ;
    | parameter_list ',' parameter_declaration
          {
             $3->next = $1 ;
-            $$ = $3 ;      
+            $$ = $3 ;
          }
    ;
 
 parameter_declaration
          }
    ;
 
 parameter_declaration
-   : type_specifier_list declarator 
-               {       
-                 symbol *loop ;
-                 pointerTypes($2->type,$1);
-                  addDecl ($2,0,$1);             
-                 for (loop=$2;loop;loop->_isparm=1,loop=loop->next);
-                 addSymChain ($2);
-                 $$ = symbolVal($2);
+   : type_specifier_list declarator
+               {
+                  symbol *loop ;
+                  pointerTypes($2->type,$1);
+                  if (options.unsigned_char && SPEC_NOUN($1) == V_CHAR && !($1)->select.s.b_signed)
+                    SPEC_USIGN($1) = 1;
+                  addDecl ($2,0,$1);
+                  for (loop=$2;loop;loop->_isparm=1,loop=loop->next);
+                  addSymChain (&$2);
+                  $$ = symbolVal($2);
+                  ignoreTypedefType = 0;
                }
                }
-   | type_name { 
-                  $$ = newValue() ; 
+   | type_name {
+                  $$ = newValue() ;
+                  if (options.unsigned_char && SPEC_NOUN($1) == V_CHAR && !($1)->select.s.b_signed)
+                    SPEC_USIGN($1) = 1;
                   $$->type = $1;
                   $$->etype = getSpec($$->type);
                   $$->type = $1;
                   $$->etype = getSpec($$->type);
+                  ignoreTypedefType = 0;
                }
    ;
 
 type_name
                }
    ;
 
 type_name
-   : type_specifier_list  { $$ = $1 ;}
-   | type_specifier_list abstract_declarator 
+   : type_specifier_list  { $$ = $1; ignoreTypedefType = 0;}
+   | type_specifier_list abstract_declarator
                {
                {
-                /* go to the end of the list */
-                sym_link *p;
-                pointerTypes($2,$1);
-                for ( p = $2 ; p && p->next ; p=p->next);
-                if (!p) {
-                  werror(E_SYNTAX_ERROR, yytext);
-                } else {
-                  p->next = $1 ;
-                }
-                $$ = $2 ;
-               }   
+                 /* go to the end of the list */
+                 sym_link *p;
+                 pointerTypes($2,$1);
+                 for ( p = $2 ; p && p->next ; p=p->next);
+                 if (!p) {
+                   werror(E_SYNTAX_ERROR, yytext);
+                 } else {
+                   p->next = $1 ;
+                 }
+                 $$ = $2 ;
+                 ignoreTypedefType = 0;
+               }
    ;
 
 abstract_declarator
    : pointer { $$ = reverseLink($1); }
    | abstract_declarator2
    ;
 
 abstract_declarator
    : pointer { $$ = reverseLink($1); }
    | abstract_declarator2
-   | pointer abstract_declarator2   { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;} 
+   | pointer abstract_declarator2   { $1 = reverseLink($1); $1->next = $2 ; $$ = $1;
+          if (IS_PTR($1) && IS_FUNC($2))
+            DCL_TYPE($1) = CPOINTER;
+        }
    ;
 
 abstract_declarator2
    : '(' abstract_declarator ')'    { $$ = $2 ; }
    ;
 
 abstract_declarator2
    : '(' abstract_declarator ')'    { $$ = $2 ; }
-   | '[' ']'                        {             
+   | '[' ']'                        {
                                        $$ = newLink (DECLARATOR);
                                        DCL_TYPE($$) = ARRAY ;
                                        DCL_ELEM($$) = 0     ;
                                     }
                                        $$ = newLink (DECLARATOR);
                                        DCL_TYPE($$) = ARRAY ;
                                        DCL_ELEM($$) = 0     ;
                                     }
-   | '[' constant_expr ']'          { 
+   | '[' constant_expr ']'          {
                                        value *val ;
                                        $$ = newLink (DECLARATOR);
                                        DCL_TYPE($$) = ARRAY ;
                                        value *val ;
                                        $$ = newLink (DECLARATOR);
                                        DCL_TYPE($$) = ARRAY ;
-                                       DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE));
+                                       DCL_ELEM($$) = (int) ulFromVal(val = constExprValue($2,TRUE));
                                     }
    | abstract_declarator2 '[' ']'   {
                                        $$ = newLink (DECLARATOR);
                                     }
    | abstract_declarator2 '[' ']'   {
                                        $$ = newLink (DECLARATOR);
@@ -1112,11 +1363,11 @@ abstract_declarator2
                                        value *val ;
                                        $$ = newLink (DECLARATOR);
                                        DCL_TYPE($$) = ARRAY ;
                                        value *val ;
                                        $$ = newLink (DECLARATOR);
                                        DCL_TYPE($$) = ARRAY ;
-                                       DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE));
+                                       DCL_ELEM($$) = (int) ulFromVal(val = constExprValue($3,TRUE));
                                        $$->next = $1 ;
                                     }
    | '(' ')'                        { $$ = NULL;}
                                        $$->next = $1 ;
                                     }
    | '(' ')'                        { $$ = NULL;}
-   | '(' parameter_type_list ')'    { $$ = NULL;}   
+   | '(' parameter_type_list ')'    { $$ = NULL;}
    | abstract_declarator2 '(' ')' {
      // $1 must be a pointer to a function
      sym_link *p=newLink(DECLARATOR);
    | abstract_declarator2 '(' ')' {
      // $1 must be a pointer to a function
      sym_link *p=newLink(DECLARATOR);
@@ -1129,22 +1380,26 @@ abstract_declarator2
      }
      $1->next=p;
    }
      }
      $1->next=p;
    }
-   | abstract_declarator2 '(' parameter_type_list ')' {
-     if (!IS_VOID($3->etype)) {
-       // this is nonsense, so let's just burp something
-       werror(E_TOO_FEW_PARMS);
-     } else {
-       // $1 must be a pointer to a function
+   | abstract_declarator2 '(' { NestLevel++ ; currBlockno++; } parameter_type_list ')' {
        sym_link *p=newLink(DECLARATOR);
        DCL_TYPE(p) = FUNCTION;
        sym_link *p=newLink(DECLARATOR);
        DCL_TYPE(p) = FUNCTION;
+
+       FUNC_HASVARARGS(p) = IS_VARG($4);
+       FUNC_ARGS(p) = reverseVal($4);
+
+       /* nest level was incremented to take care of the parms  */
+       NestLevel-- ;
+       currBlockno--;
        if (!$1) {
        if (!$1) {
-        // ((void (code *) (void)) 0) ()
-        $1=newLink(DECLARATOR);
-        DCL_TYPE($1)=CPOINTER;
-        $$ = $1;
+         /* ((void (code *) (void)) 0) () */
+         $1=newLink(DECLARATOR);
+         DCL_TYPE($1)=CPOINTER;
+         $$ = $1;
        }
        $1->next=p;
        }
        $1->next=p;
-     }
+
+       // remove the symbol args (if any)
+       cleanUpLevel(SymbolTab,NestLevel+1);
    }
    ;
 
    }
    ;
 
@@ -1166,71 +1421,112 @@ statement
    | selection_statement
    | iteration_statement
    | jump_statement
    | selection_statement
    | iteration_statement
    | jump_statement
+   | critical_statement
    | INLINEASM  ';'      {
    | INLINEASM  ';'      {
-                            ast *ex = newNode(INLINEASM,NULL,NULL);
-                           ex->values.inlineasm = strdup($1);
-                           $$ = ex;
-                         } 
+                            ast *ex;
+                            seqPointNo++;
+                            ex = newNode(INLINEASM,NULL,NULL);
+                            ex->values.inlineasm = strdup($1);
+                            seqPointNo++;
+                            $$ = ex;
+                         }
+   ;
+
+critical
+   : CRITICAL   {
+                   inCritical++;
+                   STACK_PUSH(continueStack,NULL);
+                   STACK_PUSH(breakStack,NULL);
+                   $$ = NULL;
+                }
+   ;
+
+critical_statement
+   : critical statement  {
+                   STACK_POP(breakStack);
+                   STACK_POP(continueStack);
+                   inCritical--;
+                   $$ = newNode(CRITICAL,$2,NULL);
+                }
    ;
 
 labeled_statement
    ;
 
 labeled_statement
-//   : identifier ':' statement          {  $$ = createLabel($1,$3);  }   
-   : identifier ':'                    {  $$ = createLabel($1,NULL);  }   
-   | CASE constant_expr ':' statement  {  $$ = createCase(STACK_PEEK(swStk),$2,$4); }
-   | DEFAULT ':' statement             {  $$ = createDefault(STACK_PEEK(swStk),$3); }
+//   : identifier ':' statement          {  $$ = createLabel($1,$3);  }
+   : identifier ':'                    {  $$ = createLabel($1,NULL);
+                                          $1->isitmp = 0;  }
+   | CASE constant_expr ':'
+     {
+       if (STACK_EMPTY(swStk))
+         $$ = createCase(NULL,$2,NULL);
+       else
+         $$ = createCase(STACK_PEEK(swStk),$2,NULL);
+     }
+   | DEFAULT { $<asts>$ = newNode(DEFAULT,NULL,NULL); } ':'
+     {
+       if (STACK_EMPTY(swStk))
+         $$ = createDefault(NULL,$<asts>2,NULL);
+       else
+         $$ = createDefault(STACK_PEEK(swStk),$<asts>2,NULL);
+     }
    ;
 
    ;
 
-start_block : '{' { STACK_PUSH(blockNum,currBlockno); currBlockno = ++blockNo ;  }
+start_block : '{'
+              {
+                STACK_PUSH(blockNum,currBlockno);
+                currBlockno = ++blockNo ;
+                ignoreTypedefType = 0;
+              }
             ;
 
             ;
 
-end_block   : '}'     { currBlockno = STACK_POP(blockNum); }           
+end_block   : '}'     { currBlockno = STACK_POP(blockNum); }
             ;
 
 compound_statement
             ;
 
 compound_statement
-   : start_block end_block                    { $$ = createBlock(NULL,NULL); }
-   | start_block statement_list end_block     { $$ = createBlock(NULL,$2) ;  }
-   | start_block 
-          declaration_list                    { addSymChain($2); }
-     end_block                                { $$ = createBlock($2,NULL) ;  }
-   | start_block 
-          declaration_list                    {  addSymChain ($2); }
-          statement_list   
-     end_block                                {$$ = createBlock($2,$4)   ;  }
-   | error ';'                               { $$ = NULL ; }
+   : start_block end_block                    { $$ = createBlock(NULL, NULL); }
+   | start_block statement_list end_block     { $$ = createBlock(NULL, $2); }
+   | start_block declaration_list end_block   { $$ = createBlock($2, NULL); }
+   | start_block
+          declaration_list statement_list
+     end_block                                {$$ = createBlock($2, $3); }
+   | error ';'                                { $$ = NULL ; }
    ;
 
 declaration_list
    ;
 
 declaration_list
-   : declaration       
+   : declaration
      {
        /* if this is typedef declare it immediately */
        if ( $1 && IS_TYPEDEF($1->etype)) {
      {
        /* if this is typedef declare it immediately */
        if ( $1 && IS_TYPEDEF($1->etype)) {
-        allocVariables ($1);
-        $$ = NULL ;
+         allocVariables ($1);
+         $$ = NULL ;
        }
        else
        }
        else
-        $$ = $1 ;
+         $$ = $1 ;
+       ignoreTypedefType = 0;
+       addSymChain(&$1);
      }
 
    | declaration_list declaration
      {
        symbol   *sym;
      }
 
    | declaration_list declaration
      {
        symbol   *sym;
-       
+
        /* if this is a typedef */
        if ($2 && IS_TYPEDEF($2->etype)) {
        /* if this is a typedef */
        if ($2 && IS_TYPEDEF($2->etype)) {
-        allocVariables ($2);
-        $$ = $1 ;
+         allocVariables ($2);
+         $$ = $1 ;
        }
        else {
        }
        else {
-                               /* get to the end of the previous decl */
-        if ( $1 ) {
-          $$ = sym = $1 ;
-          while (sym->next)
-            sym = sym->next ;
-          sym->next = $2;
-        } 
-        else
-          $$ = $2 ;
+                                /* get to the end of the previous decl */
+         if ( $1 ) {
+           $$ = sym = $1 ;
+           while (sym->next)
+             sym = sym->next ;
+           sym->next = $2;
+         }
+         else
+           $$ = $2 ;
        }
        }
+       ignoreTypedefType = 0;
+       addSymChain(&$2);
      }
    ;
 
      }
    ;
 
@@ -1241,7 +1537,7 @@ statement_list
 
 expression_statement
    : ';'                { $$ = NULL;}
 
 expression_statement
    : ';'                { $$ = NULL;}
-   | expr ';' 
+   | expr ';'           { $$ = $1; seqPointNo++;}
    ;
 
 else_statement
    ;
 
 else_statement
@@ -1249,164 +1545,190 @@ else_statement
    |                    { $$ = NULL;}
    ;
 
    |                    { $$ = NULL;}
    ;
 
-  
+
 selection_statement
 selection_statement
-   : IF '(' expr ')'  statement else_statement { noLineno++ ; $$ = createIf ($3, $5, $6 ); noLineno--;}
-   | SWITCH '(' expr ')'   { 
-                              ast *ex ;                              
+   : IF '(' expr ')' { seqPointNo++;} statement else_statement
+                           {
+                              noLineno++ ;
+                              $$ = createIf ($3, $6, $7 );
+                              $$->lineno = $3->lineno;
+                              $$->filename = $3->filename;
+                              noLineno--;
+                           }
+   | SWITCH '(' expr ')'   {
+                              ast *ex ;
                               static   int swLabel = 0 ;
 
                               static   int swLabel = 0 ;
 
+                              seqPointNo++;
                               /* create a node for expression  */
                               ex = newNode(SWITCH,$3,NULL);
                               STACK_PUSH(swStk,ex);   /* save it in the stack */
                               ex->values.switchVals.swNum = swLabel ;
                               /* create a node for expression  */
                               ex = newNode(SWITCH,$3,NULL);
                               STACK_PUSH(swStk,ex);   /* save it in the stack */
                               ex->values.switchVals.swNum = swLabel ;
-                                 
+
                               /* now create the label */
                               /* now create the label */
-                              SNPRINTF(lbuff, sizeof(lbuff), 
-                                      "_swBrk_%d",swLabel++);
+                              SNPRINTF(lbuff, sizeof(lbuff),
+                                       "_swBrk_%d",swLabel++);
                               $<sym>$  =  newSymbol(lbuff,NestLevel);
                               /* put label in the break stack  */
                               $<sym>$  =  newSymbol(lbuff,NestLevel);
                               /* put label in the break stack  */
-                              STACK_PUSH(breakStack,$<sym>$);   
+                              STACK_PUSH(breakStack,$<sym>$);
                            }
                            }
-     statement             {  
+     statement             {
                               /* get back the switch form the stack  */
                               $$ = STACK_POP(swStk)  ;
                               $$->right = newNode (NULLOP,$6,createLabel($<sym>5,NULL));
                               /* get back the switch form the stack  */
                               $$ = STACK_POP(swStk)  ;
                               $$->right = newNode (NULLOP,$6,createLabel($<sym>5,NULL));
-                              STACK_POP(breakStack);   
+                              STACK_POP(breakStack);
                            }
                            }
-       ;
+        ;
 
 while : WHILE  {  /* create and push the continue , break & body labels */
                   static int Lblnum = 0 ;
 
 while : WHILE  {  /* create and push the continue , break & body labels */
                   static int Lblnum = 0 ;
-                 /* continue */
+                  /* continue */
                   SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum);
                   SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum);
-                 STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
-                 /* break */
-                 SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum);
-                 STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
-                 /* body */
-                 SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++);
-                 $$ = newSymbol(lbuff,NestLevel);
+                  STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
+                  /* break */
+                  SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum);
+                  STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
+                  /* body */
+                  SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++);
+                  $$ = newSymbol(lbuff,NestLevel);
                }
    ;
 
 do : DO {  /* create and push the continue , break & body Labels */
            static int Lblnum = 0 ;
 
                }
    ;
 
 do : DO {  /* create and push the continue , break & body Labels */
            static int Lblnum = 0 ;
 
-          /* continue */
-          SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum);
-          STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
-          /* break */
-          SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum);
-          STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
-          /* do body */
-          SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++);
-          $$ = newSymbol (lbuff,NestLevel);       
+           /* continue */
+           SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum);
+           STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
+           /* break */
+           SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum);
+           STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
+           /* do body */
+           SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++);
+           $$ = newSymbol (lbuff,NestLevel);
         }
    ;
 
 for : FOR { /* create & push continue, break & body labels */
             static int Lblnum = 0 ;
         }
    ;
 
 for : FOR { /* create & push continue, break & body labels */
             static int Lblnum = 0 ;
-         
+
             /* continue */
             /* continue */
-           SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum);
-           STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
-           /* break    */
-           SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum);
-           STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
-           /* body */
-           SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum);
-           $$ = newSymbol(lbuff,NestLevel);
-           /* condition */
-           SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++);
-           STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
+            SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum);
+            STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
+            /* break    */
+            SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum);
+            STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
+            /* body */
+            SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum);
+            $$ = newSymbol(lbuff,NestLevel);
+            /* condition */
+            SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++);
+            STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
           }
    ;
 
           }
    ;
 
-iteration_statement  
-   : while '(' expr ')'  statement 
-                         { 
-                          noLineno++ ;
-                          $$ = createWhile ( $1, STACK_POP(continueStack),
-                                             STACK_POP(breakStack), $3, $5 ); 
-                          $$->lineno = $1->lineDef ;
-                          noLineno-- ;
-                        }
-   | do statement   WHILE '(' expr ')' ';' 
-                        { 
-                         noLineno++ ; 
-                         $$ = createDo ( $1 , STACK_POP(continueStack), 
-                                         STACK_POP(breakStack), $5, $2);
-                         $$->lineno = $1->lineDef ;
-                         noLineno-- ;
-                       }                                                 
-   | for '(' expr_opt  ';' expr_opt ';' expr_opt ')'  statement   
+iteration_statement
+   : while '(' expr ')' { seqPointNo++;}  statement
+                         {
+                           noLineno++ ;
+                           $$ = createWhile ( $1, STACK_POP(continueStack),
+                                              STACK_POP(breakStack), $3, $6 );
+                           $$->lineno = $1->lineDef;
+                           $$->filename = $1->fileDef;
+                           noLineno-- ;
+                         }
+   | do statement   WHILE '(' expr ')' ';'
+                        {
+                          seqPointNo++;
+                          noLineno++ ;
+                          $$ = createDo ( $1 , STACK_POP(continueStack),
+                                          STACK_POP(breakStack), $5, $2);
+                          $$->lineno = $1->lineDef;
+                          $$->filename = $1->fileDef;
+                          noLineno-- ;
+                        }
+   | for '(' expr_opt   ';' expr_opt ';' expr_opt ')'  statement
                         {
                         {
-                         noLineno++ ;  
-                         
-                         /* if break or continue statement present
-                            then create a general case loop */
-                         if (STACK_PEEK(continueStack)->isref ||
-                             STACK_PEEK(breakStack)->isref) {
-                             $$ = createFor ($1, STACK_POP(continueStack),
-                                             STACK_POP(breakStack) ,
-                                             STACK_POP(forStack)   ,
-                                             $3 , $5 , $7, $9 );
-                         } else {
-                             $$ = newNode(FOR,$9,NULL);
-                             AST_FOR($$,trueLabel) = $1;
-                             AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
-                             AST_FOR($$,falseLabel) = STACK_POP(breakStack);
-                             AST_FOR($$,condLabel)  = STACK_POP(forStack)  ;
-                             AST_FOR($$,initExpr)   = $3;
-                             AST_FOR($$,condExpr)   = $5;
-                             AST_FOR($$,loopExpr)   = $7;
-                         }
-                         
-                         noLineno-- ;
-                       }
+                          noLineno++ ;
+
+                          /* if break or continue statement present
+                             then create a general case loop */
+                          if (STACK_PEEK(continueStack)->isref ||
+                              STACK_PEEK(breakStack)->isref) {
+                              $$ = createFor ($1, STACK_POP(continueStack),
+                                              STACK_POP(breakStack) ,
+                                              STACK_POP(forStack)   ,
+                                              $3 , $5 , $7, $9 );
+                          } else {
+                              $$ = newNode(FOR,$9,NULL);
+                              AST_FOR($$,trueLabel) = $1;
+                              AST_FOR($$,continueLabel) =  STACK_POP(continueStack);
+                              AST_FOR($$,falseLabel) = STACK_POP(breakStack);
+                              AST_FOR($$,condLabel)  = STACK_POP(forStack)  ;
+                              AST_FOR($$,initExpr)   = $3;
+                              AST_FOR($$,condExpr)   = $5;
+                              AST_FOR($$,loopExpr)   = $7;
+                          }
+
+                          noLineno-- ;
+                        }
 ;
 
 expr_opt
 ;
 
 expr_opt
-       :                       { $$ = NULL ; }
-       |       expr
-       ;
+        :                       { $$ = NULL ; seqPointNo++; }
+        |       expr            { $$ = $1 ; seqPointNo++; }
+        ;
 
 
-jump_statement          
-   : GOTO identifier ';'   { 
+jump_statement
+   : GOTO identifier ';'   {
                               $2->islbl = 1;
                               $2->islbl = 1;
-                              $$ = newAst_VALUE(symbolVal($2)); 
+                              $$ = newAst_VALUE(symbolVal($2));
                               $$ = newNode(GOTO,$$,NULL);
                            }
                               $$ = newNode(GOTO,$$,NULL);
                            }
-   | CONTINUE ';'          {  
+   | CONTINUE ';'          {
        /* make sure continue is in context */
        /* make sure continue is in context */
-       if (STACK_PEEK(continueStack) == NULL) {
-          werror(E_BREAK_CONTEXT);
-          $$ = NULL;
+       if (STACK_EMPTY(continueStack) || STACK_PEEK(continueStack) == NULL) {
+           werror(E_BREAK_CONTEXT);
+           $$ = NULL;
        }
        else {
        }
        else {
-          $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack)));      
-          $$ = newNode(GOTO,$$,NULL);
-          /* mark the continue label as referenced */
-          STACK_PEEK(continueStack)->isref = 1;
+           $$ = newAst_VALUE(symbolVal(STACK_PEEK(continueStack)));
+           $$ = newNode(GOTO,$$,NULL);
+           /* mark the continue label as referenced */
+           STACK_PEEK(continueStack)->isref = 1;
        }
    }
        }
    }
-   | BREAK ';'             { 
-       if (STACK_PEEK(breakStack) == NULL) {
-          werror(E_BREAK_CONTEXT);
-          $$ = NULL;
+   | BREAK ';'             {
+       if (STACK_EMPTY(breakStack) || STACK_PEEK(breakStack) == NULL) {
+           werror(E_BREAK_CONTEXT);
+           $$ = NULL;
        } else {
        } else {
-          $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack)));
-          $$ = newNode(GOTO,$$,NULL);
-          STACK_PEEK(breakStack)->isref = 1;
+           $$ = newAst_VALUE(symbolVal(STACK_PEEK(breakStack)));
+           $$ = newNode(GOTO,$$,NULL);
+           STACK_PEEK(breakStack)->isref = 1;
+       }
+   }
+   | RETURN ';'            {
+       seqPointNo++;
+       if (inCritical) {
+           werror(E_INVALID_CRITICAL);
+           $$ = NULL;
+       } else {
+           $$ = newNode(RETURN,NULL,NULL);
+       }
+   }
+   | RETURN expr ';'       {
+       seqPointNo++;
+       if (inCritical) {
+           werror(E_INVALID_CRITICAL);
+           $$ = NULL;
+       } else {
+           $$ = newNode(RETURN,NULL,$2);
        }
    }
        }
    }
-   | RETURN ';'            { $$ = newNode(RETURN,NULL,NULL)    ; }
-   | RETURN expr ';'       { $$ = newNode(RETURN,NULL,$2) ; } 
    ;
 
 identifier
    : IDENTIFIER   { $$ = newSymbol ($1,NestLevel) ; }
    ;
 %%
    ;
 
 identifier
    : IDENTIFIER   { $$ = newSymbol ($1,NestLevel) ; }
    ;
 %%
-