189 lines
5.6 KiB
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;
|
|
}
|