int ForDirective( int i, enum irp_type type ) /*******************************************/ { int start = i - 1; /* location of "directive name .. after any labels" */ int arg_loc; char *parmstring = NULL; char *ptr; char *next_parm; char *end_of_parms; char buffer[MAX_LINE_LEN]; int len = 0; if( type == IRP_REPEAT ) { ExpandTheWorld( i, FALSE, TRUE ); /* make a temporary macro, then call it */ if( AsmBuffer[i]->class != TC_NUM ) { AsmError( OPERAND_EXPECTED ); return( ERROR ); } arg_loc = i; len = AsmBuffer[i]->u.value; i++; if( AsmBuffer[i]->class != TC_FINAL ) { AsmError( OPERAND_EXPECTED ); return( ERROR ); } } else {
static void add_constant( char *string ) /**************************************/ { char *tmp; char *one = "1"; tmp = strchr( string, '=' ); if( tmp == NULL ) { tmp = strchr( string, '#' ); if( tmp == NULL ) { tmp = one; } else { *tmp = '\0'; tmp++; } } else { *tmp = '\0'; tmp++; } if( isvalidident( string ) == ERROR ) { AsmError( SYNTAX_ERROR ); // fixme return; } StoreConstant( string, tmp, FALSE ); // don't allow it to be redef'd }
static void add_constant( const char *string, bool underscored ) /**************************************************************/ { char name[MAX_LINE_LEN]; char *tmp; char c; tmp = name; if( underscored ) { *tmp++ = '_'; *tmp++ = '_'; } while( (c = *string) != '\0' ) { ++string; if( c == '=' || c == '#' ) break; *tmp++ = c; } if( underscored ) { *tmp++ = '_'; *tmp++ = '_'; } *tmp = '\0'; if( *string == '\0' ) string = "1"; if( isvalidident( name ) ) { AsmError( SYNTAX_ERROR ); // fixme return; } StoreConstant( name, string, false ); // don't allow it to be redef'd }
extern void AsError( int resource_id, ... ) //***************************************** { va_list arglist; char msg[ MAX_RESOURCE_SIZE ]; va_start( arglist, resource_id ); AsMsgGet( resource_id, AsResBuffer ); vsprintf( msg, AsResBuffer, arglist ); va_end( arglist ); AsmError( msg ); // CC provides this }
int StructDef( int i ) /********************/ { char *name; dir_node *dir; int n; if( Options.mode & MODE_IDEAL ) { n = i + 1; if( ( AsmBuffer[i]->u.token == T_STRUC ) && ( AsmBuffer[n]->class != TC_ID ) ) { AsmError( SYNTAX_ERROR ); return( ERROR ); } } else {
static ret_code EvaluateHllExpression( hll_list * hll, int *i, int ilabel, bool is_true ) /***************************************************************************************/ { char *lastjmp = NULL; expr_list opndx; char buffer[MAX_LINE_LEN*2]; DebugMsg(("EvaluateHllExpression enter\n")); buffer[0] = NULLC; if ( ERROR == GetExpression( hll, i, ilabel, is_true, buffer, &lastjmp, &opndx ) ) return( ERROR ); if ( buffer[0] ) WriteExprSrc( hll, buffer ); if ( hll->condlines != NULL && *hll->condlines == '\n' ) { AsmError( SYNTAX_ERROR_IN_CONTROL_FLOW_DIRECTIVE ); return( ERROR ); } return( NOT_ERROR ); }
int conditional_assembly_directive( int i ) /*****************************************/ { uint_16 direct; direct = AsmBuffer[i]->u.value; switch( direct ) { case T_IF: case T_IF1: case T_IF2: case T_IFB: case T_IFDEF: case T_IFDIF: case T_IFDIFI: case T_IFE: case T_IFIDN: case T_IFIDNI: case T_IFNB: case T_IFNDEF: if( CurState == ACTIVE ) { NestLevel++; if( NestLevel > MAX_NESTING ) { /*fixme */ AsmError( NESTING_LEVEL_TOO_DEEP ); return( ERROR ); } CurState = get_cond_state( i ); } else { falseblocknestlevel++; } break; case T_ELSEIF: case T_ELSEIF1: case T_ELSEIF2: case T_ELSEIFB: case T_ELSEIFDEF: case T_ELSEIFDIF: case T_ELSEIFDIFI: case T_ELSEIFE: case T_ELSEIFIDN: case T_ELSEIFIDNI: case T_ELSEIFNB: case T_ELSEIFNDEF: if( CurState == ACTIVE ) { CurState = DONE; } else if( CurState == LOOKING_FOR_TRUE_COND ) { if( falseblocknestlevel == 0 ) { CurState = get_cond_state( i ); } } break; case T_ELSE: if( CurState == ACTIVE ) { CurState = DONE; } else if( CurState == LOOKING_FOR_TRUE_COND ) { if( falseblocknestlevel == 0 ) { CurState = ACTIVE; } } break; case T_ENDIF: if( CurState == ACTIVE || falseblocknestlevel == 0 ) { NestLevel--; if( NestLevel < 0 ) { NestLevel = 0; AsmError( BLOCK_NESTING_ERROR ); return( ERROR ); } CurState = ACTIVE; } else { falseblocknestlevel--; } break; default: /**/ myassert( 0 ); return( ERROR ); } return( NOT_ERROR ); }
bool jmp( expr_list *opndx, int *flags ) /* determine the displacement of jmp; */ { int_32 addr; enum fixup_types fixup_type; enum fixup_options fixup_option; enum sym_state state; struct asm_sym *sym; #if defined( _STANDALONE_ ) dir_node *seg; #endif *flags = 0; Code->data[Opnd_Count] = opndx->value; sym = opndx->sym; if( sym == NULL ) { if( Code->info.token == T_CALL ) { Code->info.token = T_CALLF; } else if( Code->info.token == T_JMP ) { Code->info.token = T_JMPF; } if( Code->data[Opnd_Count] > USHRT_MAX ) Code->info.opnd_type[Opnd_Count] = OP_I32; else Code->info.opnd_type[Opnd_Count] = OP_I16; return( RC_OK ); } #if defined( _STANDALONE_ ) if( sym->mem_type == MT_ERROR ) { AsmError( LABEL_NOT_DEFINED ); return( RC_ERROR ); } #endif state = sym->state; #if defined( _STANDALONE_ ) seg = GetSeg( sym ); if( seg == NULL || CurrSeg == NULL || CurrSeg->seg != seg ) { /* jumps to another segment are just like to another file */ state = SYM_EXTERNAL; } #endif if( !Code->mem_type_fixed ) { Code->mem_type = MT_EMPTY; } fixup_option = OPTJ_NONE; fixup_type = FIX_RELOFF8; switch( state ) { case SYM_INTERNAL: #if defined( _STANDALONE_ ) case SYM_PROC: #endif if( ( Code->mem_type == MT_EMPTY || Code->mem_type == MT_SHORT || Code->mem_type == MT_NEAR ) && sym->mem_type != MT_WORD && sym->mem_type != MT_DWORD && sym->mem_type != MT_FWORD && !IS_JMPCALLF( Code->info.token ) ) { #if defined( _STANDALONE_ ) if( ( Code->info.token == T_CALL ) && ( Code->mem_type == MT_EMPTY ) && ( sym->mem_type == MT_FAR ) ) { FarCallToNear(); *flags = SCRAP_INSTRUCTION; return( RC_OK ); } addr = sym->offset; #else addr = sym->addr; #endif addr -= ( AsmCodeAddress + 2 ); // calculate the displacement addr += Code->data[Opnd_Count]; switch( Code->info.token ) { case T_JCXZ: case T_LOOPW: case T_LOOPEW: case T_LOOPZW: case T_LOOPNEW: case T_LOOPNZW: if( Code->use32 ) { // 1 extra byte for OPNSIZ addr--; } break; case T_JECXZ: case T_LOOPD: case T_LOOPED: case T_LOOPZD: case T_LOOPNED: case T_LOOPNZD: if( !Code->use32 ) { // 1 extra byte for OPNSIZ addr--; } break; } if( Code->info.token == T_CALL && Code->mem_type == MT_EMPTY ) { Code->mem_type = MT_NEAR; } if( Code->mem_type != MT_NEAR && Code->info.token != T_CALL && ( addr >= SCHAR_MIN && addr <= SCHAR_MAX ) ) { Code->info.opnd_type[Opnd_Count] = OP_I8; } else { /* near jmp */ if( Code->use32 ) { Code->info.opnd_type[Opnd_Count] = OP_I32; addr -= 3; // 32 bit displacement } else { Code->info.opnd_type[Opnd_Count] = OP_I16; addr -= 1; // 16 bit displacement } if( IS_JMP( Code->info.token ) ) { switch( Code->info.token ) { case T_JMP: case T_JMPF: case T_JCXZ: case T_JECXZ: break; default: // 1 extra byte for opcode ( 0F ) addr--; break; } } } /* store the displacement */ Code->data[Opnd_Count] = addr; switch( Code->info.token ) { case T_JCXZ: case T_JECXZ: case T_LOOP: case T_LOOPE: case T_LOOPNE: case T_LOOPNZ: case T_LOOPZ: case T_LOOPD: case T_LOOPED: case T_LOOPNED: case T_LOOPNZD: case T_LOOPZD: case T_LOOPW: case T_LOOPEW: case T_LOOPNEW: case T_LOOPNZW: case T_LOOPZW: #if defined( _STANDALONE_ ) if( !PhaseError && (Code->info.opnd_type[Opnd_Count] != OP_I8) ) { #else if( (Code->info.opnd_type[Opnd_Count] != OP_I8) ) { #endif AsmError( JUMP_OUT_OF_RANGE ); return( RC_ERROR ); } Code->info.opnd_type[Opnd_Count] = OP_I8; break; } if( (Code->info.cpu&P_CPU_MASK) < P_386 && IS_JMP( Code->info.token ) ) { /* look into jump extension */ switch( Code->info.token ) { case T_JMP: case T_JMPF: break; default: if( Code->info.opnd_type[Opnd_Count] != OP_I8 ) { #if defined( _STANDALONE_ ) if( Code->mem_type == MT_EMPTY ) { jumpExtend( 0 ); *flags = SCRAP_INSTRUCTION; return( RC_OK ); } else if( !PhaseError ) { AsmError( JUMP_OUT_OF_RANGE ); return( RC_ERROR ); } #else AsmError( JUMP_OUT_OF_RANGE ); return( RC_ERROR ); #endif } } } break; } /* otherwise fall through & get handled like external symbols */ case SYM_UNDEFINED: case SYM_EXTERNAL: /* forward ref, or external symbol */ if( Code->mem_type == MT_EMPTY && sym->mem_type != MT_EMPTY ) { switch( sym->mem_type ) { case MT_FAR: if( Code->info.token == T_CALL ) { Code->info.token = T_CALLF; } else if( Code->info.token == T_JMP ) { Code->info.token = T_JMPF; } // fall through case MT_SHORT: case MT_NEAR: Code->mem_type = sym->mem_type; break; #if defined( _STANDALONE_ ) case MT_PROC: if( IS_PROC_FAR() ) { Code->mem_type = MT_FAR; if( Code->info.token == T_CALL ) { Code->info.token = T_CALLF; } else if( Code->info.token == T_JMP ) { Code->info.token = T_JMPF; } } else { Code->mem_type = MT_NEAR; } break; #endif case MT_FWORD: if( ptr_operator( MT_FWORD, true ) ) return( RC_ERROR ); break; default: Code->mem_type = sym->mem_type; } } if( Code->mem_type == MT_FAR ) { if( Code->info.token == T_CALL ) { Code->info.token = T_CALLF; } else if( Code->info.token == T_JMP ) { Code->info.token = T_JMPF; } } switch( Code->info.token ) { case T_CALLF: case T_JMPF: switch( Code->mem_type ) { case MT_SHORT: case MT_NEAR: if( Opnd_Count == OPND1 && Code->mem_type_fixed ) { AsmError( CANNOT_USE_SHORT_OR_NEAR ); return( RC_ERROR ); } /* fall through */ case MT_FAR: case MT_EMPTY: #if defined( _STANDALONE_ ) SET_OPSIZ( Code, SymIs32( sym )); find_frame( sym ); #endif if( Opnd_Count == OPND2 ) { if( IS_OPSIZ_32( Code ) ) { fixup_type = FIX_OFF32; Code->info.opnd_type[Opnd_Count] = OP_I32; } else { fixup_type = FIX_OFF16; Code->info.opnd_type[Opnd_Count] = OP_I16; } } else { if( IS_OPSIZ_32( Code ) ) { fixup_type = FIX_PTR32; Code->info.opnd_type[Opnd_Count] = OP_J48; } else { fixup_type = FIX_PTR16; Code->info.opnd_type[Opnd_Count] = OP_J32; } } break; case MT_BYTE: case MT_WORD: #if defined( _STANDALONE_ ) case MT_SBYTE: case MT_SWORD: #endif AsmError( INVALID_SIZE ); return( RC_ERROR ); case MT_DWORD: case MT_FWORD: #if defined( _STANDALONE_ ) case MT_SDWORD: #endif *flags = INDIRECT_JUMP; return( RC_OK ); case MT_QWORD: case MT_TBYTE: case MT_OWORD: AsmError( INVALID_SIZE ); return( RC_ERROR ); } break; case T_CALL: if( Code->mem_type == MT_SHORT ) { AsmError( CANNOT_USE_SHORT_WITH_CALL ); return( RC_ERROR ); } else if( Code->mem_type == MT_EMPTY ) { #if defined( _STANDALONE_ ) fixup_option = OPTJ_CALL; #else fixup_option = OPTJ_NONE; #endif if( Code->use32 ) { fixup_type = FIX_RELOFF32; Code->info.opnd_type[Opnd_Count] = OP_I32; } else { fixup_type = FIX_RELOFF16; Code->info.opnd_type[Opnd_Count] = OP_I16; } break; } /* fall through */ case T_JMP: switch( Code->mem_type ) { case MT_SHORT: fixup_option = OPTJ_EXPLICIT; fixup_type = FIX_RELOFF8; Code->info.opnd_type[Opnd_Count] = OP_I8; break; case MT_FAR: AsmError( SYNTAX_ERROR ); break; case MT_EMPTY: // forward reference // inline assembler jmp default distance is near // stand-alone assembler jmp default distance is short fixup_option = OPTJ_NONE; #if defined( _STANDALONE_ ) /* guess short if JMP, we will expand later if needed */ fixup_type = FIX_RELOFF8; Code->info.opnd_type[Opnd_Count] = OP_I8; #else if( Code->use32 ) { fixup_type = FIX_RELOFF32; Code->info.opnd_type[Opnd_Count] = OP_I32; } else { fixup_type = FIX_RELOFF16; Code->info.opnd_type[Opnd_Count] = OP_I16; } #endif break; case MT_NEAR: fixup_option = OPTJ_EXPLICIT; if( Code->use32 ) { fixup_type = FIX_RELOFF32; Code->info.opnd_type[Opnd_Count] = OP_I32; } else { fixup_type = FIX_RELOFF16; Code->info.opnd_type[Opnd_Count] = OP_I16; } break; case MT_DWORD: case MT_WORD: #if defined( _STANDALONE_ ) case MT_SDWORD: case MT_SWORD: #endif *flags = INDIRECT_JUMP; return( RC_OK ); #if defined( _STANDALONE_ ) case MT_SBYTE: #endif case MT_BYTE: case MT_FWORD: case MT_QWORD: case MT_TBYTE: case MT_OWORD: AsmError( INVALID_SIZE ); return( RC_ERROR ); } // check_assume( sym, PREFIX_EMPTY ); break; case T_JCXZ: case T_JECXZ: // JCXZ and JECXZ always require SHORT label case T_LOOP: case T_LOOPE: case T_LOOPNE: case T_LOOPNZ: case T_LOOPZ: case T_LOOPD: case T_LOOPED: case T_LOOPNED: case T_LOOPNZD: case T_LOOPZD: case T_LOOPW: case T_LOOPEW: case T_LOOPNEW: case T_LOOPNZW: case T_LOOPZW: #if defined( _STANDALONE_ ) if( ( Code->mem_type != MT_EMPTY ) && ( Code->mem_type != MT_SHORT ) && ( (Options.mode & MODE_IDEAL) == 0 ) ) { #else if( ( Code->mem_type != MT_EMPTY ) && ( Code->mem_type != MT_SHORT ) ) { #endif AsmError( ONLY_SHORT_DISPLACEMENT_IS_ALLOWED ); return( RC_ERROR ); } Code->info.opnd_type[Opnd_Count] = OP_I8; fixup_option = OPTJ_EXPLICIT; fixup_type = FIX_RELOFF8; break; default: if( (Code->info.cpu&P_CPU_MASK) >= P_386 ) { switch( Code->mem_type ) { case MT_SHORT: fixup_option = OPTJ_EXPLICIT; fixup_type = FIX_RELOFF8; Code->info.opnd_type[Opnd_Count] = OP_I8; break; case MT_EMPTY: // forward reference // inline assembler default distance is near // stand-alone assembler default distance is short #if defined( _STANDALONE_ ) fixup_option = OPTJ_JXX; fixup_type = FIX_RELOFF8; Code->info.opnd_type[Opnd_Count] = OP_I8; break; #endif case MT_NEAR: fixup_option = OPTJ_EXPLICIT; if( Code->use32 ) { fixup_type = FIX_RELOFF32; Code->info.opnd_type[Opnd_Count] = OP_I32; } else { fixup_type = FIX_RELOFF16; Code->info.opnd_type[Opnd_Count] = OP_I16; } break; case MT_FAR: #if defined( _STANDALONE_ ) jumpExtend( 1 ); *flags = SCRAP_INSTRUCTION; return( RC_OK ); #endif default: AsmError( ONLY_SHORT_AND_NEAR_DISPLACEMENT_IS_ALLOWED ); return( RC_ERROR ); } } else { // the only mode in 8086, 80186, 80286 is // Jxx SHORT switch( Code->mem_type ) { case MT_EMPTY: #if defined( _STANDALONE_ ) fixup_option = OPTJ_EXTEND; fixup_type = FIX_RELOFF8; Code->info.opnd_type[Opnd_Count] = OP_I8; break; #endif case MT_SHORT: fixup_option = OPTJ_EXPLICIT; fixup_type = FIX_RELOFF8; Code->info.opnd_type[Opnd_Count] = OP_I8; break; default: AsmError( ONLY_SHORT_DISPLACEMENT_IS_ALLOWED ); return( RC_ERROR ); } } } AddFixup( sym, fixup_type, fixup_option ); break; default: /* SYM_STACK */ AsmError( NO_JUMP_TO_AUTO ); return( RC_ERROR ); } return( RC_OK ); } bool ptr_operator( memtype mem_type, bool fix_mem_type ) /******************************************************/ /* determine what should be done with SHORT, NEAR, FAR, BYTE, WORD, DWORD, PTR operator; */ { /* new idea: * when we get a near/far/dword/etc, just set distance / mem_type * operator will be called again with PTR, then we set the opsiz, etc. */ if( Code->info.token == T_LEA ) return( RC_OK ); if( Code->info.token == T_SMSW ) return( RC_OK ); if( mem_type == MT_PTR ) { /* finish deciding what type to make the inst NOW * ie: decide size overrides etc. */ if( Code->use32 && MEM_TYPE( Code->mem_type, WORD ) ) { // if we are in use32 mode, we have to add OPSIZ prefix for // most of the 386 instructions ( except MOVSX and MOVZX ) // when we find WORD PTR if( !IS_BRANCH( Code->info.token ) ) { if( Code->info.opnd_type[OPND1] == OP_MMX ) { /* JBS 2001/02/19 no WORD operands for MMX instructions, only 64-bit or 128-bit so no WORD override needed */ } else { switch( Code->info.token ) { case T_MOVSX: case T_MOVZX: break; default: SET_OPSIZ_ON( Code ); break; } } } } else if( !Code->use32 && MEM_TYPE( Code->mem_type, DWORD ) ) { /* if we are not in use32 mode, we have to add OPSIZ * when we find DWORD PTR * unless we have a LXS ins. * which moves a DWORD ptr into SR:word reg * fixme - can this be done by breaking up the LXS instructions in * asmins.h, and then putting F_32 or F_16 to append * opsize bytes when necessary ? */ if( !IS_BRANCH( Code->info.token ) ) { if( Code->info.opnd_type[OPND1] == OP_MMX ) { /* JBS 2001/02/19 no WORD operands for MMX instructions, only 64-bit or 128-bit so no DWORD override needed */ } else { switch( Code->info.token ) { case T_LDS: case T_LES: case T_LFS: case T_LGS: case T_LSS: /* in these cases, opsize does NOT need to be changed */ break; default: // OPSIZ prefix SET_OPSIZ_ON( Code ); } } } } } else { if( ( mem_type != MT_EMPTY ) && !Code->mem_type_fixed ) { #if defined( _STANDALONE_ ) if( mem_type != MT_STRUCT ) { #endif Code->mem_type = mem_type; if( fix_mem_type ) { Code->mem_type_fixed = true; if( mem_type == MT_FAR ) { if( Code->info.token == T_CALL ) { Code->info.token = T_CALLF; } else if( Code->info.token == T_JMP ) { Code->info.token = T_JMPF; } } } #if defined( _STANDALONE_ ) } #endif } } return( RC_OK ); }
int directive( int i, long direct ) /* Handle all directives */ { int ret; /* no expansion on the following */ switch( direct ) { case T_MASM: Options.mode &= ~MODE_IDEAL; return( NOT_ERROR ); case T_IDEAL: Options.mode |= MODE_IDEAL; return( NOT_ERROR ); case T_DOT_286C: direct = T_DOT_286; case T_DOT_8086: case T_DOT_186: case T_DOT_286: case T_DOT_286P: case T_DOT_386: case T_DOT_386P: case T_DOT_486: case T_DOT_486P: case T_DOT_586: case T_DOT_586P: case T_DOT_686: case T_DOT_686P: case T_DOT_8087: case T_DOT_287: case T_DOT_387: case T_DOT_NO87: case T_DOT_K3D: case T_DOT_MMX: case T_DOT_XMM: case T_DOT_XMM2: case T_DOT_XMM3: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } else { ret = cpu_directive(direct); if( Parse_Pass != PASS_1 ) ret = NOT_ERROR; return( ret ); } case T_P286N: direct = T_P286; case T_P8086: case T_P186: case T_P286: case T_P286P: case T_P386: case T_P386P: case T_P486: case T_P486P: case T_P586: case T_P586P: case T_P686: case T_P686P: case T_P8087: case T_P287: case T_P387: case T_PK3D: case T_PMMX: case T_PXMM: case T_PXMM2: case T_PXMM3: ret = cpu_directive(direct); if( Parse_Pass != PASS_1 ) ret = NOT_ERROR; return( ret ); case T_DOT_DOSSEG: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_DOSSEG: Globals.dosseg = TRUE; return( NOT_ERROR ); case T_PUBLIC: /* special case - expanded inside iff it is an EQU to a symbol */ return( Parse_Pass == PASS_1 ? PubDef(i+1) : NOT_ERROR ); case T_ELSE: case T_ELSEIF: case T_ELSEIF1: case T_ELSEIF2: case T_ELSEIFB: case T_ELSEIFDEF: case T_ELSEIFE: case T_ELSEIFNB: case T_ELSEIFNDEF: case T_ELSEIFDIF: case T_ELSEIFDIFI: case T_ELSEIFIDN: case T_ELSEIFIDNI: case T_ENDIF: case T_IF: case T_IF1: case T_IF2: case T_IFB: case T_IFDEF: case T_IFE: case T_IFNB: case T_IFNDEF: case T_IFDIF: case T_IFDIFI: case T_IFIDN: case T_IFIDNI: return( conditional_assembly_directive( i ) ); case T_DOT_ERR: case T_DOT_ERRB: case T_DOT_ERRDEF: case T_DOT_ERRDIF: case T_DOT_ERRDIFI: case T_DOT_ERRE: case T_DOT_ERRIDN: case T_DOT_ERRIDNI: case T_DOT_ERRNB: case T_DOT_ERRNDEF: case T_DOT_ERRNZ: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_ERR: case T_ERRIFB: case T_ERRIFDEF: case T_ERRIFDIF: case T_ERRIFDIFI: case T_ERRIFE: case T_ERRIFIDN: case T_ERRIFIDNI: case T_ERRIFNDEF: return( conditional_error_directive( i ) ); case T_ENDS: if( Definition.struct_depth != 0 ) return( StructDef( i ) ); // else fall through to T_SEGMENT case T_SEGMENT: return( Parse_Pass == PASS_1 ? SegDef(i) : SetCurrSeg(i) ); case T_GROUP: return( Parse_Pass == PASS_1 ? GrpDef(i) : NOT_ERROR ); case T_PROC: return( ProcDef( i, TRUE ) ); case T_ENDP: return( ProcEnd(i) ); case T_ENUM: return( EnumDef( i ) ); case T_DOT_CODE: case T_DOT_STACK: case T_DOT_DATA: case T_DOT_DATA_UN: case T_DOT_FARDATA: case T_DOT_FARDATA_UN: case T_DOT_CONST: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_CODESEG: case T_STACK: case T_DATASEG: case T_UDATASEG: case T_FARDATA: case T_UFARDATA: case T_CONST: return( SimSeg(i) ); case T_WARN: case T_NOWARN: return( NOT_ERROR ); /* Not implemented yet */ case T_DOT_ALPHA: case T_DOT_SEQ: case T_DOT_LIST: case T_DOT_LISTALL: case T_DOT_LISTIF: case T_DOT_LISTMACRO: case T_DOT_LISTMACROALL: case T_DOT_NOLIST: case T_DOT_XLIST: case T_DOT_TFCOND: case T_DOT_SFCOND: case T_DOT_LFCOND: case T_DOT_CREF: case T_DOT_XCREF: case T_DOT_NOCREF: case T_DOT_SALL: case T_PAGE: case T_TITLE: case T_SUBTITLE: case T_SUBTTL: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } AsmWarn( 4, IGNORING_DIRECTIVE ); return( NOT_ERROR ); case T_DOT_BREAK: case T_DOT_CONTINUE: case T_DOT_ELSE: case T_DOT_ENDIF: case T_DOT_ENDW: case T_DOT_IF: case T_DOT_RADIX: case T_DOT_REPEAT: case T_DOT_UNTIL: case T_DOT_WHILE: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_ECHO: case T_HIGH: case T_HIGHWORD: case T_LOW: case T_LOWWORD: case T_ADDR: case T_BOUND: case T_CASEMAP: case T_INVOKE: case T_LROFFSET: case T_OPATTR: case T_OPTION: case T_POPCONTEXT: case T_PUSHCONTEXT: case T_PROTO: case T_THIS: case T_WIDTH: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_CATSTR: case T_MASK: case T_PURGE: case T_RECORD: case T_TYPEDEF: case T_UNION: AsmError( NOT_SUPPORTED ); return( ERROR ); case T_ORG: ExpandTheWorld( 0, FALSE, TRUE ); break; case T_TEXTEQU: /* TEXTEQU */ if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_EQU2: /* = */ case T_EQU: /* EQU */ /* expand any constants and simplify any expressions */ ExpandTheConstant( 0, FALSE, TRUE ); break; case T_NAME: /* no expand parameters */ break; case T_DOT_STARTUP: case T_DOT_EXIT: if( Options.mode & MODE_IDEAL ) { AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); } case T_STARTUPCODE: case T_EXITCODE: default: /* expand any constants in all other directives */ ExpandAllConsts( 0, FALSE ); break; } switch( direct ) { case T_ALIAS: if( Parse_Pass == PASS_1 ) return( AddAlias( i ) ); return( NOT_ERROR ); case T_EXTERN: if( Options.mode & MODE_IDEAL ) { break; } case T_EXTRN: return( Parse_Pass == PASS_1 ? ExtDef( i+1, FALSE ) : NOT_ERROR ); case T_COMM: return( Parse_Pass == PASS_1 ? CommDef(i+1) : NOT_ERROR ); case T_EXTERNDEF: if( Options.mode & MODE_IDEAL ) { break; } case T_GLOBAL: return( Parse_Pass == PASS_1 ? ExtDef( i+1, TRUE ) : NOT_ERROR ); case T_DOT_MODEL: if( Options.mode & MODE_IDEAL ) { break; } case T_MODEL: return( Model(i) ); case T_INCLUDE: return( Include(i+1) ); case T_INCLUDELIB: return( Parse_Pass == PASS_1 ? IncludeLib(i+1) : NOT_ERROR ); case T_ASSUME: return( SetAssume(i) ); case T_END: return( ModuleEnd(Token_Count) ); case T_EQU: return( DefineConstant( i-1, FALSE, FALSE ) ); case T_EQU2: return( DefineConstant( i-1, TRUE, FALSE ) ); case T_TEXTEQU: return( DefineConstant( i-1, TRUE, TRUE ) ); case T_MACRO: return( MacroDef(i, FALSE ) ); case T_ENDM: return( MacroEnd( FALSE ) ); case T_EXITM: return( MacroEnd( TRUE ) ); case T_ARG: return( Parse_Pass == PASS_1 ? ArgDef(i) : NOT_ERROR ); case T_USES: return( Parse_Pass == PASS_1 ? UsesDef(i) : NOT_ERROR ); case T_LOCAL: return( Parse_Pass == PASS_1 ? LocalDef(i) : NOT_ERROR ); case T_COMMENT: if( Options.mode & MODE_IDEAL ) break; return( Comment( START_COMMENT, i ) ); case T_STRUCT: if( Options.mode & MODE_IDEAL ) { break; } case T_STRUC: return( StructDef( i ) ); case T_NAME: return( Parse_Pass == PASS_1 ? NameDirective(i) : NOT_ERROR ); case T_LABEL: return( LabelDirective( i ) ); case T_ORG: return( OrgDirective( i ) ); case T_ALIGN: case T_EVEN: return( AlignDirective( direct, i ) ); case T_FOR: if( Options.mode & MODE_IDEAL ) { break; } case T_IRP: return( ForDirective ( i+1, IRP_WORD ) ); case T_FORC: if( Options.mode & MODE_IDEAL ) { break; } case T_IRPC: return( ForDirective ( i+1, IRP_CHAR ) ); case T_REPEAT: if( Options.mode & MODE_IDEAL ) { break; } case T_REPT: return( ForDirective ( i+1, IRP_REPEAT ) ); case T_DOT_STARTUP: case T_DOT_EXIT: case T_STARTUPCODE: case T_EXITCODE: return( Startup ( i ) ); case T_LOCALS: case T_NOLOCALS: return( Locals( i ) ); } AsmError( UNKNOWN_DIRECTIVE ); return( ERROR ); }
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 ); }
static ret_code GetSimpleExpression( hll_list * hll, int *i, int ilabel, bool is_true, char * buffer, char **jmp, expr_list *opndx ) /**********************************************************************************************************************************/ { //expr_list opndx; expr_list op2; c_bop op; //int size; //int end_tok; int op1_pos; int op1_end; int op2_pos; int op2_end; char *label; bool issigned; DebugMsg(("GetSimpleExpression(buffer=%s) enter\n", buffer )); while ( AsmBuffer[*i]->string_ptr[0] == '!' && AsmBuffer[*i]->string_ptr[1] == '\0' ) { GetCOp(i); is_true = 1 - is_true; } op1_pos = *i; /* the problem with '()' is that is might enclose just a standard Masm * expression or a "hll" expression. The first case is to be handled * entirely by the expression evaluator, while the latter case is to be * handled HERE! */ if ( AsmBuffer[*i]->token == T_OP_BRACKET ) { int brcnt; int j; for ( brcnt = 1, j = *i + 1; AsmBuffer[j]->token != T_FINAL; j++ ) { if ( AsmBuffer[j]->token == T_OP_BRACKET ) brcnt++; else if ( AsmBuffer[j]->token == T_CL_BRACKET ) { brcnt--; if ( brcnt == 0 ) /* a standard Masm expression? */ break; } else if ( ( GetCOp( &j )) != COP_NONE ) break; } if ( brcnt ) { (*i)++; DebugMsg(("GetSimpleExpression: calling GetExpression, i=%u\n", *i)); if ( ERROR == GetExpression( hll, i, ilabel, is_true, buffer, jmp, opndx ) ) return( ERROR ); DebugMsg(("return from GetExpression, i=%u\n", *i)); if ( AsmBuffer[*i]->token != T_CL_BRACKET ) { //if ((AsmBuffer[*i]->token == T_FINAL) || (AsmBuffer[*i]->token == T_CL_BRACKET)) DebugMsg(( "GetSimpleExpression: expected ')', found: %s\n", AsmBuffer[*i]->string_ptr )); AsmError( SYNTAX_ERROR_IN_CONTROL_FLOW_DIRECTIVE ); return( ERROR ); } (*i)++; return( NOT_ERROR ); } } if ( ERROR == GetToken( hll, i, is_true, opndx ) ) return ( ERROR ); op1_end = *i; op = GetCOp( i ); if ( op == COP_AND || op == COP_OR ) { *i = op1_end; if ( opndx->kind == EXPR_EMPTY ) return( NOT_ERROR ); op = COP_NONE; } label = GetLabel( hll, ilabel ); DebugMsg(("GetSimpleExpression: EvalOperand ok, kind=%X, i=%u\n", opndx->kind, *i)); if ( opndx->kind == EXPR_EMPTY ) { /* no valid ASM expression detected. check for some special ops */ /* COP_ZERO, COP_CARRY, COP_SIGN, COP_PARITY, COP_OVERFLOW */ if ( op >= COP_ZERO ) { //char t; char * p; //char * s; p = buffer; *jmp = p; *p++ = 'j'; if ( is_true == FALSE ) *p++ = 'n'; switch ( op ) { case COP_CARRY: *p++ = 'c'; break; case COP_ZERO: *p++ = 'z'; break; case COP_SIGN: *p++ = 's'; break; case COP_PARITY: *p++ = 'p'; break; case COP_OVERFLOW: *p++ = 'o'; break; } *p++ = ' '; if ( is_true == TRUE ) *p++ = ' '; strcpy( p, label ); goto done; } if ( hll->condlines ) return( NOT_ERROR ); else { AsmError( SYNTAX_ERROR_IN_CONTROL_FLOW_DIRECTIVE ); return( NOT_ERROR ); } } if ( ( opndx->kind != EXPR_CONST ) && ( opndx->kind != EXPR_ADDR ) && ( opndx->kind != EXPR_REG ) ) return( ERROR ); op2_pos = *i; if ( op != COP_NONE ) { if ( ERROR == GetToken( hll, i, is_true, &op2 ) ) { return( ERROR ); } DebugMsg(("GetSimpleExpression: EvalOperand 2 ok, type=%X, i=%u\n", op2.type, *i)); if ( ( op2.kind != EXPR_CONST ) && ( op2.kind != EXPR_ADDR ) && ( op2.kind != EXPR_REG ) ) { DebugMsg(("GetSimpleExpression: syntax error, op2.kind=%u\n", op2.kind )); AsmError( SYNTAX_ERROR ); return( ERROR ); } } op2_end = *i; /* now generate ASM code for expression */ buffer[0] = 0; if ( ( op == COP_EQ ) || ( op == COP_NE ) || ( op == COP_GT ) || ( op == COP_LT ) || ( op == COP_GE ) || ( op == COP_LE ) ) { char * p; /* optimisation: generate 'or EAX,EAX' instead of 'cmp EAX,0' */ if ( Options.masm_compat_gencode && ( op == COP_EQ || op == COP_NE ) && opndx->kind == EXPR_REG && opndx->indirect == FALSE && op2.kind == EXPR_CONST && op2.value == 0 ) { strcat( buffer," or " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); strcat( buffer, ", " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); } else { strcat( buffer," cmp " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); strcat( buffer, ", " ); RenderOpnd( &op2, buffer, op2_pos, op2_end ); } strcat( buffer, "\n" ); p = buffer + strlen( buffer ); *jmp = p; if (IS_SIGNED( opndx->mem_type ) || IS_SIGNED(op2.mem_type)) issigned = TRUE; else issigned = FALSE; switch ( op ) { case COP_EQ: if ( is_true ) strcpy( p, "jz " ); else strcpy( p, "jnz " ); break; case COP_NE: if ( is_true ) strcpy( p, "jnz " ); else strcpy( p, "jz " ); break; case COP_GT: if ( issigned == TRUE ) { if ( is_true ) strcpy( p, "jg " ); else strcpy( p, "jle " ); } else { if ( is_true ) strcpy( p, "ja " ); else strcpy( p, "jbe " ); } break; case COP_LT: if ( issigned == TRUE ) { if ( is_true ) strcpy( p, "jl " ); else strcpy( p, "jge " ); } else { if ( is_true ) strcpy( p, "jb " ); else strcpy( p, "jae " ); } break; case COP_GE: if ( issigned == TRUE ) { if ( is_true ) strcpy( p, "jge " ); else strcpy( p, "jl " ); } else { if ( is_true ) strcpy( p, "jae " ); else strcpy( p, "jb " ); } break; case COP_LE: if ( issigned == TRUE ) { if ( is_true ) strcpy( p, "jle " ); else strcpy( p, "jg " ); } else { if ( is_true ) strcpy( p, "jbe " ); else strcpy( p, "ja " ); } break; } strcat( p, label ); } else if ( op == COP_ANDB ) { char * p; strcat( buffer," test " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); strcat( buffer, ", " ); RenderOpnd( &op2, buffer, op2_pos, op2_end ); strcat( buffer, "\n" ); p = buffer + strlen( buffer ); *jmp = p; if ( is_true ) strcpy( p, "jne " ); else strcpy( p, "je " ); strcat( p, label ); } else if ( op == COP_NONE ) { char * p; switch ( opndx->kind ) { case EXPR_REG: if ( opndx->indirect == FALSE ) { strcat( buffer, "and " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); strcat( buffer, ", " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); strcat( buffer, "\n" ); p = buffer + strlen( buffer ); *jmp = p; if ( is_true ) strcpy( p, "jnz " ); else strcpy( p, "jz " ); strcat( p, label ); break; } case EXPR_ADDR: strcat( buffer, "cmp " ); RenderOpnd( opndx, buffer, op1_pos, op1_end ); strcat( buffer, ", 0\n" ); p = buffer + strlen( buffer ); *jmp = p; if ( is_true ) strcpy( p, "jnz " ); /* switched */ else strcpy( p, "jz " ); strcat( buffer, label ); break; case EXPR_CONST: if ( opndx->string != NULL ) { AsmError( SYNTAX_ERROR_IN_CONTROL_FLOW_DIRECTIVE ); return ( ERROR ); } *jmp = buffer; if ( is_true == TRUE ) if ( opndx->value ) sprintf( buffer, "jmp %s", label ); else strcpy( buffer, " "); /* make sure there is a char */ if ( is_true == FALSE ) if ( opndx->value == 0 ) sprintf( buffer, "jmp %s", label ); else strcpy( buffer, " " ); /* make sure there is a char */ break; } } done: strcat( buffer, "\n" ); 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 ); }