2011-04-25 20:59:53 +00:00
|
|
|
/*------------------------------------------------------------------
|
|
|
|
* Glue for libpsyc.
|
|
|
|
*------------------------------------------------------------------
|
|
|
|
* test LPC code:
|
2011-04-26 08:02:17 +00:00
|
|
|
*
|
2011-05-19 19:27:20 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
#define CHECK_PARSE_RET if (ret != 0) raise_error(sprintf("FAIL: psyc_parse returned %d\n", ret))
|
|
|
|
|
2011-05-19 19:27:20 +00:00
|
|
|
string s, s2;
|
|
|
|
|
|
|
|
create() {
|
2011-05-20 08:36:18 +00:00
|
|
|
mixed p, r;
|
2011-05-22 22:55:39 +00:00
|
|
|
int ret;
|
2011-05-20 08:36:18 +00:00
|
|
|
|
|
|
|
s = "=_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
2011-05-22 22:55:39 +00:00
|
|
|
ret = psyc_parse(s+s+s); CHECK_PARSE_RET;
|
2011-05-19 19:27:20 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
ret = psyc_parse("=_context\ttest\n\n:_topic\ttest"); CHECK_PARSE_RET;
|
|
|
|
ret = psyc_parse("ing\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"); CHECK_PARSE_RET;
|
2011-05-19 19:27:20 +00:00
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
p = ({ ([ "_context": "test"; '=' ]), ([ "_topic": "testing" ]),
|
2011-05-19 19:27:20 +00:00
|
|
|
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
|
|
|
r = psyc_render(p);
|
2011-05-20 08:36:18 +00:00
|
|
|
debug_message(sprintf(">> psyc_render returned:\n%s\n", r));
|
|
|
|
if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s));
|
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
s = "=_context\ttest\n\n:_amount\t4404\n:_list\t|4|4|0|4\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
|
|
|
s2 = "=_context\ttest\n\n:_list\t|4|4|0|4\n:_amount\t4404\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
|
|
|
p = ({ ([ "_context": "test"; '=' ]), ([ "_amount": 4404, "_list": ({4,4,0,4}) ]),
|
|
|
|
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
|
|
|
r = psyc_render(p);
|
|
|
|
|
|
|
|
debug_message(sprintf(">> psyc_render returned:\n%s\n", r));
|
|
|
|
if (r != s && r != s2) raise_error(sprintf(">> FAIL, expected:\n%s- or -\n%s\n", s, s2));
|
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
s = "=_context\ttest\n\n:_time_foo\t59\n:_time_bar\t-41\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
|
|
|
s2 = "=_context\ttest\n\n:_time_bar\t-41\n:_time_foo\t59\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
2011-05-22 22:55:39 +00:00
|
|
|
ret = psyc_parse(s); CHECK_PARSE_RET;
|
2011-05-19 19:27:20 +00:00
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
s = "=_context\ttest\n\n:_date_foo\t59\n:_date_bar\t-41\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
|
|
|
s2 = "=_context\ttest\n\n:_date_bar\t-41\n:_date_foo\t59\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
2011-05-22 22:55:39 +00:00
|
|
|
ret = psyc_parse(s); CHECK_PARSE_RET;
|
2011-05-19 19:27:20 +00:00
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
s = "=_context\ttest\n\n:_list_foo\t|foo|bar|baz\n:_list_bar\t\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
|
|
|
s2 = "=_context\ttest\n\n:_list_bar\t\n:_list_foo\t|foo|bar|baz\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
|
2011-05-22 22:55:39 +00:00
|
|
|
ret = psyc_parse(s); CHECK_PARSE_RET;
|
2011-05-20 08:36:18 +00:00
|
|
|
|
|
|
|
p = ({ ([ "_context": "test"; '=' ]),
|
2011-05-19 19:27:20 +00:00
|
|
|
([ "_list_foo": ({ "foo", "bar", "baz" }), "_list_bar": ({}) ]),
|
|
|
|
"_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
|
|
|
r = psyc_render(p);
|
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
debug_message(sprintf(">> psyc_render returned:\n%s\n", r));
|
|
|
|
if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s));
|
2011-05-19 19:27:20 +00:00
|
|
|
|
|
|
|
debug_message(sprintf(">> SUCCESS\n"));
|
|
|
|
}
|
|
|
|
|
|
|
|
psyc_dispatch(mixed p) {
|
|
|
|
debug_message(sprintf(">> psyc_parse returned:\n%O\n", p));
|
|
|
|
|
|
|
|
mixed r = psyc_render(p);
|
|
|
|
debug_message(sprintf(">> psyc_render returned:\n%s", r));
|
2011-05-20 08:36:18 +00:00
|
|
|
if (r != s && r != s2) raise_error(sprintf(">> FAIL, expected:\n%s- or -\n%s\n", s, s2));
|
2011-05-19 19:27:20 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "array.h"
|
|
|
|
#include "interpret.h"
|
2011-04-26 00:42:01 +00:00
|
|
|
#include "mapping.h"
|
2011-04-25 20:59:53 +00:00
|
|
|
#include "mstrings.h"
|
2011-05-08 19:54:28 +00:00
|
|
|
#include "object.h"
|
2011-04-26 08:02:17 +00:00
|
|
|
#include "pkg-psyc.h"
|
2011-04-25 20:59:53 +00:00
|
|
|
#include "simulate.h"
|
2011-04-26 00:42:01 +00:00
|
|
|
#include "xalloc.h"
|
2011-05-22 22:55:39 +00:00
|
|
|
#include "efuns.h"
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-05-24 14:29:03 +00:00
|
|
|
#ifdef HAS_PSYC
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-05-08 19:28:31 +00:00
|
|
|
# include "pkg-psyc.h"
|
|
|
|
|
2011-04-26 08:02:17 +00:00
|
|
|
# include <stdio.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <fcntl.h>
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-04-26 08:02:17 +00:00
|
|
|
# include <psyc.h>
|
2011-05-09 19:33:45 +00:00
|
|
|
# include <psyc/parse.h>
|
2011-04-26 08:02:17 +00:00
|
|
|
# include <psyc/render.h>
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-05-12 14:40:45 +00:00
|
|
|
void
|
|
|
|
fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
|
|
|
|
psyc_modifier_t *m = extra;
|
2011-05-22 22:55:39 +00:00
|
|
|
char oper = 0;
|
|
|
|
char *name, *value;
|
2011-05-13 21:17:10 +00:00
|
|
|
size_t namelen, valuelen, i;
|
2011-05-20 08:36:18 +00:00
|
|
|
uint8_t type;
|
2011-05-22 22:55:39 +00:00
|
|
|
svalue_t vsp, *lval;
|
|
|
|
|
|
|
|
psycList list;
|
|
|
|
psycString *elems = NULL;
|
2011-05-12 11:54:56 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
if (key->type != T_STRING) {
|
2011-05-13 21:17:10 +00:00
|
|
|
errorf("fill_header_from_mapping: key type %d not supported\n", key->type);
|
2011-05-22 22:55:39 +00:00
|
|
|
return; // not reached
|
|
|
|
}
|
2011-05-12 11:54:56 +00:00
|
|
|
|
|
|
|
name = get_txt(key->u.str);
|
|
|
|
namelen = mstrsize(key->u.str);
|
2011-05-20 08:36:18 +00:00
|
|
|
type = psyc_getVarType2(name, namelen);
|
|
|
|
|
|
|
|
if (m->num_values > 1)
|
|
|
|
oper = val[1].u.number;
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!oper)
|
2011-05-20 08:36:18 +00:00
|
|
|
oper = C_GLYPH_OPERATOR_SET;
|
2011-05-12 11:54:56 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
switch (val->type) {
|
|
|
|
case T_STRING:
|
|
|
|
value = get_txt(val->u.str);
|
|
|
|
valuelen = mstrsize(val->u.str);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case T_NUMBER:
|
|
|
|
case T_OBJECT:
|
|
|
|
vsp.type = val->type;
|
|
|
|
switch (val->type) {
|
|
|
|
case T_NUMBER:
|
|
|
|
if (type == PSYC_TYPE_DATE)
|
|
|
|
vsp.u.number = val->u.number - PSYC_EPOCH;
|
|
|
|
else
|
|
|
|
vsp.u.number = val->u.number;
|
|
|
|
break;
|
|
|
|
case T_OBJECT:
|
|
|
|
vsp.u.ob = val->u.ob;
|
|
|
|
break;
|
2011-05-13 21:17:10 +00:00
|
|
|
}
|
|
|
|
|
2011-05-23 11:03:06 +00:00
|
|
|
f_to_string(&vsp); // generates an mstring
|
2011-05-22 22:55:39 +00:00
|
|
|
value = get_txt(vsp.u.str);
|
2011-05-23 11:03:06 +00:00
|
|
|
valuelen = mstrsize(vsp.u.str);
|
2011-05-22 22:55:39 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case T_POINTER:
|
|
|
|
if (VEC_SIZE(val->u.vec)) {
|
|
|
|
elems = pxalloc(sizeof(psycString) * VEC_SIZE(val->u.vec));
|
|
|
|
if (!elems) {
|
|
|
|
errorf("Out of memory in fill_header_from_mapping for elems\n");
|
|
|
|
return; // not reached
|
|
|
|
}
|
2011-05-13 21:17:10 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
for (i = 0; i < VEC_SIZE(val->u.vec); i++) {
|
|
|
|
lval = &(val->u.vec->item[i]);
|
|
|
|
switch (lval->type) {
|
|
|
|
case T_STRING:
|
|
|
|
elems[i] = (psycString){mstrsize(lval->u.str), get_txt(lval->u.str)};
|
|
|
|
break;
|
|
|
|
case T_NUMBER:
|
|
|
|
case T_OBJECT:
|
|
|
|
vsp.type = lval->type;
|
|
|
|
switch (lval->type) {
|
|
|
|
case T_NUMBER:
|
|
|
|
vsp.u.number = lval->u.number;
|
|
|
|
break;
|
|
|
|
case T_OBJECT:
|
|
|
|
vsp.u.ob = lval->u.ob;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
f_to_string(&vsp);
|
2011-05-23 11:03:06 +00:00
|
|
|
elems[i] = (psycString){mstrsize(vsp.u.str), get_txt(vsp.u.str)};
|
2011-05-22 22:55:39 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errorf("fill_header_from_mapping: list value type %d not supported\n", lval->type);
|
|
|
|
return; // not reached
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
list = psyc_newList(elems, VEC_SIZE(val->u.vec), PSYC_LIST_CHECK_LENGTH);
|
|
|
|
valuelen = list.length;
|
|
|
|
value = pxalloc(valuelen);
|
|
|
|
if (!value) {
|
|
|
|
errorf("Out of memory in fill_header_from_mapping for list value\n");
|
|
|
|
return; // not reached
|
|
|
|
}
|
|
|
|
|
|
|
|
psyc_renderList(&list, value, valuelen);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
errorf("fill_header_from_mapping: value type %d not supported\n", val->type);
|
|
|
|
return; // not reached
|
|
|
|
}
|
2011-05-12 11:54:56 +00:00
|
|
|
|
2011-05-12 14:40:45 +00:00
|
|
|
m->header->modifiers[m->header->lines++] =
|
2011-05-20 08:36:18 +00:00
|
|
|
psyc_newModifier2(oper, name, namelen, value, valuelen, m->flag);
|
2011-05-12 11:54:56 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
/*-------------------------------------------------------------------------*/
|
2011-04-26 08:02:17 +00:00
|
|
|
// old: string psyc_render(mapping, mapping, string, int* | string);
|
|
|
|
// new: string psyc_render(mixed*);
|
2011-04-25 20:59:53 +00:00
|
|
|
|
|
|
|
svalue_t *
|
|
|
|
f_psyc_render(svalue_t *sp) {
|
2011-05-22 22:55:39 +00:00
|
|
|
uint8_t i;
|
2011-04-26 08:02:17 +00:00
|
|
|
vector_t *v;
|
2011-04-25 20:59:53 +00:00
|
|
|
string_t *out;
|
2011-04-26 22:19:55 +00:00
|
|
|
char *meth, *body;
|
2011-04-27 10:26:37 +00:00
|
|
|
size_t mlen, blen;
|
|
|
|
mapping_t *map;
|
2011-04-26 08:02:17 +00:00
|
|
|
|
2011-05-12 11:54:56 +00:00
|
|
|
psycPacket packet;
|
|
|
|
psycHeader headers[2];
|
|
|
|
|
2011-04-26 08:02:17 +00:00
|
|
|
// unless (sp->type == T_POINTER) return sp;
|
|
|
|
v = sp->u.vec;
|
2011-05-22 22:55:39 +00:00
|
|
|
if (VEC_SIZE(v) == PACKET_BODY + 1) {
|
|
|
|
for (i = PACKET_ROUTING; i <= PACKET_ENTITY; i++) {
|
2011-05-23 16:30:47 +00:00
|
|
|
headers[i].lines = 0;
|
2011-05-22 22:55:39 +00:00
|
|
|
if (v->item[i].type == T_MAPPING) {
|
|
|
|
map = v->item[i].u.map;
|
|
|
|
if (!MAP_SIZE(map)) continue;
|
|
|
|
|
|
|
|
headers[i].modifiers = malloc(sizeof(psycModifier) * MAP_SIZE(v->item[i].u.map));
|
|
|
|
if (!headers[i].modifiers) {
|
2011-05-23 11:03:06 +00:00
|
|
|
errorf("Out of memory in psyc_render for modifier table.\n");
|
2011-05-22 22:55:39 +00:00
|
|
|
return sp; // not reached
|
|
|
|
}
|
|
|
|
|
2011-05-12 14:40:45 +00:00
|
|
|
walk_mapping(map, &fill_header_from_mapping,
|
2011-05-22 22:55:39 +00:00
|
|
|
&(psyc_modifier_t) {
|
|
|
|
&headers[i], map->num_values,
|
|
|
|
i == PACKET_ROUTING ?
|
|
|
|
PSYC_MODIFIER_ROUTING :
|
|
|
|
PSYC_MODIFIER_CHECK_LENGTH
|
|
|
|
});
|
|
|
|
}
|
2011-05-23 11:03:06 +00:00
|
|
|
// else ... ignoring possibly invalid args
|
2011-05-12 11:54:56 +00:00
|
|
|
}
|
2011-05-22 22:55:39 +00:00
|
|
|
} else {
|
|
|
|
errorf("Wrong number of elements (%" PRIdMPINT ") "
|
|
|
|
"in array argument to psyc_render()\n", VEC_SIZE(v));
|
|
|
|
return sp; // not reached
|
2011-04-27 10:26:37 +00:00
|
|
|
}
|
|
|
|
|
2011-05-12 11:54:56 +00:00
|
|
|
if (v->item[PACKET_METHOD].type == T_STRING) {
|
|
|
|
meth = get_txt(v->item[PACKET_METHOD].u.str);
|
|
|
|
mlen = mstrsize(v->item[PACKET_METHOD].u.str);
|
2011-04-26 22:19:55 +00:00
|
|
|
} else {
|
|
|
|
meth = NULL;
|
|
|
|
mlen = 0;
|
|
|
|
}
|
2011-05-22 22:55:39 +00:00
|
|
|
|
2011-05-12 11:54:56 +00:00
|
|
|
if (v->item[PACKET_BODY].type == T_STRING) {
|
|
|
|
body = get_txt(v->item[PACKET_BODY].u.str);
|
|
|
|
blen = mstrsize(v->item[PACKET_BODY].u.str);
|
2011-04-26 22:19:55 +00:00
|
|
|
} else {
|
|
|
|
body = NULL;
|
|
|
|
blen = 0;
|
|
|
|
}
|
2011-04-26 08:02:17 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
packet = psyc_newPacket2(headers[PACKET_ROUTING].modifiers,
|
|
|
|
headers[PACKET_ROUTING].lines,
|
|
|
|
headers[PACKET_ENTITY].modifiers,
|
|
|
|
headers[PACKET_ENTITY].lines,
|
|
|
|
meth, mlen, body, blen,
|
|
|
|
PSYC_PACKET_CHECK_LENGTH);
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2011-05-09 19:33:45 +00:00
|
|
|
printf("rendering... packet.length = %ld\n", packet.length);
|
2011-05-22 22:55:39 +00:00
|
|
|
#endif
|
2011-04-26 20:00:45 +00:00
|
|
|
// alloc_mstring creates an *untabled* string suitable for tmp data
|
2011-04-26 08:02:17 +00:00
|
|
|
memsafe(out = alloc_mstring(packet.length), packet.length, "f_psyc_render");
|
|
|
|
psyc_render(&packet, get_txt(out), packet.length);
|
|
|
|
|
|
|
|
free_svalue(sp);
|
2011-04-25 20:59:53 +00:00
|
|
|
put_string(sp, out);
|
2011-04-26 20:00:45 +00:00
|
|
|
// stack should take care of freeing the string after use
|
2011-04-25 20:59:53 +00:00
|
|
|
return sp;
|
|
|
|
|
|
|
|
} /* f_psyc_render */
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
2011-05-22 22:55:39 +00:00
|
|
|
// int psyc_parse(int* | string);
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-05-20 00:37:03 +00:00
|
|
|
static string_t *psyc_dispatch_callback = NULL;
|
2011-05-22 22:55:39 +00:00
|
|
|
static string_t *psyc_error_callback = NULL;
|
2011-05-20 00:37:03 +00:00
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
svalue_t *
|
|
|
|
f_psyc_parse (svalue_t *sp) {
|
2011-05-11 15:09:22 +00:00
|
|
|
char *buffer = NULL;
|
2011-05-13 21:17:10 +00:00
|
|
|
svalue_t *sv;
|
|
|
|
vector_t *v, *list;
|
2011-04-26 00:42:01 +00:00
|
|
|
mapping_t *map;
|
2011-05-08 14:58:35 +00:00
|
|
|
char oper = 0;
|
2011-05-13 21:17:10 +00:00
|
|
|
psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem;
|
2011-04-26 00:42:01 +00:00
|
|
|
psycParseListState listState;
|
2011-05-22 22:55:39 +00:00
|
|
|
int ret, retl, type = -1, error = 0;
|
2011-05-13 21:17:10 +00:00
|
|
|
size_t size, i;
|
2011-05-23 11:11:32 +00:00
|
|
|
ssize_t n;
|
2011-05-23 11:21:15 +00:00
|
|
|
time_t timmy;
|
2011-05-20 00:37:03 +00:00
|
|
|
|
|
|
|
if (!psyc_dispatch_callback)
|
|
|
|
psyc_dispatch_callback = new_tabled("psyc_dispatch");
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!psyc_error_callback)
|
|
|
|
psyc_error_callback = new_tabled("psyc_error");
|
|
|
|
|
2011-05-08 20:11:58 +00:00
|
|
|
assert_shadow_sent(current_object);
|
2011-05-09 19:33:45 +00:00
|
|
|
psyc_state_t *state = O_GET_PSYC_STATE(current_object);
|
2011-05-08 14:58:35 +00:00
|
|
|
if (!state) {
|
2011-05-09 19:33:45 +00:00
|
|
|
state = pxalloc(sizeof(psyc_state_t));
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!state) {
|
|
|
|
errorf("Out of memory for psyc state struct.\n");
|
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-08 14:58:35 +00:00
|
|
|
O_GET_PSYC_STATE(current_object) = state;
|
2011-05-09 23:02:14 +00:00
|
|
|
memset(state, 0, sizeof(psyc_state_t));
|
|
|
|
|
2011-05-08 14:58:35 +00:00
|
|
|
state->parser = pxalloc(sizeof(psycParseState));
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!state->parser) {
|
|
|
|
errorf("Out of memory for psyc parse state struct.\n");
|
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-08 14:58:35 +00:00
|
|
|
psyc_initParseState(state->parser);
|
|
|
|
}
|
2011-05-19 19:27:20 +00:00
|
|
|
v = state->packet;
|
2011-05-08 14:58:35 +00:00
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
if (sp->type == T_POINTER) {
|
2011-05-22 22:55:39 +00:00
|
|
|
errorf("\npsyc_parse got %ld int* bytes... not supported yet\n",
|
|
|
|
VEC_SIZE(sp->u.vec));
|
|
|
|
return sp; // not reached
|
2011-05-11 15:09:22 +00:00
|
|
|
} else if (sp->type == T_STRING) {
|
2011-05-22 22:55:39 +00:00
|
|
|
#ifdef DEBUG
|
2011-05-09 19:33:45 +00:00
|
|
|
printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
|
2011-05-22 22:55:39 +00:00
|
|
|
#endif
|
2011-05-11 15:09:22 +00:00
|
|
|
if (state->remaining) {
|
|
|
|
// there are remaining bytes from the previous call to psyc_parse,
|
|
|
|
// copy them together with the newly arrived data
|
|
|
|
buffer = pxalloc(state->remaining_len + mstrsize(sp->u.str));
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!buffer) {
|
|
|
|
errorf("Out of memory for psyc_parse buffer.\n");
|
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-11 15:09:22 +00:00
|
|
|
memcpy(buffer, state->remaining, state->remaining_len);
|
2011-05-22 22:55:39 +00:00
|
|
|
memcpy(buffer + state->remaining_len, get_txt(sp->u.str),
|
|
|
|
mstrsize(sp->u.str));
|
|
|
|
psyc_setParseBuffer2(state->parser, buffer,
|
|
|
|
state->remaining_len + mstrsize(sp->u.str));
|
2011-05-11 15:09:22 +00:00
|
|
|
pfree(state->remaining);
|
|
|
|
state->remaining = NULL;
|
|
|
|
state->remaining_len = 0;
|
|
|
|
} else {
|
2011-05-22 22:55:39 +00:00
|
|
|
psyc_setParseBuffer2(state->parser, get_txt(sp->u.str),
|
|
|
|
mstrsize(sp->u.str));
|
2011-05-11 15:09:22 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
errorf("\npsyc_parse got type %d, not supported\n", sp->type);
|
2011-05-22 22:55:39 +00:00
|
|
|
return sp; // not reached
|
2011-04-25 20:59:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
do {
|
2011-05-08 19:28:31 +00:00
|
|
|
ret = psyc_parse(state->parser, &oper, &name, &value);
|
2011-05-22 22:55:39 +00:00
|
|
|
#ifdef DEBUG
|
|
|
|
printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ',
|
|
|
|
(int)name.length, name.ptr, (int)value.length, value.ptr);
|
|
|
|
#endif
|
2011-05-19 19:27:20 +00:00
|
|
|
if (!state->packet) {
|
|
|
|
state->packet = allocate_array(4);
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!state->packet) {
|
|
|
|
errorf("Out of memory for psyc_parse array.\n");
|
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-19 19:27:20 +00:00
|
|
|
v = state->packet;
|
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
map = allocate_mapping(0, 2); // empty mapping
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!map) {
|
|
|
|
errorf("Out of memory for psyc_parse routing header.\n");
|
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-19 19:27:20 +00:00
|
|
|
put_mapping(&v->item[PACKET_ROUTING], map);
|
2011-05-20 08:36:18 +00:00
|
|
|
map = allocate_mapping(0, 2); // empty mapping
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!map) {
|
|
|
|
errorf("Out of memory for psyc_parse entity header.\n");
|
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-19 19:27:20 +00:00
|
|
|
put_mapping(&v->item[PACKET_ENTITY], map);
|
|
|
|
}
|
|
|
|
|
2011-05-08 14:58:35 +00:00
|
|
|
switch (ret) {
|
|
|
|
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
|
2011-05-22 22:55:39 +00:00
|
|
|
// save oper, name & value in state at the start of
|
|
|
|
// incomplete entity or body
|
2011-05-09 19:33:45 +00:00
|
|
|
state->oper = oper;
|
2011-05-11 15:09:22 +00:00
|
|
|
state->name = mstring_alloc_string(name.length);
|
|
|
|
memcpy(get_txt(state->name), name.ptr, name.length);
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!state->name) {
|
2011-05-09 19:33:45 +00:00
|
|
|
errorf("Out of memory for name.\n");
|
2011-05-22 22:55:39 +00:00
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-09 19:33:45 +00:00
|
|
|
|
|
|
|
// allocate memory for the total length of the value
|
2011-05-11 15:09:22 +00:00
|
|
|
state->value_len = 0;
|
|
|
|
state->value = mstring_alloc_string(psyc_getParseValueLength(state->parser));
|
2011-05-22 22:55:39 +00:00
|
|
|
if (!state->value) {
|
2011-05-09 19:33:45 +00:00
|
|
|
errorf("Out of memory for value.\n");
|
2011-05-22 22:55:39 +00:00
|
|
|
return sp; // not reached
|
|
|
|
}
|
2011-05-09 19:33:45 +00:00
|
|
|
|
|
|
|
// fall thru
|
2011-05-08 14:58:35 +00:00
|
|
|
case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT:
|
|
|
|
case PSYC_PARSE_ENTITY_END: case PSYC_PARSE_BODY_END:
|
2011-05-09 19:33:45 +00:00
|
|
|
// append value to tmp buffer in state
|
2011-05-11 15:09:22 +00:00
|
|
|
memcpy(get_txt(state->value) + state->value_len, value.ptr, value.length);
|
2011-05-09 19:33:45 +00:00
|
|
|
state->value_len += value.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
|
2011-05-22 22:55:39 +00:00
|
|
|
// incomplete entity or body parsing done,
|
|
|
|
// set oper/name/value to the ones saved in state
|
2011-05-09 19:33:45 +00:00
|
|
|
oper = state->oper;
|
2011-05-11 15:09:22 +00:00
|
|
|
name.ptr = get_txt(state->name);
|
|
|
|
name.length = mstrsize(state->name);
|
|
|
|
value.ptr = get_txt(state->value);
|
|
|
|
value.length = mstrsize(state->value);
|
2011-05-08 14:58:35 +00:00
|
|
|
}
|
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
switch (ret) {
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_ROUTING:
|
2011-05-08 14:58:35 +00:00
|
|
|
sv = pxalloc(sizeof(svalue_t));
|
2011-05-20 08:36:18 +00:00
|
|
|
|
2011-04-26 20:00:45 +00:00
|
|
|
// new_n_tabled fetches a reference of a probably existing
|
|
|
|
// shared string
|
|
|
|
put_string(sv, new_n_tabled(name.ptr, name.length));
|
2011-05-12 11:54:56 +00:00
|
|
|
sv = get_map_lvalue(v->item[PACKET_ROUTING].u.map, sv);
|
2011-05-20 08:36:18 +00:00
|
|
|
put_number(&sv[1], oper);
|
2011-04-26 20:00:45 +00:00
|
|
|
// strings are capable of containing 0 so we can do this
|
|
|
|
// for binary data too. let's use a tabled string even
|
|
|
|
// for values of routing variables as they repeat a lot
|
|
|
|
put_string(sv, new_n_tabled(value.ptr, value.length));
|
2011-04-26 00:42:01 +00:00
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-10 12:10:30 +00:00
|
|
|
case PSYC_PARSE_ENTITY_START:
|
|
|
|
case PSYC_PARSE_ENTITY_CONT:
|
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_ENTITY_END:
|
2011-05-20 08:36:18 +00:00
|
|
|
case PSYC_PARSE_ENTITY:
|
2011-05-11 15:09:22 +00:00
|
|
|
sv = pxalloc(sizeof(svalue_t));
|
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
if (ret == PSYC_PARSE_ENTITY)
|
|
|
|
put_string(sv, new_n_tabled(name.ptr, name.length));
|
|
|
|
else // PSYC_PARSE_ENTITY_END
|
|
|
|
put_string(sv, make_tabled(state->name));
|
2011-05-09 19:33:45 +00:00
|
|
|
|
2011-05-12 11:54:56 +00:00
|
|
|
sv = get_map_lvalue(v->item[PACKET_ENTITY].u.map, sv);
|
2011-05-20 08:36:18 +00:00
|
|
|
put_number(&sv[1], oper);
|
|
|
|
|
|
|
|
type = psyc_getVarType(&name);
|
2011-05-22 22:55:39 +00:00
|
|
|
|
2011-05-20 08:36:18 +00:00
|
|
|
switch (type) {
|
|
|
|
case PSYC_TYPE_DATE: // number + PSYC_EPOCH
|
2011-05-23 11:21:15 +00:00
|
|
|
if (psyc_parseDate(&value, &timmy))
|
|
|
|
put_number(sv, timmy);
|
2011-05-20 08:36:18 +00:00
|
|
|
else
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_DATE;
|
2011-05-20 08:36:18 +00:00
|
|
|
break;
|
|
|
|
case PSYC_TYPE_TIME: // number
|
2011-05-23 11:21:15 +00:00
|
|
|
if (psyc_parseTime(&value, &timmy))
|
|
|
|
put_number(sv, timmy);
|
2011-05-20 08:36:18 +00:00
|
|
|
else
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_TIME;
|
2011-05-20 08:36:18 +00:00
|
|
|
break;
|
|
|
|
case PSYC_TYPE_AMOUNT: // number
|
2011-05-23 11:11:32 +00:00
|
|
|
if (psyc_parseNumber(&value, &n))
|
|
|
|
put_number(sv, n);
|
2011-05-20 08:36:18 +00:00
|
|
|
else
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_AMOUNT;
|
2011-05-20 08:36:18 +00:00
|
|
|
break;
|
|
|
|
case PSYC_TYPE_DEGREE: // first digit
|
|
|
|
if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '9')
|
|
|
|
put_number(sv, value.ptr[0] - '0');
|
|
|
|
else
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_DEGREE;
|
2011-05-20 08:36:18 +00:00
|
|
|
break;
|
|
|
|
case PSYC_TYPE_FLAG: // 0 or 1
|
|
|
|
if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '1')
|
|
|
|
put_number(sv, value.ptr[0] - '0');
|
|
|
|
else
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_FLAG;
|
2011-05-20 08:36:18 +00:00
|
|
|
break;
|
|
|
|
case PSYC_TYPE_LIST: // array
|
|
|
|
size = 0;
|
|
|
|
if (value.length) {
|
|
|
|
psyc_initParseListState(&listState);
|
|
|
|
psyc_setParseListBuffer(&listState, value);
|
|
|
|
elem = (psycString){0, 0};
|
|
|
|
do {
|
|
|
|
retl = psyc_parseList(&listState, &elem);
|
|
|
|
switch (retl) {
|
|
|
|
case PSYC_PARSE_LIST_END:
|
|
|
|
retl = 0;
|
|
|
|
case PSYC_PARSE_LIST_ELEM:
|
|
|
|
if (size >= MAX_LIST_SIZE) {
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_LIST_TOO_LARGE;
|
|
|
|
break;
|
2011-05-20 08:36:18 +00:00
|
|
|
}
|
|
|
|
elems[size++] = elem;
|
|
|
|
break;
|
|
|
|
default:
|
2011-05-22 22:55:39 +00:00
|
|
|
error = PSYC_PARSE_ERROR_LIST;
|
2011-05-20 08:36:18 +00:00
|
|
|
}
|
2011-05-22 22:55:39 +00:00
|
|
|
} while (retl > 0 && !error);
|
2011-05-20 08:36:18 +00:00
|
|
|
}
|
2011-05-22 22:55:39 +00:00
|
|
|
if (error) break;
|
2011-05-20 08:36:18 +00:00
|
|
|
|
|
|
|
list = allocate_array(size);
|
|
|
|
for (i = 0; i < size; i++)
|
2011-05-22 22:55:39 +00:00
|
|
|
put_string(&list->item[i], new_n_tabled(elems[i].ptr,
|
|
|
|
elems[i].length));
|
2011-05-20 08:36:18 +00:00
|
|
|
|
|
|
|
put_array(sv, list);
|
|
|
|
break;
|
|
|
|
default: // string
|
|
|
|
if (ret == PSYC_PARSE_ENTITY)
|
|
|
|
// is it good to put entity variable values into the
|
|
|
|
// shared string table? probably yes.. but it's a guess
|
|
|
|
//t_string(sv, new_n_mstring(value.ptr, value.length));
|
|
|
|
put_string(sv, new_n_tabled(value.ptr, value.length));
|
|
|
|
else // PSYC_PARSE_ENTITY_END
|
|
|
|
put_string(sv, state->value);
|
|
|
|
}
|
2011-04-26 00:42:01 +00:00
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-10 12:10:30 +00:00
|
|
|
case PSYC_PARSE_BODY_START:
|
|
|
|
case PSYC_PARSE_BODY_CONT:
|
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_BODY_END:
|
2011-05-12 11:54:56 +00:00
|
|
|
put_string(&v->item[PACKET_METHOD], make_tabled(state->name));
|
|
|
|
put_string(&v->item[PACKET_BODY], state->value);
|
2011-05-11 15:09:22 +00:00
|
|
|
break;
|
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_BODY:
|
2011-04-26 20:00:45 +00:00
|
|
|
// new_n_tabled gets the shared string for the method
|
2011-05-12 11:54:56 +00:00
|
|
|
put_string(&v->item[PACKET_METHOD],
|
2011-05-09 19:33:45 +00:00
|
|
|
new_n_tabled(name.ptr, name.length));
|
2011-04-26 20:00:45 +00:00
|
|
|
|
|
|
|
// allocate an untabled string for the packet body
|
2011-05-12 11:54:56 +00:00
|
|
|
put_string(&v->item[PACKET_BODY],
|
2011-04-26 20:00:45 +00:00
|
|
|
new_n_mstring(value.ptr, value.length));
|
2011-04-25 20:59:53 +00:00
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_COMPLETE:
|
2011-05-19 19:27:20 +00:00
|
|
|
put_array(inter_sp, v);
|
2011-05-20 00:37:03 +00:00
|
|
|
sapply(psyc_dispatch_callback, current_object, 1);
|
2011-05-09 23:02:14 +00:00
|
|
|
state->packet = NULL;
|
2011-04-25 20:59:53 +00:00
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_INSUFFICIENT:
|
|
|
|
// insufficient data, save remaining bytes
|
|
|
|
state->remaining_len = psyc_getParseRemainingLength(state->parser);
|
|
|
|
if (state->remaining_len) {
|
|
|
|
state->remaining = pxalloc(state->remaining_len);
|
|
|
|
memcpy(state->remaining,
|
|
|
|
psyc_getParseRemainingBuffer(state->parser),
|
|
|
|
state->remaining_len);
|
|
|
|
} else
|
|
|
|
state->remaining = NULL;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
|
|
|
ret = 0;
|
2011-05-09 19:33:45 +00:00
|
|
|
break;
|
2011-05-11 15:09:22 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
default:
|
2011-05-22 22:55:39 +00:00
|
|
|
error = ret;
|
2011-04-25 20:59:53 +00:00
|
|
|
}
|
2011-05-09 19:33:45 +00:00
|
|
|
|
2011-05-11 15:09:22 +00:00
|
|
|
switch (ret) {
|
|
|
|
case PSYC_PARSE_BODY_END:
|
|
|
|
case PSYC_PARSE_ENTITY_END:
|
2011-05-22 22:55:39 +00:00
|
|
|
// reset tmp buffers in state when incomplete
|
|
|
|
// entity or body parsing is finished
|
2011-05-11 15:09:22 +00:00
|
|
|
state->oper = 0;
|
|
|
|
state->name = NULL;
|
|
|
|
state->value = NULL;
|
2011-05-09 19:33:45 +00:00
|
|
|
}
|
2011-05-22 22:55:39 +00:00
|
|
|
} while (ret && !error);
|
2011-04-25 20:59:53 +00:00
|
|
|
|
2011-05-11 15:09:22 +00:00
|
|
|
if (buffer)
|
|
|
|
pfree(buffer);
|
|
|
|
|
2011-05-22 22:55:39 +00:00
|
|
|
free_svalue(sp);
|
|
|
|
put_number(sp, error);
|
|
|
|
return sp;
|
2011-04-25 20:59:53 +00:00
|
|
|
} /* f_psyc_parse */
|
|
|
|
|
2011-05-24 14:29:03 +00:00
|
|
|
#endif /* HAS_PSYC */
|