aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild/metabin27552 -> 0 bytes
-rwxr-xr-xbuild/metacbin27640 -> 32816 bytes
-rwxr-xr-xmisc/build.sh4
-rwxr-xr-xmisc/debug3
-rw-r--r--source/meta.c274
-rw-r--r--source/table.c15
-rwxr-xr-xsource/table.metabin0 -> 21088 bytes
-rw-r--r--source/table.meta.c25
8 files changed, 189 insertions, 132 deletions
diff --git a/build/meta b/build/meta
deleted file mode 100755
index 72848e4..0000000
--- a/build/meta
+++ /dev/null
Binary files differ
diff --git a/build/metac b/build/metac
index e47ee30..cac4e03 100755
--- a/build/metac
+++ b/build/metac
Binary files differ
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
diff --git a/misc/debug b/misc/debug
index 6990914..dde611e 100755
--- a/misc/debug
+++ b/misc/debug
@@ -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
new file mode 100755
index 0000000..63edbd2
--- /dev/null
+++ b/source/table.meta
Binary files differ
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;
+}