diff options
-rwxr-xr-x | build/meta | bin | 27552 -> 0 bytes | |||
-rwxr-xr-x | build/metac | bin | 27640 -> 32816 bytes | |||
-rwxr-xr-x | misc/build.sh | 4 | ||||
-rwxr-xr-x | misc/debug | 3 | ||||
-rw-r--r-- | source/meta.c | 274 | ||||
-rw-r--r-- | source/table.c | 15 | ||||
-rwxr-xr-x | source/table.meta | bin | 0 -> 21088 bytes | |||
-rw-r--r-- | source/table.meta.c | 25 |
8 files changed, 189 insertions, 132 deletions
diff --git a/build/meta b/build/meta Binary files differdeleted file mode 100755 index 72848e4..0000000 --- a/build/meta +++ /dev/null diff --git a/build/metac b/build/metac Binary files differindex e47ee30..cac4e03 100755 --- a/build/metac +++ b/build/metac diff --git a/misc/build.sh b/misc/build.sh index f477a40..9618a66 100755 --- a/misc/build.sh +++ b/misc/build.sh @@ -4,4 +4,6 @@ set -ex ThisDirectory="$(dirname "$(readlink -f "$0")")" -gcc -ggdb -Wall -o "$ThisDirectory"/../build/metac "$ThisDirectory"/../source/meta.c +gcc -ggdb \ + -Wall -Wno-unused-but-set-variable -Wno-unused-variable \ + -o "$ThisDirectory"/../build/metac "$ThisDirectory"/../source/meta.c @@ -1,3 +1,4 @@ #!/bin/sh -setsid gf2 ./meta > /dev/null 2>&1 +ThisDir="$(dirname "$(readlink -f "$0")")" +setsid gf2 "$ThisDir"/../build/metac > /dev/null 2>&1 diff --git a/source/meta.c b/source/meta.c index 39de3c8..1eb643d 100644 --- a/source/meta.c +++ b/source/meta.c @@ -30,26 +30,41 @@ typedef int64_t i64; #define true 1 #define false 0 +///~ Misc macro's ////////////////////////////////////// +#define Assert(expr) if (!(expr)) { raise(SIGTRAP); } +#define Kilobyte(byte) byte * 1024L +#define Megabyte(byte) Kilobyte(byte) * 1024L +#define Gigabyte(byte) Megabyte(byte) * 1024L +#define internal static +#define global_variable static +#define local_persist static +//////////////////////////////////////////////////////// + +///~ String //////////////////////////////////////////// typedef struct { char *Memory; u64 Size; } s8; -#define S8(str) { str, sizeof(str) - 1 } #define S8_LIT(str) str, sizeof(str) - 1 #define S8_ARG(str) str.Memory, str.Size +#define S8(str) { S8_LIT(str) } +#define S8_FMT "Memory: %.5s Size: %lu" +//////////////////////////////////////////////////////// -#define Assert(expr) if (!(expr)) { raise(SIGTRAP); } - -#define Kilobyte(byte) byte * 1024L -#define Megabyte(byte) Kilobyte(byte) * 1024L -#define Gigabyte(byte) Megabyte(byte) * 1024L - +///~ Arena ///////////////////////////////////////////// typedef struct { char *Memory; u64 Pos; u64 Size; } arena; +///~ Global variables ///////////////////////////////////////////// +// TODO: use meta program to generate Keywords table +global_variable s8 TableKeyword = S8("table"); +global_variable s8 TableGenEnumKeyword = S8("table_gen_enum"); +global_variable s8 ExpandKeyword = S8("expand"); +//////////////////////////////////////////////////////// + char * ArenaPush(arena* Arena, i64 Size) { @@ -59,7 +74,9 @@ ArenaPush(arena* Arena, i64 Size) Assert(Arena->Pos <= Arena->Size); return Result; } +//////////////////////////////////////////////////////// +///~ MetaC data structures ///////////////////////////// typedef struct { s8 Name; i32 LabelsCount; @@ -72,24 +89,19 @@ typedef struct { i32 Start; i32 End; } range; +//////////////////////////////////////////////////////// s8 ReadEntireFileIntoMemory(char *Filepath) { - i32 Ret = 0; i32 FD = 0; s8 Result = {0}; struct stat StatBuffer = {0}; FD = open(Filepath, O_RDONLY); - Assert(FD != -1); fstat(FD, &StatBuffer); - Assert(Ret != -1); - Result.Size = StatBuffer.st_size; - Result.Memory = mmap(0, Result.Size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); - Assert(Result.Memory); - Ret = read(FD, Result.Memory, Result.Size); - Assert(Ret != -1); + Result.Size = StatBuffer.st_size; + Result.Memory = mmap(0, Result.Size, PROT_READ | PROT_WRITE, MAP_PRIVATE, FD, 0); return Result; } @@ -155,13 +167,14 @@ main(int ArgC, char *Args[]) .Size = Megabyte(1) }; arena TablesArena = { - .Memory = Storage + ScratchArena.Size, + .Memory = ScratchArena.Memory + ScratchArena.Size, .Pos = 0, .Size = Megabyte(1) }; table *Tables = (table*)TablesArena.Memory; i32 TablesCount = 0; - char *Out = ScratchArena.Memory + TablesArena.Size; + char *Out = TablesArena.Memory + TablesArena.Size; + char *OutBase = Out; if (ArgC > 1) { @@ -176,146 +189,149 @@ main(int ArgC, char *Args[]) // NOTE(luca): The memory is assumed to stay mapped until program exits, because we will use // pointers into that memory. - s8 File = ReadEntireFileIntoMemory(Filename); - char *In = File.Memory; + s8 FileContents = ReadEntireFileIntoMemory(Filename); + + if (!FileContents.Memory || (void*)FileContents.Memory == (void*)-1) + { + fprintf(stderr, "File '%s' could not be loaded into memory.\n", Filename); + return 1; + } + + char *In = FileContents.Memory; + i64 InSize = FileContents.Size; for (i64 At = 0; - At < File.Size; + At < InSize; At++) { if (In[At] == '@') { At++; - s8 TableKeyword = S8("table"); - s8 TableGenEnumKeyword = S8("table_gen_enum"); - s8 ExpandKeyword = S8("expand"); - s8 Keywords[] = { TableKeyword, TableGenEnumKeyword, ExpandKeyword }; - if (!strncmp(In + At, S8_ARG(ExpandKeyword))) { - i32 ExpressionAt = 0; + table *ExpressionTable = 0; s8 ExpressionTableName = {0}; i32 ExpressionTableNameAt = 0; s8 ExpressionTableArgument = {0}; i32 ExpressionTableArgumentAt = 0; - s8 ExpandArgument = {0}; - i32 ExpandArgumentAt = 0; - s8 ExpandArgumentLabel = {0}; - i32 ExpandArgumentLabelAt = 0; - range Expansion = {0}; - At += ExpandKeyword.Size; - Assert(At < File.Size); + Assert(At < InSize); Assert(In[At] == '('); At++; ExpressionTableNameAt = At; - while (!IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (!IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); ExpressionTableName.Memory = In + ExpressionTableNameAt; ExpressionTableName.Size = At - ExpressionTableNameAt; + + for (i32 TableAt = 0; + TableAt < TablesCount; + TableAt++) + { + if (!strncmp(Tables[TableAt].Name.Memory, ExpressionTableName.Memory, ExpressionTableName.Size)) + { + ExpressionTable = Tables + TableAt; + break; + } + } + Assert(ExpressionTable); - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + // TODO: not used yet + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); ExpressionTableArgumentAt = At; - while (In[At] != ')' && At < File.Size) At++; - Assert(At < File.Size); + while (In[At] != ')' && At < InSize) At++; + Assert(At < InSize); ExpressionTableArgument.Memory = In + ExpressionTableArgumentAt; ExpressionTableArgument.Size = At - ExpressionTableArgumentAt; At++; - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); Assert(In[At] == '`'); At++; - ExpressionAt = At; - // TODO: multiple expansions in one expression - while (In[At] != '`') + i32 ExpressionAt = At; + for (i32 ElementAt = 0; + ElementAt < ExpressionTable->ElementsCount; + ElementAt++) { - if (In[At] == '$' && In[At + 1] == '(') - { - Expansion.Start = At; - At += 2; - - ExpandArgumentAt = At; - while (In[At] != '.' && At < File.Size) At++; - Assert(At < File.Size); - ExpandArgument.Memory = In + ExpandArgumentAt; - ExpandArgument.Size = At - ExpandArgumentAt; - At++; - - ExpandArgumentLabelAt = At; - while (In[At] != ')' && At < File.Size) At++; - Assert(At < File.Size); - ExpandArgumentLabel.Memory = In + ExpandArgumentLabelAt; - ExpandArgumentLabel.Size = At - ExpandArgumentLabelAt; + At = ExpressionAt; - Expansion.End = At; - At++; - - // ExpressionAt| | Start | End | | At | - // repeat Labels repeat - - table *CurrentTable = 0; - for (i32 TableAt = 0; - TableAt < TablesCount; - TableAt++) + while (In[At] != '`' && At < InSize) + { + while ((In[At] != '$' && In[At] != '`') && At < InSize) { - if (!strncmp(Tables[TableAt].Name.Memory, S8_ARG(ExpressionTableName))) - { - CurrentTable = Tables + TableAt; - break; - } + if (In[At] == '\\') At++; + *Out++ = In[At++]; } - Assert(CurrentTable); - // TODO(now): Debug this - i32 LabelIndex = -1; - for (i32 LabelAt = 0; - LabelAt < CurrentTable->LabelsCount; - LabelAt++) + // TODO: allow escaping characters with '\' + if (In[At] == '$' && In[At + 1] == '(') { - if (!strncmp(CurrentTable->Labels[LabelAt].Memory, S8_ARG(ExpandArgumentLabel))) - { - LabelIndex = LabelAt; - break; - } - } - Assert(LabelIndex != -1); + At += 2; + + s8 ExpandArgument = {0}; + i32 ExpandArgumentAt = At; + while (In[At] != '.' && At < InSize) At++; + ExpandArgument.Memory = In + ExpandArgumentAt; + ExpandArgument.Size = At - ExpandArgumentAt; + Assert(!strncmp(ExpandArgument.Memory, ExpressionTableArgument.Memory, ExpandArgument.Size)); + At++; - // TODO(now): the bug + s8 ExpansionLabel = {0}; + i32 ExpansionLabelAt = At; + while (In[At] != ')' && At < InSize) At++; + Assert(At < InSize); + ExpansionLabel.Memory = In + ExpansionLabelAt; + ExpansionLabel.Size = At - ExpansionLabelAt; + At++; - while (In[At] != '`' && At < File.Size) At++; - Assert(File.Size); + i32 LabelIndex = -1; + for (i32 LabelAt = 0; + LabelAt < ExpressionTable->LabelsCount; + LabelAt++) + { + if (!strncmp(ExpansionLabel.Memory, + ExpressionTable->Labels[LabelAt].Memory, + ExpansionLabel.Size)) + { + LabelIndex = LabelAt; + break; + } + } + Assert(LabelIndex != -1); - for (i32 ElementAt = 0; - ElementAt < CurrentTable->ElementsCount; - ElementAt++) + s8 Expansion = ExpressionTable->Elements[ElementAt * ExpressionTable->LabelsCount + LabelIndex]; + memcpy(Out, Expansion.Memory, Expansion.Size); + Out += Expansion.Size; + } + else if (In[At] == '`') { - s8 ExpansionText = CurrentTable->Elements[ElementAt * CurrentTable->LabelsCount + LabelIndex]; - write(STDOUT_FILENO, In + ExpressionAt, Expansion.Start - ExpressionAt); - write(STDOUT_FILENO, S8_ARG(ExpansionText)); - write(STDOUT_FILENO, In + Expansion.End + 1, At - (Expansion.End + 1)); - write(STDOUT_FILENO, S8_LIT("\n")); + // ERROR: When the last character is '`' does not print. + *Out++ = '\n'; + } + else + { + *Out++ = In[At++]; } - break; } - At++; - Assert(At < File.Size); } + Assert(At < InSize); + At++; } else if (!strncmp(In + At, TableGenEnumKeyword.Memory, TableGenEnumKeyword.Size)) { // TODO: not implemented yet - while (In[At] != '}' && At < File.Size) At++; - Assert(At < File.Size); + while (In[At] != '}' && At < InSize) At++; + Assert(At < InSize); } else if (!strncmp(In + At, TableKeyword.Memory, TableKeyword.Size)) { @@ -325,6 +341,8 @@ main(int ArgC, char *Args[]) i32 ElementsCount = 0; s8* Elements = 0; + Labels = (s8*)(ScratchArena.Memory + ScratchArena.Pos); + // Parse the labels At += TableKeyword.Size; Assert(In[At] == '('); @@ -343,13 +361,13 @@ main(int ArgC, char *Args[]) LabelsCount++; At++; - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); CurrentLabelAt = At; } At++; - Assert(At < File.Size); + Assert(At < InSize); } if (BeginParenAt + 1 == At) @@ -359,7 +377,6 @@ main(int ArgC, char *Args[]) } else { - Labels = (s8*)(ScratchArena.Memory); CurrentLabel = (s8*)ArenaPush(&ScratchArena, sizeof(*CurrentLabel)); CurrentLabel->Memory = In + CurrentLabelAt; CurrentLabel->Size = At - CurrentLabelAt; @@ -368,16 +385,16 @@ main(int ArgC, char *Args[]) // Parse table name At++; - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); i32 TableNameAt = At; - while (!IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (!IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); TableName.Memory = In + TableNameAt; TableName.Size = At - TableNameAt; - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); Assert(In[At] == '{'); At++; @@ -398,8 +415,8 @@ main(int ArgC, char *Args[]) while (!ShouldStop) { - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); if (In[At] == '}') { ShouldStop = true; @@ -415,8 +432,8 @@ main(int ArgC, char *Args[]) LabelAt < LabelsCount; LabelAt++) { - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); CurrentElementAt = At; IsPair = true; @@ -435,14 +452,14 @@ main(int ArgC, char *Args[]) // same character to open and to close. We can also assume // that a label within an element must be a minimum of 1 // character so skipping should be fine. - while (In[At] != PairChar && At < File.Size) At++; - Assert(At < File.Size); + while (In[At] != PairChar && At < InSize) At++; + Assert(At < InSize); At++; } else { - while (!IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (!IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); } CurrentElement[LabelAt].Memory = In + CurrentElementAt; @@ -451,8 +468,8 @@ main(int ArgC, char *Args[]) ElementsCount++; // Find end of element '}' - while (IsWhitespace(In[At]) && At < File.Size) At++; - Assert(At < File.Size); + while (IsWhitespace(In[At]) && At < InSize) At++; + Assert(At < InSize); Assert(In[At] == '}'); At++; } @@ -470,16 +487,17 @@ main(int ArgC, char *Args[]) else { // ERROR: What if the code contains a non meta-"@_expand" tag ??? - write(STDOUT_FILENO, In + At, 1); + *Out++ = In[At]; } } else { - write(STDOUT_FILENO, In + At, 1); + *Out++ = In[At]; } } - + + write(STDOUT_FILENO, OutBase, Out - OutBase); return 0; } diff --git a/source/table.c b/source/table.c index e1bc9a8..d2ec1ad 100644 --- a/source/table.c +++ b/source/table.c @@ -1,3 +1,5 @@ +#include <stdio.h> + @table(name, str) MyEnumTable { { A "A" } @@ -7,10 +9,19 @@ typedef enum { @expand(MyEnumTable a) - `MyEnum_$(a.name), // lololol` + `MyEnum_$(a.name),` MyEnum_Count } MyEnum; -char *StringTable[MyEnumCount] = { +char *StringTable[MyEnum_Count] = { @expand(MyEnumTable a) `$(a.str),` +}; + + +int +main(int Argc, char *Args[]) +{ + printf("%s\n", StringTable[MyEnum_B]); + + return 0; } diff --git a/source/table.meta b/source/table.meta Binary files differnew file mode 100755 index 0000000..63edbd2 --- /dev/null +++ b/source/table.meta diff --git a/source/table.meta.c b/source/table.meta.c new file mode 100644 index 0000000..4f38e0e --- /dev/null +++ b/source/table.meta.c @@ -0,0 +1,25 @@ +#include <stdio.h> + + + +typedef enum { +MyEnum_A, +MyEnum_B, +MyEnum_C, +MyEnum_Count +} MyEnum; + +char *StringTable[MyEnum_Count] = { +"A", +"B", +"C", +}; + + +int +main(int Argc, char *Args[]) +{ + printf("%s\n", StringTable[MyEnum_B]); + + return 0; +} |