int reentrant = 0 ;
int blockNo = 0 ; /* sequential block number */
int currBlockno=0 ;
+int inCritical= 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;
%}
%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 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
%type <yyint> Interrupt_storage
%type <sym> identifier declarator declarator2 enumerator_list enumerator
%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 <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
$$ = 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;
;
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
| CODE {
$$ = newLink (SPECIFIER) ;
SPEC_SCLS($$) = S_CODE ;
- if (port->mem.code_ro) {
- SPEC_CONST($$) = 1;
- }
}
| EEPROM {
$$ = newLink (SPECIFIER) ;
SPEC_BSTR($$) = 0;
}
- | struct_or_union_specifier
+ | struct_or_union_specifier {
+ uselessDecl = FALSE;
+ $$ = $1 ;
+ }
| enum_specifier {
cenum = NULL ;
+ uselessDecl = FALSE;
$$ = $1 ;
}
| TYPE_NAME
: 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 */
: 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;
}
;
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;
}
;
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(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
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);
+ if ((! $1) || (! IS_FUNC($1->etype)))
+ {
+ // function_attribute is only allowed if declarator2 was
+ // an actual function
+ werror(E_FUNC_ATTR);
+ $$=$1;
+ }
+ else
+ {
+ // 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);
+ }
}
;
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 ')'
{
$$ = $1 ;
DCL_TSPEC($1) = $2;
+ DCL_PTR_CONST($1) = SPEC_CONST($2);
+ DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
}
| unqualified_pointer pointer
{
DCL_TYPE($3) = POINTER ;
break;
case S_CODE:
- DCL_PTR_CONST($3) = 1;
DCL_TYPE($3) = CPOINTER ;
break;
case S_EEPROM:
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);
ex->values.inlineasm = strdup($1);
}
;
+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); }
STACK_PEEK(breakStack)->isref = 1;
}
}
- | RETURN ';' { $$ = newNode(RETURN,NULL,NULL) ; }
- | RETURN expr ';' { $$ = newNode(RETURN,NULL,$2) ; }
+ | RETURN ';' {
+ if (inCritical) {
+ werror(E_INVALID_CRITICAL);
+ $$ = NULL;
+ } else {
+ $$ = newNode(RETURN,NULL,NULL);
+ }
+ }
+ | RETURN expr ';' {
+ if (inCritical) {
+ werror(E_INVALID_CRITICAL);
+ $$ = NULL;
+ } else {
+ $$ = newNode(RETURN,NULL,$2);
+ }
+ }
;
identifier