spyc: use libpsyc for parsing & rendering

This commit is contained in:
Gabor Adam Toth 2011-05-23 01:33:12 +02:00
parent a21b0024ef
commit ffabd7af08
12 changed files with 343 additions and 242 deletions

View File

@ -1,9 +1,18 @@
#ifndef LPC_LIBPSYC_H #ifndef LPC_LIBPSYC_H
#define LPC_LIBPSYC_H 1 # define LPC_LIBPSYC_H 1
#define PACKET_ROUTING 0 // 2-dimensional mapping of routing modifiers # define PACKET_ROUTING 0 // 2-dimensional mapping of routing modifiers
#define PACKET_ENTITY 1 // 2-dimensional mapping of entity modifiers # define PACKET_ENTITY 1 // 2-dimensional mapping of entity modifiers
#define PACKET_METHOD 2 // PSYC method string # define PACKET_METHOD 2 // PSYC method string
#define PACKET_BODY 3 // packet body.. possibly binary data # define PACKET_BODY 3 // packet body.. possibly binary data
// error codes returned by psyc_parse
# 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
#endif #endif

View File

@ -15,6 +15,8 @@
#else #else
# define C_GLYPH_PACKET_DELIMITER '.' # define C_GLYPH_PACKET_DELIMITER '.'
# define S_GLYPH_PACKET_DELIMITER "." # define S_GLYPH_PACKET_DELIMITER "."
# define C_GLYPH_NEW_PACKET_DELIMITER '|'
# define S_GLYPH_NEW_PACKET_DELIMITER "|"
#endif #endif
#define C_GLYPH_SEPARATOR_KEYWORD '_' #define C_GLYPH_SEPARATOR_KEYWORD '_'

View File

@ -1113,6 +1113,19 @@ protected int deliver(mixed ip, string host, string mc, string buffer, mapping c
return 1; return 1;
} }
void peek(string data) {
P4((">> peek: %O\n", data));
#ifdef USE_SPYC
if (data[0] == C_GLYPH_NEW_PACKET_DELIMITER) {
# if __EFUN_DEFINED__(enable_binary)
enable_binary(ME);
# else
raise_error("Driver compiled without enable_binary()");
# endif
}
#endif
}
#ifdef PSYC_TCP #ifdef PSYC_TCP
vamixed startParse(string a) { vamixed startParse(string a) {
if (a == ".") { // old S_GLYPH_PACKET_DELIMITER if (a == ".") { // old S_GLYPH_PACKET_DELIMITER
@ -1121,7 +1134,7 @@ vamixed startParse(string a) {
} }
// new syntax is so broken, we should not pretend to support it yet FIXME // new syntax is so broken, we should not pretend to support it yet FIXME
# if defined(SPYC_PATH) && defined(USE_SPYC) # if defined(SPYC_PATH) && defined(USE_SPYC)
else if (a == "|") { // new S_GLYPH_PACKET_DELIMITER else if (a[0] == C_GLYPH_NEW_PACKET_DELIMITER) {
object o = clone_object(SPYC_PATH "server"); object o = clone_object(SPYC_PATH "server");
unless (o && exec(o, ME) && o->logon(0)) { unless (o && exec(o, ME) && o->logon(0)) {
croak("_failure_object_creation_server", croak("_failure_object_creation_server",
@ -1129,7 +1142,7 @@ vamixed startParse(string a) {
QUIT QUIT
} }
// if (isServer()) o->greet(); // if (isServer()) o->greet();
o->feed("|\n"); o->feed(a);
return 1; return 1;
} }
# endif # endif

View File

@ -26,6 +26,7 @@ static int build_header(string key, mixed val, mapping vars) {
key, routeMe, routeMe & PSYC_ROUTING_RENDER)) key, routeMe, routeMe & PSYC_ROUTING_RENDER))
if ((routeMe &&! (routeMe & PSYC_ROUTING_RENDER)) if ((routeMe &&! (routeMe & PSYC_ROUTING_RENDER))
|| abbrev("_INTERNAL", key)) return -1; || abbrev("_INTERNAL", key)) return -1;
P2(("build_header(%O, %O) into %s vars\n", key, val, P2(("build_header(%O, %O) into %s vars\n", key, val,
routeMe ? "routing" : "entity")) routeMe ? "routing" : "entity"))
if (key[0] == '_') key = ":"+key; if (key[0] == '_') key = ":"+key;
@ -143,7 +144,9 @@ static varargs string render_psyc(mixed source, string mc, mixed data,
// vaobject obj, vastring target, vaint hascontext) // vaobject obj, vastring target, vaint hascontext)
P4(("%O render_psyc %O for %O\n", ME, vars, previous_object())) P4(("%O render_psyc %O for %O\n", ME, vars, previous_object()))
string t, context; string t, context;
mapping rvars = ([ ]);
int needLen = 0; int needLen = 0;
mixed key, val;
#ifndef NEW_LINE #ifndef NEW_LINE
int excessiveNewline = 0; int excessiveNewline = 0;
#endif #endif
@ -247,41 +250,63 @@ static varargs string render_psyc(mixed source, string mc, mixed data,
context = vars["_context"]; context = vars["_context"];
# endif # endif
if (context) { if (context) {
rbuf += "\n:_context\t"+ UNIFORM(context); rvars["_context"] = UNIFORM(context);
t = source || vars["_source_relay"]; t = source || vars["_source_relay"];
if (t) rbuf += "\n:_source_relay\t"+ UNIFORM(t); if (t) rvars["_source_relay"] = UNIFORM(t);
// resend of /history transmitted according to spec: // resend of /history transmitted according to spec:
if (showingLog && target) rbuf += "\n:_target\t"+ target; if (showingLog && target) rvars["_target"] = target;
// usually the same as context or a different channel of // usually the same as context or a different channel of
// context or the actual recipient of a multicast // context or the actual recipient of a multicast
// ... not interesting in any case // ... not interesting in any case
//else if (target) rbuf += "\n:_target_relay\t"+ target; //else if (target) rbuf += "\n:_target_relay\t"+ target;
} else { } else {
if (source) rbuf += "\n:_source\t"+ UNIFORM(source); if (source) rvars["_source"] = UNIFORM(source);
if (target) rbuf += "\n:_target\t"+ target; if (target) rvars["_target"] = target;
// this is necessary for message forwarding ( /set id ) // this is necessary for message forwarding ( /set id )
if (t = vars["_source_relay"]) if (t = vars["_source_relay"])
rbuf += "\n:_source_relay\t"+ UNIFORM(t); rvars["_source_relay"] = UNIFORM(t);
} }
#endif /* NEW_RENDER */ #endif /* NEW_RENDER */
if (mappingp(vars)) { #ifdef LIBPSYC
int routeMe = 0;
mapping evars = ([ ]);
if (mappingp(vars))
mapeach (key, val, vars) {
routeMe = isRouting[key];
if ((routeMe &&! (routeMe & PSYC_ROUTING_RENDER))
|| abbrev("_INTERNAL", key))
continue;
if (routeMe)
rvars[key] = val;
else
evars[key] = val;
}
return psyc_render(({ rvars, evars, mc, data }));
#endif
if (mappingp(vars))
vars = vars + rvars;
else
vars = rvars;
#if 0 //ndef EXPERIMENTAL #if 0 //ndef EXPERIMENTAL
if (member(vars, "_count")) if (member(vars, "_count"))
ebuf += "\n:_count\t" + vars["_count"]; ebuf += "\n:_count\t" + vars["_count"];
#endif #endif
#if __EFUN_DEFINED__(walk_mapping) #if __EFUN_DEFINED__(walk_mapping)
// walk_mapping could be rewritten into foreach, but thats work // walk_mapping could be rewritten into foreach, but thats work
walk_mapping(vars, #'build_header, vars); walk_mapping(vars, #'build_header, vars);
#else // PIKE, MudOS... #else // PIKE, MudOS...
mixed key, val; mapeach(key, val, vars) {
build_header(key, val, vars);
mapeach(key, val, vars) {
build_header(key, val, vars);
}
#endif
} }
if (data == "") ebuf += "\n"+ mc; #endif
if (data == "") ebuf += "\n"+ mc;
else ebuf += "\n"+ mc + "\n"+ data; else ebuf += "\n"+ mc + "\n"+ data;
#ifdef SPYC // || MODULE_LENGTH #ifdef SPYC // || MODULE_LENGTH

View File

@ -2,9 +2,10 @@
// $Id: circuit.c,v 1.38 2008/10/14 19:02:29 lynx Exp $ // $Id: circuit.c,v 1.38 2008/10/14 19:02:29 lynx Exp $
#include "psyc.h" #include "psyc.h"
#include "../psyc/circuit.c"
#if 0 // first we get the syntax running, then we'll think of new features: #ifdef USE_PSYC
# include "../psyc/circuit.c"
#else
#include <net.h> #include <net.h>
#include <uniform.h> #include <uniform.h>
@ -35,7 +36,7 @@ volatile string netloc;
return 0; \ return 0; \
} }
mapping instate; mapping instate = ([ ]);
mapping outstate; mapping outstate;
mapping legal_senders; mapping legal_senders;
@ -51,6 +52,14 @@ void runQ();
int isServer() { return 0; } int isServer() { return 0; }
void peek(string data) {
#if __EFUN_DEFINED__(enable_binary)
enable_binary(ME);
#else
raise_error("Driver compiled without enable_binary()");
#endif
}
void feed(string data) { void feed(string data) {
input_to(#'feed, INPUT_IGNORE_BANG); input_to(#'feed, INPUT_IGNORE_BANG);
::feed(data); ::feed(data);
@ -91,7 +100,7 @@ void sender_verification(array(string) sourcehosts, array(string) targethosts)
int logon(int failure) { int logon(int failure) {
sAuthHosts(([ ])); // reset authhosts sAuthHosts(([ ])); // reset authhosts
legal_senders = ([ ]); legal_senders = ([ ]);
instate = ([ "_INTERNAL_origin" : ME]); instate = ([ "_INTERNAL_origin" : ME ]);
outstate = ([ ]); outstate = ([ ]);
#ifdef __TLS__ #ifdef __TLS__
mixed cert; mixed cert;
@ -145,11 +154,6 @@ int logon(int failure) {
peerip = query_ip_number(ME) || "127.0.0.1"; peerip = query_ip_number(ME) || "127.0.0.1";
#if __EFUN_DEFINED__(enable_binary)
enable_binary(ME);
#else
# echo Driver compiled without enable_binary() - PSYC functionality warning!
#endif
input_to(#'feed, INPUT_IGNORE_BANG); input_to(#'feed, INPUT_IGNORE_BANG);
call_out(#'quit, 90); call_out(#'quit, 90);
@ -202,37 +206,6 @@ first_response() {
emit("|\n"); emit("|\n");
} }
// processes routing header variable assignments
// basic version does no state
mapping process_header(mixed varops) {
mapping vars = ([ ]);
foreach(mixed vop : varops) {
string vname = vop[0];
switch(vop[1]) {
case C_GLYPH_MODIFIER_ASSIGN:
instate[vname] = vop[2];
// fall thru
case C_GLYPH_MODIFIER_SET:
vars[vname] = vop[2];
break;
case C_GLYPH_MODIFIER_AUGMENT:
case C_GLYPH_MODIFIER_DIMINISH:
case C_GLYPH_MODIFIER_QUERY:
CIRCUITERROR("header modifier with glyph other than ':', this is not implemented")
break;
default:
CIRCUITERROR("header modifier with unknown glyph")
break;
}
// FIXME: not every legal varname is a mmp varname
// look at shared_memory("routing")
if (!legal_keyword(vname) || abbrev("_INTERNAL", vname)) {
CIRCUITERROR("illegal varname in header")
}
}
return vars;
}
#define PSYC_TCP #define PSYC_TCP
#include "dispatch.i" #include "dispatch.i"
@ -329,4 +302,4 @@ varargs int msg(string source, string mc, string data,
return emit(buf); return emit(buf);
} }
#endif // 0 #endif // USE_PSYC

View File

@ -1,2 +1,3 @@
#include "../psyc/common.h" #ifdef USE_PSYC
# include "../psyc/common.h"
#endif

View File

@ -1,34 +1,161 @@
#if 0 // first we get the syntax running, then we'll think of new features:
// included by TCP circuit *and* UDP daemon // vim:syntax=lpc // included by TCP circuit *and* UDP daemon // vim:syntax=lpc
void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) { // processes routing header variable assignments
// basic version does no state
mixed process_routing_modifiers(mapping rvars, mapping vars) {
if (!mappingp(instate)) // no routing state for udp
return;
foreach (mixed vname : m_indices(rvars)) {
if (!isRouting[vname]) {
CIRCUITERROR("illegal varname in routing header")
}
switch (rvars[vname, 1]) {
case C_GLYPH_MODIFIER_ASSIGN:
// TODO: delete if empty?
instate[vname] = rvars[vname];
// fall thru
case C_GLYPH_MODIFIER_SET:
vars[vname] = rvars[vname];
break;
case C_GLYPH_MODIFIER_AUGMENT:
case C_GLYPH_MODIFIER_DIMINISH:
case C_GLYPH_MODIFIER_QUERY:
CIRCUITERROR("header modifier with glyph other than ':' or '=', this is not implemented")
break;
default:
CIRCUITERROR("header modifier with unknown glyph")
break;
}
}
vars += instate;
return 1;
}
mixed process_entity_modifiers(mapping evars, mapping vars, mapping cstate) {
// apply evars to context state
foreach (mixed vname : m_indices(evars)) {
if (isRouting[vname] || abbrev("_INTERNAL", vname)
#ifndef LIBPSYC
|| !legal_keyword(vname)
#endif
) {
DISPATCHERROR("illegal varname in entity header")
}
if (!mappingp(cstate) && evars[vname, 1] != C_GLYPH_MODIFIER_SET) {
DISPATCHERROR("entity modifier with glyph other than ':' and there's no _context set")
}
switch (evars[vname, 1]) { // the glyph
case C_GLYPH_MODIFIER_ASSIGN:
// TODO: delete if empty?
cstate[vname] = evars[vname];
// fall thru
case C_GLYPH_MODIFIER_SET:
vars[vname] = evars[vname];
break;
case C_GLYPH_MODIFIER_AUGMENT:
if (!abbrev("_list", vname)) {
DISPATCHERROR("psyc modifier + with non-list arg")
}
// FIXME: duplicates?
cstate[vname] += evars[vname];
PT(("current state is %O, augment %O\n", cstate[vname], evars[vname]))
break;
case C_GLYPH_MODIFIER_DIMINISH:
if (!abbrev("_list", vname)) {
DISPATCHERROR("psyc modifier + with non-list arg")
}
PT(("current state is %O, diminish %O\n", cstate[vname], evars[vname]))
foreach(mixed item : evars[vname])
cstate[vname] -= ({ item });
PT(("after dim: %O\n", cstate[vname]))
break;
case C_GLYPH_MODIFIER_QUERY:
DISPATCHERROR("psyc modifier ? not implemented")
}
}
if (mappingp(cstate))
vars += cstate;
return 1;
}
mixed process_var_types(mapping evars) {
string family;
int glyph;
// FIXME: i dont like this block... maybe we decode each variable
// when setting it?
// that would also fit with 0 as varname deletion
// below
foreach (mixed vname : m_indices(evars)) {
// psyc type conversion implementation ( http://about.psyc.eu/Type )
// this does not support register_type() yet, but it is feasible
PSYC_TRY(vname) {
case "_uniform":
case "_page":
case "_entity":
if (!parse_uniform(evars[vname]))
croak("_error_illegal_uniform");
break;
case "_nick":
if (!legal_name(evars[vname]))
croak("_error_illegal_nick");
break;
#ifndef LIBPSYC
case "_degree":
// only honour the first digit
if (strlen(evars[vname]) && evars[vname][0] >= '0' && evars[vname][0] <= '9')
evars[vname] = evars[vname][0] - '0';
else {
PT(("type parser _degree: could not handle value %O\n",
evars[vname]))
evars[vname] = 0;
}
break;
case "_date":
evars[vname] = to_int(evars[vname]) + PSYC_EPOCH;
break;
case "_time":
case "_amount":
evars[vname] = to_int(evars[vname]);
break;
case "_list":
mixed plist = list_parse(evars[vname]);
if (plist == -1) {
DISPATCHERROR("could not parse list");
}
evars[vname] = plist;
break;
#endif
PSYC_SLICE_AND_REPEAT
}
}
return 1;
}
void dispatch(mapping rvars, mapping evars, mixed method, mixed body) {
string vname; string vname;
mixed vop; // value operation mixed vop; // value operation
string t; string t;
mapping vars; mapping vars = ([ ]);
string family;
int glyph; PT((">> dispatch(%O, %O, %O, %O)\n", rvars, evars, method, body))
// check that method is a valid keyword // check that method is a valid keyword
if (method && !legal_keyword(method)) { if (method && !legal_keyword(method)) {
DISPATCHERROR("non legal method"); DISPATCHERROR("non legal method");
} }
#ifdef PSYC_TCP
// copy() + occasional double modifier ops should be more
// efficient than merge at every packet --lynX
// no one cares about "efficiency" here. please proof your
// bold statements with benchmarks anyway
vars = header_vars + instate;
#else
vars = header_vars;
#endif
// FIXME: this can happen earlier, e.g. in parse.c after // FIXME: this can happen earlier, e.g. in parse.c after
// process_header // process_header
// check _source/_context // check _source/_context
// this check can be skipped if _source and _context are empty // this check can be skipped if _source and _context are empty
if ((t = vars["_context"] || vars["_source"])) { if ((t = rvars["_context"] || rvars["_source"])) {
array(mixed) u; array(mixed) u;
unless (u = parse_uniform(t)) { unless (u = parse_uniform(t)) {
DISPATCHERROR("logical source is not a uniform\n") DISPATCHERROR("logical source is not a uniform\n")
@ -43,8 +170,17 @@ void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
# endif # endif
#endif #endif
} }
if (!process_routing_modifiers(rvars, vars))
return;
#ifndef LIBPSYC
if (!process_var_types(evars))t
return;
#endif
// check that _target is hosted by us // check that _target is hosted by us
// this check can be skipped if _target is not set // this check can be skipped if _target is not set
if ((t = vars["_target"])) { if ((t = vars["_target"])) {
array(mixed) u; array(mixed) u;
unless (u = parse_uniform(t)) { unless (u = parse_uniform(t)) {
@ -55,51 +191,6 @@ void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
DISPATCHERROR("target is not configured on this server\n") DISPATCHERROR("target is not configured on this server\n")
} }
} }
// FIXME: i dont like this block... maybe we decode each variable
// when setting it?
// that would also fit with 0 as varname deletion
// below
foreach(vop : varops) {
vname = vop[0];
// psyc type conversion implementation ( http://about.psyc.eu/Type )
// this does not support register_type() yet, but it is feasible
PSYC_TRY(vname) {
case "_uniform":
case "_page":
case "_entity":
// TODO: check legal uniform
break;
case "_nick":
// TODO: check legal nick
break;
case "_degree":
// only honour the first digit
if (strlen(vop[2]) && vop[2][0] >= '0' && vop[2][0] <= '9')
vop[2] = vop[2][0] - '0';
else {
PT(("type parser _degree: could not handle value %O\n",
vop[2]))
vop[2] = 0;
}
break;
case "_date":
vop[2] = to_int(vop[2]) + PSYC_EPOCH;
break;
case "_time":
case "_amount":
vop[2] = to_int(vop[2]);
break;
case "_list":
mixed plist = list_parse(vop[2]);
if (plist == -1) {
DISPATCHERROR("could not parse list");
}
vop[2] = plist;
break;
PSYC_SLICE_AND_REPEAT
}
}
// FIXME deliver packet // FIXME deliver packet
// this should be a separate function // this should be a separate function
@ -108,7 +199,7 @@ void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
// delivery rules as usual, but // delivery rules as usual, but
if (vars["_context"]) { if (vars["_context"]) {
mixed context; mixed context;
mixed context_state; mixed cstate;
mixed source, target; mixed source, target;
if (vars["_source"]) { if (vars["_source"]) {
@ -122,48 +213,13 @@ void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
P0(("context %O not found?!\n", vars["_context"])) P0(("context %O not found?!\n", vars["_context"]))
return; return;
} }
context_state = context->get_state();
// apply varops to context state cstate = context->get_state();
foreach(vop : varops) { process_entity_modifiers(evars, vars, cstate);
vname = vop[0];
if (!legal_keyword(vname) || abbrev("_INTERNAL", vname)) {
DISPATCHERROR("illegal varname in psyc")
}
switch(vop[1]) { // the glyph
case C_GLYPH_MODIFIER_SET:
vars[vname] = vop[2];
break;
case C_GLYPH_MODIFIER_ASSIGN:
vars[vname] = context_state[vname] = vop[2];
break;
case C_GLYPH_MODIFIER_AUGMENT:
if (!abbrev("_list", vname)) {
DISPATCHERROR("psyc modifier + with non-list arg")
}
// FIXME: duplicates?
context_state[vname] += vop[2];
PT(("current state is %O, augment %O\n", context_state[vname], vop[2]))
break;
case C_GLYPH_MODIFIER_DIMINISH:
if (!abbrev("_list", vname)) {
DISPATCHERROR("psyc modifier + with non-list arg")
}
PT(("current state is %O, diminish %O\n", context_state[vname], vop[2]))
foreach(mixed item : vop[2])
context_state[vname] -= ({ item });
PT(("after dim: %O\n", context_state[vname]))
break;
case C_GLYPH_MODIFIER_QUERY:
DISPATCHERROR("psyc modifier ? not implemented")
break;
}
}
vars = vars + context_state;
// FIXME: is it legal to do this if this has _target? // FIXME: is it legal to do this if this has _target?
// there should be no mods then anyway // there should be no mods then anyway
context->commit_state(context_state); // It can have only entity vars, so no _target.
context->commit_state(cstate);
if (vars["_target"]) { if (vars["_target"]) {
// FIXME: delivery copycat from below // FIXME: delivery copycat from below
@ -200,6 +256,8 @@ void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
} }
} }
} else { } else {
process_entity_modifiers(evars, vars, 0);
if (!vars["_target"] && !vars["_source"]) { if (!vars["_target"] && !vars["_source"]) {
#ifdef PSYC_TCP #ifdef PSYC_TCP
circuit_msg(method, vars, body); circuit_msg(method, vars, body);
@ -241,7 +299,5 @@ void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
} }
} }
} }
::dispatch(header_vars, varops, method, body); ::dispatch(rvars, evars, method, body);
} }
#endif // 0

View File

@ -1,59 +1,24 @@
#if 0 // first we get the syntax running, then we'll think of new features:
// vim:foldmethod=marker:syntax=lpc:noexpandtab // vim:foldmethod=marker:syntax=lpc:noexpandtab
// $Id: parse.c,v 1.30 2008/12/18 18:16:14 lynx Exp $ // $Id: parse.c,v 1.30 2008/12/18 18:16:14 lynx Exp $
//
#ifndef USE_PSYC
#include "psyc.h" #include "psyc.h"
#include <net.h> #include <net.h>
#include <input_to.h> #include <input_to.h>
private string buffer; private string buffer;
int state; int state;
int may_parse_more;
#if __EFUN_DEFINED__(psyc_parse) #ifndef LIBPSYC
# echo ___ using libpsyc!
void parser_init() {
if (state != PSYCPARSE_STATE_BLOCKED)
state = PSYCPARSE_STATE_HEADER;
buffer = "";
}
// called when a complete packet has arrived
void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
parser_init();
}
// input data to the buffer
void feed(string data) {
# ifdef _flag_log_sockets_SPYC
log_file("RAW_SPYC", "» %O\n%s\n", ME, data);
# endif
buffer += data;
if (data == "|\n") {
mixed p = psyc_parse(buffer);
if (pointerp(p) && sizeof(p) == 4)
dispatch(p[0], p[1], p[2], p[3]);
else {
P1(("psyc_parse(%O) returned %O\n", buffer, p))
}
}
}
mixed list_parse(string val) {
return 0; // TBD
}
#else /* !libpsyc */
private string body_buffer; private string body_buffer;
int body_len; int body_len;
int may_parse_more;
// tempoary used to hold assigment lists vname -> ({ glyph, state, vvalue }) // tempoary used to hold assigment lists vname -> ({ glyph, state, vvalue })
array(mixed) tvars; array(mixed) tvars;
mapping hvars; mapping hvars;
#endif
// being faded out in favor of regular croak() // being faded out in favor of regular croak()
#define PARSEERROR(reason) { \ #define PARSEERROR(reason) { \
@ -73,6 +38,10 @@ mapping hvars;
step(); // prototype step(); // prototype
// overload this as needed
varargs mixed croak(string mc, string data, vamapping vars) { return 0; }
#ifndef LIBPSYC
// reset parser state // reset parser state
void parser_reset() { void parser_reset() {
if (state != PSYCPARSE_STATE_BLOCKED) if (state != PSYCPARSE_STATE_BLOCKED)
@ -83,37 +52,81 @@ void parser_reset() {
tvars = ({ }); tvars = ({ });
hvars = ([ ]); hvars = ([ ]);
} }
#endif
// initialize the parser // initialize the parser
void parser_init() { void parser_init() {
buffer = ""; # ifndef LIBPSYC
parser_reset(); parser_reset();
# endif
buffer = "";
state = PSYCPARSE_STATE_GREET; // AFTER reset state = PSYCPARSE_STATE_GREET; // AFTER reset
} }
// input data to the buffer // input data to the buffer
void feed(string data) { void feed(string data) {
P4((">> feed: %O\n", data));
# ifdef _flag_log_sockets_SPYC # ifdef _flag_log_sockets_SPYC
log_file("RAW_SPYC", "» %O\n%s\n", ME, data); log_file("RAW_SPYC", "» %O\n%s\n", ME, data);
# endif # endif
buffer += data; buffer += data;
# ifndef LIBPSYC
do { do {
may_parse_more = 0; may_parse_more = 0;
step(); step();
} while (may_parse_more); } while (may_parse_more);
# else
if (state != PSYCPARSE_STATE_HEADER)
step();
if (state == PSYCPARSE_STATE_HEADER) {
switch (psyc_parse(buffer)) {
case 0: // success
break;
case PSYC_PARSE_ERROR_AMOUNT:
croak("_error_invalid_amount");
QUIT
case PSYC_PARSE_ERROR_DEGREE:
croak("_error_invalid_degree");
QUIT
case PSYC_PARSE_ERROR_DATE:
croak("_error_invalid_date");
QUIT
case PSYC_PARSE_ERROR_TIME:
croak("_error_invalid_time");
QUIT
case PSYC_PARSE_ERROR_FLAG:
croak("_error_invalid_flag");
QUIT
case PSYC_PARSE_ERROR_LIST:
croak("_error_invalid_list");
QUIT
case PSYC_PARSE_ERROR_LIST_TOO_LARGE:
croak("_error_list_too_large");
QUIT
default: // parse error
croak("_error_invalid_syntax");
}
buffer = "";
}
# endif
} }
// overload this as needed
varargs mixed croak(string mc, string data, vamapping vars) { return 0; }
// called when a complete packet has arrived // called when a complete packet has arrived
void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) { void dispatch(mixed header_vars, mixed varops, mixed method, mixed body) {
#ifndef LIBPSYC
parser_reset(); parser_reset();
#endif
} }
void psyc_dispatch(mixed p) {
dispatch(p[PACKET_ROUTING], p[PACKET_ENTITY], p[PACKET_METHOD], p[PACKET_BODY]);
}
#ifndef LIBPSYC
// processes routing header variable assignments // processes routing header variable assignments
// basic version does no state // basic version does no state
mapping process_header(mixed varops) { mapping process_header(mixed varops) {
@ -121,7 +134,7 @@ mapping process_header(mixed varops) {
// apply mmp state // apply mmp state
foreach(mixed vop : varops) { foreach(mixed vop : varops) {
string vname = vop[0]; string vname = vop[0];
switch(vop[1]) { switch(vop[1]) {
case C_GLYPH_MODIFIER_SET: case C_GLYPH_MODIFIER_SET:
vars[vname] = vop[2]; vars[vname] = vop[2];
break; break;
@ -360,6 +373,7 @@ void buffer_content() {
P4(("buffer_content: waiting for more plain data. buffer %O vs %O\n", to_array(buffer), to_array("\n" DELIM))) P4(("buffer_content: waiting for more plain data. buffer %O vs %O\n", to_array(buffer), to_array("\n" DELIM)))
} }
} }
#endif // LIBPSYC
// respond to the first empty packet // respond to the first empty packet
void first_response() { void first_response() {
@ -372,12 +386,14 @@ void step() {
if (!strlen(buffer)) if (!strlen(buffer))
return; return;
switch(state) { switch(state) {
#ifndef LIBPSYC
case PSYCPARSE_STATE_HEADER: case PSYCPARSE_STATE_HEADER:
parse_header(); parse_header();
break; break;
case PSYCPARSE_STATE_CONTENT: case PSYCPARSE_STATE_CONTENT:
buffer_content(); buffer_content();
break; break;
#endif
case PSYCPARSE_STATE_BLOCKED: case PSYCPARSE_STATE_BLOCKED:
// someone requested to stop parsing - e.g. _request_features circuit // someone requested to stop parsing - e.g. _request_features circuit
// message // message
@ -389,7 +405,9 @@ void step() {
state = PSYCPARSE_STATE_HEADER; state = PSYCPARSE_STATE_HEADER;
buffer = buffer[2 ..]; buffer = buffer[2 ..];
first_response(); first_response();
#ifndef LIBPSYC
step(); step();
#endif
} else { } else {
croak("_error_syntax_initialization"); croak("_error_syntax_initialization");
// "The new protocol begins with a pipe and a line feed."); // "The new protocol begins with a pipe and a line feed.");
@ -400,6 +418,7 @@ void step() {
} }
} }
#ifndef LIBPSYC
// FIXME should be in a standalone module // FIXME should be in a standalone module
//#define PARSEERROR(args) debug_message(sprintf("LIST PARSE ERROR: " args)); //#define PARSEERROR(args) debug_message(sprintf("LIST PARSE ERROR: " args));
#define LISTSEP '|' #define LISTSEP '|'
@ -432,14 +451,13 @@ mixed list_parse(string val) {
return lv; return lv;
} }
#ifdef SELFTESTS # ifdef SELFTESTS
test() { test() {
list_parse("|psyc://example.symlynX.com/~jim|psyc://example.org/~judy"); list_parse("|psyc://example.symlynX.com/~jim|psyc://example.org/~judy");
list_parse("5\tabcde|4\tabcd"); list_parse("5\tabcde|4\tabcd");
} }
#endif # endif
#endif // !LIBPSYC
#endif /* !libpsyc */
// it is sometimes useful to stop parsing // it is sometimes useful to stop parsing
void interrupt_parse() { void interrupt_parse() {
@ -451,4 +469,4 @@ void resume_parse() {
state = PSYCPARSE_STATE_HEADER; state = PSYCPARSE_STATE_HEADER;
} }
#endif // 0 #endif // USE_PSYC

View File

@ -1,3 +1,3 @@
#include "psyc.h" //#include "psyc.h"
#include "../psyc/parse.i" //#include "../psyc/parse.i"

View File

@ -23,16 +23,17 @@
* the first byte. * the first byte.
*/ */
#ifndef SPYC #define SPYC
# define SPYC
# include <psyc.h> #include <psyc.h>
#ifndef USE_PSYC
#if __EFUN_DEFINED__(psyc_parse)
# define LIBPSYC
# include <sys/libpsyc.h>
#endif #endif
// EOF
#if 0 // first we get the syntax running, then we'll think of new features:
#define PSYCPARSE_STATE_HEADER 0 #define PSYCPARSE_STATE_HEADER 0
#define PSYCPARSE_STATE_CONTENT 1 #define PSYCPARSE_STATE_CONTENT 1
#define PSYCPARSE_STATE_BLOCKED 2 #define PSYCPARSE_STATE_BLOCKED 2
@ -45,4 +46,4 @@
return; \ return; \
} }
#endif // 0 #endif // USE_PSYC

View File

@ -4,9 +4,10 @@
// the thing that answers on port 4404 of psyced. // the thing that answers on port 4404 of psyced.
#include "psyc.h" #include "psyc.h"
#include "../psyc/server.c"
#if 0 // first we get the syntax running, then we'll think of new features: #ifdef USE_PSYC
# include "../psyc/server.c"
#else
#include <net.h> #include <net.h>
#include <services.h> #include <services.h>
@ -194,4 +195,4 @@ void circuit_msg(string mc, mapping vars, string data) {
} }
} }
#endif // 0 #endif // USE_PSYC

View File

@ -2,9 +2,10 @@
// $Id: udp.c,v 1.7 2008/07/17 15:07:59 lynx Exp $ // $Id: udp.c,v 1.7 2008/07/17 15:07:59 lynx Exp $
#include "psyc.h" #include "psyc.h"
#include "../psyc/udp.c"
#if 0 // first we get the syntax running, then we'll think of new features: #ifdef USE_PSYC
# include "../psyc/udp.c"
#else
#include <net.h> #include <net.h>
#include <uniform.h> #include <uniform.h>
@ -13,6 +14,7 @@
inherit NET_PATH "spyc/parse"; inherit NET_PATH "spyc/parse";
string netloc; string netloc;
mapping instate;
object load() { return ME; } // avoid a find_object call in obj/master object load() { return ME; } // avoid a find_object call in obj/master
@ -41,4 +43,4 @@ parseUDP(ip, port, msg) {
#define PSYC_UDP #define PSYC_UDP
#include "dispatch.i" #include "dispatch.i"
#endif // 0 #endif // USE_PSYC