void SetCurPC( struct asym *sym ) /*******************************/ { if( CurrStruct ) { //symPC.segment = NULL; //symPC.mem_type = MT_ABS; symPC.mem_type = MT_EMPTY; symPC.segment = NULL; /* v2.07: needed again */ symPC.offset = CurrStruct->sym.offset + (CurrStruct->next ? CurrStruct->next->sym.offset : 0); } else { symPC.mem_type = MT_NEAR; symPC.segment = (struct asym *)CurrSeg; symPC.offset = GetCurrOffset(); } DebugMsg1(("SetCurPC: curr value=%" FX32 "h\n", symPC.offset )); }
void PutMsg( FILE *fp, int severity, int msgnum, va_list args ) /********************************************************************/ { int i,j; char *type; char msgbuf[MAXMSGSIZE]; char buffer[MAX_LINE_LEN]; if( fp != NULL ) { MsgGet( msgnum, msgbuf ); switch (severity ) { case 1: type = MsgGetEx( MSG_FATAL_PREFIX ); break; case 2: type = MsgGetEx( MSG_ERROR_PREFIX ); break; case 4: type = MsgGetEx( MSG_WARNING_PREFIX ); break; default: type = NULL; i = 0; break; } if ( type ) i = sprintf( buffer, "%s A%4u: ", type, severity * 1000 + msgnum ); i += vsprintf( buffer+i, msgbuf, args ); //buffer[i] = NULLC; if ( severity && (j = GetCurrSrcPos( msgbuf ))) { fwrite( msgbuf, 1, j, fp ); } else j = 0; fwrite( buffer, 1, i, fp ); fwrite( "\n", 1, 1, fp ); /* if in Pass 1, add the error msg to the listing */ if ( FileInfo.file[LST] && severity && Parse_Pass == PASS_1 && fp == FileInfo.file[ERR] ) { LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), 0 ); LstPrintf( " %s", buffer ); LstNL(); } } }
void LstWrite( enum lsttype type, uint_32 oldofs, void *value ) /*************************************************************/ { uint_32 newofs; struct asym *sym = value; int len; int len2; int idx; int srcfile; char *p1; char *p2; char *pSrcline; struct lstleft *pll; struct lstleft ll; //char buffer2[MAX_LINE_LEN]; /* stores text macro value */ if ( ModuleInfo.list == FALSE || CurrFile[LST] == NULL || ( ModuleInfo.line_flags & LOF_LISTED ) ) return; if ( ModuleInfo.GeneratedCode && ( ModuleInfo.list_generated_code == FALSE ) ) return; if ( MacroLevel ) { switch ( ModuleInfo.list_macro ) { case LM_NOLISTMACRO: return; case LM_LISTMACRO: /* todo: filter certain macro lines */ break; } } ModuleInfo.line_flags |= LOF_LISTED; DebugMsg1(("LstWrite( %u, %" I32_SPEC "u ): enter [ pos=%" I32_SPEC "u, GeneratedCode=%u, MacroLevel=%u ]\n", type, oldofs, list_pos, ModuleInfo.GeneratedCode, MacroLevel )); pSrcline = CurrSource; #if FASTPASS if ( ( Parse_Pass > PASS_1 ) && UseSavedState ) { if ( ModuleInfo.GeneratedCode == 0 ) { if ( !( ModuleInfo.line_flags & LOF_SKIPPOS ) ) list_pos = LineStoreCurr->list_pos; #if USELSLINE /* either use CurrSource + CurrComment or LineStoreCurr->line (see assemble.c, OnePass() */ pSrcline = LineStoreCurr->line; if ( ModuleInfo.CurrComment ) { /* if comment was removed, readd it! */ *( LineStoreCurr->line + strlen( LineStoreCurr->line ) ) = ';'; ModuleInfo.CurrComment = NULL; } #endif DebugMsg1(("LstWrite: Pass=%u, stored pos=%" I32_SPEC "u\n", Parse_Pass+1, list_pos )); } fseek( CurrFile[LST], list_pos, SEEK_SET ); } #endif ll.next = NULL; memset( ll.buffer, ' ', sizeof( ll.buffer ) ); srcfile = get_curr_srcfile(); switch ( type ) { case LSTTYPE_DATA: if ( Parse_Pass == PASS_1 && Options.first_pass_listing == FALSE ) { break; } /* no break */ case LSTTYPE_CODE: newofs = GetCurrOffset(); sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs ); ll.buffer[OFSSIZE] = ' '; if ( CurrSeg == NULL ) break; //if ( write_to_file == FALSE ) if ( Options.first_pass_listing ) { if ( Parse_Pass > PASS_1 ) break; #ifdef DEBUG_OUT } else if ( Options.max_passes == 1 ) { ; /* write a listing in pass 1 */ #endif } else if ( Parse_Pass == PASS_1 ) /* changed v1.96 */ break; len = CODEBYTES; p2 = ll.buffer + OFSSIZE + 2; if ( CurrSeg->e.seginfo->CodeBuffer == NULL || CurrSeg->e.seginfo->written == FALSE ) { while ( oldofs < newofs && len ) { *p2++ = '0'; *p2++ = '0'; oldofs++; len--; } break; } /* OMF hold just a small buffer for one LEDATA record */ /* if it has been flushed, use LastCodeBufSize */ idx = (CurrSeg->e.seginfo->current_loc - CurrSeg->e.seginfo->start_loc) - (newofs - oldofs); if ( Options.output_format == OFORMAT_OMF ) { /* v2.11: additional check to make the hack more robust [ test case: db 800000h dup (0) ] */ if ( ( idx+LastCodeBufSize ) < 0 ) break; /* just exit. The code bytes area will remain empty */ while ( idx < 0 && len ) { sprintf( p2, "%02X", CurrSeg->e.seginfo->CodeBuffer[idx+LastCodeBufSize] ); p2 += 2; idx++; oldofs++; len--; } } else if (idx < 0) idx = 0; while ( oldofs < newofs && len ) { sprintf( p2, "%02X", CurrSeg->e.seginfo->CodeBuffer[idx] ); p2 += 2; idx++; oldofs++; len--; } *p2 = ' '; break; case LSTTYPE_EQUATE: /* v2.10: display current offset if equate is an alias for a label in this segment */ idx = 1; if ( sym->segment && sym->segment == &CurrSeg->sym ) { sprintf( ll.buffer, "%08" I32_SPEC "X", GetCurrOffset() ); idx = 10; } ll.buffer[idx] = '='; #if AMD64_SUPPORT if ( sym->value3264 != 0 && ( sym->value3264 != -1 || sym->value >= 0 ) ) sprintf( &ll.buffer[idx+2], "%-" PREFFMTSTR I64_SPEC "X", (uint_64)sym->value + ( (uint_64)sym->value3264 << 32 ) ); else #endif sprintf( &ll.buffer[idx+2], "%-" PREFFMTSTR I32_SPEC "X", sym->value ); ll.buffer[28] = ' '; break; case LSTTYPE_TMACRO: ll.buffer[1] = '='; //GetLiteralValue( buffer2, sym->string_ptr ); //strcpy( buffer2, sym->string_ptr ); for ( p1 = sym->string_ptr, p2 = &ll.buffer[3], pll = ≪ *p1; ) { if ( p2 >= &pll->buffer[28] ) { struct lstleft *next = myalloca( sizeof( struct lstleft ) ); pll->next = next; pll = next; pll->next = NULL; memset( pll->buffer, ' ', sizeof( pll->buffer) ); p2 = &pll->buffer[3]; } *p2++ = *p1++; } break; case LSTTYPE_MACROLINE: ll.buffer[1] = '>'; pSrcline = value; break; case LSTTYPE_LABEL: oldofs = GetCurrOffset(); /* no break */ case LSTTYPE_STRUCT: sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs ); ll.buffer[8] = ' '; break; case LSTTYPE_DIRECTIVE: if ( CurrSeg || value ) { sprintf( ll.buffer, "%08" I32_SPEC "X", oldofs ); ll.buffer[8] = ' '; } break; default: /* LSTTYPE_MACRO */ if ( *pSrcline == NULLC && ModuleInfo.CurrComment == NULL && srcfile == ModuleInfo.srcfile ) { DebugMsg1(("LstWrite: type=%u, writing CRLF\n", type )); fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] ); list_pos += NLSIZ; return; } break; } #if FASTPASS if ( Parse_Pass == PASS_1 || UseSavedState == FALSE ) { #endif idx = sizeof( ll.buffer ); if ( ModuleInfo.GeneratedCode ) ll.buffer[28] = '*'; if ( MacroLevel ) { len = sprintf( &ll.buffer[29], "%u", MacroLevel ); ll.buffer[29+len] = ' '; } if ( srcfile != ModuleInfo.srcfile ) { ll.buffer[30] = 'C'; } #ifdef DEBUG_OUT ll.last = NULLC; #endif #if FASTPASS } else { idx = OFSSIZE + 2 + 2 * CODEBYTES; #ifdef DEBUG_OUT ll.buffer[idx] = NULLC; #endif } #endif fwrite( ll.buffer, 1, idx, CurrFile[LST] ); len = strlen( pSrcline ); len2 = ( ModuleInfo.CurrComment ? strlen( ModuleInfo.CurrComment ) : 0 ); list_pos += sizeof( ll.buffer ) + len + len2 + NLSIZ; DebugMsg1(("LstWrite: writing (%u b) >%s< [%u/%u], new pos=%" I32_SPEC "u\n", idx, ll.buffer, len, len2, list_pos )); /* write source and comment part */ #if FASTPASS if ( Parse_Pass == PASS_1 || UseSavedState == FALSE ) { #endif if ( len ) fwrite( pSrcline, 1, len, CurrFile[LST] ); if ( len2 ) { fwrite( ModuleInfo.CurrComment, 1, len2, CurrFile[LST] ); DebugMsg1(("LstWrite: writing (%u b) >%s%s<\n", len + len2 + NLSIZ, pSrcline, ModuleInfo.CurrComment )); } #ifdef DEBUG_OUT else DebugMsg1(("LstWrite: writing (%u b) >%s<\n", len + NLSIZ, pSrcline )); #endif fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] ); #if FASTPASS } #endif /* write optional additional lines. * currently works in pass one only. */ for ( pll = ll.next; pll; pll = pll->next ) { fwrite( pll->buffer, 1, 32, CurrFile[LST] ); fwrite( NLSTR, 1, NLSIZ, CurrFile[LST] ); list_pos += 32 + NLSIZ; DebugMsg1(("LstWrite: additional line >%s<, new pos=%" I32_SPEC "u\n", pll->buffer, list_pos )); } return; }
void AddLinnumDataRef( unsigned srcfile, uint_32 line_num ) /*********************************************************/ { struct line_num_info *curr; #if COFF_SUPPORT /* COFF line number info is related to functions/procedures. Since * assembly allows code lines outside of procs, "dummy" procs must * be generated. A dummy proc lasts until * - a true PROC is detected or * - the source file changes or * - the segment/section changes ( added in v2.11 ) */ if ( Options.output_format == OFORMAT_COFF && CurrProc == NULL && ( dmyproc == NULL || dmyproc->debuginfo->file != srcfile || dmyproc->segment != (struct asym *)CurrSeg ) ) { char procname[12]; if ( dmyproc ) { /**/myassert( dmyproc->segment ); dmyproc->total_size = ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc - dmyproc->offset; } sprintf( procname, "$$$%05u", procidx ); DebugMsg1(("AddLinnumDataRef(src=%u.%u): CurrProc==NULL, dmyproc=%s searching proc=%s\n", srcfile, line_num, dmyproc ? dmyproc->name : "NULL", procname )); dmyproc = SymSearch( procname ); /* in pass 1, create the proc */ if ( dmyproc == NULL ) { dmyproc = CreateProc( NULL, procname, SYM_INTERNAL ); DebugMsg1(("AddLinnumDataRef: new proc %s created\n", procname )); dmyproc->isproc = TRUE; /* flag is usually set inside ParseProc() */ dmyproc->included = TRUE; AddPublicData( dmyproc ); } else procidx++; /* for passes > 1, adjust procidx */ /* if the symbols isn't a PROC, the symbol name has been used * by the user - bad! A warning should be displayed */ if ( dmyproc->isproc == TRUE ) { SetSymSegOfs( dmyproc ); dmyproc->Ofssize = ModuleInfo.Ofssize; dmyproc->langtype = ModuleInfo.langtype; if ( write_to_file == TRUE ) { curr = LclAlloc( sizeof( struct line_num_info ) ); curr->sym = dmyproc; curr->line_number = GetLineNumber(); curr->file = srcfile; curr->number = 0; DebugMsg1(("AddLinnumDataRef: CURRPROC=NULL, sym=%s, calling AddLinnumData(src=%u.%u)\n", curr->sym->name, curr->file, curr->line_number )); AddLinnumData( curr ); } } } #endif if( line_num && ( write_to_file == FALSE || lastLineNumber == line_num )) { #ifdef DEBUG_OUT if ( write_to_file == TRUE ) DebugMsg1(("AddLinnumDataRef(src=%u.%u) line skipped, lastline=%u\n", srcfile, line_num, lastLineNumber )); #endif return; } DebugMsg1(("AddLinnumDataRef(src=%u.%u): currofs=%Xh, CurrProc=%s, GeneratedCode=%u\n", srcfile, line_num, GetCurrOffset(), CurrProc ? CurrProc->sym.name : "NULL", ModuleInfo.GeneratedCode )); curr = LclAlloc( sizeof( struct line_num_info ) ); curr->number = line_num; #if COFF_SUPPORT if ( line_num == 0 ) { /* happens for COFF only */ /* changed v2.03 (CurrProc might have been NULL) */ /* if ( Options.output_format == OFORMAT_COFF && CurrProc->sym.public == FALSE ) { */ /* v2.09: avoid duplicates, check for pass 1 */ //if ( Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.public == FALSE ) { if ( Parse_Pass == PASS_1 && Options.output_format == OFORMAT_COFF && CurrProc && CurrProc->sym.ispublic == FALSE ) { CurrProc->sym.included = TRUE; AddPublicData( (struct asym *)CurrProc ); } /* changed v2.03 */ /* curr->sym = (struct asym *)CurrProc; */ curr->sym = ( CurrProc ? (struct asym *)CurrProc : dmyproc ); curr->line_number = GetLineNumber(); curr->file = srcfile; /* set the function's size! */ if ( dmyproc ) { /**/myassert( dmyproc->segment ); dmyproc->total_size = ((struct dsym *)dmyproc->segment)->e.seginfo->current_loc - dmyproc->offset; dmyproc = NULL; } /* v2.11: write a 0x7fff line item if prologue exists */ if ( CurrProc && CurrProc->e.procinfo->size_prolog ) { DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u) sym=%s\n", curr->file, curr->line_number, curr->sym->name )); AddLinnumData( curr ); curr = LclAlloc( sizeof( struct line_num_info ) ); curr->number = GetLineNumber(); curr->offset = GetCurrOffset(); curr->srcfile = srcfile; } } else { #endif curr->offset = GetCurrOffset(); curr->srcfile = srcfile; #if COFF_SUPPORT } #endif lastLineNumber = line_num; /* v2.11: added, improved multi source support for CV. * Also, the size of line number info could have become > 1024, * ( even > 4096, thus causing an "internal error in omfint.c" ) */ if ( Options.output_format == OFORMAT_OMF ) omf_check_flush( curr ); /* v2.10: warning if line-numbers for segments without class code! */ if ( CurrSeg->e.seginfo->linnum_init == FALSE ) { CurrSeg->e.seginfo->linnum_init = TRUE; if ( TypeFromClassName( CurrSeg, CurrSeg->e.seginfo->clsym ) != SEGTYPE_CODE ) { EmitWarn( 2, LINNUM_INFO_FOR_SEGMENT_WITHOUT_CLASS_CODE, CurrSeg->sym.name ); } } DebugMsg1(("AddLinnumDataRef: calling AddLinnumData(src=%u.%u ofs=%X)\n", curr->number == 0 ? curr->file : curr->srcfile, curr->number, curr->offset )); AddLinnumData( curr ); return; }
void SetSymSegOfs( struct asym *sym ) /***********************************/ { sym->segment = &CurrSeg->sym; sym->offset = GetCurrOffset(); }
ret_code HllEndDef( int i ) /*************************/ { //struct asm_sym *sym; struct hll_list *hll; int cmd = AsmBuffer[i]->value; char buffer[MAX_ID_LEN+1+64]; DebugMsg(("HllEndDef(%s) enter\n", AsmBuffer[i]->string_ptr )); if ( HllStack == NULL ) { DebugMsg(("HllEndDef: hll stack is empty\n")); AsmError( DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK ); return( ERROR ); } hll = HllStack; HllStack = hll->next; PushLineQueue(); switch (cmd) { case T_DOT_ENDIF: if ( hll->cmd != HLL_IF ) { DebugMsg(("HllEndDef no .IF on the hll stack\n")); AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr ); return( ERROR ); } /* if a test label isn't created yet, create it */ if ( hll->symtest ) { MakeLabel( buffer, hll->symtest ); AddLineQueue( buffer ); } /* create the exit label if it exists */ if ( hll->symexit ) { MakeLabel( buffer, hll->symexit ); AddLineQueue( buffer ); } i++; break; case T_DOT_ENDW: if ( hll->cmd != HLL_WHILE ) { DebugMsg(("HllEndDef no .WHILE on the hll stack\n")); AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr ); return( ERROR ); } /* create test label */ if ( hll->symtest ) { MakeLabel( buffer, hll->symtest ); DebugMsg(("HllEndDef: created: %s\n", buffer)); AddLineQueue( buffer ); } HllPushTestLines( hll ); MakeLabel( buffer, hll->symexit ); AddLineQueue( buffer ); i++; break; case T_DOT_UNTILCXZ: if ( hll->cmd != HLL_REPEAT ) { DebugMsg(("HllEndDef no .REPEAT on the hll stack\n")); AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr ); return( ERROR ); } MakeLabel( buffer, hll->symtest ); AddLineQueue( buffer ); i++; /* read in optional (simple) expression */ if ( AsmBuffer[i]->token != T_FINAL ) { if ( ERROR == EvaluateHllExpression( hll, &i, LABELFIRST, FALSE ) ) { return( ERROR ); } if ( HllCheckTestLines(hll) == ERROR ) { AsmError( EXPR_TOO_COMPLEX_FOR_UNTILCXZ ); return( ERROR ); } /* write condition lines */ HllPushTestLines( hll ); } else { sprintf( buffer, " loop %s", hll->symfirst ); AddLineQueue( buffer ); } MakeLabel( buffer, hll->symexit ); AddLineQueue( buffer ); break; case T_DOT_UNTIL: if ( hll->cmd != HLL_REPEAT ) { DebugMsg(("HllEndDef no .REPEAT on the hll stack\n")); AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr ); return( ERROR ); } MakeLabel( buffer, hll->symtest ); AddLineQueue( buffer ); i++; /* read in (optional) expression */ /* if expression is missing, just generate nothing */ if ( AsmBuffer[i]->token != T_FINAL ) { if ( ERROR == EvaluateHllExpression( hll, &i, LABELFIRST, FALSE ) ) { return( ERROR ); } /* write condition lines */ HllPushTestLines( hll ); } #if 0 sprintf( buffer, " jmp %s", hll->symfirst ); AddLineQueue( buffer ); #endif MakeLabel( buffer, hll->symexit ); AddLineQueue( buffer ); break; } AsmFree( hll->symfirst ); AsmFree( hll->symtest ); AsmFree( hll->symexit ); AsmFree( hll->condlines ); AsmFree( hll ); if ( AsmBuffer[i]->token != T_FINAL ) { AsmErr( SYNTAX_ERROR_EX, AsmBuffer[i]->string_ptr ); return( ERROR ); } if ( ModuleInfo.list ) LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), NULL ); if ( line_queue ) RunLineQueue(); return( NOT_ERROR ); }
ret_code HllStartDef( int i ) /***************************/ { struct hll_list *hll; int cmd = AsmBuffer[i]->value; char buffer[MAX_ID_LEN+1+64]; DebugMsg(("HllStartDef(%u [=%s]) enter\n", i, AsmBuffer[i]->string_ptr )); #if FASTPASS /* make sure the directive is stored */ if ( StoreState == FALSE && Parse_Pass == PASS_1 ) { SaveState(); } #endif switch (cmd) { case T_DOT_REPEAT: if ( AsmBuffer[i+1]->token != T_FINAL ) { DebugMsg(("HllStartDef: unexpected tokens behind .REPEAT\n" )); AsmError( SYNTAX_ERROR ); return( ERROR ); } break; case T_DOT_IF: case T_DOT_WHILE: #if 0 /* Masm allows a missing expression! */ if ( AsmBuffer[i+1]->token == T_FINAL ) { AsmError( SYNTAX_ERROR ); return( ERROR ); } #endif break; } hll = AsmAlloc( sizeof(hll_list) ); hll->cmd = HLL_UNDEF; /* create labels which are always needed */ /* for .IF -.ENDIF without .ELSE no symexit label is needed. */ hll->symfirst = NULL; hll->symexit = NULL; hll->symtest = MakeAnonymousLabel(); hll->condlines = NULL; // structure for .IF .ELSE .ENDIF // cond jump to symtest // ... // jmp symexit // symtest: // ... // symexit: // structure for .IF .ELSEIF // cond jump to symtest // ... // jmp symexit // symtest: // cond jump to (new) symtest // ... // jmp symexit // symtest: // ... // structure for .WHILE and .REPEAT: // jmp symtest (for .WHILE only) // symfirst: // ... // symtest: (jumped to by .continue) // test end condition, cond jump to symfirst // symexit: (jumped to by .break) PushLineQueue(); switch (cmd) { case T_DOT_IF: hll->cmd = HLL_IF; /* get the C-style expression, convert to ASM code lines */ i++; if ( ERROR == EvaluateHllExpression( hll, &i, LABELTEST, FALSE ) ) { return( ERROR ); } HllPushTestLines( hll ); #if 1 /* if no lines have been created, the symtest label isn't needed */ if ( line_queue == NULL ) { AsmFree( hll->symtest ); hll->symtest = NULL; } #endif break; case T_DOT_WHILE: case T_DOT_REPEAT: /* create the label to loop start */ hll->symfirst = MakeAnonymousLabel(); hll->symexit = MakeAnonymousLabel(); if ( cmd == T_DOT_WHILE ) { i++; hll->cmd = HLL_WHILE; if ( AsmBuffer[i]->token != T_FINAL ) { if ( ERROR == EvaluateHllExpression( hll, &i, LABELFIRST, TRUE ) ) { return( ERROR ); } } else hll->condlines = ""; /* create a jump to second label */ /* optimisation: if second label is just a jump, dont jump! */ if ( hll->condlines && _memicmp(hll->condlines, "jmp", 3) ) { sprintf( buffer, " jmp %s", hll->symtest ); AddLineQueue( buffer ); } else { AsmFree( hll->symtest ); hll->symtest = NULL; } } else { i++; hll->cmd = HLL_REPEAT; } MakeLabel( buffer, hll->symfirst ); AddLineQueue( buffer ); break; } if ( AsmBuffer[i]->token != T_FINAL ) { DebugMsg(("HllStartDef: unexpected token %u [%s]\n", AsmBuffer[i]->token, AsmBuffer[i]->string_ptr )); AsmErr( SYNTAX_ERROR_EX, AsmBuffer[i]->string_ptr ); return( ERROR ); } hll->next = HllStack; HllStack = hll; if ( ModuleInfo.list ) LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), NULL ); if ( line_queue ) /* might be NULL! (".if 1") */ RunLineQueue(); return( NOT_ERROR ); }
ret_code HllExitDef( int i ) /**************************/ { //int level; //struct asm_sym *sym; struct hll_list *hll; char *savedlines; hll_cmd savedcmd; int cmd = AsmBuffer[i]->value; char buffer[MAX_ID_LEN+1+64]; DebugMsg(("HllExitDef(%s) enter\n", AsmBuffer[i]->string_ptr )); hll = HllStack; if ( hll == NULL ) { DebugMsg(("HllExitDef stack error\n")); AsmError( DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK ); return( ERROR ); } PushLineQueue(); switch (cmd) { case T_DOT_ELSE: case T_DOT_ELSEIF: if ( hll->cmd != HLL_IF ) { DebugMsg(("HllExitDef(%s): symtest=%X\n", AsmBuffer[i]->string_ptr, hll->symtest)); AsmErr( BLOCK_NESTING_ERROR, AsmBuffer[i]->string_ptr ); return( ERROR ); } /* the "symexit" label is only needed if an .ELSE branch exists. That's why it is created delayed. */ if ( hll->symexit == NULL) hll->symexit = MakeAnonymousLabel(); sprintf( buffer," jmp %s", hll->symexit ); AddLineQueue( buffer ); if ( hll->symtest ) { MakeLabel( buffer, hll->symtest ); AddLineQueue( buffer ); AsmFree( hll->symtest ); hll->symtest = NULL; } i++; if (cmd == T_DOT_ELSEIF) { /* create new symtest label */ hll->symtest = MakeAnonymousLabel(); if ( ERROR == EvaluateHllExpression( hll, &i, LABELTEST, FALSE ) ) { return( ERROR ); } HllPushTestLines( hll ); } break; case T_DOT_BREAK: case T_DOT_CONTINUE: for ( ; hll && hll->cmd == HLL_IF; hll = hll->next ); if ( hll == NULL ) { AsmError( DIRECTIVE_MUST_BE_IN_CONTROL_BLOCK ); return( ERROR ); } /* .BREAK .IF ... or .CONTINUE .IF ? */ i++; if ( AsmBuffer[i]->token != T_FINAL ) { if ( AsmBuffer[i]->token == T_DIRECTIVE && AsmBuffer[i]->value == T_DOT_IF ) { savedlines = hll->condlines; savedcmd = hll->cmd; hll->condlines = NULL; hll->cmd = HLL_BREAK; i++; if ( cmd == T_DOT_BREAK ) { if ( ERROR == EvaluateHllExpression( hll, &i, LABELEXIT, TRUE ) ) { return( ERROR ); } } else { /* T_DOT_CONTINUE */ if ( ERROR == EvaluateHllExpression( hll, &i, LABELTEST, TRUE ) ) { return( ERROR ); } } HllPushTestLines( hll ); AsmFree( hll->condlines ); hll->condlines = savedlines; hll->cmd = savedcmd; } } else { if ( cmd == T_DOT_BREAK ) { sprintf( buffer," jmp %s", hll->symexit ); } else { if ( hll->symtest ) sprintf( buffer," jmp %s", hll->symtest ); else sprintf( buffer," jmp %s", hll->symfirst ); } AddLineQueue( buffer ); } break; } if ( AsmBuffer[i]->token != T_FINAL ) { AsmErr( SYNTAX_ERROR_EX, AsmBuffer[i]->string_ptr ); return( ERROR ); } if ( ModuleInfo.list ) LstWrite( LSTTYPE_DIRECTIVE, GetCurrOffset(), NULL ); RunLineQueue(); return( NOT_ERROR ); }