forked from github/server
message parsing from exparse is working, but allocates too much.
This commit is contained in:
parent
19b3b5b35a
commit
6b0f75339f
|
@ -17,6 +17,8 @@
|
|||
#include "util/functions.h"
|
||||
#include "util/log.h"
|
||||
#include "util/message.h"
|
||||
#include "util/crmessage.h"
|
||||
#include "util/nrmessage.h"
|
||||
#include "util/strings.h"
|
||||
|
||||
#include <expat.h>
|
||||
|
@ -285,8 +287,56 @@ static void handle_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **at
|
|||
wtype->flags = flags;
|
||||
}
|
||||
|
||||
static void XMLCALL start_messages(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static int msg_nargs;
|
||||
static char * msg_args[MSG_MAXARGS];
|
||||
|
||||
static void end_messages(parseinfo *pi, const XML_Char *el) {
|
||||
if (xml_strcmp(el, "message") == 0) {
|
||||
int i;
|
||||
struct message_type *mtype = (struct message_type *)pi->object;
|
||||
assert(mtype);
|
||||
assert(msg_nargs < MSG_MAXARGS);
|
||||
mt_create(mtype, (const char **)msg_args, msg_nargs);
|
||||
/* register the type for CR and NR */
|
||||
crt_register(mtype);
|
||||
nrt_register(mtype);
|
||||
|
||||
for (i = 0; i != msg_nargs; ++i) {
|
||||
free(msg_args[i]);
|
||||
msg_args[i] = NULL;
|
||||
}
|
||||
msg_nargs = 0;
|
||||
}
|
||||
else if (xml_strcmp(el, "messages") == 0) {
|
||||
pi->type = EXP_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
static void start_messages(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
if (xml_strcmp(el, "arg") == 0) {
|
||||
int i;
|
||||
const XML_Char *name = NULL, *type = NULL;
|
||||
|
||||
assert(msg_nargs < MSG_MAXARGS);
|
||||
for (i = 0; attr[i]; i += 2) {
|
||||
const XML_Char *key = attr[i], *val = attr[i + 1];
|
||||
if (xml_strcmp(key, "name") == 0) {
|
||||
name = val;
|
||||
}
|
||||
else if (xml_strcmp(key, "type") == 0) {
|
||||
type = val;
|
||||
}
|
||||
else {
|
||||
handle_bad_input(pi, el, key);
|
||||
}
|
||||
}
|
||||
if (name && type) {
|
||||
char zBuffer[128];
|
||||
sprintf(zBuffer, "%s:%s", name, type);
|
||||
msg_args[msg_nargs++] = str_strdup(zBuffer);
|
||||
}
|
||||
}
|
||||
else if (xml_strcmp(el, "message") == 0) {
|
||||
const XML_Char *name = NULL, *section = NULL;
|
||||
int i;
|
||||
for (i = 0; attr[i]; i += 2) {
|
||||
|
@ -297,18 +347,24 @@ static void XMLCALL start_messages(parseinfo *pi, const XML_Char *el, const XML_
|
|||
else if (xml_strcmp(key, "section") == 0) {
|
||||
section = val;
|
||||
}
|
||||
else {
|
||||
handle_bad_input(pi, el, key);
|
||||
}
|
||||
}
|
||||
if (name) {
|
||||
pi->object = mt_new(name, NULL);
|
||||
pi->object = mt_new(name, section);
|
||||
}
|
||||
}
|
||||
else if (xml_strcmp(el, "type") != 0 && xml_strcmp(el, "text") != 0) {
|
||||
handle_bad_input(pi, el, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_COMPONENTS 8
|
||||
static spell_component components[MAX_COMPONENTS];
|
||||
static int ncomponents;
|
||||
|
||||
static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static void start_spells(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
const char *flag_names[] = {
|
||||
"far", "variable", "ocean", "ship", "los",
|
||||
"unittarget", "shiptarget", "buildingtarget", "regiontarget", "globaltarget", NULL };
|
||||
|
@ -390,7 +446,7 @@ static void XMLCALL start_spells(parseinfo *pi, const XML_Char *el, const XML_Ch
|
|||
}
|
||||
}
|
||||
|
||||
static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static void start_spellbooks(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
spellbook * sb = (spellbook *)pi->object;
|
||||
if (xml_strcmp(el, "spellbook") == 0) {
|
||||
const XML_Char *name = attr_get(attr, "name");
|
||||
|
@ -430,7 +486,7 @@ static void XMLCALL start_spellbooks(parseinfo *pi, const XML_Char *el, const XM
|
|||
}
|
||||
}
|
||||
|
||||
static void XMLCALL start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static void start_weapon(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
resource_type *rtype = (resource_type *)pi->object;
|
||||
|
||||
assert(rtype && rtype->wtype);
|
||||
|
@ -791,7 +847,7 @@ static void start_resources(parseinfo *pi, const XML_Char *el, const XML_Char **
|
|||
}
|
||||
}
|
||||
|
||||
static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static void start_ships(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
const char *flag_names[] = { "opensea", "fly", "nocoast", "speedy", NULL };
|
||||
if (xml_strcmp(el, "ship") == 0) {
|
||||
const XML_Char *name;
|
||||
|
@ -899,7 +955,7 @@ static void XMLCALL start_ships(parseinfo *pi, const XML_Char *el, const XML_Cha
|
|||
static int nattacks;
|
||||
static int nfamiliars;
|
||||
|
||||
static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static void start_races(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
race *rc = (race *)pi->object;
|
||||
const char *flag_names[] = {
|
||||
"playerrace", "killpeasants", "scarepeasants", "!cansteal",
|
||||
|
@ -1116,7 +1172,7 @@ static void XMLCALL start_races(parseinfo *pi, const XML_Char *el, const XML_Cha
|
|||
}
|
||||
}
|
||||
|
||||
static void XMLCALL start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
static void start_buildings(parseinfo *pi, const XML_Char *el, const XML_Char **attr) {
|
||||
const char *flag_names[] = { "nodestroy", "nobuild", "unique", "decay", "magic", "namechange", "fort", "oneperturn", NULL };
|
||||
if (xml_strcmp(el, "building") == 0) {
|
||||
const XML_Char *name;
|
||||
|
@ -1427,6 +1483,9 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
|
|||
case EXP_SPELLS:
|
||||
end_spells(pi, el);
|
||||
break;
|
||||
case EXP_MESSAGES:
|
||||
end_messages(pi, el);
|
||||
break;
|
||||
default:
|
||||
if (pi->depth == 1) {
|
||||
pi->object = NULL;
|
||||
|
@ -1444,18 +1503,6 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
|
|||
}
|
||||
}
|
||||
|
||||
static void XMLCALL handle_data(void *data, const XML_Char *xs, int len) {
|
||||
parseinfo *pi = (parseinfo *)data;
|
||||
if (len > 0) {
|
||||
if (pi->type == EXP_MESSAGES && pi->depth == 4) {
|
||||
size_t bytes = (size_t)len;
|
||||
pi->cdata = realloc(pi->cdata, pi->clength + bytes);
|
||||
memcpy(pi->cdata + pi->clength, xs, bytes);
|
||||
pi->clength = pi->clength + bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int exparse_readfile(const char * filename) {
|
||||
XML_Parser xp;
|
||||
FILE *F;
|
||||
|
@ -1469,7 +1516,6 @@ int exparse_readfile(const char * filename) {
|
|||
}
|
||||
xp = XML_ParserCreate("UTF-8");
|
||||
XML_SetElementHandler(xp, handle_start, handle_end);
|
||||
XML_SetCharacterDataHandler(xp, handle_data);
|
||||
XML_SetUserData(xp, &pi);
|
||||
memset(&pi, 0, sizeof(pi));
|
||||
for (;;) {
|
||||
|
|
|
@ -25,7 +25,7 @@ void test_message(CuTest *tc) {
|
|||
message_type *mtype;
|
||||
|
||||
test_setup();
|
||||
mtype = mt_create(mt_new("custom", NULL), NULL);
|
||||
mtype = mt_create(mt_new("custom", NULL), NULL, 0);
|
||||
CuAssertPtrEquals(tc, mtype, (void *)mt_find("custom"));
|
||||
CuAssertIntEquals(tc, 0, mtype->nparameters);
|
||||
CuAssertPtrEquals(tc, NULL, (void *)mtype->pnames);
|
||||
|
@ -51,7 +51,7 @@ static void test_merge_split(CuTest *tc) {
|
|||
message *msg;
|
||||
|
||||
test_setup();
|
||||
mtype = mt_create(mt_new("custom", NULL), NULL);
|
||||
mtype = mt_create(mt_new("custom", NULL), NULL, 0);
|
||||
add_message(&mlist, msg = msg_message(mtype->name, ""));
|
||||
msg_release(msg);
|
||||
add_message(&append, msg = msg_message(mtype->name, ""));
|
||||
|
|
|
@ -75,15 +75,22 @@ static unsigned int mt_id(const message_type * mtype)
|
|||
#define MT_MAXHASH 1021
|
||||
static selist *messagetypes[MT_MAXHASH];
|
||||
|
||||
message_type *mt_create(message_type * mtype, const char *args[])
|
||||
{
|
||||
int nparameters = 0;
|
||||
static void mt_register(message_type * mtype) {
|
||||
unsigned int hash = str_hash(mtype->name) % MT_MAXHASH;
|
||||
selist **qlp = messagetypes + hash;
|
||||
|
||||
if (args != NULL) {
|
||||
if (selist_set_insert(qlp, mtype, NULL)) {
|
||||
mtype->key = mt_id(mtype);
|
||||
}
|
||||
}
|
||||
|
||||
message_type *mt_create(message_type * mtype, const char *args[], int nparameters)
|
||||
{
|
||||
if (args != NULL && args[nparameters]) {
|
||||
/* count the number of parameters */
|
||||
while (args[nparameters]) ++nparameters;
|
||||
do {
|
||||
++nparameters;
|
||||
} while (args[nparameters]);
|
||||
}
|
||||
if (nparameters > 0) {
|
||||
int i;
|
||||
|
@ -111,9 +118,7 @@ message_type *mt_create(message_type * mtype, const char *args[])
|
|||
}
|
||||
}
|
||||
}
|
||||
if (selist_set_insert(qlp, mtype, NULL)) {
|
||||
mtype->key = mt_id(mtype);
|
||||
}
|
||||
mt_register(mtype);
|
||||
return mtype;
|
||||
}
|
||||
|
||||
|
@ -151,7 +156,7 @@ message_type *mt_create_va(message_type *mtype, ...)
|
|||
}
|
||||
va_end(marker);
|
||||
args[i] = NULL;
|
||||
return mt_create(mtype, args);
|
||||
return mt_create(mtype, args, i - 1);
|
||||
}
|
||||
|
||||
static variant copy_arg(const arg_type * atype, variant data)
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define MSG_MAXARGS 8
|
||||
#define MT_NEW_END ((const char *)0)
|
||||
|
||||
typedef struct arg_type {
|
||||
struct arg_type *next;
|
||||
variant_type vtype;
|
||||
|
@ -44,9 +47,6 @@ extern "C" {
|
|||
void message_done(void);
|
||||
|
||||
void mt_clear(void);
|
||||
#define MT_NEW_END ((const char *)0)
|
||||
/* mt_new("simple_sentence", "subject:string", "predicate:string",
|
||||
* "object:string", "lang:locale", MT_NEW_END); */
|
||||
|
||||
struct message *msg_create(const struct message_type *type,
|
||||
variant args[]);
|
||||
|
@ -60,7 +60,7 @@ extern "C" {
|
|||
|
||||
struct message_type *mt_new(const char *name, const char *section);
|
||||
/** message_type registry (optional): **/
|
||||
struct message_type *mt_create(struct message_type *, const char *args[]);
|
||||
struct message_type *mt_create(struct message_type *, const char *args[], int nargs);
|
||||
struct message_type *mt_create_va(struct message_type *, ...);
|
||||
const struct message_type *mt_find(const char *);
|
||||
|
||||
|
|
|
@ -1277,7 +1277,7 @@ static int parse_messages(xmlDocPtr doc)
|
|||
xmlChar *propSection;
|
||||
xmlChar *propValue;
|
||||
xmlXPathObjectPtr result;
|
||||
int k;
|
||||
int nargs = 0;
|
||||
char **argv = NULL;
|
||||
const message_type *mtype;
|
||||
|
||||
|
@ -1285,8 +1285,10 @@ static int parse_messages(xmlDocPtr doc)
|
|||
xpath->node = node;
|
||||
result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath);
|
||||
if (result->nodesetval && result->nodesetval->nodeNr > 0) {
|
||||
argv = malloc(sizeof(char *) * (result->nodesetval->nodeNr + 1));
|
||||
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
||||
int k;
|
||||
nargs = result->nodesetval->nodeNr;
|
||||
argv = malloc(sizeof(char *) * (nargs + 1));
|
||||
for (k = 0; k != nargs; ++k) {
|
||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
||||
char zBuffer[128];
|
||||
xmlChar *propName, *propType;
|
||||
|
@ -1299,7 +1301,7 @@ static int parse_messages(xmlDocPtr doc)
|
|||
xmlFree(propType);
|
||||
argv[k] = str_strdup(zBuffer);
|
||||
}
|
||||
argv[result->nodesetval->nodeNr] = NULL;
|
||||
argv[nargs] = NULL;
|
||||
}
|
||||
xmlXPathFreeObject(result);
|
||||
|
||||
|
@ -1312,7 +1314,7 @@ static int parse_messages(xmlDocPtr doc)
|
|||
propValue = xmlGetProp(node, BAD_CAST "name");
|
||||
mtype = mt_find((const char *)propValue);
|
||||
if (mtype == NULL) {
|
||||
mtype = mt_create(mt_new((const char *)propValue, (const char *)propSection), (const char **)argv);
|
||||
mtype = mt_create(mt_new((const char *)propValue, (const char *)propSection), (const char **)argv, nargs);
|
||||
}
|
||||
else {
|
||||
assert(argv != NULL || !"cannot redefine arguments of message now");
|
||||
|
@ -1329,8 +1331,10 @@ static int parse_messages(xmlDocPtr doc)
|
|||
|
||||
/* let's clean up the mess */
|
||||
if (argv != NULL) {
|
||||
for (k = 0; argv[k] != NULL; ++k)
|
||||
int k;
|
||||
for (k = 0; argv[k] != NULL; ++k) {
|
||||
free(argv[k]);
|
||||
}
|
||||
free(argv);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue