1
0
Fork 0

Add Manifest module.

master
Marrub 2016-10-21 15:05:29 -04:00
parent fb08786729
commit abc86aaa8f
8 changed files with 630 additions and 54 deletions

View File

@ -43,6 +43,7 @@ SOURCES= \
$(SRC)/draw.c \
$(SRC)/font.c \
$(SRC)/main.c \
$(SRC)/manifest.c \
$(SRC)/stdlib.c \
$(SRC)/token.c \
$(SRC)/tokenstream.c \
@ -60,6 +61,7 @@ HEADERS= \
$(INC)/Lth_hashmap.h \
$(INC)/Lth_hudmessage.h \
$(INC)/Lth_linklist.h \
$(INC)/Lth_manifest.h \
$(INC)/Lth_stdlib.h \
$(INC)/Lth_token.h \
$(INC)/Lth_tokenstream.h \

View File

@ -22,6 +22,7 @@
#include "Lth_font.h"
#include "Lth_hudmessage.h"
#include "Lth_linklist.h"
#include "Lth_manifest.h"
#include "Lth_stdlib.h"
#include "Lth_token.h"
#include "Lth_tokenstream.h"

View File

@ -15,6 +15,22 @@
#include "Lth_types.h"
#include "Lth_font.h"
#include "Lth_manifest.h"
#define Lth_ContextResource(ctx, type, key) \
((type *)Lth_ContextResourceFind((ctx), (key)))
#define Lth_ContextManifestLoad_extern(ctx, ...) \
( \
((ctx)->rsrc ? (Lth_ResourceMapDestroy((ctx)->rsrc)) : (void)0), \
(ctx)->rsrc = Lth_ManifestLoad_extern(__VA_ARGS__) \
)
#define Lth_ContextManifestLoad_static(ctx, ...) \
( \
((ctx)->rsrc ? (Lth_ResourceMapDestroy((ctx)->rsrc)) : (void)0), \
(ctx)->rsrc = Lth_ManifestLoad_static(__VA_ARGS__) \
)
// Type Definitions ----------------------------------------------------------|
@ -24,12 +40,14 @@
//
// internal data
// clip
// lastmap
// map
// rsrcBase
// rsrc
// lastmap
//
// read-only
// w: width of screen
// h: height of screen
// w: width of screen
// h: height of screen
//
// read-write
// hid: HUD ID range
@ -40,6 +58,7 @@ typedef struct Lth_Context
{
struct { Lth_Rect rects[16]; int num; } clip;
struct { Lth_LinkList *head, *tail; } map;
Lth_ResourceMap *rsrcBase, *rsrc;
Lth_IVec2 lastmap;
int w, h;
@ -53,10 +72,14 @@ typedef struct Lth_Context
// Extern Functions ----------------------------------------------------------|
Lth_Context *Lth_ContextNew(int w, int h, Lth_HID hidBase, Lth_HID hidEnd);
void Lth_ContextMap(Lth_Context *ctx, struct Lth_Window *window);
void Lth_ContextDestroy(Lth_Context *ctx);
void Lth_ContextRun(Lth_Context *ctx);
void Lth_ContextMap(Lth_Context *ctx, struct Lth_Window *window);
void Lth_ContextClipPush(Lth_Context *ctx, int x, int y, int w, int h);
void Lth_ContextClipPop(Lth_Context *ctx);
void *Lth_ContextResourceFind(Lth_Context *ctx, char const *key);
#endif//lithos3__Lth_context_h

View File

@ -0,0 +1,84 @@
//-----------------------------------------------------------------------------
//
// Copyright © 2016 Project Golan
//
// See "LICENSE" for more information.
//
//-----------------------------------------------------------------------------
//
// Resource manifests.
//
//-----------------------------------------------------------------------------
#ifndef lithos3__Lth_manifest_h
#define lithos3__Lth_manifest_h
#include "Lth_hashmap.h"
#include "Lth_types.h"
#define Lth_ManifestNew(...) \
((Lth_Manifest[]){ \
__VA_ARGS__, \
Lth_Resource(NULL, 0) \
})
#define Lth_Resource(name, val) \
_Generic((val)+0, \
int: Lth_ManifestNew_Integ, \
_Accum: Lth_ManifestNew_Fixed, \
char const *: Lth_ManifestNew_Strng \
)((name), (val))
// Type Definitions ----------------------------------------------------------|
//
// Lth_ResourceType
//
typedef enum Lth_ResourceType
{
Lth_ResourceType_Integ,
Lth_ResourceType_Fixed,
Lth_ResourceType_Strng,
Lth_ResourceType_Max
} Lth_ResourceType;
//
// Lth_Manifest
//
typedef struct Lth_Manifest
{
int type;
size_t keyhash;
union
{
int integ;
_Accum fixed;
char *strng;
};
} Lth_Manifest;
//
// Lth_ResourceMap
//
typedef struct Lth_ResourceMap
{
Lth_Vector(int) vecInteg;
Lth_Vector(_Accum) vecFixed;
Lth_Vector(char *) vecStrng;
Lth_HashMap map;
} Lth_ResourceMap;
// Extern Functions ----------------------------------------------------------|
void Lth_ResourceMapDestroy(Lth_ResourceMap *rsrc);
Lth_ScriptCall Lth_ResourceMap *Lth_ManifestLoad_extern(char const *fname);
Lth_ScriptCall Lth_ResourceMap *Lth_ManifestLoad_static(Lth_Manifest *manifest);
Lth_Manifest Lth_ManifestNew_Integ(char const *key, int value);
Lth_Manifest Lth_ManifestNew_Fixed(char const *key, _Accum value);
Lth_Manifest Lth_ManifestNew_Strng(char const *key, char const *value);
#endif//lithos3__Lth_manifest_h

View File

@ -17,6 +17,22 @@
#include <stdbool.h>
// Static Functions ----------------------------------------------------------|
//
// Lth_ContextSetup
//
static void Lth_ContextSetup(Lth_Context *ctx, void *ctrl_)
{
Lth_Control *ctrl = ctrl_;
Lth_ListForEach(Lth_Control *owner, ctrl->descendants)
Lth_ContextSetup(ctx, owner);
ctrl->ctx = ctx;
}
// Extern Functions ----------------------------------------------------------|
//
@ -35,20 +51,53 @@ Lth_Context *Lth_ContextNew(int w, int h, Lth_HID hidBase, Lth_HID hidEnd)
ctx->mapspace.x = 24;
ctx->mapspace.y = 16;
ctx->rsrcBase = Lth_ManifestLoad_static(Lth_ManifestNew(
Lth_Resource("Base.Resource1", 999)
));
return ctx;
}
//
// Lth_ContextSetup
// Lth_ContextDestroy
//
void Lth_ContextSetup(Lth_Context *ctx, void *ctrl_)
void Lth_ContextDestroy(Lth_Context *ctx)
{
Lth_Control *ctrl = ctrl_;
if(ctx == NULL)
return;
Lth_ListForEach(Lth_Control *owner, ctrl->descendants)
Lth_ContextSetup(ctx, owner);
if(ctx->map.head)
{
Lth_ListFor(Lth_Control *owner, ctx->map.head)
{
Lth_ListRemove(list);
if(owner) Lth_ControlDestroy(owner);
list = next;
}
}
ctrl->ctx = ctx;
Lth_ResourceMapDestroy(ctx->rsrc);
Lth_ResourceMapDestroy(ctx->rsrcBase);
free(ctx->rsrc);
free(ctx->rsrcBase);
free(ctx);
}
//
// Lth_ContextRun
//
void Lth_ContextRun(Lth_Context *ctx)
{
Lth_assert(ctx != NULL);
ACS_SetHudSize(ctx->w, ctx->h, true);
ctx->hid.cur = ctx->hid.base;
if(ctx->map.head)
Lth_ListForEach(Lth_Control *owner, ctx->map.head)
Lth_ControlRun(owner);
}
//
@ -69,42 +118,6 @@ void Lth_ContextMap(Lth_Context *ctx, Lth_Window *ctrl)
Lth_ListInsertTail(&ctrl->link, ctrl, &ctx->map.head, &ctx->map.tail);
}
//
// Lth_ContextDestroy
//
void Lth_ContextDestroy(Lth_Context *ctx)
{
if(ctx == NULL)
return;
if(ctx->map.head)
{
Lth_ListFor(Lth_Control *owner, ctx->map.head)
{
Lth_ListRemove(list);
if(owner) Lth_ControlDestroy(owner);
list = next;
}
}
free(ctx);
}
//
// Lth_ContextRun
//
void Lth_ContextRun(Lth_Context *ctx)
{
Lth_assert(ctx != NULL);
ACS_SetHudSize(ctx->w, ctx->h, true);
ctx->hid.cur = ctx->hid.base;
if(ctx->map.head)
Lth_ListForEach(Lth_Control *owner, ctx->map.head)
Lth_ControlRun(owner);
}
//
// Lth_ContextClipPush
//
@ -116,18 +129,13 @@ void Lth_ContextClipPush(Lth_Context *ctx, int x, int y, int w, int h)
if(!(rect.x == 0 && rect.y == 0 && rect.w == 0 && rect.h == 0))
{
if(rect.x < x) rect.x = x;
if(rect.y < y) rect.y = y;
if(rect.x < x) rect.x = x;
if(rect.y < y) rect.y = y;
if(rect.x + rect.w > x + w) rect.w = w;
if(rect.y + rect.h > y + h) rect.h = h;
}
else
{
rect.x = x;
rect.y = y;
rect.h = h;
rect.w = w;
}
rect = (Lth_Rect){ x, y, w, h };
ctx->clip.rects[ctx->clip.num] = rect;
ACS_SetHudClipRect(rect.x, rect.y, rect.w, rect.h);
@ -144,4 +152,14 @@ void Lth_ContextClipPop(Lth_Context *ctx)
ACS_SetHudClipRect(rect.x, rect.y, rect.w, rect.h);
}
//
// Lth_ContextResourceFind
//
void *Lth_ContextResourceFind(Lth_Context *ctx, char const *key)
{
void *p = Lth_HashMapFind(&ctx->rsrc->map, key);
if(p) return p;
else return Lth_HashMapFind(&ctx->rsrcBase->map, key);
}
// EOF

405
lithos_c/src/manifest.c Normal file
View File

@ -0,0 +1,405 @@
//-----------------------------------------------------------------------------
//
// Copyright © 2016 Project Golan
//
// See "LICENSE" for more information.
//
//-----------------------------------------------------------------------------
//
// Resource manifests.
//
//-----------------------------------------------------------------------------
#include "Lth.h"
// Define fixed so it is not aliased (this breaks our code).
#define fixed
#include <stdfix.h>
#undef fixed
#include <stdbool.h>
#include <string.h>
#include <setjmp.h>
#define GenAlloc(name, type) \
if(rsrc->vec##name.size) \
rsrc->vec##name.data = calloc(rsrc->vec##name.size, sizeof(type)); \
\
size_t iter##name = 0
#define GenSpecCase(name, var, i, expr) \
case Lth_ResourceType_##name: \
rsrc->vec##name.data[iter##name] = iter->var; \
rsrc->map.elem.data[i ].keyhash = iter->keyhash; \
rsrc->map.elem.data[i++].value = expr; \
break
#define GenRsrcCase(name, var, i) \
GenSpecCase(name, var, i, &rsrc->vec##name.data[iter##name++])
#define GenManifestValue(name, value, setexpr) \
(Lth_Manifest){ \
.type = Lth_ResourceType_##name, \
.keyhash = Lth_Hash_char(key), \
.value = (setexpr) \
}
#define GenValueGetter(name, value, setexpr) \
if(repr->manifest.size + 1 > repr->manifest.bufsz) \
repr->manifest.data = realloc(repr->manifest.data, \
sizeof(Lth_Manifest) * (repr->manifest.bufsz += 32)); \
\
repr->manifest.data[repr->manifest.size++] = (Lth_Manifest){ \
.type = Lth_ResourceType_##name, \
.keyhash = key, \
.value = (setexpr) \
}
#define ManifestError(repr, str) \
if(1) \
{ \
fprintf(stderr, "%s (in %s): %s\n", __func__, (repr)->fname, str); \
repr->err = true; \
longjmp(ManifestJmpBuf, ManifestJmpBufToken); \
} \
else ((void)0)
// Type Definitions ----------------------------------------------------------|
//
// ManifestState
//
typedef struct ManifestState
{
char *block;
char *data;
bool err;
char const *fname;
Lth_TokenStream *stream;
Lth_Vector(Lth_Manifest) manifest;
} ManifestState;
// Static Objects ------------------------------------------------------------|
static jmp_buf ManifestJmpBuf;
static int const ManifestJmpBufToken = 30;
// Static Functions ----------------------------------------------------------|
//
// ManifestGetInteg
//
static void ManifestGetInteg(ManifestState *repr, size_t key, char const *str)
{
// integer-constant
char *end;
int value = strtoi(str, &end, 0);
if(*end != '\0')
ManifestError(repr, "bad integral value");
GenValueGetter(Integ, integ, value);
}
//
// ManifestGetFixed
//
static void ManifestGetFixed(ManifestState *repr, size_t key, char const *str)
{
// fixed-constant
char *end;
_Accum value = strtofxk(str, &end);
if(*end != '\0')
ManifestError(repr, "bad fixed-point value");
GenValueGetter(Fixed, fixed, value);
}
//
// ManifestGetStrng
//
static void ManifestGetStrng(ManifestState *repr, size_t key, char const *str)
{
// string-constant
GenValueGetter(Strng, strng, Lth_strdup(str));
}
//
// ManifestGetHeaderNameSequence
//
static void ManifestGetHeaderNameSequence(ManifestState *repr)
{
// header-name-sequence:
// identifier
// header-name-sequence . identifier
ACS_BeginPrint();
do
{
Lth_Token const *tok = Lth_TokenStreamPeek(repr->stream);
// identifier
if(tok->type != Lth_TOK_Identi)
ManifestError(repr, "expected identifier");
Lth_PrintString(tok->str);
Lth_TokenStreamBump(repr->stream);
}
Lth_pfor(Lth_TokenStreamDrop(repr->stream, Lth_TOK_Dot), ACS_PrintChar('.'));
}
//
// ManifestGetInitializer
//
static void ManifestGetInitializer(ManifestState *repr, size_t key)
{
// initializer:
// integer-constant
// fixed-constant
// string-constant
switch(Lth_TokenStreamPeek(repr->stream)->type)
{
case Lth_TOK_Number:
__with(char const *str = Lth_TokenStreamBump(repr->stream)->str;)
if(!Lth_strcontains(str, '.'))
ManifestGetInteg(repr, key, str);
else
ManifestGetFixed(repr, key, str);
break;
case Lth_TOK_String:
ManifestGetStrng(repr, key, Lth_TokenStreamBump(repr->stream)->str);
break;
default:
ManifestError(repr, "expected initializer");
break;
}
}
//
// ManifestGetDecl_Object
//
static void ManifestGetDecl_Object(ManifestState *repr)
{
// obj-decl-terminator:
// '\n'
// ;
// object-declaration:
// identifier = initializer obj-decl-terminator
// identifier
if(Lth_TokenStreamPeek(repr->stream)->type != Lth_TOK_Identi)
ManifestError(repr, "exptected declarator");
// Build the key name. Format is: "blockname.identifier"
__with(char const *name = Lth_TokenStreamBump(repr->stream)->str;)
{
ACS_BeginPrint();
Lth_PrintString(repr->block);
ACS_PrintChar('.');
Lth_PrintString(name);
}
size_t key = Lth_Hash_str(ACS_EndStrParam());
repr->stream->skipeol = false;
// =
if(!Lth_TokenStreamDrop(repr->stream, Lth_TOK_Equals))
ManifestError(repr, "expected '='");
// initializer
ManifestGetInitializer(repr, key);
// obj-decl-terminator
if(!Lth_TokenStreamDrop(repr->stream, Lth_TOK_LnEnd) &&
!Lth_TokenStreamDrop(repr->stream, Lth_TOK_Semico))
ManifestError(repr, "expected newline or ';'");
repr->stream->skipeol = true;
}
//
// ManifestGetDecl_Header
//
static void ManifestGetDecl_Header(ManifestState *repr)
{
// header-declaration:
// [ header-name-sequence ]
// [
if(!Lth_TokenStreamDrop(repr->stream, Lth_TOK_BrackO))
ManifestError(repr, "expected '['");
// header-name-sequence
ManifestGetHeaderNameSequence(repr);
repr->block = Lth_strealoc_str(repr->block, ACS_EndStrParam());
// ]
if(!Lth_TokenStreamDrop(repr->stream, Lth_TOK_BrackC))
ManifestError(repr, "expected ']'");
}
//
// ManifestGetDecl
//
Lth_ScriptCall static void ManifestGetDecl(ManifestState *repr)
{
switch(Lth_TokenStreamPeek(repr->stream)->type)
{
case Lth_TOK_BrackO: ManifestGetDecl_Header(repr); break;
default: ManifestGetDecl_Object(repr); break;
}
}
//
// ManifestClose
//
static void ManifestClose(ManifestState *repr)
{
Lth_TokenStreamClose(repr->stream);
free(repr->data);
free(repr->block);
free(repr->manifest.data);
}
// Extern Functions ----------------------------------------------------------|
//
// Lth_ResourceMapDestroy
//
void Lth_ResourceMapDestroy(Lth_ResourceMap *rsrc)
{
if(rsrc == NULL) return;
Lth_HashMapFree(&rsrc->map);
if(rsrc->vecStrng.data)
Lth_VectorForEach(char **, rsrc->vecStrng)
free(*itr);
free(rsrc->vecInteg.data);
free(rsrc->vecFixed.data);
free(rsrc->vecStrng.data);
free(rsrc);
}
//
// Lth_ManifestLoad_extern
//
Lth_ScriptCall Lth_ResourceMap *Lth_ManifestLoad_extern(char const *fname)
{
ManifestState repr = {};
repr.fname = fname;
repr.data = Lth_strdup_str(Lth_strlocal(Lth_strentdup(repr.fname)));
repr.stream = Lth_TokenStreamOpen(repr.data, strlen(repr.data));
repr.block = Lth_strdup("Base");
Lth_assert(repr.stream != NULL);
if(strcmp(repr.data, repr.fname) == 0)
{
fprintf(stderr, "%s: No file named '%s'.", __func__, fname);
ManifestClose(&repr);
return NULL;
}
if(setjmp(ManifestJmpBuf) != ManifestJmpBufToken)
for(;;)
if(Lth_TokenStreamPeek(repr.stream)->type != Lth_TOK_EOF)
ManifestGetDecl(&repr);
else
break;
Lth_ResourceMap *rsrc = NULL;
if(!repr.err)
rsrc = Lth_ManifestLoad_static(repr.manifest.data);
ManifestClose(&repr);
return rsrc;
}
//
// Lth_ManifestLoad_static
//
Lth_ScriptCall Lth_ResourceMap *Lth_ManifestLoad_static(Lth_Manifest *manifest)
{
Lth_ResourceMap *rsrc = calloc(1, sizeof(Lth_ResourceMap));
Lth_assert(rsrc != NULL);
size_t count = 0;
// If keyhash is 0, it was a NULL string, thus a terminator for this list.
// Get the size of each vector and the total size for the map.
for(Lth_Manifest *iter = manifest; iter->keyhash; iter++, count++)
switch(iter->type)
{
case Lth_ResourceType_Integ: rsrc->vecInteg.size++; break;
case Lth_ResourceType_Fixed: rsrc->vecFixed.size++; break;
case Lth_ResourceType_Strng: rsrc->vecStrng.size++; break;
default: break;
}
// Allocate each data vector and make an iterator for it.
GenAlloc(Integ, int);
GenAlloc(Fixed, _Accum);
GenAlloc(Strng, char *);
// Allocate the hash map.
Lth_HashMapAlloc(&rsrc->map, count);
// Iterate over all of the data vectors, adding them to the map, and
// adding data to them.
__with(size_t i = 0;)
for(Lth_Manifest *iter = manifest; iter->keyhash; iter++)
switch(iter->type)
{
GenRsrcCase(Integ, integ, i);
GenRsrcCase(Fixed, fixed, i);
GenRsrcCase(Strng, strng, i);
}
// Build the map.
Lth_HashMapBuild(&rsrc->map);
return rsrc;
}
//
// Lth_ManifestNew_Integ
//
Lth_Manifest Lth_ManifestNew_Integ(char const *key, int value)
{
return GenManifestValue(Integ, integ, value);
}
//
// Lth_ManifestNew_Fixed
//
Lth_Manifest Lth_ManifestNew_Fixed(char const *key, _Accum value)
{
return GenManifestValue(Fixed, fixed, value);
}
//
// Lth_ManifestNew_Strng
//
Lth_Manifest Lth_ManifestNew_Strng(char const *key, char const *value)
{
return GenManifestValue(Strng, strng, Lth_strdup(value));
}
// EOF

3
lithos_fs/Base.lthm Normal file
View File

@ -0,0 +1,3 @@
Resource1 = 0x30
// EOF

40
lithos_tools/createfs.lua Executable file
View File

@ -0,0 +1,40 @@
#!/usr/bin/env lua
local lfs = require("lfs")
function procLine(ln)
ln = ln:gsub('\\', "\\\\")
ln = ln:gsub('\"', "\\\"")
return ln
end
function procFile(out, dir, fname)
out:write("\"" .. dir .. '/' .. fname .. "\" =")
for ln in io.lines(dir .. '/' .. fname) do
out:write("\n \"" .. procLine(ln) .. "\\n\"")
end
out:write(";\n");
end
function procDir(out, dir)
for fname in lfs.dir(dir) do
local attr = lfs.attributes(dir .. '/' .. fname)
if fname:sub(1, 1) ~= '.' then
if attr.mode == "directory" then
procDir(out, dir .. '/' .. fname)
elseif attr.mode == "file" then
procFile(out, dir, fname)
end
end
end
end
function main(out)
out:write("[default]\n\n")
procDir(out, "lithos_fs")
end
main(io.open("language.fs.txt", "w"))
-- EOF