/* preprocessor directive or macro procedure is preceded * by a code label. */ ret_code WriteCodeLabel( char *line, struct asm_tok tokenarray[] ) /****************************************************************/ { int oldcnt; int oldtoken; char oldchar; if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } /* ensure the listing is written with the FULL source line */ if ( CurrFile[LST] ) LstWrite( LSTTYPE_LABEL, 0, NULL ); /* v2.04: call ParseLine() to parse the "label" part of the line */ oldcnt = Token_Count; oldtoken = tokenarray[2].token; oldchar = *tokenarray[2].tokpos; Token_Count = 2; tokenarray[2].token = T_FINAL; *tokenarray[2].tokpos = NULLC; ParseLine( tokenarray ); if ( Options.preprocessor_stdout == TRUE ) WritePreprocessedLine( line ); Token_Count = oldcnt; tokenarray[2].token = oldtoken; *tokenarray[2].tokpos = oldchar; return( NOT_ERROR ); }
static ret_code SetCurrSeg( int i, struct asm_tok tokenarray[] ) /**************************************************************/ { struct asym *sym; sym = SymSearch( tokenarray[0].string_ptr ); DebugMsg1(("SetCurrSeg(%s) sym=%p\n", tokenarray[0].string_ptr, sym)); if ( sym == NULL || sym->state != SYM_SEG ) { EmitErr( SEG_NOT_DEFINED, tokenarray[0].string_ptr ); return( ERROR ); } /* v2.04: added */ sym->isdefined = TRUE; if ( CurrSeg && Options.output_format == OFORMAT_OMF ) { omf_FlushCurrSeg(); if ( Options.no_comment_data_in_code_records == FALSE ) omf_OutSelect( FALSE ); } push_seg( (struct dsym *)sym ); if ( ModuleInfo.list ) LstWrite( LSTTYPE_LABEL, 0, NULL ); return( SetOfssize() ); }
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(); } } }
ret_code EndsDir( int i, struct asm_tok tokenarray[] ) /****************************************************/ { if( CurrStruct != NULL ) { return( EndstructDirective( i, tokenarray ) ); } /* a label must precede ENDS */ if( i != 1 ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } if ( Parse_Pass != PASS_1 ) { if ( ModuleInfo.list ) LstWrite( LSTTYPE_LABEL, 0, NULL ); } if ( CloseSeg( tokenarray[0].string_ptr ) == ERROR ) return( ERROR ); i++; if ( tokenarray[i].token != T_FINAL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); } return( SetOfssize() ); }
/* SizeStr() * defines a numeric variable which contains size of a string */ ret_code SizeStrDir( int i, struct asm_tok tokenarray[] ) /*******************************************************/ { struct asym *sym; int sizestr; DebugMsg1(("SizeStrDir entry\n")); DebugCmd( sizstrcnt++ ); if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } #if 0 /* this is checked in ParseLine() */ if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif if ( tokenarray[2].token != T_STRING || tokenarray[2].string_delim != '<' ) { return( TextItemError( &tokenarray[2] ) ); } if ( Token_Count > 3 ) { DebugMsg(("SizeStrDir: syntax error, name=%s, Token_Count=%u\n", tokenarray[0].string_ptr, Token_Count)); return( EmitErr( SYNTAX_ERROR_EX, tokenarray[3].string_ptr ) ); } //sizestr = GetLiteralValue( StringBufferEnd, tokenarray[2].string_ptr ); sizestr = tokenarray[2].stringlen; if ( sym = CreateVariable( tokenarray[0].string_ptr, sizestr ) ) { DebugMsg1(("SizeStrDir(%s) exit, value=%u\n", tokenarray[0].string_ptr, sizestr)); LstWrite( LSTTYPE_EQUATE, 0, sym ); return( NOT_ERROR ); } return( ERROR ); }
/* 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 ); }
void LstWriteSrcLine( void ) /**************************/ { LstWrite( LSTTYPE_MACRO, 0, NULL ); }
ret_code SegmentDir( int i, struct asm_tok tokenarray[] ) /*******************************************************/ { char is_old; char *token; int typeidx; const struct typeinfo *type; /* type of option */ int temp; int temp2; uint initstate = 0; /* flags for attribute initialization */ unsigned char oldreadonly; /* readonly value of a defined segment */ //unsigned char oldsegtype; unsigned char oldOfssize; char oldalign; char oldcombine; uint oldclassidx; uint_8 oldcharacteristics; struct dsym *dir; char *name; struct asym *sym; struct expr opndx; if ( Parse_Pass != PASS_1 ) return( SetCurrSeg( i, tokenarray ) ); if( i != 1 ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } name = tokenarray[0].string_ptr; DebugMsg1(("SegmentDir(%s) enter: ModuleInfo.Ofssize=%u, num_seg=%u\n", name, ModuleInfo.Ofssize, ModuleInfo.g.num_segs )); /* See if the segment is already defined */ sym = SymSearch( name ); if( sym == NULL || sym->state == SYM_UNDEFINED ) { /* segment is not defined (yet) */ sym = (struct asym *)CreateSegment( (struct dsym *)sym, name, TRUE ); sym->list = TRUE; /* always list segments */ dir = (struct dsym *)sym; dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs; is_old = FALSE; /* * initialize segment with values from the one without suffix */ #if COFF_SUPPORT || ELF_SUPPORT if (Options.output_format == OFORMAT_COFF #if ELF_SUPPORT || Options.output_format == OFORMAT_ELF #endif ) { char *p; if ( p = strchr(sym->name, '$') ) { char buffer[MAX_ID_LEN+1]; struct dsym *dir2; memcpy(buffer, sym->name, p - sym->name); buffer[p - sym->name] = NULLC; if ((dir2 = (struct dsym *)SymSearch(buffer)) && dir2->sym.state == SYM_SEG) { dir->e.seginfo->readonly = dir2->e.seginfo->readonly; dir->e.seginfo->segtype = dir2->e.seginfo->segtype; dir->e.seginfo->Ofssize = dir2->e.seginfo->Ofssize; dir->e.seginfo->alignment= dir2->e.seginfo->alignment; dir->e.seginfo->characteristics = dir2->e.seginfo->characteristics; dir->e.seginfo->combine = dir2->e.seginfo->combine; dir->e.seginfo->class_name_idx = dir2->e.seginfo->class_name_idx; } } } #endif } else if ( sym->state == SYM_SEG ) { /* segment already defined */ dir = (struct dsym *)sym; is_old = TRUE; oldreadonly = dir->e.seginfo->readonly; //oldsegtype = dir->e.seginfo->segtype; oldOfssize = dir->e.seginfo->Ofssize; oldalign = dir->e.seginfo->alignment; oldcharacteristics = dir->e.seginfo->characteristics; oldcombine = dir->e.seginfo->combine; oldclassidx = dir->e.seginfo->class_name_idx; if( dir->e.seginfo->lname_idx == 0 ) { /* segment was mentioned in a group statement, but not really set up */ is_old = FALSE; /* the segment list is to be sorted. * So unlink the segment and add it at the end. */ UnlinkSeg( dir ); dir->e.seginfo->seg_idx = ++ModuleInfo.g.num_segs; dir->next = NULL; if ( SymTables[TAB_SEG].head == NULL ) SymTables[TAB_SEG].head = SymTables[TAB_SEG].tail = dir; else { SymTables[TAB_SEG].tail->next = dir; SymTables[TAB_SEG].tail = dir; } } } else { /* symbol is different kind, error */ DebugMsg(("SegmentDir(%s): symbol redefinition\n", name )); EmitErr( SYMBOL_REDEFINITION, name ); return( ERROR ); } i++; /* go past SEGMENT */ for( ; i < Token_Count; i++ ) { token = tokenarray[i].string_ptr; DebugMsg1(("SegmentDir(%s): i=%u, string=%s token=%X\n", name, i, token, tokenarray[i].token )); if( tokenarray[i].token == T_STRING ) { /* the class name - the only token which is of type STRING */ /* string must be delimited by [double]quotes */ if ( tokenarray[i].string_delim != '"' && tokenarray[i].string_delim != '\'' ) { EmitErr( SYNTAX_ERROR_EX, token ); continue; } /* remove the quote delimiters */ token++; *(token+tokenarray[i].stringlen) = NULLC; SetSegmentClass( &dir->sym, token ); DebugMsg1(("SegmentDir(%s): class found: %s\n", name, token )); continue; } /* check the rest of segment attributes. */ typeidx = FindToken( token, SegAttrToken, sizeof( SegAttrToken )/sizeof( SegAttrToken[0] ) ); if( typeidx < 0 ) { EmitErr( UNKNOWN_SEGMENT_ATTRIBUTE, token ); continue; } type = &SegAttrValue[typeidx]; /* initstate is used to check if any field is already * initialized */ if( initstate & INIT_EXCL_MASK & type->init ) { EmitErr( SEGMENT_ATTRIBUTE_DEFINED_ALREADY, token ); continue; } else { initstate |= type->init; /* mark it initialized */ } switch ( type->init ) { case INIT_ATTR: dir->e.seginfo->readonly = TRUE; break; case INIT_ALIGN: DebugMsg1(("SegmentDir(%s): align attribute found\n", name )); dir->e.seginfo->alignment = type->value; break; case INIT_ALIGN_PARAM: DebugMsg1(("SegmentDir(%s): ALIGN() found\n", name )); if ( Options.output_format == OFORMAT_OMF ) { EmitErr( NOT_SUPPORTED_WITH_OMF_FORMAT, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_OP_BRACKET ) { EmitErr( EXPECTED, "(" ); break; } i++; if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR ) break; if ( tokenarray[i].token != T_CL_BRACKET ) { EmitErr( EXPECTED, ")" ); break; } if ( opndx.kind != EXPR_CONST ) { EmitError( CONSTANT_EXPECTED ); break; } /* COFF allows alignment values 1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192 */ for( temp = 1, temp2 = 0; temp < opndx.value && temp < 8192 ; temp <<= 1, temp2++ ); if( temp != opndx.value ) { EmitError( POWER_OF_2 ); } dir->e.seginfo->alignment = temp2; break; case INIT_COMBINE: DebugMsg1(("SegmentDir(%s): combine attribute found\n", name )); dir->e.seginfo->combine = type->value; break; case INIT_COMBINE_AT: DebugMsg1(("SegmentDir(%s): AT found\n", name )); dir->e.seginfo->combine = type->value; /* v2.05: always use MAX_SEGALIGNMENT */ //dir->e.seginfo->alignment = -1; dir->e.seginfo->alignment = MAX_SEGALIGNMENT; i++; if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) != ERROR ) { if ( opndx.kind == EXPR_CONST ) { dir->e.seginfo->abs_frame = opndx.value; dir->e.seginfo->abs_offset = 0; } else { EmitError( CONSTANT_EXPECTED ); } } break; #if COMDATSUPP case INIT_COMBINE_COMDAT: DebugMsg1(("SegmentDir(%s): COMDAT found\n", name )); if ( Options.output_format != OFORMAT_COFF ) { EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_OP_BRACKET ) { EmitErr( EXPECTED, "(" ); break; } i++; if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR ) break; if ( opndx.kind != EXPR_CONST ) { EmitError( CONSTANT_EXPECTED ); i = Token_Count; /* stop further parsing of this line */ break; } if ( opndx.value < 1 || opndx.value > 6 ) { EmitErr( VALUE_NOT_WITHIN_ALLOWED_RANGE, "1-6" ); } else { /* if value is IMAGE_COMDAT_SELECT_ASSOCIATIVE, * get the associated segment name argument. */ if ( opndx.value == 5 ) { struct asym *sym2; if ( tokenarray[i].token != T_COMMA ) { EmitError( EXPECTING_COMMA ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_ID ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } /* associated segment must be COMDAT, but not associative */ sym2 = SymSearch( tokenarray[i].string_ptr ); if ( sym2 == NULL || sym2->state != SYM_SEG || ((struct dsym *)sym2)->e.seginfo->comdat_selection == 0 || ((struct dsym *)sym2)->e.seginfo->comdat_selection == 5 ) EmitErr( INVALID_ASSOCIATED_SEGMENT, tokenarray[i].string_ptr ); else dir->e.seginfo->comdat_number = ((struct dsym *)sym2)->e.seginfo->seg_idx; i++; } } if ( tokenarray[i].token != T_CL_BRACKET ) { EmitErr( EXPECTED, ")" ); break; } dir->e.seginfo->comdat_selection = opndx.value; dir->e.seginfo->combine = type->value; break; #endif case INIT_OFSSIZE: case INIT_OFSSIZE_FLAT: /* v2.07: check for compatible cpu mode */ if ( type->value == USE32 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_386 ) #if AMD64_SUPPORT || type->value == USE64 && ( ( ModuleInfo.curr_cpu & P_CPU_MASK ) < P_64 ) #endif ) { EmitError( INSTRUCTION_OR_REGISTER_NOT_ACCEPTED_IN_CURRENT_CPU_MODE ); break; } if ( type->init == INIT_OFSSIZE_FLAT ) { DefineFlatGroup(); #if AMD64_SUPPORT dir->e.seginfo->Ofssize = ModuleInfo.defOfssize; #else dir->e.seginfo->Ofssize = USE32; #endif /* put the segment into the FLAT group. * this is not quite Masm-compatible, because trying to put * the segment into another group will cause an error. */ dir->e.seginfo->group = &ModuleInfo.flat_grp->sym; } else dir->e.seginfo->Ofssize = type->value; break; #if COFF_SUPPORT || ELF_SUPPORT case INIT_CHAR_INFO: dir->e.seginfo->info = TRUE; break; case INIT_CHAR: DebugMsg1(("SegmentDir(%s): characteristics found\n", name )); ; /* characteristics are restricted to COFF/ELF */ if ( Options.output_format == OFORMAT_OMF || Options.output_format == OFORMAT_BIN ) { EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr ); } else dir->e.seginfo->characteristics |= type->value; break; case INIT_ALIAS: DebugMsg1(("SegmentDir(%s): ALIAS found\n", name )); if ( Options.output_format != OFORMAT_COFF && Options.output_format != OFORMAT_ELF ) { EmitErr( NOT_SUPPORTED_WITH_CURR_FORMAT, tokenarray[i].string_ptr ); i = Token_Count; /* stop further parsing of this line */ break; } i++; if ( tokenarray[i].token != T_OP_BRACKET ) { EmitErr( EXPECTED, "(" ); break; } i++; if ( tokenarray[i].token != T_STRING || ( tokenarray[i].string_delim != '"' && tokenarray[i].string_delim != '\'' ) ) { EmitErr( SYNTAX_ERROR_EX, token ); i = Token_Count; /* stop further parsing of this line */ break; } temp = i; i++; if ( tokenarray[i].token != T_CL_BRACKET ) { EmitErr( EXPECTED, ")" ); break; } dir->e.seginfo->aliasname = LclAlloc( tokenarray[temp].stringlen ); memcpy( dir->e.seginfo->aliasname, tokenarray[temp].string_ptr+1, tokenarray[temp].stringlen ); *(dir->e.seginfo->aliasname+tokenarray[temp].stringlen) = NULLC; break; #endif #ifdef DEBUG_OUT default: /* shouldn't happen */ myassert( 0 ); break; #endif } } /* end for */ /* make a guess about the segment's type */ if( dir->e.seginfo->segtype != SEGTYPE_CODE ) { enum seg_type res; token = GetLname( dir->e.seginfo->class_name_idx ); res = TypeFromClassName( dir, token ); if( res != SEGTYPE_UNDEF ) { dir->e.seginfo->segtype = res; } #if 0 /* v2.03: removed */ else { res = TypeFromSegmentName( name ); dir->e.seginfo->segtype = res; } #endif } if( is_old ) { int txt = 0; /* Check if new definition is different from previous one */ // oldobj = dir->e.seginfo->segrec; if( oldreadonly != dir->e.seginfo->readonly ) txt = TXT_READONLY; else if ( oldalign != dir->e.seginfo->alignment ) txt = TXT_ALIGNMENT; else if ( oldcombine != dir->e.seginfo->combine ) txt = TXT_COMBINE; else if ( oldOfssize != dir->e.seginfo->Ofssize ) txt = TXT_SEG_WORD_SIZE; else if ( oldclassidx != dir->e.seginfo->class_name_idx ) txt = TXT_CLASS; /* Masm warns only! */ else if ( oldcharacteristics != dir->e.seginfo->characteristics ) txt = TXT_CHARACTERISTICS; if ( txt ) { EmitErr( SEGDEF_CHANGED, dir->sym.name, MsgGetEx( txt ) ); //return( ERROR ); /* v2: display error, but continue */ } } else { /* A new definition */ sym = &dir->sym; sym->isdefined = TRUE; sym->segment = sym; sym->offset = 0; if( dir->e.seginfo->lname_idx == 0 ) { dir->e.seginfo->lname_idx = ++LnamesIdx; AddLnameData( sym ); } } push_seg( dir ); /* set CurrSeg */ if ( ModuleInfo.list ) LstWrite( LSTTYPE_LABEL, 0, NULL ); return( SetOfssize() ); }
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 ); }
ret_code CatStrDir( int i, struct asm_tok tokenarray[] ) /******************************************************/ { struct asym *sym; int count; char *p; /* struct expr opndx; */ DebugMsg1(("CatStrDir(%u) enter\n", i )); DebugCmd( catstrcnt++ ); #if 0 /* can't happen */ /* syntax must be <id> CATSTR textitem[,textitem,...] */ if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif i++; /* go past CATSTR/TEXTEQU */ /* v2.08: don't copy to temp buffer */ //*StringBufferEnd = NULLC; /* check correct syntax and length of items */ for ( count = 0; i < Token_Count; ) { DebugMsg1(("CatStrDir(%s): item[%u]=%s delim=0x%x\n", tokenarray[0].string_ptr, i, tokenarray[i].string_ptr, tokenarray[i].string_delim )); if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { DebugMsg(("CatStrDir: error, not a <>-literal: %s\n", tokenarray[i].tokpos )); return( TextItemError( &tokenarray[i] ) ); } /* v2.08: using tokenarray.stringlen is not quite correct, since some chars * are stored in 2 bytes (!) */ if ( ( count + tokenarray[i].stringlen ) >= MAX_LINE_LEN ) { DebugMsg(("CatStrDir: error, literal too long: %u + %u >= %u\n", count, tokenarray[i].stringlen, MAX_LINE_LEN )); return( EmitError( STRING_OR_TEXT_LITERAL_TOO_LONG ) ); } /* v2.08: don't copy to temp buffer */ //strcpy( StringBufferEnd + count, tokenarray[i].string_ptr ); count = count + tokenarray[i].stringlen; i++; if ( ( tokenarray[i].token != T_COMMA ) && ( tokenarray[i].token != T_FINAL ) ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } i++; } sym = SymSearch( tokenarray[0].string_ptr ); if ( sym == NULL ) { sym = SymCreate( tokenarray[0].string_ptr ); DebugMsg1(( "CatStrDir: new symbol %s created\n", sym->name)); } else if( sym->state == SYM_UNDEFINED ) { /* v2.01: symbol has been used already. Using * a textmacro before it has been defined is * somewhat problematic. */ sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); #if FASTPASS SkipSavedState(); /* further passes must be FULL! */ #endif EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name ); } else if( sym->state != SYM_TMACRO ) { /* it is defined as something else, get out */ DebugMsg(( "CatStrDir(%s) exit, symbol redefinition\n", sym->name)); return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } sym->state = SYM_TMACRO; sym->isdefined = TRUE; #if FASTMEM==0 if ( sym->string_ptr ) LclFree( sym->string_ptr ); sym->string_ptr = (char *)LclAlloc( count + 1 ); #else /* v2.08: reuse string space if fastmem is on */ if ( sym->total_size < ( count+1 ) ) { LclFree( sym->string_ptr ); /* is a noop if fastmem is on */ sym->string_ptr = (char *)LclAlloc( count + 1 ); sym->total_size = count + 1; } #endif /* v2.08: don't use temp buffer */ //memcpy( sym->string_ptr, StringBufferEnd, count + 1 ); for ( i = 2, p = sym->string_ptr; i < Token_Count; i += 2 ) { memcpy( p, tokenarray[i].string_ptr, tokenarray[i].stringlen ); p += tokenarray[i].stringlen; } *p = NULLC; DebugMsg1(("CatStrDir(%s) (new) value: >%s<\n", sym->name, sym->string_ptr )); if ( ModuleInfo.list ) LstWrite( LSTTYPE_TMACRO, 0, sym ); return( NOT_ERROR ); }
/* InStr() * defines a numeric variable which contains position of substring. * syntax: * name INSTR [pos,]string, substr */ ret_code InStrDir( int i, struct asm_tok tokenarray[] ) /*****************************************************/ { struct asym *sym; int sizestr; int j; /* int commas; */ char *src; char *p; char *q; char *string1; struct expr opndx; int start = 1; int strpos; DebugMsg1(("InStrDir entry\n")); DebugCmd( instrcnt++ ); if ( i != 1) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } #if 0 /* this is checked in ParseLine() */ if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif i++; /* go past INSTR */ if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { /* v2.11: flag NOUNDEF added - no forward reference accepted */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) return( ERROR ); if ( opndx.kind != EXPR_CONST ) { return( EmitError( CONSTANT_EXPECTED ) ); } start = opndx.value; if ( start <= 0 ) { /* v2.05: don't change the value. if it's invalid, the result * is to be 0. Emit a level 3 warning instead. */ //start = 1; EmitWarn( 3, POSITIVE_VALUE_EXPECTED ); } if ( tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } i++; /* skip comma */ } if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { return( TextItemError( &tokenarray[i] ) ); } /* to compare the strings, the "visible" format is needed, since * the possible '!' operators inside the strings is optional and * must be ignored. */ //src = StringBufferEnd; //sizestr = GetLiteralValue( src, tokenarray[i].string_ptr ); src = tokenarray[i].string_ptr; sizestr = tokenarray[i].stringlen; DebugMsg1(("InStrDir: first string >%s< \n", src )); if ( start > sizestr ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, start ) ); } p = src + start - 1; i++; if ( tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } i++; if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { return( TextItemError( &tokenarray[i] ) ); } //q = GetAlignedPointer( src, sizestr ); //j = GetLiteralValue( q, tokenarray[i].string_ptr ); q = tokenarray[i].string_ptr; j = tokenarray[i].stringlen; DebugMsg1(("InStrDir: second string >%s< \n", q )); i++; if ( tokenarray[i].token != T_FINAL ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } strpos = 0; /* v2.05: check for start > 0 added */ /* v2.08: check for j > 0 added */ if ( ( start > 0 ) && ( sizestr >= j ) && j && ( string1 = strstr( p, q ) )) strpos = string1 - src + 1; if ( sym = CreateVariable( tokenarray[0].string_ptr, strpos ) ) { DebugMsg1(("InStrDir(%s) exit, value=%u\n", tokenarray[0].string_ptr, strpos)); LstWrite( LSTTYPE_EQUATE, 0, sym ); return ( NOT_ERROR ); } return( ERROR ); }
/* SubStr() * defines a text equate. * syntax: name SUBSTR <string>, pos [, size] */ ret_code SubStrDir( int i, struct asm_tok tokenarray[] ) /******************************************************/ { struct asym *sym; char *name; char *p; //char *newvalue; int pos; int size; int cnt; bool chksize; struct expr opndx; DebugMsg1(("SubStrDir enter\n")); DebugCmd( substrcnt++ ); /* at least 5 items are needed * 0 1 2 3 4 5 6 * ID SUBSTR SRC_ID , POS [, LENGTH] */ #if 0 /* can't happen */ if ( i != 1 ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( tokenarray[0].token != T_ID ) { return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) ); } #endif name = tokenarray[0].string_ptr; i++; /* go past SUBSTR */ /* third item must be a string */ if ( tokenarray[i].token != T_STRING || tokenarray[i].string_delim != '<' ) { DebugMsg(("SubStrDir: error, no text item\n")); return( TextItemError( &tokenarray[i] ) ); } p = tokenarray[i].string_ptr; cnt = tokenarray[i].stringlen; i++; DebugMsg1(("SubStrDir(%s): src=>%s<\n", name, p)); if ( tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } i++; /* get pos, must be a numeric value and > 0 */ /* v2.11: flag NOUNDEF added - no forward ref possible */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) { DebugMsg(("SubStrDir(%s): invalid pos value\n", name)); return( ERROR ); } /* v2.04: "string" constant allowed as second argument */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) { DebugMsg(("SubStrDir(%s): pos value is not a constant\n", name)); return( EmitError( CONSTANT_EXPECTED ) ); } /* pos is expected to be 1-based */ pos = opndx.value; if ( pos <= 0 ) { return( EmitError( POSITIVE_VALUE_EXPECTED ) ); } if ( tokenarray[i].token != T_FINAL ) { if ( tokenarray[i].token != T_COMMA ) { return( EmitErr( EXPECTING_COMMA, tokenarray[i].tokpos ) ); } i++; /* get size, must be a constant */ /* v2.11: flag NOUNDEF added - no forward ref possible */ if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, EXPF_NOUNDEF ) == ERROR ) { DebugMsg(("SubStrDir(%s): invalid size value\n", name)); return( ERROR ); } /* v2.04: string constant ok */ //if ( opndx.kind != EXPR_CONST || opndx.string != NULL ) { if ( opndx.kind != EXPR_CONST ) { DebugMsg(("SubStrDir(%s): size value is not a constant\n", name)); return( EmitError( CONSTANT_EXPECTED ) ); } size = opndx.value; if ( tokenarray[i].token != T_FINAL ) { DebugMsg(("SubStrDir(%s): additional items found\n", name)); return( EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ) ); } if ( size < 0 ) { return( EmitError( COUNT_MUST_BE_POSITIVE_OR_ZERO ) ); } chksize = TRUE; } else { size = -1; chksize = FALSE; } #if 0 cnt = pos; /* position p to start of substring */ for ( pos--; pos > 0 && *p ; pos--, p++ ) if ( *p == '!' && *(p+1) != NULLC ) p++; if ( *p == NULLC ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, cnt ) ); } if ( *p == '!' && *(p+1) != NULLC ) p++; for ( newvalue = p, cnt = size; *p && cnt; cnt--, p++ ) if ( *p == '!' && *(p+1) != NULLC ) p++; /* v2.04: check added */ if ( chksize && cnt ) { return( EmitError( COUNT_VALUE_TOO_LARGE ) ); } size = p - newvalue; p = newvalue; #else if ( pos > cnt ) { return( EmitErr( INDEX_VALUE_PAST_END_OF_STRING, pos ) ); } if ( chksize && (pos+size-1) > cnt ) { return( EmitError( COUNT_VALUE_TOO_LARGE ) ); } p += pos - 1; if ( size == -1 ) size = cnt - pos + 1; #endif sym = SymSearch( name ); /* if we've never seen it before, put it in */ if( sym == NULL ) { sym = SymCreate( name ); } else if( sym->state == SYM_UNDEFINED ) { /* it was referenced before being defined. This is * a bad idea for preprocessor text items, because it * will require a full second pass! */ sym_remove_table( &SymTables[TAB_UNDEF], (struct dsym *)sym ); #if FASTPASS SkipSavedState(); EmitWarn( 2, TEXT_MACRO_USED_PRIOR_TO_DEFINITION, sym->name ); #endif } else if( sym->state != SYM_TMACRO ) { /* it is defined as something incompatible, get out */ DebugMsg(( "SubStrDir(%s) error, incompatible type\n", sym->name)); return( EmitErr( SYMBOL_REDEFINITION, sym->name ) ); } sym->state = SYM_TMACRO; sym->isdefined = TRUE; #if FASTMEM==0 if ( sym->string_ptr ) LclFree( sym->string_ptr ); sym->string_ptr = (char *)LclAlloc( size + 1 ); #else if ( sym->total_size < ( size + 1 ) ) { LclFree( sym->string_ptr ); sym->string_ptr = LclAlloc ( size + 1 ); sym->total_size = size + 1; } #endif memcpy( sym->string_ptr, p, size ); *(sym->string_ptr + size) = NULLC; DebugMsg1(("SubStrDir(%s): result=>%s<\n", sym->name, sym->string_ptr )); LstWrite( LSTTYPE_TMACRO, 0, sym ); return( NOT_ERROR ); }
ret_code SimplifiedSegDir( int i, struct asm_tok tokenarray[] ) /*************************************************************/ /* Handles simplified segment directives: .CODE, .STACK, .DATA, .DATA?, .FARDATA, .FARDATA?, .CONST */ { const char *name = NULL; char init; int type; struct expr opndx; DebugMsg1(("SimplifiedSegDir(%s) enter\n", tokenarray[i].string_ptr )); LstWrite( LSTTYPE_DIRECTIVE, 0, NULL ); if( ModuleInfo.model == MODEL_NONE ) { EmitError( MODEL_IS_NOT_DECLARED ); return( ERROR ); } //type = tokenarray[i].value; type = GetSflagsSp( tokenarray[i].tokval ); i++; /* get past the directive token */ if( type == SIM_STACK ) { if ( EvalOperand( &i, tokenarray, Token_Count, &opndx, 0 ) == ERROR ) return( ERROR ); if( opndx.kind == EXPR_EMPTY ) opndx.value = DEFAULT_STACK_SIZE; else if( opndx.kind != EXPR_CONST ) { EmitError( CONSTANT_EXPECTED ); return( ERROR ); } } else { /* Masm accepts a name argument for .CODE and .FARDATA[?] only. * JWasm also accepts this for .DATA[?] and .CONST unless * option -Zne is set. */ if( tokenarray[i].token == T_ID && ( type == SIM_CODE || type == SIM_FARDATA || type == SIM_FARDATA_UN || ( Options.strict_masm_compat == FALSE && ( type == SIM_DATA || type == SIM_DATA_UN || type == SIM_CONST )))) { name = tokenarray[i].string_ptr; i++; } } if ( tokenarray[i].token != T_FINAL ) { EmitErr( SYNTAX_ERROR_EX, tokenarray[i].string_ptr ); return( ERROR ); } NewLineQueue(); if( type != SIM_STACK ) close_currseg(); /* emit a "xxx ENDS" line to close current seg */ if ( name == NULL ) init = ( ModuleInfo.simseg_init & ( 1 << type ) ); switch( type ) { case SIM_CODE: /* .code */ SetSimSeg( SIM_CODE, name ); if( ModuleInfo.model == MODEL_TINY ) { /* v2.05: add the named code segment to DGROUP */ if ( name ) AddToDgroup( SIM_CODE, name ); name = szDgroup; } else if( ModuleInfo.model == MODEL_FLAT ) { name = "FLAT"; } else { if( name == NULL ) name = SegmNames[SIM_CODE]; } AddLineQueueX( "%r %r:%s", T_ASSUME, T_CS, name ); break; case SIM_STACK: /* .stack */ /* if code is generated which does "emit" bytes, * the original source line has to be saved. * v2.05: must not be done after LstWrite() has been called! * Also, there are no longer bytes "emitted". */ //FStoreLine(); SetSimSeg( SIM_STACK, NULL ); AddLineQueueX( "ORG 0%xh", NUMQUAL opndx.value ); EndSimSeg( SIM_STACK ); /* add stack to dgroup for some segmented models */ if ( !init ) if ( ModuleInfo.distance != STACK_FAR ) AddToDgroup( SIM_STACK, NULL ); break; case SIM_DATA: /* .data */ case SIM_DATA_UN: /* .data? */ case SIM_CONST: /* .const */ SetSimSeg( type, name ); AddLineQueueX( "%r %r:ERROR", T_ASSUME, T_CS ); if ( name || (!init) ) AddToDgroup( type, name ); break; case SIM_FARDATA: /* .fardata */ case SIM_FARDATA_UN: /* .fardata? */ SetSimSeg( type, name ); AddLineQueueX( "%r %r:ERROR", T_ASSUME, T_CS ); break; default: /* shouldn't happen */ /**/myassert( 0 ); break; } RunLineQueue(); DebugMsg1(("SimplifiedSegDir exit\n")); return( NOT_ERROR ); }