#include "port.h"
#include "newalloc.h"
#include "SDCCerr.h"
+#include "SDCCutil.h"
extern int yyerror (char *);
extern FILE *yyin;
%token <yychar> IDENTIFIER TYPE_NAME
%token <val> CONSTANT STRING_LITERAL
-%token SIZEOF
+%token SIZEOF TYPEOF
%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 <yyint> MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN
%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
%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_using_reentrant while do for
+%type <sym> declarator2_function_attributes while do for
%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> using_reentrant using_reentrant_interrupt enum_specifier
+%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 <sdef> stag opt_stag
;
external_definition
- : function_definition { blockNo=0;}
+ : function_definition {
+ blockNo=0;
+ }
| declaration {
if ($1 && $1->type
&& IS_FUNC($1->type))
}
;
-using_reentrant
- : using_reentrant_interrupt
- | using_reentrant_interrupt using_reentrant { $$ = mergeSpec($1,$2,"using_reentrant"); }
+function_attribute
+ : function_attributes
+ | function_attributes function_attribute { $$ = mergeSpec($1,$2,"function_attribute"); }
;
-using_reentrant_interrupt
+function_attributes
: USING CONSTANT {
$$ = newLink() ;
$$->class = SPECIFIER ;
- SPEC_BNKF($$) = 1;
- SPEC_BANK($$) = (int) floatFromVal($2);
+ FUNC_REGBANK($$) = (int) floatFromVal($2);
}
| REENTRANT { $$ = newLink ();
$$->class = SPECIFIER ;
- SPEC_RENT($$) = 1;
+ FUNC_ISREENT($$)=1;
}
| CRITICAL { $$ = newLink ();
$$->class = SPECIFIER ;
- SPEC_CRTCL($$) = 1;
+ FUNC_ISCRITICAL($$) = 1;
}
| NAKED { $$ = newLink ();
$$->class = SPECIFIER ;
- SPEC_NAKED($$) = 1;
+ FUNC_ISNAKED($$)=1;
+ }
+ | JAVANATIVE { $$ = newLink ();
+ $$->class = SPECIFIER ;
+ FUNC_ISJAVANATIVE($$)=1;
+ }
+ | OVERLAY { $$ = newLink ();
+ $$->class = SPECIFIER ;
+ FUNC_ISOVERLAY($$)=1;
}
| NONBANKED {$$ = newLink ();
$$->class = SPECIFIER ;
- SPEC_NONBANKED($$) = 1;
- if (SPEC_BANKED($$)) {
+ FUNC_NONBANKED($$) = 1;
+ if (FUNC_BANKED($$)) {
werror(W_BANKED_WITH_NONBANKED);
}
}
| BANKED {$$ = newLink ();
$$->class = SPECIFIER ;
- SPEC_BANKED($$) = 1;
- if (SPEC_NONBANKED($$)) {
+ FUNC_BANKED($$) = 1;
+ if (FUNC_NONBANKED($$)) {
werror(W_BANKED_WITH_NONBANKED);
}
if (SPEC_STAT($$)) {
{
$$ = newLink () ;
$$->class = SPECIFIER ;
- SPEC_INTN($$) = $1 ;
- SPEC_INTRTN($$) = 1;
+ FUNC_INTNO($$) = $1 ;
+ FUNC_ISISR($$) = 1;
}
;
| unary_operator cast_expr { $$ = newNode($1,$2,NULL) ; }
| SIZEOF unary_expr { $$ = newNode(SIZEOF,NULL,$2); }
| SIZEOF '(' type_name ')' { $$ = newAst_VALUE(sizeofOp($3)); }
+ | TYPEOF unary_expr { $$ = newNode(TYPEOF,NULL,$2); }
;
unary_operator
$$ = 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;
enum_specifier
: ENUM '{' enumerator_list '}' {
- addSymChain ($3);
- allocVariables(reverseSyms($3)) ;
+ //addSymChain ($3);
+ //allocVariables(reverseSyms($3)) ;
$$ = copyLinkChain(cenum->type);
}
| ENUM identifier '{' enumerator_list '}' {
werror(E_DUPLICATE_TYPEDEF,csym->name);
addSym ( enumTab,$2,$2->name,$2->level,$2->block, 0);
- addSymChain ($4);
- allocVariables (reverseSyms($4));
+ //addSymChain ($4);
+ //allocVariables (reverseSyms($4));
$$ = copyLinkChain(cenum->type);
SPEC_SCLS(getSpec($$)) = 0 ;
}
;
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);
}
}
;
declarator
- : declarator2_using_reentrant { $$ = $1; }
- | pointer declarator2_using_reentrant
+ : declarator2_function_attributes { $$ = $1; }
+ | pointer declarator2_function_attributes
{
addDecl ($2,0,reverseLink($1));
$$ = $2 ;
}
;
-declarator2_using_reentrant
+declarator2_function_attributes
: declarator2 { $$ = $1 ; }
- | declarator2 using_reentrant { addDecl ($1,0,$2); }
+ | 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);
+ }
;
declarator2
addDecl ($1,FUNCTION,NULL) ;
- $1->hasVargs = IS_VARG($4);
- $1->args = reverseVal($4) ;
-
+ 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, remove the symbol args
- // (if any)
- if (IS_PTR($1->type) && IS_FUNC($1->etype)) {
+ // 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);
- /* fprintf (stderr, "Removed parm symbols of %s in line %d\n",
- $1->name, yylineno); */
}
$$ = $1;
{
$$ = $1 ;
$$->next = $2 ;
- DCL_TYPE($2)=GPOINTER;
+ DCL_TYPE($2)=port->unqualified_pointer;
}
| unqualified_pointer type_specifier_list pointer
{
DCL_TYPE($3) = EEPPOINTER;
break;
default:
- werror(W_PTR_TYPE_INVALID);
+ // this could be just "constant"
+ // werror(W_PTR_TYPE_INVALID);
+ ;
}
}
else
type_specifier_list
: type_specifier
- | type_specifier_list type_specifier { $$ = mergeSpec ($1,$2, "type_specifier_list"); }
+ //| type_specifier_list type_specifier { $$ = mergeSpec ($1,$2, "type_specifier_list"); }
+ | type_specifier_list type_specifier {
+ /* 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, "type_specifier_list");
+ $$ = $2 ;
+ }
+ else
+ $$ = mergeSpec($1,$2, "type_specifier_list");
+ }
;
parameter_identifier_list
/* 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 ;
}
;
// $1 must be a pointer to a function
sym_link *p=newLink();
DCL_TYPE(p) = FUNCTION;
+ if (!$1) {
+ // ((void (code *) ()) 0) ()
+ $1=newLink();
+ DCL_TYPE($1)=CPOINTER;
+ $$ = $1;
+ }
$1->next=p;
}
| abstract_declarator2 '(' parameter_type_list ')' {
// $1 must be a pointer to a function
sym_link *p=newLink();
DCL_TYPE(p) = FUNCTION;
+ if (!$1) {
+ // ((void (code *) (void)) 0) ()
+ $1=newLink();
+ 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