int reentrant = 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 ;
STACK_DCL(blockNum,int,MAX_NEST_LEVEL*3)
value *cenum = NULL ; /* current enumeration type chain*/
+bool uselessDecl = TRUE;
+
+#define YYDEBUG 1
%}
%expect 6
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 */
- 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 <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 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 CONST VOLATILE VOID BIT
%token STRUCT UNION ENUM ELIPSIS RANGE FAR
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN
%token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE
%token RRC RLC
%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> 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_list identifier_list parameter_identifier_list
-%type <sym> declarator2_function_attributes while do for
+%type <sym> declarator2_function_attributes while do for critical
%type <lnk> pointer type_specifier_list type_specifier type_name
%type <lnk> storage_class_specifier struct_or_union_specifier
-%type <lnk> declaration_specifiers sfr_reg_bit type_specifier2
+%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 <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 <yyint> unary_operator assignment_operator struct_or_union
blockNo=0;
}
| declaration {
+ ignoreTypedefType = 0;
if ($1 && $1->type
&& IS_FUNC($1->type))
{
SPEC_EXTR($1->etype) = 1;
}
}
- addSymChain ($1);
+ addSymChain (&$1);
allocVariables ($1) ;
cleanUpLevel (SymbolTab,1);
}
;
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());
$$ = createFunction($1,$2);
}
- | declaration_specifiers declarator function_body
+ | declaration_specifiers function_declarator function_body
{
pointerTypes($2->type,copyLinkChain($1));
addDecl($2,0,$1);
werror(W_BANKED_WITH_NONBANKED);
}
}
+ | SHADOWREGS {$$ = newLink (SPECIFIER);
+ FUNC_ISSHADOWREGS($$) = 1;
+ }
+ | WPARAM {$$ = newLink (SPECIFIER);
+ FUNC_ISWPARAM($$) = 1;
+ }
| BANKED {$$ = newLink (SPECIFIER);
FUNC_BANKED($$) = 1;
if (FUNC_NONBANKED($$)) {
{
$$ = newNode (CALL,$1,$3) ; $$->left->funcName = 1;
}
- | postfix_expr '.' identifier
+ | postfix_expr '.' { ignoreTypedefType = 1; } 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))) ; */
+ 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 identifier
+ | postfix_expr PTR_OP { ignoreTypedefType = 1; } identifier
{
- $3 = newSymbol($3->name,NestLevel);
- $3->implicit = 1;
- $$ = newNode(PTR_OP,$1,newAst_VALUE(symbolVal($3)));
+ 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);}
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 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
- | 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,$$) ;
}
;
assignment_expr
: conditional_expr
- | unary_expr assignment_operator assignment_expr
+ | cast_expr assignment_operator assignment_expr
{
switch ($2) {
$$ = newNode($2,$1,$3);
break;
case MUL_ASSIGN:
- $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('*',removePreIncDecOps(copyAst($1)),$3));
break;
case DIV_ASSIGN:
- $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('/',removePreIncDecOps(copyAst($1)),$3));
break;
case MOD_ASSIGN:
- $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('%',removePreIncDecOps(copyAst($1)),$3));
break;
case ADD_ASSIGN:
- $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('+',removePreIncDecOps(copyAst($1)),$3));
break;
case SUB_ASSIGN:
- $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('-',removePreIncDecOps(copyAst($1)),$3));
break;
case LEFT_ASSIGN:
- $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode(LEFT_OP,removePreIncDecOps(copyAst($1)),$3));
break;
case RIGHT_ASSIGN:
- $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode(RIGHT_OP,removePreIncDecOps(copyAst($1)),$3));
break;
case AND_ASSIGN:
- $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('&',removePreIncDecOps(copyAst($1)),$3));
break;
case XOR_ASSIGN:
- $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3));
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('^',removePreIncDecOps(copyAst($1)),$3));
break;
case OR_ASSIGN:
- $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3));
+ /* $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3)); */
+ $$ = newNode('=',removePostIncDecOps(copyAst($1)),
+ newNode('|',removePreIncDecOps(copyAst($1)),$3));
break;
default :
$$ = NULL;
expr
: assignment_expr
- | expr ',' assignment_expr { $$ = newNode(',',$1,$3);}
+ | expr ',' { seqPointNo++;} assignment_expr { $$ = newNode(',',$1,$4);}
;
constant_expr
;
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 */
addDecl (sym,0,lnk) ;
}
+ uselessDecl = TRUE;
$$ = sym1 ;
}
;
;
Interrupt_storage
- : INTERRUPT CONSTANT { $$ = (int) floatFromVal($2) ; }
+ : INTERRUPT { $$ = INTNO_UNSPEC ; }
+ | INTERRUPT CONSTANT
+ { int intno = (int) floatFromVal($2);
+ if ((intno >= 0) && (intno <= INTNO_MAX))
+ $$ = intno;
+ else
+ {
+ werror(E_INT_BAD_INTNO, intno);
+ $$ = INTNO_UNSPEC;
+ }
+ }
;
type_specifier
: type_specifier2
| type_specifier2 AT constant_expr
{
- /* add this to the storage class specifier */
+ /* 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)) ;
: CHAR {
$$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_CHAR ;
+ ignoreTypedefType = 1;
}
| SHORT {
$$=newLink(SPECIFIER);
$$->select.s._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._signed = 1;
+ ignoreTypedefType = 1;
}
| UNSIGNED {
$$=newLink(SPECIFIER);
SPEC_USIGN($$) = 1 ;
+ ignoreTypedefType = 1;
}
| VOID {
$$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_VOID ;
+ ignoreTypedefType = 1;
}
| CONST {
$$=newLink(SPECIFIER);
| FLOAT {
$$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_FLOAT;
+ ignoreTypedefType = 1;
}
| XDATA {
$$ = newLink (SPECIFIER);
SPEC_SCLS($$) = S_BIT ;
SPEC_BLEN($$) = 1;
SPEC_BSTR($$) = 0;
+ ignoreTypedefType = 1;
}
- | struct_or_union_specifier
+ | struct_or_union_specifier {
+ uselessDecl = FALSE;
+ $$ = $1 ;
+ ignoreTypedefType = 1;
+ }
| enum_specifier {
cenum = NULL ;
+ uselessDecl = FALSE;
+ ignoreTypedefType = 1;
$$ = $1 ;
}
| TYPE_NAME
sym = findSym(TypedefTab,NULL,$1) ;
$$ = p = copyLinkChain(sym->type);
SPEC_TYPEDEF(getSpec(p)) = 0;
+ ignoreTypedefType = 1;
}
| sfr_reg_bit
;
$$ = newLink(SPECIFIER) ;
SPEC_NOUN($$) = V_SBIT;
SPEC_SCLS($$) = S_SBIT;
+ SPEC_BLEN($$) = 1;
+ SPEC_BSTR($$) = 0;
+ ignoreTypedefType = 1;
+ }
+ | sfr_attributes
+ ;
+
+sfr_attributes
+ : SFR {
+ $$ = newLink(SPECIFIER) ;
+ FUNC_REGBANK($$) = 0;
+ SPEC_NOUN($$) = V_CHAR;
+ SPEC_SCLS($$) = S_SFR ;
+ SPEC_USIGN($$) = 1 ;
+ ignoreTypedefType = 1;
}
- | SFR {
+ | SFR BANKED {
$$ = newLink(SPECIFIER) ;
- SPEC_NOUN($$) = V_CHAR;
- SPEC_SCLS($$) = S_SFR ;
- SPEC_USIGN($$) = 1 ;
+ 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) ;
+ 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 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 ;
symbol *sym, *dsym;
- // check for duplicate structure members
- for (sym=$4; sym; sym=sym->next) {
+ // 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 (strcmp(sym->name, dsym->name)==0) {
- werror(E_DUPLICATE_MEMBER,
+ 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 ;
- sdef->fields = reverseSyms($4) ; /* link the fields */
+ sdef->fields = reverseSyms($5) ; /* link the fields */
sdef->size = compStructSize($1,sdef); /* update size of */
-
+ promoteAnonStructs ($1, sdef);
+
/* Create the 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");
+ }
}
;
/* add this type to all the symbols */
symbol *sym ;
for ( sym = $2 ; sym != NULL ; sym = sym->next ) {
+ sym_link *btype = copyLinkChain($1);
/* make the symbol one level up */
sym->level-- ;
- pointerTypes(sym->type,copyLinkChain($1));
+ pointerTypes(sym->type,btype);
if (!sym->type) {
- sym->type = copyLinkChain($1);
+ sym->type = btype;
sym->etype = getSpec(sym->type);
}
else
- addDecl (sym,0,copyLinkChain($1));
+ addDecl (sym,0,btype);
/* make sure the type is complete and sane */
checkTypeSanity(sym->etype, sym->name);
}
- $$ = $2;
+ ignoreTypedefType = 0;
+ $$ = $2;
}
;
struct_declarator
: declarator
- | ':' constant_expr {
+ | ':' constant_expr {
+ int bitsize;
$$ = newSymbol (genSymName(NestLevel),NestLevel) ;
- $$->bitVar = (int) floatFromVal(constExprValue($2,TRUE));
+ bitsize= (int) floatFromVal(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;
}
| declarator ':' constant_expr
- {
- $1->bitVar = (int) floatFromVal(constExprValue($3,TRUE));
+ {
+ int bitsize;
+ bitsize= (int) floatFromVal(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 '}' {
- symbol *sym, *dsym;
- char _error=0;
-
- // check for duplicate enums
- for (sym=$3; sym; sym=sym->next) {
- for (dsym=sym->next; dsym; dsym=dsym->next) {
- if (strcmp(sym->name, dsym->name)==0) {
- werror(E_DUPLICATE_MEMBER, "enum", sym->name);
- _error++;
- }
- }
- }
- if (_error==0) {
- $$ = copyLinkChain(cenum->type);
- } else {
- $$ = newIntLink();
- SPEC_NOUN($$)=0;
- }
+ $$ = newEnumType ($3); //copyLinkChain(cenum->type);
+ SPEC_SCLS(getSpec($$)) = 0;
}
| ENUM identifier '{' enumerator_list '}' {
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);
+ }
- $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);
+ enumtype = newEnumType ($4); //copyLinkChain(cenum->type);
+ SPEC_SCLS(getSpec(enumtype)) = 0;
+ $2->type = enumtype;
- addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
- //addSymChain ($4);
- //allocVariables (reverseSyms($4));
- $$ = copyLinkChain(cenum->type);
- 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 ;
$$ = newLink(SPECIFIER) ;
SPEC_NOUN($$) = V_INT ;
}
-
- SPEC_SCLS(getSpec($$)) = 0 ;
}
;
: enumerator
| enumerator_list ',' {
}
- | enumerator_list ',' enumerator {
- $3->next = $1 ;
- $$ = $3 ;
- }
+ | enumerator_list ',' enumerator
+ {
+ symbol *dsym;
+
+ for (dsym=$1; dsym; dsym=dsym->next)
+ {
+ if (strcmp($3->name, dsym->name)==0)
+ {
+ werrorfl($3->fileDef, $3->lineDef, E_DUPLICATE_MEMBER, "enum", $3->name);
+ werrorfl(dsym->fileDef, dsym->lineDef, E_PREVIOUS_DEF);
+ }
+ }
+
+ $3->next = $1 ;
+ $$ = $3 ;
+ }
;
enumerator
SPEC_ENUM($1->etype) = 1;
$$ = $1 ;
// do this now, so we can use it for the next enums in the list
- addSymChain($1);
+ addSymChain(&$1);
}
;
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) floatFromVal(val));
+ val = constVal(lbuff);
+ }
$$ = cenum = val ;
}
| {
;
declarator
+ : declarator3 { $$ = $1 ; }
+ | pointer declarator3
+ {
+ addDecl ($2,0,reverseLink($1));
+ $$ = $2 ;
+ }
+ ;
+
+declarator3
+ : declarator2_function_attributes { $$ = $1 ; }
+ | declarator2 { $$ = $1 ; }
+ ;
+
+function_declarator
: declarator2_function_attributes { $$ = $1; }
| pointer declarator2_function_attributes
{
$$ = $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));
-
- FUNC_ARGS(funcType)=args;
- FUNC_HASVARARGS(funcType)=hasVargs;
-
- // just to be sure
- memset (&$2->funcAttrs, 0,
- sizeof($2->funcAttrs));
-
- addDecl ($1,0,$2);
+ : 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 '[' ']'
+ | declarator3 '[' ']'
{
sym_link *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;
+ tval = constExprValue($3,TRUE);
/* if it is not a constant then Error */
- if ( SPEC_SCLS(p) != S_LITERAL)
+ 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. */
+ DCL_ELEM(p) = 1;
+ }
else {
- p = newLink (DECLARATOR);
- DCL_TYPE(p) = ARRAY ;
DCL_ELEM(p) = (int) floatFromVal(tval) ;
- addDecl($1,0,p);
}
+ 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 ')'
{
+ sym_link *funcType;
addDecl ($1,FUNCTION,NULL) ;
+
+ funcType = $1->type;
+ while (funcType && !IS_FUNC(funcType))
+ funcType = funcType->next;
- FUNC_HASVARARGS($1->type) = IS_VARG($4);
- FUNC_ARGS($1->type) = reverseVal($4);
+ 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_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)
+ 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 ;
}
;
-
+
pointer
: unqualified_pointer { $$ = $1 ;}
| unqualified_pointer type_specifier_list
{
- $$ = $1 ;
- DCL_TSPEC($1) = $2;
+ $$ = $1 ;
+ if (IS_SPEC($2)) {
+ DCL_TSPEC($1) = $2;
+ DCL_PTR_CONST($1) = SPEC_CONST($2);
+ DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
+ }
+ else
+ werror (W_PTR_TYPE_INVALID);
}
| unqualified_pointer pointer
{
DCL_TYPE($3) = POINTER ;
break;
case S_CODE:
- DCL_PTR_CONST($3) = 1;
DCL_TYPE($3) = CPOINTER ;
break;
case S_EEPROM:
;
parameter_list
- : parameter_declaration
+ : parameter_declaration
| parameter_list ',' parameter_declaration
{
$3->next = $1 ;
- $$ = $3 ;
+ $$ = $3 ;
}
;
pointerTypes($2->type,$1);
addDecl ($2,0,$1);
for (loop=$2;loop;loop->_isparm=1,loop=loop->next);
- addSymChain ($2);
+ addSymChain (&$2);
$$ = symbolVal($2);
+ ignoreTypedefType = 0;
}
| type_name {
$$ = newValue() ;
$$->type = $1;
$$->etype = getSpec($$->type);
+ ignoreTypedefType = 0;
}
;
type_name
- : type_specifier_list { $$ = $1 ;}
+ : type_specifier_list { $$ = $1; ignoreTypedefType = 0;}
| type_specifier_list abstract_declarator
{
/* go to the end of the list */
p->next = $1 ;
}
$$ = $2 ;
+ ignoreTypedefType = 0;
}
;
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
}
$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;
- if (!$1) {
- // ((void (code *) (void)) 0) ()
- $1=newLink(DECLARATOR);
- DCL_TYPE($1)=CPOINTER;
- $$ = $1;
- }
- $1->next=p;
- }
+
+ FUNC_HASVARARGS(p) = IS_VARG($4);
+ FUNC_ARGS(p) = reverseVal($4);
+
+ /* nest level was incremented to take care of the parms */
+ NestLevel-- ;
+ currBlockno--;
+ p->next = $1;
+ $$ = p;
+
+ // remove the symbol args (if any)
+ cleanUpLevel(SymbolTab,NestLevel+1);
}
;
| selection_statement
| iteration_statement
| jump_statement
+ | critical_statement
| INLINEASM ';' {
- ast *ex = newNode(INLINEASM,NULL,NULL);
+ 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
// : 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 ':' { $$ = 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); }
: start_block end_block { $$ = createBlock(NULL,NULL); }
| start_block statement_list end_block { $$ = createBlock(NULL,$2) ; }
| start_block
- declaration_list { addSymChain($2); }
+ declaration_list { addSymChain(&$2); }
end_block { $$ = createBlock($2,NULL) ; }
| start_block
- declaration_list { addSymChain ($2); }
+ declaration_list { addSymChain (&$2); }
statement_list
end_block {$$ = createBlock($2,$4) ; }
| error ';' { $$ = NULL ; }
}
else
$$ = $1 ;
+ ignoreTypedefType = 0;
}
| declaration_list declaration
else
$$ = $2 ;
}
+ ignoreTypedefType = 0;
}
;
expression_statement
: ';' { $$ = NULL;}
- | expr ';'
+ | expr ';' { $$ = $1; seqPointNo++;}
;
else_statement
selection_statement
- : IF '(' expr ')' statement else_statement { noLineno++ ; $$ = createIf ($3, $5, $6 ); noLineno--;}
+ : IF '(' expr ')' { seqPointNo++;} statement else_statement
+ {
+ noLineno++ ;
+ $$ = createIf ($3, $6, $7 );
+ noLineno--;
+ }
| SWITCH '(' expr ')' {
ast *ex ;
static int swLabel = 0 ;
+ seqPointNo++;
/* create a node for expression */
ex = newNode(SWITCH,$3,NULL);
STACK_PUSH(swStk,ex); /* save it in the stack */
;
iteration_statement
- : while '(' expr ')' statement
+ : while '(' expr ')' { seqPointNo++;} statement
{
noLineno++ ;
$$ = createWhile ( $1, STACK_POP(continueStack),
- STACK_POP(breakStack), $3, $5 );
+ STACK_POP(breakStack), $3, $6 );
$$->lineno = $1->lineDef ;
noLineno-- ;
}
| do statement WHILE '(' expr ')' ';'
{
+ seqPointNo++;
noLineno++ ;
$$ = createDo ( $1 , STACK_POP(continueStack),
STACK_POP(breakStack), $5, $2);
;
expr_opt
- : { $$ = NULL ; }
- | expr
+ : { $$ = NULL ; seqPointNo++; }
+ | expr { $$ = $1 ; seqPointNo++; }
;
jump_statement
}
| CONTINUE ';' {
/* make sure continue is in context */
- if (STACK_PEEK(continueStack) == NULL) {
+ if (STACK_EMPTY(continueStack) || STACK_PEEK(continueStack) == NULL) {
werror(E_BREAK_CONTEXT);
$$ = NULL;
}
}
}
| BREAK ';' {
- if (STACK_PEEK(breakStack) == NULL) {
+ if (STACK_EMPTY(breakStack) || STACK_PEEK(breakStack) == NULL) {
werror(E_BREAK_CONTEXT);
$$ = NULL;
} else {
STACK_PEEK(breakStack)->isref = 1;
}
}
- | RETURN ';' { $$ = newNode(RETURN,NULL,NULL) ; }
- | RETURN expr ';' { $$ = newNode(RETURN,NULL,$2) ; }
+ | 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);
+ }
+ }
;
identifier