pkg-psyc: psyc_parse now returns int error code, psyc_render can convert more types to_string

This commit is contained in:
Gabor Adam Toth 2011-05-23 00:55:39 +02:00
parent f38eecb344
commit f33e0048f0
3 changed files with 221 additions and 121 deletions

View File

@ -604,7 +604,7 @@ int send_erq(int, int*|string, null|closure default: F_CONST0);
#endif #endif
#ifdef USE_PSYC #ifdef USE_PSYC
void psyc_parse(int* | string); int psyc_parse(int* | string);
string psyc_render(mixed*); string psyc_render(mixed*);
#endif /* USE_PSYC */ #endif /* USE_PSYC */

View File

@ -4,35 +4,46 @@
* test LPC code: * test LPC code:
* *
#define CHECK_PARSE_RET if (ret != 0) raise_error(sprintf("FAIL: psyc_parse returned %d\n", ret))
string s, s2; string s, s2;
create() { create() {
mixed p, r; mixed p, r;
int ret;
s = "=_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; s = "=_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
psyc_parse(s+s+s); ret = psyc_parse(s+s+s); CHECK_PARSE_RET;
psyc_parse("=_context\ttest\n\n:_topic\ttest"); ret = psyc_parse("=_context\ttest\n\n:_topic\ttest"); CHECK_PARSE_RET;
psyc_parse("ing\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"); ret = psyc_parse("ing\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"); CHECK_PARSE_RET;
p = ({ ([ "_context": "test"; '=' ]), ([ "_topic": "testing" ]), p = ({ ([ "_context": "test"; '=' ]), ([ "_topic": "testing" ]),
"_notice_test_libpsyc", "Just [_topic] libpsyc." }); "_notice_test_libpsyc", "Just [_topic] libpsyc." });
r = psyc_render(p); r = psyc_render(p);
debug_message(sprintf(">> psyc_render returned:\n%s\n", r)); debug_message(sprintf(">> psyc_render returned:\n%s\n", r));
if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s)); if (r != s) raise_error(sprintf(">> FAIL, expected:\n%s\n", s));
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));
s = "=_context\ttest\n\n:_time_foo\t59\n:_time_bar\t-41\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; 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"; s2 = "=_context\ttest\n\n:_time_bar\t-41\n:_time_foo\t59\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
psyc_parse(s); ret = psyc_parse(s); CHECK_PARSE_RET;
s = "=_context\ttest\n\n:_date_foo\t59\n:_date_bar\t-41\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; 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"; s2 = "=_context\ttest\n\n:_date_bar\t-41\n:_date_foo\t59\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
psyc_parse(s); ret = psyc_parse(s); CHECK_PARSE_RET;
s = "=_context\ttest\n\n:_list_foo\t|foo|bar|baz\n:_list_bar\t\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n"; 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"; s2 = "=_context\ttest\n\n:_list_bar\t\n:_list_foo\t|foo|bar|baz\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n";
psyc_parse(s); ret = psyc_parse(s); CHECK_PARSE_RET;
p = ({ ([ "_context": "test"; '=' ]), p = ({ ([ "_context": "test"; '=' ]),
([ "_list_foo": ({ "foo", "bar", "baz" }), "_list_bar": ({}) ]), ([ "_list_foo": ({ "foo", "bar", "baz" }), "_list_bar": ({}) ]),
@ -63,6 +74,7 @@ psyc_dispatch(mixed p) {
#include "pkg-psyc.h" #include "pkg-psyc.h"
#include "simulate.h" #include "simulate.h"
#include "xalloc.h" #include "xalloc.h"
#include "efuns.h"
#ifdef USE_PSYC #ifdef USE_PSYC
@ -79,13 +91,19 @@ psyc_dispatch(mixed p) {
void void
fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) { fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
psyc_modifier_t *m = extra; psyc_modifier_t *m = extra;
char oper; char oper = 0;
char *name, *value, buf[32]; char *name, *value;
size_t namelen, valuelen, i; size_t namelen, valuelen, i;
uint8_t type; uint8_t type;
svalue_t vsp, *lval;
if (key->type != T_STRING) psycList list;
psycString *elems = NULL;
if (key->type != T_STRING) {
errorf("fill_header_from_mapping: key type %d not supported\n", key->type); errorf("fill_header_from_mapping: key type %d not supported\n", key->type);
return; // not reached
}
name = get_txt(key->u.str); name = get_txt(key->u.str);
namelen = mstrsize(key->u.str); namelen = mstrsize(key->u.str);
@ -93,45 +111,86 @@ fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
if (m->num_values > 1) if (m->num_values > 1)
oper = val[1].u.number; oper = val[1].u.number;
else if (!oper)
oper = C_GLYPH_OPERATOR_SET; oper = C_GLYPH_OPERATOR_SET;
if (val->type == T_STRING) { switch (val->type) {
value = get_txt(val->u.str); case T_STRING:
valuelen = mstrsize(val->u.str); value = get_txt(val->u.str);
} else if (val->type == T_NUMBER) { valuelen = mstrsize(val->u.str);
if (type == PSYC_TYPE_DATE) break;
snprintf(buf, 32, "%ld", val->u.number - PSYC_EPOCH);
else
snprintf(buf, 32, "%ld", val->u.number);
valuelen = strlen(buf);
value = pxalloc(valuelen);
if (!value) errorf("Out of memory in fill_header_from_mapping for number\n");
memcpy(value, buf, valuelen);
} else if (val->type == T_POINTER) {
psycList list;
psycString *elems = NULL;
if (VEC_SIZE(val->u.vec)) { case T_NUMBER:
elems = pxalloc(sizeof(psycString) * VEC_SIZE(val->u.vec)); case T_OBJECT:
if (!elems) errorf("Out of memory in fill_header_from_mapping for elems\n"); vsp.type = val->type;
switch (val->type) {
for (i = 0; i < VEC_SIZE(val->u.vec); i++) { case T_NUMBER:
if (val->u.vec->item[i].type == T_STRING) if (type == PSYC_TYPE_DATE)
elems[i] = (psycString){mstrsize(val->u.vec->item[i].u.str), get_txt(val->u.vec->item[i].u.str)}; vsp.u.number = val->u.number - PSYC_EPOCH;
else else
errorf("fill_header_from_mapping: list value type %d not supported\n", key->type); vsp.u.number = val->u.number;
break;
case T_OBJECT:
vsp.u.ob = val->u.ob;
break;
} }
}
list = psyc_newList(elems, VEC_SIZE(val->u.vec), PSYC_LIST_CHECK_LENGTH); f_to_string(&vsp);
valuelen = list.length; value = get_txt(vsp.u.str);
value = pxalloc(valuelen); valuelen = strlen(value);
if (!value) errorf("Out of memory in fill_header_from_mapping for list value\n"); break;
psyc_renderList(&list, value, valuelen); case T_POINTER:
} else if (VEC_SIZE(val->u.vec)) {
errorf("fill_header_from_mapping: value type %d not supported\n", key->type); 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
}
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);
elems[i] = (psycString){strlen(get_txt(vsp.u.str)), get_txt(vsp.u.str)};
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
}
m->header->modifiers[m->header->lines++] = m->header->modifiers[m->header->lines++] =
psyc_newModifier2(oper, name, namelen, value, valuelen, m->flag); psyc_newModifier2(oper, name, namelen, value, valuelen, m->flag);
@ -143,7 +202,7 @@ fill_header_from_mapping (svalue_t *key, svalue_t *val, void *extra) {
svalue_t * svalue_t *
f_psyc_render(svalue_t *sp) { f_psyc_render(svalue_t *sp) {
mp_int i; uint8_t i;
vector_t *v; vector_t *v;
string_t *out; string_t *out;
char *meth, *body; char *meth, *body;
@ -155,41 +214,34 @@ f_psyc_render(svalue_t *sp) {
// unless (sp->type == T_POINTER) return sp; // unless (sp->type == T_POINTER) return sp;
v = sp->u.vec; v = sp->u.vec;
if ((i = (mp_int)VEC_SIZE(v)) != 1+PACKET_BODY) { if (VEC_SIZE(v) == PACKET_BODY + 1) {
errorf("Wrong number of elements (%"PRIdMPINT") in array argument to psyc_render()\n", i); for (i = PACKET_ROUTING; i <= PACKET_ENTITY; i++) {
/* NOTREACHED */ if (v->item[i].type == T_MAPPING) {
return sp; map = v->item[i].u.map;
} if (!MAP_SIZE(map)) continue;
for (i = PACKET_ROUTING; i <= PACKET_ENTITY; i++) {
if (v->item[i].type == T_MAPPING) { headers[i].lines = 0;
map = v->item[i].u.map; headers[i].modifiers = malloc(sizeof(psycModifier) * MAP_SIZE(v->item[i].u.map));
headers[i].lines = 0; if (!headers[i].modifiers) {
headers[i].modifiers = malloc(sizeof(psycModifier) * MAP_SIZE(map)); errorf("Out of memory in psyc_render for entity header.\n");
if (!headers[i].modifiers) errorf("Out of memory in psyc_render for header.\n"); return sp; // not reached
}
if (i == PACKET_ROUTING)
walk_mapping(map, &fill_header_from_mapping, walk_mapping(map, &fill_header_from_mapping,
&(psyc_modifier_t) {&headers[i], map->num_values, &(psyc_modifier_t) {
PSYC_MODIFIER_ROUTING}); &headers[i], map->num_values,
else i == PACKET_ROUTING ?
walk_mapping(map, &fill_header_from_mapping, PSYC_MODIFIER_ROUTING :
&(psyc_modifier_t) {&headers[i], map->num_values, PSYC_MODIFIER_CHECK_LENGTH
PSYC_MODIFIER_CHECK_LENGTH}); });
}
} }
} else {
errorf("Wrong number of elements (%" PRIdMPINT ") "
"in array argument to psyc_render()\n", VEC_SIZE(v));
return sp; // not reached
} }
#if 0
if (v->item[PACKET_METHOD].type != T_STRING) {
errorf("Wrong type for PACKET_METHOD element in PSYC packet.\n");
/* NOTREACHED */
return sp;
}
if (v->item[PACKET_BODY].type != T_STRING) {
errorf("Wrong type for PACKET_BODY element in PSYC packet.\n");
/* NOTREACHED */
return sp;
}
#else
if (v->item[PACKET_METHOD].type == T_STRING) { if (v->item[PACKET_METHOD].type == T_STRING) {
meth = get_txt(v->item[PACKET_METHOD].u.str); meth = get_txt(v->item[PACKET_METHOD].u.str);
mlen = mstrsize(v->item[PACKET_METHOD].u.str); mlen = mstrsize(v->item[PACKET_METHOD].u.str);
@ -197,6 +249,7 @@ f_psyc_render(svalue_t *sp) {
meth = NULL; meth = NULL;
mlen = 0; mlen = 0;
} }
if (v->item[PACKET_BODY].type == T_STRING) { if (v->item[PACKET_BODY].type == T_STRING) {
body = get_txt(v->item[PACKET_BODY].u.str); body = get_txt(v->item[PACKET_BODY].u.str);
blen = mstrsize(v->item[PACKET_BODY].u.str); blen = mstrsize(v->item[PACKET_BODY].u.str);
@ -204,14 +257,17 @@ f_psyc_render(svalue_t *sp) {
body = NULL; body = NULL;
blen = 0; blen = 0;
} }
#endif
// TODO: handle _lists
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);
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
printf("rendering... packet.length = %ld\n", packet.length); printf("rendering... packet.length = %ld\n", packet.length);
#endif
// alloc_mstring creates an *untabled* string suitable for tmp data // alloc_mstring creates an *untabled* string suitable for tmp data
memsafe(out = alloc_mstring(packet.length), packet.length, "f_psyc_render"); memsafe(out = alloc_mstring(packet.length), packet.length, "f_psyc_render");
psyc_render(&packet, get_txt(out), packet.length); psyc_render(&packet, get_txt(out), packet.length);
@ -224,9 +280,10 @@ f_psyc_render(svalue_t *sp) {
} /* f_psyc_render */ } /* f_psyc_render */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
// void psyc_parse(int* | string); // int psyc_parse(int* | string);
static string_t *psyc_dispatch_callback = NULL; static string_t *psyc_dispatch_callback = NULL;
static string_t *psyc_error_callback = NULL;
svalue_t * svalue_t *
f_psyc_parse (svalue_t *sp) { f_psyc_parse (svalue_t *sp) {
@ -237,82 +294,116 @@ f_psyc_parse (svalue_t *sp) {
char oper = 0; char oper = 0;
psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem; psycString name = {0,0}, value = {0,0}, elems[MAX_LIST_SIZE], elem;
psycParseListState listState; psycParseListState listState;
int ret, retl, type = -1; int ret, retl, type = -1, error = 0;
size_t size, i; size_t size, i;
time_t t; time_t t;
if (!psyc_dispatch_callback) if (!psyc_dispatch_callback)
psyc_dispatch_callback = new_tabled("psyc_dispatch"); psyc_dispatch_callback = new_tabled("psyc_dispatch");
if (!psyc_error_callback)
psyc_error_callback = new_tabled("psyc_error");
assert_shadow_sent(current_object); assert_shadow_sent(current_object);
psyc_state_t *state = O_GET_PSYC_STATE(current_object); psyc_state_t *state = O_GET_PSYC_STATE(current_object);
if (!state) { if (!state) {
state = pxalloc(sizeof(psyc_state_t)); state = pxalloc(sizeof(psyc_state_t));
if (!state) errorf("Out of memory for psyc state struct.\n"); if (!state) {
errorf("Out of memory for psyc state struct.\n");
return sp; // not reached
}
O_GET_PSYC_STATE(current_object) = state; O_GET_PSYC_STATE(current_object) = state;
memset(state, 0, sizeof(psyc_state_t)); memset(state, 0, sizeof(psyc_state_t));
state->parser = pxalloc(sizeof(psycParseState)); state->parser = pxalloc(sizeof(psycParseState));
if (!state->parser) errorf("Out of memory for psyc parse state struct.\n"); if (!state->parser) {
errorf("Out of memory for psyc parse state struct.\n");
return sp; // not reached
}
psyc_initParseState(state->parser); psyc_initParseState(state->parser);
} }
v = state->packet; v = state->packet;
if (sp->type == T_POINTER) { if (sp->type == T_POINTER) {
errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", VEC_SIZE(sp->u.vec)); errorf("\npsyc_parse got %ld int* bytes... not supported yet\n",
VEC_SIZE(sp->u.vec));
return sp; // not reached
} else if (sp->type == T_STRING) { } else if (sp->type == T_STRING) {
#ifdef DEBUG
printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str)); printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
#endif
if (state->remaining) { if (state->remaining) {
// there are remaining bytes from the previous call to psyc_parse, // there are remaining bytes from the previous call to psyc_parse,
// copy them together with the newly arrived data // copy them together with the newly arrived data
buffer = pxalloc(state->remaining_len + mstrsize(sp->u.str)); buffer = pxalloc(state->remaining_len + mstrsize(sp->u.str));
if (!buffer) errorf("Out of memory for psyc_parse buffer.\n"); if (!buffer) {
errorf("Out of memory for psyc_parse buffer.\n");
return sp; // not reached
}
memcpy(buffer, state->remaining, state->remaining_len); memcpy(buffer, state->remaining, state->remaining_len);
memcpy(buffer + state->remaining_len, get_txt(sp->u.str), mstrsize(sp->u.str)); memcpy(buffer + state->remaining_len, get_txt(sp->u.str),
psyc_setParseBuffer2(state->parser, buffer, state->remaining_len + mstrsize(sp->u.str)); mstrsize(sp->u.str));
psyc_setParseBuffer2(state->parser, buffer,
state->remaining_len + mstrsize(sp->u.str));
pfree(state->remaining); pfree(state->remaining);
state->remaining = NULL; state->remaining = NULL;
state->remaining_len = 0; state->remaining_len = 0;
} else { } else {
psyc_setParseBuffer2(state->parser, get_txt(sp->u.str), mstrsize(sp->u.str)); psyc_setParseBuffer2(state->parser, get_txt(sp->u.str),
mstrsize(sp->u.str));
} }
} else { } else {
errorf("\npsyc_parse got type %d, not supported\n", sp->type); errorf("\npsyc_parse got type %d, not supported\n", sp->type);
return sp; // not reached
} }
do { do {
ret = psyc_parse(state->parser, &oper, &name, &value); ret = psyc_parse(state->parser, &oper, &name, &value);
#ifdef DEBUG
printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ', (int)name.length, name.ptr, (int)value.length, value.ptr); printf("#%2d %c%.*s = %.*s\n", ret, oper ? oper : ' ',
(int)name.length, name.ptr, (int)value.length, value.ptr);
#endif
if (!state->packet) { if (!state->packet) {
state->packet = allocate_array(4); state->packet = allocate_array(4);
if (!state->packet) errorf("Out of memory for psyc_parse array.\n"); if (!state->packet) {
errorf("Out of memory for psyc_parse array.\n");
return sp; // not reached
}
v = state->packet; v = state->packet;
map = allocate_mapping(0, 2); // empty mapping map = allocate_mapping(0, 2); // empty mapping
if (!map) errorf("Out of memory for psyc_parse routing header.\n"); if (!map) {
errorf("Out of memory for psyc_parse routing header.\n");
return sp; // not reached
}
put_mapping(&v->item[PACKET_ROUTING], map); put_mapping(&v->item[PACKET_ROUTING], map);
map = allocate_mapping(0, 2); // empty mapping map = allocate_mapping(0, 2); // empty mapping
if (!map) errorf("Out of memory for psyc_parse entity header.\n"); if (!map) {
errorf("Out of memory for psyc_parse entity header.\n");
return sp; // not reached
}
put_mapping(&v->item[PACKET_ENTITY], map); put_mapping(&v->item[PACKET_ENTITY], map);
} }
switch (ret) { switch (ret) {
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START: case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
// save oper, name & value in state at the start of incomplete entity or body // save oper, name & value in state at the start of
// incomplete entity or body
state->oper = oper; state->oper = oper;
state->name = mstring_alloc_string(name.length); state->name = mstring_alloc_string(name.length);
memcpy(get_txt(state->name), name.ptr, name.length); memcpy(get_txt(state->name), name.ptr, name.length);
if (!state->name) if (!state->name) {
errorf("Out of memory for name.\n"); errorf("Out of memory for name.\n");
return sp; // not reached
}
// allocate memory for the total length of the value // allocate memory for the total length of the value
state->value_len = 0; state->value_len = 0;
state->value = mstring_alloc_string(psyc_getParseValueLength(state->parser)); state->value = mstring_alloc_string(psyc_getParseValueLength(state->parser));
if (!state->value) if (!state->value) {
errorf("Out of memory for value.\n"); errorf("Out of memory for value.\n");
return sp; // not reached
}
// fall thru // fall thru
case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT: case PSYC_PARSE_ENTITY_CONT: case PSYC_PARSE_BODY_CONT:
@ -323,7 +414,8 @@ f_psyc_parse (svalue_t *sp) {
} }
if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) { if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
// incomplete entity or body parsing done, set oper/name/value to the ones saved in state // incomplete entity or body parsing done,
// set oper/name/value to the ones saved in state
oper = state->oper; oper = state->oper;
name.ptr = get_txt(state->name); name.ptr = get_txt(state->name);
name.length = mstrsize(state->name); name.length = mstrsize(state->name);
@ -363,36 +455,37 @@ f_psyc_parse (svalue_t *sp) {
put_number(&sv[1], oper); put_number(&sv[1], oper);
type = psyc_getVarType(&name); type = psyc_getVarType(&name);
switch (type) { switch (type) {
case PSYC_TYPE_DATE: // number + PSYC_EPOCH case PSYC_TYPE_DATE: // number + PSYC_EPOCH
if (psyc_parseDate(&value, &t)) if (psyc_parseDate(&value, &t))
put_number(sv, t); put_number(sv, t);
else else
errorf("Error while parsing _date value\n"); // TODO: _error_invalid_value? error = PSYC_PARSE_ERROR_DATE;
break; break;
case PSYC_TYPE_TIME: // number case PSYC_TYPE_TIME: // number
if (psyc_parseTime(&value, &t)) if (psyc_parseTime(&value, &t))
put_number(sv, t); put_number(sv, t);
else else
errorf("Error while parsing _time value\n"); error = PSYC_PARSE_ERROR_TIME;
break; break;
case PSYC_TYPE_AMOUNT: // number case PSYC_TYPE_AMOUNT: // number
if (psyc_parseNumber(&value, &t)) if (psyc_parseNumber(&value, &t))
put_number(sv, t); put_number(sv, t);
else else
errorf("Error while parsing _amount value\n"); error = PSYC_PARSE_ERROR_AMOUNT;
break; break;
case PSYC_TYPE_DEGREE: // first digit case PSYC_TYPE_DEGREE: // first digit
if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '9') if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '9')
put_number(sv, value.ptr[0] - '0'); put_number(sv, value.ptr[0] - '0');
else else
errorf("Error while parsing _degree value\n"); error = PSYC_PARSE_ERROR_DEGREE;
break; break;
case PSYC_TYPE_FLAG: // 0 or 1 case PSYC_TYPE_FLAG: // 0 or 1
if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '1') if (value.length && value.ptr[0] >= '0' && value.ptr[0] <= '1')
put_number(sv, value.ptr[0] - '0'); put_number(sv, value.ptr[0] - '0');
else else
errorf("Error while parsing _flag value\n"); error = PSYC_PARSE_ERROR_FLAG;
break; break;
case PSYC_TYPE_LIST: // array case PSYC_TYPE_LIST: // array
size = 0; size = 0;
@ -407,23 +500,22 @@ f_psyc_parse (svalue_t *sp) {
retl = 0; retl = 0;
case PSYC_PARSE_LIST_ELEM: case PSYC_PARSE_LIST_ELEM:
if (size >= MAX_LIST_SIZE) { if (size >= MAX_LIST_SIZE) {
errorf("Error while parsing PSYC list: max list size reached\n"); error = PSYC_PARSE_ERROR_LIST_TOO_LARGE;
/* NOTREACHED */ break;
return sp;
} }
elems[size++] = elem; elems[size++] = elem;
break; break;
default: default:
errorf("Error while parsing PSYC list: %i\n", retl); error = PSYC_PARSE_ERROR_LIST;
/* NOTREACHED */
return sp;
} }
} while (retl > 0); } while (retl > 0 && !error);
} }
if (error) break;
list = allocate_array(size); list = allocate_array(size);
for (i = 0; i < size; i++) for (i = 0; i < size; i++)
put_string(&list->item[i], new_n_tabled(elems[i].ptr, elems[i].length)); put_string(&list->item[i], new_n_tabled(elems[i].ptr,
elems[i].length));
put_array(sv, list); put_array(sv, list);
break; break;
@ -478,26 +570,26 @@ f_psyc_parse (svalue_t *sp) {
break; break;
default: default:
errorf("Error while parsing PSYC: %i\n", ret); error = ret;
/* NOTREACHED */
return sp;
} }
switch (ret) { switch (ret) {
case PSYC_PARSE_BODY_END: case PSYC_PARSE_BODY_END:
case PSYC_PARSE_ENTITY_END: case PSYC_PARSE_ENTITY_END:
// reset tmp buffers in state when incomplete entity or body parsing is done // reset tmp buffers in state when incomplete
// entity or body parsing is finished
state->oper = 0; state->oper = 0;
state->name = NULL; state->name = NULL;
state->value = NULL; state->value = NULL;
} }
} while (ret); } while (ret && !error);
if (buffer) if (buffer)
pfree(buffer); pfree(buffer);
free_svalue(sp); // f_remove_interactive does it the same way... free_svalue(sp);
return --sp; put_number(sp, error);
return sp;
} /* f_psyc_parse */ } /* f_psyc_parse */
#endif /* USE_PSYC */ #endif /* USE_PSYC */

View File

@ -19,6 +19,14 @@
# define MAX_LIST_SIZE 1024 # define MAX_LIST_SIZE 1024
# define PSYC_PARSE_ERROR_AMOUNT 1
# define PSYC_PARSE_ERROR_DEGREE 2
# define PSYC_PARSE_ERROR_DATE 3
# define PSYC_PARSE_ERROR_TIME 4
# define PSYC_PARSE_ERROR_FLAG 5
# define PSYC_PARSE_ERROR_LIST 6
# define PSYC_PARSE_ERROR_LIST_TOO_LARGE 7
typedef struct psyc_state_s { typedef struct psyc_state_s {
psycParseState *parser; psycParseState *parser;
vector_t *packet; vector_t *packet;