playing with a packaging VM

master
Allen Webster 2017-04-01 02:15:15 -04:00
parent 3ad502780f
commit 767cc164d5
2 changed files with 1129 additions and 80 deletions

View File

@ -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 <stdio.h> // include system for windows
#include <stdlib.h> // include system for linux (YAY!)
#include <string.h>
// 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(&params[0]);
terminate_with_null(&params[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(&params[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 <time.h>
#include <unistd.h>
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(&params[0]);
terminate_with_null(&params[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

View File

@ -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