#include "port.h"
#include "newalloc.h"
#include "SDCCerr.h"
+#include "SDCCutil.h"
extern int yyerror (char *);
extern FILE *yyin;
%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 NAKED
+%token NAKED JAVANATIVE OVERLAY
%token <yyinline> INLINEASM
%token IFX ADDRESS_OF GET_VALUE_AT_ADDRESS SPIL UNSPIL GETHBIT
%token BITWISEAND UNARYMINUS IPUSH IPOP PCALL ENDFUNCTION JUMPTABLE
function_attributes
: USING CONSTANT {
- $$ = newLink() ;
- $$->class = SPECIFIER ;
+ $$ = newLink(SPECIFIER) ;
FUNC_REGBANK($$) = (int) floatFromVal($2);
}
- | REENTRANT { $$ = newLink ();
- $$->class = SPECIFIER ;
+ | REENTRANT { $$ = newLink (SPECIFIER);
FUNC_ISREENT($$)=1;
}
- | CRITICAL { $$ = newLink ();
- $$->class = SPECIFIER ;
+ | CRITICAL { $$ = newLink (SPECIFIER);
FUNC_ISCRITICAL($$) = 1;
}
- | NAKED { $$ = newLink ();
- $$->class = SPECIFIER ;
+ | NAKED { $$ = newLink (SPECIFIER);
FUNC_ISNAKED($$)=1;
}
- | NONBANKED {$$ = newLink ();
- $$->class = SPECIFIER ;
+ | JAVANATIVE { $$ = newLink (SPECIFIER);
+ FUNC_ISJAVANATIVE($$)=1;
+ }
+ | OVERLAY { $$ = newLink (SPECIFIER);
+ FUNC_ISOVERLAY($$)=1;
+ }
+ | NONBANKED {$$ = newLink (SPECIFIER);
FUNC_NONBANKED($$) = 1;
if (FUNC_BANKED($$)) {
werror(W_BANKED_WITH_NONBANKED);
}
}
- | BANKED {$$ = newLink ();
- $$->class = SPECIFIER ;
+ | BANKED {$$ = newLink (SPECIFIER);
FUNC_BANKED($$) = 1;
if (FUNC_NONBANKED($$)) {
werror(W_BANKED_WITH_NONBANKED);
}
| Interrupt_storage
{
- $$ = newLink () ;
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER) ;
FUNC_INTNO($$) = $1 ;
FUNC_ISISR($$) = 1;
}
$$ = newNode($2,$1,$3);
break;
case MUL_ASSIGN:
- $$ = newNode('=',$1,newNode('*',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('*',removeIncDecOps(copyAst($1)),$3));
break;
case DIV_ASSIGN:
- $$ = newNode('=',$1,newNode('/',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('/',removeIncDecOps(copyAst($1)),$3));
break;
case MOD_ASSIGN:
- $$ = newNode('=',$1,newNode('%',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('%',removeIncDecOps(copyAst($1)),$3));
break;
case ADD_ASSIGN:
- $$ = newNode('=',$1,newNode('+',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('+',removeIncDecOps(copyAst($1)),$3));
break;
case SUB_ASSIGN:
- $$ = newNode('=',$1,newNode('-',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('-',removeIncDecOps(copyAst($1)),$3));
break;
case LEFT_ASSIGN:
- $$ = newNode('=',$1,newNode(LEFT_OP,copyAst($1),$3));
+ $$ = newNode('=',$1,newNode(LEFT_OP,removeIncDecOps(copyAst($1)),$3));
break;
case RIGHT_ASSIGN:
- $$ = newNode('=',$1,newNode(RIGHT_OP,copyAst($1),$3));
+ $$ = newNode('=',$1,newNode(RIGHT_OP,removeIncDecOps(copyAst($1)),$3));
break;
case AND_ASSIGN:
- $$ = newNode('=',$1,newNode('&',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('&',removeIncDecOps(copyAst($1)),$3));
break;
case XOR_ASSIGN:
- $$ = newNode('=',$1,newNode('^',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('^',removeIncDecOps(copyAst($1)),$3));
break;
case OR_ASSIGN:
- $$ = newNode('=',$1,newNode('|',copyAst($1),$3));
+ $$ = newNode('=',$1,newNode('|',removeIncDecOps(copyAst($1)),$3));
break;
default :
$$ = NULL;
sym_link *lnk = $2 ;
while (lnk && !IS_SPEC(lnk->next))
lnk = lnk->next;
- lnk->next = mergeSpec($1,lnk->next, yytext);
+ lnk->next = mergeSpec($1,lnk->next, "storage_class_specifier declaration_specifiers - skipped");
$$ = $2 ;
}
else
- $$ = mergeSpec($1,$2, yytext);
+ $$ = mergeSpec($1,$2, "storage_class_specifier declaration_specifiers");
}
| type_specifier { $$ = $1; }
| type_specifier declaration_specifiers {
sym_link *lnk = $2 ;
while (lnk && !IS_SPEC(lnk->next))
lnk = lnk->next;
- lnk->next = mergeSpec($1,lnk->next, yytext);
+ lnk->next = mergeSpec($1,lnk->next, "type_specifier declaration_specifiers - skipped");
$$ = $2 ;
}
else
- $$ = mergeSpec($1,$2, yytext);
+ $$ = mergeSpec($1,$2, "type_specifier declaration_specifiers");
}
;
storage_class_specifier
: TYPEDEF {
- $$ = newLink () ;
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER) ;
SPEC_TYPEDEF($$) = 1 ;
}
| EXTERN {
- $$ = newLink();
- $$->class = SPECIFIER ;
+ $$ = newLink(SPECIFIER);
SPEC_EXTR($$) = 1 ;
}
| STATIC {
- $$ = newLink ();
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER);
SPEC_STAT($$) = 1 ;
}
| AUTO {
- $$ = newLink () ;
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER) ;
SPEC_SCLS($$) = S_AUTO ;
}
| REGISTER {
- $$ = newLink ();
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER);
SPEC_SCLS($$) = S_REGISTER ;
}
;
type_specifier2
: CHAR {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_CHAR ;
}
| SHORT {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
$$->select.s._short = 1 ;
}
| INT {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_INT ;
}
| LONG {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_LONG($$) = 1 ;
}
| SIGNED {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
$$->select.s._signed = 1;
}
| UNSIGNED {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_USIGN($$) = 1 ;
}
| VOID {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_VOID ;
}
| CONST {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_CONST($$) = 1;
}
| VOLATILE {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_VOLATILE($$) = 1 ;
}
| FLOAT {
- $$=newLink();
+ $$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_FLOAT;
- $$->class = SPECIFIER ;
}
| XDATA {
- $$ = newLink ();
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER);
SPEC_SCLS($$) = S_XDATA ;
}
| CODE {
- $$ = newLink () ;
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER) ;
SPEC_SCLS($$) = S_CODE ;
}
| EEPROM {
- $$ = newLink () ;
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER) ;
SPEC_SCLS($$) = S_EEPROM ;
}
| DATA {
- $$ = newLink ();
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER);
SPEC_SCLS($$) = S_DATA ;
}
| IDATA {
- $$ = newLink ();
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER);
SPEC_SCLS($$) = S_IDATA ;
}
| PDATA {
- $$ = newLink ();
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER);
SPEC_SCLS($$) = S_PDATA ;
}
| BIT {
- $$=newLink();
- $$->class = SPECIFIER ;
+ $$=newLink(SPECIFIER);
SPEC_NOUN($$) = V_BIT ;
SPEC_SCLS($$) = S_BIT ;
SPEC_BLEN($$) = 1;
sfr_reg_bit
: SBIT {
- $$ = newLink() ;
- $$->class = SPECIFIER ;
+ $$ = newLink(SPECIFIER) ;
SPEC_NOUN($$) = V_SBIT;
SPEC_SCLS($$) = S_SBIT;
}
| SFR {
- $$ = newLink() ;
- $$->class = SPECIFIER ;
+ $$ = newLink(SPECIFIER) ;
SPEC_NOUN($$) = V_CHAR;
SPEC_SCLS($$) = S_SFR ;
SPEC_USIGN($$) = 1 ;
: struct_or_union opt_stag '{' struct_declaration_list '}'
{
structdef *sdef ;
+ symbol *sym, *dsym;
+
+ // check for duplicate structure members
+ for (sym=$4; sym; sym=sym->next) {
+ for (dsym=sym->next; dsym; dsym=dsym->next) {
+ if (strcmp(sym->name, dsym->name)==0) {
+ werror(E_DUPLICATE_MEMBER,
+ $1==STRUCT ? "struct" : "union", sym->name);
+ }
+ }
+ }
- /* Create a structdef */
+ /* Create a structdef */
sdef = $2 ;
sdef->fields = reverseSyms($4) ; /* link the fields */
sdef->size = compStructSize($1,sdef); /* update size of */
/* Create the specifier */
- $$ = newLink () ;
- $$->class = SPECIFIER ;
+ $$ = newLink (SPECIFIER) ;
SPEC_NOUN($$) = V_STRUCT;
SPEC_STRUCT($$)= sdef ;
}
| struct_or_union stag
{
- $$ = newLink() ;
- $$->class = SPECIFIER ;
+ $$ = newLink(SPECIFIER) ;
SPEC_NOUN($$) = V_STRUCT;
SPEC_STRUCT($$) = $2 ;
}
: 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 ;
+
$$ = $2;
}
;
sym->etype = getSpec(sym->type);
}
else
- addDecl (sym,0,cloneSpec($1));
+ addDecl (sym,0,copyLinkChain($1));
/* make sure the type is complete and sane */
checkTypeSanity(sym->etype, sym->name);
}
enum_specifier
: ENUM '{' enumerator_list '}' {
- addSymChain ($3);
- allocVariables(reverseSyms($3)) ;
- $$ = copyLinkChain(cenum->type);
- }
+ 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;
+ }
+ }
+
| 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 ;
- }
+ 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 ;
-
- /* check the enumerator table */
- if ((csym = findSym(enumTab,$2,$2->name)))
- $$ = copyLinkChain(csym->type);
- else {
- $$ = newLink() ;
- $$->class = SPECIFIER ;
- SPEC_NOUN($$) = V_INT ;
- }
-
- SPEC_SCLS(getSpec($$)) = 0 ;
- }
+ symbol *csym ;
+
+ /* check the enumerator table */
+ if ((csym = findSym(enumTab,$2,$2->name)))
+ $$ = copyLinkChain(csym->type);
+ else {
+ $$ = newLink(SPECIFIER) ;
+ SPEC_NOUN($$) = V_INT ;
+ }
+
+ SPEC_SCLS(getSpec($$)) = 0 ;
+ }
;
enumerator_list
;
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 ;
-
- }
+ : 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);
+ }
;
opt_assign_expr
}
| {
if (cenum) {
- sprintf(lbuff,"%d",(int) floatFromVal(cenum)+1);
+ SNPRINTF(lbuff, sizeof(lbuff),
+ "%d",(int) floatFromVal(cenum)+1);
$$ = cenum = constVal(lbuff);
}
else {
- sprintf(lbuff,"%d",0);
+ SNPRINTF(lbuff, sizeof(lbuff),
+ "%d",0);
$$ = cenum = constVal(lbuff);
}
}
{
sym_link *p;
- p = newLink ();
+ p = newLink (DECLARATOR);
DCL_TYPE(p) = ARRAY ;
DCL_ELEM(p) = 0 ;
addDecl($1,0,p);
if ( SPEC_SCLS(p) != S_LITERAL)
werror(E_CONST_EXPECTED) ;
else {
- p = newLink ();
+ p = newLink (DECLARATOR);
DCL_TYPE(p) = ARRAY ;
DCL_ELEM(p) = (int) floatFromVal(tval) ;
addDecl($1,0,p);
{
$$ = $1 ;
$$->next = $2 ;
- DCL_TYPE($2)=GPOINTER;
+ DCL_TYPE($2)=port->unqualified_pointer;
}
| unqualified_pointer type_specifier_list pointer
{
default:
// this could be just "constant"
// werror(W_PTR_TYPE_INVALID);
+ ;
}
}
else
unqualified_pointer
: '*'
{
- $$ = newLink();
+ $$ = newLink(DECLARATOR);
DCL_TYPE($$)=UPOINTER;
}
;
sym_link *lnk = $2 ;
while (lnk && !IS_SPEC(lnk->next))
lnk = lnk->next;
- lnk->next = mergeSpec($1,lnk->next, "type_specifier_list");
+ lnk->next = mergeSpec($1,lnk->next, "type_specifier_list type_specifier skipped");
$$ = $2 ;
}
else
- $$ = mergeSpec($1,$2, "type_specifier_list");
+ $$ = mergeSpec($1,$2, "type_specifier_list type_specifier");
}
;
/* go to the end of the list */
sym_link *p;
pointerTypes($2,$1);
- for ( p = $2 ; p->next ; p=p->next);
- p->next = $1 ;
- $$ = $2 ;
+ for ( p = $2 ; p && p->next ; p=p->next);
+ if (!p) {
+ werror(E_SYNTAX_ERROR, yytext);
+ } else {
+ p->next = $1 ;
+ }
+ $$ = $2 ;
}
;
abstract_declarator2
: '(' abstract_declarator ')' { $$ = $2 ; }
| '[' ']' {
- $$ = newLink ();
+ $$ = newLink (DECLARATOR);
DCL_TYPE($$) = ARRAY ;
DCL_ELEM($$) = 0 ;
}
| '[' constant_expr ']' {
value *val ;
- $$ = newLink ();
+ $$ = newLink (DECLARATOR);
DCL_TYPE($$) = ARRAY ;
DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($2,TRUE));
}
| abstract_declarator2 '[' ']' {
- $$ = newLink ();
+ $$ = newLink (DECLARATOR);
DCL_TYPE($$) = ARRAY ;
DCL_ELEM($$) = 0 ;
$$->next = $1 ;
| abstract_declarator2 '[' constant_expr ']'
{
value *val ;
- $$ = newLink ();
+ $$ = newLink (DECLARATOR);
DCL_TYPE($$) = ARRAY ;
DCL_ELEM($$) = (int) floatFromVal(val = constExprValue($3,TRUE));
$$->next = $1 ;
| '(' parameter_type_list ')' { $$ = NULL;}
| abstract_declarator2 '(' ')' {
// $1 must be a pointer to a function
- sym_link *p=newLink();
+ sym_link *p=newLink(DECLARATOR);
DCL_TYPE(p) = FUNCTION;
+ if (!$1) {
+ // ((void (code *) ()) 0) ()
+ $1=newLink(DECLARATOR);
+ DCL_TYPE($1)=CPOINTER;
+ $$ = $1;
+ }
$1->next=p;
}
| abstract_declarator2 '(' parameter_type_list ')' {
- if (!IS_VOID($3->type)) {
+ 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
- sym_link *p=newLink();
+ 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;
}
}
+ ;
initializer
: assignment_expr { $$ = newiList(INIT_NODE,$1); }
| jump_statement
| INLINEASM ';' {
ast *ex = newNode(INLINEASM,NULL,NULL);
- ex->values.inlineasm = malloc(strlen($1)+1);
- strcpy(ex->values.inlineasm,$1);
+ ex->values.inlineasm = strdup($1);
$$ = ex;
}
;
ex->values.switchVals.swNum = swLabel ;
/* now create the label */
- sprintf(lbuff,"_swBrk_%d",swLabel++);
+ SNPRINTF(lbuff, sizeof(lbuff),
+ "_swBrk_%d",swLabel++);
$<sym>$ = newSymbol(lbuff,NestLevel);
/* put label in the break stack */
STACK_PUSH(breakStack,$<sym>$);
while : WHILE { /* create and push the continue , break & body labels */
static int Lblnum = 0 ;
/* continue */
- sprintf (lbuff,"_whilecontinue_%d",Lblnum);
+ SNPRINTF (lbuff, sizeof(lbuff), "_whilecontinue_%d",Lblnum);
STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
/* break */
- sprintf (lbuff,"_whilebreak_%d",Lblnum);
+ SNPRINTF (lbuff, sizeof(lbuff), "_whilebreak_%d",Lblnum);
STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
/* body */
- sprintf (lbuff,"_whilebody_%d",Lblnum++);
+ SNPRINTF (lbuff, sizeof(lbuff), "_whilebody_%d",Lblnum++);
$$ = newSymbol(lbuff,NestLevel);
}
+ ;
do : DO { /* create and push the continue , break & body Labels */
static int Lblnum = 0 ;
/* continue */
- sprintf(lbuff,"_docontinue_%d",Lblnum);
+ SNPRINTF(lbuff, sizeof(lbuff), "_docontinue_%d",Lblnum);
STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
/* break */
- sprintf (lbuff,"_dobreak_%d",Lblnum);
+ SNPRINTF(lbuff, sizeof(lbuff), "_dobreak_%d",Lblnum);
STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
/* do body */
- sprintf (lbuff,"_dobody_%d",Lblnum++);
+ SNPRINTF(lbuff, sizeof(lbuff), "_dobody_%d",Lblnum++);
$$ = newSymbol (lbuff,NestLevel);
}
+ ;
+
for : FOR { /* create & push continue, break & body labels */
static int Lblnum = 0 ;
/* continue */
- sprintf (lbuff,"_forcontinue_%d",Lblnum);
+ SNPRINTF(lbuff, sizeof(lbuff), "_forcontinue_%d",Lblnum);
STACK_PUSH(continueStack,newSymbol(lbuff,NestLevel));
/* break */
- sprintf (lbuff,"_forbreak_%d",Lblnum);
+ SNPRINTF(lbuff, sizeof(lbuff), "_forbreak_%d",Lblnum);
STACK_PUSH(breakStack,newSymbol(lbuff,NestLevel));
/* body */
- sprintf (lbuff,"_forbody_%d",Lblnum);
+ SNPRINTF(lbuff, sizeof(lbuff), "_forbody_%d",Lblnum);
$$ = newSymbol(lbuff,NestLevel);
/* condition */
- sprintf (lbuff,"_forcond_%d",Lblnum++);
+ SNPRINTF(lbuff, sizeof(lbuff), "_forcond_%d",Lblnum++);
STACK_PUSH(forStack,newSymbol(lbuff,NestLevel));
}
+ ;
iteration_statement
: while '(' expr ')' statement