#include #include #include #include "ByteCodePrinter.h" #define LINE_LENGTH 80 static ByteCode* code; static int readIndex; static int line; static char buffer[LINE_LENGTH]; static int bIndex; static void btPrintHeading() { puts("| Index | Line | Operation | Argument 1 | Argument 2 |"); puts("|--------|-------|----------------------|------------|------------|"); } static void btAdd(const char* format, ...) { va_list args; va_start(args, format); bIndex += vsnprintf(buffer + bIndex, LINE_LENGTH - bIndex, format, args); va_end(args); } static void btFillBase() { buffer[0] = '\0'; bIndex = 0; btAdd("| %6d | %5d |", readIndex - 1, line); } static void btRead(void* buffer, int length) { if(readIndex + length > code->length) { return; } memcpy(buffer, code->code + readIndex, length); readIndex += length; } static void btAddOperation(const char* s) { if(s[0] != '\0' && s[1] != '\0' && s[2] != '\0' && s[3] != '\0') { s += 3; } btAdd(" %20s |", s); } static void btAddInt() { int value = 0; btRead(&value, sizeof(int)); btAdd(" %10d |", value); } static void btAddFloat() { float value = 0; btRead(&value, sizeof(float)); btAdd(" %10.2f |", value); } static void btAddFiller() { btAdd(" |"); } static void sPrintLine() { btRead(&line, 2); printf("| %6d |-------|----------------------|------------|------------|\n", readIndex - 3); } static void btPrintOp(const char* op) { btFillBase(); btAddOperation(op); btAddFiller(); btAddFiller(); puts(buffer); } static void btPrintInt(const char* op) { btFillBase(); btAddOperation(op); btAddInt(); btAddFiller(); puts(buffer); } static void btPrintInt2(const char* op) { btFillBase(); btAddOperation(op); btAddInt(); btAddInt(); puts(buffer); } static void btPrintFloat(const char* op) { btFillBase(); btAddOperation(op); btAddFloat(); btAddFiller(); puts(buffer); } static void btPrintString(const char* msg) { btFillBase(); int length = 0; btRead(&length, sizeof(int)); char* s = (char*)(code->code + readIndex); readIndex += length; btAddOperation(msg); btAdd(" %10s |", s); btAddFiller(); puts(buffer); } #define PRINT_OP_BASE(op, name) \ case op: \ btPrint##name(#op); \ break; #define PRINT_OP(op) PRINT_OP_BASE(op, Op) #define PRINT_OP_INT(op) PRINT_OP_BASE(op, Int) #define PRINT_OP_INT2(op) PRINT_OP_BASE(op, Int2) static void btConsumeOperation() { int op = code->code[readIndex++]; switch(op) { PRINT_OP(OP_NOTHING); PRINT_OP_INT(OP_PUSH_INT); PRINT_OP_BASE(OP_PUSH_FLOAT, Float); PRINT_OP(OP_PUSH_NULL); PRINT_OP(OP_PUSH_TRUE); PRINT_OP(OP_PUSH_FALSE); PRINT_OP_INT2(OP_PUSH_VARS); PRINT_OP_INT(OP_POP_VARS); PRINT_OP(OP_POP); PRINT_OP(OP_SET); PRINT_OP(OP_PRE_INCREMENT); PRINT_OP(OP_POST_INCREMENT); PRINT_OP(OP_PRE_DECREMENT); PRINT_OP(OP_POST_DECREMENT); PRINT_OP(OP_ADD); PRINT_OP(OP_SUB); PRINT_OP(OP_MUL); PRINT_OP(OP_DIV); PRINT_OP(OP_MOD); PRINT_OP(OP_INVERT_SIGN); PRINT_OP(OP_LESS); PRINT_OP(OP_GREATER); PRINT_OP(OP_EQUAL); PRINT_OP(OP_NOT); PRINT_OP(OP_AND); PRINT_OP(OP_OR); PRINT_OP(OP_BIT_NOT); PRINT_OP(OP_BIT_AND); PRINT_OP(OP_BIT_OR); PRINT_OP(OP_BIT_XOR); PRINT_OP(OP_LEFT_SHIFT); PRINT_OP(OP_RIGHT_SHIFT); PRINT_OP(OP_PRINT); PRINT_OP_INT(OP_GOTO); PRINT_OP_INT2(OP_GOSUB); PRINT_OP_INT(OP_IF_GOTO); PRINT_OP(OP_SET_RETURN); PRINT_OP(OP_RETURN); PRINT_OP(OP_DUPLICATE); PRINT_OP(OP_ALLOCATE_ARRAY); PRINT_OP(OP_ARRAY_LENGTH); PRINT_OP_INT(OP_REFERENCE_FROM_VAR); PRINT_OP_INT(OP_REFERENCE_FROM_ARRAY); PRINT_OP(OP_DEREFERENCE); PRINT_OP_BASE(OP_PUSH_CONST_STRING, String); case OP_LINE: sPrintLine(); break; default: printf("Unknown: %d\n", op); } } void btPrint(ByteCode* bt) { code = bt; readIndex = 0; line = 0; btPrintHeading(); while(readIndex < code->length) { btConsumeOperation(); } }