diff --git a/meta/4tech_file_moving.h b/meta/4tech_file_moving.h index 5e450f7b..a0e30984 100644 --- a/meta/4tech_file_moving.h +++ b/meta/4tech_file_moving.h @@ -1,50 +1,875 @@ /* -4tech_file_moving.h - Code for moving files around on the file system. -By Allen Webster -21.01.2017 (dd.mm.yyyy) -*/ + * Mr. 4th Dimention - Allen Webster + * + * 21.01.2017 + * + * Code for file manipulating scripts. + * + */ // TOP #if !defined(FTECH_FILE_MOVING_H) #define FTECH_FILE_MOVING_H +#include "../4tech_defines.h" +#include "../4coder_lib/4coder_string.h" + #include // include system for windows #include // include system for linux (YAY!) +#include -// NOTE(allen): Compiler/OS cracking. -#if defined(_MSC_VER) +static char SF_CMD[4096]; +static i32 error_state = 0; +static i32 prev_error = 0; -# if !defined(IS_CL) -# define IS_CL -# endif - -# define snprintf _snprintf - -# if defined(_WIN32) -# define IS_WINDOWS -# pragma comment(lib, "Kernel32.lib") -# else -# error This compiler/platform combo is not supported yet -# endif - -#elif defined(__GNUC__) || defined(__GNUG__) - -# if !defined(IS_GCC) -# define IS_GCC -# endif - -# if defined(__gnu_linux__) -# define IS_LINUX -# else -# error This compiler/platform combo is not supported yet -# endif +#define systemf(...) do{ \ + int32_t n = snprintf(SF_CMD, sizeof(SF_CMD), __VA_ARGS__); \ + AllowLocal(n); \ + Assert(n < sizeof(SF_CMD)); \ + /** printf("%s\n", SF_CMD); /**/ \ + prev_error = system(SF_CMD); \ + if (prev_error != 0) error_state = 1; \ +}while(0) +// OS selectors +#if defined(IS_WINDOWS) +# define ONLY_WINDOWS(x) x +# define ONLY_LINUX(x) (void)0 +#elif defined(IS_LINUX) +# define ONLY_WINDOWS(x) (void)0 +# define ONLY_LINUX(x) x #else -#error This compiler is not supported yet +# error File moving is not setup on this OS. #endif +// String helpers +internal void +require_size(String *str, i32 size){ + if (str->memory_size <= size){ + free(str->str); + str->memory_size = l_round_up_i32(str->size*2, 64); + str->str = (char*)malloc(str->memory_size); + } +} +internal void +require_size_preserve(String *str, i32 size){ + if (str->memory_size <= size){ + str->memory_size = l_round_up_i32(str->size*2, 64); + char *newstr = (char*)malloc(str->memory_size); + memcpy(newstr, str->str, str->size); + free(str->str); + str->str = newstr; + } +} +internal void +copy_always(String *dst, String src){ + require_size(dst, src.size+1); + copy(dst, src); + terminate_with_null(dst); +} + +internal void +append_always(String *dst, String src){ + require_size_preserve(dst, dst->size+src.size+1); + append(dst, src); + terminate_with_null(dst); +} + +// Instruction format +typedef u16 Instruction_FM; +enum Instruction_FM_{ + InstrFM_BeginTime, + InstrFM_EndTime, + InstrFM_Push, + InstrFM_StackLoad, + InstrFM_Pop, + InstrFM_MovCWD, + InstrFM_Mov, + InstrFM_Leaf, + InstrFM_Path, + InstrFM_Cat, + InstrFM_SlashFix, + InstrFM_MkDir, + InstrFM_ClrDir, + InstrFM_Del, + InstrFM_Copy, + InstrFM_CopyAll, + InstrFM_Zip, + InstrFM_CD, + InstrFM_Command, + InstrFM_COUNT +}; +enum Instruction_Flag_FM_{ + InstrFM_LiteralParam1 = 0x8000, + InstrFM_LiteralParam2 = 0x4000, + InstrFM_LiteralParam3 = 0x2000, + InstrFM_InstrMask = 0x00FF +}; + +typedef u16 String_Reg; + +// Instruction VM +#define REG_COUNT_FM 16 +struct Virtual_Machine_FM{ + umem pc; + u64 time_start; + String temp; + String stage_reg; + String reg[REG_COUNT_FM]; + + String *stack_base; + String *stack_ptr; +}; + +internal String_Reg +read_register_fm(u8 **ptr){ + String_Reg result = *(String_Reg*)(*ptr); + Assert(result < REG_COUNT_FM); + (*ptr) += 2; + return(result); +} + +internal u16 +read_u16_fm(u8 **ptr){ + u16 result = *(u16*)(*ptr); + (*ptr) += 2; + return(result); +} + +internal String +read_parameter_fm(b32 is_literal, u8 **ptr){ + String result = {0}; + if (is_literal){ + result.size = *(u16*)(*ptr); + result.memory_size = result.size+1; + (*ptr) += 2; + result.str = (char*)ptr; + u16 step_forward = (result.memory_size+1)&(~1); + ptr += step_forward; + } + else{ + String_Reg result = *(String_Reg*)(*ptr); + Assert(result < REG_COUNT_FM); + (*ptr) += 2; + } + return(result); +} + +internal void +stage_params(String *params, u32 count, u16 dest, Virtual_Machine_FM *vm){ + String dest_str = vm->reg[dest]; + u32 i = 0; + for (; i < count; ++i){ + if (params[i].str == dest_str.str){ + copy_always(&vm->stage_reg, params[i]); + params[i] = vm->stage_reg; + break; + } + } + for (++i; i < count; ++i){ + if (params[i].str == dest_str.str){ + params[i] = vm->stage_reg; + } + } +} + +internal void run_instruction_fm(Virtual_Machine_FM *vm, u16 op, String_Reg dest, u16 n, String *params); + +internal void +execute_instructions_fm(void *code, umem length){ + Assert(InstrFM_InstrMask >= InstrFM_COUNT-1); + + u8 *base = (u8*)code; + Virtual_Machine_FM vm = {0}; + + u32 n = 0; + String_Reg dest = 0; + String param[3] = {0}; + for (;vm.pc < length;){ + Instruction_FM ins = *(Instruction_FM*)(base+vm.pc); + u16 op = (ins)&InstrFM_InstrMask; + + u8 *ptr = (u8*)(base+vm.pc+2); + switch(op){ + case InstrFM_MovCWD: + { + dest = read_register_fm(&ptr); + }break; + + case InstrFM_StackLoad: + { + dest = read_register_fm(&ptr); + n = read_u16_fm(&ptr); + }break; + + case InstrFM_Pop: + { + n = read_u16_fm(&ptr); + }break; + + case InstrFM_Mov: + case InstrFM_Leaf: + case InstrFM_Path: + case InstrFM_Cat: + case InstrFM_SlashFix: + { + dest = read_register_fm(&ptr); + param[0] = read_parameter_fm(ins&InstrFM_LiteralParam1, &ptr); + stage_params(param, 1, dest, &vm); + }break; + + case InstrFM_Push: + case InstrFM_EndTime: + case InstrFM_MkDir: + case InstrFM_ClrDir: + case InstrFM_Del: + case InstrFM_CD: + case InstrFM_Command: + { + param[0] = read_parameter_fm(ins&InstrFM_LiteralParam1, &ptr); + }break; + + case InstrFM_Copy: + case InstrFM_Zip: + { + param[0] = read_parameter_fm(ins&InstrFM_LiteralParam1, &ptr); + param[1] = read_parameter_fm(ins&InstrFM_LiteralParam2, &ptr); + }break; + + case InstrFM_CopyAll: + { + param[0] = read_parameter_fm(ins&InstrFM_LiteralParam1, &ptr); + param[1] = read_parameter_fm(ins&InstrFM_LiteralParam2, &ptr); + param[2] = read_parameter_fm(ins&InstrFM_LiteralParam3, &ptr); + }break; + } + + run_instruction_fm(&vm, op, dest, n, param); + + vm.pc = (umem)((ptr)-(base+vm.pc)); + Assert(vm.pc <= length); + } +} + +#define LLU_CAST(n) (long long unsigned int)(n) +#define TSCALE 1000000 +#define PRINT_TIME_FM(n) \ +printf("%-20s: %.2llu.%.6llu\n", (n), LLU_CAST(total/TSCALE), LLU_CAST(total%TSCALE)); + +#if defined(IS_WINDOWS) + +#define DONT_BUG_ME\ +FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NOCONFIRMMKDIR + +internal void +run_instruction_fm(Virtual_Machine_FM *vm, u16 op, String_Reg dest, String *params){ + switch(op){ + case InstrFM_BeginTime: + case InstrFM_EndTime: + { + u64 time = 0; + LARGE_INTEGER lint; + if (QueryPerformanceCounter(&lint)){ + time = lint.QuadPart; + time = (time * 1000000) / perf_frequency; + } + if (op == InstrFM_BeginTime){ + vm->time_start = time; + } + else{ + u64 total = time - vm->time_start; + PRINT_TIME_FM(params[0].str); + } + }break; + + case InstrFM_MovCWD: + { + String *d = &vm->reg[dest]; + i32 length = GetCurrentDirectoryA(0, 0); + require_size(d, length+1); + d->size = GetCurrentDirectoryA(d->memory_size, d->str); + terminate_with_null(d); + }break; + + case InstrFM_Push: + { + copy_always(&vm->stack_ptr[0], params[0]); + ++vm->stack_ptr; + }break; + + case InstrFM_StackLoad: + { + Assert((vm->stack_ptr - vm->stack_base) >= n); + String *d = &vm->reg[dest]; + String *s = vm->stack_ptr - n; + copy_always(d, *s); + }break; + + case InstrFM_Pop: + { + Assert((vm->stack_ptr - vm->stack_base) >= n); + stack_ptr = vm->strack_ptr - n; + }break; + + case InstrFM_Mov: + { + String *d = &vm->reg[dest]; + copy_always(d, params[0]); + terminate_with_null(d); + }break; + + case InstrFM_Leaf: + { + String *d = &vm->reg[dest]; + copy_always(d, front_of_directory(params[0])); + terminate_with_null(d); + }break; + + case InstrFM_Path: + { + String *d = &vm->reg[dest]; + copy_always(d, path_of_directory(params[0])); + terminate_with_null(d); + }break; + + case InstrFM_Cat: + { + String *d = &vm->reg[dest]; + append_always(d, params[0]); + terminate_with_null(d); + }break; + + case InstrFM_SlashFix: + { + String *d = &vm->reg[dest]; + copy_always(d, params[0]); + u32 size = d->size; + char *str = d->str; + for (u32 i = 0; i < size; ++i){ + if (str[i] == '/'){ + str[i] == '//'; + } + } + terminate_with_null(d); + }break; + + case InstrFM_MkDir: + { + String path = param[0]; + char *p = path.str; + for (; *p; ++p){ + if (*p == '\\'){ + *p = 0; + CreateDirectoryA(path.str, 0); + *p = '\\'; + } + } + if (!CreateDirectoryA(path.str, 0)){ + // TODO(allen): error. + } + }break; + + case InstrFM_ClrDir: + { + String *d = &vm->temp; + copy_always(d, params[0].size+4); + if (d->str[d->size-1] != '\\'){ + d->str[d->size++] = '\\'; + } + d->str[d->size++] = '*'; + d->str[d->size++] = 0; + d->str[d->size] = 0; + + SHFILEOPSTRUCT fileop = {0}; + fileop.wFunc = FO_DELETE; + fileop.pFrom = d->str; + fileop.fFlags = DONT_BUG_ME; + if (SHFileOperation(&fileop) != 0){ + // TODO(allen): error. + } + }break; + + case InstrFM_Del: + { + if (!DeleteFileA(param[0].str)){ + // TODO(allen): error. + } + }break; + + case InstrFM_CD: + { + if (!SetCurrentDirectoryA(param[0].str)){ + // TODO(allen): error. + } + }break; + + case InstrFM_Command: + { + systemf("%s", param[0].str); + }break; + + case InstrFM_Copy: + { + if (!CopyFileA(param[0], param[1], false)){ + // TODO(allen): error. + } + }break; + + case InstrFM_Zip: + { + u32 length = GetCurrentDirectoryA(0, 0); + String *d = &vm->temp; + require_size(d, length+11); + d->size = GetCurrentDirectoryA(d->memory_size, d->str); + terminate_with_null(d); + + i32 original_length = params[0].size; + remove_last_folder(¶ms[0]); + terminate_with_null(¶ms[0]); + if (SetCurrentDirectoryA(params[0].str)){ + systemf("zip %s\\4tech_gobble.zip", d->str); + SetCurrentDirectoryA(d->str); + append_always(d, make_lit_string("\\gobble.zip")); + terminate_with_null(d); + + if (!MoveFile(d->str, params[1].str)){ + // TODO(allen): error. + } + } + else{ + // TODO(allen): error. + } + params[0].str[params[0].size-1] = '\\'; + params[0].size = original_length; + }break; + + case InstrFM_CopyAll: + { + require_size_preserve(¶ms[2], params[2].size+2); + params[2].str[params[2].size] = 0; + params[2].str[params[2].size+1] = 0; + + require_size(&vm->temp, params[0].size+params[1].size+3); + copy_always(&vm->temp, params[0]); + copy_always(&vm->temp, make_lit_string("\\")); + copy_always(&vm->temp, params[1]); + vm->temp.str[vm->temp.size] = 0; + vm->temp.str[vm->temp.size+1] = 0; + + SHFILEOPSTRUCT fileop = {0}; + fileop.wFunc = FO_COPY; + fileop.pFrom = vm->temp.str; + fileop.pTo = param[2].str; + fileop.fFlags = DONT_BUG_ME | FOF_NORECURSION | FOF_FILESONLY; + if (SHFileOperation(&fileop) != 0){ + // TODO(allen): error. + } + }break; + + default: InvalidCodePath; + } +} + +#undef DONT_BUG_ME + +#elif defined(IS_LINUX) + +#include +#include + +internal void +run_instruction_fm(Virtual_Machine_FM *vm, u16 op, String_Reg dest, u16 n, String *params){ + switch(op){ + case InstrFM_BeginTime: + case InstrFM_EndTime: + { + struct timespec spec; + clock_gettime(CLOCK_MONOTONIC, &spec); + u64 time = (spec.tv_sec * 1000000) + (spec.tv_nsec / 1000); + if (op == InstrFM_BeginTime){ + vm->time_start = time; + } + else{ + u64 total = time - vm->time_start; + PRINT_TIME_FM(params[0].str); + } + }break; + + case InstrFM_MovCWD: + { + String *d = &vm->reg[dest]; + char *r = getcwd(d->str, d->memory_size); + if (r == d->str){ + d->size = str_size(d->str); + } + terminate_with_null(d); + }break; + + case InstrFM_Push: + { + copy_always(&vm->stack_ptr[0], params[0]); + ++vm->stack_ptr; + }break; + + case InstrFM_StackLoad: + { + Assert((vm->stack_ptr - vm->stack_base) >= n); + String *d = &vm->reg[dest]; + String *s = vm->stack_ptr - n; + copy_always(d, *s); + }break; + + case InstrFM_Pop: + { + Assert((vm->stack_ptr - vm->stack_base) >= n); + vm->stack_ptr = vm->stack_ptr - n; + }break; + + case InstrFM_Mov: + { + String *d = &vm->reg[dest]; + copy_always(d, params[0]); + terminate_with_null(d); + }break; + + case InstrFM_Leaf: + { + String *d = &vm->reg[dest]; + copy_always(d, front_of_directory(params[0])); + terminate_with_null(d); + }break; + + case InstrFM_Cat: + { + String *d = &vm->reg[dest]; + append_always(d, params[0]); + terminate_with_null(d); + }break; + + case InstrFM_SlashFix:break; + + case InstrFM_MkDir: + { + systemf("mkdir -p %s", params[0].str); + }break; + + case InstrFM_ClrDir: + { + systemf("rm -rf %s*", params[0].str); + }break; + + case InstrFM_Del: + { + systemf("rm %s", params[0].str); + }break; + + case InstrFM_CD: + { + chdir(params[0].str); + }break; + + case InstrFM_Command: + { + systemf("%s", params[0].str); + }break; + + case InstrFM_Copy: + { + systemf("cp %s %s", params[0].str, params[1].str); + }break; + + case InstrFM_Zip: + { + String *d = &vm->temp; + char *r = getcwd(d->str, d->memory_size); + + if (r == d->str){ + d->size = str_size(d->str); + + i32 original_length = params[0].size; + remove_last_folder(¶ms[0]); + terminate_with_null(¶ms[0]); + if (chdir(params[0].str)){ + char *folder = params[0].str + params[0].size + 1; + systemf("zip -r %s %s", params[1].str, folder); + chdir(d->str); + terminate_with_null(d); + } + else{ + // TODO(allen): error. + } + params[0].str[params[0].size-1] = '\\'; + params[0].size = original_length; + } + else{ + // TODO(allen): error. + } + }break; + + case InstrFM_CopyAll: + { + + }break; + } +} +#else +#error No implementation for run_instruction_fm on this OS. +#endif + +// Instruction emitter +struct Emitter_FM{ + u8 *buffer; + umem pos, max; +}; +Emitter_FM global_emitter_fm = {0}; + +internal void +init_fm(void *buffer, umem length){ + global_emitter_fm.buffer = (u8*)buffer; + global_emitter_fm.pos = 0; + global_emitter_fm.max = length; +} + +internal void +execute_fm(){ + execute_instructions_fm(global_emitter_fm.buffer, global_emitter_fm.pos); + global_emitter_fm.pos = 0; +} + +internal void +emit_u16_fm(u16 x){ + Assert(global_emitter_fm.pos+2 <= global_emitter_fm.max); + *(u16*)(global_emitter_fm.buffer + global_emitter_fm.pos) = x; + global_emitter_fm.pos += 2; +} + +internal void +emit_strlit_fm(char *str, u16 len){ + u16 full_len = len+1; + u16 mem_len = (full_len+1)&(~1); + Assert(global_emitter_fm.pos+mem_len <= global_emitter_fm.max); + u8 *dst = global_emitter_fm.buffer + global_emitter_fm.pos; + u16 i = 0; + for (; i < len; ++i){ + dst[i] = str[i]; + } + dst[i] = 0; + global_emitter_fm.pos += mem_len; +} + +struct String_Param{ + b32 is_literal; + String_Reg reg; + u16 len; + char *n; +}; +internal String_Param +reg_fm(String_Reg reg){ + String_Param result = {0}; + result.reg = reg; + return(result); +} +internal String_Param +lit_fm(char *n){ + String_Param result = {0}; + result.is_literal = true; + result.len = str_size(n); + result.n = n; + return(result); +} +internal String_Param +litn_fm(char *n, u16 len){ + String_Param result = {0}; + result.is_literal = true; + result.len = len; + result.n = n; + return(result); +} +internal void +emit_param_fm(String_Param n){ + if (n.is_literal){ + emit_strlit_fm(n.n, n.len); + } + else{ + emit_u16_fm(n.reg); + } +} +internal void +param_flag_fm(u16 *ins, String_Param n, u16 param_i){ + local_persist u16 flags[] = { + InstrFM_LiteralParam1, + InstrFM_LiteralParam2, + InstrFM_LiteralParam3, + }; + if (n.is_literal){ + *ins |= flags[param_i]; + } +} + +internal void +begin_time_fm(){ + u16 ins = InstrFM_BeginTime; + emit_u16_fm(ins); +} + +internal void +end_time_fm(String_Param n){ + u16 ins = InstrFM_EndTime; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_param_fm(n); +} + +internal void +push_fm(String_Param n){ + u16 ins = InstrFM_Push; + emit_u16_fm(ins); + emit_param_fm(n); +} + +internal void +stack_load_fm(String_Reg reg, u16 index){ + u16 ins = InstrFM_StackLoad; + emit_u16_fm(ins); + emit_u16_fm(reg); + emit_u16_fm(index); +} + +internal void +pop_fm(u16 count){ + u16 ins = InstrFM_Pop; + emit_u16_fm(ins); + emit_u16_fm(count); +} + +internal void +mov_cwd_fm(String_Reg reg){ + u16 ins = InstrFM_MovCWD; + emit_u16_fm(ins); + emit_u16_fm(reg); +} + +internal void +mov_fm(String_Reg reg, String_Param n){ + u16 ins = InstrFM_Mov; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_u16_fm(reg); + emit_param_fm(n); +} + +internal void +leaf_fm(String_Reg reg, String_Param n){ + u16 ins = InstrFM_Leaf; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_u16_fm(reg); + emit_param_fm(n); +} + +internal void +path_fm(String_Reg reg, String_Param n){ + u16 ins = InstrFM_Path; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_u16_fm(reg); + emit_param_fm(n); +} + +internal void +cat_fm(String_Reg reg, String_Param n){ + u16 ins = InstrFM_Cat; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_u16_fm(reg); + emit_param_fm(n); +} + +internal void +slash_fix_fm(String_Reg reg, String_Param n){ + u16 ins = InstrFM_SlashFix; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_u16_fm(reg); + emit_param_fm(n); +} + +internal void +mkdir_fm(String_Param n){ + u16 ins = InstrFM_MkDir; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_param_fm(n); +} + +internal void +clrdir_fm(String_Param n){ + u16 ins = InstrFM_ClrDir; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_param_fm(n); +} + +internal void +del_fm(String_Param n){ + u16 ins = InstrFM_Del; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_param_fm(n); +} + +internal void +copy_fm(String_Param s, String_Param d){ + u16 ins = InstrFM_Copy; + param_flag_fm(&ins, s, 0); + param_flag_fm(&ins, d, 1); + emit_u16_fm(ins); + emit_param_fm(s); + emit_param_fm(d); +} + +internal void +copy_all_fm(String_Param s, String_Param d, String_Param p){ + u16 ins = InstrFM_CopyAll; + param_flag_fm(&ins, s, 0); + param_flag_fm(&ins, d, 1); + param_flag_fm(&ins, p, 2); + emit_u16_fm(ins); + emit_param_fm(s); + emit_param_fm(d); + emit_param_fm(p); +} + +internal void +zip_fm(String_Param s, String_Param d){ + u16 ins = InstrFM_Copy; + param_flag_fm(&ins, s, 0); + param_flag_fm(&ins, d, 1); + emit_u16_fm(ins); + emit_param_fm(s); + emit_param_fm(d); +} + +internal void +cd_fm(String_Param n){ + u16 ins = InstrFM_Copy; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_param_fm(n); +} + +internal void +command_fm(String_Param n){ + u16 ins = InstrFM_Command; + param_flag_fm(&ins, n, 0); + emit_u16_fm(ins); + emit_param_fm(n); +} + +// OLD VERSION +#if 0 #if defined(IS_WINDOWS) # define ONLY_WINDOWS(x) x # define ONLY_LINUX(x) (void)0 @@ -60,15 +885,9 @@ static char platform_correct_slash = '\\'; static char platform_correct_slash = '/'; #else -# define ONLY_WINDOWS(x) (void)0 -# define ONLY_LINUX(x) (void)0 - -#define SLASH "/" -static char platform_correct_slash = '/'; - +# error File moving is not setup on this OS. #endif - static char SF_CMD[4096]; static i32 error_state = 0; static i32 prev_error = 0; @@ -442,5 +1261,7 @@ zip(char *parent, char *folder, char *file){ #endif +#endif + // BOTTOM diff --git a/meta/build.cpp b/meta/build.cpp index 7aa9b33e..1c044dee 100644 --- a/meta/build.cpp +++ b/meta/build.cpp @@ -1,5 +1,5 @@ /* -4coder development build rule. +The 4coder build and package rules. */ // TOP @@ -21,10 +21,12 @@ #define IS_64BIT +#if 0 #define LLU_CAST(n) (long long unsigned int)(n) #define BEGIN_TIME_SECTION() uint64_t start = get_time() #define END_TIME_SECTION(n) uint64_t total = get_time() - start; printf("%-20s: %.2llu.%.6llu\n", (n), LLU_CAST(total/1000000), LLU_CAST(total%1000000)); +#endif // // 4coder specific @@ -145,6 +147,7 @@ init_build_line(Build_Line *line){ #define CL_X86 "-MACHINE:X86" +#if 0 static void build_cl(u32 flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){ Build_Line line; @@ -239,7 +242,107 @@ build_cl(u32 flags, char *code_path, char *code_file, char *out_path, char *out_ systemf("%scl %s \"%s\\%s\" /Fe%s /link /INCREMENTAL:NO %s", line_prefix.build_options, line.build_options, code_path, code_file, out_file, link_line.build_options); popdir(temp); } +#endif +static void +build_cl(u32 flags){ + push_fm(reg_fm(0)); + push_fm(reg_fm(1)); + push_fm(reg_fm(2)); + + mov_fm(0, lit_fm("")); + mov_fm(1, lit_fm("")); + mov_fm(2, lit_fm("")); + + // line prefix + if (flags & X86){ + cat_fm(0, lit_fm("SETUP_CLX86 & ")); + } + + // line + if (flags & OPTS){ + cat_fm(1, lit_fm(" "CL_OPTS)); + } + if (flags & X86){ + cat_fm(1, lit_fm(" /DFTECH_32_BIT")); + } + if (flags & INCLUDES){ + cat_fm(1, lit_fm(" "CL_INCLUDES)); + } + if (flags & SITE_INCLUDES){ + cat_fm(1, lit_fm(" "CL_SITE_INCLUDES)); + } + if (flags & LIBS){ + if (flags & X86){ + cat_fm(1, lit_fm(" "CL_LIBS_X86)); + } + else{ + cat_fm(1, lit_fm(" "CL_LIBS_X64)); + } + } + if (flags & ICON){ + cat_fm(1, lit_fm(" "CL_ICON)); + } + if (flags & DEBUG_INFO){ + cat_fm(1, lit_fm(" /Zi")); + } + if (flags & OPTIMIZATION){ + cat_fm(1, lit_fm(" /O2")); + } + if (flags & SHARED_CODE){ + cat_fm(1, lit_fm(" /LD")); + } + if (flags & SUPER){ + cat_fm(1, lit_fm(" /DFRED_SUPER")); + } + if (flags & INTERNAL){ + cat_fm(1, lit_fm(" /DFRED_INTERNAL")); + } + if (flags & KEEP_ASSERT){ + cat_fm(1, lit_fm(" /DFRED_KEEP_ASSERT")); + } + + // link line + if (flags & X86){ + cat_fm(2, lit_fm(" "CL_X86)); + } + if (flags & DEBUG_INFO){ + cat_fm(2, lit_fm(" /DEBUG")); + } + if (flags & SHARED_CODE){ + stack_load_fm(3, 1); + cat_fm(2, lit_fm(" /OPT:REF ")); + cat_fm(2, reg_fm(3)); + } + + stack_load_fm(4, 2); + leaf_fm(4, reg_fm(4)); + + // prefix + mov_fm(3, reg_fm(0)); + // compiler + cat_fm(3, lit_fm("cl ")); + cat_fm(3, reg_fm(1)); + // input file + cat_fm(3, lit_fm(" \"")); + stack_load_fm(0, 3); + cat_fm(3, reg_fm(0)); + // output name + cat_fm(3, lit_fm("\" /Fe")); + cat_fm(3, reg_fm(4)); + // linker + cat_fm(3, lit_fm(" /link /INCREMENTAL:NO ")); + cat_fm(3, reg_fm(2)); + + stack_load_fm(4, 2); + path_fm(4, reg_fm(4)); + mov_cwd_fm(0); + cd_fm(reg_fm(4)); + command_fm(reg_fm(3)); + cd_fm(reg_fm(0)); + + pop_fm(3); +} #define GCC_OPTS \ "-Wno-write-strings -D_GNU_SOURCE -fPIC " \ @@ -257,6 +360,7 @@ build_cl(u32 flags, char *code_path, char *code_file, char *out_path, char *out_ "-L/usr/local/lib -lX11 -lpthread -lm -lrt " \ "-lGL -ldl -lXfixes -lfreetype -lfontconfig" +#if 0 static void build_gcc(u32 flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){ Build_Line line; @@ -330,18 +434,129 @@ build_gcc(u32 flags, char *code_path, char *code_file, char *out_path, char *out systemf("g++ %s -o %s", line.build_options, out_file); popdir(temp); } +#endif static void -build(u32 flags, char *code_path, char *code_file, char *out_path, char *out_file, char *exports){ -#if defined(IS_CL) - build_cl(flags, code_path, code_file, out_path, out_file, exports); -#elif defined(IS_GCC) - build_gcc(flags, code_path, code_file, out_path, out_file, exports); -#else -#error The build rule for this compiler is not ready +build_gcc(u32 flags){ + push_fm(reg_fm(0)); + push_fm(reg_fm(1)); + push_fm(reg_fm(2)); + + mov_fm(0, lit_fm("g++ ")); + + if (flags & X86){ + cat_fm(0, lit_fm(GCC_X86)); + } + else{ + cat_fm(0, lit_fm(GCC_X64)); + } + if (flags & OPTS){ + cat_fm(0, lit_fm(GCC_OPTS)); + } + if (flags & INCLUDES){ + // TODO(allen): Abstract this out. +#if defined(IS_LINUX) + i32 size = 0; + char freetype_include[512]; + FILE *file = popen("pkg-config --cflags freetype2", "r"); + if (file != 0){ + fgets(freetype_include, sizeof(freetype_include), file); + size = strlen(freetype_include); + freetype_include[--size] = 0; + pclose(file); + } + + cat_fm(0, lit_fm(GCC_INCLUDES" ")); + cat_fm(0, litn_fm(freetype_include, size)); #endif + } + if (flags & SITE_INCLUDES){ + cat_fm(0, lit_fm(GCC_SITE_INCLUDES)); + } + if (flags & DEBUG_INFO){ + cat_fm(0, lit_fm("-g -O0")); + } + if (flags & OPTIMIZATION){ + cat_fm(0, lit_fm("-O3")); + } + if (flags & SHARED_CODE){ + cat_fm(0, lit_fm("-shared")); + } + if (flags & SUPER){ + cat_fm(0, lit_fm("-DFRED_SUPER")); + } + if (flags & INTERNAL){ + cat_fm(0, lit_fm("-DFRED_INTERNAL")); + } + if (flags & KEEP_ASSERT){ + cat_fm(0, lit_fm("-DFRED_KEEP_ASSERT")); + } + + cat_fm(0, lit_fm(" ")); + stack_load_fm(1, 3); + cat_fm(0, reg_fm(1)); + + if (flags & LIBS){ + cat_fm(0, lit_fm(GCC_LIBS)); + } + + stack_load_fm(1, 2); + leaf_fm(1, reg_fm(1)); + cat_fm(0, lit_fm(" -o ")); + cat_fm(0, reg_fm(1)); + + pop_fm(3); } +#if defined(IS_CL) +#define build build_cl +#elif defined(IS_GCC) +#define build build_gcc +#else +#error The build rule for this compiler is not ready. +#endif + +static void +buildsuper(b32 x86_build){ + mov_cwd_fm(3); + cd_fm(reg_fm(1)); +#if defined(IS_CL) + { + if (x86_build){ + mov_fm(4, lit_fm("setup_clx86 & ")); + } + else{ + mov_fm(4, lit_fm("")); + } + cat_fm(4, lit_fm("call \"")); + cat_fm(4, reg_fm(0)); + if (x86_build){ + cat_fm(4, lit_fm("buildsuper_x86.bat\" ")); + } + else{ + cat_fm(4, lit_fm("buildsuper.bat\" \"")); + } + cat_fm(4, reg_fm(2)); + cat_fm(4, lit_fm("\"")); + command_fm(reg_fm(4)); + } +#elif defined(IS_GCC) + { + mov_fm(4, lit_fm("\"")); + cat_fm(4, reg_fm(0)); + cat_fm(4, lit_fm("/buildsuper.sh\" \"")); + cat_fm(4, reg_fm(2)); + cat_fm(4, lit_fm("\"")); + command_fm(reg_fm(4)); + } +#else +#error The build rule for this compiler is not ready. +#endif + + cd_fm(reg_fm(3)); +} + +#if 0 static void buildsuper(char *code_path, char *out_path, char *filename, b32 x86_build){ Temp_Dir temp = pushdir(out_path); @@ -364,6 +579,7 @@ buildsuper(char *code_path, char *out_path, char *filename, b32 x86_build){ #endif popdir(temp); } +#endif #if defined(IS_WINDOWS) #define PLAT_LAYER "win32_4ed.cpp" @@ -379,39 +595,54 @@ buildsuper(char *code_path, char *out_path, char *filename, b32 x86_build){ static void fsm_generator(char *cdir){ { - DECL_STR(file, "meta/fsm_table_generator.cpp"); - DECL_STR(dir, META_DIR); - - BEGIN_TIME_SECTION(); - build(OPTS | DEBUG_INFO, cdir, file, dir, "fsmgen", 0); - END_TIME_SECTION("build fsm generator"); + begin_time_fm(); + mov_fm(0, lit_fm(cdir)); + cat_fm(0, lit_fm("/meta/fsm_table_generator.cpp")); + slash_fix_fm(0, reg_fm(0)); + slash_fix_fm(1, lit_fm(META_DIR)); + mov_fm(2, lit_fm("")); + build(OPTS | DEBUG_INFO); + end_time_fm(lit_fm("build fsm generator")); } if (prev_error == 0){ - DECL_STR(cmd, META_DIR"/fsmgen"); - BEGIN_TIME_SECTION(); - execute_in_dir(cdir, cmd, 0); - END_TIME_SECTION("run fsm generator"); + begin_time_fm(); + mov_fm(1, lit_fm(cdir)); + mov_cwd_fm(0); + cd_fm(reg_fm(1)); + mov_fm(2, lit_fm(META_DIR"/fsmgen")); + command_fm(reg_fm(2)); + cd_fm(reg_fm(0)); + end_time_fm(lit_fm("run fsm generator")); } + execute_fm(); } static void metagen(char *cdir){ { - DECL_STR(file, "meta/4ed_metagen.cpp"); - DECL_STR(dir, META_DIR); - - BEGIN_TIME_SECTION(); - build(OPTS | INCLUDES | DEBUG_INFO, cdir, file, dir, "metagen", 0); - END_TIME_SECTION("build metagen"); + begin_time_fm(); + mov_fm(0, lit_fm(cdir)); + cat_fm(0, lit_fm("/meta/4ed_metagen.cpp")); + slash_fix_fm(0, reg_fm(0)); + slash_fix_fm(1, lit_fm(META_DIR)); + mov_fm(2, lit_fm("")); + build(OPTS | INCLUDES | DEBUG_INFO); + end_time_fm(lit_fm("build metagen")); } - if (prev_error == 0){ - DECL_STR(cmd, META_DIR "/metagen"); - BEGIN_TIME_SECTION(); - execute_in_dir(cdir, cmd, 0); - END_TIME_SECTION("run metagen"); + { + begin_time_fm(); + mov_fm(1, lit_fm(cdir)); + mov_cwd_fm(0); + cd_fm(reg_fm(1)); + mov_fm(2, lit_fm(META_DIR"/metagen")); + command_fm(reg_fm(2)); + cd_fm(reg_fm(0)); + end_time_fm(lit_fm("run metagen")); } + + execute_fm(); } enum{ @@ -424,43 +655,40 @@ enum{ static void do_buildsuper(char *cdir, i32 custom_option, u32 flags){ - char space[1024]; - String str = make_fixed_width_string(space); + begin_time_fm(); - BEGIN_TIME_SECTION(); + b32 x86_build = ((flags & X86) != 0); + + mov_fm(0, lit_fm(cdir)); switch (custom_option){ case Custom_Default: { - copy_sc(&str, "../code/4coder_default_bindings.cpp"); + slash_fix_fm(2, lit_fm("../code/4coder_default_bindings.cpp")); }break; case Custom_Experiments: { - copy_sc(&str, "../code/power/4coder_experiments.cpp"); + slash_fix_fm(2, lit_fm("../code/power/4coder_experiments.cpp")); }break; case Custom_Casey: { - copy_sc(&str, "../code/power/4coder_casey.cpp"); + slash_fix_fm(2, lit_fm("../code/power/4coder_casey.cpp")); }break; case Custom_ChronalVim: { - copy_sc(&str, "../4vim/4coder_chronal.cpp"); + slash_fix_fm(2, lit_fm("../4vim/4coder_chronal.cpp")); }break; } - terminate_with_null(&str); - b32 x86_build = false; - if (flags & X86){ - x86_build = true; - } DECL_STR(dir, BUILD_DIR); buildsuper(cdir, dir, str.str, x86_build); - END_TIME_SECTION("build custom"); + end_time_fm("build custom"); + execute_fm(); } static void