Add Manifest module.
parent
fb08786729
commit
abc86aaa8f
|
@ -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 \
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
Resource1 = 0x30
|
||||
|
||||
// EOF
|
|
@ -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
|
Loading…
Reference in New Issue