ia64/xen-unstable

changeset 4905:7f7c68433c4c

bitkeeper revision 1.1403 (4284c2edzLTGTr4gHmGzYsZMuetTRQ)

Switch to using unix-domain interface on xend instead
of http via libcurl.
Sundry other merges and fixes.
Signed-off-by: Mike Wray <mike.wray@hp.com>
author mjw@wray-m-3.hpl.hp.com
date Fri May 13 15:08:29 2005 +0000 (2005-05-13)
parents 940a73d4b2a6
children 69bd3136c3b7
files .rootkeys tools/libxutil/fd_stream.c tools/libxutil/fd_stream.h tools/libxutil/lexis.h tools/libxutil/sxpr.c tools/libxutil/sxpr.h tools/libxutil/sxpr_parser.c tools/libxutil/sxpr_parser.h tools/libxutil/sys_string.c tools/libxutil/sys_string.h tools/python/xen/xend/server/SrvDaemon.py tools/python/xen/xend/server/event.py tools/xfrd/Make.xfrd tools/xfrd/Makefile tools/xfrd/connection.c tools/xfrd/lzi_stream.c tools/xfrd/xen_domain.c tools/xfrd/xfrd.c
line diff
     1.1 --- a/.rootkeys	Fri May 13 15:01:20 2005 +0000
     1.2 +++ b/.rootkeys	Fri May 13 15:08:29 2005 +0000
     1.3 @@ -754,6 +754,8 @@ 40e03332KYz7o1bn2MG_KPbBlyoIMA tools/lib
     1.4  41a216cav5JJbtDQnusfuMa_1x_Xpw tools/libxutil/debug.h
     1.5  40e9808eyjiahG5uF6AMelNVujBzCg tools/libxutil/enum.c
     1.6  40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/libxutil/enum.h
     1.7 +4284c2ecWyadIhHF1u_QSgWqIXkaLA tools/libxutil/fd_stream.c
     1.8 +4284c2ecEOOcF6fZUf_NsZzYAoNo-w tools/libxutil/fd_stream.h
     1.9  40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c
    1.10  40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h
    1.11  40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/libxutil/fd_stream.c	Fri May 13 15:08:29 2005 +0000
     2.3 @@ -0,0 +1,184 @@
     2.4 +/*
     2.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     2.6 + *
     2.7 + * This library is free software; you can redistribute it and/or modify
     2.8 + * it under the terms of the GNU Lesser General Public License as published by
     2.9 + * the Free Software Foundation; either version 2.1 of the License, or
    2.10 + * (at your option) any later version.
    2.11 + *
    2.12 + * This library is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU Lesser General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU Lesser General Public License
    2.18 + * along with this library; if not, write to the Free Software
    2.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    2.20 + */
    2.21 +
    2.22 +/** @file
    2.23 + * An IOStream implementation using fds.
    2.24 + */
    2.25 +#ifndef __KERNEL__
    2.26 +
    2.27 +#include <stdio.h>
    2.28 +#include <stdlib.h>
    2.29 +#include <string.h>
    2.30 +#include <unistd.h>
    2.31 +#include <errno.h>
    2.32 +#include "allocate.h"
    2.33 +#include "fd_stream.h"
    2.34 +
    2.35 +#define MODULE_NAME "fd_stream"
    2.36 +#define DEBUG 1
    2.37 +//#undef DEBUG
    2.38 +#include "debug.h"
    2.39 +
    2.40 +static int fd_read(IOStream *s, void *buf, size_t n);
    2.41 +static int fd_write(IOStream *s, const void *buf, size_t n);
    2.42 +static int fd_error(IOStream *s);
    2.43 +static int fd_close(IOStream *s);
    2.44 +static void fd_free(IOStream *s);
    2.45 +static int fd_flush(IOStream *s);
    2.46 +
    2.47 +/** Methods used by a fd IOStream. */
    2.48 +static const IOMethods fd_methods = {
    2.49 +    read:  fd_read,
    2.50 +    write: fd_write,
    2.51 +    error: fd_error,
    2.52 +    close: fd_close,
    2.53 +    free:  fd_free,
    2.54 +    flush: fd_flush,
    2.55 +};
    2.56 +
    2.57 +/** Get the fd data.
    2.58 + * 
    2.59 + * @param io fd stream
    2.60 + * @return data
    2.61 + */
    2.62 +static inline FDData * fd_data(IOStream *io){
    2.63 +    return (FDData *)io->data;
    2.64 +}
    2.65 +
    2.66 +/** Test if a stream is a fd stream.
    2.67 + *
    2.68 + * @param io stream
    2.69 + * @return 0 if a fd stream, -EINVAL if not
    2.70 + */
    2.71 +int fd_stream_check(IOStream *io){
    2.72 +    return (io && io->methods == &fd_methods ? 0 : -EINVAL);
    2.73 +}
    2.74 +
    2.75 +/** Get the data for a fd stream.
    2.76 + *
    2.77 + * @param io stream
    2.78 + * @param data return value for the data
    2.79 + * @return 0 if a fd stream, -EINVAL if not
    2.80 + */
    2.81 +int fd_stream_data(IOStream *io, FDData **data){
    2.82 +    int err = fd_stream_check(io);
    2.83 +    if(err){
    2.84 +        *data = NULL;
    2.85 +    } else {
    2.86 +        *data = fd_data(io);
    2.87 +    }
    2.88 +    return err;
    2.89 +}
    2.90 +
    2.91 +
    2.92 +/** Write to the underlying fd.
    2.93 + *
    2.94 + * @param stream input
    2.95 + * @param buf where to put input
    2.96 + * @param n number of bytes to write
    2.97 + * @return number of bytes written
    2.98 + */
    2.99 +static int fd_write(IOStream *s, const void *buf, size_t n){
   2.100 +    FDData *data = fd_data(s);
   2.101 +    int k;
   2.102 +    k = write(data->fd, buf, n);
   2.103 +    return k;
   2.104 +}
   2.105 +
   2.106 +/** Read from the underlying stream;
   2.107 + *
   2.108 + * @param stream input
   2.109 + * @param buf where to put input
   2.110 + * @param n number of bytes to read
   2.111 + * @return number of bytes read
   2.112 + */
   2.113 +static int fd_read(IOStream *s, void *buf, size_t n){
   2.114 +    FDData *data = fd_data(s);
   2.115 +    int k;
   2.116 +    k = read(data->fd, buf, n);
   2.117 +    //printf("> fd_read> buf=%p n=%d --> k=%d\n", buf, n, k);
   2.118 +    return k;
   2.119 +}
   2.120 +
   2.121 +/** Flush the fd (no-op).
   2.122 + *
   2.123 + * @param s fd stream
   2.124 + * @return 0 on success, error code otherwise
   2.125 + */
   2.126 +static int fd_flush(IOStream *s){
   2.127 +    return 0;
   2.128 +}
   2.129 +
   2.130 +/** Check if a fd stream has an error (no-op).
   2.131 + *
   2.132 + * @param s fd stream
   2.133 + * @return 1 if has an error, 0 otherwise
   2.134 + */
   2.135 +static int fd_error(IOStream *s){
   2.136 +    return 0;
   2.137 +}
   2.138 +
   2.139 +/** Close a fd stream.
   2.140 + *
   2.141 + * @param s fd stream to close
   2.142 + * @return result of the close
   2.143 + */
   2.144 +static int fd_close(IOStream *s){
   2.145 +    FDData *data = fd_data(s);
   2.146 +    return close(data->fd);
   2.147 +}
   2.148 +
   2.149 +/** Free a fd stream.
   2.150 + *
   2.151 + * @param s fd stream
   2.152 + */
   2.153 +static void fd_free(IOStream *s){
   2.154 +    FDData *data = fd_data(s);
   2.155 +    deallocate(data);
   2.156 +}
   2.157 +
   2.158 +/** Create an IOStream for a fd.
   2.159 + *
   2.160 + * @param fd fd to wtap
   2.161 + * @return new IOStream using fd for i/o
   2.162 + */
   2.163 +IOStream *fd_stream_new(int fd){
   2.164 +    int err = -ENOMEM;
   2.165 +    IOStream *io = NULL;
   2.166 +    FDData *data = NULL;
   2.167 +
   2.168 +    io = ALLOCATE(IOStream);
   2.169 +    if(!io) goto exit;
   2.170 +    io->methods = &fd_methods;
   2.171 +    data = ALLOCATE(FDData);
   2.172 +    if(!data) goto exit;
   2.173 +    io->data = data;
   2.174 +    data->fd = fd;
   2.175 +    err = 0;
   2.176 +  exit:
   2.177 +    if(err){
   2.178 +        if(io){
   2.179 +            if(data) deallocate(data);
   2.180 +            deallocate(io);
   2.181 +            io = NULL;
   2.182 +        }
   2.183 +    }
   2.184 +    return io;
   2.185 +}
   2.186 +
   2.187 +#endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxutil/fd_stream.h	Fri May 13 15:08:29 2005 +0000
     3.3 @@ -0,0 +1,36 @@
     3.4 +/*
     3.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     3.6 + *
     3.7 + * This library is free software; you can redistribute it and/or modify
     3.8 + * it under the terms of the GNU Lesser General Public License as published by
     3.9 + * the Free Software Foundation; either version 2.1 of the License, or
    3.10 + * (at your option) any later version.
    3.11 + *
    3.12 + * This library is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU Lesser General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU Lesser General Public License
    3.18 + * along with this library; if not, write to the Free Software
    3.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.20 + */
    3.21 +
    3.22 +#ifndef _XMC_FD_STREAM_H_
    3.23 +#define _XMC_FD_STREAM_H_
    3.24 +
    3.25 +#ifndef __KERNEL__
    3.26 +#include "iostream.h"
    3.27 +
    3.28 +/** Data associated with a fd stream. */
    3.29 +typedef struct FDData {
    3.30 +    /** The socket file descriptor. */
    3.31 +    int fd;
    3.32 +} FDData;
    3.33 +
    3.34 +extern IOStream *fd_stream_new(int fd);
    3.35 +extern int fd_stream_data(IOStream *io, FDData **data);
    3.36 +extern int fd_stream_check(IOStream *io);
    3.37 +
    3.38 +#endif
    3.39 +#endif /* !_XMC_FD_STREAM_H_ */
     4.1 --- a/tools/libxutil/lexis.h	Fri May 13 15:01:20 2005 +0000
     4.2 +++ b/tools/libxutil/lexis.h	Fri May 13 15:08:29 2005 +0000
     4.3 @@ -34,7 +34,7 @@
     4.4  #define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
     4.5  
     4.6  /** Class of separator characters. */
     4.7 -#define sep_class "{}()<>[]@!;"
     4.8 +#define sep_class "{}()<>[]!;\"'"
     4.9  
    4.10  #define comment_class "#"
    4.11  
     5.1 --- a/tools/libxutil/sxpr.c	Fri May 13 15:01:20 2005 +0000
     5.2 +++ b/tools/libxutil/sxpr.c	Fri May 13 15:08:29 2005 +0000
     5.3 @@ -28,6 +28,19 @@
     5.4  #include <errno.h>
     5.5  #endif
     5.6  
     5.7 +#ifdef __KERNEL__
     5.8 +#include <linux/random.h>
     5.9 +
    5.10 +int rand(void){
    5.11 +    int v;
    5.12 +    get_random_bytes(&v, sizeof(v));
    5.13 +    return v;
    5.14 +}
    5.15 +
    5.16 +#else
    5.17 +#include <stdlib.h>
    5.18 +#endif
    5.19 +
    5.20  #undef free
    5.21  
    5.22  /** @file
    5.23 @@ -42,41 +55,51 @@
    5.24  static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
    5.25  static int atom_equal(Sxpr x, Sxpr y);
    5.26  static void atom_free(Sxpr obj);
    5.27 +static Sxpr atom_copy(Sxpr obj);
    5.28  
    5.29  static int string_print(IOStream *io, Sxpr obj, unsigned flags);
    5.30  static int string_equal(Sxpr x, Sxpr y);
    5.31  static void string_free(Sxpr obj);
    5.32 +static Sxpr string_copy(Sxpr obj);
    5.33  
    5.34  static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
    5.35  static int cons_equal(Sxpr x, Sxpr y);
    5.36  static void cons_free(Sxpr obj);
    5.37 +static Sxpr cons_copy(Sxpr obj);
    5.38  
    5.39  static int null_print(IOStream *io, Sxpr obj, unsigned flags);
    5.40  static int none_print(IOStream *io, Sxpr obj, unsigned flags);
    5.41  static int int_print(IOStream *io, Sxpr obj, unsigned flags);
    5.42  static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
    5.43 +static int err_print(IOStream *io, Sxpr obj, unsigned flags);
    5.44 +static int nomem_print(IOStream *io, Sxpr obj, unsigned flags);
    5.45  
    5.46  /** Type definitions. */
    5.47  static SxprType types[1024] = {
    5.48 -    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
    5.49 -    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
    5.50 -    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
    5.51 -    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
    5.52 -    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
    5.53 -		   pointer: TRUE,
    5.54 -		   free:    atom_free,
    5.55 -		   equal:   atom_equal,
    5.56 -		 },
    5.57 -    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
    5.58 -		   pointer: TRUE,
    5.59 -		   free:    string_free,
    5.60 -		   equal:   string_equal,
    5.61 -		 },
    5.62 -    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
    5.63 -		   pointer: TRUE,
    5.64 -		   free:    cons_free,
    5.65 -		   equal:   cons_equal,
    5.66 -		 },
    5.67 +    [T_NONE]     { .type=    T_NONE,     .name= "none",       .print= none_print      },
    5.68 +    [T_NULL]     { .type=    T_NULL,     .name= "null",       .print= null_print      },
    5.69 +    [T_UINT]     { .type=    T_UINT,     .name= "int",        .print= int_print,      },
    5.70 +    [T_BOOL]     { .type=    T_BOOL,     .name= "bool",       .print= bool_print,     },
    5.71 +    [T_ERR]      { .type=    T_ERR,      .name= "err",        .print= err_print,      },
    5.72 +    [T_NOMEM]    { .type=    T_ERR,      .name= "nomem",      .print= nomem_print,    },
    5.73 +    [T_ATOM]     { .type=    T_ATOM,     .name= "atom",       .print= atom_print,
    5.74 +                   .pointer= TRUE,
    5.75 +                   .free=    atom_free,
    5.76 +                   .equal=   atom_equal,
    5.77 +                   .copy=    atom_copy,
    5.78 +                 },
    5.79 +    [T_STRING]   { .type=    T_STRING,   .name= "string",     .print= string_print,
    5.80 +                   .pointer= TRUE,
    5.81 +                   .free=    string_free,
    5.82 +                   .equal=   string_equal,
    5.83 +                   .copy=    string_copy,
    5.84 +                 },
    5.85 +    [T_CONS]     { .type=    T_CONS,     .name= "cons",       .print= cons_print,
    5.86 +                   .pointer= TRUE,
    5.87 +                   .free=    cons_free,
    5.88 +                   .equal=   cons_equal,
    5.89 +                   .copy=    cons_copy,
    5.90 +                 },
    5.91  };
    5.92  
    5.93  /** Number of entries in the types array. */
    5.94 @@ -157,12 +180,29 @@ int objprint(IOStream *io, Sxpr x, unsig
    5.95      int k = 0;
    5.96      if(!io) return k;
    5.97      if(flags & PRINT_TYPE){
    5.98 -	k += IOStream_print(io, "%s:", def->name);
    5.99 +        k += IOStream_print(io, "%s:", def->name);
   5.100 +    }
   5.101 +    if(def->pointer && (flags & PRINT_ADDR)){
   5.102 +        k += IOStream_print(io, "<%p>", get_ptr(x));
   5.103      }
   5.104      k += print_fn(io, x, flags);
   5.105      return k;
   5.106  }
   5.107  
   5.108 +Sxpr objcopy(Sxpr x){
   5.109 +    SxprType *def = get_sxpr_type(get_type(x));
   5.110 +    ObjCopyFn *copy_fn = (def ? def->copy : NULL);
   5.111 +    Sxpr v;
   5.112 +    if(copy_fn){
   5.113 +        v = copy_fn(x);
   5.114 +    } else if(def->pointer){
   5.115 +        v = ONOMEM;
   5.116 +    } else {
   5.117 +        v = x;
   5.118 +    }
   5.119 +    return v;
   5.120 +}
   5.121 +
   5.122  /** General sxpr free function.
   5.123   * Frees an sxpr using the free function for its type.
   5.124   * Free functions must recursively free any subsxprs.
   5.125 @@ -176,11 +216,11 @@ void objfree(Sxpr x){
   5.126      SxprType *def = get_sxpr_type(get_type(x));
   5.127  
   5.128      if(def){
   5.129 -	if(def->free){
   5.130 -	    def->free(x);
   5.131 -	} else if (def->pointer){
   5.132 -	    hfree(x);
   5.133 -	}
   5.134 +        if(def->free){
   5.135 +            def->free(x);
   5.136 +        } else if (def->pointer){
   5.137 +            hfree(x);
   5.138 +        }
   5.139      }
   5.140  }
   5.141  
   5.142 @@ -284,9 +324,9 @@ Sxpr cons_member_if(Sxpr l, ObjEqualFn *
   5.143   */
   5.144  int cons_subset(Sxpr s, Sxpr t){
   5.145      for( ; CONSP(t); t = CDR(t)){
   5.146 -	if(!CONSP(cons_member(s, CAR(t)))){
   5.147 -	    return 0;
   5.148 -	}
   5.149 +        if(!CONSP(cons_member(s, CAR(t)))){
   5.150 +            return 0;
   5.151 +        }
   5.152      }
   5.153      return 1;
   5.154  }
   5.155 @@ -365,18 +405,27 @@ Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
   5.156  #endif /* USE_GC */
   5.157  
   5.158  /** Create a new atom with the given name.
   5.159 + * Makes an integer sxpr if the name can be parsed as an int.
   5.160   *
   5.161   * @param name the name
   5.162   * @return new atom
   5.163   */
   5.164  Sxpr atom_new(char *name){
   5.165      Sxpr n, obj = ONOMEM;
   5.166 +    long v;
   5.167  
   5.168 -    n = string_new(name);
   5.169 -    if(NOMEMP(n)) goto exit;
   5.170 -    obj = HALLOC(ObjAtom, T_ATOM);
   5.171 -    if(NOMEMP(obj)) goto exit;
   5.172 -    OBJ_ATOM(obj)->name = n;
   5.173 +    if(convert_atol(name, &v) == 0){
   5.174 +        obj = OINT(v);
   5.175 +    } else {
   5.176 +        n = string_new(name);
   5.177 +        if(NOMEMP(n)) goto exit;
   5.178 +        obj = HALLOC(ObjAtom, T_ATOM);
   5.179 +        if(NOMEMP(obj)){
   5.180 +            string_free(n);
   5.181 +            goto exit;
   5.182 +        }
   5.183 +        OBJ_ATOM(obj)->name = n;
   5.184 +    }
   5.185    exit:
   5.186      return obj;
   5.187  }
   5.188 @@ -392,6 +441,20 @@ void atom_free(Sxpr obj){
   5.189      hfree(obj);
   5.190  }
   5.191  
   5.192 +/** Copy an atom.
   5.193 + *
   5.194 + * @param obj to copy
   5.195 + */
   5.196 +Sxpr atom_copy(Sxpr obj){
   5.197 +    Sxpr v;
   5.198 +    if(OBJ_ATOM(obj)->interned){
   5.199 +        v = obj;
   5.200 +    } else {
   5.201 +        v = atom_new(atom_name(obj));
   5.202 +    }
   5.203 +    return v;
   5.204 +}
   5.205 +
   5.206  /** Print an atom. Prints the atom name.
   5.207   *
   5.208   * @param io stream to print to
   5.209 @@ -400,8 +463,7 @@ void atom_free(Sxpr obj){
   5.210   * @return number of bytes printed
   5.211   */
   5.212  int atom_print(IOStream *io, Sxpr obj, unsigned flags){
   5.213 -    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
   5.214 -    return string_print(io, OBJ_ATOM(obj)->name, flags);
   5.215 +    return objprint(io, OBJ_ATOM(obj)->name, flags);
   5.216  }
   5.217  
   5.218  /** Atom equality.
   5.219 @@ -430,13 +492,17 @@ char * atom_name(Sxpr obj){
   5.220      return string_string(OBJ_ATOM(obj)->name);
   5.221  }
   5.222  
   5.223 +int atom_length(Sxpr obj){
   5.224 +    return string_length(OBJ_ATOM(obj)->name);
   5.225 +}
   5.226 +
   5.227  /** Get the C string from a string sxpr.
   5.228   *
   5.229   * @param obj string sxpr
   5.230   * @return string
   5.231   */
   5.232  char * string_string(Sxpr obj){
   5.233 -    return OBJ_STRING(obj);
   5.234 +    return OBJ_STRING(obj)->data;
   5.235  }
   5.236  
   5.237  /** Get the length of a string.
   5.238 @@ -445,7 +511,7 @@ char * string_string(Sxpr obj){
   5.239   * @return length
   5.240   */
   5.241  int string_length(Sxpr obj){
   5.242 -    return strlen(OBJ_STRING(obj));
   5.243 +    return OBJ_STRING(obj)->len;
   5.244  }
   5.245  
   5.246  /** Create a new string. The input string is copied,
   5.247 @@ -456,12 +522,28 @@ int string_length(Sxpr obj){
   5.248   */
   5.249  Sxpr string_new(char *s){
   5.250      int n = (s ? strlen(s) : 0);
   5.251 +    return string_new_n(s, n);
   5.252 +}
   5.253 +
   5.254 +/** Create a new string. The input string is copied,
   5.255 + * and need not be null-terminated.
   5.256 + *
   5.257 + * @param s characters to put in the string (may be null)
   5.258 + * @param n string length
   5.259 + * @return new sxpr
   5.260 + */
   5.261 +Sxpr string_new_n(char *s, int n){
   5.262      Sxpr obj;
   5.263 -    obj = halloc(n+1, T_STRING);
   5.264 +    obj = halloc(sizeof(ObjString) + n + 1, T_STRING);
   5.265      if(!NOMEMP(obj)){
   5.266 -        char *str = OBJ_STRING(obj);
   5.267 -        strncpy(str, s, n);
   5.268 -        str[n] = '\0';
   5.269 +        char *str = OBJ_STRING(obj)->data;
   5.270 +        OBJ_STRING(obj)->len = n;
   5.271 +        if(s){
   5.272 +            memcpy(str, s, n);
   5.273 +            str[n] = '\0';
   5.274 +        } else {
   5.275 +            memset(str, 0, n + 1);
   5.276 +        }
   5.277      }
   5.278      return obj;
   5.279  }
   5.280 @@ -474,70 +556,180 @@ void string_free(Sxpr obj){
   5.281      hfree(obj);
   5.282  }
   5.283  
   5.284 +/** Copy a string.
   5.285 + *
   5.286 + * @param obj to copy
   5.287 + */
   5.288 +Sxpr string_copy(Sxpr obj){
   5.289 +    return string_new_n(string_string(obj), string_length(obj));
   5.290 +}
   5.291 +
   5.292  /** Determine if a string needs escapes when printed
   5.293   * using the given flags.
   5.294   *
   5.295   * @param str string to check
   5.296 + * @param n string length
   5.297   * @param flags print flags
   5.298   * @return 1 if needs escapes, 0 otherwise
   5.299   */
   5.300 -int needs_escapes(char *str, unsigned flags){
   5.301 +int needs_escapes(char *str, int n, unsigned flags){
   5.302      char *c;
   5.303 +    int i;
   5.304      int val = 0;
   5.305  
   5.306      if(str){
   5.307 -	for(c=str; *c; c++){
   5.308 -	    if(in_alpha_class(*c)) continue;
   5.309 -	    if(in_decimal_digit_class(*c)) continue;
   5.310 -	    if(in_class(*c, "/._+:@~-")) continue;
   5.311 -	    val = 1;
   5.312 -	    break;
   5.313 -	}
   5.314 +        for(i=0, c=str; i<n; i++, c++){
   5.315 +            if(in_alpha_class(*c)) continue;
   5.316 +            if(in_decimal_digit_class(*c)) continue;
   5.317 +            if(in_class(*c, "/._+:@~-")) continue;
   5.318 +            val = 1;
   5.319 +            break;
   5.320 +        }
   5.321 +    }
   5.322 +    return val;
   5.323 +}
   5.324 +
   5.325 +char randchar(void){
   5.326 +    int r;
   5.327 +    char c;
   5.328 +    for( ; ; ){
   5.329 +        r = rand();
   5.330 +        c = (r >> 16) & 0xff;
   5.331 +        if('a' <= c && c <= 'z') break;
   5.332 +    }
   5.333 +    return c;
   5.334 +}
   5.335 +
   5.336 +int string_contains(char *s, int s_n, char *k, int k_n){
   5.337 +    int i, n = s_n - k_n;
   5.338 +    for(i=0; i < n; i++){
   5.339 +        if(!memcmp(s+i, k, k_n)) return 1;
   5.340 +    }
   5.341 +    return 0;
   5.342 +}
   5.343 +
   5.344 +int string_delim(char *s, int s_n, char *d, int d_n){
   5.345 +    int i;
   5.346 +    if(d_n < 4) return -1;
   5.347 +    memset(d, 0, d_n+1);
   5.348 +    for(i=0; i<3; i++){
   5.349 +        d[i] = randchar();
   5.350 +    }
   5.351 +    for( ; i < d_n; i++){
   5.352 +        if(!string_contains(s, s_n, d, i)){
   5.353 +            return i;
   5.354 +        }
   5.355 +        d[i] = randchar();
   5.356      }
   5.357 -    //printf("\n> val=%d str=|%s|\n", val, str);
   5.358 -    return val;
   5.359 +    return -1;
   5.360 +}
   5.361 +
   5.362 +/** Print the bytes in a string as-is.
   5.363 + *
   5.364 + * @param io stream
   5.365 + * @param str string
   5.366 + * @param n length
   5.367 + * @return bytes written or error code
   5.368 + */
   5.369 +int _string_print_raw(IOStream *io, char *str, int n){
   5.370 +    int k = 0;
   5.371 +    k = IOStream_write(io, str, n);
   5.372 +    return k;
   5.373 +}
   5.374 +
   5.375 +/** Print a string in counted data format.
   5.376 + *
   5.377 + * @param io stream
   5.378 + * @param str string
   5.379 + * @param n length
   5.380 + * @return bytes written or error code
   5.381 + */
   5.382 +int _string_print_counted(IOStream *io, char *str, int n){
   5.383 +    int k = 0;
   5.384 +    k += IOStream_print(io, "%c%c%d%c",
   5.385 +                        c_data_open, c_data_count, n, c_data_count);
   5.386 +    k += IOStream_write(io, str, n);
   5.387 +    return k;
   5.388 +}
   5.389 +  
   5.390 +/** Print a string in quoted data format.
   5.391 + *
   5.392 + * @param io stream
   5.393 + * @param str string
   5.394 + * @param n length
   5.395 + * @return bytes written or error code
   5.396 + */
   5.397 +int _string_print_quoted(IOStream *io, char *str, int n){
   5.398 +    int k = 0;
   5.399 +    char d[10];
   5.400 +    int d_n;
   5.401 +    d_n = string_delim(str, n, d, sizeof(d) - 1);
   5.402 +    k += IOStream_print(io, "%c%c%s%c",
   5.403 +                        c_data_open, c_data_quote, d, c_data_quote);
   5.404 +    k += IOStream_write(io, str, n);
   5.405 +    k += IOStream_print(io, "%c%s%c", c_data_quote, d, c_data_quote);
   5.406 +    return k;
   5.407 +}
   5.408 +
   5.409 +/** Print a string as a quoted string.
   5.410 + *
   5.411 + * @param io stream
   5.412 + * @param str string
   5.413 + * @param n length
   5.414 + * @return bytes written or error code
   5.415 + */
   5.416 +int _string_print_string(IOStream *io, char *str, int n){
   5.417 +    int k = 0;
   5.418 +    
   5.419 +    k += IOStream_print(io, "\"");
   5.420 +    if(str){
   5.421 +        char *s, *t;
   5.422 +        for(s = str, t = str + n; s < t; s++){
   5.423 +            if(*s < ' ' || *s >= 127 ){
   5.424 +                switch(*s){
   5.425 +                case '\a': k += IOStream_print(io, "\\a");  break;
   5.426 +                case '\b': k += IOStream_print(io, "\\b");  break;
   5.427 +                case '\f': k += IOStream_print(io, "\\f");  break;
   5.428 +                case '\n': k += IOStream_print(io, "\\n");  break;
   5.429 +                case '\r': k += IOStream_print(io, "\\r");  break;
   5.430 +                case '\t': k += IOStream_print(io, "\\t");  break;
   5.431 +                case '\v': k += IOStream_print(io, "\\v");  break;
   5.432 +                default:
   5.433 +                    // Octal escape;
   5.434 +                    k += IOStream_print(io, "\\%o", *s);
   5.435 +                    break;
   5.436 +                }
   5.437 +            } else if(*s == c_double_quote ||
   5.438 +                      *s == c_single_quote ||
   5.439 +                      *s == c_escape){
   5.440 +                k += IOStream_print(io, "\\%c", *s);
   5.441 +            } else {
   5.442 +                k+= IOStream_print(io, "%c", *s);
   5.443 +            }
   5.444 +        }
   5.445 +    }
   5.446 +    k += IOStream_print(io, "\"");
   5.447 +    return k;
   5.448  }
   5.449  
   5.450  /** Print a string to a stream, with escapes if necessary.
   5.451   *
   5.452   * @param io stream to print to
   5.453   * @param str string
   5.454 + * @param n string length
   5.455   * @param flags print flags
   5.456   * @return number of bytes written
   5.457   */
   5.458 -int _string_print(IOStream *io, char *str, unsigned flags){
   5.459 +int _string_print(IOStream *io, char *str, int n, unsigned flags){
   5.460      int k = 0;
   5.461 -    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
   5.462 -        k += IOStream_print(io, str);
   5.463 +    if((flags & PRINT_COUNTED)){
   5.464 +        k = _string_print_counted(io, str, n);
   5.465 +    } else if((flags & PRINT_RAW) || !needs_escapes(str, n, flags)){
   5.466 +        k = _string_print_raw(io, str, n);
   5.467 +    } else if(n > 50){
   5.468 +        k = _string_print_quoted(io, str, n);
   5.469      } else {
   5.470 -	k += IOStream_print(io, "\"");
   5.471 -	if(str){
   5.472 -            char *s;
   5.473 -            for(s = str; *s; s++){
   5.474 -                if(*s < ' ' || *s >= 127 ){
   5.475 -                    switch(*s){
   5.476 -                    case '\a': k += IOStream_print(io, "\\a");  break;
   5.477 -                    case '\b': k += IOStream_print(io, "\\b");  break;
   5.478 -                    case '\f': k += IOStream_print(io, "\\f");  break;
   5.479 -                    case '\n': k += IOStream_print(io, "\\n");  break;
   5.480 -                    case '\r': k += IOStream_print(io, "\\r");  break;
   5.481 -                    case '\t': k += IOStream_print(io, "\\t");  break;
   5.482 -                    case '\v': k += IOStream_print(io, "\\v");  break;
   5.483 -                    default:
   5.484 -                        // Octal escape;
   5.485 -                        k += IOStream_print(io, "\\%o", *s);
   5.486 -                        break;
   5.487 -                    }
   5.488 -                } else if(*s == c_double_quote ||
   5.489 -                          *s == c_single_quote ||
   5.490 -                          *s == c_escape){
   5.491 -                    k += IOStream_print(io, "\\%c", *s);
   5.492 -                } else {
   5.493 -                    k+= IOStream_print(io, "%c", *s);
   5.494 -                }
   5.495 -            }
   5.496 -	}
   5.497 -	k += IOStream_print(io, "\"");
   5.498 +        k = _string_print_string(io, str, n);
   5.499      }
   5.500      return k;
   5.501  }
   5.502 @@ -550,7 +742,14 @@ int _string_print(IOStream *io, char *st
   5.503   * @return number of bytes written
   5.504   */
   5.505  int string_print(IOStream *io, Sxpr obj, unsigned flags){
   5.506 -    return _string_print(io, OBJ_STRING(obj), flags);
   5.507 +    return _string_print(io,
   5.508 +                         OBJ_STRING(obj)->data,
   5.509 +                         OBJ_STRING(obj)->len,
   5.510 +                         flags);
   5.511 +}
   5.512 +
   5.513 +int string_eq(char *s, int s_n, char *t, int t_n){
   5.514 +    return (s_n == t_n) && (memcmp(s, t, s_n) == 0);
   5.515  }
   5.516  
   5.517  /** Compare an sxpr with a string for equality.
   5.518 @@ -563,9 +762,13 @@ int string_equal(Sxpr x, Sxpr y){
   5.519      int ok = 0;
   5.520      ok = eq(x,y);
   5.521      if(ok) goto exit;
   5.522 -    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
   5.523 +    ok = has_type(y, T_STRING) &&
   5.524 +        string_eq(OBJ_STRING(x)->data, OBJ_STRING(x)->len,
   5.525 +                  OBJ_STRING(y)->data, OBJ_STRING(y)->len);
   5.526      if(ok) goto exit;
   5.527 -    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
   5.528 +    ok = has_type(y, T_ATOM) &&
   5.529 +        string_eq(OBJ_STRING(x)->data, OBJ_STRING(x)->len,
   5.530 +                  atom_name(y), atom_length(y));
   5.531    exit:
   5.532      return ok;
   5.533  }
   5.534 @@ -613,15 +816,38 @@ int cons_push(Sxpr *list, Sxpr elt){
   5.535  void cons_free(Sxpr obj){
   5.536      Sxpr next;
   5.537      for(; CONSP(obj); obj = next){
   5.538 -	next = CDR(obj);
   5.539 -	objfree(CAR(obj));
   5.540 -	hfree(obj);
   5.541 +        next = CDR(obj);
   5.542 +        objfree(CAR(obj));
   5.543 +        hfree(obj);
   5.544      }
   5.545      if(!NULLP(obj)){
   5.546 -	objfree(obj);
   5.547 +        objfree(obj);
   5.548      }
   5.549  }
   5.550  
   5.551 +/** Copy a cons. Recursively copies the car and cdr.
   5.552 + *
   5.553 + * @param obj to copy
   5.554 + */
   5.555 +Sxpr cons_copy(Sxpr obj){
   5.556 +    Sxpr v = ONULL;
   5.557 +    Sxpr l = ONULL, x = ONONE;
   5.558 +    for(l = obj; CONSP(l); l = CDR(l)){
   5.559 +        x = objcopy(CAR(l));
   5.560 +        if(NOMEMP(x)) goto exit;
   5.561 +        x = cons_new(x, v);
   5.562 +        if(NOMEMP(x)) goto exit;
   5.563 +        v = x;
   5.564 +    }
   5.565 +    v = nrev(v);
   5.566 +  exit:
   5.567 +    if(NOMEMP(x)){
   5.568 +        objfree(v);
   5.569 +        v = ONOMEM;
   5.570 +    }
   5.571 +    return v;
   5.572 +}
   5.573 +
   5.574  /** Free a cons and its cdr cells, but not the car sxprs.
   5.575   * Does nothing if called on something that is not a cons.
   5.576   *
   5.577 @@ -630,8 +856,8 @@ void cons_free(Sxpr obj){
   5.578  void cons_free_cells(Sxpr obj){
   5.579      Sxpr next;
   5.580      for(; CONSP(obj); obj = next){
   5.581 -	next = CDR(obj);
   5.582 -	hfree(obj);
   5.583 +        next = CDR(obj);
   5.584 +        hfree(obj);
   5.585      }
   5.586  }
   5.587  
   5.588 @@ -698,26 +924,26 @@ int cons_length(Sxpr obj){
   5.589   */
   5.590  Sxpr nrev(Sxpr l){
   5.591      if(CONSP(l)){
   5.592 -	// Iterate down the cells in the list making the cdr of
   5.593 -	// each cell point to the previous cell. The last cell 
   5.594 -	// is the head of the reversed list.
   5.595 -	Sxpr prev = ONULL;
   5.596 -	Sxpr cell = l;
   5.597 -	Sxpr next;
   5.598 +        // Iterate down the cells in the list making the cdr of
   5.599 +        // each cell point to the previous cell. The last cell 
   5.600 +        // is the head of the reversed list.
   5.601 +        Sxpr prev = ONULL;
   5.602 +        Sxpr cell = l;
   5.603 +        Sxpr next;
   5.604  
   5.605 -	while(1){
   5.606 -	    next = CDR(cell);
   5.607 -	    CDR(cell) = prev;
   5.608 -	    if(!CONSP(next)) break;
   5.609 -	    prev = cell;
   5.610 -	    cell = next;
   5.611 -	}
   5.612 -	l = cell;
   5.613 +        while(1){
   5.614 +            next = CDR(cell);
   5.615 +            CDR(cell) = prev;
   5.616 +            if(!CONSP(next)) break;
   5.617 +            prev = cell;
   5.618 +            cell = next;
   5.619 +        }
   5.620 +        l = cell;
   5.621      }
   5.622      return l;
   5.623  }
   5.624  
   5.625 -/** Print the null sxpr.	
   5.626 +/** Print the null sxpr.        
   5.627   *
   5.628   * @param io stream to print to
   5.629   * @param obj to print
   5.630 @@ -761,6 +987,30 @@ static int bool_print(IOStream *io, Sxpr
   5.631      return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
   5.632  }
   5.633  
   5.634 +/** Print an error.
   5.635 + *
   5.636 + * @param io stream to print to
   5.637 + * @param obj to print
   5.638 + * @param flags print flags
   5.639 + * @return number of bytes written
   5.640 + */
   5.641 +static int err_print(IOStream *io, Sxpr obj, unsigned flags){
   5.642 +    int err = OBJ_INT(obj);
   5.643 +    if(err < 0) err = -err;
   5.644 +    return IOStream_print(io, "[error:%d:%s]", err, strerror(err));
   5.645 +}
   5.646 +
   5.647 +/** Print the 'nomem' sxpr.
   5.648 + *
   5.649 + * @param io stream to print to
   5.650 + * @param obj to print
   5.651 + * @param flags print flags
   5.652 + * @return number of bytes written
   5.653 + */
   5.654 +static int nomem_print(IOStream *io, Sxpr obj, unsigned flags){
   5.655 +    return IOStream_print(io, "[ENOMEM]");
   5.656 +}
   5.657 +
   5.658  int sxprp(Sxpr obj, Sxpr name){
   5.659      return CONSP(obj) && objequal(CAR(obj), name);
   5.660  }
   5.661 @@ -781,8 +1031,8 @@ Sxpr sxpr_name(Sxpr obj){
   5.662  }
   5.663  
   5.664  int sxpr_is(Sxpr obj, char *s){
   5.665 -    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
   5.666 -    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
   5.667 +    if(ATOMP(obj)) return string_eq(atom_name(obj), atom_length(obj), s, strlen(s));
   5.668 +    if(STRINGP(obj)) return string_eq(string_string(obj), string_length(obj), s, strlen(s));
   5.669      return 0;
   5.670  }
   5.671  
   5.672 @@ -915,11 +1165,11 @@ static int sym_equal_fn(void *x, void *y
   5.673   */
   5.674  static void sym_free_fn(HashTable *table, HTEntry *entry){
   5.675      if(entry){
   5.676 -	objfree(((ObjAtom*)entry->value)->name);
   5.677 -	HTEntry_free(entry);
   5.678 +        objfree(((ObjAtom*)entry->value)->name);
   5.679 +        HTEntry_free(entry);
   5.680      }
   5.681  }
   5.682 -	
   5.683 +        
   5.684  /** Initialize the symbol table.
   5.685   *
   5.686   * @return 0 on sucess, error code otherwise
   5.687 @@ -929,7 +1179,7 @@ static int init_symbols(void){
   5.688      if(symbols){
   5.689          symbols->key_hash_fn = sym_hash_fn;
   5.690          symbols->key_equal_fn = sym_equal_fn;
   5.691 -	symbols->entry_free_fn = sym_free_fn;
   5.692 +        symbols->entry_free_fn = sym_free_fn;
   5.693          return 0;
   5.694      }
   5.695      return -1;
   5.696 @@ -950,8 +1200,8 @@ void cleanup_symbols(void){
   5.697  Sxpr get_symbol(char *sym){
   5.698      HTEntry *entry;
   5.699      if(!symbols){
   5.700 -	if(init_symbols()) return ONOMEM;
   5.701 -	return ONULL;
   5.702 +        if(init_symbols()) return ONOMEM;
   5.703 +        return ONULL;
   5.704      }
   5.705      entry = HashTable_get_entry(symbols, sym);
   5.706      if(entry){
   5.707 @@ -969,10 +1219,10 @@ Sxpr get_symbol(char *sym){
   5.708  Sxpr intern(char *sym){
   5.709      Sxpr symbol = get_symbol(sym);
   5.710      if(NULLP(symbol)){
   5.711 -	if(!symbols) return ONOMEM;
   5.712 +        if(!symbols) return ONOMEM;
   5.713          symbol = atom_new(sym);
   5.714          if(!NOMEMP(symbol)){
   5.715 -	    OBJ_ATOM(symbol)->interned = TRUE;
   5.716 +            OBJ_ATOM(symbol)->interned = TRUE;
   5.717              HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
   5.718          }
   5.719      }
     6.1 --- a/tools/libxutil/sxpr.h	Fri May 13 15:01:20 2005 +0000
     6.2 +++ b/tools/libxutil/sxpr.h	Fri May 13 15:08:29 2005 +0000
     6.3 @@ -52,142 +52,13 @@ typedef struct Sxpr {
     6.4      /** Sxpr type. */
     6.5      TypeCode type;
     6.6      union {
     6.7 -	/** Sxpr value. */
     6.8 +        /** Sxpr value. */
     6.9          unsigned long ul;
    6.10 -	/** Pointer. */
    6.11 +        /** Pointer. */
    6.12          void *ptr;
    6.13      } v;
    6.14  } Sxpr;
    6.15  
    6.16 -/** Sxpr type to indicate out of memory. */
    6.17 -#define T_NOMEM      ((TypeCode)-1)
    6.18 -/** The 'unspecified' sxpr. */
    6.19 -#define T_NONE       ((TypeCode)0)
    6.20 -/** The empty list. */
    6.21 -#define T_NULL       ((TypeCode)1)
    6.22 -/** Unsigned integer. */
    6.23 -#define T_UINT       ((TypeCode)2)
    6.24 -/** A string. */
    6.25 -#define T_STRING     ((TypeCode)3)
    6.26 -/** An atom. */
    6.27 -#define T_ATOM       ((TypeCode)4)
    6.28 -/** A boolean. */
    6.29 -#define T_BOOL       ((TypeCode)5)
    6.30 -
    6.31 -/** A cons (pair or list). */
    6.32 -#define T_CONS       ((TypeCode)10)
    6.33 -
    6.34 -/** An error. */
    6.35 -#define T_ERR        ((TypeCode)40)
    6.36 -
    6.37 -/** An atom. */
    6.38 -typedef struct ObjAtom {
    6.39 -    Sxpr name;
    6.40 -    Hashcode hashcode;
    6.41 -    int interned;
    6.42 -} ObjAtom;
    6.43 -
    6.44 -/** A cons (pair). */
    6.45 -typedef struct ObjCons {
    6.46 -    Sxpr car;
    6.47 -    Sxpr cdr;
    6.48 -} ObjCons;
    6.49 -
    6.50 -/** A vector. */
    6.51 -typedef struct ObjVector {
    6.52 -    int n;
    6.53 -    Sxpr data[0];
    6.54 -} ObjVector;
    6.55 -
    6.56 -/** Flags for sxpr printing. */
    6.57 -enum PrintFlags {
    6.58 -    PRINT_RAW           = 0x001,
    6.59 -    PRINT_TYPE          = 0x002,
    6.60 -    PRINT_PRETTY        = 0x004,
    6.61 -    PRINT_NUM           = 0x008,
    6.62 -};
    6.63 -
    6.64 -/** An integer sxpr.
    6.65 - *
    6.66 - * @param ty type
    6.67 - * @param val integer value
    6.68 - */
    6.69 -#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
    6.70 -
    6.71 -/** A pointer sxpr.
    6.72 - * If the pointer is non-null, returns an sxpr containing it.
    6.73 - * If the pointer is null, returns ONOMEM.
    6.74 - *
    6.75 - * @param ty type
    6.76 - * @param val pointer
    6.77 - */
    6.78 -#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
    6.79 -
    6.80 -/** Make an integer sxpr containing a pointer.
    6.81 - *
    6.82 - * @param val pointer
    6.83 - */
    6.84 -#define PTR(val) OBJP(T_UINT, (void*)(val))
    6.85 -
    6.86 -/** Make an integer sxpr.
    6.87 - * @param x value
    6.88 - */
    6.89 -#define OINT(x)       OBJI(T_UINT,  x)
    6.90 -
    6.91 -/** Make an error sxpr.
    6.92 - *
    6.93 - * @param x value
    6.94 - */
    6.95 -#define OERR(x)       OBJI(T_ERR,   x)
    6.96 -
    6.97 -/** Out of memory constant. */
    6.98 -#define ONOMEM        OBJI(T_NOMEM, 0)
    6.99 -
   6.100 -/** The `unspecified' constant. */
   6.101 -#define ONONE         OBJI(T_NONE,  0)
   6.102 -
   6.103 -/** Empty list constant. */
   6.104 -#define ONULL         OBJI(T_NULL,  0)
   6.105 -
   6.106 -/** False constant. */
   6.107 -#define OFALSE        OBJI(T_BOOL,  0)
   6.108 -
   6.109 -/** True constant. */
   6.110 -#define OTRUE         OBJI(T_BOOL,  1)
   6.111 -
   6.112 -/* Recognizers for the various sxpr types.  */
   6.113 -#define ATOMP(obj)        has_type(obj, T_ATOM)
   6.114 -#define BOOLP(obj)        has_type(obj, T_BOOL)
   6.115 -#define CONSP(obj)        has_type(obj, T_CONS)
   6.116 -#define ERRP(obj)         has_type(obj, T_ERR)
   6.117 -#define INTP(obj)         has_type(obj, T_UINT)
   6.118 -#define NOMEMP(obj)       has_type(obj, T_NOMEM)
   6.119 -#define NONEP(obj)        has_type(obj, T_NONE)
   6.120 -#define NULLP(obj)        has_type(obj, T_NULL)
   6.121 -#define STRINGP(obj)      has_type(obj, T_STRING)
   6.122 -
   6.123 -#define TRUEP(obj)    get_ul(obj)
   6.124 -
   6.125 -/** Convert an sxpr to an unsigned integer. */
   6.126 -#define OBJ_UINT(x)   get_ul(x)
   6.127 -/** Convert an sxpr to an integer. */
   6.128 -#define OBJ_INT(x)    (int)get_ul(x)
   6.129 -
   6.130 -/* Conversions of sxprs to their values.
   6.131 - * No checking is done.
   6.132 - */
   6.133 -#define OBJ_STRING(x)  ((char*)get_ptr(x))
   6.134 -#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
   6.135 -#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
   6.136 -#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
   6.137 -#define CAR(x)         (OBJ_CONS(x)->car)
   6.138 -#define CDR(x)         (OBJ_CONS(x)->cdr)
   6.139 -
   6.140 -#define CAAR(x)        (CAR(CAR(x)))
   6.141 -#define CADR(x)        (CAR(CDR(x)))
   6.142 -#define CDAR(x)        (CDR(CAR(x)))
   6.143 -#define CDDR(x)        (CDR(CDR(x)))
   6.144 -
   6.145  /** Get the integer value from an sxpr.
   6.146   *
   6.147   * @param obj sxpr
   6.148 @@ -208,22 +79,22 @@ static inline void * get_ptr(Sxpr obj){
   6.149  
   6.150  /** Create an sxpr containing a pointer.
   6.151   *
   6.152 - * @param type typecode
   6.153 + * @param ty typecode
   6.154   * @param val pointer
   6.155   * @return sxpr
   6.156   */
   6.157 -static inline Sxpr obj_ptr(TypeCode type, void *val){
   6.158 -    return (Sxpr){ type: type, v: { ptr: val } };
   6.159 +static inline Sxpr obj_ptr(TypeCode ty, void *val){
   6.160 +    return (Sxpr){ .type= ty, .v= { .ptr= val } };
   6.161  }
   6.162  
   6.163  /** Create an sxpr containing an integer.
   6.164   *
   6.165 - * @param type typecode
   6.166 + * @param ty typecode
   6.167   * @param val integer
   6.168   * @return sxpr
   6.169   */
   6.170 -static inline Sxpr obj_ul(TypeCode type, unsigned long val){
   6.171 -    return (Sxpr){ type: type, v: { ul: val } };
   6.172 +static inline Sxpr obj_ul(TypeCode ty, unsigned long val){
   6.173 +    return (Sxpr){ .type= ty, .v= { .ul= val } };
   6.174  }
   6.175  
   6.176  /** Get the type of an sxpr.
   6.177 @@ -255,6 +126,160 @@ static inline int eq(Sxpr x, Sxpr y){
   6.178      return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
   6.179  }
   6.180  
   6.181 +/** The 'unspecified' sxpr. */
   6.182 +#define T_NONE       ((TypeCode)0)
   6.183 +/** The empty list. */
   6.184 +#define T_NULL       ((TypeCode)1)
   6.185 +/** Unsigned integer. */
   6.186 +#define T_UINT       ((TypeCode)2)
   6.187 +/** A string. */
   6.188 +#define T_STRING     ((TypeCode)3)
   6.189 +/** An atom. */
   6.190 +#define T_ATOM       ((TypeCode)4)
   6.191 +/** A boolean. */
   6.192 +#define T_BOOL       ((TypeCode)5)
   6.193 +
   6.194 +/** A cons (pair or list). */
   6.195 +#define T_CONS       ((TypeCode)10)
   6.196 +
   6.197 +/** An error. */
   6.198 +#define T_ERR        ((TypeCode)40)
   6.199 +/** Sxpr type to indicate out of memory. */
   6.200 +#define T_NOMEM      ((TypeCode)41)
   6.201 +
   6.202 +typedef struct ObjString {
   6.203 +    int len;
   6.204 +    char data[];
   6.205 +} ObjString;
   6.206 +
   6.207 +/** An atom. */
   6.208 +typedef struct ObjAtom {
   6.209 +    Sxpr name;
   6.210 +    Hashcode hashcode;
   6.211 +    int interned;
   6.212 +} ObjAtom;
   6.213 +
   6.214 +/** A cons (pair). */
   6.215 +typedef struct ObjCons {
   6.216 +    Sxpr car;
   6.217 +    Sxpr cdr;
   6.218 +} ObjCons;
   6.219 +
   6.220 +/** Flags for sxpr printing. */
   6.221 +enum PrintFlags {
   6.222 +    PRINT_RAW           = 0x001,
   6.223 +    PRINT_TYPE          = 0x002,
   6.224 +    PRINT_PRETTY        = 0x004,
   6.225 +    PRINT_COUNTED       = 0x008,
   6.226 +    PRINT_ADDR          = 0x010,
   6.227 +};
   6.228 +
   6.229 +extern int _string_print(IOStream *io, char *str, int n, unsigned flags);
   6.230 +extern int _string_print_raw(IOStream *io, char *str, int n);
   6.231 +extern int _string_print_counted(IOStream *io, char *str, int n);
   6.232 +extern int _string_print_quoted(IOStream *io, char *str, int n);
   6.233 +extern int _string_print_string(IOStream *io, char *str, int n);
   6.234 +
   6.235 +/** An integer sxpr.
   6.236 + *
   6.237 + * @param ty type
   6.238 + * @param val integer value
   6.239 + */
   6.240 +#define OBJI(ty, val) obj_ul(ty, val)
   6.241 +
   6.242 +/** Make an integer sxpr.
   6.243 + * @param x value
   6.244 + */
   6.245 +#define OINT(x)       OBJI(T_UINT,  x)
   6.246 +
   6.247 +/** Make an error sxpr.
   6.248 + *
   6.249 + * @param x value
   6.250 + */
   6.251 +#define OERR(x)       OBJI(T_ERR,   x)
   6.252 +
   6.253 +/** Out of memory constant. */
   6.254 +#define ONOMEM        OBJI(T_NOMEM, 0)
   6.255 +
   6.256 +/** The `unspecified' constant. */
   6.257 +#define ONONE         OBJI(T_NONE,  0)
   6.258 +
   6.259 +/** Empty list constant. */
   6.260 +#define ONULL         OBJI(T_NULL,  0)
   6.261 +
   6.262 +/** False constant. */
   6.263 +#define OFALSE        OBJI(T_BOOL,  0)
   6.264 +
   6.265 +/** True constant. */
   6.266 +#define OTRUE         OBJI(T_BOOL,  1)
   6.267 +
   6.268 +/** A pointer sxpr.
   6.269 + * If the pointer is non-null, returns an sxpr containing it.
   6.270 + * If the pointer is null, returns ONOMEM.
   6.271 + *
   6.272 + * @param ty type
   6.273 + * @param val pointer
   6.274 + */
   6.275 +static inline Sxpr OBJP(int ty, void *val){
   6.276 +    return (val ? obj_ptr(ty, val) : ONOMEM);
   6.277 +}
   6.278 +
   6.279 +/** Make an integer sxpr containing a pointer.
   6.280 + *
   6.281 + * @param val pointer
   6.282 + */
   6.283 +#define PTR(val) OBJP(T_UINT, (void*)(val))
   6.284 +
   6.285 +/** Allocate some memory and return an sxpr containing it.
   6.286 + * Returns ONOMEM if allocation failed.
   6.287 + *
   6.288 + * @param n number of bytes to allocate
   6.289 + * @param ty typecode
   6.290 + * @return sxpr
   6.291 + */
   6.292 +#define halloc(_n, _ty) OBJP(_ty, allocate(_n))
   6.293 +
   6.294 +/** Allocate an sxpr containing a pointer to the given type.
   6.295 + *
   6.296 + * @param _ctype type (uses sizeof to determine how many bytes to allocate)
   6.297 + * @param _tycode typecode
   6.298 + * @return sxpr, ONOMEM if allocation failed
   6.299 + */
   6.300 +#define HALLOC(_ctype, _tycode) halloc(sizeof(_ctype), _tycode)
   6.301 +
   6.302 +/* Recognizers for the various sxpr types.  */
   6.303 +#define ATOMP(obj)        has_type(obj, T_ATOM)
   6.304 +#define BOOLP(obj)        has_type(obj, T_BOOL)
   6.305 +#define CONSP(obj)        has_type(obj, T_CONS)
   6.306 +#define ERRP(obj)         has_type(obj, T_ERR)
   6.307 +#define INTP(obj)         has_type(obj, T_UINT)
   6.308 +#define NOMEMP(obj)       has_type(obj, T_NOMEM)
   6.309 +#define NONEP(obj)        has_type(obj, T_NONE)
   6.310 +#define NULLP(obj)        has_type(obj, T_NULL)
   6.311 +#define STRINGP(obj)      has_type(obj, T_STRING)
   6.312 +
   6.313 +#define TRUEP(obj)    get_ul(obj)
   6.314 +
   6.315 +/** Convert an sxpr to an unsigned integer. */
   6.316 +#define OBJ_UINT(x)   get_ul(x)
   6.317 +/** Convert an sxpr to an integer. */
   6.318 +#define OBJ_INT(x)    (int)get_ul(x)
   6.319 +
   6.320 +/* Conversions of sxprs to their values.
   6.321 + * No checking is done.
   6.322 + */
   6.323 +#define OBJ_STRING(x)  ((ObjString*)get_ptr(x))
   6.324 +#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
   6.325 +#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
   6.326 +#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
   6.327 +#define CAR(x)         (OBJ_CONS(x)->car)
   6.328 +#define CDR(x)         (OBJ_CONS(x)->cdr)
   6.329 +
   6.330 +#define CAAR(x)        (CAR(CAR(x)))
   6.331 +#define CADR(x)        (CAR(CDR(x)))
   6.332 +#define CDAR(x)        (CDR(CAR(x)))
   6.333 +#define CDDR(x)        (CDR(CDR(x)))
   6.334 +
   6.335  /** Checked version of CAR
   6.336   *
   6.337   * @param x sxpr
   6.338 @@ -273,28 +298,10 @@ static inline Sxpr cdr(Sxpr x){
   6.339      return (CONSP(x) ? CDR(x) : ONULL);
   6.340  }
   6.341  
   6.342 -/** Allocate some memory and return an sxpr containing it.
   6.343 - * Returns ONOMEM if allocation failed.
   6.344 - *
   6.345 - * @param n number of bytes to allocate
   6.346 - * @param ty typecode
   6.347 - * @return sxpr
   6.348 - */
   6.349 -static inline Sxpr halloc(size_t n,  TypeCode ty){
   6.350 -    return OBJP(ty, allocate(n));
   6.351 -}
   6.352 -
   6.353 -/** Allocate an sxpr containing a pointer to the given type.
   6.354 - *
   6.355 - * @param ty type (uses sizeof to determine how many bytes to allocate)
   6.356 - * @param code typecode
   6.357 - * @return sxpr, ONOMEM if allocation failed
   6.358 - */
   6.359 -#define HALLOC(ty, code) halloc(sizeof(ty), code)
   6.360 -
   6.361  typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
   6.362  typedef int ObjEqualFn(Sxpr obj, Sxpr other);
   6.363  typedef void ObjFreeFn(Sxpr obj);
   6.364 +typedef Sxpr ObjCopyFn(Sxpr obj);
   6.365  
   6.366  /** An sxpr type definition. */
   6.367  typedef struct SxprType {
   6.368 @@ -304,6 +311,7 @@ typedef struct SxprType {
   6.369      ObjPrintFn *print;
   6.370      ObjEqualFn *equal;
   6.371      ObjFreeFn *free;
   6.372 +    ObjCopyFn *copy;
   6.373  } SxprType;
   6.374  
   6.375  
   6.376 @@ -321,6 +329,7 @@ static inline void hfree(Sxpr x){
   6.377  extern int objprint(IOStream *io, Sxpr x, unsigned flags);
   6.378  extern int objequal(Sxpr x, Sxpr y);
   6.379  extern void objfree(Sxpr x);
   6.380 +extern Sxpr objcopy(Sxpr x);
   6.381  
   6.382  extern void cons_free_cells(Sxpr obj);
   6.383  extern Sxpr intern(char *s);
   6.384 @@ -341,8 +350,10 @@ extern Sxpr cons_remove_if(Sxpr l, ObjEq
   6.385  
   6.386  extern Sxpr atom_new(char *name);
   6.387  extern char * atom_name(Sxpr obj);
   6.388 +extern int atom_length(Sxpr obj);
   6.389  
   6.390  extern Sxpr string_new(char *s);
   6.391 +extern Sxpr string_new_n(char *s, int n);
   6.392  extern char * string_string(Sxpr obj);
   6.393  extern int string_length(Sxpr obj);
   6.394  
   6.395 @@ -405,15 +416,20 @@ static inline Sxpr mkbool(int b){
   6.396  #define k_true         "true"
   6.397  #define k_false        "false"
   6.398  
   6.399 -#define c_var          '$'
   6.400  #define c_escape       '\\'
   6.401  #define c_single_quote '\''
   6.402  #define c_double_quote '"'
   6.403  #define c_string_open  c_double_quote
   6.404  #define c_string_close c_double_quote
   6.405 -#define c_data_open    '['
   6.406 -#define c_data_close   ']'
   6.407 -#define c_binary       '*'
   6.408 +
   6.409 +#define c_data_open    '<'
   6.410 +#define c_data_quote   '<'
   6.411 +#define c_data_count   '*'
   6.412 +//#define c_data_open    '['
   6.413 +//#define c_data_close   ']'
   6.414 +//#define c_binary       '*'
   6.415 +
   6.416 +#define c_var          '$'
   6.417  #define c_eval         '!'
   6.418  #define c_concat_open  '{'
   6.419  #define c_concat_close '}'
     7.1 --- a/tools/libxutil/sxpr_parser.c	Fri May 13 15:01:20 2005 +0000
     7.2 +++ b/tools/libxutil/sxpr_parser.c	Fri May 13 15:08:29 2005 +0000
     7.3 @@ -1,5 +1,5 @@
     7.4  /*
     7.5 - * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     7.6 + * Copyright (C) 2001 - 2005 Mike Wray <mike.wray@hp.com>
     7.7   *
     7.8   * This library is free software; you can redistribute it and/or modify
     7.9   * it under the terms of the GNU Lesser General Public License as
    7.10 @@ -26,6 +26,8 @@
    7.11  #  include <errno.h>
    7.12  #endif
    7.13  
    7.14 +#include "sys_net.h"
    7.15 +
    7.16  #include "iostream.h"
    7.17  #include "lexis.h"
    7.18  #include "sxpr_parser.h"
    7.19 @@ -42,45 +44,24 @@
    7.20   * @author Mike Wray <mike.wray@hpl.hp.com>
    7.21   */
    7.22  
    7.23 +#ifdef DEBUG
    7.24  #define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
    7.25 +#else
    7.26 +#define dprintf(fmt, args...) do{ }while(0)
    7.27 +#endif
    7.28 +
    7.29  #undef printf
    7.30  #define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
    7.31  
    7.32 -static void reset(Parser *z);
    7.33 -static int inputchar(Parser *p, char c);
    7.34 -static int savechar(Parser *p, char c);
    7.35 -extern void parse_error(Parser *in);
    7.36 -extern void parse_error_id(Parser *in, ParseErrorId id);
    7.37 -
    7.38 +static int state_start(Parser *p, char c);
    7.39  static int begin_start(Parser *p, char c);
    7.40 -static int state_start(Parser *p, char c);
    7.41 -static int end_start(Parser *p);
    7.42 -
    7.43 -static int begin_comment(Parser *p, char c);
    7.44 -static int state_comment(Parser *p, char c);
    7.45 -static int end_comment(Parser *p);
    7.46 -
    7.47 -static int begin_string(Parser *p, char c);
    7.48 -static int state_string(Parser *p, char c);
    7.49 -static int end_string(Parser *p);
    7.50 -static int state_escape(Parser *p, char c);
    7.51 -static int state_octal(Parser *p, char c);
    7.52 -static int state_hex(Parser *p, char c);
    7.53 -
    7.54 -static int begin_atom(Parser *p, char c);
    7.55 -static int state_atom(Parser *p, char c);
    7.56 -static int end_atom(Parser *p);
    7.57 -
    7.58 -static int state_list(Parser *p, char c);
    7.59 -static int begin_list(Parser *p, char c);
    7.60 -static int end_list(Parser *p);
    7.61  
    7.62  /** Print a parse error.
    7.63   *
    7.64   * @param in parser
    7.65   * @param msg format followed by printf arguments
    7.66   */
    7.67 -void eprintf(Parser *in, char *msg, ...){
    7.68 +static void eprintf(Parser *in, char *msg, ...){
    7.69      va_list args;
    7.70      if(in->error_out){
    7.71          va_start(args, msg);
    7.72 @@ -94,7 +75,7 @@ void eprintf(Parser *in, char *msg, ...)
    7.73   * @param in parser
    7.74   * @param msg format followed by printf arguments
    7.75   */
    7.76 -void wprintf(Parser *in, char *msg, ...){
    7.77 +static void wprintf(Parser *in, char *msg, ...){
    7.78      va_list args;
    7.79      if(in->error_out){
    7.80          va_start(args, msg);
    7.81 @@ -107,8 +88,8 @@ void wprintf(Parser *in, char *msg, ...)
    7.82  
    7.83  /** Record defining the message for a parse error. */
    7.84  typedef struct {
    7.85 -  ParseErrorId id;
    7.86 -  char *message;
    7.87 +    ParseErrorId id;
    7.88 +    char *message;
    7.89  } ParseError;
    7.90  
    7.91  /** Format for printing parse error messages. */
    7.92 @@ -116,18 +97,189 @@ typedef struct {
    7.93  
    7.94  /** Message catalog for the parse error codes. */
    7.95  static ParseError catalog[] = {
    7.96 -  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
    7.97 -  { PARSE_ERR_NOMEM,                  "out of memory" },
    7.98 -  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
    7.99 -  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
   7.100 -  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
   7.101 -  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
   7.102 -  { 0, NULL }
   7.103 +    { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
   7.104 +    { PARSE_ERR_NOMEM,                  "out of memory" },
   7.105 +    { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
   7.106 +    { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
   7.107 +    { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
   7.108 +    { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
   7.109 +    { 0, NULL }
   7.110  };
   7.111  
   7.112  /** Number of entries in the message catalog. */
   7.113  const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
   7.114  
   7.115 +/** Set the parser error stream.
   7.116 + * Parse errors are reported on the the error stream if it is non-null.
   7.117 + * 
   7.118 + * @param z parser
   7.119 + * @param error_out error stream
   7.120 + */
   7.121 +void Parser_set_error_stream(Parser *z, IOStream *error_out){
   7.122 +    z->error_out = error_out;
   7.123 +}
   7.124 +
   7.125 +/** Get the parser error message for an error code.
   7.126 + *
   7.127 + * @param id error code
   7.128 + * @return error message (empty string if the code is unknown)
   7.129 + */
   7.130 +static char *get_message(ParseErrorId id){
   7.131 +    int i;
   7.132 +    for(i = 0; i < catalog_n; i++){
   7.133 +        if(id == catalog[i].id){
   7.134 +            return catalog[i].message;
   7.135 +        }
   7.136 +    }
   7.137 +    return "";
   7.138 +}
   7.139 +
   7.140 +/** Get the line number.
   7.141 + *
   7.142 + * @param in parser
   7.143 + */
   7.144 +static int get_line(Parser *in){
   7.145 +    return in->line_no;
   7.146 +}
   7.147 +
   7.148 +/** Get the column number.
   7.149 + *
   7.150 + * @param in parser
   7.151 + */
   7.152 +static int get_column(Parser *in){
   7.153 +    return in->char_no;
   7.154 +}
   7.155 +
   7.156 +/** Get the line number the current token started on.
   7.157 + *
   7.158 + * @param in parser
   7.159 + */
   7.160 +static int get_tok_line(Parser *in){
   7.161 +    return in->tok_begin_line;
   7.162 +}
   7.163 +
   7.164 +/** Get the column number the current token started on.
   7.165 + *
   7.166 + * @param in parser
   7.167 + */
   7.168 +static int get_tok_column(Parser *in){
   7.169 +    return in->tok_begin_char;
   7.170 +}
   7.171 +
   7.172 +/** Return the current token.
   7.173 + * The return value points at the internal buffer, so
   7.174 + * it must not be modified (or freed). Use copy_token() if you need a copy.
   7.175 + *
   7.176 + * @param p parser
   7.177 + * @return token
   7.178 + */
   7.179 +char *peek_token(Parser *p){
   7.180 +    return p->tok;
   7.181 +}
   7.182 +
   7.183 +int token_len(Parser *p){
   7.184 +    return p->tok_end - p->tok;
   7.185 +}
   7.186 +
   7.187 +/** Return a copy of the current token.
   7.188 + * The returned value should be freed when finished with.
   7.189 + *
   7.190 + * @param p parser
   7.191 + * @return copy of token
   7.192 + */
   7.193 +char *copy_token(Parser *p){
   7.194 +    int n = token_len(p);
   7.195 +    char *buf = allocate(n + 1);
   7.196 +    if(buf){
   7.197 +        memcpy(buf, peek_token(p), n);
   7.198 +        buf[n] = '\0';
   7.199 +    }
   7.200 +    return buf;
   7.201 +}
   7.202 +
   7.203 +void new_token(Parser *p){
   7.204 +    memset(p->buf, 0, p->buf_end - p->buf);
   7.205 +    p->tok = p->buf;
   7.206 +    p->tok_end = p->tok;
   7.207 +    p->tok_begin_line = p->line_no;
   7.208 +    p->tok_begin_char = p->char_no;
   7.209 +}
   7.210 +
   7.211 +/** Report a parse error.
   7.212 + * Does nothing if the error stream is null or there is no error.
   7.213 + *
   7.214 + * @param in parser
   7.215 + */
   7.216 +static void report_error(Parser *in){
   7.217 +    if(in->error_out && in->err){
   7.218 +        char *msg = get_message(in->err);
   7.219 +        char *tok = peek_token(in);
   7.220 +        IOStream_print(in->error_out, PARSE_ERR_FMT,
   7.221 +                       get_tok_line(in), get_tok_column(in), msg);
   7.222 +        if(tok && tok[0]){
   7.223 +            IOStream_print(in->error_out, " '%s'", tok);
   7.224 +        }
   7.225 +        IOStream_print(in->error_out, "\n");
   7.226 +    }
   7.227 +}
   7.228 +
   7.229 +/** Get the error message for the current parse error code.
   7.230 + * Does nothing if there is no error.
   7.231 + *
   7.232 + * @param in parser
   7.233 + * @param buf where to place the message
   7.234 + * @param n maximum number of characters to place in buf
   7.235 + * @return current error code (zero for no error)
   7.236 + */
   7.237 +int Parser_error_message(Parser *in, char *buf, int n){
   7.238 +    if(in->err){
   7.239 +        char *msg = get_message(in->err);
   7.240 +        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in),
   7.241 +                 get_tok_column(in), msg);
   7.242 +    }
   7.243 +    return in->err;
   7.244 +}
   7.245 +
   7.246 +/** Flag a parse error. All subsequent reads will fail.
   7.247 + * Does not change the parser error code if it is already set.
   7.248 + *
   7.249 + * @param in parser
   7.250 + * @param id error code
   7.251 + */
   7.252 +int Parser_error_id(Parser *in, ParseErrorId id){
   7.253 +    if(!in->err){
   7.254 +        in->err = id;
   7.255 +        report_error(in);
   7.256 +    }
   7.257 +    return -EINVAL;
   7.258 +}
   7.259 +
   7.260 +/** Flag an unspecified parse error.
   7.261 + *
   7.262 + * @param in parser
   7.263 + */
   7.264 +int Parser_error(Parser *in){
   7.265 +    return Parser_error_id(in, PARSE_ERR_INVALID_SYNTAX);
   7.266 +}
   7.267 +
   7.268 +/** Test if the parser's error flag is set.
   7.269 + *
   7.270 + * @param in parser
   7.271 + * @return 1 if set, 0 otherwise
   7.272 + */
   7.273 +int Parser_has_error(Parser *in){
   7.274 +    return (in->err > 0);
   7.275 +}
   7.276 +
   7.277 +/** Test if the parser is at end of input.
   7.278 + *
   7.279 + * @param in parser
   7.280 + * @return 1 if at EOF, 0 otherwise
   7.281 + */
   7.282 +int Parser_at_eof(Parser *p){
   7.283 +    return p->eof;
   7.284 +}
   7.285 +
   7.286  void ParserState_free(ParserState *z){
   7.287      if(!z) return;
   7.288      objfree(z->val);
   7.289 @@ -136,19 +288,28 @@ void ParserState_free(ParserState *z){
   7.290  
   7.291  int ParserState_new(ParserStateFn *fn, char *name,
   7.292                      ParserState *parent, ParserState **val){
   7.293 -    int err = 0;
   7.294 +    int err = -ENOMEM;
   7.295      ParserState *z;
   7.296      z = ALLOCATE(ParserState);
   7.297 -    if(z){
   7.298 -        z->name = name;
   7.299 -        z->fn = fn;
   7.300 -        z->parent = parent;
   7.301 -        z->val = ONULL;
   7.302 -    } else {
   7.303 -        err = -ENOMEM;
   7.304 +    if(!z) goto exit;
   7.305 +    z->name = name;
   7.306 +    z->fn = fn;
   7.307 +    z->parent = parent;
   7.308 +    z->val = ONULL;
   7.309 +    err = 0;
   7.310 +  exit:
   7.311 +    *val = (err ? NULL : z);
   7.312 +    return err;
   7.313 +}
   7.314 +
   7.315 +void Parser_pop(Parser *p){
   7.316 +    ParserState *s = p->state;
   7.317 +    if(!s) return;
   7.318 +    p->state = s->parent;
   7.319 +    if (p->start_state == s) {
   7.320 +        p->start_state = NULL;
   7.321      }
   7.322 -    if(!err) *val = z;
   7.323 -    return err;
   7.324 +    ParserState_free(s);
   7.325  }
   7.326  
   7.327  /** Free a parser.
   7.328 @@ -158,19 +319,80 @@ int ParserState_new(ParserStateFn *fn, c
   7.329   */
   7.330  void Parser_free(Parser *z){
   7.331      if(!z) return;
   7.332 +    // Hmmm. Need to free states, but careful about double free of values.
   7.333 +    while(z->state){
   7.334 +        objfree(z->state->val);
   7.335 +        Parser_pop(z);
   7.336 +    }
   7.337 +    if(z->buf) deallocate(z->buf);
   7.338      objfree(z->val);
   7.339      z->val = ONONE;
   7.340      deallocate(z);
   7.341  }
   7.342  
   7.343 +int Parser_push(Parser *p, ParserStateFn *fn, char *name){
   7.344 +    return ParserState_new(fn, name, p->state, &p->state);
   7.345 +}
   7.346 +        
   7.347 +int Parser_return(Parser *p){
   7.348 +    int err = 0;
   7.349 +    Sxpr val = ONONE;
   7.350 +    if(!p->state){
   7.351 +        err = -EINVAL;
   7.352 +        goto exit;
   7.353 +    }
   7.354 +    val = p->state->val;
   7.355 +    p->state->val = ONONE;
   7.356 +    Parser_pop(p);
   7.357 +    if(p->state){
   7.358 +        err = cons_push(&p->state->val, val);
   7.359 +    } else {
   7.360 +        val = nrev(val);
   7.361 +        p->val = val;
   7.362 +    }
   7.363 +  exit:
   7.364 +    if(err){
   7.365 +        objfree(val);
   7.366 +    }
   7.367 +    return err;
   7.368 +}
   7.369 +
   7.370 +/** Reset the fields of a parser to initial values.
   7.371 + *
   7.372 + * @param z parser
   7.373 + */
   7.374 +static void reset(Parser *z){
   7.375 +    // leave flags
   7.376 +    // leave error_out
   7.377 +    while(z->state){
   7.378 +        Parser_pop(z);
   7.379 +    }
   7.380 +    z->val = ONONE;
   7.381 +    z->eof = 0;
   7.382 +    z->err = 0;
   7.383 +    z->line_no = 1;
   7.384 +    z->char_no = 0;
   7.385 +    memset(z->buf, 0, z->buf_end - z->buf);
   7.386 +    z->tok = z->buf;
   7.387 +    z->tok_end = z->tok;
   7.388 +    z->tok_begin_line = 0;
   7.389 +    z->tok_begin_char = 0;
   7.390 +    z->start_state = NULL;
   7.391 +}
   7.392 +
   7.393  /** Create a new parser. The error stream defaults to null.
   7.394   */
   7.395  Parser * Parser_new(void){
   7.396      Parser *z = ALLOCATE(Parser);
   7.397 +    int n = PARSER_BUF_SIZE;
   7.398      int err = -ENOMEM;
   7.399    
   7.400      if(!z) goto exit;
   7.401 +    z->buf = allocate(n);
   7.402 +    if(!z->buf) goto exit;
   7.403      err = 0;
   7.404 +    z->buf_end = z->buf + n;
   7.405 +    z->begin = begin_start;
   7.406      reset(z);
   7.407    exit:
   7.408      if(err){
   7.409 @@ -187,7 +409,7 @@ Parser * Parser_new(void){
   7.410   * @param p parser
   7.411   * @return error flag: 0 on success, non-zero on error
   7.412   */
   7.413 -static int inputchar(Parser *p, char c){
   7.414 +static int input_char(Parser *p, char c){
   7.415      int err = 0;
   7.416      if(c=='\n'){
   7.417          p->line_no++;
   7.418 @@ -198,95 +420,24 @@ static int inputchar(Parser *p, char c){
   7.419      return err;
   7.420  }
   7.421  
   7.422 -static int savechar(Parser *p, char c){
   7.423 -    int err = 0;
   7.424 -    if(p->buf_i >= p->buf_n){
   7.425 -        err = -ENOMEM;
   7.426 -        goto exit;
   7.427 -    }
   7.428 -    p->buf[p->buf_i] = c;
   7.429 -    p->buf_i++;
   7.430 -  exit:
   7.431 -    return err;
   7.432 -}
   7.433 -
   7.434 -int Parser_input_char(Parser *p, char c){
   7.435 +int save_char(Parser *p, char c){
   7.436      int err = 0;
   7.437 -    if(at_eof(p)){
   7.438 -        //skip;
   7.439 -    } else {
   7.440 -        inputchar(p, c);
   7.441 -    }
   7.442 -    if(!p->state){
   7.443 -        err = begin_start(p, c);
   7.444 -        if(err) goto exit;
   7.445 -    }
   7.446 -    err = p->state->fn(p, c);
   7.447 -  exit:
   7.448 -    return err;
   7.449 -}
   7.450 -
   7.451 -int Parser_input_eof(Parser *p){
   7.452 -    int err = 0;
   7.453 -    p->eof = 1;
   7.454 -    err = Parser_input_char(p, IOSTREAM_EOF);
   7.455 -    return err;
   7.456 -}
   7.457 -
   7.458 -int Parser_input(Parser *p, char *buf, int buf_n){
   7.459 -    int err = 0;
   7.460 -    int i = 0;
   7.461 -    if(buf_n <= 0){
   7.462 -        err = Parser_input_eof(p);
   7.463 -        goto exit;
   7.464 +    if(p->tok_end >= p->buf_end){
   7.465 +        int buf_n = (p->buf_end - p->buf) + PARSER_BUF_INCREMENT;
   7.466 +        char *buf = allocate(buf_n);
   7.467 +        if(!buf){
   7.468 +            err = -ENOMEM;
   7.469 +            goto exit;
   7.470 +        }
   7.471 +        memcpy(buf, p->buf, p->tok_end - p->buf);
   7.472 +        p->buf_end = buf + buf_n;
   7.473 +        p->tok     = buf + (p->tok     - p->buf);
   7.474 +        p->tok_end = buf + (p->tok_end - p->buf);
   7.475 +        deallocate(p->buf);
   7.476 +        p->buf = buf;
   7.477      }
   7.478 -    for(i = 0; i<buf_n; i++){
   7.479 -        err = Parser_input_char(p, buf[i]);
   7.480 -        if(err) goto exit;
   7.481 -    }
   7.482 +    *p->tok_end++ = c;
   7.483    exit:
   7.484 -    err = (err < 0 ? err : buf_n);
   7.485 -    return err;
   7.486 -}
   7.487 -
   7.488 -int Parser_push(Parser *p, ParserStateFn *fn, char *name){
   7.489 -    int err = 0;
   7.490 -    err = ParserState_new(fn, name, p->state, &p->state);
   7.491 -    return err;
   7.492 -}
   7.493 -        
   7.494 -int Parser_pop(Parser *p){
   7.495 -    int err = 0;
   7.496 -    ParserState *s = p->state;
   7.497 -    p->state = s->parent;
   7.498 -    if (p->start_state == s) {
   7.499 -        p->start_state = NULL;
   7.500 -    }
   7.501 -    ParserState_free(s);
   7.502 -    return err;
   7.503 -}
   7.504 -
   7.505 -int Parser_return(Parser *p){
   7.506 -    int err = 0;
   7.507 -    Sxpr val = ONONE;
   7.508 -    if(!p->state){
   7.509 -        err = -EINVAL;
   7.510 -        goto exit;
   7.511 -    }
   7.512 -    val = p->state->val;
   7.513 -    p->state->val = ONONE;
   7.514 -    err = Parser_pop(p);
   7.515 -    if(err) goto exit;
   7.516 -    if(p->state){
   7.517 -        err = cons_push(&p->state->val, val);
   7.518 -    } else {
   7.519 -        val = nrev(val);
   7.520 -        p->val = val;
   7.521 -    }
   7.522 -  exit:
   7.523 -    if(err){
   7.524 -        objfree(val);
   7.525 -    }
   7.526      return err;
   7.527  }
   7.528  
   7.529 @@ -300,30 +451,8 @@ static int is_separator(Parser *p, char 
   7.530      return in_sep_class(c);
   7.531  }
   7.532  
   7.533 -/** Return the current token.
   7.534 - * The return value points at the internal buffer, so
   7.535 - * it must not be modified (or freed). Use copy_token() if you need a copy.
   7.536 - *
   7.537 - * @param p parser
   7.538 - * @return token
   7.539 - */
   7.540 -char *peek_token(Parser *p){
   7.541 -    return p->buf;
   7.542 -}
   7.543 -
   7.544 -/** Return a copy of the current token.
   7.545 - * The returned value should be freed when finished with.
   7.546 - *
   7.547 - * @param p parser
   7.548 - * @return copy of token
   7.549 - */
   7.550 -char *copy_token(Parser *p){
   7.551 -    return strdup(peek_token(p));
   7.552 -}
   7.553 -
   7.554 -static int do_intern(Parser *p){
   7.555 +int Parser_set_value(Parser *p, Sxpr obj){
   7.556      int err = 0;
   7.557 -    Sxpr obj = intern(peek_token(p));
   7.558      if(NOMEMP(obj)){
   7.559          err = -ENOMEM;
   7.560      } else {
   7.561 @@ -331,27 +460,33 @@ static int do_intern(Parser *p){
   7.562      }
   7.563      return err;
   7.564  }
   7.565 +    
   7.566 +int Parser_intern(Parser *p){
   7.567 +    Sxpr obj = intern(peek_token(p));
   7.568 +    return Parser_set_value(p, obj);
   7.569 +}
   7.570  
   7.571 -static int do_string(Parser *p){
   7.572 -    int err = 0;
   7.573 -    Sxpr obj;
   7.574 -    obj = string_new(peek_token(p));
   7.575 -    if(NOMEMP(obj)){
   7.576 -        err = -ENOMEM;
   7.577 -    } else {
   7.578 -        p->state->val = obj;
   7.579 -    }
   7.580 -    return err;
   7.581 +int Parser_atom(Parser *p){
   7.582 +    Sxpr obj = atom_new(peek_token(p));
   7.583 +    return Parser_set_value(p, obj);
   7.584  }
   7.585  
   7.586 -void newtoken(Parser *p){
   7.587 -    memset(p->buf, 0, p->buf_n);
   7.588 -    p->buf_i = 0;
   7.589 -    p->tok_begin_line = p->line_no;
   7.590 -    p->tok_begin_char = p->char_no;
   7.591 +int Parser_string(Parser *p){
   7.592 +    Sxpr obj = string_new_n(peek_token(p), token_len(p));
   7.593 +    return Parser_set_value(p, obj);
   7.594  }
   7.595  
   7.596 -int get_escape(char c, char *d){
   7.597 +int Parser_data(Parser *p){
   7.598 +    Sxpr obj = string_new_n(peek_token(p), token_len(p));
   7.599 +    return Parser_set_value(p, obj);
   7.600 +}
   7.601 +
   7.602 +int Parser_uint(Parser *p){
   7.603 +    unsigned int x = htonl(*(unsigned int *)peek_token(p));
   7.604 +    return Parser_set_value(p, OINT(x));
   7.605 +}
   7.606 +
   7.607 +static int get_escape(char c, char *d){
   7.608      int err = 0;
   7.609      switch(c){
   7.610      case 'a':            *d = '\a'; break;
   7.611 @@ -377,15 +512,18 @@ int Parser_ready(Parser *p){
   7.612  Sxpr Parser_get_val(Parser *p){
   7.613      Sxpr v = ONONE;
   7.614      if(CONSP(p->val)){
   7.615 -        v = CAR(p->val);
   7.616 -        p->val = CDR(p->val);
   7.617 -    } else if (CONSP(p->start_state->val)){
   7.618 +    } else if (p->start_state && CONSP(p->start_state->val)){
   7.619          p->val = p->start_state->val;
   7.620          p->val = nrev(p->val);
   7.621          p->start_state->val = ONULL;
   7.622 -        v = CAR(p->val);
   7.623 -        p->val = CDR(p->val);
   7.624 -    }        
   7.625 +    }  else {
   7.626 +        goto exit;
   7.627 +    }
   7.628 +    Sxpr w = p->val;
   7.629 +    v = CAR(w);
   7.630 +    p->val = CDR(w);
   7.631 +    hfree(w);
   7.632 +  exit:
   7.633      return v;
   7.634  }
   7.635  
   7.636 @@ -401,118 +539,132 @@ Sxpr Parser_get_all(Parser *p){
   7.637      }
   7.638      return v;
   7.639  }
   7.640 -    
   7.641 -int begin_start(Parser *p, char c){
   7.642 -    int err = 0;
   7.643 -    err = Parser_push(p, state_start, "start");
   7.644 -    if(err) goto exit;
   7.645 -    p->start_state = p->state;
   7.646 -  exit:
   7.647 -    return err;
   7.648 -}
   7.649  
   7.650 -int state_start(Parser *p, char c){
   7.651 +static int state_comment(Parser *p, char c){
   7.652      int err = 0;
   7.653 -    if(at_eof(p)){
   7.654 -        err = end_start(p);
   7.655 -    } else if(in_space_class(c)){
   7.656 -        //skip
   7.657 -    } else if(in_comment_class(c)){
   7.658 -        begin_comment(p, c);
   7.659 -    } else if(c == c_list_open){
   7.660 -        begin_list(p, c);
   7.661 -    } else if(c == c_list_close){
   7.662 -        parse_error(p);
   7.663 -        err = -EINVAL;
   7.664 -    } else if(in_string_quote_class(c)){
   7.665 -        begin_string(p, c);
   7.666 -    } else if(in_printable_class(c)){
   7.667 -        begin_atom(p, c);
   7.668 -    } else if(c == 0x04){
   7.669 -        //ctrl-D, EOT: end-of-text.
   7.670 -        Parser_input_eof(p);
   7.671 +    if(c == '\n' || Parser_at_eof(p)){
   7.672 +        Parser_pop(p);
   7.673      } else {
   7.674 -        parse_error(p);
   7.675 -        err = -EINVAL;
   7.676 +        err = input_char(p, c);
   7.677      }
   7.678      return err;
   7.679  }
   7.680  
   7.681 -int end_start(Parser *p){
   7.682 -    int err = 0;
   7.683 -    err = Parser_return(p);
   7.684 -    return err;
   7.685 -}
   7.686 -
   7.687 -int begin_comment(Parser *p, char c){
   7.688 +static int begin_comment(Parser *p, char c){
   7.689      int err = 0;
   7.690      err = Parser_push(p, state_comment, "comment");
   7.691      if(err) goto exit;
   7.692 -    err = inputchar(p, c);
   7.693 +    err = input_char(p, c);
   7.694    exit:
   7.695      return err;
   7.696  }
   7.697  
   7.698 -int state_comment(Parser *p, char c){
   7.699 -    int err = 0;
   7.700 -    if(c == '\n' || at_eof(p)){
   7.701 -        err = end_comment(p);
   7.702 -    } else {
   7.703 -        err = inputchar(p, c);
   7.704 -    }
   7.705 -    return err;
   7.706 -}
   7.707 -
   7.708 -int end_comment(Parser *p){
   7.709 -    return Parser_pop(p);
   7.710 -}
   7.711 -
   7.712 -int begin_string(Parser *p, char c){
   7.713 +static int end_string(Parser *p){
   7.714      int err = 0;
   7.715 -    err = Parser_push(p, state_string, "string");
   7.716 -    if(err) goto exit;
   7.717 -    newtoken(p);
   7.718 -    p->state->delim = c;
   7.719 -  exit:
   7.720 -    return err;
   7.721 -}
   7.722 -
   7.723 -int state_string(Parser *p, char c){
   7.724 -    int err = 0;
   7.725 -    if(at_eof(p)){
   7.726 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.727 -        err = -EINVAL;
   7.728 -    } else if(c == p->state->delim){
   7.729 -        err = end_string(p);
   7.730 -    } else if(c == '\\'){
   7.731 -        err = Parser_push(p, state_escape, "escape");
   7.732 -    } else {
   7.733 -        err = savechar(p, c);
   7.734 -    }
   7.735 -    return err;
   7.736 -}
   7.737 -
   7.738 -int end_string(Parser *p){
   7.739 -    int err = 0;
   7.740 -    err = do_string(p);
   7.741 +    err = Parser_string(p);
   7.742      if(err) goto exit;
   7.743      err = Parser_return(p);
   7.744    exit:
   7.745      return err;
   7.746  }
   7.747  
   7.748 -int state_escape(Parser *p, char c){
   7.749 +static int octaldone(Parser *p){
   7.750 +    int err = 0;
   7.751 +    char d = (char)(p->state->ival & 0xff);
   7.752 +    Parser_pop(p);
   7.753 +    err = Parser_input_char(p, d);
   7.754 +    return err;
   7.755 +}
   7.756 +
   7.757 +static int octaldigit(Parser *p, int d){
   7.758 +    int err = 0;
   7.759 +    p->state->ival *= 8;
   7.760 +    p->state->ival += d; 
   7.761 +    p->state->count++;
   7.762 +    if(err) goto exit;
   7.763 +    if(p->state->ival < 0 || p->state->ival > 0xff){
   7.764 +        err = Parser_error(p);
   7.765 +        goto exit;
   7.766 +    }
   7.767 +    if(p->state->count == 3){
   7.768 +        err = octaldone(p);
   7.769 +    }
   7.770 +  exit:
   7.771 +    return err;
   7.772 +}
   7.773 +
   7.774 +static int state_octal(Parser *p, char c){
   7.775 +    int err = 0;
   7.776 +    if(Parser_at_eof(p)){
   7.777 +        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.778 +        goto exit;
   7.779 +    } else if('0' <= c && c <= '7'){
   7.780 +        err = octaldigit(p, c - '0');
   7.781 +    } else {
   7.782 +        err = octaldone(p);
   7.783 +        if(err) goto exit;
   7.784 +        Parser_input_char(p, c);
   7.785 +    }
   7.786 +  exit:
   7.787 +    return err;
   7.788 +}
   7.789 +
   7.790 +static int hexdone(Parser *p){
   7.791 +    int err = 0;
   7.792 +    char d = (char)(p->state->ival & 0xff);
   7.793 +    Parser_pop(p);
   7.794 +    err = Parser_input_char(p, d);
   7.795 +    return err;
   7.796 +}
   7.797 +    
   7.798 +static int hexdigit(Parser *p, int d){
   7.799 +    int err = 0;
   7.800 +    p->state->ival *= 16;
   7.801 +    p->state->ival += d; 
   7.802 +    p->state->count++;
   7.803 +    if(err) goto exit;
   7.804 +    if(p->state->ival < 0 || p->state->ival > 0xff){
   7.805 +        err = Parser_error(p);
   7.806 +        goto exit;
   7.807 +    }
   7.808 +    if(p->state->count == 2){
   7.809 +        err = hexdone(p);
   7.810 +    }
   7.811 +  exit:
   7.812 +    return err;
   7.813 +}
   7.814 +    
   7.815 +static int state_hex(Parser *p, char c){
   7.816 +    int err = 0;
   7.817 +    if(Parser_at_eof(p)){
   7.818 +        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.819 +        goto exit;
   7.820 +    } else if('0' <= c && c <= '9'){
   7.821 +        err = hexdigit(p, c - '0');
   7.822 +    } else if('A' <= c && c <= 'F'){
   7.823 +        err = hexdigit(p, c - 'A' + 10);
   7.824 +    } else if('a' <= c && c <= 'f'){
   7.825 +        err = hexdigit(p, c - 'a' + 10);
   7.826 +    } else if(p->state->count){
   7.827 +        err = hexdone(p);
   7.828 +        if(err) goto exit;
   7.829 +        Parser_input_char(p, c);
   7.830 +    }
   7.831 +  exit:
   7.832 +    return err;
   7.833 +}
   7.834 +
   7.835 +static int state_escape(Parser *p, char c){
   7.836      int err = 0;
   7.837      char d;
   7.838 -    if(at_eof(p)){
   7.839 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.840 -        err = -EINVAL;
   7.841 +    if(Parser_at_eof(p)){
   7.842 +        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.843          goto exit;
   7.844      }
   7.845      if(get_escape(c, &d) == 0){
   7.846 -        err = savechar(p, d);
   7.847 +        err = save_char(p, d);
   7.848          if(err) goto exit;
   7.849 -        err = Parser_pop(p);
   7.850 +        Parser_pop(p);
   7.851      } else if(c == 'x'){
   7.852          p->state->fn = state_hex;
   7.853          p->state->ival = 0;
   7.854 @@ -527,113 +679,42 @@ int state_escape(Parser *p, char c){
   7.855      return err;
   7.856  }
   7.857  
   7.858 -int octaldone(Parser *p){
   7.859 +static int state_string(Parser *p, char c){
   7.860      int err = 0;
   7.861 -    char d = (char)(p->state->ival & 0xff);
   7.862 -    err = Parser_pop(p);
   7.863 -    if(err) goto exit;
   7.864 -    err = Parser_input_char(p, d);
   7.865 -  exit:
   7.866 +    if(Parser_at_eof(p)){
   7.867 +        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.868 +    } else if(c == p->state->delim){
   7.869 +        err = end_string(p);
   7.870 +    } else if(c == '\\'){
   7.871 +        err = Parser_push(p, state_escape, "escape");
   7.872 +    } else {
   7.873 +        err = save_char(p, c);
   7.874 +    }
   7.875      return err;
   7.876  }
   7.877  
   7.878 -int octaldigit(Parser *p, char c){
   7.879 +static int begin_string(Parser *p, char c){
   7.880      int err = 0;
   7.881 -    p->state->ival *= 8;
   7.882 -    p->state->ival += c - '0'; 
   7.883 -    p->state->count++;
   7.884 +    err = Parser_push(p, state_string, "string");
   7.885      if(err) goto exit;
   7.886 -    if(p->state->ival < 0 || p->state->ival > 0xff){
   7.887 -        parse_error(p);
   7.888 -        err = -EINVAL;
   7.889 -        goto exit;
   7.890 -    }
   7.891 -    if(p->state->count == 3){
   7.892 -        err = octaldone(p);
   7.893 -    }
   7.894 -  exit:
   7.895 -    return err;
   7.896 -}
   7.897 -
   7.898 -int state_octal(Parser *p, char c){
   7.899 -    int err = 0;
   7.900 -    if(at_eof(p)){
   7.901 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.902 -        err = -EINVAL;
   7.903 -        goto exit;
   7.904 -    } else if('0' <= c && c <= '7'){
   7.905 -        err = octaldigit(p, c);
   7.906 -    } else {
   7.907 -        err = octaldone(p);
   7.908 -        if(err) goto exit;
   7.909 -        Parser_input_char(p, c);
   7.910 -    }
   7.911 +    new_token(p);
   7.912 +    p->state->delim = c;
   7.913    exit:
   7.914      return err;
   7.915  }
   7.916  
   7.917 -int hexdone(Parser *p){
   7.918 +static int end_atom(Parser *p){
   7.919      int err = 0;
   7.920 -    char d = (char)(p->state->ival & 0xff);
   7.921 -    err = Parser_pop(p);
   7.922 -    if(err) goto exit;
   7.923 -    err = Parser_input_char(p, d);
   7.924 -  exit:
   7.925 -    return err;
   7.926 -}
   7.927 -    
   7.928 -int hexdigit(Parser *p, char c, char d){
   7.929 -    int err = 0;
   7.930 -    p->state->ival *= 16;
   7.931 -    p->state->ival += c - d; 
   7.932 -    p->state->count++;
   7.933 +    err = Parser_atom(p);
   7.934      if(err) goto exit;
   7.935 -    if(p->state->ival < 0 || p->state->ival > 0xff){
   7.936 -        parse_error(p);
   7.937 -        err = -EINVAL;
   7.938 -        goto exit;
   7.939 -    }
   7.940 -    if(p->state->count == 2){
   7.941 -        err = hexdone(p);
   7.942 -    }
   7.943 -  exit:
   7.944 -    return err;
   7.945 -}
   7.946 -    
   7.947 -int state_hex(Parser *p, char c){
   7.948 -    int err = 0;
   7.949 -    if(at_eof(p)){
   7.950 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
   7.951 -        err = -EINVAL;
   7.952 -        goto exit;
   7.953 -    } else if('0' <= c && c <= '9'){
   7.954 -        err = hexdigit(p, c, '0');
   7.955 -    } else if('A' <= c && c <= 'F'){
   7.956 -        err = hexdigit(p, c, 'A');
   7.957 -    } else if('a' <= c && c <= 'f'){
   7.958 -        err = hexdigit(p, c, 'a');
   7.959 -    } else if(p->state->count){
   7.960 -        err =hexdone(p);
   7.961 -        if(err) goto exit;
   7.962 -        Parser_input_char(p, c);
   7.963 -    }
   7.964 +    err = Parser_return(p);
   7.965    exit:
   7.966      return err;
   7.967  }
   7.968  
   7.969 -int begin_atom(Parser *p, char c){
   7.970 +static int state_atom(Parser *p, char c){
   7.971      int err = 0;
   7.972 -    err = Parser_push(p, state_atom, "atom");
   7.973 -    if(err) goto exit;
   7.974 -    newtoken(p);
   7.975 -    err = savechar(p, c);
   7.976 -  exit:
   7.977 -    return err;
   7.978 -}
   7.979 -
   7.980 -int state_atom(Parser *p, char c){
   7.981 -    int err = 0;
   7.982 -    if(at_eof(p)){
   7.983 +    if(Parser_at_eof(p)){
   7.984          err = end_atom(p);
   7.985      } else if(is_separator(p, c) ||
   7.986                in_space_class(c) ||
   7.987 @@ -642,257 +723,231 @@ int state_atom(Parser *p, char c){
   7.988          if(err) goto exit;
   7.989          err = Parser_input_char(p, c);
   7.990      } else {
   7.991 -        err = savechar(p, c);
   7.992 +        err = save_char(p, c);
   7.993      }
   7.994    exit:
   7.995      return err;
   7.996  }
   7.997  
   7.998 -int end_atom(Parser *p){
   7.999 +static int begin_atom(Parser *p, char c){
  7.1000      int err = 0;
  7.1001 -    err = do_intern(p);
  7.1002 +    err = Parser_push(p, state_atom, "atom");
  7.1003 +    if(err) goto exit;
  7.1004 +    new_token(p);
  7.1005 +    err = save_char(p, c);
  7.1006 +  exit:
  7.1007 +    return err;
  7.1008 +}
  7.1009 +
  7.1010 +static int end_data(Parser *p){
  7.1011 +    int err = 0;
  7.1012 +    err = Parser_data(p);
  7.1013      if(err) goto exit;
  7.1014      err = Parser_return(p);
  7.1015    exit:
  7.1016      return err;
  7.1017  }
  7.1018  
  7.1019 -int state_list(Parser *p, char c){
  7.1020 +static int counted_data(Parser *p, char c){
  7.1021 +    int err = 0;
  7.1022 +    err = save_char(p, c);
  7.1023 +    if(err) goto exit;
  7.1024 +    if(token_len(p) == p->state->count){
  7.1025 +        err = end_data(p);
  7.1026 +    }
  7.1027 +  exit:
  7.1028 +    return err;
  7.1029 +}
  7.1030 +
  7.1031 +static int counted_data_count(Parser *p, char c){
  7.1032 +    int err = 0;
  7.1033 +    if(c == p->state->delim){
  7.1034 +        new_token(p);
  7.1035 +        p->state->count = p->state->ival;
  7.1036 +        p->state->fn = counted_data;
  7.1037 +    } else if('0' <= c && c <= '9'){
  7.1038 +        p->state->ival *= 10;
  7.1039 +        p->state->ival += c - '0';
  7.1040 +    } else {
  7.1041 +        err = -EINVAL;
  7.1042 +    }
  7.1043 +    return err;
  7.1044 +}
  7.1045 +
  7.1046 +static int quoted_data(Parser *p, char c){
  7.1047 +    int err = 0;
  7.1048 +    int count = p->state->count;
  7.1049 +    err = save_char(p, c);
  7.1050 +    if(err) goto exit;
  7.1051 +    // Check that buf is longer than delim and
  7.1052 +    // ends with delim. If so, trim delim off and return.
  7.1053 +    if((token_len(p) >= count) &&
  7.1054 +       !memcmp(p->tok_end - count, p->buf, count)){
  7.1055 +        p->tok_end -= count;
  7.1056 +        end_data(p);
  7.1057 +    }
  7.1058 +  exit:
  7.1059 +    return err;
  7.1060 +}
  7.1061 +
  7.1062 +static int quoted_data_delim(Parser *p, char c){
  7.1063 +    // Saves the delim in the token buffer.
  7.1064      int err = 0;
  7.1065 -    if(at_eof(p)){
  7.1066 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  7.1067 -        err = -EINVAL;
  7.1068 +    err = save_char(p, c);
  7.1069 +    if(err) goto exit;
  7.1070 +    if(c == p->state->delim){
  7.1071 +        p->state->fn = quoted_data;
  7.1072 +        p->state->count = token_len(p);
  7.1073 +        // Advance the token pointer past the delim.
  7.1074 +        p->tok = p->tok_end;
  7.1075 +    }
  7.1076 +  exit:
  7.1077 +    return err;
  7.1078 +}
  7.1079 +
  7.1080 +static int state_data(Parser *p, char c){
  7.1081 +    // Quoted data:
  7.1082 +    // <<delim< anything not containing delimiter<delim<
  7.1083 +    // Where 'delim' is anything not containing '<'.
  7.1084 +    // Counted data:
  7.1085 +    // <*nnn..* N bytes
  7.1086 +    // Where nnn... is N in decimal (
  7.1087 +    int err = 0;
  7.1088 +    switch(c){
  7.1089 +    case c_data_count:
  7.1090 +        p->state->delim = c;
  7.1091 +        p->state->fn = counted_data_count;
  7.1092 +        p->state->ival = 0;
  7.1093 +        new_token(p);
  7.1094 +        break;
  7.1095 +    case c_data_quote:
  7.1096 +        p->state->delim = c;
  7.1097 +        p->state->fn = quoted_data_delim;
  7.1098 +        new_token(p);
  7.1099 +        err = save_char(p, c);
  7.1100 +        break;
  7.1101 +    default:
  7.1102 +        err = Parser_error(p);
  7.1103 +        break;
  7.1104 +    }
  7.1105 +    return err;
  7.1106 +}
  7.1107 +
  7.1108 +static int begin_data(Parser *p, char c){
  7.1109 +    int err = 0;
  7.1110 +    err = Parser_push(p, state_data, "data");
  7.1111 +    if(err) goto exit;
  7.1112 +    new_token(p);
  7.1113 +  exit:
  7.1114 +    return err;
  7.1115 +}
  7.1116 +
  7.1117 +static int state_list(Parser *p, char c){
  7.1118 +    int err = 0;
  7.1119 +    dprintf(">\n");
  7.1120 +    if(Parser_at_eof(p)){
  7.1121 +        err = Parser_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  7.1122      } else if(c == c_list_close){
  7.1123          p->state->val = nrev(p->state->val);
  7.1124 -        err = end_list(p);
  7.1125 +        err = Parser_return(p);
  7.1126      } else {
  7.1127          err = state_start(p, c);
  7.1128      }
  7.1129 +    dprintf("< err=%d\n", err);
  7.1130      return err;
  7.1131      
  7.1132  }
  7.1133  
  7.1134 -int begin_list(Parser *p, char c){
  7.1135 +static int begin_list(Parser *p, char c){
  7.1136      return Parser_push(p, state_list, "list");
  7.1137  }
  7.1138  
  7.1139 -int end_list(Parser *p){
  7.1140 -    return Parser_return(p);
  7.1141 -}
  7.1142 -
  7.1143 -/** Reset the fields of a parser to initial values.
  7.1144 - *
  7.1145 - * @param z parser
  7.1146 - */
  7.1147 -static void reset(Parser *z){
  7.1148 -  IOStream *error_out = z->error_out;
  7.1149 -  int flags = z->flags;
  7.1150 -  memzero(z, sizeof(Parser));
  7.1151 -  z->buf_n = sizeof(z->buf) - 1;
  7.1152 -  z->buf_i = 0;
  7.1153 -  z->line_no = 1;
  7.1154 -  z->char_no = 0;
  7.1155 -  z->error_out = error_out;
  7.1156 -  z->flags = flags;
  7.1157 -}
  7.1158 -
  7.1159 -/** Set the parser error stream.
  7.1160 - * Parse errors are reported on the the error stream if it is non-null.
  7.1161 - * 
  7.1162 - * @param z parser
  7.1163 - * @param error_out error stream
  7.1164 - */
  7.1165 -void set_error_stream(Parser *z, IOStream *error_out){
  7.1166 -  if(z){
  7.1167 -    z->error_out = error_out;
  7.1168 -  }
  7.1169 +static int state_start(Parser *p, char c){
  7.1170 +    int err = 0;
  7.1171 +    dprintf(">\n");
  7.1172 +    if(Parser_at_eof(p)){
  7.1173 +        err = Parser_return(p);
  7.1174 +    } else if(in_space_class(c)){
  7.1175 +        //skip
  7.1176 +    } else if(in_comment_class(c)){
  7.1177 +        begin_comment(p, c);
  7.1178 +    } else if(c == c_list_open){
  7.1179 +        begin_list(p, c);
  7.1180 +    } else if(c == c_list_close){
  7.1181 +        err = Parser_error(p);
  7.1182 +    } else if(in_string_quote_class(c)){
  7.1183 +        begin_string(p, c);
  7.1184 +    } else if(c == c_data_open){
  7.1185 +        begin_data(p, c);
  7.1186 +    } else if(in_printable_class(c)){
  7.1187 +        begin_atom(p, c);
  7.1188 +    } else if(c == 0x04){
  7.1189 +        //ctrl-D, EOT: end-of-text.
  7.1190 +        Parser_input_eof(p);
  7.1191 +    } else {
  7.1192 +        err = Parser_error(p);
  7.1193 +    }
  7.1194 +    dprintf("< err=%d\n", err);
  7.1195 +    return err;
  7.1196  }
  7.1197  
  7.1198 -/** Get the parser error message for an error code.
  7.1199 - *
  7.1200 - * @param id error code
  7.1201 - * @return error message (empty string if the code is unknown)
  7.1202 - */
  7.1203 -static char *get_message(ParseErrorId id){
  7.1204 -  int i;
  7.1205 -  for(i=0; i<catalog_n; i++){
  7.1206 -    if(id == catalog[i].id){
  7.1207 -      return catalog[i].message;
  7.1208 -    }
  7.1209 -  }
  7.1210 -  return "";
  7.1211 -}
  7.1212 -
  7.1213 -/** Get the line number.
  7.1214 - *
  7.1215 - * @param in parser
  7.1216 - */
  7.1217 -int get_line(Parser *in){
  7.1218 -  return in->line_no;
  7.1219 -}
  7.1220 -
  7.1221 -/** Get the column number.
  7.1222 - *
  7.1223 - * @param in parser
  7.1224 - */
  7.1225 -int get_column(Parser *in){
  7.1226 -  return in->char_no;
  7.1227 -}
  7.1228 -
  7.1229 -/** Get the line number the current token started on.
  7.1230 - *
  7.1231 - * @param in parser
  7.1232 - */
  7.1233 -int get_tok_line(Parser *in){
  7.1234 -  return in->tok_begin_line;
  7.1235 +int begin_start(Parser *p, char c){
  7.1236 +    int err = 0;
  7.1237 +    dprintf(">\n");
  7.1238 +    err = Parser_push(p, state_start, "start");
  7.1239 +    if(err) goto exit;
  7.1240 +    p->start_state = p->state;
  7.1241 +  exit:
  7.1242 +    dprintf("< err=%d\n", err);
  7.1243 +    return err;
  7.1244  }
  7.1245  
  7.1246 -/** Get the column number the current token started on.
  7.1247 - *
  7.1248 - * @param in parser
  7.1249 - */
  7.1250 -int get_tok_column(Parser *in){
  7.1251 -  return in->tok_begin_char;
  7.1252 -}
  7.1253 -
  7.1254 -/** Report a parse error.
  7.1255 - * Does nothing if the error stream is null or there is no error.
  7.1256 - *
  7.1257 - * @param in parser
  7.1258 - */
  7.1259 -static void report_error(Parser *in){
  7.1260 -  if(in->error_out && in->err){
  7.1261 -    char *msg = get_message(in->err);
  7.1262 -    char *tok = peek_token(in);
  7.1263 -    IOStream_print(in->error_out, PARSE_ERR_FMT,
  7.1264 -		   get_tok_line(in), get_tok_column(in), msg);
  7.1265 -    if(tok && tok[0]){
  7.1266 -        IOStream_print(in->error_out, " '%s'", tok);
  7.1267 +int Parser_input_char(Parser *p, char c){
  7.1268 +    int err = 0;
  7.1269 +    if(Parser_at_eof(p)){
  7.1270 +        //skip;
  7.1271 +    } else {
  7.1272 +        input_char(p, c);
  7.1273      }
  7.1274 -    IOStream_print(in->error_out, "\n");
  7.1275 -  }
  7.1276 +    if(!p->state){
  7.1277 +        err = p->begin(p, c);
  7.1278 +        if(err) goto exit;
  7.1279 +    }
  7.1280 +    err = p->state->fn(p, c);
  7.1281 +  exit:
  7.1282 +    return err;
  7.1283  }
  7.1284  
  7.1285 -/** Get the error message for the current parse error code.
  7.1286 - * Does nothing if there is no error.
  7.1287 - *
  7.1288 - * @param in parser
  7.1289 - * @param buf where to place the message
  7.1290 - * @param n maximum number of characters to place in buf
  7.1291 - * @return current error code (zero for no error)
  7.1292 - */
  7.1293 -int parse_error_message(Parser *in, char *buf, int n){
  7.1294 -    if(in->err){
  7.1295 -        char *msg = get_message(in->err);
  7.1296 -        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
  7.1297 -    }
  7.1298 -    return in->err;
  7.1299 -}
  7.1300 -
  7.1301 -/** Flag an unspecified parse error. All subsequent reads will fail.
  7.1302 - *
  7.1303 - * @param in parser
  7.1304 - */
  7.1305 -void parse_error(Parser *in){
  7.1306 -    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
  7.1307 +int Parser_input_eof(Parser *p){
  7.1308 +    int err = 0;
  7.1309 +    p->eof = 1;
  7.1310 +    err = Parser_input_char(p, IOSTREAM_EOF);
  7.1311 +    return err;
  7.1312  }
  7.1313  
  7.1314 -/** Flag a parse error. All subsequent reads will fail.
  7.1315 - * Does not change the parser error code if it is already set.
  7.1316 - *
  7.1317 - * @param in parser
  7.1318 - * @param id error code
  7.1319 - */
  7.1320 -void parse_error_id(Parser *in, ParseErrorId id){
  7.1321 -    if(!in->err){
  7.1322 -        in->err = id;
  7.1323 -        report_error(in);
  7.1324 +int Parser_input(Parser *p, char *buf, int buf_n){
  7.1325 +    int err = 0;
  7.1326 +    int i = 0;
  7.1327 +    dprintf("> |%s|\n", buf);
  7.1328 +    if(buf_n <= 0){
  7.1329 +        err = Parser_input_eof(p);
  7.1330 +        goto exit;
  7.1331      }
  7.1332 -}
  7.1333 -
  7.1334 -/** Test if the parser's error flag is set.
  7.1335 - *
  7.1336 - * @param in parser
  7.1337 - * @return 1 if set, 0 otherwise
  7.1338 - */
  7.1339 -int has_error(Parser *in){
  7.1340 -    return (in->err > 0);
  7.1341 -}
  7.1342 -
  7.1343 -/** Test if the parser is at end of input.
  7.1344 - *
  7.1345 - * @param in parser
  7.1346 - * @return 1 if at EOF, 0 otherwise
  7.1347 - */
  7.1348 -int at_eof(Parser *p){
  7.1349 -    return p->eof;
  7.1350 +    for(i = 0; i < buf_n; i++){
  7.1351 +        err = Parser_input_char(p, buf[i]);
  7.1352 +        if(err) goto exit;
  7.1353 +    }
  7.1354 +  exit:
  7.1355 +    err = (err < 0 ? err : buf_n);
  7.1356 +    dprintf("< err=%d\n", err);
  7.1357 +    return err;
  7.1358  }
  7.1359  
  7.1360  #ifdef SXPR_PARSER_MAIN
  7.1361  /* Stuff for standalone testing. */
  7.1362  
  7.1363  #include "file_stream.h"
  7.1364 -#include "string_stream.h"
  7.1365 -
  7.1366 -extern int stringof(Sxpr exp, char **s);
  7.1367 -int child_string(Sxpr exp, Sxpr key, char **s){
  7.1368 -    int err = 0;
  7.1369 -    Sxpr val = sxpr_child_value(exp, key, ONONE);
  7.1370 -    err = stringof(val, s);
  7.1371 -    return err;
  7.1372 -}
  7.1373 -
  7.1374 -extern int intof(Sxpr exp, int *v);
  7.1375 -int child_int(Sxpr exp, Sxpr key, int *v){
  7.1376 -    int err = 0;
  7.1377 -    Sxpr val = sxpr_child_value(exp, key, ONONE);
  7.1378 -    err = intof(val, v);
  7.1379 -    return err;
  7.1380 -}
  7.1381 -
  7.1382 -int eval_vnet(Sxpr exp){
  7.1383 -    int err = 0;
  7.1384 -    Sxpr oid = intern("id");
  7.1385 -    int id;
  7.1386 -    err = child_int(exp, oid, &id);
  7.1387 -    if(err) goto exit;
  7.1388 -    dprintf("> vnet id=%d\n", id);
  7.1389 - exit:
  7.1390 -    dprintf("< err=%d\n", err);
  7.1391 -    return err;
  7.1392 -}
  7.1393 -
  7.1394 -int eval_connect(Sxpr exp){
  7.1395 -    int err = 0;
  7.1396 -    Sxpr ovif = intern("vif");
  7.1397 -    Sxpr ovnet = intern("vnet");
  7.1398 -    char *vif;
  7.1399 -    int vnet;
  7.1400 -
  7.1401 -    err = child_string(exp, ovif, &vif);
  7.1402 -    if(err) goto exit;
  7.1403 -    err = child_int(exp, ovnet, &vnet);
  7.1404 -    if(err) goto exit;
  7.1405 -    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
  7.1406 - exit:
  7.1407 -    dprintf("< err=%d\n", err);
  7.1408 -    return err;
  7.1409 -}
  7.1410 -
  7.1411 -int eval(Sxpr exp){
  7.1412 -    int err = 0;
  7.1413 -    Sxpr oconnect = intern("connect");
  7.1414 -    Sxpr ovnet = intern("vnet");
  7.1415 -    
  7.1416 -    if(sxpr_elementp(exp, ovnet)){
  7.1417 -        err = eval_vnet(exp);
  7.1418 -    } else if(sxpr_elementp(exp, oconnect)){
  7.1419 -        err = eval_connect(exp);
  7.1420 -    } else {
  7.1421 -        err = -EINVAL;
  7.1422 -    }
  7.1423 -    return err;
  7.1424 -}
  7.1425 +//#include "string_stream.h"
  7.1426  
  7.1427  /** Main program for testing.
  7.1428   * Parses input and prints it.
  7.1429 @@ -907,14 +962,16 @@ int main(int argc, char *argv[]){
  7.1430      char buf[1024];
  7.1431      int k;
  7.1432      Sxpr obj;
  7.1433 -    //Sxpr l, x;
  7.1434      int i = 0;
  7.1435  
  7.1436      pin = Parser_new();
  7.1437 -    set_error_stream(pin, iostdout);
  7.1438 +    Parser_set_error_stream(pin, iostdout);
  7.1439      dprintf("> parse...\n");
  7.1440      while(1){
  7.1441 -        k = fread(buf, 1, 1, stdin);
  7.1442 +        k = fread(buf, 1, 100, stdin);
  7.1443 +        if(k>=0){
  7.1444 +            buf[k+1] = '\0';
  7.1445 +        }
  7.1446          err = Parser_input(pin, buf, k);
  7.1447          while(Parser_ready(pin)){
  7.1448              obj = Parser_get_val(pin);
  7.1449 @@ -923,12 +980,6 @@ int main(int argc, char *argv[]){
  7.1450          }
  7.1451          if(k <= 0) break;
  7.1452      }
  7.1453 -/*     obj = Parser_get_all(pin); */
  7.1454 -/*     for(l = obj ; CONSP(l); l = CDR(l)){ */
  7.1455 -/*         x = CAR(l); */
  7.1456 -/*         objprint(iostdout, x, 0); printf("\n"); */
  7.1457 -/*         eval(x); */
  7.1458 -/*     } */
  7.1459      dprintf("> err=%d\n", err);
  7.1460      return 0;
  7.1461  }
     8.1 --- a/tools/libxutil/sxpr_parser.h	Fri May 13 15:01:20 2005 +0000
     8.2 +++ b/tools/libxutil/sxpr_parser.h	Fri May 13 15:08:29 2005 +0000
     8.3 @@ -1,5 +1,5 @@
     8.4  /*
     8.5 - * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     8.6 + * Copyright (C) 2001 - 2005 Mike Wray <mike.wray@hp.com>
     8.7   *
     8.8   * This library is free software; you can redistribute it and/or modify
     8.9   * it under the terms of the GNU Lesser General Public License as
    8.10 @@ -25,10 +25,13 @@
    8.11   * Sxpr parsing definitions.
    8.12   */
    8.13  
    8.14 -/** Size of a parser input buffer.
    8.15 - * Tokens read must fit into this size (including trailing null).
    8.16 +/** Initial size of a parser input buffer.
    8.17   */
    8.18 -#define PARSER_BUF_SIZE 4096
    8.19 +#define PARSER_BUF_SIZE 512
    8.20 +
    8.21 +/** Input buffer size increment (when it's full).
    8.22 + */
    8.23 +#define PARSER_BUF_INCREMENT 512
    8.24  
    8.25  struct Parser;
    8.26  typedef int ParserStateFn(struct Parser *, char c);
    8.27 @@ -43,13 +46,14 @@ typedef struct ParserState {
    8.28      char *name;
    8.29  } ParserState;
    8.30  
    8.31 -/** Structure representing an input source for the parser.
    8.32 - * Can read from any IOStream implementation.
    8.33 - */
    8.34  typedef struct Parser {
    8.35 +    /** Initial state function. */
    8.36 +    ParserStateFn *begin;
    8.37 +    /** Parse value. */
    8.38      Sxpr val;
    8.39      /** Error reporting stream (null for no reports). */
    8.40      IOStream *error_out;
    8.41 +    /** End-of-file flag, */
    8.42      int eof;
    8.43      /** Error flag. Non-zero if there has been a read error. */
    8.44      int err;
    8.45 @@ -57,13 +61,11 @@ typedef struct Parser {
    8.46      int line_no;
    8.47      /** Column number of input (reset on new line). */
    8.48      int char_no;
    8.49 -    /** Lookahead character. */
    8.50 -    char c;
    8.51      /** Buffer for reading tokens. */
    8.52 -    char buf[PARSER_BUF_SIZE];
    8.53 -    /** Size of token buffer. */
    8.54 -    int buf_n;
    8.55 -    int buf_i;
    8.56 +    char *buf;
    8.57 +    char *buf_end;
    8.58 +    char *tok;
    8.59 +    char *tok_end;
    8.60      /** Line the last token started on. */
    8.61      int tok_begin_line;
    8.62      /** Character number the last token started on. */
    8.63 @@ -95,7 +97,7 @@ typedef enum {
    8.64   * @param in parser
    8.65   * @param flags flags mask
    8.66   */
    8.67 -inline static void parser_flags_raise(Parser *in, int flags){
    8.68 +inline static void Parser_flags_raise(Parser *in, int flags){
    8.69      in->flags |= flags;
    8.70  }
    8.71  
    8.72 @@ -104,7 +106,7 @@ inline static void parser_flags_raise(Pa
    8.73   * @param in parser
    8.74   * @param flags flags mask
    8.75   */
    8.76 -inline static void parser_flags_lower(Parser *in, int flags){
    8.77 +inline static void Parser_flags_lower(Parser *in, int flags){
    8.78      in->flags &= ~flags;
    8.79  }
    8.80  
    8.81 @@ -112,7 +114,7 @@ inline static void parser_flags_lower(Pa
    8.82   *
    8.83   * @param in parser
    8.84   */
    8.85 -inline static void parser_flags_clear(Parser *in){
    8.86 +inline static void Parser_flags_clear(Parser *in){
    8.87      in->flags = 0;
    8.88  }
    8.89  
    8.90 @@ -121,14 +123,32 @@ extern Parser * Parser_new(void);
    8.91  extern int Parser_input(Parser *p, char *buf, int buf_n);
    8.92  extern int Parser_input_eof(Parser *p);
    8.93  extern int Parser_input_char(Parser *p, char c);
    8.94 -extern void set_error_stream(Parser *z, IOStream *error_out);
    8.95 +extern void Parser_set_error_stream(Parser *z, IOStream *error_out);
    8.96 +
    8.97 +extern int Parser_error_message(Parser *in, char *buf, int n);
    8.98 +extern int Parser_has_error(Parser *in);
    8.99 +extern int Parser_at_eof(Parser *in);
   8.100 +
   8.101 +extern int Parser_ready(Parser *p);
   8.102 +extern Sxpr Parser_get_val(Parser *p);
   8.103 +extern Sxpr Parser_get_all(Parser *p);
   8.104  
   8.105 -extern int parse_error_message(Parser *in, char *buf, int n);
   8.106 -extern int has_error(Parser *in);
   8.107 -extern int at_eof(Parser *in);
   8.108 +/* Internal parser api. */
   8.109 +void Parser_pop(Parser *p);
   8.110 +int Parser_push(Parser *p, ParserStateFn *fn, char *name);
   8.111 +int Parser_return(Parser *p);
   8.112 +int Parser_at_eof(Parser *p);
   8.113 +int Parser_error(Parser *in);
   8.114 +int Parser_set_value(Parser *p, Sxpr val);
   8.115 +int Parser_intern(Parser *p);
   8.116 +int Parser_string(Parser *p);
   8.117 +int Parser_data(Parser *p);
   8.118 +int Parser_uint(Parser *p);
   8.119  
   8.120 -int Parser_ready(Parser *p);
   8.121 -Sxpr Parser_get_val(Parser *p);
   8.122 -Sxpr Parser_get_all(Parser *p);
   8.123 +char *peek_token(Parser *p);
   8.124 +char *copy_token(Parser *p);
   8.125 +void new_token(Parser *p);
   8.126 +int save_char(Parser *p, char c);
   8.127 +int token_len(Parser *p);
   8.128  
   8.129  #endif /* ! _XUTIL_SXPR_PARSER_H_ */
     9.1 --- a/tools/libxutil/sys_string.c	Fri May 13 15:01:20 2005 +0000
     9.2 +++ b/tools/libxutil/sys_string.c	Fri May 13 15:08:29 2005 +0000
     9.3 @@ -49,6 +49,27 @@ inline static const char * convert_set_b
     9.4      return s;
     9.5  }
     9.6  
     9.7 +/** Set the sign to use for converting a string to a number.
     9.8 + * Value is 1 for positive, -1 for negative.
     9.9 + *
    9.10 + * @param s input string
    9.11 + * @param sign where to put the sign
    9.12 + * @return rest of s to parse as a number
    9.13 + */
    9.14 +inline static const char * convert_set_sign(const char *s, int *sign){
    9.15 +    *sign = 1;
    9.16 +    if(s){
    9.17 +        if(*s == '+'){
    9.18 +            *sign = 1;
    9.19 +            s++;
    9.20 +        } else if (*s == '-'){
    9.21 +            *sign = -1;
    9.22 +            s++;
    9.23 +        }
    9.24 +    }
    9.25 +    return s;
    9.26 +}
    9.27 +
    9.28  /** Get the numerical value of a digit in the given base.
    9.29   *
    9.30   * @param c digit character
    9.31 @@ -103,6 +124,40 @@ int convert_atoul(const char *str, unsig
    9.32      return err;
    9.33  }
    9.34  
    9.35 +/** Convert a string to a long by parsing it as a number.
    9.36 + * Will accept hex or decimal in usual C syntax.
    9.37 + *
    9.38 + * @param str input string
    9.39 + * @param val where to put the result
    9.40 + * @return 0 if converted OK, negative otherwise
    9.41 + */
    9.42 +int convert_atol(const char *str, long *val){
    9.43 +    int err = 0;
    9.44 +    unsigned long v = 0;
    9.45 +    int base, sign = 1;
    9.46 +    const char *s = str;
    9.47 +
    9.48 +    if(!s) {
    9.49 +        err = -EINVAL;
    9.50 +        goto exit;
    9.51 +    }
    9.52 +    s = convert_set_sign(s, &sign);
    9.53 +    s = convert_set_base(s, &base);
    9.54 +    for( ; !err && *s; s++){
    9.55 +        int digit = convert_get_digit(*s, base);
    9.56 +        if(digit<0){
    9.57 +            err = -EINVAL;
    9.58 +            goto exit;
    9.59 +        }
    9.60 +        v *= base;
    9.61 +        v += digit;
    9.62 +    } 
    9.63 +    if(sign < 0) v = -v;
    9.64 +  exit:
    9.65 +    *val = (err ? 0 : v);
    9.66 +    return err;
    9.67 +}
    9.68 +
    9.69  /** Combine a directory path with a relative path to produce
    9.70   * a new path.
    9.71   *
    10.1 --- a/tools/libxutil/sys_string.h	Fri May 13 15:01:20 2005 +0000
    10.2 +++ b/tools/libxutil/sys_string.h	Fri May 13 15:08:29 2005 +0000
    10.3 @@ -86,6 +86,7 @@ static inline size_t strnlen(const char 
    10.4  /*============================================================================*/
    10.5  
    10.6  extern int convert_atoul(const char *s, unsigned long *v);
    10.7 +extern int convert_atol(const char *s, long *v);
    10.8  extern int path_concat(char *s, char *t, char **val);
    10.9  
   10.10  #endif /* !_XUTIL_SYS_STRING_H_ */
    11.1 --- a/tools/python/xen/xend/server/SrvDaemon.py	Fri May 13 15:01:20 2005 +0000
    11.2 +++ b/tools/python/xen/xend/server/SrvDaemon.py	Fri May 13 15:08:29 2005 +0000
    11.3 @@ -60,7 +60,6 @@ class Daemon:
    11.4              if not pm: continue
    11.5              xm = xendre.match(pm.group('cmd'))
    11.6              if not xm: continue
    11.7 -            #print 'pid=', pm.group('pid'), 'cmd=', pm.group('cmd')
    11.8              pids.append(int(pm.group('pid')))
    11.9          return pids
   11.10  
   11.11 @@ -313,7 +312,7 @@ class Daemon:
   11.12              os.setuid(pwd.getpwnam(XEND_USER)[2])
   11.13              return 0
   11.14          except KeyError, error:
   11.15 -            print "Error: no such user '%s'" % XEND_USER
   11.16 +            print >>sys.stderr, "Error: no such user '%s'" % XEND_USER
   11.17              return 1
   11.18  
   11.19      def stop(self):
   11.20 @@ -328,7 +327,6 @@ class Daemon:
   11.21              self.listenChannels()
   11.22              servers = SrvServer.create()
   11.23              self.daemonize()
   11.24 -            print 'running serverthread...'
   11.25              servers.start()
   11.26          except Exception, ex:
   11.27              print >>sys.stderr, 'Exception starting xend:', ex
   11.28 @@ -342,14 +340,12 @@ class Daemon:
   11.29  
   11.30      def listenChannels(self):
   11.31          def virqReceived(virq):
   11.32 -            print 'virqReceived>', virq
   11.33              eserver.inject('xend.virq', virq)
   11.34  
   11.35          self.channelF.setVirqHandler(virqReceived)
   11.36          self.channelF.start()
   11.37  
   11.38      def exit(self, rc=0):
   11.39 -        #reactor.disconnectAll()
   11.40          if self.channelF:
   11.41              self.channelF.stop()
   11.42          # Calling sys.exit() raises a SystemExit exception, which only
    12.1 --- a/tools/python/xen/xend/server/event.py	Fri May 13 15:01:20 2005 +0000
    12.2 +++ b/tools/python/xen/xend/server/event.py	Fri May 13 15:08:29 2005 +0000
    12.3 @@ -3,17 +3,13 @@ import StringIO
    12.4  
    12.5  from xen.web import reactor, protocol
    12.6  
    12.7 -from xen.lowlevel import xu
    12.8 -
    12.9  from xen.xend import sxp
   12.10  from xen.xend import PrettyPrint
   12.11 -from xen.xend import EventServer
   12.12 -eserver = EventServer.instance()
   12.13 +from xen.xend import EventServer; eserver = EventServer.instance()
   12.14  from xen.xend.XendError import XendError
   12.15 -
   12.16  from xen.xend import XendRoot; xroot = XendRoot.instance()
   12.17  
   12.18 -DEBUG = 1
   12.19 +DEBUG = 0
   12.20  
   12.21  class EventProtocol(protocol.Protocol):
   12.22      """Asynchronous handler for a connected event socket.
   12.23 @@ -30,7 +26,7 @@ class EventProtocol(protocol.Protocol):
   12.24          self.pretty = 0
   12.25  
   12.26          # For debugging subscribe to everything and make output pretty.
   12.27 -        self.subscribe(['*'])
   12.28 +        #self.subscribe(['*'])
   12.29          self.pretty = 1
   12.30  
   12.31      def dataReceived(self, data):
   12.32 @@ -45,10 +41,7 @@ class EventProtocol(protocol.Protocol):
   12.33          except SystemExit:
   12.34              raise
   12.35          except:
   12.36 -            if DEBUG:
   12.37 -                raise
   12.38 -            else:
   12.39 -                self.send_error()
   12.40 +            self.send_error()
   12.41  
   12.42      def loseConnection(self):
   12.43          if self.transport:
   12.44 @@ -73,7 +66,11 @@ class EventProtocol(protocol.Protocol):
   12.45              return 0
   12.46  
   12.47      def send_result(self, res):
   12.48 -        return self.send_reply(['ok', res])
   12.49 +        if res is None:
   12.50 +            resp = ['ok']
   12.51 +        else:
   12.52 +            resp = ['ok', res]
   12.53 +        return self.send_reply(resp)
   12.54  
   12.55      def send_error(self):
   12.56          (extype, exval) = sys.exc_info()[:2]
   12.57 @@ -129,7 +126,6 @@ class EventProtocol(protocol.Protocol):
   12.58  
   12.59      def op_pretty(self, name, req):
   12.60          self.pretty = 1
   12.61 -        return ['ok']
   12.62  
   12.63      def op_console_disconnect(self, name, req):
   12.64          id = sxp.child_value(req, 'id')
   12.65 @@ -137,7 +133,6 @@ class EventProtocol(protocol.Protocol):
   12.66              raise XendError('Missing console id')
   12.67          id = int(id)
   12.68          self.daemon.console_disconnect(id)
   12.69 -        return ['ok']
   12.70  
   12.71      def op_info(self, name, req):
   12.72          val = ['info']
   12.73 @@ -151,13 +146,11 @@ class EventProtocol(protocol.Protocol):
   12.74          # (sys.subscribe event*)
   12.75          # Subscribe to the events:
   12.76          self.subscribe(v[1:])
   12.77 -        return ['ok']
   12.78  
   12.79      def op_sys_inject(self, name, v):
   12.80          # (sys.inject event)
   12.81          event = v[1]
   12.82          eserver.inject(sxp.name(event), event)
   12.83 -        return ['ok']
   12.84  
   12.85      def op_trace(self, name, v):
   12.86          mode = (v[1] == 'on')
   12.87 @@ -181,6 +174,27 @@ class EventProtocol(protocol.Protocol):
   12.88          import controller
   12.89          controller.DEBUG = (mode == 'on')
   12.90  
   12.91 +    def op_domain_ls(self, name, v):
   12.92 +        xd = xroot.get_component("xen.xend.XendDomain")
   12.93 +        return xd.domain_ls()
   12.94 +
   12.95 +    def op_domain_configure(self, name, v):
   12.96 +        domid = sxp.child_value(v, "dom")
   12.97 +        config = sxp.child_value(v, "config")
   12.98 +        if domid is None:
   12.99 +            raise XendError("missing domain id")
  12.100 +        if config is None:
  12.101 +            raise XendError("missing domain config")
  12.102 +        xd = xroot.get_component("xen.xend.XendDomain")
  12.103 +        xd.domain_configure(domid, config)
  12.104 +
  12.105 +    def op_domain_unpause(self, name, v):
  12.106 +        domid = sxp.child_value(v, "dom")
  12.107 +        if domid is None:
  12.108 +            raise XendError("missing domain id")
  12.109 +        xd = xroot.get_component("xen.xend.XendDomain")
  12.110 +        xd.domain_unpause(domid)
  12.111 +
  12.112  class EventFactory(protocol.ServerFactory):
  12.113      """Asynchronous handler for the event server socket.
  12.114      """
    13.1 --- a/tools/xfrd/Make.xfrd	Fri May 13 15:01:20 2005 +0000
    13.2 +++ b/tools/xfrd/Make.xfrd	Fri May 13 15:08:29 2005 +0000
    13.3 @@ -6,6 +6,7 @@ UTIL_LIB = libutil.a
    13.4  UTIL_LIB_SRC =
    13.5  UTIL_LIB_SRC += allocate.c
    13.6  UTIL_LIB_SRC += enum.c
    13.7 +UTIL_LIB_SRC += fd_stream.c
    13.8  UTIL_LIB_SRC += file_stream.c
    13.9  UTIL_LIB_SRC += gzip_stream.c
   13.10  UTIL_LIB_SRC += hash_table.c
   13.11 @@ -19,7 +20,7 @@ UTIL_LIB_SRC += sxpr_parser.c
   13.12  UTIL_LIB_SRC += sys_net.c
   13.13  UTIL_LIB_SRC += sys_string.c
   13.14  #UTIL_LIB_SRC += util.c
   13.15 -UTIL_LIB_SRC += xdr.c
   13.16 +#UTIL_LIB_SRC += xdr.c
   13.17  
   13.18  #----------------------------------------------------------------------------
   13.19  # Xfrd.
    14.1 --- a/tools/xfrd/Makefile	Fri May 13 15:01:20 2005 +0000
    14.2 +++ b/tools/xfrd/Makefile	Fri May 13 15:08:29 2005 +0000
    14.3 @@ -26,18 +26,11 @@ UTIL_LIB_OBJ = $(UTIL_LIB_SRC:.c=.o)
    14.4  XFRD_PROG_OBJ = $(XFRD_PROG_SRC:.c=.o)
    14.5  XFRD_PROG_OBJ += $(UTIL_LIB)
    14.6  
    14.7 -# Flag controlling whether to use stubs.
    14.8 -# Define to use stubs, undefine to use the real Xen functions.
    14.9 -#CPPFLAGS += -D _XEN_XFR_STUB_
   14.10 -
   14.11 -ifeq ($(SXPR_DEBUG),1)
   14.12 -CPPFLAGS += -D _XEN_XFR_STUB_ -D SXPR_PARSER_MAIN
   14.13 -endif
   14.14 -
   14.15  CC := gcc
   14.16  
   14.17  CFLAGS += -Wall -Werror -O3 -fno-strict-aliasing
   14.18  CFLAGS += $(INCLUDES)
   14.19 +
   14.20  # Make gcc generate dependencies.
   14.21  CFLAGS += -Wp,-MD,.$(@F).d
   14.22  PROG_DEP = .*.d
   14.23 @@ -55,12 +48,6 @@ XFRD_LIBS += -L $(XEN_LIBXUTIL) -lxutil
   14.24  # zlib library.
   14.25  XFRD_LIBS += -lz
   14.26  
   14.27 -CURL_FLAGS = $(shell curl-config --cflags)
   14.28 -CURL_LIBS  = $(shell curl-config --libs)
   14.29 -CFLAGS     += $(CURL_FLAGS)
   14.30 -# libcurl libraries.
   14.31 -XFRD_LIBS += $(CURL_LIBS)
   14.32 -
   14.33  #$(warning XFRD_LIBS = $(XFRD_LIBS))
   14.34  
   14.35  all: build
    15.1 --- a/tools/xfrd/connection.c	Fri May 13 15:01:20 2005 +0000
    15.2 +++ b/tools/xfrd/connection.c	Fri May 13 15:08:29 2005 +0000
    15.3 @@ -171,7 +171,7 @@ int Conn_sxpr(Conn *conn, Sxpr *sxpr){
    15.4      dprintf(">\n");
    15.5      if(!conn->parser){
    15.6          conn->parser = Parser_new();
    15.7 -        set_error_stream(conn->parser, iostdout);
    15.8 +        Parser_set_error_stream(conn->parser, iostdout);
    15.9      }
   15.10      while(!err && c >= 0 && !Parser_ready(conn->parser)){
   15.11          c = IOStream_getc(conn->in);
    16.1 --- a/tools/xfrd/lzi_stream.c	Fri May 13 15:01:20 2005 +0000
    16.2 +++ b/tools/xfrd/lzi_stream.c	Fri May 13 15:08:29 2005 +0000
    16.3 @@ -475,7 +475,6 @@ static int lzi_close(IOStream *io){
    16.4   */
    16.5  static void lzi_free(IOStream *s){
    16.6      LZIState *state = lzi_state(s);
    16.7 -    IOStream_free(state->io);
    16.8      LZIState_free(state);
    16.9      s->data = NULL;
   16.10  }
   16.11 @@ -525,8 +524,8 @@ IOStream *lzi_stream_fdopen(int fd, cons
   16.12      err = 0;
   16.13    exit:
   16.14      if(err){
   16.15 -        IOStream_free(io);
   16.16 -        IOStream_free(zio);
   16.17 +        IOStream_close(io);
   16.18 +        IOStream_close(zio);
   16.19          zio = NULL;
   16.20      }
   16.21      return zio;
    17.1 --- a/tools/xfrd/xen_domain.c	Fri May 13 15:01:20 2005 +0000
    17.2 +++ b/tools/xfrd/xen_domain.c	Fri May 13 15:08:29 2005 +0000
    17.3 @@ -1,17 +1,18 @@
    17.4  #include <unistd.h>
    17.5  #include <stdlib.h>
    17.6  #include <stdio.h>
    17.7 +#include <sys/socket.h>
    17.8 +#include <sys/un.h>
    17.9  
   17.10 -#ifdef _XEN_XFR_STUB_
   17.11 -typedef unsigned long u32;
   17.12 -#else
   17.13  #include "xc.h"
   17.14  #include "xc_io.h"
   17.15 -#endif
   17.16 +
   17.17 +#include "sxpr.h"
   17.18 +#include "sxpr_parser.h"
   17.19 +#include "file_stream.h"
   17.20 +#include "fd_stream.h"
   17.21  
   17.22  #include "xen_domain.h"
   17.23 -#include "marshal.h"
   17.24 -#include "xdr.h"
   17.25  #include "xfrd.h"
   17.26  
   17.27  #define MODULE_NAME "XFRD"
   17.28 @@ -33,7 +34,6 @@ int domain_configure(void *data, u32 dom
   17.29      return xen_domain_configure(dom, vmconfig, vmconfig_n);
   17.30  }
   17.31  
   17.32 -#ifndef _XEN_XFR_STUB_
   17.33  static int xc_handle = 0;
   17.34  
   17.35  int xcinit(void){
   17.36 @@ -50,7 +50,6 @@ void xcfini(void){
   17.37          xc_handle = 0;
   17.38      }
   17.39  }
   17.40 -#endif   
   17.41  
   17.42  /** Write domain state.
   17.43   *
   17.44 @@ -62,31 +61,6 @@ int xen_domain_snd(Conn *xend, IOStream 
   17.45                     char *vmconfig, int vmconfig_n,
   17.46                     int live, int resource){
   17.47      int err = 0;
   17.48 -#ifdef _XEN_XFR_STUB_
   17.49 -    char buf[1024];
   17.50 -    int n, k, d, buf_n;
   17.51 -    dprintf("> dom=%d\n", dom);
   17.52 -    err = marshal_uint32(io, dom);
   17.53 -    if(err) goto exit;
   17.54 -    err = marshal_string(io, vmconfig, vmconfig_n);
   17.55 -    if(err) goto exit;
   17.56 -    n = 32 * 1024 * 1024;
   17.57 -    n = 32 * 1024;
   17.58 -    buf_n = sizeof(buf);
   17.59 -    err = marshal_uint32(io, n);
   17.60 -    for(k = 0; k < n; k += d){
   17.61 -        d = n - k;
   17.62 -        if(d > buf_n) d = buf_n;
   17.63 -        err = marshal_bytes(io, buf, d);
   17.64 -        if(err) goto exit;
   17.65 -        dprintf("> k=%d n=%d\n", k, n);
   17.66 -    }
   17.67 -    
   17.68 -    dom = 99;
   17.69 -    err = domain_suspend(xend, dom);
   17.70 -    IOStream_close(io);
   17.71 -  exit:
   17.72 -#else 
   17.73      XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
   17.74      ioctxt->domain = dom;
   17.75      ioctxt->io = io;
   17.76 @@ -101,7 +75,6 @@ int xen_domain_snd(Conn *xend, IOStream 
   17.77      }
   17.78      ioctxt->resource = resource;
   17.79      err = xc_linux_save(xcinit(), ioctxt);
   17.80 -#endif   
   17.81      dprintf("< err=%d\n", err);
   17.82      return err;
   17.83  }
   17.84 @@ -114,25 +87,6 @@ int xen_domain_rcv(IOStream *io,
   17.85                     char **vmconfig, int *vmconfig_n,
   17.86                     int *configured){
   17.87      int err = 0;
   17.88 -#ifdef _XEN_XFR_STUB_
   17.89 -    char buf[1024];
   17.90 -    int n, k, d, buf_n;
   17.91 -    dprintf(">\n");
   17.92 -    err = unmarshal_uint32(io, dom);
   17.93 -    if(err) goto exit;
   17.94 -    err = unmarshal_new_string(io, vmconfig, vmconfig_n);
   17.95 -    if(err) goto exit;
   17.96 -    err = unmarshal_uint32(io, &n);
   17.97 -    buf_n = sizeof(buf);
   17.98 -    for(k = 0; k < n; k += d){
   17.99 -        d = n - k;
  17.100 -        if(d > buf_n) d = buf_n;
  17.101 -        err = unmarshal_bytes(io, buf, d);
  17.102 -        if(err) goto exit;
  17.103 -        dprintf("> k=%d n=%d\n", k, n);
  17.104 -    }
  17.105 -  exit:
  17.106 -#else    
  17.107      XcIOContext _ioctxt = {}, *ioctxt = &_ioctxt;
  17.108      dprintf(">\n");
  17.109      ioctxt->io = io;
  17.110 @@ -147,137 +101,182 @@ int xen_domain_rcv(IOStream *io,
  17.111      *vmconfig = ioctxt->vmconfig;
  17.112      *vmconfig_n = ioctxt->vmconfig_n;
  17.113      *configured = (ioctxt->flags & XCFLAGS_CONFIGURE);
  17.114 -#endif   
  17.115      dprintf("< err=%d\n", err);
  17.116      return err;
  17.117  }
  17.118  
  17.119 -#include <curl/curl.h>
  17.120 -#include "http.h"
  17.121 -
  17.122 -/** Flag indicating whether we need to initialize libcurl. 
  17.123 - */
  17.124 -static int do_curl_global_init = 1;
  17.125 +typedef struct xend {
  17.126 +    int fd;
  17.127 +    IOStream *io;
  17.128 +    Parser *parser;
  17.129 +    int seeneof;
  17.130 +} Xend;
  17.131  
  17.132 -/** Get a curl handle, initializing libcurl if needed.
  17.133 - *
  17.134 - * @return curl handle
  17.135 - */
  17.136 -static CURL *curlinit(void){
  17.137 -    if(do_curl_global_init){
  17.138 -        do_curl_global_init = 0;
  17.139 -        // Stop libcurl using the proxy. There's a curl option to
  17.140 -        // set the proxy - but no option to defeat it.
  17.141 -        unsetenv("http_proxy");
  17.142 -        curl_global_init(CURL_GLOBAL_ALL);
  17.143 -    }
  17.144 -    return curl_easy_init();
  17.145 -}
  17.146 -
  17.147 -/** Curl debug function.
  17.148 - */
  17.149 -int curldebug(CURL *curl, curl_infotype ty, char *buf, int buf_n, void *data){
  17.150 -    // printf("%*s\n", buf_n, buf); /* Does not compile correctly on non 32bit platforms */
  17.151 -    fwrite(data, buf_n, 1, stdout);
  17.152 -    printf("\n");
  17.153 -    return 0;
  17.154 +char *xend_server_addr(void){
  17.155 +    char * val = getenv("XEND_EVENT_ADDR");
  17.156 +    return (val ? val : "/var/lib/xend/event-socket");
  17.157  }
  17.158  
  17.159 -/** Setup a curl handle with a url.
  17.160 - * Creates the url by formatting 'fmt' and the remaining arguments.
  17.161 - *
  17.162 - * @param pcurl return parameter for the curl handle
  17.163 - * @param url url buffer
  17.164 - * @param url_n size of url
  17.165 - * @param fmt url format string, followed by parameters
  17.166 - * @return 0 on success, error code otherwise
  17.167 +/** Open a unix-domain socket to the xend server.
  17.168   */
  17.169 -static int curlsetup(CURL **pcurl, struct curl_slist **pheaders, char *url, int url_n, char *fmt, ...){
  17.170 +int xend_open_fd(void){
  17.171 +    struct sockaddr_un addr_un = { .sun_family = AF_UNIX };
  17.172 +    struct sockaddr *addr = (struct sockaddr*)&addr_un;
  17.173 +    int addr_n = sizeof(addr_un);
  17.174      int err = 0;
  17.175 -    va_list args;
  17.176 -    CURL *curl = NULL;
  17.177 -    struct curl_slist *headers = NULL;
  17.178 -    int n = 0;
  17.179  
  17.180 -    curl = curlinit();
  17.181 -    if(!curl){
  17.182 -        eprintf("> Could not init libcurl\n");
  17.183 -        err = -ENOMEM;
  17.184 +    int fd = socket(AF_UNIX, SOCK_STREAM, 0);
  17.185 +    if(fd < 0){
  17.186 +        err = -errno;
  17.187 +        perror("socket");
  17.188 +        goto exit;
  17.189 +    }
  17.190 +    strcpy(addr_un.sun_path, xend_server_addr());
  17.191 +    if(connect(fd, addr, addr_n) < 0){
  17.192 +        err = -errno;
  17.193 +        perror("connect");
  17.194          goto exit;
  17.195      }
  17.196 -    url_n -= 1;
  17.197 -    va_start(args, fmt);
  17.198 -    n = vsnprintf(url, url_n, fmt, args);
  17.199 -    va_end(args);
  17.200 -    if(n <= 0 || n >= url_n){
  17.201 -        err = -ENOMEM;
  17.202 -        eprintf("> Out of memory in url\n");
  17.203 +  exit:
  17.204 +    if(err && (fd >= 0)){
  17.205 +        close(fd);
  17.206 +    }
  17.207 +    
  17.208 +    return (err ? err : fd);
  17.209 +}
  17.210 +
  17.211 +/** Close a connection to the server.
  17.212 + *
  17.213 +  * @param xend connection
  17.214 +*/
  17.215 +void xend_close(Xend *xend){
  17.216 +    if(!xend) return;
  17.217 +    close(xend->fd);
  17.218 +    Parser_free(xend->parser);
  17.219 +}
  17.220 +
  17.221 +/** Open a connection to the server.
  17.222 + *
  17.223 + * @param xend result parameter for the connection
  17.224 + * @return 0 on success, negative error code otherwise
  17.225 + */
  17.226 +int xend_open(Xend **xend){
  17.227 +    int err = 0;
  17.228 +    Xend *val = ALLOCATE(Xend);
  17.229 +
  17.230 +    val->fd = xend_open_fd();
  17.231 +
  17.232 +    if(val->fd < 0){
  17.233 +        err = val->fd;
  17.234          goto exit;
  17.235      }
  17.236 -    dprintf("> url=%s\n", url);
  17.237 -#if DEBUG
  17.238 -    // Verbose.
  17.239 -    curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
  17.240 -    // Call the debug function on data received.
  17.241 -    curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, curldebug);
  17.242 -#else
  17.243 -    // No progress meter.
  17.244 -    curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
  17.245 -    // Completely quiet.
  17.246 -    curl_easy_setopt(curl, CURLOPT_MUTE, 1);
  17.247 -#endif
  17.248 -    // Set the URL.
  17.249 -    curl_easy_setopt(curl, CURLOPT_URL, url);
  17.250 -
  17.251 -    headers = curl_slist_append(headers, "Expect:");
  17.252 -    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
  17.253 -    
  17.254 +    val->io = fd_stream_new(val->fd);
  17.255 +    val->parser = Parser_new();
  17.256    exit:
  17.257 -    if(err && curl){
  17.258 -        curl_easy_cleanup(curl);
  17.259 -        curl = NULL;
  17.260 -    }
  17.261 -    *pcurl = curl;
  17.262 -    if (pheaders)
  17.263 -	*pheaders = headers;
  17.264 +    if(err) xend_close(val);
  17.265 +    *xend = (err ? NULL : val);
  17.266      return err;
  17.267  }
  17.268  
  17.269 -static void curlcleanup(CURL **pcurl, struct curl_slist **pheaders){
  17.270 -    if (*pcurl)
  17.271 -	curl_easy_cleanup(*pcurl);
  17.272 -    if (*pheaders)
  17.273 -	curl_slist_free_all(*pheaders);
  17.274 -    *pcurl = NULL;
  17.275 -    *pheaders = NULL;
  17.276 -}
  17.277 -/** Make the http request stored in the curl handle and get
  17.278 - *  the result code from the curl code and the http return code.
  17.279 - *
  17.280 - * @param curl curl handle
  17.281 - * @return 0 for success, error code otherwise
  17.282 +/** Read a response from a server connection.
  17.283   */
  17.284 -int curlresult(CURL *curl){
  17.285 +int xend_read_resp(Xend *xend, Sxpr *resp){
  17.286      int err = 0;
  17.287 -    CURLcode curlcode = 0;
  17.288 -    long httpcode = 0;
  17.289 +    Sxpr val = ONONE;
  17.290 +    char buf[1024];
  17.291 +    int buf_n = sizeof(buf), n;
  17.292  
  17.293 -    curlcode = curl_easy_perform(curl);
  17.294 -    if(curlcode){
  17.295 -        eprintf("> curlcode=%d\n", curlcode);
  17.296 -        err = -EINVAL;
  17.297 -        goto exit;
  17.298 -    }
  17.299 -    curl_easy_getinfo(curl, CURLINFO_HTTP_CODE, &httpcode);
  17.300 -    if(httpcode != HTTP_OK){
  17.301 -        eprintf("> httpcode=%d\n", (int)httpcode);
  17.302 -        err = -EINVAL;
  17.303 -        goto exit;
  17.304 +    for( ; ; ){
  17.305 +        if(Parser_ready(xend->parser)){
  17.306 +            val = Parser_get_val(xend->parser);
  17.307 +            goto exit;
  17.308 +        }
  17.309 +        if(xend->seeneof){
  17.310 +            err = -EIO;
  17.311 +            goto exit;
  17.312 +        }
  17.313 +        memset(buf, 0, buf_n);
  17.314 +        n = IOStream_read(xend->io, buf, 100);
  17.315 +        if(n <= 0){
  17.316 +            xend->seeneof = 1;
  17.317 +            err = Parser_input_eof(xend->parser);
  17.318 +        } else {
  17.319 +            err = Parser_input(xend->parser, buf, n);
  17.320 +        }
  17.321      }
  17.322    exit:
  17.323 +    *resp = (err < 0 ? ONONE : val);
  17.324      return err;
  17.325  }
  17.326  
  17.327 +/** Read a response from a server connection and decode the value.
  17.328 + *
  17.329 + * @param xend server connection
  17.330 + * @param resp result parameter for the response value
  17.331 + * @return 0 on success, negative error code otherwise
  17.332 + */
  17.333 +int xend_read(Xend *xend, Sxpr *resp){
  17.334 +    int err = 0;
  17.335 +    Sxpr val = ONONE;
  17.336 +
  17.337 +    dprintf(">\n");
  17.338 +    for( ; ; ){
  17.339 +        err = xend_read_resp(xend, &val);
  17.340 +        if(err < 0) goto exit;
  17.341 +        
  17.342 +        if(sxpr_is(sxpr_name(val), "event")){
  17.343 +            // We don't care about events, try again.
  17.344 +            err = 0;
  17.345 +            continue;
  17.346 +        } else if(sxpr_is(sxpr_name(val), "err")){
  17.347 +            eprintf("> "); objprint(iostderr, val, 0); fprintf(stderr, "\n");
  17.348 +            err = -EINVAL;
  17.349 +            break;
  17.350 +        } else {
  17.351 +            err = 0;
  17.352 +            val = sxpr_child0(val, ONULL);
  17.353 +            break;
  17.354 +        }
  17.355 +    }
  17.356 +#ifdef DEBUG
  17.357 +    dprintf("> OK ");
  17.358 +    objprint(iostdout, val, 0);
  17.359 +    printf("\n");
  17.360 +#endif
  17.361 +  exit:
  17.362 +    if(resp){
  17.363 +        *resp = (err < 0 ? ONONE : val);
  17.364 +    }
  17.365 +    dprintf("> err=%d\n", err);
  17.366 +    return err;
  17.367 +}
  17.368 +
  17.369 +/** Send a request to the server and return the result value in resp.
  17.370 + *
  17.371 + * @param xend server connection
  17.372 + * @param resp result parameter for the response value
  17.373 + * @param format request format followed by args to print
  17.374 + * @return 0 on success, negative error code otherwise
  17.375 + */
  17.376 +int xend_call(Xend *xend, Sxpr *resp, char *format, ...){
  17.377 +    va_list args;
  17.378 +    int err;
  17.379 +    
  17.380 +    dprintf("> ");
  17.381 +    va_start(args, format);
  17.382 +#ifdef DEBUG
  17.383 +    vprintf(format, args); printf("\n");
  17.384 +#endif
  17.385 +    err = IOStream_vprint(xend->io, format, args);
  17.386 +    va_end(args);
  17.387 +    if(err < 0) goto exit;
  17.388 +    IOStream_flush(xend->io);
  17.389 +    err = xend_read(xend, resp);
  17.390 +  exit:
  17.391 +    dprintf("> err=%d\n", err);
  17.392 +    return (err < 0 ? err : 0);
  17.393 +}
  17.394 +
  17.395  /** Get xend to list domains.
  17.396   * We use this to force xend to refresh its domain list.
  17.397   *
  17.398 @@ -285,18 +284,12 @@ int curlresult(CURL *curl){
  17.399   */
  17.400  int xen_domain_ls(void){
  17.401      int err = 0;
  17.402 -    CURL *curl = NULL;
  17.403 -    struct curl_slist *headers = NULL;
  17.404 -    char url[128] = {};
  17.405 -    int url_n = sizeof(url);
  17.406 -
  17.407 -    dprintf(">\n");
  17.408 -    err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain", XEND_PORT);
  17.409 +    Xend *xend = NULL;
  17.410 +    err = xend_open(&xend);
  17.411      if(err) goto exit;
  17.412 -    err = curlresult(curl);
  17.413 +    err = xend_call(xend, NULL, "(domain.ls)");
  17.414    exit:
  17.415 -    curlcleanup(&curl, &headers);
  17.416 -    dprintf("< err=%d\n", err);
  17.417 +    xend_close(xend);
  17.418      return err;
  17.419  }
  17.420  
  17.421 @@ -309,49 +302,18 @@ int xen_domain_ls(void){
  17.422   */
  17.423  int xen_domain_configure(uint32_t dom, char *vmconfig, int vmconfig_n){
  17.424      int err = 0;
  17.425 -    CURL *curl = NULL;
  17.426 -    struct curl_slist *headers = NULL;
  17.427 -    char url[128] = {};
  17.428 -    int url_n = sizeof(url);
  17.429 -    struct curl_httppost *form = NULL, *last = NULL;
  17.430 -    CURLFORMcode formcode = 0;
  17.431 -
  17.432 +    Xend *xend = NULL;
  17.433      dprintf("> dom=%u\n", dom);
  17.434      // List domains so that xend will update its domain list and notice the new domain.
  17.435      xen_domain_ls();
  17.436 -
  17.437 -    err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
  17.438 +    // Now configure it.
  17.439 +    err = xend_open(&xend);
  17.440      if(err) goto exit;
  17.441 -
  17.442 -    // Config field - set from vmconfig.
  17.443 -    formcode = curl_formadd(&form, &last,
  17.444 -                            CURLFORM_COPYNAME,     "config",
  17.445 -                            CURLFORM_BUFFER,       "config",
  17.446 -                            CURLFORM_BUFFERPTR,    vmconfig,
  17.447 -                            CURLFORM_BUFFERLENGTH, vmconfig_n,
  17.448 -                            CURLFORM_CONTENTTYPE,  "application/octet-stream",
  17.449 -                            CURLFORM_END);
  17.450 -    if(formcode){
  17.451 -        eprintf("> Error adding config field.\n");
  17.452 -        goto exit;
  17.453 -    }
  17.454 -    // Op field.
  17.455 -    formcode = curl_formadd(&form, &last,
  17.456 -                            CURLFORM_COPYNAME,     "op",
  17.457 -                            CURLFORM_COPYCONTENTS, "configure",
  17.458 -                            CURLFORM_END);
  17.459 -    if(formcode){
  17.460 -        eprintf("> Error adding op field.\n");
  17.461 -        err = -EINVAL;
  17.462 -        goto exit;
  17.463 -    }
  17.464 -    // POST the form.
  17.465 -    curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
  17.466 -    err = curlresult(curl);
  17.467 +    err = xend_call(xend, NULL, "(domain.configure (dom %d) (config %*s))",
  17.468 +                    dom, vmconfig_n, vmconfig);
  17.469    exit:
  17.470 -    curlcleanup(&curl, &headers);
  17.471 -    if(form) curl_formfree(form);
  17.472      dprintf("< err=%d\n", err);
  17.473 +    xend_close(xend);
  17.474      return err;
  17.475  }
  17.476  
  17.477 @@ -362,34 +324,11 @@ int xen_domain_configure(uint32_t dom, c
  17.478   */
  17.479  int xen_domain_unpause(uint32_t dom){
  17.480      int err = 0;
  17.481 -    CURL *curl = NULL;
  17.482 -    struct curl_slist *headers = NULL;
  17.483 -    char url[128] = {};
  17.484 -    int url_n = sizeof(url);
  17.485 -    struct curl_httppost *form = NULL, *last = NULL;
  17.486 -    CURLFORMcode formcode = 0;
  17.487 -
  17.488 -    dprintf("> dom=%u\n", dom);
  17.489 -
  17.490 -    err = curlsetup(&curl, &headers, url, url_n, "http://localhost:%d/xend/domain/%u", XEND_PORT, dom);
  17.491 +    Xend *xend = NULL;
  17.492 +    err = xend_open(&xend);
  17.493      if(err) goto exit;
  17.494 -
  17.495 -    // Op field.
  17.496 -    formcode = curl_formadd(&form, &last,
  17.497 -                            CURLFORM_COPYNAME,     "op",
  17.498 -                            CURLFORM_COPYCONTENTS, "unpause",
  17.499 -                            CURLFORM_END);
  17.500 -    if(formcode){
  17.501 -        eprintf("> Error adding op field.\n");
  17.502 -        err = -EINVAL;
  17.503 -        goto exit;
  17.504 -    }
  17.505 -    // POST the form.
  17.506 -    curl_easy_setopt(curl, CURLOPT_HTTPPOST, form);
  17.507 -    err = curlresult(curl);
  17.508 +    err = xend_call(xend, NULL, "(domain.unpause (dom %d))", dom);
  17.509    exit:
  17.510 -    curlcleanup(&curl, &headers);
  17.511 -    if(form) curl_formfree(form);
  17.512 -    dprintf("< err=%d\n", err);
  17.513 +    xend_close(xend);
  17.514      return err;
  17.515  }
    18.1 --- a/tools/xfrd/xfrd.c	Fri May 13 15:01:20 2005 +0000
    18.2 +++ b/tools/xfrd/xfrd.c	Fri May 13 15:08:29 2005 +0000
    18.3 @@ -188,7 +188,6 @@ enum {
    18.4      XFR_MAX
    18.5  };
    18.6  
    18.7 -#ifndef SXPR_PARSER_MAIN
    18.8  /** Short options. Options followed by ':' take an argument. */
    18.9  static char *short_opts = (char[]){
   18.10      OPT_PORT,     ':',
   18.11 @@ -213,7 +212,6 @@ static Args _args = {};
   18.12  
   18.13  /** Xfrd arguments. */
   18.14  static Args *args = &_args;
   18.15 -#endif
   18.16  
   18.17  /** Initialize an array element for a constant to its string name. */
   18.18  #define VALDEF(val) { val, #val }
   18.19 @@ -782,7 +780,6 @@ int xfr_save(Args *args, XfrState *state
   18.20    exit:
   18.21      if(io){
   18.22          IOStream_close(io);
   18.23 -        IOStream_free(io);
   18.24      }
   18.25      if(err){
   18.26          unlink(file);
   18.27 @@ -798,7 +795,7 @@ int xfr_save(Args *args, XfrState *state
   18.28  int xfr_restore(Args *args, XfrState *state, Conn *xend, char *file){
   18.29      int err = 0;
   18.30      IOStream *io = NULL;
   18.31 -    int configured=0;
   18.32 +    int configured = 0;
   18.33  
   18.34      dprintf("> file=%s\n", file);
   18.35      io = gzip_stream_fopen(file, "rb");
   18.36 @@ -820,7 +817,6 @@ int xfr_restore(Args *args, XfrState *st
   18.37    exit:
   18.38      if(io){
   18.39          IOStream_close(io);
   18.40 -        IOStream_free(io);
   18.41      }
   18.42      if(err){
   18.43          xfr_error(xend, err);
   18.44 @@ -1215,7 +1211,6 @@ int xfrd_main(Args *args){
   18.45      return err;
   18.46  }
   18.47  
   18.48 -#ifndef SXPR_PARSER_MAIN
   18.49  /** Parse command-line arguments and call the xfrd main program.
   18.50   *
   18.51   * @param arg argument count
   18.52 @@ -1271,4 +1266,3 @@ int main(int argc, char *argv[]){
   18.53      }
   18.54      return (err ? 1 : 0);
   18.55  }
   18.56 -#endif