Add proper memory management to tokenizers

master
Marrub 2017-09-21 14:29:03 -04:00
parent c87e35a647
commit 7f86cbf988
6 changed files with 91 additions and 52 deletions

View File

@ -220,7 +220,7 @@ static G_odarg G_ObjDef_getArgs(G_dodst *st, char const *arg)
#define CaseN(c, t, f, ...) \
case c: \
a.argv[a.argc++].t = \
f(st->expect(tok_number, "number")->text, __VA_ARGS__); \
f(st->expect(tok_number, "number")->textV, __VA_ARGS__); \
break
CaseN('u', u, strtoui, NULL, 0);
CaseN('i', i, strtoi, NULL, 0);
@ -248,17 +248,15 @@ static G_odarg G_ObjDef_getArgs(G_dodst *st, char const *arg)
//
static void G_ObjDef_getEntAnim(G_dodst *st, G_etdcl *decl)
{
char alias[M_countof(decl->name)];
M_strbufcpy(alias, st->expect(tok_identi, "alias name")->text);
char const *alias = st->expect(tok_identi, "alias name")->textV;
st->expect(tok_eq, "'='");
G_andcl *an = G_animsmap.find(st->expect(tok_identi, "anim name")->text);
G_andcl *an = G_animsmap.find(st->expect(tok_identi, "anim name")->textV);
if(an == NULL) st->throw("anim not defined");
if(decl->anim.find(alias)) st->throw("alias redefinition");
M_Vec_grow(decl->anims, 1);
G_manim *anim = &decl->animsV[decl->animsC++];
G_manim *anim = &M_Vec_next(decl->anims);
M_strbufcpy(anim->name, alias);
anim->keyhash = M_StrHash(anim->name);
anim->anim = (G_anima){an->frameV, an->frameC};
@ -272,7 +270,7 @@ static void G_ObjDef_getEntProp(G_dodst *st, G_entty *type, char const *id)
{
if(strcmp(id, "task") == 0)
{
G_ofdcl *fn = G_objfuncs.find(st->expect(tok_identi, "function")->text);
G_ofdcl *fn = G_objfuncs.find(st->expect(tok_identi, "function")->textV);
if(!fn) st->throw("invalid function name");
type->task = fn->fptr;
}
@ -300,7 +298,7 @@ static void G_ObjDef_getEntProp(G_dodst *st, G_entty *type, char const *id)
else if(strcmp(id, "sprite") == 0)
{
type->sprite = DGE_Texture_Get(
M_StrCreate(st->expect(tok_string, "sprite name")->text));
M_StrCreate(st->expect(tok_string, "sprite name")->textV));
}
// TODO: change this when access through rvalues is fixed
@ -325,13 +323,13 @@ static M_texid G_ObjDef_getFrameSprite(char const *fmt, char frame, int i)
for(; *fmt; fmt++)
{
if(*fmt != '%') {M_Vec_grow(buf, 1); bufV[bufC++] = *fmt; continue;}
if(*fmt != '%') {M_Vec_grow(buf, 1); M_Vec_next(buf) = *fmt; continue;}
switch(*++fmt)
{
default:
case '%': M_Vec_grow(buf, 1); bufV[bufC++] = *fmt; break;
case 'c': M_Vec_grow(buf, 1); bufV[bufC++] = frame; break;
case '%': M_Vec_grow(buf, 1); M_Vec_next(buf) = *fmt; break;
case 'c': M_Vec_grow(buf, 1); M_Vec_next(buf) = frame; break;
case 'i':
M_Vec_grow(buf, 20);
bufC += snprintf(&bufV[bufC], 20, "%i", i);
@ -351,10 +349,9 @@ static M_texid G_ObjDef_getFrameSprite(char const *fmt, char frame, int i)
//
static void G_ObjDef_parseFrameDef(G_dodst *st)
{
char name[32], frame[32], fmt[32];
M_strbufcpy(name, st->expect(tok_identi, "name")->text);
M_strbufcpy(frame, st->expect(tok_identi, "frames")->text);
M_strbufcpy(fmt, st->expect(tok_string, "format")->text);
char const *name = st->expect(tok_identi, "name")->textV;
char const *frame = st->expect(tok_identi, "frames")->textV;
char const *fmt = st->expect(tok_string, "format")->textV;
for(int i = 0; frame[i]; i++)
{
@ -367,7 +364,7 @@ static void G_ObjDef_parseFrameDef(G_dodst *st)
if(!decl)
{
M_Vec_grow(G_frvec, 1);
*(decl = &G_frvecV[G_frvecC++]) = (G_frdcl){};
*(decl = &M_Vec_next(G_frvec)) = (G_frdcl){};
M_strbufcpy(decl->name, key);
decl->keyhash = M_StrHash(decl->name);
G_frametab.insert(decl);
@ -382,17 +379,16 @@ static void G_ObjDef_parseFrameDef(G_dodst *st)
//
static void G_ObjDef_parseAnim(G_dodst *st, G_andcl *decl)
{
char name[32], frames[32];
M_strbufcpy(name, st->expect(tok_identi, "name")->text);
M_strbufcpy(frames, st->expect(tok_identi, "frame")->text);
int time = strtoi(st->expect(tok_number, "time")->text, NULL, 0);
char const *name = st->expect(tok_identi, "name")->textV;
char const *frames = st->expect(tok_identi, "frame")->textV;
int time = strtoi(st->expect(tok_number, "time")->textV, NULL, 0);
M_Vec_growN(decl->frame, strlen(frames), 0);
for(char const *frame = frames; *frame; frame++) {
char *key = M_StrFmt("%s%c", name, *frame);
G_frdcl *fr = G_frametab.find(key);
if(!fr) st->throw(M_StrFmt("undefined frame '%s'", key));
decl->frameV[decl->frameC++] = (G_frame){time, fr->sprite};
M_Vec_next(decl->frame) = (G_frame){time, fr->sprite};
}
}
@ -404,11 +400,11 @@ static void G_ObjDef_parseAnimDef(G_dodst *st)
bool ins = true;
G_andcl *decl;
__with(char const *name = st->expect(tok_identi, "anim name")->text;)
__with(char const *name = st->expect(tok_identi, "anim name")->textV;)
{
if((decl = G_animsmap.find(name)) == NULL) {
M_Vec_grow(G_anvec, 1);
*(decl = &G_anvecV[G_anvecC++]) = (G_andcl){};
*(decl = &M_Vec_next(G_anvec)) = (G_andcl){};
M_strbufcpy(decl->name, name);
} else {
ins = false;
@ -434,11 +430,11 @@ static void G_ObjDef_parseEntDef(G_dodst *st)
bool ins = true;
G_etdcl *decl;
__with(char const *name = st->expect(tok_identi, "entity name")->text;)
__with(char const *name = st->expect(tok_identi, "entity name")->textV;)
{
if((decl = G_enttypes.find(name)) == NULL) {
M_Vec_grow(G_etvec, 1);
*(decl = &G_etvecV[G_etvecC++]) = (G_etdcl){};
*(decl = &M_Vec_next(G_etvec)) = (G_etdcl){};
M_strbufcpy(decl->name, name);
G_anims_ctor(&decl->anim, 8, 8);
} else {
@ -448,7 +444,7 @@ static void G_ObjDef_parseEntDef(G_dodst *st)
if(st->drop(tok_lt)) {
G_etdcl *base =
G_enttypes.find(st->expect(tok_identi, "base entity name")->text);
G_enttypes.find(st->expect(tok_identi, "base entity name")->textV);
if(!base) st->throw("base type not found");
decl->type = base->type;
}
@ -459,10 +455,10 @@ static void G_ObjDef_parseEntDef(G_dodst *st)
switch(tok->type)
{
case tok_identi:
if(strcmp(tok->text, "anim") == 0)
if(strcmp(tok->textV, "anim") == 0)
G_ObjDef_getEntAnim(st, decl);
else
G_ObjDef_getEntProp(st, &decl->type, tok->text);
G_ObjDef_getEntProp(st, &decl->type, tok->textV);
break;
case tok_semico:
continue;
@ -506,7 +502,7 @@ void G_ObjDef_Load(char const *fname)
goto done;
}
st.tb.toks = calloc(G_dodTokEnd, sizeof(M_token));
st.tb.ctor();
if(setjmp(st.ejmp) == 1)
goto done;
@ -515,14 +511,14 @@ void G_ObjDef_Load(char const *fname)
switch(tok->type)
{
case tok_identi:
if(strcmp(tok->text, "entity") == 0)
if(strcmp(tok->textV, "entity") == 0)
G_ObjDef_parseEntDef(&st);
else if(strcmp(tok->text, "anim") == 0)
else if(strcmp(tok->textV, "anim") == 0)
G_ObjDef_parseAnimDef(&st);
else if(strcmp(tok->text, "frame") == 0)
else if(strcmp(tok->textV, "frame") == 0)
G_ObjDef_parseFrameDef(&st);
else if(strcmp(tok->text, "include") == 0)
G_ObjDef_Load(st.expect(tok_string, "string")->text);
else if(strcmp(tok->textV, "include") == 0)
G_ObjDef_Load(st.expect(tok_string, "string")->textV);
else
st.throw("unknown identifier in toplevel");
continue;
@ -533,7 +529,7 @@ void G_ObjDef_Load(char const *fname)
printf("ObjDef: '%s' loaded.\n", fname);
done:
free(st.tb.toks);
st.tb.dtor();
fclose(st.fp);
}
@ -544,7 +540,7 @@ void G_ObjDef_LoadFunc(char const *name, DGE_CallbackType fptr)
{
M_Vec_grow(G_ofvec, 1);
G_ofvecV[G_ofvecC] = (G_ofdcl){fptr, name, M_StrHash(name)};
G_objfuncs.insert(&G_ofvecV[G_ofvecC++]);
G_objfuncs.insert(&M_Vec_next(G_ofvec));
}
//

View File

@ -20,4 +20,6 @@
#define M_Vec_grow(vec, n) M_Vec_growN(vec, n, 8)
#define M_Vec_next(vec) ((vec##V)[(vec##C)++])
#endif

View File

@ -2,9 +2,29 @@
#include "m_tokbuf.h"
#include <string.h>
#include <stdlib.h>
// Extern Functions ----------------------------------------------------------|
//
// M_TokBuf_Ctor
//
void M_TokBuf_Ctor(M_tkbuf *tb)
{
tb->toks = calloc(tb->bend, sizeof(M_token));
}
//
// M_TokBuf_Dtor
//
void M_TokBuf_Dtor(M_tkbuf *tb)
{
for(int i = 0; i < tb->bend; i++)
free(tb->toks[i].textV);
free(tb->toks);
}
//
// M_TokBuf_Get
//
@ -14,6 +34,9 @@ M_token *M_TokBuf_Get(M_tkbuf *tb)
if(++tb->tpos < tb->tend)
return &tb->toks[tb->tpos];
for(int i = 0; i < tb->tend - tb->bbeg; i++)
free(tb->toks[i].textV);
memmove(&tb->toks[0], &tb->toks[tb->tend - tb->bbeg],
sizeof(M_token) * tb->bbeg);

View File

@ -6,6 +6,8 @@
// Extern Functions ----------------------------------------------------------|
void M_TokBuf_Ctor(struct M_tkbuf *tb);
void M_TokBuf_Dtor(struct M_tkbuf *tb);
M_token *M_TokBuf_Get(struct M_tkbuf *tb);
M_token *M_TokBuf_UnGet(struct M_tkbuf *tb);
M_token *M_TokBuf_ReGet(struct M_tkbuf *tb);
@ -22,6 +24,8 @@ enum M_tkprc
typedef struct M_tkbuf
{
__prop ctor {call: M_TokBuf_Ctor (this)}
__prop dtor {call: M_TokBuf_Dtor (this)}
__prop get {call: M_TokBuf_Get (this)}
__prop unget {call: M_TokBuf_UnGet(this)}
__prop reget {call: M_TokBuf_ReGet(this)}

View File

@ -1,14 +1,18 @@
// Copyright © 2017 Project Golan, all rights reserved.
#include "m_token.h"
#include "m_darray.h"
#include <ctype.h>
#include <stdlib.h>
#define M_Tk_getPredStr(s, fn) \
#define M_Tk_getPredStr(fn) \
do { \
int i; \
for(i = (s); i < M_countof(tok->text)-1 && fn(ch); i++, ch = fgetc(fp)) \
tok->text[i] = ch; \
tok->text[i] = '\0'; \
for(; fn(ch); ch = fgetc(fp)) { \
M_Vec_grow(tok->text, 1); \
M_Vec_next(tok->text) = ch; \
} \
M_Vec_grow(tok->text, 1); \
M_Vec_next(tok->text) = '\0'; \
ungetc(ch, fp); \
} while(0)
@ -24,7 +28,11 @@ void M_Tk_Parse(FILE *fp, M_token *tok)
{
if(!tok) return;
tok->text[0] = '\0';
if(tok->textV) {
free(tok->textV);
tok->textV = NULL;
tok->textC = tok->textS = 0;
}
if(!fp || feof(fp)) {
tok->type = tok_eof;
@ -88,7 +96,7 @@ begin:;
{
#define incmt(ch) ((ch) != '\n' && !feof(fp))
ch = fgetc(fp);
M_Tk_getPredStr(0, incmt);
M_Tk_getPredStr(incmt);
tok->type = tok_cmtlin;
#undef incmt
}
@ -112,9 +120,12 @@ begin:;
case '"': tok->type = tok_string; goto string;
string: {
int i, beg;
for(i = 0, beg = ch; (ch = fgetc(fp)) != beg && !feof(fp); i++)
tok->text[i] = ch;
tok->text[i] = '\0';
for(i = 0, beg = ch; (ch = fgetc(fp)) != beg && !feof(fp);) {
M_Vec_grow(tok->text, 1);
M_Vec_next(tok->text) = ch;
}
M_Vec_grow(tok->text, 1);
M_Vec_next(tok->text) = '\0';
return;
}
}
@ -127,20 +138,22 @@ begin:;
}
else if(isdigit(ch) || ch == '.' || ch == '-')
{
tok->text[0] = ch;
M_Vec_grow(tok->text, 1);
M_Vec_next(tok->text) = ch;
ch = fgetc(fp);
M_Tk_getPredStr(1, M_Tk_isnum);
M_Tk_getPredStr(M_Tk_isnum);
tok->type = tok_number;
}
else if(M_Tk_isidenti(ch))
{
M_Tk_getPredStr(0, M_Tk_isidenti);
M_Tk_getPredStr(M_Tk_isidenti);
tok->type = tok_identi;
}
else
{
tok->text[0] = ch;
tok->text[1] = '\0';
M_Vec_grow(tok->text, 2);
M_Vec_next(tok->text) = ch;
M_Vec_next(tok->text) = '\0';
tok->type = tok_chrseq;
}
}

View File

@ -3,6 +3,7 @@
#define m_token_h
#include "m_types.h"
#include "m_darray.h"
#include <stdio.h>
@ -90,7 +91,7 @@ typedef struct M_token
{
M_tokty type;
int line;
char text[1024];
M_Vec_decl(char, text);
} M_token;
// Extern Functions ----------------------------------------------------------|