omi-eikyo/src/r_resdec.c

149 lines
3.4 KiB
C

// Copyright © 2017 Project Golan, all rights reserved.
#include "m_tokbuf.h"
#include "m_str.h"
#include <Doominati.h>
#include <setjmp.h>
#include <string.h>
#include <stdlib.h>
// Static Functions ----------------------------------------------------------|
_Noreturn static void R_ResDec_throw (struct R_rdcst *st, char const *emsg);
static M_token *R_ResDec_expect(struct R_rdcst *st, M_tokty t, char const *exp);
// Types ---------------------------------------------------------------------|
typedef struct R_rdcst
{
__prop throw {call: R_ResDec_throw (this)}
__prop expect {call: R_ResDec_expect(this)}
M_tkbuf tb;
jmp_buf ejmp;
} R_rdcst;
// Static Functions ----------------------------------------------------------|
//
// R_ResDec_throw
//
_Noreturn static void R_ResDec_throw(R_rdcst *st, char const *emsg)
{
fprintf(stderr, "ResDec: %s\n", emsg);
longjmp(st->ejmp, 1);
}
//
// R_ResDec_expect
//
static M_token *R_ResDec_expect(R_rdcst *st, M_tokty t, char const *exp)
{
M_token *tok;
if((tok = st->tb.get())->type != t)
st->throw(M_StrFmt("expected %s", exp));
return tok;
}
//
// R_ResDec_getFont
//
static void R_ResDec_getFont(R_rdcst *st)
{
char const *fname;
__str name;
int pt;
name = M_StrCreate(st->expect(tok_string, "alias name")->textV);
st->expect(tok_eq, "'='");
fname = st->expect(tok_string, "file name")->textV;
st->expect(tok_comma, "','");
pt = strtoi(st->expect(tok_number, "pt size")->textV, NULL, 0);
DGE_Font_Create(name, fname, pt);
}
//
// R_ResDec_getTexture
//
static void R_ResDec_getTexture(R_rdcst *st)
{
char const *fname;
__str name;
name = M_StrCreate(st->expect(tok_string, "alias name")->textV);
st->expect(tok_eq, "'='");
fname = st->expect(tok_string, "file name")->textV;
DGE_Texture_Create(name, fname);
}
//
// R_ResDec_getShader
//
static void R_ResDec_getShader(R_rdcst *st)
{
char const *fp, *vp;
__str name;
bool data = false;
name = M_StrCreate(st->expect(tok_string, "alias name")->textV);
st->expect(tok_eq, "'='");
if(st->tb.drop(tok_identi) && strcmp(st->tb.reget()->textV, "data") == 0)
data = true;
fp = st->expect(tok_string, "fragment shader")->textV;
st->expect(tok_comma, "','");
vp = st->expect(tok_string, "vertex shader")->textV;
if(data) DGE_Shader_CreateData(name, fp, vp);
else DGE_Shader_CreateFile(name, fp, vp);
}
// Extern Functions ----------------------------------------------------------|
//
// R_ResDec_Load
//
void R_ResDec_Load(char const *fname)
{
R_rdcst st = {{.bbeg = 4, .bend = 10, .fp = fopen(fname, "r")}};
if(!st.tb.fp) {
fprintf(stderr, "ResDec: couldn't open file '%s'\n", fname);
goto done;
}
st.tb.ctor();
if(setjmp(st.ejmp) == 1)
goto done;
for(M_token *tok; (tok = st.tb.get())->type != tok_eof;)
{
if(tok->type != tok_identi)
st.throw("expected identifier");
else if(strcmp(tok->textV, "font") == 0)
R_ResDec_getFont(&st);
else if(strcmp(tok->textV, "texture") == 0)
R_ResDec_getTexture(&st);
else if(strcmp(tok->textV, "shader") == 0)
R_ResDec_getShader(&st);
else if(strcmp(tok->textV, "include") == 0)
R_ResDec_Load(st.expect(tok_string, "file name")->textV);
else
st.throw(M_StrFmt("invalid resource type '%s'", tok->textV));
}
printf("ResDec: '%s' loaded.\n", fname);
done:
st.tb.dtor();
fclose(st.tb.fp);
}
// EOF