vn/code/third_party/codegen/codegen.c

189 lines
5.6 KiB
C

#define _CRT_SECURE_NO_WARNINGS 1
#include <inttypes.h>
#include "../metadesk/md.h"
#include "../metadesk/md.c"
#include "../meow_hash_x64_aesni.h"
#include "codegen_embed.h"
#include "codegen_table.h"
#include "codegen.h"
#include "codegen_embed.c"
#include "codegen_table.c"
////////////////////////////////
//~ rjf: Helpers
static CG_FilePair
CG_FilePairFromNode(MD_Node *node)
{
CG_FilePair result = {0};
MD_CodeLoc loc = MD_CodeLocFromNode(node);
MD_String8 filename = loc.filename;
MD_b32 found = 0;
for(int i = 0; i < cg_file_pair_count; i += 1)
{
if(MD_S8Match(filename, cg_file_pairs[i].src_filename, 0))
{
result = cg_file_pairs[i];
found = 1;
break;
}
}
if(found == 0)
{
MD_String8 folder = MD_PathChopLastSlash(filename);
MD_String8 layer_name = MD_PathChopLastPeriod(MD_PathSkipLastSlash(loc.filename));
MD_String8 gen_folder = MD_S8Fmt(cg_arena, "%.*s/generated", MD_S8VArg(folder));
MD_String8 h_filename = MD_S8Fmt(cg_arena, "%.*s/%.*s.meta.h", MD_S8VArg(gen_folder), MD_S8VArg(layer_name));
MD_String8 c_filename = MD_S8Fmt(cg_arena, "%.*s/%.*s.meta.c", MD_S8VArg(gen_folder), MD_S8VArg(layer_name));
result.src_filename = filename;
result.h = fopen((char *)h_filename.str, "w");
result.c = fopen((char *)c_filename.str, "w");
cg_file_pairs[cg_file_pair_count] = result;
cg_file_pair_count += 1;
}
return result;
}
static FILE *
CG_FileFromNodePair(MD_Node *node, CG_FilePair *pair)
{
FILE *result = pair->h;
if(MD_NodeHasTag(node, MD_S8Lit("c"), MD_StringMatchFlag_CaseInsensitive))
{
result = pair->c;
}
return result;
}
static void
CG_CloseAllFiles(void)
{
for(int i = 0; i < cg_file_pair_count; i += 1)
{
fclose(cg_file_pairs[i].h);
fclose(cg_file_pairs[i].c);
}
}
static void
CG_GenerateMultilineStringAsCLiteral(FILE *file, MD_String8 string)
{
fprintf(file, "\"\"\n\"");
for(MD_u64 i = 0; i < string.size; i += 1)
{
if(string.str[i] == '\n')
{
fprintf(file, "\\n\"\n\"");
}
else if(string.str[i] == '\r')
{
continue;
}
else
{
fprintf(file, "%c", string.str[i]);
}
}
fprintf(file, "\"\n");
}
static MD_String8
CG_EscapedFromString(MD_Arena *arena, MD_String8 string)
{
MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
MD_String8List strs = {0};
MD_b32 escaped = 0;
MD_u64 start = 0;
for(MD_u64 idx = 0; idx <= string.size; idx += 1)
{
if(idx < string.size && escaped)
{
escaped = 0;
start = idx+1;
MD_u8 replace_char = 0;
switch(string.str[idx])
{
default: break;
case 'a': replace_char = 0x07; break;
case 'b': replace_char = 0x08; break;
case 'e': replace_char = 0x1b; break;
case 'f': replace_char = 0x0c; break;
case 'n': replace_char = 0x0a; break;
case 'r': replace_char = 0x0d; break;
case 't': replace_char = 0x09; break;
case 'v': replace_char = 0x0b; break;
case '\\': replace_char = 0x5c; break;
case '\'': replace_char = 0x27; break;
case '\"': replace_char = 0x22; break;
case '\?': replace_char = 0x3f; break;
}
if(replace_char)
{
MD_String8 string = MD_S8Copy(scratch.arena, MD_S8(&replace_char, 1));
MD_S8ListPush(scratch.arena, &strs, string);
}
}
else if(idx == string.size || string.str[idx] == '\\')
{
escaped = (string.str[idx] == '\\');
MD_String8 part = MD_S8Substring(string, start, idx);
MD_S8ListPush(scratch.arena, &strs, part);
start = idx;
}
}
MD_String8 result = MD_S8ListJoin(arena, strs, 0);
MD_ReleaseScratch(scratch);
return result;
}
////////////////////////////////
//~ rjf: Entry Point
int main(int argument_count, char **arguments)
{
cg_arena = MD_ArenaAlloc();
//- rjf: parse command line
MD_String8List options = MD_StringListFromArgCV(cg_arena, argument_count, arguments);
MD_CmdLine cmdln = MD_MakeCmdLineFromOptions(cg_arena, options);
//- rjf: parse all files
MD_Node *file_list = MD_MakeList(cg_arena);
for(MD_String8Node *n = cmdln.inputs.first; n != 0; n = n->next)
{
MD_String8 code_dir = n->string;
printf("searching %.*s for metacode...\n", MD_S8VArg(code_dir));
MD_FileIter it = {0};
MD_FileIterBegin(&it, code_dir);
for(MD_FileInfo info = {0};;)
{
info = MD_FileIterNext(cg_arena, &it);
if(info.filename.size == 0)
{
break;
}
if(!(info.flags & MD_FileFlag_Directory) &&
MD_S8Match(MD_PathSkipLastPeriod(info.filename), MD_S8Lit("md"), MD_StringMatchFlag_CaseInsensitive))
{
printf("parsing %.*s...\n", MD_S8VArg(info.filename));
MD_String8 path = MD_S8Fmt(cg_arena, "%.*s/%.*s", MD_S8VArg(code_dir), MD_S8VArg(info.filename));
MD_ParseResult parse = MD_ParseWholeFile(cg_arena, path);
MD_PushNewReference(cg_arena, file_list, parse.node);
}
}
MD_FileIterEnd(&it);
}
//- rjf: send all parses to backends
CG_EMBED_Generate(file_list);
CG_TBL_Generate(file_list);
CG_CloseAllFiles();
return 0;
}