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/functions.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
#include "util/message.h"
|
#include "util/message.h"
|
||||||
|
#include "util/crmessage.h"
|
||||||
|
#include "util/nrmessage.h"
|
||||||
#include "util/strings.h"
|
#include "util/strings.h"
|
||||||
|
|
||||||
#include <expat.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;
|
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) {
|
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;
|
const XML_Char *name = NULL, *section = NULL;
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; attr[i]; i += 2) {
|
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) {
|
else if (xml_strcmp(key, "section") == 0) {
|
||||||
section = val;
|
section = val;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
handle_bad_input(pi, el, key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (name) {
|
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
|
#define MAX_COMPONENTS 8
|
||||||
static spell_component components[MAX_COMPONENTS];
|
static spell_component components[MAX_COMPONENTS];
|
||||||
static int ncomponents;
|
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[] = {
|
const char *flag_names[] = {
|
||||||
"far", "variable", "ocean", "ship", "los",
|
"far", "variable", "ocean", "ship", "los",
|
||||||
"unittarget", "shiptarget", "buildingtarget", "regiontarget", "globaltarget", NULL };
|
"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;
|
spellbook * sb = (spellbook *)pi->object;
|
||||||
if (xml_strcmp(el, "spellbook") == 0) {
|
if (xml_strcmp(el, "spellbook") == 0) {
|
||||||
const XML_Char *name = attr_get(attr, "name");
|
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;
|
resource_type *rtype = (resource_type *)pi->object;
|
||||||
|
|
||||||
assert(rtype && rtype->wtype);
|
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 };
|
const char *flag_names[] = { "opensea", "fly", "nocoast", "speedy", NULL };
|
||||||
if (xml_strcmp(el, "ship") == 0) {
|
if (xml_strcmp(el, "ship") == 0) {
|
||||||
const XML_Char *name;
|
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 nattacks;
|
||||||
static int nfamiliars;
|
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;
|
race *rc = (race *)pi->object;
|
||||||
const char *flag_names[] = {
|
const char *flag_names[] = {
|
||||||
"playerrace", "killpeasants", "scarepeasants", "!cansteal",
|
"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 };
|
const char *flag_names[] = { "nodestroy", "nobuild", "unique", "decay", "magic", "namechange", "fort", "oneperturn", NULL };
|
||||||
if (xml_strcmp(el, "building") == 0) {
|
if (xml_strcmp(el, "building") == 0) {
|
||||||
const XML_Char *name;
|
const XML_Char *name;
|
||||||
|
@ -1427,6 +1483,9 @@ static void XMLCALL handle_end(void *data, const XML_Char *el) {
|
||||||
case EXP_SPELLS:
|
case EXP_SPELLS:
|
||||||
end_spells(pi, el);
|
end_spells(pi, el);
|
||||||
break;
|
break;
|
||||||
|
case EXP_MESSAGES:
|
||||||
|
end_messages(pi, el);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
if (pi->depth == 1) {
|
if (pi->depth == 1) {
|
||||||
pi->object = NULL;
|
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) {
|
int exparse_readfile(const char * filename) {
|
||||||
XML_Parser xp;
|
XML_Parser xp;
|
||||||
FILE *F;
|
FILE *F;
|
||||||
|
@ -1469,7 +1516,6 @@ int exparse_readfile(const char * filename) {
|
||||||
}
|
}
|
||||||
xp = XML_ParserCreate("UTF-8");
|
xp = XML_ParserCreate("UTF-8");
|
||||||
XML_SetElementHandler(xp, handle_start, handle_end);
|
XML_SetElementHandler(xp, handle_start, handle_end);
|
||||||
XML_SetCharacterDataHandler(xp, handle_data);
|
|
||||||
XML_SetUserData(xp, &pi);
|
XML_SetUserData(xp, &pi);
|
||||||
memset(&pi, 0, sizeof(pi));
|
memset(&pi, 0, sizeof(pi));
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ void test_message(CuTest *tc) {
|
||||||
message_type *mtype;
|
message_type *mtype;
|
||||||
|
|
||||||
test_setup();
|
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"));
|
CuAssertPtrEquals(tc, mtype, (void *)mt_find("custom"));
|
||||||
CuAssertIntEquals(tc, 0, mtype->nparameters);
|
CuAssertIntEquals(tc, 0, mtype->nparameters);
|
||||||
CuAssertPtrEquals(tc, NULL, (void *)mtype->pnames);
|
CuAssertPtrEquals(tc, NULL, (void *)mtype->pnames);
|
||||||
|
@ -51,7 +51,7 @@ static void test_merge_split(CuTest *tc) {
|
||||||
message *msg;
|
message *msg;
|
||||||
|
|
||||||
test_setup();
|
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, ""));
|
add_message(&mlist, msg = msg_message(mtype->name, ""));
|
||||||
msg_release(msg);
|
msg_release(msg);
|
||||||
add_message(&append, msg = msg_message(mtype->name, ""));
|
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
|
#define MT_MAXHASH 1021
|
||||||
static selist *messagetypes[MT_MAXHASH];
|
static selist *messagetypes[MT_MAXHASH];
|
||||||
|
|
||||||
message_type *mt_create(message_type * mtype, const char *args[])
|
static void mt_register(message_type * mtype) {
|
||||||
{
|
|
||||||
int nparameters = 0;
|
|
||||||
unsigned int hash = str_hash(mtype->name) % MT_MAXHASH;
|
unsigned int hash = str_hash(mtype->name) % MT_MAXHASH;
|
||||||
selist **qlp = messagetypes + hash;
|
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 */
|
/* count the number of parameters */
|
||||||
while (args[nparameters]) ++nparameters;
|
do {
|
||||||
|
++nparameters;
|
||||||
|
} while (args[nparameters]);
|
||||||
}
|
}
|
||||||
if (nparameters > 0) {
|
if (nparameters > 0) {
|
||||||
int i;
|
int i;
|
||||||
|
@ -111,9 +118,7 @@ message_type *mt_create(message_type * mtype, const char *args[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (selist_set_insert(qlp, mtype, NULL)) {
|
mt_register(mtype);
|
||||||
mtype->key = mt_id(mtype);
|
|
||||||
}
|
|
||||||
return mtype;
|
return mtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +156,7 @@ message_type *mt_create_va(message_type *mtype, ...)
|
||||||
}
|
}
|
||||||
va_end(marker);
|
va_end(marker);
|
||||||
args[i] = NULL;
|
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)
|
static variant copy_arg(const arg_type * atype, variant data)
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MSG_MAXARGS 8
|
||||||
|
#define MT_NEW_END ((const char *)0)
|
||||||
|
|
||||||
typedef struct arg_type {
|
typedef struct arg_type {
|
||||||
struct arg_type *next;
|
struct arg_type *next;
|
||||||
variant_type vtype;
|
variant_type vtype;
|
||||||
|
@ -44,9 +47,6 @@ extern "C" {
|
||||||
void message_done(void);
|
void message_done(void);
|
||||||
|
|
||||||
void mt_clear(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,
|
struct message *msg_create(const struct message_type *type,
|
||||||
variant args[]);
|
variant args[]);
|
||||||
|
@ -60,7 +60,7 @@ extern "C" {
|
||||||
|
|
||||||
struct message_type *mt_new(const char *name, const char *section);
|
struct message_type *mt_new(const char *name, const char *section);
|
||||||
/** message_type registry (optional): **/
|
/** 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 *, ...);
|
struct message_type *mt_create_va(struct message_type *, ...);
|
||||||
const struct message_type *mt_find(const char *);
|
const struct message_type *mt_find(const char *);
|
||||||
|
|
||||||
|
|
|
@ -1277,7 +1277,7 @@ static int parse_messages(xmlDocPtr doc)
|
||||||
xmlChar *propSection;
|
xmlChar *propSection;
|
||||||
xmlChar *propValue;
|
xmlChar *propValue;
|
||||||
xmlXPathObjectPtr result;
|
xmlXPathObjectPtr result;
|
||||||
int k;
|
int nargs = 0;
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
const message_type *mtype;
|
const message_type *mtype;
|
||||||
|
|
||||||
|
@ -1285,8 +1285,10 @@ static int parse_messages(xmlDocPtr doc)
|
||||||
xpath->node = node;
|
xpath->node = node;
|
||||||
result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath);
|
result = xmlXPathEvalExpression(BAD_CAST "type/arg", xpath);
|
||||||
if (result->nodesetval && result->nodesetval->nodeNr > 0) {
|
if (result->nodesetval && result->nodesetval->nodeNr > 0) {
|
||||||
argv = malloc(sizeof(char *) * (result->nodesetval->nodeNr + 1));
|
int k;
|
||||||
for (k = 0; k != result->nodesetval->nodeNr; ++k) {
|
nargs = result->nodesetval->nodeNr;
|
||||||
|
argv = malloc(sizeof(char *) * (nargs + 1));
|
||||||
|
for (k = 0; k != nargs; ++k) {
|
||||||
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
xmlNodePtr node = result->nodesetval->nodeTab[k];
|
||||||
char zBuffer[128];
|
char zBuffer[128];
|
||||||
xmlChar *propName, *propType;
|
xmlChar *propName, *propType;
|
||||||
|
@ -1299,7 +1301,7 @@ static int parse_messages(xmlDocPtr doc)
|
||||||
xmlFree(propType);
|
xmlFree(propType);
|
||||||
argv[k] = str_strdup(zBuffer);
|
argv[k] = str_strdup(zBuffer);
|
||||||
}
|
}
|
||||||
argv[result->nodesetval->nodeNr] = NULL;
|
argv[nargs] = NULL;
|
||||||
}
|
}
|
||||||
xmlXPathFreeObject(result);
|
xmlXPathFreeObject(result);
|
||||||
|
|
||||||
|
@ -1312,7 +1314,7 @@ static int parse_messages(xmlDocPtr doc)
|
||||||
propValue = xmlGetProp(node, BAD_CAST "name");
|
propValue = xmlGetProp(node, BAD_CAST "name");
|
||||||
mtype = mt_find((const char *)propValue);
|
mtype = mt_find((const char *)propValue);
|
||||||
if (mtype == NULL) {
|
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 {
|
else {
|
||||||
assert(argv != NULL || !"cannot redefine arguments of message now");
|
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 */
|
/* let's clean up the mess */
|
||||||
if (argv != NULL) {
|
if (argv != NULL) {
|
||||||
for (k = 0; argv[k] != NULL; ++k)
|
int k;
|
||||||
|
for (k = 0; argv[k] != NULL; ++k) {
|
||||||
free(argv[k]);
|
free(argv[k]);
|
||||||
|
}
|
||||||
free(argv);
|
free(argv);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue