📄 brun.c
字号:
break; // break event case -2: prog_error=-2; if ( os_graphics ) dev_settextcolor(0, 15); dev_printf("\n\a* BREAK AT LINE %d *\n", prog_line); break; }; } // if ( !prog_error ) { // next command code = prog_source[prog_ip]; prog_ip ++; switch ( code ) { case kwLABEL: case kwREM: case kwTYPE_EOC: continue; case kwTYPE_LINE: prog_line = code_getnext16(); if ( trace_flag ) dev_printf("<%d>", prog_line); continue; case kwLET: cmd_let(0); break; case kwCONST: cmd_let(1); break; case kwGOTO: next_ip = code_getnext16(); // clear the stack (whatever you can) pops = code_getnext(); while ( pops > 0 ) { code_pop(NULL); pops --; } // jump prog_ip = next_ip; continue; case kwGOSUB: cmd_gosub(); if ( prog_error ) break; continue; case kwRETURN: cmd_return(); if ( prog_error ) break; continue; case kwONJMP: cmd_on_go(); if ( prog_error ) break; continue; case kwPRINT: cmd_print(); break; case kwINPUT: cmd_input(); break; case kwCLS: dev_cls(); graph_reset(); break; case kwIF: cmd_if(); if ( prog_error ) break; continue; case kwELIF: cmd_elif(); if ( prog_error ) break; continue; case kwELSE: cmd_else(); if ( prog_error ) break; continue; case kwENDIF: code_pop(&node); // 'GOTO' SHIT while ( node.type != kwIF ) { code_pop(&node); if ( prog_error ) break; } if ( !prog_error ) { prog_ip += 4; continue; } break; case kwFOR: cmd_for(); if ( prog_error ) break; continue; case kwNEXT: cmd_next(); if ( prog_error ) break; continue; case kwWHILE: cmd_while(); if ( prog_error ) break; continue; case kwWEND: cmd_wend(); if ( prog_error ) break; continue; case kwREPEAT: node.type = kwREPEAT; prog_ip += 2; node.exit_ip = code_getnext16(); code_push(&node); continue; case kwUNTIL: cmd_until(); if ( prog_error ) break; continue; case kwDIM: cmd_dim(); break; case kwERASE: cmd_erase(); break; case kwREAD: cmd_read(); break; case kwDATA: cmd_data(); break; case kwRESTORE: cmd_restore(); break; case kwTYPE_CALL_UDP: // user defined procedure cmd_udp(kwPROC); if ( isf ) udf_level ++; if ( prog_error ) break; continue; case kwTYPE_CALL_UDF: // user defined function if ( isf ) { cmd_udp(kwFUNC); udf_level ++; } else err_syntax(); if ( prog_error ) break; continue; case kwTYPE_RET: cmd_udpret(); if ( isf ) { udf_level --; if ( udf_level == 0 ) return; } if ( prog_error ) break; continue; case kwTYPE_CRVAR: cmd_crvar(); break; case kwTYPE_PARAM: cmd_param(); break; case kwEXIT: cmd_exit(); if ( prog_error ) break; continue; // ... case kwPEN: cmd_pen(); break; case kwRANDOMIZE: cmd_randomize(); break; // graphics case kwPSET: cmd_pset(); break; case kwLINE: cmd_line(); break; case kwRECT: cmd_rect(); break; case kwCIRCLE: cmd_circle(); break; case kwDRAWPOLY: cmd_drawpoly(); break; // third class case kwAT: cmd_at(); break; case kwLOCATE: cmd_locate(); break; case kwCOLOR: cmd_color(); break; case kwBEEP: cmd_beep(); break; case kwSOUND: cmd_sound(); break; case kwPAUSE: cmd_pause(); break; case kwDELAY: cmd_delay(); break; case kwARC: cmd_arc(); break; case kwDRAW: cmd_draw(); break; case kwPLAY: cmd_play(); break; // --- at end --- case kwWSPLIT: cmd_wsplit(); break; case kwOPEN: cmd_fopen(); break; case kwCLOSE: cmd_fclose(); break; case kwFILEPRINT: cmd_fprint(); break; case kwLINEINPUT: cmd_flineinput(); break; case kwFILEINPUT: cmd_finput(); break; case kwSEEK: cmd_fseek(); break; case kwCOPY: cmd_filecp(0); break; case kwRENAME: cmd_filecp(1); break; case kwKILL: cmd_fkill(); break; case kwTRON: trace_flag = 1; continue; case kwTROFF: trace_flag = 0; continue; case kwCHART: cmd_chart(); break; case kwSTOP: case kwEND: prog_error = -1; break; case kwCHAIN: cmd_chain(); break; case kwRUN: cmd_run(); break; case kwLOGPRINT: cmd_logprint(); break; #ifdef BC_DEBUG /* This debugging command will dump the next few bytes of the byte code ** program then exit. */ case kwBCDUMP: cmd_bcdump(); prog_error = -1; break; case kwSTKDUMP: dev_print("\nSTKDUMP:\n"); dump_stack(); prog_error = -1; break; #endif default: rt_raise("OUT OF CODE SEG->CODE[0x%2X]=0x%X", prog_ip, prog_source[prog_ip]); } } // too many parameters code = prog_source[prog_ip]; if ( code != kwTYPE_EOC && code != kwTYPE_LINE && !prog_error ) rt_raise("PARAM COUNT ERROR @%d=%X", prog_ip, prog_source[prog_ip]); else { prog_ip ++; if ( code == kwTYPE_LINE ) { prog_line = code_getnext16(); if ( trace_flag ) dev_printf("<%d>", prog_line); } } // quit on error if ( prog_error ) { // cleanup stack while ( prog_stack_count > 0 ) { code_pop(&node); switch ( node.type ) { case kwTYPE_CRVAR: v_free(tvar[node.x.vdvar.vid]); // free local variable data tmp_free(tvar[node.x.vdvar.vid]); tvar[node.x.vdvar.vid] = node.x.vdvar.vptr; // restore ptr break; case kwBYREF: tvar[node.x.vdvar.vid] = node.x.vdvar.vptr; break; case kwTYPE_VAR: if ( (node.x.param.vcheck == 1) || (node.x.param.vcheck == 0x81) ) { v_free(node.x.param.res); tmp_free(node.x.param.res); } break; case kwTYPE_RET: v_free(node.x.vdvar.vptr); // free ret-var tmp_free(node.x.vdvar.vptr); break; case kwFUNC: tvar[node.x.vcall.rvid] = node.x.vcall.retvar; // restore ptr break; }; } break; } }}/** executor*/void brun(char *file){ dword tps; brun_load(file); if ( prog_error ) return; dev_init(opt_graphics,0); #if defined(_PalmOS) tps = SysTicksPerSecond(); #else tps = CLOCKS_PER_SEC; #endif evt_check_every = (50 * tps) / 1000; // 50ms bc_loop(0); if ( prog_error == -1 || prog_error == 0 ) { // normal exit if ( os_graphics ) dev_settextcolor(0, 15); dev_print("\n\a* DONE *\n"); prog_error = -1; } brun_close(); dev_restore();}/** debug info* stack dump*/void dump_stack(){ stknode_t node; int i; do { code_pop(&node); if ( node.type != 0xFF ) { for ( i = 0; keyword_table[i].name[0] != '\0'; i ++ ) { if ( node.type == keyword_table[i].code ) { dev_printf("\t%s", keyword_table[i].name); switch ( node.type ) { case kwGOSUB: dev_printf(" RIP: %d", node.x.vgosub.ret_ip); if ( prog_source[node.x.vgosub.ret_ip] == kwTYPE_LINE ) { dev_printf(" = LI %d", (*((word *) (prog_source+node.x.vgosub.ret_ip+1))) - 1); } break; } dev_print("\n"); break; } } } else break; } while ( 1 );}#if !defined(_PalmOS) && !defined(_BCB_W32_IDE)////////////////////////////////////////////////////////////////////////////////////////////// Command-line interface (Unix)/** decompiler*/void dump_bytecode(){ int c, b, d, h, l, j; int len, new_ip; fprintf(stderr, "Program size=%d\n", prog_length); do { b = code_getnext(); h = b >> 4; l = b & 0xF; printf("%06d: %c%c %c ", (int) prog_ip-1, "0123456789ABCDEF"[h], "0123456789ABCDEF"[l], (b>=32) ? b : 42 ); switch ( b ) { case kwTYPE_LINE: printf("--LINE: %d", code_getnext16()); break; case kwTYPE_EVPUSH: printf("PUSH RESULT"); break; case kwTYPE_EVPOP: printf("POP LEFT"); break; case kwTYPE_EOC: printf("--EOC"); break; case kwPROC: printf("=== PROCEDURE ==="); break; case kwFUNC: printf("=== FUNCTION ==="); break; case kwFILEPRINT: printf("FILE PRINT"); break; case kwFILEINPUT: printf("FILE INPUT"); break; case kwLINEINPUT: printf("LINE INPUT"); break; case kwFORSEP: printf("FOR SEP"); break; case kwINPUTSEP: printf("INPUT SEP"); break; case kwTYPE_PARAM: case kwTYPE_CRVAR: c = code_getnext(); if ( b == kwTYPE_PARAM ) printf("PARAM = %d: ", c); else printf("CRVAR = %d: ", c); d = 0; for ( j = 0; j < c; j ++ ) { if ( b == kwTYPE_PARAM ) { d = code_getnext(); if ( d & 0x80 ) printf("&"); } printf("%d ", code_getnext16()); if ( d & 0x1 ) printf("()"); } break; case kwTYPE_RET: printf("=== UDP/F RET ==="); break; case kwTYPE_CALL_UDP: printf("CALL UDP %d", code_getnext16()); code_skipnext16(); break; case kwTYPE_CALL_UDF: printf("CALL UDF %d", code_getnext16()); printf(", RVID: %d", code_getnext16()); break; case kwEXIT: printf("EXIT "); c = code_peek(); if ( c == kwFOR ) { printf("FOR"); code_skipnext(); } if ( c == kwLOOP ) { printf("LOOP"); code_skipnext(); } if ( c == kwPROC ) { printf("PROC"); code_skipnext(); } if ( c == kwFUNC ) { printf("FUNC"); code_skipnext(); } break; default: for ( c = 0; keyword_table[c].name[0] != '\0'; c ++) { if ( b == keyword_table[c].code ) { printf("%s ", keyword_table[c].name); break; } } switch ( b ) { case kwTYPE_SEP: c = code_getnext(); printf("SEPARATOR \'%c\' ", (c>=32) ? c : '?'); break; case kwTYPE_LOGOPR: case kwTYPE_CMPOPR: case kwTYPE_ADDOPR: case kwTYPE_MULOPR: case kwTYPE_POWOPR: case kwTYPE_UNROPR: c = code_getnext(); printf("DATA %d \'%c\' ", c, (c>=32) ? c : '?'); break; case kwTYPE_LEVEL_BEGIN: printf("("); break; case kwTYPE_LEVEL_END: printf(")"); break; case kwONJMP: new_ip = code_getnext16(); code_skipnext16(); b = code_getnext(); c = code_getnext(); printf("ON %s CNT %d\n", ((b == kwGOTO)?"GOTO":"GOSUB"), c); printf(" NEXT IP %d\n", new_ip); for ( j = 0; j < c; j ++ ) printf(" JMP IP %d\n", code_getnext16()); printf("ON %s EXPR:", ((b == kwGOTO)?"GOTO":"GOSUB")); break; case kwGOTO: new_ip = code_getnext16(); printf("= JMP %d ", new_ip); c = code_getnext(); printf("POPs %d", c); break; case kwGOSUB: c = code_getnext16(); printf("ID %d ", c); new_ip = tlab[c].ip; printf("= JMP %d ", new_ip); break; case kwRESTORE: case kwTYPE_LINE: case kwLABEL: case kwTYPE_VAR: case kwLET: printf("ID %d ", code_getnext16()); break; case kwTYPE_INT: printf("VAL %d ", code_getnext32()); break; case kwTYPE_NUM: printf("VAL %f ", code_getnext64f()); break; case kwTYPE_STR: len = code_getnext16(); printf("\""); for ( j = 0; j < len; j ++ ) printf("%c", prog_source[prog_ip+j]); printf("\""); prog_ip += len; break; case kwIF: case kwFOR: case kwWHILE: case kwREPEAT: case kwELSE: case kwELIF: case kwENDIF: case kwNEXT: case kwWEND: case kwUNTIL: printf("IP1 %d IP2 %d ", code_getnext16(), code_getnext16()); break; } } printf("\n"); } while ( prog_ip < prog_length );}/** main*/int main(int argc, char *argv[]){ char file[1024]; char prev_cwd[1024]; char cwd[1024], *slash; byte opt_decomp = 0; //, opt_graphics = 0; int i, use_stdin = 0, c; FILE *fp; printf("SmallBASIC byte-code executor version %s\n", SB_STR_VER); printf("Written by Nicholas Christopoulos\n"); strcpy(file, ""); opt_graphics = 0; for ( i = 1; i < argc; i ++ ) { if ( argv[i][0] == '-' ) { if ( argv[i][1] == 's' ) opt_decomp ++; if ( argv[i][1] == 'g' ) opt_graphics = 2; if ( argv[i][1] == 'j' ) os_charset = enc_sjis; if ( argv[i][1] == 'b' ) os_charset = enc_big5; if ( argv[i][1] == 'm' ) os_charset = enc_gmb; if ( argv[i][1] == 'u' ) os_charset = enc_unicode; if ( argv[i][1] == 'h' ) { fprintf(stderr, "usage: sbrun source [options]\n"); fprintf(stderr, "-s decompiler\n"); fprintf(stderr, "-g enable graphics\n"); fprintf(stderr, "\ncharset (default: utf8)\n"); fprintf(stderr, "-j enable sjis\n"); fprintf(stderr, "-b enable big5\n"); fprintf(stderr, "-m enable generic multibyte\n"); fprintf(stderr, "-u enable unicode!\n"); return 1; } } else strcpy(file, argv[i]); } // getcwd(prev_cwd, 1024); strcpy(cwd, prev_cwd); if ( strlen(file) == 0 ) { // stdin use_stdin ++; #if defined(_Win32) sprintf(file, "sbrun.tmp"); #else sprintf(file, "/tmp/sb%d.bas", getpid()); #endif fp = fopen(file, "wb"); if ( fp ) { while ( (c = fgetc(stdin)) != -1 ) fputc(c, fp); fclose(fp); } else perror("sbrun"); } else { #if defined(_Win32) slash = strrchr(file, '\\'); #else slash = strrchr(file, '/'); #endif if ( slash ) { char tmp[1024]; *slash = '\0'; #if defined(_Win32) strcat(cwd, "\\"); #else strcat(cwd, "/"); #endif strcat(cwd, file); strcpy(tmp, slash+1); strcpy(file, tmp);// printf("Current directory changed to [%s]\n", cwd);// printf("Source file changed to: [%s]\n", file); chdir(cwd); } } if ( opt_decomp ) { brun_load(file); if ( bc_get_error() ) return 1; dump_bytecode(); } else { // run memmgr_init(); brun(file); } // cleanup if ( use_stdin ) remove(file); chdir(prev_cwd); return 0;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -