/* PreprocessLine() is the "preprocessor". * 1. the line is tokenized with Tokenize(), Token_Count set * 2. (text) macros are expanded by ExpandLine() * 3. "preprocessor" directives are executed */ int PreprocessLine( char *line, struct asm_tok tokenarray[] ) /***********************************************************/ { int i; /* v2.11: GetTextLine() removed - this is now done in ProcessFile() */ /* v2.08: moved here from GetTextLine() */ ModuleInfo.CurrComment = NULL; /* v2.06: moved here from Tokenize() */ ModuleInfo.line_flags = 0; /* Token_Count is the number of tokens scanned */ Token_Count = Tokenize( line, 0, tokenarray, TOK_DEFAULT ); #ifdef DEBUG_OUT cntppl0++; if ( ModuleInfo.GeneratedCode ) DebugMsg1(("PreprocessLine: >%s<\n", line )); else DebugMsg1(("PreprocessLine(%s): >%s< cmt=%s\n", GetTopSrcName(), line, ModuleInfo.CurrComment ? ModuleInfo.CurrComment : "" )); #endif #if REMOVECOMENT == 0 if ( Token_Count == 0 && ( CurrIfState == BLOCK_ACTIVE || ModuleInfo.listif ) ) LstWriteSrcLine(); #endif if ( Token_Count == 0 ) return( 0 ); #ifdef DEBUG_OUT /* option -np, skip preprocessor? */ if ( Options.skip_preprocessor ) return( Token_Count ); #endif /* CurrIfState != BLOCK_ACTIVE && Token_Count == 1 | 3 may happen * if a conditional assembly directive has been detected by Tokenize(). * However, it's important NOT to expand then */ if ( CurrIfState == BLOCK_ACTIVE ) { if ( ( tokenarray[Token_Count].bytval & TF3_EXPANSION ? ExpandText( line, tokenarray, TRUE ) : ExpandLine( line, tokenarray ) ) < NOT_ERROR ) return( 0 ); } DebugCmd( cntppl1++ ); i = 0; if ( Token_Count > 2 && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) ) i = 2; /* handle "preprocessor" directives: * IF, ELSE, ENDIF, ... * FOR, REPEAT, WHILE, ... * PURGE * INCLUDE * since v2.05, error directives are no longer handled here! */ if ( tokenarray[i].token == T_DIRECTIVE && tokenarray[i].dirtype <= DRT_INCLUDE ) { /* if i != 0, then a code label is located before the directive */ if ( i > 1 ) { if ( ERROR == WriteCodeLabel( line, tokenarray ) ) return( 0 ); } directive_tab[tokenarray[i].dirtype]( i, tokenarray ); return( 0 ); } /* handle preprocessor directives which need a label */ if ( tokenarray[0].token == T_ID && tokenarray[1].token == T_DIRECTIVE ) { struct asym *sym; switch ( tokenarray[1].dirtype ) { case DRT_EQU: /* * EQU is a special case: * If an EQU directive defines a text equate * it MUST be handled HERE and 0 must be returned to the caller. * This will prevent further processing, nothing will be stored * if FASTPASS is on. * Since one cannot decide whether EQU defines a text equate or * a number before it has scanned its argument, we'll have to * handle it in ANY case and if it defines a number, the line * must be stored and, if -EP is set, written to stdout. */ if ( sym = CreateConstant( tokenarray ) ) { if ( sym->state != SYM_TMACRO ) { #if FASTPASS if ( StoreState ) FStoreLine( 0 ); #endif if ( Options.preprocessor_stdout == TRUE ) WritePreprocessedLine( line ); } /* v2.03: LstWrite() must be called AFTER StoreLine()! */ if ( ModuleInfo.list == TRUE ) { LstWrite( sym->state == SYM_INTERNAL ? LSTTYPE_EQUATE : LSTTYPE_TMACRO, 0, sym ); } } return( 0 ); case DRT_MACRO: case DRT_CATSTR: /* CATSTR + TEXTEQU directives */ case DRT_SUBSTR: directive_tab[tokenarray[1].dirtype]( 1, tokenarray ); return( 0 ); } } DebugCmd( cntppl2++ ); return( Token_Count ); }
ret_code AssumeDirective( int i, struct asm_tok tokenarray[] ) /************************************************************/ /* Handles ASSUME * syntax is : * - ASSUME * - ASSUME NOTHING * - ASSUME segregister : seglocation [, segregister : seglocation ] * - ASSUME dataregister : qualified type [, dataregister : qualified type ] * - ASSUME register : ERROR | NOTHING | FLAT */ { int reg; int j; int size; uint_32 flags; struct assume_info *info; bool segtable; struct qualified_type ti; DebugMsg1(( "AssumeDirective enter, pass=%u\n", Parse_Pass+1 )); for( i++; i < Token_Count; i++ ) { if( ( tokenarray[i].token == T_ID ) && (0 == _stricmp( tokenarray[i].string_ptr, szNothing )) ) { AssumeInit(); i++; break; } /*---- get the info ptr for the register ----*/ info = NULL; if ( tokenarray[i].token == T_REG ) { reg = tokenarray[i].tokval; j = GetRegNo( reg ); flags = GetValueSp( reg ); if ( flags & OP_SR ) { info = &SegAssumeTable[j]; segtable = TRUE; } else if ( flags & OP_R ) { info = &StdAssumeTable[j]; segtable = FALSE; } } if ( info == NULL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } if( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < GetCpuSp( reg ) ) { EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE ); return( ERROR ); } i++; /* go past register */ if( tokenarray[i].token != T_COLON ) { EmitError( COLON_EXPECTED ); return( ERROR ); } i++; if( tokenarray[i].token == T_FINAL ) { EmitError( SYNTAX_ERROR ); return( ERROR ); } /* check for ERROR and NOTHING */ if( 0 == _stricmp( tokenarray[i].string_ptr, szError )) { if ( segtable ) { info->flat = FALSE; info->error = TRUE; } else info->error |= (( reg >= T_AH && reg <= T_BH ) ? RH_ERROR : ( flags & OP_R )); info->symbol = NULL; i++; } else if( 0 == _stricmp( tokenarray[i].string_ptr, szNothing )) { if ( segtable ) { info->flat = FALSE; info->error = FALSE; } else info->error &= ~(( reg >= T_AH && reg <= T_BH ) ? RH_ERROR : ( flags & OP_R )); info->symbol = NULL; i++; } else if ( segtable == FALSE ) { /* v2.05: changed to use new GetQualifiedType() function */ ti.size = 0; ti.is_ptr = 0; ti.is_far = FALSE; ti.mem_type = MT_EMPTY; ti.ptr_memtype = MT_EMPTY; ti.symtype = NULL; ti.Ofssize = ModuleInfo.Ofssize; if ( GetQualifiedType( &i, tokenarray, &ti ) == ERROR ) return( ERROR ); /* v2.04: check size of argument! */ size = OperandSize( flags, NULL ); if ( ( ti.is_ptr == 0 && size != ti.size ) || ( ti.is_ptr > 0 && size < CurrWordSize ) ) { EmitError( TYPE_IS_WRONG_SIZE_FOR_REGISTER ); return( ERROR ); } info->error &= ~(( reg >= T_AH && reg <= T_BH ) ? RH_ERROR : ( flags & OP_R )); if ( stdsym[j] == NULL ) { stdsym[j] = CreateTypeSymbol( NULL, "", FALSE ); stdsym[j]->typekind = TYPE_TYPEDEF; } stdsym[j]->total_size = ti.size; stdsym[j]->mem_type = ti.mem_type; stdsym[j]->is_ptr = ti.is_ptr; stdsym[j]->isfar = ti.is_far; stdsym[j]->Ofssize = ti.Ofssize; stdsym[j]->ptr_memtype = ti.ptr_memtype; /* added v2.05 rc13 */ if ( ti.mem_type == MT_TYPE ) stdsym[j]->type = ti.symtype; else stdsym[j]->target_type = ti.symtype; info->symbol = stdsym[j]; } else { /* segment register */ struct expr opnd; /* v2.08: read expression with standard evaluator */ if( EvalOperand( &i, tokenarray, Token_Count, &opnd, 0 ) == ERROR ) return( ERROR ); switch ( opnd.kind ) { case EXPR_ADDR: if ( opnd.sym == NULL || opnd.indirect == TRUE || opnd.value ) { EmitError( SEGMENT_GROUP_OR_SEGREG_EXPECTED ); return( ERROR ); } else if ( opnd.sym->state == SYM_UNDEFINED ) { /* ensure that directive is rerun in pass 2 * so an error msg can be emitted. */ FStoreLine(0); info->symbol = opnd.sym; } else if ( ( opnd.sym->state == SYM_SEG || opnd.sym->state == SYM_GRP ) && opnd.instr == EMPTY ) { info->symbol = opnd.sym; } else if ( opnd.instr == T_SEG ) { info->symbol = opnd.sym->segment; } else { EmitError( SEGMENT_GROUP_OR_SEGREG_EXPECTED ); return( ERROR ); } info->flat = ( info->symbol == &ModuleInfo.flat_grp->sym ); break; case EXPR_REG: if ( GetValueSp( opnd.base_reg->tokval ) & OP_SR ) { info->symbol = SegAssumeTable[ GetRegNo( opnd.base_reg->tokval ) ].symbol; info->flat = SegAssumeTable[ GetRegNo( opnd.base_reg->tokval ) ].flat; break; } default: EmitError( SEGMENT_GROUP_OR_SEGREG_EXPECTED ); return( ERROR ); } info->error = FALSE; } /* comma expected */ if( i < Token_Count && tokenarray[i].token != T_COMMA ) break; } if ( i < Token_Count ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].tokpos ); return( ERROR ); } return( NOT_ERROR ); }