#include #include #include #include "utils/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 btAddLong() { long value = 0; btRead(&value, sizeof(long)); btAdd(" %10d |", value); } static void btAddByte() { char value = 0; btRead(&value, sizeof(char)); btAdd(" %10d |", (int)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 btPrintLong(const char* op) { btFillBase(); btAddOperation(op); btAddLong(); btAddFiller(); puts(buffer); } static void btPrintByte(const char* op) { btFillBase(); btAddOperation(op); btAddByte(); 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); } #define PRINT_OP_BASE(op, name) \ case op: \ btPrint##name(#op); \ break; #define PRINT_OP(op) PRINT_OP_BASE(op, Op) #define PRINT_OP_BYTE(op) PRINT_OP_BASE(op, Byte) #define PRINT_OP_INT(op) PRINT_OP_BASE(op, Int) #define PRINT_OP_INT2(op) PRINT_OP_BASE(op, Int2) #define PRINT_OP_LONG(op) PRINT_OP_BASE(op, Long) #define PRINT_INTEGRAL_OP(op) PRINT_OP(OP_##op##_INT) PRINT_OP(OP_##op##_LONG) #define PRINT_NUMBER_OP(op) PRINT_INTEGRAL_OP(op) PRINT_OP(OP_##op##_FLOAT) #define PRINT_TYPES(TYPE) \ PRINT_OP(OP_STORE_##TYPE); \ PRINT_OP(OP_LOAD_##TYPE); \ PRINT_OP_INT(OP_RETURN_##TYPE); \ PRINT_OP(OP_EQUAL_##TYPE); static void btConsumeOperation() { Operation op = code->code[readIndex++]; switch(op) { PRINT_TYPES(INT); PRINT_TYPES(LONG); PRINT_TYPES(BOOL); PRINT_TYPES(FLOAT); PRINT_OP(OP_NOTHING); PRINT_OP_LONG(OP_PUSH_LONG); PRINT_OP_INT(OP_PUSH_INT); PRINT_OP_BASE(OP_PUSH_FLOAT, Float); PRINT_OP(OP_PUSH_TRUE); PRINT_OP(OP_PUSH_FALSE); PRINT_OP(OP_PUSH_NULLPTR); PRINT_NUMBER_OP(ADD); PRINT_NUMBER_OP(SUB); PRINT_NUMBER_OP(MUL); PRINT_NUMBER_OP(DIV); PRINT_OP(OP_MOD_INT); PRINT_OP(OP_MOD_LONG); PRINT_NUMBER_OP(INVERT_SIGN); PRINT_NUMBER_OP(LESS); PRINT_NUMBER_OP(GREATER); PRINT_OP(OP_NOT); PRINT_OP(OP_AND); PRINT_OP(OP_OR); PRINT_INTEGRAL_OP(BIT_NOT); PRINT_INTEGRAL_OP(BIT_AND); PRINT_INTEGRAL_OP(BIT_OR); PRINT_INTEGRAL_OP(BIT_XOR); PRINT_INTEGRAL_OP(LEFT_SHIFT); PRINT_INTEGRAL_OP(RIGHT_SHIFT); PRINT_OP_INT(OP_GOTO); PRINT_OP_INT(OP_IF_GOTO); PRINT_OP_INT(OP_PEEK_FALSE_GOTO); PRINT_OP_INT(OP_PEEK_TRUE_GOTO); PRINT_OP_INT2(OP_GOSUB); PRINT_OP_INT(OP_RETURN); PRINT_OP_INT(OP_RETURN_POINTER); PRINT_OP_INT2(OP_RESERVE); PRINT_OP_INT(OP_DEREFERENCE_VAR); PRINT_OP(OP_REFERENCE); PRINT_OP(OP_DUPLICATE_REFERENCE); PRINT_OP_INT(OP_ADD_REFERENCE); PRINT_OP_INT(OP_NEW); PRINT_OP(OP_DELETE); PRINT_OP(OP_LENGTH); PRINT_OP_INT(OP_LOAD); PRINT_OP(OP_STORE_POINTER); PRINT_OP(OP_EQUAL_POINTER); PRINT_OP_BYTE(OP_PUSH_PRE_CHANGE_INT); PRINT_OP_BYTE(OP_PUSH_POST_CHANGE_INT); PRINT_OP_BYTE(OP_CHANGE_INT); PRINT_OP_BYTE(OP_PUSH_PRE_CHANGE_LONG); PRINT_OP_BYTE(OP_PUSH_POST_CHANGE_LONG); PRINT_OP_BYTE(OP_CHANGE_LONG); PRINT_OP(OP_INT_TO_FLOAT); PRINT_OP(OP_FLOAT_TO_INT); PRINT_OP(OP_INT_TO_LONG); PRINT_OP(OP_LONG_TO_INT); PRINT_OP(OP_FLOAT_TO_LONG); PRINT_OP(OP_LONG_TO_FLOAT); PRINT_OP_INT(OP_CALL); case OP_LINE: sPrintLine(); break; } } void btPrint(ByteCode* bt) { code = bt; readIndex = 0; line = 0; btPrintHeading(); while(readIndex < code->length) { btConsumeOperation(); } }