void main( void ) { //***************** int ctr; char in_str[80]; asmreloc *reloc, *next; TRMemOpen(); AsmInit(); curLine = 0; AsmCodeBuffer = (unsigned char*)buffer; AsmCodeAddress = 0; printf( "AsmCodeAddress = %u.\n", (unsigned)AsmCodeAddress ); gets( in_str ); while( strcmp( in_str, "q" ) != 0 ) { curLine++; AsmLine( in_str ); printf( "AsmCodeAddress = %u.\n", (unsigned)AsmCodeAddress ); // AsmCodeAddress is now updated, and code is filled from // AsmCodeBuffer[0] to AsmCodeBuffer[AsmCodeAddress/ins_size-1] // inclusive. gets( in_str ); } printf( "Generated [before internal fixup]:\n" ); for( ctr = 0; ctr < AsmCodeAddress / sizeof( buffer[0] ); ctr++ ) { printf( " [%#010x]\n", buffer[ctr] ); } AsmFini(); printf( "Generated [after internal fixup]:\n" ); for( ctr = 0; ctr < AsmCodeAddress / sizeof( buffer[0] ); ctr++ ) { printf( " [%#010x]\n", buffer[ctr] ); } for( reloc = AsmRelocs; reloc; reloc = next ) { next = reloc->next; printf( "Reloc:\tname = %s\n" "\toffset = %#010x\n" "\ttype = %s\n", reloc->name, reloc->offset, typeName[reloc->type] ); AsmFree( reloc->name ); AsmFree( reloc ); } #ifdef TRMEM TRMemPrtList(); #endif TRMemClose(); }
static void set_some_kinda_name( char token, char *name ) /*******************************************************/ /* set: code class / data seg. / module name / text seg */ { int len; char **tmp; len = strlen( name ) + 1; switch( token ) { case 'c': tmp = &Options.code_class; break; case 'd': tmp = &Options.data_seg; break; case 'm': tmp = &Options.module_name; break; case 't': tmp = &Options.text_seg; break; default: return; } if( *tmp != NULL ) { AsmFree(*tmp); } *tmp = AsmAlloc( len ); strcpy( *tmp, name ); }
static ret_code HllPushTestLines( hll_list * hll ) /************************************************/ { char *p = hll->condlines; char *p2; char buffer[MAX_LINE_LEN]; DebugMsg(("HllPushTestLines enter\n")); if ( !p ) return( ERROR ); while ( *p ) { if (*p == ' ') p++; /* there might be lines with 1 ' ' only! */ for ( p2=buffer; *p && (*p != 0x0A);) *p2++ = *p++; *p2 = NULLC; if ( *p == 0x0A ) p++; if ( *buffer ) AddLineQueue( buffer ); } AsmFree( hll->condlines ); hll->condlines = NULL; return( NOT_ERROR ); }
static void free_names( void ) /****************************/ /* Free names set as cmdline options */ { if( Options.build_target != NULL ) { AsmFree( Options.build_target ); } if( Options.code_class != NULL ) { AsmFree( Options.code_class ); } if( Options.data_seg != NULL ) { AsmFree( Options.data_seg ); } if( Options.module_name != NULL ) { AsmFree( Options.module_name ); } if( Options.text_seg != NULL ) { AsmFree( Options.text_seg ); } }
static void SetCPUPMC( void ) /***************************/ { char *tmp; for( tmp=OptParm; tmp < OptScanPtr; tmp++ ) { if( *tmp == 'p' ) { if( SWData.cpu >= 2 ) { // set protected mode SWData.protect_mode = TRUE; } else { MsgPrintf1( MSG_CPU_OPTION_INVALID, CopyOfParm() ); } } else if( *tmp == 'r' ) { if( SWData.cpu >= 3 ) { // set register based calling convention Options.watcom_parms_passed_by_regs = TRUE; } else { MsgPrintf1( MSG_CPU_OPTION_INVALID, CopyOfParm() ); } } else if( *tmp == 's' ) { if( SWData.cpu >= 3 ) { // set stack based calling convention Options.watcom_parms_passed_by_regs = FALSE; } else { MsgPrintf1( MSG_CPU_OPTION_INVALID, CopyOfParm() ); } } else if( *tmp == '"' ) { // set default mangler char *dest; tmp++; dest = strchr(tmp, '"'); if( Options.default_name_mangler != NULL ) { AsmFree( Options.default_name_mangler ); } Options.default_name_mangler = AsmAlloc( dest - tmp + 1 ); dest = Options.default_name_mangler; for( ; *tmp != '"'; dest++, tmp++ ) { *dest = *tmp; } *dest = NULLC; } else { MsgPrintf1( MSG_UNKNOWN_OPTION, CopyOfParm() ); exit( 1 ); } } if( SWData.cpu < 3 ) { Options.watcom_parms_passed_by_regs = TRUE; if( SWData.cpu < 2 ) { SWData.protect_mode = FALSE; } } }
void AsmShutDown( void ) /**********************/ { /* close ASM file */ if( AsmFiles.file[ASM] != NULL ) { if( fclose( AsmFiles.file[ASM] ) != 0 ) { Fatal( MSG_CANNOT_CLOSE_FILE, AsmFiles.fname[ASM] ); } } /* close OBJ file */ ObjWriteClose( pobjState.file_out ); ObjRecFini(); if( !write_to_file || Options.error_count > 0 ) { remove( AsmFiles.fname[OBJ] ); } AsmFree( AsmFiles.fname[ASM] ); AsmFree( AsmFiles.fname[ERR] ); AsmFree( AsmFiles.fname[LST] ); AsmFree( AsmFiles.fname[OBJ] ); MemFini(); }
void assemble(char *asmFile, char *objFile) { // 組譯器的主要函數 printf("Assembler:asmFile=%s objFile=%s\n", asmFile,objFile); // 輸入組合語言、輸出目的檔 printf("===============Assemble=============\n"); char *text = fileToStr(asmFile); // 讀取檔案到 text 字串中 Assembler *a = AsmNew(); AsmPass1(a, text); // 第一階段:計算位址 printf("===============SYMBOL TABLE=========\n"); HashTableEach(a->symTable, (FuncPtr1) AsmCodePrintln); // 印出符號表 AsmPass2(a); // 第二階段:建構目的碼 AsmSaveObjFile(a, objFile); AsmFree(a); // 輸出目的檔 memFree(text); // 釋放記憶體 memCheck(); }
static ret_code GetAndExpression( hll_list * hll, int *i, int ilabel, bool is_true, char * buffer, char **lastjmp, expr_list *opndx ) /***********************************************************************************************************************************/ { c_bop op; int cur_pos; char * ptr = buffer; char * truelabel = NULL; //char * nlabel; //char * olabel; DebugMsg(("GetAndExpression(buffer=%s) enter\n", buffer )); while (1) { ptr = ptr + strlen( ptr ); cur_pos = *i; if ( ERROR == GetSimpleExpression( hll, i, ilabel, is_true, ptr, lastjmp, opndx ) ) return( ERROR ); cur_pos = *i; op = GetCOp(i); if (op != COP_AND) break; /* v2.02: query is_true var instead of cmd field! * this is important if the '!' operator was used. */ //if ( hll->cmd == HLL_WHILE || hll->cmd == HLL_BREAK ) { if ( is_true ) { /* todo: please describe what's done here and why! */ if (*lastjmp) { char * p = *lastjmp; InvertJmp( p+1 ); /* step 1 */ if ( truelabel == NULL ) /* step 2 */ truelabel = MakeAnonymousLabel(); ReplaceLabel( buffer, GetLabel( hll, ilabel ), truelabel ); *lastjmp = NULL; } } }; if ( truelabel ) { MakeLabel( ptr+strlen(ptr), truelabel ); strcpy( ptr+strlen( ptr ), "\n" ); AsmFree( truelabel ); *lastjmp = NULL; } *i = cur_pos; return( NOT_ERROR ); }
static void SetTargName( char *name, size_t len ) /***********************************************/ { char *p; if( Options.build_target != NULL ) { AsmFree( Options.build_target ); Options.build_target = NULL; } if( name == NULL || len == 0 ) return; Options.build_target = AsmAlloc( len + 1 ); p = Options.build_target; for( ; len != 0; --len ) { *p++ = (char)toupper( *name++ ); } *p++ = '\0'; }
static void SetTargName( char *name, unsigned len ) /*************************************************/ { char *p; if( Options.build_target != NULL ) { AsmFree( Options.build_target ); Options.build_target = NULL; } if( name == NULL || len == 0 ) return; Options.build_target = AsmAlloc( len + 1 ); p = Options.build_target; while( len != 0 ) { *p++ = toupper( *name++ ); --len; } *p++ = '\0'; }
static ret_code WriteExprSrc( hll_list * hll, char * buffer ) /***********************************************************/ { int size; char *p; size = strlen( buffer ) + 1; if ( hll->condlines ) { size += strlen( hll->condlines ) + 1; } p = AsmAlloc( size ); if ( hll->condlines ) { strcpy( p, hll->condlines ); strcat( p, "\n" ); strcat( p, buffer ); } else strcpy( p, buffer ); AsmFree( hll->condlines ); hll->condlines = p; return( NOT_ERROR ); }
static void get_fname( char *token, int type ) /********************************************/ /* * figure out the source file name & store it in AsmFiles * fill in default object file name if it is null */ { char name [ _MAX_PATH ]; char msgbuf[80]; PGROUP pg; PGROUP def; /* get filename for source file */ if( type == ASM ) { if( token == NULL ) { MsgGet( SOURCE_FILE, msgbuf ); Fatal( MSG_CANNOT_OPEN_FILE, msgbuf ); } if( AsmFiles.fname[ASM] != NULL ) { Fatal( MSG_TOO_MANY_FILES ); } _splitpath2( token, pg.buffer, &pg.drive, &pg.dir, &pg.fname, &pg.ext ); if( *pg.ext == '\0' ) { pg.ext = ASM_EXT; } _makepath( name, pg.drive, pg.dir, pg.fname, pg.ext ); AsmFiles.fname[ASM] = AsmAlloc( strlen( name ) + 1 ); strcpy( AsmFiles.fname[ASM], name ); _makepath( name, pg.drive, pg.dir, NULL, NULL ); /* add the source path to the include path */ AddStringToIncludePath( name ); if( AsmFiles.fname[OBJ] == NULL ) { /* set up default object and error filename */ pg.ext = OBJ_EXT; _makepath( name, NULL, NULL, pg.fname, pg.ext ); } else { _splitpath2( AsmFiles.fname[OBJ], def.buffer, &def.drive, &def.dir, &def.fname, &def.ext ); if( *def.fname == NULLC ) def.fname = pg.fname; if( *def.ext == NULLC ) def.ext = OBJ_EXT; _makepath( name, def.drive, def.dir, def.fname, def.ext ); AsmFree( AsmFiles.fname[OBJ] ); } AsmFiles.fname[OBJ] = AsmAlloc( strlen( name ) + 1 ); strcpy( AsmFiles.fname[OBJ], name ); if( AsmFiles.fname[ERR] == NULL ) { pg.ext = ERR_EXT; _makepath( name, NULL, NULL, pg.fname, pg.ext ); } else { _splitpath2( AsmFiles.fname[ERR], def.buffer, &def.drive, &def.dir, &def.fname, &def.ext ); if( *def.fname == NULLC ) def.fname = pg.fname; if( *def.ext == NULLC ) def.ext = ERR_EXT; _makepath( name, def.drive, def.dir, def.fname, def.ext ); AsmFree( AsmFiles.fname[ERR] ); } AsmFiles.fname[ERR] = AsmAlloc( strlen( name ) + 1 ); strcpy( AsmFiles.fname[ERR], name ); if( AsmFiles.fname[LST] == NULL ) { pg.ext = LST_EXT; _makepath( name, NULL, NULL, pg.fname, pg.ext ); } else { _splitpath2( AsmFiles.fname[LST], def.buffer, &def.drive, &def.dir, &def.fname, &def.ext ); if( *def.fname == NULLC ) def.fname = pg.fname; if( *def.ext == NULLC ) def.ext = LST_EXT; _makepath( name, def.drive, def.dir, def.fname, def.ext ); AsmFree( AsmFiles.fname[LST] ); } AsmFiles.fname[LST] = AsmAlloc( strlen( name ) + 1 ); strcpy( AsmFiles.fname[LST], name ); } else { /* get filename for object, error, or listing file */ _splitpath2( token, pg.buffer, &pg.drive, &pg.dir, &pg.fname, &pg.ext ); if( AsmFiles.fname[ASM] != NULL ) { _splitpath2( AsmFiles.fname[ASM], def.buffer, &def.drive, &def.dir, &def.fname, &def.ext ); if( *pg.fname == NULLC ) { pg.fname = def.fname; } } if( *pg.ext == NULLC ) { switch( type ) { case ERR: pg.ext = ERR_EXT; break; case LST: pg.ext = LST_EXT; break; case OBJ: pg.ext = OBJ_EXT; break; } } _makepath( name, pg.drive, pg.dir, pg.fname, pg.ext ); if( AsmFiles.fname[type] != NULL ) { AsmFree( AsmFiles.fname[type] ); } AsmFiles.fname[type] = AsmAlloc( strlen( name ) + 1 ); strcpy( AsmFiles.fname[type], name ); } }
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 ); }
void FreeForceInclude( void ) /***************************/ { AsmFree( ForceInclude ); }
static ret_code GetExpression( hll_list * hll, int *i, int ilabel, bool is_true, char * buffer, char **lastjmp, expr_list *opndx ) /********************************************************************************************************************************/ { c_bop op; int cur_pos; //bool ordetected = FALSE; char * ptr = buffer; char * truelabel = NULL; char * nlabel; char * olabel; DebugMsg(("GetExpression(buffer=%s) enter\n", buffer )); for ( ;; ) { ptr = ptr + strlen( ptr ); cur_pos = *i; if ( ERROR == GetAndExpression( hll, i, ilabel, is_true, ptr, lastjmp, opndx ) ) return( ERROR ); cur_pos = *i; op = GetCOp( i ); if ( op != COP_OR ) { *i = cur_pos; if ( truelabel ) { MakeLabel1( ptr+strlen( ptr ), truelabel ); AsmFree( truelabel ); } break; } /* the generated code of last simple expression has to be modified 1. the last jump must be inverted 2. a "is_true" label must be created (it's used to jump "behind" the expr) 3. create a new label 4. the current "false" label must be generated if it is a .REPEAT, step 4 is slightly more difficult, since the "false" label is already "gone": 4a. create a new label 4b. replace the "false" label in the generated code by the new label */ /* v2.02: query is_true var instead of cmd field! * this is important if the '!' operator was used. */ //if (*lastjmp && ( hll->cmd != HLL_BREAK ) && ( hll->cmd != HLL_WHILE ) ) { if ( *lastjmp && is_true == FALSE ) { char * p = *lastjmp; InvertJmp(p+1); /* step 1 */ p += 4; if ( truelabel == NULL ) /* step 2 */ truelabel = MakeAnonymousLabel(); strcpy( p, truelabel ); strcat( p, "\n" ); *lastjmp = NULL; nlabel = MakeAnonymousLabel(); /* step 3 */ olabel = GetLabel( hll, ilabel ); if ( hll->cmd == HLL_REPEAT ) { ReplaceLabel( buffer, olabel, nlabel ); MakeLabel1( ptr+strlen(ptr), nlabel ); } else { #if 0 MakeLabel1( ptr+strlen(ptr), olabel ); SetLabel(hll, ilabel, nlabel); #else MakeLabel1( ptr+strlen(ptr), olabel ); ReplaceLabel( buffer, olabel, nlabel ); #endif } } } 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 ); }
static int ProcOptions( char *str, int *level ) /*********************************************/ { char *save[MAX_NESTING]; char *buffers[MAX_NESTING]; if( str != NULL ) { for( ;; ) { while( *str == ' ' || *str == '\t' ) ++str; if( *str == '@' && *level < MAX_NESTING ) { save[(*level)++] = CollectEnvOrFileName( str + 1 ); buffers[*level] = NULL; str = getenv( ParamBuf ); if( str == NULL ) { str = ReadIndirectFile(); buffers[*level] = str; } if( str != NULL ) continue; str = save[--(*level)]; } if( *str == '\0' ) { if( *level == 0 ) break; if( buffers[*level] != NULL ) { AsmFree( buffers[*level] ); buffers[*level] = NULL; } str = save[--(*level)]; continue; } if( *str == '-' || *str == SwitchChar ) { str = ProcessOption(str+1, str); } else { /* collect file name */ char *beg, *p; int len; beg = str; if( *str == '"' ) { for( ;; ) { ++str; if( *str == '"' ) { ++str; break; } if( *str == '\0' ) break; if( *str == '\\' ) { ++str; } } } else { for( ;; ) { if( *str == '\0' ) break; if( *str == ' ' ) break; if( *str == '\t' ) break; #if !defined(__UNIX__) if( *str == SwitchChar ) break; #endif ++str; } } len = str-beg; p = (char *) AsmAlloc( len + 1 ); memcpy( p, beg, len ); p[ len ] = '\0'; StripQuotes( p ); get_fname( p, ASM ); AsmFree(p); } } } return( 0 ); }
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 ); }