#include #include #include #include "Types.h" #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 btPrintEnd(void) { puts("+--------+-------+----------------------+------------+------------+"); } static void btPrintHeading(void) { btPrintEnd(); puts("| Index | Line | Operation | Argument 1 | Argument 2 |"); btPrintEnd(); } static void btAdd(const char* format, ...) { va_list args; va_start(args, format); bIndex += vsnprintf(buffer + bIndex, (size_t)(LINE_LENGTH - bIndex), format, args); va_end(args); } static void btFillBase(void) { buffer[0] = '\0'; bIndex = 0; btAdd("| %6d | %5d |", readIndex - 1, line); } static void btRead(void* b, int length) { if(readIndex + length > code->length) { return; } memcpy(b, code->code + readIndex, (size_t)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 btAddInt32(void) { int32 value = 0; btRead(&value, sizeof(int32)); btAdd(" %10d |", value); } static void btAddInt8(void) { int8 value = 0; btRead(&value, sizeof(int8)); btAdd(" %10d |", (int32)value); } static void btAddFloat(void) { float value = 0; btRead(&value, sizeof(float)); btAdd(" %10.2lf |", (double)value); } static void btAddText(void) { int32 length = 0; btRead(&length, sizeof(int32)); for(int i = 0; i < length; i++) { int32 c; btRead(&c, sizeof(int32)); } btAdd(" %10s |", "Text"); } static void btAddFiller(void) { btAdd(" |"); } static void sPrintLine(void) { btRead(&line, 2); printf("| %6d |-------|----------------------|------------|------------|\n", readIndex - 3); } static void btPrintOp(const char* op) { btFillBase(); btAddOperation(op); btAddFiller(); btAddFiller(); puts(buffer); } static void btPrintInt32(const char* op) { btFillBase(); btAddOperation(op); btAddInt32(); btAddFiller(); puts(buffer); } static void btPrintInt8(const char* op) { btFillBase(); btAddOperation(op); btAddInt8(); btAddFiller(); puts(buffer); } static void btPrint2Int32(const char* op) { btFillBase(); btAddOperation(op); btAddInt32(); btAddInt32(); puts(buffer); } static void btPrintFloat(const char* op) { btFillBase(); btAddOperation(op); btAddFloat(); btAddFiller(); puts(buffer); } static void btPrintText(const char* op) { btFillBase(); btAddOperation(op); btAddText(); 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_INT8(op) PRINT_OP_BASE(op, Int8) #define PRINT_OP_INT32(op) PRINT_OP_BASE(op, Int32) #define PRINT_OP_2INT32(op) PRINT_OP_BASE(op, 2Int32) #define PRINT_OP_INT64(op) PRINT_OP_BASE(op, Int64) #define PRINT_INTEGRAL_OP(op) PRINT_OP(OP_##op##_INT) #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_INT32(OP_RETURN_##TYPE); \ PRINT_OP(OP_EQUAL_##TYPE); \ PRINT_OP(OP_NOT_EQUAL_##TYPE); static void btConsumeOperation(void) { Operation op = (Operation)code->code[readIndex++]; switch(op) { PRINT_TYPES(INT); PRINT_TYPES(FLOAT); PRINT_OP(OP_NOTHING); PRINT_OP_INT32(OP_PUSH_INT); PRINT_OP_BASE(OP_PUSH_FLOAT, Float); PRINT_OP_BASE(OP_PUSH_TEXT, Text); PRINT_NUMBER_OP(ADD); PRINT_NUMBER_OP(SUB); PRINT_NUMBER_OP(MUL); PRINT_NUMBER_OP(DIV); PRINT_INTEGRAL_OP(MOD); PRINT_NUMBER_OP(INVERT_SIGN); PRINT_NUMBER_OP(LESS); PRINT_NUMBER_OP(LESS_EQUAL); PRINT_NUMBER_OP(GREATER); PRINT_NUMBER_OP(GREATER_EQUAL); 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_INT32(OP_GOTO); PRINT_OP_INT32(OP_IF_GOTO); PRINT_OP_INT32(OP_PEEK_FALSE_GOTO); PRINT_OP_INT32(OP_PEEK_TRUE_GOTO); PRINT_OP_2INT32(OP_GOSUB); PRINT_OP_INT32(OP_RETURN); PRINT_OP_INT32(OP_RETURN_POINTER); PRINT_OP_2INT32(OP_RESERVE); PRINT_OP_INT32(OP_GRESERVE); PRINT_OP_INT32(OP_DEREFERENCE_VAR); PRINT_OP_INT32(OP_DEREFERENCE_GVAR); PRINT_OP(OP_LOAD_ARRAY); PRINT_OP(OP_DUPLICATE_REFERENCE); PRINT_OP_INT32(OP_ADD_REFERENCE); PRINT_OP_INT32(OP_NEW); PRINT_OP(OP_LENGTH); PRINT_OP_INT32(OP_PUSH_STRUCT_REFERENCE); PRINT_OP(OP_STORE_ARRAY); PRINT_OP(OP_EQUAL_POINTER); PRINT_OP(OP_NOT_EQUAL_POINTER); PRINT_OP_INT8(OP_PUSH_PRE_CHANGE_INT); PRINT_OP_INT8(OP_PUSH_POST_CHANGE_INT); PRINT_OP_INT8(OP_CHANGE_INT); PRINT_OP(OP_INT_TO_FLOAT); PRINT_OP(OP_FLOAT_TO_INT); PRINT_OP_INT32(OP_CALL); case OP_LINE: sPrintLine(); break; } } void btPrint(ByteCode* bt) { code = bt; readIndex = 0; line = 0; btPrintHeading(); while(readIndex < code->length) { btConsumeOperation(); } btPrintEnd(); }