diff --git a/source/compiler/sc.h b/source/compiler/sc.h index a5378fa..89e08ed 100644 --- a/source/compiler/sc.h +++ b/source/compiler/sc.h @@ -870,17 +870,16 @@ SC_VDECL FILE *outf; /* file written to */ SC_VDECL jmp_buf errbuf; /* target of longjmp() on a fatal error */ -/* Possible entries for "emit_parsing_mode" - * Bits: 0 (epmACTIVE) 'emit'/'__emit' parsing is active - * 1 (epmBLOCK) multiline ('{}' block) syntax - * 2 (epmEXPR) used within an expression - * 3 (epmGLOBAL) used outside of function +/* Possible entries for "emit_flags" + * Bits: 0 (epmBLOCK) multiline ('{}' block) syntax + * 1 (epmEXPR) used within an expression + * 2 (epmGLOBAL) used outside of a function */ -#define epmACTIVE 1 -#define epmBLOCK 2 -#define epmEXPR 4 -#define epmGLOBAL 8 -SC_VDECL int emit_parsing_mode; +#define efBLOCK 1 +#define efEXPR 2 +#define efGLOBAL 4 +SC_VDECL int emit_flags; +SC_VDECL int emit_stgbuf_idx; #if !defined SC_LIGHT SC_VDECL int sc_makereport; /* generate a cross-reference report */ diff --git a/source/compiler/sc1.c b/source/compiler/sc1.c index 2bd62f4..545725b 100644 --- a/source/compiler/sc1.c +++ b/source/compiler/sc1.c @@ -895,7 +895,8 @@ static void resetglobals(void) sc_curstates=0; pc_memflags=0; pc_naked=FALSE; - emit_parsing_mode=0; + emit_flags=0; + emit_stgbuf_idx=-1; } static void initglobals(void) @@ -1652,10 +1653,11 @@ static void parse(void) break; case tEMIT: case t__EMIT: - emit_parsing_mode |= epmGLOBAL; + emit_flags |= efGLOBAL; lex(&val,&str); emit_parse_line(); - emit_parsing_mode &= ~epmGLOBAL; + needtoken(';'); + emit_flags &= ~efGLOBAL; break; case tNEW: if (getclassspec(tok,&fpublic,&fstatic,&fstock,&fconst)) @@ -5100,11 +5102,10 @@ static void statement(int *lastindent,int allow_decl) errorset(sRESET,0); tok=lex(&val,&st); - if (tok==tEMIT || tok==t__EMIT) { - doemit(); - return; - } else if ((emit_parsing_mode & epmBLOCK)!=0) { + if ((emit_flags & efBLOCK)!=0) { emit_parse_line(); + if (matchtoken('}')) + emit_flags &= ~efBLOCK; return; } /* if */ if (tok!='{') { @@ -5213,6 +5214,21 @@ static void statement(int *lastindent,int allow_decl) matchtoken(tSTATIC); decl_enum(sLOCAL,FALSE); break; + case tEMIT: + case t__EMIT: { + extern char *sc_tokens[]; + const char *bck_lptr=lptr-strlen(sc_tokens[tok-tFIRST]); + if (matchtoken('{')) { + lexpush(); + emit_flags |= efBLOCK; + lastst=tEMIT; + break; + } /* if */ + lptr=bck_lptr; + lexclr(FALSE); + tok=lex(&val,&st); + } /* case */ + /* drop through */ default: /* non-empty expression */ sc_allowproccall=optproccall; lexpush(); /* analyze token later */ @@ -5908,7 +5924,7 @@ fetchtok: *p=(neg!=FALSE) ? -sym->addr : sym->addr; break; case '(': - if ((emit_parsing_mode & epmEXPR)==0) + if ((emit_flags & efEXPR)==0) stgset(TRUE); stgget(&index,&cidx); errorset(sEXPRMARK,0); @@ -5917,7 +5933,7 @@ fetchtok: error(8); /* must be constant expression */ errorset(sEXPRRELEASE,0); stgdel(index,cidx); - if ((emit_parsing_mode & epmEXPR)==0) + if ((emit_flags & efEXPR)==0) stgset(FALSE); needtoken(')'); *p=(neg!=FALSE) ? -val : val; @@ -6641,13 +6657,6 @@ SC_FUNC void emit_parse_line(void) symbol *sym; char name[MAX_INSTR_LEN]; extern char *sc_tokens[]; - - /* write the staging buffer to the output file so instructions - * generated by the `emit`/`__emit` operator could be written - * separately without getting altered by the optimizer - */ - stgout(0); - emit_parsing_mode |= epmACTIVE; tok=tokeninfo(&val,&st); if (tok==tSYMBOL || (tok>tMIDDLE && tok<=tLAST)) { @@ -6670,21 +6679,9 @@ SC_FUNC void emit_parse_line(void) if (emit_opcodelist[i].name==NULL && *name!='\0') error(104,name); /* invalid assembler instruction */ emit_opcodelist[i].func(name); - - if ((emit_parsing_mode & epmEXPR)==0) { - /* make sure the string only contains whitespaces - * and/or an optional trailing '}' or ';' - */ - while (*lptr<=' ' && *lptr!='\0') - lptr++; - if (*lptr!='\0' && *lptr!='}' && (*lptr!=';' || (emit_parsing_mode & epmBLOCK)!=0)) - error(38); /* extra characters on line */ - } /* if */ } else if (tok==tLABEL) { - if ((emit_parsing_mode & epmEXPR)!=0) { + if ((emit_flags & (efEXPR | efGLOBAL))!=0) { error(29); /* invalid expression, assumed zero */ - } else if ((emit_parsing_mode & epmGLOBAL)!=0) { - error(11); /* invalid outside functions */ } else if (find_constval(&tagname_tab,st,0)!=NULL) { error(221,st); /* label name shadows tagname */ } else { @@ -6695,29 +6692,16 @@ SC_FUNC void emit_parse_line(void) sym->usage|=uDEFINE; } /* if */ } /* if */ - if ((emit_parsing_mode & epmBLOCK)!=0) { - if (matchtoken('}')) - emit_parsing_mode &= ~epmBLOCK; - } else if ((emit_parsing_mode & epmEXPR)==0) { - matchtoken(';'); - } /* if */ - /* write the staging buffer again */ - stgout(0); - emit_parsing_mode &= ~epmACTIVE; -} - -static void doemit(void) -{ - cell val; - char *st; - - if (matchtoken('{')) { - lexpush(); - emit_parsing_mode |= epmBLOCK; - } else { - lex(&val,&st); - emit_parse_line(); + if ((emit_flags & (efEXPR | efGLOBAL))==0) { + assert((emit_flags & efBLOCK)!=0); + /* make sure the string only contains whitespaces + * and an optional trailing '}' + */ + while (*lptr<=' ' && *lptr!='\0') + lptr++; + if (*lptr!='\0' && *lptr!='}') + error(38); /* extra characters on line */ } /* if */ } diff --git a/source/compiler/sc3.c b/source/compiler/sc3.c index 9aff411..2216597 100644 --- a/source/compiler/sc3.c +++ b/source/compiler/sc3.c @@ -1452,11 +1452,19 @@ static int hier2(value *lval) case t__EMIT: { cell val; char* st; - emit_parsing_mode |= epmEXPR; - lex(&val,&st); - emit_parse_line(); - emit_parsing_mode &= ~epmEXPR; + int block_syntax=matchtoken('('); + emit_flags |= efEXPR; + if (emit_stgbuf_idx==-1) + emit_stgbuf_idx=stgidx; + do { + lex(&val,&st); + emit_parse_line(); + } while ((block_syntax!=0) && matchtoken(',')); + if (block_syntax!=0) + needtoken(')'); + emit_flags &= ~efEXPR; lval->ident=iEXPRESSION; + pc_sideeffect=TRUE; return FALSE; } /* case */ default: diff --git a/source/compiler/sc7.c b/source/compiler/sc7.c index 0c1613e..07a25b5 100644 --- a/source/compiler/sc7.c +++ b/source/compiler/sc7.c @@ -1437,6 +1437,8 @@ SC_FUNC void stgout(int index) filewrite(stgpipe+idx); } /* if */ } /* if */ + if (stgidx<=emit_stgbuf_idx) + emit_stgbuf_idx=-1; pipeidx=0; /* reset second pipe */ } @@ -1770,7 +1772,7 @@ static void stgopt(char *start,char *end,int (*outputfunc)(char *str)) assert(sequences!=NULL); /* do not match anything if debug-level is maximum */ - if (pc_optimize>sOPTIMIZE_NONE && (emit_parsing_mode & epmACTIVE)==0 && sc_status==statWRITE) { + if (pc_optimize>sOPTIMIZE_NONE && sc_status==statWRITE && emit_stgbuf_idx==-1) { do { matches=0; start=debut; diff --git a/source/compiler/scvars.c b/source/compiler/scvars.c index 2038ad8..5055a15 100644 --- a/source/compiler/scvars.c +++ b/source/compiler/scvars.c @@ -105,7 +105,8 @@ SC_VDEFINE FILE *outf = NULL; /* (intermediate) text file written to */ SC_VDEFINE jmp_buf errbuf; -SC_VDEFINE int emit_parsing_mode=0; +SC_VDEFINE int emit_flags; +SC_VDEFINE int emit_stgbuf_idx; #if !defined SC_LIGHT SC_VDEFINE int sc_makereport=FALSE; /* generate a cross-reference report */