2011-04-25 20:59:53 +00:00
|
|
|
/*------------------------------------------------------------------
|
|
|
|
* Glue for libpsyc.
|
|
|
|
*------------------------------------------------------------------
|
|
|
|
* test LPC code:
|
2011-04-26 08:02:17 +00:00
|
|
|
*
|
2011-04-25 20:59:53 +00:00
|
|
|
// doesn't work with (int *) yet
|
2011-04-26 08:02:17 +00:00
|
|
|
mixed* x = psyc_parse(":_context\ttest\n\n:_topic\ttesting\n_notice_test_libpsyc\nJust [_topic] libpsyc.\n|\n");
|
|
|
|
mixed y = psyc_render(x);
|
|
|
|
mixed z = ({ ([ "_context": "test" ]), ([ "_topic": "testing" ]), "_notice_test_libpsyc", "Just [_topic] libpsyc." });
|
|
|
|
z = psyc_render(z);
|
|
|
|
// psyc_render currently having some memory corruption problems
|
|
|
|
debug_message(sprintf("libpsyc returned %O, %O and %O (%s)\n", x, y, z,
|
|
|
|
y == z? "success": "FAIL!"));
|
|
|
|
*
|
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-04-25 20:59:53 +00:00
|
|
|
|
2011-04-26 08:02:17 +00:00
|
|
|
#ifdef USE_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-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-04-26 08:02:17 +00:00
|
|
|
mp_int i;
|
|
|
|
vector_t *v;
|
|
|
|
psycPacket packet;
|
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
|
|
|
|
|
|
|
// unless (sp->type == T_POINTER) return sp;
|
|
|
|
v = sp->u.vec;
|
2011-04-26 22:19:55 +00:00
|
|
|
if ((i = (mp_int)VEC_SIZE(v)) != 1+PSYC_BODY) {
|
2011-04-26 08:02:17 +00:00
|
|
|
errorf("Wrong number of elements (%"PRIdMPINT") in array argument to psyc_render()\n", i);
|
|
|
|
/* NOTREACHED */
|
|
|
|
return sp;
|
|
|
|
}
|
2011-04-27 10:26:37 +00:00
|
|
|
if (v->item[PSYC_ROUTING].type == T_MAPPING) {
|
|
|
|
map = v->item[PSYC_ROUTING].u.map;
|
|
|
|
} else {
|
|
|
|
map = NULL;
|
|
|
|
}
|
|
|
|
|
2011-04-26 22:19:55 +00:00
|
|
|
#if 0
|
2011-04-26 20:00:45 +00:00
|
|
|
if (v->item[PSYC_METHOD].type != T_STRING) {
|
|
|
|
errorf("Wrong type for PSYC_METHOD element in PSYC packet.\n");
|
2011-04-26 08:02:17 +00:00
|
|
|
/* NOTREACHED */
|
|
|
|
return sp;
|
|
|
|
}
|
2011-04-26 20:00:45 +00:00
|
|
|
if (v->item[PSYC_BODY].type != T_STRING) {
|
|
|
|
errorf("Wrong type for PSYC_BODY element in PSYC packet.\n");
|
2011-04-26 08:02:17 +00:00
|
|
|
/* NOTREACHED */
|
|
|
|
return sp;
|
|
|
|
}
|
2011-04-26 22:19:55 +00:00
|
|
|
#else
|
|
|
|
if (v->item[PSYC_METHOD].type == T_STRING) {
|
|
|
|
meth = get_txt(v->item[PSYC_METHOD].u.str);
|
|
|
|
mlen = mstrsize(v->item[PSYC_METHOD].u.str);
|
|
|
|
} else {
|
|
|
|
meth = NULL;
|
|
|
|
mlen = 0;
|
|
|
|
}
|
|
|
|
if (v->item[PSYC_BODY].type == T_STRING) {
|
|
|
|
body = get_txt(v->item[PSYC_BODY].u.str);
|
|
|
|
blen = mstrsize(v->item[PSYC_BODY].u.str);
|
|
|
|
} else {
|
|
|
|
body = NULL;
|
|
|
|
blen = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// TODO: handle _lists
|
2011-04-26 08:02:17 +00:00
|
|
|
// FIXME: handle mappings
|
|
|
|
packet = psyc_newPacket2(NULL, 0, NULL, 0,
|
2011-05-08 19:28:31 +00:00
|
|
|
meth, mlen, body, blen,
|
|
|
|
PSYC_PACKET_CHECK_LENGTH);
|
2011-04-26 08:02:17 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
printf("rendering... packet.length = %ld\n", packet.length);
|
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 */
|
|
|
|
|
|
|
|
/*-------------------------------------------------------------------------*/
|
|
|
|
// mixed psyc_parse(int* | string);
|
|
|
|
|
|
|
|
svalue_t *
|
|
|
|
f_psyc_parse (svalue_t *sp) {
|
2011-04-26 00:42:01 +00:00
|
|
|
string_t *str = NULL;
|
|
|
|
vector_t *v;
|
|
|
|
mapping_t *map;
|
2011-04-25 20:59:53 +00:00
|
|
|
mp_int i;
|
2011-05-08 14:58:35 +00:00
|
|
|
char oper = 0;
|
2011-05-09 19:33:45 +00:00
|
|
|
psycString name = {0,0}, value = {0,0}, elem;
|
2011-04-26 00:42:01 +00:00
|
|
|
psycParseListState listState;
|
2011-04-25 20:59:53 +00:00
|
|
|
int ret;
|
|
|
|
|
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-08 14:58:35 +00:00
|
|
|
if (!state) errorf("Out of memory for psyc state struct.\n");
|
|
|
|
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));
|
|
|
|
if (!state->parser) errorf("Out of memory for psyc parse state struct.\n");
|
|
|
|
psyc_initParseState(state->parser);
|
|
|
|
}
|
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
i = 0;
|
|
|
|
if (sp->type == T_POINTER) {
|
2011-05-08 14:58:35 +00:00
|
|
|
errorf("\npsyc_parse got %ld int* bytes... not supported yet\n", i);
|
2011-04-25 20:59:53 +00:00
|
|
|
}
|
|
|
|
else if (sp->type == T_STRING) {
|
2011-05-09 19:33:45 +00:00
|
|
|
printf("\npsyc_parse got a %ld bytes long string...\n", mstrsize(sp->u.str));
|
2011-05-10 15:17:41 +00:00
|
|
|
psyc_setParseBuffer2(state->parser, get_txt(sp->u.str), mstrsize(sp->u.str));
|
2011-04-25 20:59:53 +00:00
|
|
|
}
|
|
|
|
|
2011-05-08 14:58:35 +00:00
|
|
|
if (!state->packet) {
|
|
|
|
state->packet = allocate_array(4);
|
|
|
|
if (!state->packet) errorf("Out of memory for psyc_parse array.\n");
|
|
|
|
}
|
|
|
|
v = state->packet;
|
|
|
|
|
2011-04-26 00:42:01 +00:00
|
|
|
map = allocate_mapping( 0, 1 ); // empty mapping
|
|
|
|
if (!map) errorf("Out of memory for psyc_parse routing header.\n");
|
2011-04-26 08:02:17 +00:00
|
|
|
put_mapping(&v->item[PSYC_ROUTING], map);
|
2011-04-26 00:42:01 +00:00
|
|
|
map = allocate_mapping( 0, 1 ); // empty mapping
|
|
|
|
if (!map) errorf("Out of memory for psyc_parse entity header.\n");
|
2011-04-26 08:02:17 +00:00
|
|
|
put_mapping(&v->item[PSYC_ENTITY], map);
|
2011-04-26 00:42:01 +00:00
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
do {
|
2011-05-08 20:11:58 +00:00
|
|
|
svalue_t *sv;
|
2011-05-08 19:28:31 +00:00
|
|
|
ret = psyc_parse(state->parser, &oper, &name, &value);
|
2011-05-08 14:58:35 +00:00
|
|
|
|
2011-05-09 19:33:45 +00:00
|
|
|
if (state->remaining) {
|
|
|
|
pfree(state->remaining);
|
2011-05-09 23:02:14 +00:00
|
|
|
state->remaining = NULL;
|
2011-05-09 19:33:45 +00:00
|
|
|
state->remaining_len = 0;
|
|
|
|
}
|
|
|
|
|
2011-05-08 14:58:35 +00:00
|
|
|
switch (ret) {
|
|
|
|
case PSYC_PARSE_ENTITY_START: case PSYC_PARSE_BODY_START:
|
2011-05-09 19:33:45 +00:00
|
|
|
// save oper, name & value in state at the start of incomplete entity or body
|
|
|
|
state->oper = oper;
|
|
|
|
|
|
|
|
state->name_len = name.length;
|
|
|
|
state->name = pxalloc(name.length);
|
|
|
|
memcpy(state->name, name.ptr, name.length);
|
|
|
|
if (!state->name)
|
|
|
|
errorf("Out of memory for name.\n");
|
|
|
|
|
|
|
|
state->value_len = 0;
|
|
|
|
// allocate memory for the total length of the value
|
|
|
|
state->value = pxalloc(psyc_getParseValueLength(state->parser));
|
|
|
|
if (!state->value)
|
|
|
|
errorf("Out of memory for value.\n");
|
|
|
|
|
|
|
|
// 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
|
|
|
|
memcpy(state->value + state->value_len, value.ptr, value.length);
|
|
|
|
state->value_len += value.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
oper = state->oper;
|
|
|
|
name.ptr = state->name;
|
|
|
|
name.length = state->name_len;
|
|
|
|
value.ptr = state->value;
|
|
|
|
value.length = state->value_len;
|
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-04-26 00:42:01 +00:00
|
|
|
if (oper != ':') {
|
2011-05-09 19:33:45 +00:00
|
|
|
puts("_failure_unsupported_state");
|
|
|
|
continue;
|
2011-04-26 00:42:01 +00:00
|
|
|
}
|
2011-05-08 14:58:35 +00:00
|
|
|
sv = pxalloc(sizeof(svalue_t));
|
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-04-26 08:02:17 +00:00
|
|
|
sv = get_map_lvalue(v->item[PSYC_ROUTING].u.map, sv);
|
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-10 12:10:30 +00:00
|
|
|
case PSYC_PARSE_ENTITY_START:
|
|
|
|
case PSYC_PARSE_ENTITY_CONT:
|
|
|
|
break;
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_ENTITY_END:
|
|
|
|
case PSYC_PARSE_ENTITY:
|
|
|
|
if (oper != ':') {
|
|
|
|
puts("_failure_unsupported_state");
|
|
|
|
continue;
|
2011-04-26 00:42:01 +00:00
|
|
|
}
|
2011-05-09 19:33:45 +00:00
|
|
|
|
|
|
|
sv = pxalloc(sizeof(svalue_t));
|
|
|
|
put_string(sv, new_n_tabled(name.ptr, name.length));
|
|
|
|
sv = get_map_lvalue(v->item[PSYC_ENTITY].u.map, sv);
|
2011-05-08 14:58:35 +00:00
|
|
|
|
2011-04-26 20:00:45 +00:00
|
|
|
// 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));
|
2011-04-26 00:42:01 +00:00
|
|
|
|
2011-04-26 20:00:45 +00:00
|
|
|
// list parsing not supported yet.. TODO
|
2011-05-09 19:33:45 +00:00
|
|
|
if (psyc_isListVar(&name)) {
|
|
|
|
psyc_initParseListState(&listState);
|
|
|
|
psyc_setParseListBuffer(&listState, value);
|
|
|
|
elem = (psycString){0, 0};
|
|
|
|
while ((ret = psyc_parseList(&listState, &value, &elem))) {
|
|
|
|
switch (ret)
|
2011-04-25 20:59:53 +00:00
|
|
|
{
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_LIST_END:
|
|
|
|
case PSYC_PARSE_LIST_ELEM:
|
|
|
|
// TODO: store elem
|
|
|
|
//write(1, elem.ptr, elem.length);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errorf("Error while parsing PSYC list: %i\n", ret);
|
|
|
|
/* NOTREACHED */
|
|
|
|
return sp;
|
2011-04-25 20:59:53 +00:00
|
|
|
}
|
2011-05-09 19:33:45 +00:00
|
|
|
|
|
|
|
if (ret == PSYC_PARSE_LIST_END)
|
|
|
|
break;
|
|
|
|
}
|
2011-04-25 20:59:53 +00:00
|
|
|
}
|
2011-04-26 00:42:01 +00:00
|
|
|
break;
|
2011-05-10 12:10:30 +00:00
|
|
|
case PSYC_PARSE_BODY_START:
|
|
|
|
case PSYC_PARSE_BODY_CONT:
|
|
|
|
break;
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_BODY_END:
|
|
|
|
case PSYC_PARSE_BODY:
|
2011-04-26 00:42:01 +00:00
|
|
|
if (str) errorf("Got two PSYC methods in the same packet!?\n");
|
2011-04-26 20:00:45 +00:00
|
|
|
// new_n_tabled gets the shared string for the method
|
|
|
|
put_string(&v->item[PSYC_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
|
|
|
|
put_string(&v->item[PSYC_BODY],
|
|
|
|
new_n_mstring(value.ptr, value.length));
|
2011-04-26 00:42:01 +00:00
|
|
|
|
2011-04-25 20:59:53 +00:00
|
|
|
break;
|
2011-05-09 19:33:45 +00:00
|
|
|
case PSYC_PARSE_COMPLETE:
|
2011-05-09 23:02:14 +00:00
|
|
|
state->packet = NULL;
|
2011-04-25 20:59:53 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
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;
|
|
|
|
//TODO: psyc_setRemainingBuffer2(state->parser, state->remaining, state->remaining_len);
|
|
|
|
break;
|
|
|
|
default:
|
2011-04-25 20:59:53 +00:00
|
|
|
errorf("Error while parsing PSYC: %i\n", ret);
|
|
|
|
/* NOTREACHED */
|
|
|
|
return sp;
|
|
|
|
}
|
2011-05-09 19:33:45 +00:00
|
|
|
|
|
|
|
// free tmp buffers in state when incomplete entity or body parsing is done
|
|
|
|
if (ret == PSYC_PARSE_ENTITY_END || ret == PSYC_PARSE_BODY_END) {
|
|
|
|
oper = 0;
|
|
|
|
|
|
|
|
if (state->name)
|
|
|
|
pfree(state->name);
|
|
|
|
state->name = NULL;
|
|
|
|
state->name_len = 0;
|
|
|
|
|
|
|
|
if (value.ptr)
|
|
|
|
pfree((void*)value.ptr);
|
|
|
|
state->value = NULL;
|
|
|
|
state->value_len = 0;
|
|
|
|
}
|
2011-04-25 20:59:53 +00:00
|
|
|
} while (ret);
|
|
|
|
|
|
|
|
free_svalue(sp);
|
2011-04-26 00:42:01 +00:00
|
|
|
put_array(sp, v);
|
2011-05-08 14:58:35 +00:00
|
|
|
state->packet = 0;
|
2011-04-25 20:59:53 +00:00
|
|
|
return sp;
|
|
|
|
|
|
|
|
} /* f_psyc_parse */
|
|
|
|
|
|
|
|
#endif /* USE_PSYC */
|