aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xfrd
diff options
context:
space:
mode:
authormjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>2004-07-07 15:54:47 +0000
committermjw@wray-m-3.hpl.hp.com <mjw@wray-m-3.hpl.hp.com>2004-07-07 15:54:47 +0000
commit29b083850c38f1249e96bad60332c998f31c519c (patch)
tree470607290464436d397264fc4f5d382375f6a0ac /tools/xfrd
parent5b630a450d5c0472e9d70a093838df4a5a813d15 (diff)
downloadxen-29b083850c38f1249e96bad60332c998f31c519c.tar.gz
xen-29b083850c38f1249e96bad60332c998f31c519c.tar.bz2
xen-29b083850c38f1249e96bad60332c998f31c519c.zip
bitkeeper revision 1.1041.16.1 (40ec1cc7JZD3Tq_wg7Ea5ZjrczQ0_A)
Starting to call xfrd from xend.
Diffstat (limited to 'tools/xfrd')
-rw-r--r--tools/xfrd/Make.xfrd2
-rw-r--r--tools/xfrd/connection.c32
-rw-r--r--tools/xfrd/connection.h4
-rw-r--r--tools/xfrd/sxpr_parser.c943
-rw-r--r--tools/xfrd/sxpr_parser.h133
-rw-r--r--tools/xfrd/xen_domain.c4
-rw-r--r--tools/xfrd/xfrd.c118
-rwxr-xr-xtools/xfrd/xfrdClient.py10
8 files changed, 1158 insertions, 88 deletions
diff --git a/tools/xfrd/Make.xfrd b/tools/xfrd/Make.xfrd
index 39f3afd3c5..bb746d6bef 100644
--- a/tools/xfrd/Make.xfrd
+++ b/tools/xfrd/Make.xfrd
@@ -15,7 +15,7 @@ UTIL_LIB_SRC += lzi_stream.c
UTIL_LIB_SRC += marshal.c
UTIL_LIB_SRC += string_stream.c
UTIL_LIB_SRC += sxpr.c
-#UTIL_LIB_SRC += sxpr_parser.c
+UTIL_LIB_SRC += sxpr_parser.c
UTIL_LIB_SRC += sys_net.c
UTIL_LIB_SRC += sys_string.c
#UTIL_LIB_SRC += util.c
diff --git a/tools/xfrd/connection.c b/tools/xfrd/connection.c
index 26dca9968b..36f2ca8475 100644
--- a/tools/xfrd/connection.c
+++ b/tools/xfrd/connection.c
@@ -8,6 +8,7 @@
#include "connection.h"
#include "file_stream.h"
#include "lzi_stream.h"
+#include "sxpr_parser.h"
#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
#define wprintf(fmt, args...) fprintf(stderr, "[WARN] %s" fmt, __FUNCTION__, ##args)
@@ -161,3 +162,34 @@ void Conn_close(Conn *conn){
if(conn->out) IOStream_close(conn->out);
shutdown(conn->sock, 2);
}
+
+int Conn_sxpr(Conn *conn, Sxpr *sxpr){
+ int err = 0;
+ Sxpr val = ONONE;
+ int c = 0;
+
+ dprintf(">\n");
+ if(!conn->parser){
+ conn->parser = Parser_new();
+ set_error_stream(conn->parser, iostdout);
+ }
+ while(!err && c >= 0 && !Parser_ready(conn->parser)){
+ c = IOStream_getc(conn->in);
+ printf("%c", (char)c);
+ if(c < 0){
+ err = Parser_input_eof(conn->parser);
+ } else {
+ err = Parser_input_char(conn->parser, c);
+ }
+ }
+ if(Parser_ready(conn->parser)){
+ val = Parser_get_val(conn->parser);
+ }
+ if(err){
+ objfree(val);
+ val = ONONE;
+ }
+ *sxpr = val;
+ dprintf("< err=%d\n", err);
+ return err;
+}
diff --git a/tools/xfrd/connection.h b/tools/xfrd/connection.h
index 790c01f1e8..2b67e767ba 100644
--- a/tools/xfrd/connection.h
+++ b/tools/xfrd/connection.h
@@ -5,6 +5,7 @@
#include <netinet/in.h>
#include "iostream.h"
+#include "sxpr_parser.h"
/** A connection.
* The underlying transport is a socket.
@@ -15,6 +16,7 @@ typedef struct Conn {
int sock;
IOStream *in;
IOStream *out;
+ Parser *parser;
} Conn;
enum {
@@ -29,4 +31,6 @@ extern int Conn_init(Conn *conn, int flags, int sock, struct sockaddr_in addr);
extern int Conn_connect(Conn *conn, int flags, struct in_addr ipaddr, uint16_t port);
extern void Conn_close(Conn *conn);
+extern int Conn_sxpr(Conn *conn, Sxpr *sxpr);
+
#endif /* ! _VFC_CONNECTION_H_ */
diff --git a/tools/xfrd/sxpr_parser.c b/tools/xfrd/sxpr_parser.c
new file mode 100644
index 0000000000..dbe386a862
--- /dev/null
+++ b/tools/xfrd/sxpr_parser.c
@@ -0,0 +1,943 @@
+
+#ifdef __KERNEL__
+# include <linux/config.h>
+# include <linux/module.h>
+# include <linux/kernel.h>
+# include <linux/string.h>
+# include <linux/errno.h>
+#else
+# include <stdlib.h>
+# include <errno.h>
+#endif
+
+#include "iostream.h"
+#include "lexis.h"
+#include "sxpr_parser.h"
+#include "sys_string.h"
+#include "enum.h"
+
+/** @file
+ * Sxpr parsing.
+ *
+ * So that the parser does not leak memory, all sxprs constructed by
+ * the parser must be freed on error. On successful parse the sxpr
+ * returned becomes the responsibility of the caller.
+ *
+ * @author Mike Wray <mike.wray@hpl.hp.com>
+ */
+
+#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
+#define printf(fmt, args...) IOStream_print(iostdout, fmt, ##args)
+
+static void reset(Parser *z);
+static int inputchar(Parser *p, char c);
+static int savechar(Parser *p, char c);
+extern void parse_error(Parser *in);
+extern void parse_error_id(Parser *in, ParseErrorId id);
+
+static int begin_start(Parser *p, char c);
+static int state_start(Parser *p, char c);
+static int end_start(Parser *p);
+
+static int begin_comment(Parser *p, char c);
+static int state_comment(Parser *p, char c);
+static int end_comment(Parser *p);
+
+static int begin_string(Parser *p, char c);
+static int state_string(Parser *p, char c);
+static int end_string(Parser *p);
+static int state_escape(Parser *p, char c);
+static int state_octal(Parser *p, char c);
+static int state_hex(Parser *p, char c);
+
+static int begin_atom(Parser *p, char c);
+static int state_atom(Parser *p, char c);
+static int end_atom(Parser *p);
+
+static int state_list(Parser *p, char c);
+static int begin_list(Parser *p, char c);
+static int end_list(Parser *p);
+
+/** Print a parse error.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void eprintf(Parser *in, char *msg, ...){
+ va_list args;
+ if(in->error_out){
+ va_start(args, msg);
+ IOStream_vprint(in->error_out, msg, args);
+ va_end(args);
+ }
+}
+
+/** Print a parse warning.
+ *
+ * @param in parser
+ * @param msg format followed by printf arguments
+ */
+void wprintf(Parser *in, char *msg, ...){
+ va_list args;
+ if(in->error_out){
+ va_start(args, msg);
+ IOStream_vprint(in->error_out, msg, args);
+ va_end(args);
+ }
+}
+
+/*============================================================================*/
+
+/** Record defining the message for a parse error. */
+typedef struct {
+ ParseErrorId id;
+ char *message;
+} ParseError;
+
+/** Format for printing parse error messages. */
+#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
+
+/** Message catalog for the parse error codes. */
+static ParseError catalog[] = {
+ { PARSE_ERR_UNSPECIFIED, "unspecified error" },
+ { PARSE_ERR_NOMEM, "out of memory" },
+ { PARSE_ERR_UNEXPECTED_EOF, "unexpected end of input" },
+ { PARSE_ERR_TOKEN_TOO_LONG, "token too long" },
+ { PARSE_ERR_INVALID_SYNTAX, "syntax error" },
+ { PARSE_ERR_INVALID_ESCAPE, "invalid escape" },
+ { 0, NULL }
+};
+
+/** Number of entries in the message catalog. */
+const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
+
+void ParserState_free(ParserState *z){
+ if(!z) return;
+ objfree(z->val);
+ deallocate(z);
+}
+
+int ParserState_new(ParserStateFn *fn, char *name,
+ ParserState *parent, ParserState **val){
+ int err = 0;
+ ParserState *z;
+ z = ALLOCATE(ParserState);
+ if(z){
+ z->name = name;
+ z->fn = fn;
+ z->parent = parent;
+ z->val = ONULL;
+ } else {
+ err = -ENOMEM;
+ }
+ if(!err) *val = z;
+ return err;
+}
+
+/** Free a parser.
+ * No-op if the parser is null.
+ *
+ * @param z parser
+ */
+void Parser_free(Parser *z){
+ if(!z) return;
+ objfree(z->val);
+ z->val = ONONE;
+ deallocate(z);
+}
+
+/** Create a new parser. The error stream defaults to null.
+ */
+Parser * Parser_new(void){
+ Parser *z = ALLOCATE(Parser);
+ int err = -ENOMEM;
+
+ if(!z) goto exit;
+ err = 0;
+ reset(z);
+ exit:
+ if(err){
+ Parser_free(z);
+ z = NULL;
+ }
+ return z;
+}
+
+/** Get the next character.
+ * Records the character read in the parser,
+ * and sets the line and character counts.
+ *
+ * @param p parser
+ * @return error flag: 0 on success, non-zero on error
+ */
+static int inputchar(Parser *p, char c){
+ int err = 0;
+ if(c=='\n'){
+ p->line_no++;
+ p->char_no = 0;
+ } else {
+ p->char_no++;
+ }
+ return err;
+}
+
+static int savechar(Parser *p, char c){
+ int err = 0;
+ if(p->buf_i >= p->buf_n){
+ err = -ENOMEM;
+ goto exit;
+ }
+ p->buf[p->buf_i] = c;
+ p->buf_i++;
+ exit:
+ return err;
+}
+
+int Parser_input_char(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ //skip;
+ } else {
+ inputchar(p, c);
+ }
+ if(!p->state){
+ err = begin_start(p, c);
+ if(err) goto exit;
+ }
+ err = p->state->fn(p, c);
+ exit:
+ return err;
+}
+
+int Parser_input_eof(Parser *p){
+ int err = 0;
+ p->eof = 1;
+ err = Parser_input_char(p, IOSTREAM_EOF);
+ return err;
+}
+
+int Parser_input(Parser *p, char *buf, int buf_n){
+ int err = 0;
+ int i = 0;
+ if(buf_n <= 0){
+ err = Parser_input_eof(p);
+ goto exit;
+ }
+ for(i = 0; i<buf_n; i++){
+ err = Parser_input_char(p, buf[i]);
+ if(err) goto exit;
+ }
+ exit:
+ err = (err < 0 ? err : buf_n);
+ return err;
+}
+
+int Parser_push(Parser *p, ParserStateFn *fn, char *name){
+ int err = 0;
+ err = ParserState_new(fn, name, p->state, &p->state);
+ return err;
+}
+
+int Parser_pop(Parser *p){
+ int err = 0;
+ ParserState *s = p->state;
+ p->state = s->parent;
+ ParserState_free(s);
+ return err;
+}
+
+int Parser_return(Parser *p){
+ int err = 0;
+ Sxpr val = ONONE;
+ if(!p->state){
+ err = -EINVAL;
+ goto exit;
+ }
+ val = p->state->val;
+ p->state->val = ONONE;
+ err = Parser_pop(p);
+ if(err) goto exit;
+ if(p->state){
+ err = cons_push(&p->state->val, val);
+ } else {
+ val = nrev(val);
+ p->val = val;
+ }
+ exit:
+ if(err){
+ objfree(val);
+ }
+ return err;
+}
+
+/** Determine if a character is a separator.
+ *
+ * @param p parser
+ * @param c character to test
+ * @return 1 if a separator, 0 otherwise
+ */
+static int is_separator(Parser *p, char c){
+ return in_sep_class(c);
+}
+
+/** Return the current token.
+ * The return value points at the internal buffer, so
+ * it must not be modified (or freed). Use copy_token() if you need a copy.
+ *
+ * @param p parser
+ * @return token
+ */
+char *peek_token(Parser *p){
+ return p->buf;
+}
+
+/** Return a copy of the current token.
+ * The returned value should be freed when finished with.
+ *
+ * @param p parser
+ * @return copy of token
+ */
+char *copy_token(Parser *p){
+ return strdup(peek_token(p));
+}
+
+static int do_intern(Parser *p){
+ int err = 0;
+ Sxpr obj = intern(peek_token(p));
+ if(NOMEMP(obj)){
+ err = -ENOMEM;
+ } else {
+ p->state->val = obj;
+ }
+ return err;
+}
+
+static int do_string(Parser *p){
+ int err = 0;
+ Sxpr obj;
+ obj = string_new(peek_token(p));
+ if(NOMEMP(obj)){
+ err = -ENOMEM;
+ } else {
+ p->state->val = obj;
+ }
+ return err;
+}
+
+void newtoken(Parser *p){
+ memset(p->buf, 0, p->buf_n);
+ p->buf_i = 0;
+ p->tok_begin_line = p->line_no;
+ p->tok_begin_char = p->char_no;
+}
+
+int get_escape(char c, char *d){
+ int err = 0;
+ switch(c){
+ case 'a': *d = '\a'; break;
+ case 'b': *d = '\b'; break;
+ case 'f': *d = '\f'; break;
+ case 'n': *d = '\n'; break;
+ case 'r': *d = '\r'; break;
+ case 't': *d = '\t'; break;
+ case 'v': *d = '\v'; break;
+ case c_escape: *d = c_escape; break;
+ case c_single_quote: *d = c_single_quote; break;
+ case c_double_quote: *d = c_double_quote; break;
+ default:
+ err = -EINVAL;
+ }
+ return err;
+}
+
+int Parser_ready(Parser *p){
+ return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
+}
+
+Sxpr Parser_get_val(Parser *p){
+ Sxpr v = ONONE;
+ if(CONSP(p->val)){
+ v = CAR(p->val);
+ p->val = CDR(p->val);
+ } else if (CONSP(p->start_state->val)){
+ p->val = p->start_state->val;
+ p->val = nrev(p->val);
+ p->start_state->val = ONULL;
+ v = CAR(p->val);
+ p->val = CDR(p->val);
+ }
+ return v;
+}
+
+Sxpr Parser_get_all(Parser *p){
+ Sxpr v = ONULL;
+ if(CONSP(p->val)){
+ v = p->val;
+ p->val = ONONE;
+ } else if(CONSP(p->start_state->val)){
+ v = p->start_state->val;
+ p->start_state->val = ONULL;
+ v = nrev(v);
+ }
+ return v;
+}
+
+int begin_start(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_start, "start");
+ if(err) goto exit;
+ p->start_state = p->state;
+ exit:
+ return err;
+}
+
+int state_start(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ err = end_start(p);
+ } else if(in_space_class(c)){
+ //skip
+ } else if(in_comment_class(c)){
+ begin_comment(p, c);
+ } else if(c == c_list_open){
+ begin_list(p, c);
+ } else if(c == c_list_close){
+ parse_error(p);
+ err = -EINVAL;
+ } else if(in_string_quote_class(c)){
+ begin_string(p, c);
+ } else if(in_printable_class(c)){
+ begin_atom(p, c);
+ } else if(c == 0x04){
+ //ctrl-D, EOT: end-of-text.
+ Parser_input_eof(p);
+ } else {
+ parse_error(p);
+ err = -EINVAL;
+ }
+ return err;
+}
+
+int end_start(Parser *p){
+ int err = 0;
+ err = Parser_return(p);
+ return err;
+}
+
+int begin_comment(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_comment, "comment");
+ if(err) goto exit;
+ err = inputchar(p, c);
+ exit:
+ return err;
+}
+
+int state_comment(Parser *p, char c){
+ int err = 0;
+ if(c == '\n' || at_eof(p)){
+ err = end_comment(p);
+ } else {
+ err = inputchar(p, c);
+ }
+ return err;
+}
+
+int end_comment(Parser *p){
+ return Parser_pop(p);
+}
+
+int begin_string(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_string, "string");
+ if(err) goto exit;
+ newtoken(p);
+ p->state->delim = c;
+ exit:
+ return err;
+}
+
+int state_string(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ } else if(c == p->state->delim){
+ err = end_string(p);
+ } else if(c == '\\'){
+ err = Parser_push(p, state_escape, "escape");
+ } else {
+ err = savechar(p, c);
+ }
+ return err;
+}
+
+int end_string(Parser *p){
+ int err = 0;
+ err = do_string(p);
+ if(err) goto exit;
+ err = Parser_return(p);
+ exit:
+ return err;
+}
+
+int state_escape(Parser *p, char c){
+ int err = 0;
+ char d;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ goto exit;
+ }
+ if(get_escape(c, &d) == 0){
+ err = savechar(p, d);
+ if(err) goto exit;
+ err = Parser_pop(p);
+ } else if(c == 'x'){
+ p->state->fn = state_hex;
+ p->state->ival = 0;
+ p->state->count = 0;
+ } else {
+ p->state->fn = state_octal;
+ p->state->ival = 0;
+ p->state->count = 0;
+ err = Parser_input_char(p, c);
+ }
+ exit:
+ return err;
+}
+
+int octaldone(Parser *p){
+ int err = 0;
+ char d = (char)(p->state->ival & 0xff);
+ err = Parser_pop(p);
+ if(err) goto exit;
+ err = Parser_input_char(p, d);
+ exit:
+ return err;
+}
+
+int octaldigit(Parser *p, char c){
+ int err = 0;
+ p->state->ival *= 8;
+ p->state->ival += c - '0';
+ p->state->count++;
+ if(err) goto exit;
+ if(p->state->ival < 0 || p->state->ival > 0xff){
+ parse_error(p);
+ err = -EINVAL;
+ goto exit;
+ }
+ if(p->state->count == 3){
+ err = octaldone(p);
+ }
+ exit:
+ return err;
+}
+
+int state_octal(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ goto exit;
+ } else if('0' <= c && c <= '7'){
+ err = octaldigit(p, c);
+ } else {
+ err = octaldone(p);
+ if(err) goto exit;
+ Parser_input_char(p, c);
+ }
+ exit:
+ return err;
+}
+
+int hexdone(Parser *p){
+ int err = 0;
+ char d = (char)(p->state->ival & 0xff);
+ err = Parser_pop(p);
+ if(err) goto exit;
+ err = Parser_input_char(p, d);
+ exit:
+ return err;
+}
+
+int hexdigit(Parser *p, char c, char d){
+ int err = 0;
+ p->state->ival *= 16;
+ p->state->ival += c - d;
+ p->state->count++;
+ if(err) goto exit;
+ if(p->state->ival < 0 || p->state->ival > 0xff){
+ parse_error(p);
+ err = -EINVAL;
+ goto exit;
+ }
+ if(p->state->count == 2){
+ err = hexdone(p);
+ }
+ exit:
+ return err;
+}
+
+int state_hex(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ goto exit;
+ } else if('0' <= c && c <= '9'){
+ err = hexdigit(p, c, '0');
+ } else if('A' <= c && c <= 'F'){
+ err = hexdigit(p, c, 'A');
+ } else if('a' <= c && c <= 'f'){
+ err = hexdigit(p, c, 'a');
+ } else if(p->state->count){
+ err =hexdone(p);
+ if(err) goto exit;
+ Parser_input_char(p, c);
+ }
+ exit:
+ return err;
+}
+
+int begin_atom(Parser *p, char c){
+ int err = 0;
+ err = Parser_push(p, state_atom, "atom");
+ if(err) goto exit;
+ newtoken(p);
+ err = savechar(p, c);
+ exit:
+ return err;
+}
+
+int state_atom(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ err = end_atom(p);
+ } else if(is_separator(p, c) ||
+ in_space_class(c) ||
+ in_comment_class(c)){
+ err = end_atom(p);
+ if(err) goto exit;
+ err = Parser_input_char(p, c);
+ } else {
+ err = savechar(p, c);
+ }
+ exit:
+ return err;
+}
+
+int end_atom(Parser *p){
+ int err = 0;
+ err = do_intern(p);
+ if(err) goto exit;
+ err = Parser_return(p);
+ exit:
+ return err;
+}
+
+int state_list(Parser *p, char c){
+ int err = 0;
+ if(at_eof(p)){
+ parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
+ err = -EINVAL;
+ } else if(c == c_list_close){
+ p->state->val = nrev(p->state->val);
+ err = end_list(p);
+ } else {
+ err = state_start(p, c);
+ }
+ return err;
+
+}
+
+int begin_list(Parser *p, char c){
+ return Parser_push(p, state_list, "list");
+}
+
+int end_list(Parser *p){
+ return Parser_return(p);
+}
+
+/** Reset the fields of a parser to initial values.
+ *
+ * @param z parser
+ */
+static void reset(Parser *z){
+ IOStream *error_out = z->error_out;
+ int flags = z->flags;
+ memzero(z, sizeof(Parser));
+ z->buf_n = sizeof(z->buf) - 1;
+ z->buf_i = 0;
+ z->line_no = 1;
+ z->char_no = 0;
+ z->error_out = error_out;
+ z->flags = flags;
+}
+
+/** Set the parser error stream.
+ * Parse errors are reported on the the error stream if it is non-null.
+ *
+ * @param z parser
+ * @param error_out error stream
+ */
+void set_error_stream(Parser *z, IOStream *error_out){
+ if(z){
+ z->error_out = error_out;
+ }
+}
+
+/** Get the parser error message for an error code.
+ *
+ * @param id error code
+ * @return error message (empty string if the code is unknown)
+ */
+static char *get_message(ParseErrorId id){
+ int i;
+ for(i=0; i<catalog_n; i++){
+ if(id == catalog[i].id){
+ return catalog[i].message;
+ }
+ }
+ return "";
+}
+
+/** Get the line number.
+ *
+ * @param in parser
+ */
+int get_line(Parser *in){
+ return in->line_no;
+}
+
+/** Get the column number.
+ *
+ * @param in parser
+ */
+int get_column(Parser *in){
+ return in->char_no;
+}
+
+/** Get the line number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_line(Parser *in){
+ return in->tok_begin_line;
+}
+
+/** Get the column number the current token started on.
+ *
+ * @param in parser
+ */
+int get_tok_column(Parser *in){
+ return in->tok_begin_char;
+}
+
+/** Report a parse error.
+ * Does nothing if the error stream is null or there is no error.
+ *
+ * @param in parser
+ */
+static void report_error(Parser *in){
+ if(in->error_out && in->err){
+ char *msg = get_message(in->err);
+ char *tok = peek_token(in);
+ IOStream_print(in->error_out, PARSE_ERR_FMT,
+ get_tok_line(in), get_tok_column(in), msg);
+ if(tok && tok[0]){
+ IOStream_print(in->error_out, " '%s'", tok);
+ }
+ IOStream_print(in->error_out, "\n");
+ }
+}
+
+/** Get the error message for the current parse error code.
+ * Does nothing if there is no error.
+ *
+ * @param in parser
+ * @param buf where to place the message
+ * @param n maximum number of characters to place in buf
+ * @return current error code (zero for no error)
+ */
+int parse_error_message(Parser *in, char *buf, int n){
+ if(in->err){
+ char *msg = get_message(in->err);
+ snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
+ }
+ return in->err;
+}
+
+/** Flag an unspecified parse error. All subsequent reads will fail.
+ *
+ * @param in parser
+ */
+void parse_error(Parser *in){
+ parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
+}
+
+/** Flag a parse error. All subsequent reads will fail.
+ * Does not change the parser error code if it is already set.
+ *
+ * @param in parser
+ * @param id error code
+ */
+void parse_error_id(Parser *in, ParseErrorId id){
+ if(!in->err){
+ in->err = id;
+ report_error(in);
+ }
+}
+
+/** Test if the parser's error flag is set.
+ *
+ * @param in parser
+ * @return 1 if set, 0 otherwise
+ */
+int has_error(Parser *in){
+ return (in->err > 0);
+}
+
+/** Test if the parser is at end of input.
+ *
+ * @param in parser
+ * @return 1 if at EOF, 0 otherwise
+ */
+int at_eof(Parser *p){
+ return p->eof;
+}
+
+//#define SXPR_PARSER_MAIN
+#ifdef SXPR_PARSER_MAIN
+/* Stuff for standalone testing. */
+
+#include "file_stream.h"
+#include "string_stream.h"
+
+int stringof(Sxpr exp, char **s){
+ int err = 0;
+ if(ATOMP(exp)){
+ *s = atom_name(exp);
+ } else if(STRINGP(exp)){
+ *s = string_string(exp);
+ } else {
+ err = -EINVAL;
+ *s = NULL;
+ }
+ return err;
+}
+
+int child_string(Sxpr exp, Sxpr key, char **s){
+ int err = 0;
+ Sxpr val = sxpr_child_value(exp, key, ONONE);
+ err = stringof(val, s);
+ return err;
+}
+
+int intof(Sxpr exp, int *v){
+ int err = 0;
+ char *s;
+ unsigned long l;
+ if(INTP(exp)){
+ *v = OBJ_INT(exp);
+ } else {
+ err = stringof(exp, &s);
+ if(err) goto exit;
+ err = convert_atoul(s, &l);
+ *v = (int)l;
+ }
+ exit:
+ return err;
+}
+
+int child_int(Sxpr exp, Sxpr key, int *v){
+ int err = 0;
+ Sxpr val = sxpr_child_value(exp, key, ONONE);
+ err = intof(val, v);
+ return err;
+}
+
+int eval_vnet(Sxpr exp){
+ int err = 0;
+ Sxpr oid = intern("id");
+ int id;
+ err = child_int(exp, oid, &id);
+ if(err) goto exit;
+ dprintf("> vnet id=%d\n", id);
+ exit:
+ dprintf("< err=%d\n", err);
+ return err;
+}
+
+int eval_connect(Sxpr exp){
+ int err = 0;
+ Sxpr ovif = intern("vif");
+ Sxpr ovnet = intern("vnet");
+ char *vif;
+ int vnet;
+
+ err = child_string(exp, ovif, &vif);
+ if(err) goto exit;
+ err = child_int(exp, ovnet, &vnet);
+ if(err) goto exit;
+ dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
+ exit:
+ dprintf("< err=%d\n", err);
+ return err;
+}
+
+int eval(Sxpr exp){
+ int err = 0;
+ Sxpr oconnect = intern("connect");
+ Sxpr ovnet = intern("vnet");
+
+ if(sxpr_elementp(exp, ovnet)){
+ err = eval_vnet(exp);
+ } else if(sxpr_elementp(exp, oconnect)){
+ err = eval_connect(exp);
+ } else {
+ err = -EINVAL;
+ }
+ return err;
+}
+
+/** Main program for testing.
+ * Parses input and prints it.
+ *
+ * @param argc number of arguments
+ * @param argv arguments
+ * @return error code
+ */
+int main(int argc, char *argv[]){
+ Parser *pin;
+ int err = 0;
+ char buf[1024];
+ int k;
+ Sxpr obj;
+ //Sxpr l, x;
+ int i = 0;
+
+ pin = Parser_new();
+ set_error_stream(pin, iostdout);
+ dprintf("> parse...\n");
+ while(1){
+ k = fread(buf, 1, 1, stdin);
+ err = Parser_input(pin, buf, k);
+ while(Parser_ready(pin)){
+ obj = Parser_get_val(pin);
+ printf("obj %d\n", i++);
+ objprint(iostdout, obj, 0); printf("\n");
+ }
+ if(k <= 0) break;
+ }
+/* obj = Parser_get_all(pin); */
+/* for(l = obj ; CONSP(l); l = CDR(l)){ */
+/* x = CAR(l); */
+/* objprint(iostdout, x, 0); printf("\n"); */
+/* eval(x); */
+/* } */
+ dprintf("> err=%d\n", err);
+ return 0;
+}
+#endif
diff --git a/tools/xfrd/sxpr_parser.h b/tools/xfrd/sxpr_parser.h
new file mode 100644
index 0000000000..64a417608c
--- /dev/null
+++ b/tools/xfrd/sxpr_parser.h
@@ -0,0 +1,133 @@
+/*
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of the
+ * License, or (at your option) any later version. This library is
+ * distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _XUTIL_SXPR_PARSER_H_
+#define _XUTIL_SXPR_PARSER_H_
+
+#include "sxpr.h"
+#include "iostream.h"
+
+/** @file
+ * Sxpr parsing definitions.
+ */
+
+/** Size of a parser input buffer.
+ * Tokens read must fit into this size (including trailing null).
+ */
+#define PARSER_BUF_SIZE 1024
+
+struct Parser;
+typedef int ParserStateFn(struct Parser *, char c);
+
+typedef struct ParserState {
+ struct ParserState *parent;
+ Sxpr val;
+ int ival;
+ int count;
+ char delim;
+ ParserStateFn *fn;
+ char *name;
+} ParserState;
+
+/** Structure representing an input source for the parser.
+ * Can read from any IOStream implementation.
+ */
+typedef struct Parser {
+ Sxpr val;
+ /** Error reporting stream (null for no reports). */
+ IOStream *error_out;
+ int eof;
+ /** Error flag. Non-zero if there has been a read error. */
+ int err;
+ /** Line number on input (from 1). */
+ int line_no;
+ /** Column number of input (reset on new line). */
+ int char_no;
+ /** Lookahead character. */
+ char c;
+ /** Buffer for reading tokens. */
+ char buf[PARSER_BUF_SIZE];
+ /** Size of token buffer. */
+ int buf_n;
+ int buf_i;
+ /** Line the last token started on. */
+ int tok_begin_line;
+ /** Character number the last token started on. */
+ int tok_begin_char;
+ /** Parsing flags. */
+ int flags;
+ ParserState *state;
+ ParserState *start_state;
+} Parser;
+
+/** Parser error codes. */
+typedef enum {
+ PARSE_ERR_NONE=0,
+ PARSE_ERR_UNSPECIFIED,
+ PARSE_ERR_NOMEM,
+ PARSE_ERR_UNEXPECTED_EOF,
+ PARSE_ERR_TOKEN_TOO_LONG,
+ PARSE_ERR_INVALID_SYNTAX,
+ PARSE_ERR_INVALID_ESCAPE,
+} ParseErrorId;
+
+
+/** Parser flags. */
+//enum {
+//};
+
+/** Raise some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_raise(Parser *in, int flags){
+ in->flags |= flags;
+}
+
+/** Lower some parser flags.
+ *
+ * @param in parser
+ * @param flags flags mask
+ */
+inline static void parser_flags_lower(Parser *in, int flags){
+ in->flags &= ~flags;
+}
+
+/** Clear all parser flags.
+ *
+ * @param in parser
+ */
+inline static void parser_flags_clear(Parser *in){
+ in->flags = 0;
+}
+
+extern void Parser_free(Parser *z);
+extern Parser * Parser_new(void);
+extern int Parser_input(Parser *p, char *buf, int buf_n);
+extern int Parser_input_eof(Parser *p);
+extern int Parser_input_char(Parser *p, char c);
+extern void set_error_stream(Parser *z, IOStream *error_out);
+
+extern int parse_error_message(Parser *in, char *buf, int n);
+extern int has_error(Parser *in);
+extern int at_eof(Parser *in);
+
+int Parser_ready(Parser *p);
+Sxpr Parser_get_val(Parser *p);
+Sxpr Parser_get_all(Parser *p);
+
+#endif /* ! _XUTIL_SXPR_PARSER_H_ */
diff --git a/tools/xfrd/xen_domain.c b/tools/xfrd/xen_domain.c
index 5c5f7c5bef..4c197e8396 100644
--- a/tools/xfrd/xen_domain.c
+++ b/tools/xfrd/xen_domain.c
@@ -38,7 +38,7 @@ int xen_domain_snd(Conn *xend, IOStream *io, uint32_t dom, char *vmconfig, int v
if(d > buf_n) d = buf_n;
err = marshal_bytes(io, buf, d);
if(err) goto exit;
- //dprintf("> k=%d n=%d\n", k, n);
+ dprintf("> k=%d n=%d\n", k, n);
}
exit:
@@ -68,7 +68,7 @@ int xen_domain_rcv(IOStream *io, uint32_t *dom, char **vmconfig, int *vmconfig_n
if(d > buf_n) d = buf_n;
err = unmarshal_bytes(io, buf, d);
if(err) goto exit;
- //dprintf("> k=%d n=%d\n", k, n);
+ dprintf("> k=%d n=%d\n", k, n);
}
exit:
#else
diff --git a/tools/xfrd/xfrd.c b/tools/xfrd/xfrd.c
index 1836231075..5dac7be0ba 100644
--- a/tools/xfrd/xfrd.c
+++ b/tools/xfrd/xfrd.c
@@ -36,7 +36,7 @@
#include "sys_net.h"
#include "sys_string.h"
-#include "xdr.h"
+//#include "xdr.h"
#include "enum.h"
#include "xfrd.h"
@@ -362,10 +362,10 @@ int addrof(Sxpr exp, uint32_t *v){
err = stringof(exp, &h);
if(err) goto exit;
if(get_host_address(h, &a)){
- *v = a;
- } else {
err = -EINVAL;
+ goto exit;
}
+ *v = a;
exit:
dprintf("< err=%d v=%x\n", err, *v);
return err;
@@ -383,11 +383,12 @@ int portof(Sxpr exp, uint16_t *v){
unsigned long p;
err = stringof(exp, &s);
if(err) goto exit;
- if(get_service_port(s, &p)){
- *v = p;
- } else {
+ err = convert_service_to_port(s, &p);
+ if(err){
err = -EINVAL;
+ goto exit;
}
+ *v = p;
}
exit:
dprintf("< err=%d v=%u\n", err, *v);
@@ -414,20 +415,12 @@ time_t stats(time_t t0, uint64_t offset, uint64_t memory, float *percent, float
*/
int xfr_error(Conn *conn, int errcode){
int err = 0;
+
if(!conn->out) return -ENOTCONN;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_err);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(errcode));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- exit:
- return err;
+ if(errcode <0) errcode = -errcode;
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_err), errcode);
+ return (err < 0 ? err : 0);
}
/** Read a response message - error or ok.
@@ -441,7 +434,7 @@ int xfr_response(Conn *conn){
dprintf(">\n");
if(!conn->out) return -ENOTCONN;
- err = unpack_sxpr(conn->in, &sxpr);
+ err = Conn_sxpr(conn, &sxpr);
if(err) goto exit;
if(sxpr_elementp(sxpr, oxfr_err)){
int errcode;
@@ -468,7 +461,7 @@ int xfr_hello(Conn *conn){
Sxpr sxpr;
if(!conn->in) return -ENOTCONN;
dprintf(">\n");
- err = unpack_sxpr(conn->in, &sxpr);
+ err = Conn_sxpr(conn, &sxpr);
if(err) goto exit;
if(!sxpr_elementp(sxpr, oxfr_hello)){
dprintf("> sxpr_elementp test failed\n");
@@ -503,21 +496,12 @@ int xfr_hello(Conn *conn){
int xfr_send_hello(Conn *conn){
int err = 0;
dprintf(">\n");
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_hello);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(XFR_PROTO_MAJOR));
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(XFR_PROTO_MINOR));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
+
+ err = IOStream_print(conn->out, "(%s %d %d)",
+ atom_name(oxfr_hello),
+ XFR_PROTO_MAJOR,
+ XFR_PROTO_MINOR);
+ if(err < 0) goto exit;
IOStream_flush(conn->out);
dprintf("> xfr_response...\n");
err = xfr_response(conn);
@@ -528,55 +512,26 @@ int xfr_send_hello(Conn *conn){
int xfr_send_xfr(Conn *conn, uint32_t vmid){
int err;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_xfr);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(vmid));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- if(err) goto exit;
- exit:
- return err;
+
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_xfr), vmid);
+ return (err < 0 ? err : 0);
}
int xfr_send_ok(Conn *conn, uint32_t vmid){
int err = 0;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_ok);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(vmid));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- exit:
- return err;
+
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_ok), vmid);
+ return (err < 0 ? err : 0);
}
int xfr_send_suspend(Conn *conn, uint32_t vmid){
int err = 0;
- err = pack_type(conn->out, T_CONS);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, oxfr_suspend);
- if(err) goto exit;
- err = pack_bool(conn->out, 1);
- if(err) goto exit;
- err = pack_sxpr(conn->out, mkint(vmid));
- if(err) goto exit;
- err = pack_bool(conn->out, 0);
- exit:
- return err;
+ err = IOStream_print(conn->out, "(%s %d)",
+ atom_name(oxfr_suspend), vmid);
+ return (err < 0 ? err : 0);
}
/** Get vm state. Send transfer message.
@@ -594,11 +549,12 @@ int xfr_send_state(XfrState *state, Conn *xend, Conn *peer){
// Send xfr message and the domain state.
err = xfr_send_xfr(peer, state->vmid);
if(err) goto exit;
- err = xen_domain_snd(xend, peer->out, state->vmid, state->vmconfig, state->vmconfig_n);
+ err = xen_domain_snd(xend, peer->out,
+ state->vmid, state->vmconfig, state->vmconfig_n);
if(err) goto exit;
IOStream_flush(peer->out);
// Read the response from the peer.
- err = unpack_sxpr(peer->in, &sxpr);
+ err = Conn_sxpr(peer, &sxpr);
if(err) goto exit;
if(sxpr_elementp(sxpr, oxfr_err)){
// Error.
@@ -785,10 +741,14 @@ int xfrd_service(Args *args, int peersock, struct sockaddr_in peer_in){
dprintf(">\n");
err = Conn_init(conn, flags, peersock, peer_in);
if(err) goto exit;
+ dprintf(">xfr_hello... \n");
err = xfr_hello(conn);
if(err) goto exit;
- err = unpack_sxpr(conn->in, &sxpr);
+ dprintf("> sxpr...\n");
+ err = Conn_sxpr(conn, &sxpr);
if(err) goto exit;
+ dprintf("> sxpr=\n");
+ objprint(iostdout, sxpr, PRINT_TYPE); IOStream_print(iostdout, "\n");
if(sxpr_elementp(sxpr, oxfr_migrate)){
// Migrate message from xend.
uint32_t addr;
diff --git a/tools/xfrd/xfrdClient.py b/tools/xfrd/xfrdClient.py
index b8a3554729..1f1fc22407 100755
--- a/tools/xfrd/xfrdClient.py
+++ b/tools/xfrd/xfrdClient.py
@@ -34,13 +34,11 @@ class TCPClient:
self.sockin = self.sock.makefile("r")
self.sockout = self.sock.makefile("w")
- self.packer = SxpPacker(self.sockout)
- self.unpacker = SxpUnpacker(self.sockin)
#pass
def request(self, req):
print "request>", req
- self.packer.pack(req)
+ sxp.show(req, out=self.sockout)
self.sockout.flush()
print "request<"
@@ -52,10 +50,10 @@ class TCPClient:
def read(self):
while(1):
- v = self.unpacker.unpack()
+ v = self.sockin.read()
print 'read>', v
- if v[0] == 'xfr.err' and v[1]: return
- if v[0] == 'xfr.ok': return
+ #if v[0] == 'xfr.err' and v[1]: return
+ #if v[0] == 'xfr.ok': return
XFR_PROTO_MAJOR = 1
XFR_PROTO_MINOR = 0