ia64/xen-unstable

changeset 1611:cdccf1a15b0f

bitkeeper revision 1.1026.1.2 (40e15b09oBOK6QWmjoE3IKmAR5xlVA)

Merge http://xen.bkbits.net:8080/xeno-unstable.bk
into gandalf.hpl.hp.com:/var/bk/xeno-unstable.bk
author xenbk@gandalf.hpl.hp.com
date Tue Jun 29 12:05:29 2004 +0000 (2004-06-29)
parents cf2f7da0af83 be911ab15381
children d881debab3eb 498a8eca0ab9
files .rootkeys BitKeeper/etc/ignore tools/examples/xmdefaults tools/lib/allocate.c tools/lib/allocate.h tools/lib/debug.h tools/lib/enum.c tools/lib/enum.h tools/lib/file_stream.c tools/lib/file_stream.h tools/lib/gzip_stream.c tools/lib/gzip_stream.h tools/lib/hash_table.c tools/lib/hash_table.h tools/lib/iostream.c tools/lib/iostream.h tools/lib/kernel_stream.c tools/lib/kernel_stream.h tools/lib/lexis.c tools/lib/lexis.h tools/lib/lzi_stream.c tools/lib/lzi_stream.h tools/lib/lzo_stream.c tools/lib/lzo_stream.h tools/lib/marshal.c tools/lib/marshal.h tools/lib/socket_stream.c tools/lib/socket_stream.h tools/lib/string_stream.c tools/lib/string_stream.h tools/lib/sxpr.c tools/lib/sxpr.h tools/lib/sxpr_parser.c tools/lib/sxpr_parser.h tools/lib/sys_ctype.h tools/lib/sys_net.c tools/lib/sys_net.h tools/lib/sys_string.c tools/lib/sys_string.h tools/lib/xdr.c tools/lib/xdr.h tools/misc/Makefile tools/xc/lib/Makefile tools/xc/lib/xc.h tools/xc/lib/xc_io.c tools/xc/lib/xc_io.h tools/xc/lib/xc_linux_restore.c tools/xc/lib/xc_linux_save.c tools/xc/lib/xc_private.h tools/xc/py/Xc.c tools/xc/py/setup.py tools/xen/lib/xend/XendDomain.py tools/xen/lib/xend/XendDomainInfo.py tools/xen/lib/xend/server/SrvDomain.py tools/xen/lib/xend/server/SrvDomainDir.py tools/xen/lib/xend/sxp.py tools/xen/lib/xm/create.py tools/xen/lib/xm/main.py tools/xen/lib/xm/opts.py tools/xen/lib/xm/shutdown.py tools/xen/xend tools/xentrace/Makefile
line diff
     1.1 --- a/.rootkeys	Tue Jun 29 00:51:10 2004 +0000
     1.2 +++ b/.rootkeys	Tue Jun 29 12:05:29 2004 +0000
     1.3 @@ -164,6 +164,44 @@ 401d7e16RJj-lbtsVEjua6HYAIiKiA tools/exa
     1.4  40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
     1.5  40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
     1.6  40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
     1.7 +40e033325Sjqs-_4TuzeUEprP_gYFg tools/lib/allocate.c
     1.8 +40e03332KYz7o1bn2MG_KPbBlyoIMA tools/lib/allocate.h
     1.9 +40e03332IyRttYoXKoJla5qCC514SQ tools/lib/debug.h
    1.10 +40e03332qV5tJ-GJZjo-LBCeGuEjJA tools/lib/enum.c
    1.11 +40e03332wwMVxfobgA1PSMTSAGLiCw tools/lib/enum.h
    1.12 +40e03332p5Dc_owJQRuN72ymJZddFQ tools/lib/file_stream.c
    1.13 +40e03332jWfB2viAhLSkq1WK0r_iDQ tools/lib/file_stream.h
    1.14 +40e03332rUjNMGg11n2rN6V4DCrvOg tools/lib/gzip_stream.c
    1.15 +40e033321O5Qg22haLoq5lpmk4tooQ tools/lib/gzip_stream.h
    1.16 +40e03332QrTR96tc6yS2rMBpd2mq1A tools/lib/hash_table.c
    1.17 +40e033325KoIb0d_uy8s7b5DUR9fPQ tools/lib/hash_table.h
    1.18 +40e03332ihnBGzHykVwZnFmkAppb4g tools/lib/iostream.c
    1.19 +40e03332UGwbLR4wsw4ft14p0Yw5pg tools/lib/iostream.h
    1.20 +40e0333245DLDzJemeSVBLuutHtzEQ tools/lib/kernel_stream.c
    1.21 +40e03332aK0GkgpDdc-PVTkWKTeOBg tools/lib/kernel_stream.h
    1.22 +40e03332HJ0cDcZDKDUUT-tEiBWOZw tools/lib/lexis.c
    1.23 +40e03332tnH9Ggzxbfi3xY9Vh2hUlg tools/lib/lexis.h
    1.24 +40e03332aYIW0BNBh6wXuKKn_P7Yyg tools/lib/lzi_stream.c
    1.25 +40e0333233voTffE4cJSMGJARfiSSQ tools/lib/lzi_stream.h
    1.26 +40e03332FXuMoUnfsAKSgV8X4rFbYQ tools/lib/lzo_stream.c
    1.27 +40e03332InJaiLfpDcIXBy2fI0RFGQ tools/lib/lzo_stream.h
    1.28 +40e03332a5SCuRsejHStTuWzMQNv8Q tools/lib/marshal.c
    1.29 +40e03332TwKyJrZQiiQfNq4vc2hpgw tools/lib/marshal.h
    1.30 +40e033328ccHlJuTR1FswYL_EC6LFA tools/lib/socket_stream.c
    1.31 +40e03332P0KVQGkmahj47aafo1X0nA tools/lib/socket_stream.h
    1.32 +40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/lib/string_stream.c
    1.33 +40e03332-VtK6_OZa1vMHXFil8uq6w tools/lib/string_stream.h
    1.34 +40e03332dDtczi6YX7_mMxhYjJeAdQ tools/lib/sxpr.c
    1.35 +40e03332QPuyNKDOTIYVvkwK5qO-vg tools/lib/sxpr.h
    1.36 +40e03332Pi0_osJ3XPBi38ADPqdl4A tools/lib/sxpr_parser.c
    1.37 +40e033324v5QFMvWEXXzv38uUT9kHg tools/lib/sxpr_parser.h
    1.38 +40e03332gKUInsqtxQOV4mPiMqf_dg tools/lib/sys_ctype.h
    1.39 +40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/lib/sys_net.c
    1.40 +40e03332lQHvQHw4Rh7VsT1_sui29A tools/lib/sys_net.h
    1.41 +40e033321smklZd7bDSdWvQCeIshtg tools/lib/sys_string.c
    1.42 +40e03332h5V611rRWURRLqb1Ekatxg tools/lib/sys_string.h
    1.43 +40e03332u4q5kgF0N7RfqB4s0pZVew tools/lib/xdr.c
    1.44 +40e03332hY16nfRXF4gGd5S1aUJUBw tools/lib/xdr.h
    1.45  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.46  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.47  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.48 @@ -185,6 +223,8 @@ 3fbba6dbEVkVMX0JuDFzap9jeaucGA tools/xc/
    1.49  3fbba6dbasJQV-MVElDC0DGSHMiL5w tools/xc/lib/xc_domain.c
    1.50  40278d99BLsfUv3qxv0I8C1sClZ0ow tools/xc/lib/xc_elf.h
    1.51  403e0977Bjsm_e82pwvl9VvaJxh8Gg tools/xc/lib/xc_evtchn.c
    1.52 +40e03333Eegw8czSWvHsbKxrRZJjRA tools/xc/lib/xc_io.c
    1.53 +40e03333vrWGbLAhyJjXlqCHaJt7eA tools/xc/lib/xc_io.h
    1.54  3fbba6dbNCU7U6nsMYiXzKkp3ztaJg tools/xc/lib/xc_linux_build.c
    1.55  3fbba6dbl267zZOAVHYLOdLCdhcZMw tools/xc/lib/xc_linux_restore.c
    1.56  3fbba6db7li3FJiABYtCmuGxOJxEGw tools/xc/lib/xc_linux_save.c
     2.1 --- a/BitKeeper/etc/ignore	Tue Jun 29 00:51:10 2004 +0000
     2.2 +++ b/BitKeeper/etc/ignore	Tue Jun 29 12:05:29 2004 +0000
     2.3 @@ -3,8 +3,8 @@
     2.4  *.pyc
     2.5  *.so
     2.6  *.so.*
     2.7 +*.tar.bz2
     2.8  *.tar.gz
     2.9 -*.tar.bz2
    2.10  *~
    2.11  BitKeeper/*/*
    2.12  PENDING/*
    2.13 @@ -12,15 +12,34 @@ TAGS
    2.14  extras/mini-os/h/hypervisor-ifs
    2.15  install
    2.16  install/*
    2.17 +linux-*-xen*/*
    2.18 +linux-2.4.26-xen/*
    2.19 +linux-xen-sparse
    2.20  patches/*
    2.21 -linux-*-xen*/*
    2.22 -linux-xen-sparse
    2.23  tools/*/build/lib*/*.py
    2.24  tools/balloon/balloon
    2.25  tools/misc/miniterm/miniterm
    2.26  tools/misc/xen_cpuperf
    2.27  tools/misc/xen_log
    2.28  tools/misc/xen_read_console
    2.29 +tools/xc/lib/.allocate.o.d
    2.30 +tools/xc/lib/.file_stream.o.d
    2.31 +tools/xc/lib/.gzip_stream.o.d
    2.32 +tools/xc/lib/.iostream.o.d
    2.33 +tools/xc/lib/.sys_net.o.d
    2.34 +tools/xc/lib/.sys_string.o.d
    2.35 +tools/xc/lib/.xc_atropos.o.d
    2.36 +tools/xc/lib/.xc_bvtsched.o.d
    2.37 +tools/xc/lib/.xc_domain.o.d
    2.38 +tools/xc/lib/.xc_evtchn.o.d
    2.39 +tools/xc/lib/.xc_io.o.d
    2.40 +tools/xc/lib/.xc_linux_build.o.d
    2.41 +tools/xc/lib/.xc_linux_restore.o.d
    2.42 +tools/xc/lib/.xc_linux_save.o.d
    2.43 +tools/xc/lib/.xc_misc.o.d
    2.44 +tools/xc/lib/.xc_netbsd_build.o.d
    2.45 +tools/xc/lib/.xc_physdev.o.d
    2.46 +tools/xc/lib/.xc_private.o.d
    2.47  tools/xentrace/xentrace
    2.48  xen/drivers/pci/classlist.h
    2.49  xen/drivers/pci/devlist.h
     3.1 --- a/tools/examples/xmdefaults	Tue Jun 29 00:51:10 2004 +0000
     3.2 +++ b/tools/examples/xmdefaults	Tue Jun 29 12:05:29 2004 +0000
     3.3 @@ -5,9 +5,6 @@
     3.4  # This file expects the variable 'vmid' to be set.
     3.5  #============================================================================
     3.6  
     3.7 -import sys
     3.8 -import xenctl.ip
     3.9 -
    3.10  try:
    3.11      vmid = int(vmid) # convert to integer
    3.12  except:
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/lib/allocate.c	Tue Jun 29 12:05:29 2004 +0000
     4.3 @@ -0,0 +1,116 @@
     4.4 +/*
     4.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     4.6 + *
     4.7 + * This library is free software; you can redistribute it and/or modify
     4.8 + * it under the terms of the GNU Lesser General Public License as published by
     4.9 + * the Free Software Foundation; either version 2.1 of the License, or
    4.10 + * (at your option) any later version.
    4.11 + *
    4.12 + * This library is distributed in the hope that it will be useful,
    4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    4.15 + * GNU Lesser General Public License for more details.
    4.16 + *
    4.17 + * You should have received a copy of the GNU Lesser General Public License
    4.18 + * along with this library; if not, write to the Free Software
    4.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    4.20 + */
    4.21 +
    4.22 +#include "allocate.h"
    4.23 +
    4.24 +/** @file
    4.25 + * Support for allocating memory.
    4.26 + * Usable from user code or kernel code (with __KERNEL__ defined).
    4.27 + * In user code will use GC if USE_GC is defined.
    4.28 + */
    4.29 +
    4.30 +#ifdef __KERNEL__
    4.31 +/*----------------------------------------------------------------------------*/
    4.32 +#  include <linux/config.h>
    4.33 +#  include <linux/slab.h>
    4.34 +#  include <linux/string.h>
    4.35 +#  include <linux/types.h>
    4.36 +
    4.37 +#  define DEFAULT_TYPE    0
    4.38 +#  define MALLOC(n, type) kmalloc(n, type)
    4.39 +#  define FREE(ptr)       kfree(ptr)
    4.40 +
    4.41 +/*----------------------------------------------------------------------------*/
    4.42 +#else /* ! __KERNEL__ */
    4.43 +
    4.44 +#  include <stdlib.h>
    4.45 +#  include <string.h>
    4.46 +
    4.47 +#  define DEFAULT_TYPE    0
    4.48 +
    4.49 +#ifdef USE_GC
    4.50 +#  include "gc.h"
    4.51 +#  define MALLOC(n, typ)  GC_malloc(n)
    4.52 +#  define FREE(ptr)       (ptr=NULL)
    4.53 +//typedef void *GC_PTR;
    4.54 +//GC_PTR (*GC_oom_fn)(size_t n);
    4.55 +#else
    4.56 +#  define MALLOC(n, type) malloc(n)
    4.57 +#  define FREE(ptr)       free(ptr)
    4.58 +#endif
    4.59 +
    4.60 +/*----------------------------------------------------------------------------*/
    4.61 +#endif
    4.62 +
    4.63 +/** Function to call when memory cannot be allocated. */
    4.64 +AllocateFailedFn *allocate_failed_fn = NULL;
    4.65 +
    4.66 +/** Allocate memory and zero it.
    4.67 + * The type is only relevant when calling from kernel code,
    4.68 + * from user code it is ignored.
    4.69 + * In kernel code the values accepted by kmalloc can be used:
    4.70 + * GFP_USER, GFP_ATOMIC, GFP_KERNEL.
    4.71 + *
    4.72 + * @param size number of bytes to allocate
    4.73 + * @param type memory type to allocate (kernel only)
    4.74 + * @return pointer to the allocated memory or zero
    4.75 + * if malloc failed
    4.76 + */
    4.77 +void *allocate_type(int size, int type){
    4.78 +    void *p = MALLOC(size, type);
    4.79 +    if(p){
    4.80 +        memzero(p, size);
    4.81 +    } else if(allocate_failed_fn){
    4.82 +        allocate_failed_fn(size, type);
    4.83 +    }
    4.84 +    return p;
    4.85 +}
    4.86 +
    4.87 +/** Allocate memory and zero it.
    4.88 + *
    4.89 + * @param size number of bytes to allocate
    4.90 + * @return pointer to the allocated memory or zero
    4.91 + * if malloc failed
    4.92 + */
    4.93 +void *allocate(int size){
    4.94 +    return allocate_type(size, DEFAULT_TYPE);
    4.95 +}
    4.96 +
    4.97 +/** Free memory allocated by allocate().
    4.98 + * No-op if 'p' is null.
    4.99 + *
   4.100 + * @param p memory to free
   4.101 + */
   4.102 +void deallocate(void *p){
   4.103 +    if(p){
   4.104 +        FREE(p);
   4.105 +    }
   4.106 +}
   4.107 +
   4.108 +/** Set bytes to zero.
   4.109 + * No-op if 'p' is null.
   4.110 + *
   4.111 + * @param p memory to zero
   4.112 + * @param size number of bytes to zero
   4.113 + */
   4.114 +void memzero(void *p, int size){
   4.115 +    if(p){
   4.116 +        memset(p, 0, (size_t)size);
   4.117 +    }
   4.118 +}
   4.119 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/lib/allocate.h	Tue Jun 29 12:05:29 2004 +0000
     5.3 @@ -0,0 +1,45 @@
     5.4 +/*
     5.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     5.6 + *
     5.7 + * This library is free software; you can redistribute it and/or modify
     5.8 + * it under the terms of the GNU Lesser General Public License as published by
     5.9 + * the Free Software Foundation; either version 2.1 of the License, or
    5.10 + * (at your option) any later version.
    5.11 + *
    5.12 + * This library is distributed in the hope that it will be useful,
    5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    5.15 + * GNU Lesser General Public License for more details.
    5.16 + *
    5.17 + * You should have received a copy of the GNU Lesser General Public License
    5.18 + * along with this library; if not, write to the Free Software
    5.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.20 + */
    5.21 +
    5.22 +#ifndef _XEN_LIB_ALLOCATE_H_
    5.23 +#define _XEN_LIB_ALLOCATE_H_
    5.24 +
    5.25 +/** Allocate memory for a given type, and cast. */
    5.26 +#define ALLOCATE(ctype) (ctype *)allocate(sizeof(ctype))
    5.27 +
    5.28 +/** Allocate memory for a given type, and cast. */
    5.29 +#define ALLOCATE_TYPE(ctype, type) (ctype *)allocate(sizeof(ctype))
    5.30 +
    5.31 +extern void *allocate_type(int size, int type);
    5.32 +extern void *allocate(int size);
    5.33 +extern void deallocate(void *);
    5.34 +extern void memzero(void *p, int size);
    5.35 +
    5.36 +typedef void AllocateFailedFn(int size, int type);
    5.37 +extern AllocateFailedFn *allocate_failed_fn;
    5.38 +
    5.39 +#endif /* _XEN_LIB_ALLOCATE_H_ */
    5.40 +
    5.41 +
    5.42 +
    5.43 +
    5.44 +
    5.45 +
    5.46 +
    5.47 +
    5.48 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/lib/debug.h	Tue Jun 29 12:05:29 2004 +0000
     6.3 @@ -0,0 +1,72 @@
     6.4 +/*
     6.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     6.6 + *
     6.7 + * This library is free software; you can redistribute it and/or modify
     6.8 + * it under the terms of the GNU Lesser General Public License as published by
     6.9 + * the Free Software Foundation; either version 2.1 of the License, or
    6.10 + * (at your option) any later version.
    6.11 + *
    6.12 + * This library is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU Lesser General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU Lesser General Public License
    6.18 + * along with this library; if not, write to the Free Software
    6.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    6.20 + */
    6.21 +#ifndef _XEN_LIB_DEBUG_H_
    6.22 +#define _XEN_LIB_DEBUG_H_
    6.23 +
    6.24 +#ifndef MODULE_NAME
    6.25 +#define MODULE_NAME ""
    6.26 +#endif
    6.27 +
    6.28 +#ifdef __KERNEL__
    6.29 +#include <linux/config.h>
    6.30 +#include <linux/kernel.h>
    6.31 +
    6.32 +#ifdef DEBUG
    6.33 +
    6.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG   "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.36 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.37 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.38 +
    6.39 +#else
    6.40 +
    6.41 +#define dprintf(fmt, args...) do {} while(0)
    6.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args)
    6.43 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME fmt, ##args)
    6.44 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME fmt, ##args)
    6.45 +
    6.46 +#endif
    6.47 +
    6.48 +#else
    6.49 +
    6.50 +#include <stdio.h>
    6.51 +
    6.52 +#ifdef DEBUG
    6.53 +
    6.54 +#define dprintf(fmt, args...) fprintf(stdout, "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.55 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.56 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.57 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    6.58 +
    6.59 +#else
    6.60 +
    6.61 +#define dprintf(fmt, args...) do {} while(0)
    6.62 +#define wprintf(fmt, args...) fprintf(stderr, "[WRN] " MODULE_NAME fmt, ##args)
    6.63 +#define iprintf(fmt, args...) fprintf(stderr, "[INF] " MODULE_NAME fmt, ##args)
    6.64 +#define eprintf(fmt, args...) fprintf(stderr, "[ERR] " MODULE_NAME fmt, ##args)
    6.65 +
    6.66 +#endif
    6.67 +
    6.68 +#endif
    6.69 +
    6.70 +/** Print format for an IP address.
    6.71 + * See NIPQUAD(), HIPQUAD()
    6.72 + */
    6.73 +#define IPFMT "%u.%u.%u.%u"
    6.74 +
    6.75 +#endif /* ! _XEN_LIB_DEBUG_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/lib/enum.c	Tue Jun 29 12:05:29 2004 +0000
     7.3 @@ -0,0 +1,61 @@
     7.4 +/*
     7.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
     7.6 + *
     7.7 + * This library is free software; you can redistribute it and/or modify
     7.8 + * it under the terms of the GNU Lesser General Public License as
     7.9 + * published by the Free Software Foundation; either version 2.1 of the
    7.10 + * License, or  (at your option) any later version. This library is 
    7.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
    7.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
    7.13 + * FITNESS FOR A PARTICULAR PURPOSE.
    7.14 + * See the GNU Lesser General Public License for more details.
    7.15 + *
    7.16 + * You should have received a copy of the GNU Lesser General Public License
    7.17 + * along with this library; if not, write to the Free Software Foundation,
    7.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    7.19 + */
    7.20 +
    7.21 +#ifdef __KERNEL__
    7.22 +#include <linux/errno.h>
    7.23 +#else
    7.24 +#include <errno.h>
    7.25 +#endif
    7.26 +
    7.27 +#include "sys_string.h"
    7.28 +#include "enum.h"
    7.29 +
    7.30 +/** Map an enum name to its value using a table.
    7.31 + *
    7.32 + * @param name enum name
    7.33 + * @param defs enum definitions
    7.34 + * @return enum value or -1 if not known
    7.35 + */
    7.36 +int enum_name_to_val(char *name, EnumDef *defs){
    7.37 +    int val = -1;
    7.38 +    for(; defs->name; defs++){
    7.39 +	if(!strcmp(defs->name, name)){
    7.40 +	    val = defs->val;
    7.41 +	    break;
    7.42 +	}
    7.43 +    }
    7.44 +    return val;
    7.45 +}
    7.46 +
    7.47 +/** Map an enum value to its name using a table.
    7.48 + *
    7.49 + * @param val enum value
    7.50 + * @param defs enum definitions
    7.51 + * @param defs_n number of definitions
    7.52 + * @return enum name or NULL if not known
    7.53 + */
    7.54 +char *enum_val_to_name(int val, EnumDef *defs){
    7.55 +    char *name = NULL;
    7.56 +    for(; defs->name; defs++){
    7.57 +	if(val == defs->val){
    7.58 +	    name = defs->name;
    7.59 +	    break;
    7.60 +	}
    7.61 +    }
    7.62 +    return name;
    7.63 +}
    7.64 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/lib/enum.h	Tue Jun 29 12:05:29 2004 +0000
     8.3 @@ -0,0 +1,30 @@
     8.4 +/*
     8.5 + * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
     8.6 + *
     8.7 + * This library is free software; you can redistribute it and/or modify
     8.8 + * it under the terms of the GNU Lesser General Public License as
     8.9 + * published by the Free Software Foundation; either version 2.1 of the
    8.10 + * License, or  (at your option) any later version. This library is 
    8.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
    8.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
    8.13 + * FITNESS FOR A PARTICULAR PURPOSE.
    8.14 + * See the GNU Lesser General Public License for more details.
    8.15 + *
    8.16 + * You should have received a copy of the GNU Lesser General Public License
    8.17 + * along with this library; if not, write to the Free Software Foundation,
    8.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    8.19 + */
    8.20 +
    8.21 +#ifndef _XEN_LIB_ENUM_H_
    8.22 +#define _XEN_LIB_ENUM_H_
    8.23 +
    8.24 +/** Mapping of an enum value to a name. */
    8.25 +typedef struct EnumDef {
    8.26 +    int val;
    8.27 +    char *name;
    8.28 +} EnumDef;
    8.29 +
    8.30 +extern int enum_name_to_val(char *name, EnumDef *defs);
    8.31 +extern char *enum_val_to_name(int val, EnumDef *defs);
    8.32 +
    8.33 +#endif /* _XEN_LIB_ENUM_H_ */
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tools/lib/file_stream.c	Tue Jun 29 12:05:29 2004 +0000
     9.3 @@ -0,0 +1,202 @@
     9.4 +/*
     9.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     9.6 + *
     9.7 + * This library is free software; you can redistribute it and/or modify
     9.8 + * it under the terms of the GNU Lesser General Public License as published by
     9.9 + * the Free Software Foundation; either version 2.1 of the License, or
    9.10 + * (at your option) any later version.
    9.11 + *
    9.12 + * This library is distributed in the hope that it will be useful,
    9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.15 + * GNU Lesser General Public License for more details.
    9.16 + *
    9.17 + * You should have received a copy of the GNU Lesser General Public License
    9.18 + * along with this library; if not, write to the Free Software
    9.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.20 + */
    9.21 +
    9.22 +/** @file
    9.23 + * An IOStream implementation using FILE*.
    9.24 + */
    9.25 +#ifndef __KERNEL__
    9.26 +#include <stdio.h>
    9.27 +#include <stdlib.h>
    9.28 +#include "allocate.h"
    9.29 +#include "file_stream.h"
    9.30 +
    9.31 +static int file_read(IOStream *s, void *buf, size_t n);
    9.32 +static int file_write(IOStream *s, const void *buf, size_t n);
    9.33 +static int file_error(IOStream *s);
    9.34 +static int file_close(IOStream *s);
    9.35 +static void file_free(IOStream *s);
    9.36 +static int file_flush(IOStream *s);
    9.37 +
    9.38 +/** Methods used by a FILE* IOStream. */
    9.39 +static const IOMethods file_methods = {
    9.40 +    read:  file_read,
    9.41 +    write: file_write,
    9.42 +    error: file_error,
    9.43 +    close: file_close,
    9.44 +    free:  file_free,
    9.45 +    flush: file_flush,
    9.46 +};
    9.47 +
    9.48 +/** IOStream for stdin. */
    9.49 +static IOStream _iostdin = {
    9.50 +    methods: &file_methods,
    9.51 +    data: (void*)1,
    9.52 +};
    9.53 +
    9.54 +/** IOStream for stdout. */
    9.55 +static IOStream _iostdout = {
    9.56 +    methods: &file_methods,
    9.57 +    data: (void*)2,
    9.58 +};
    9.59 +
    9.60 +/** IOStream for stderr. */
    9.61 +static IOStream _iostderr = {
    9.62 +    methods: &file_methods,
    9.63 +    data: (void*)3,
    9.64 +};
    9.65 +
    9.66 +/** IOStream for stdin. */
    9.67 +IOStream *iostdin = &_iostdin;
    9.68 +
    9.69 +/** IOStream for stdout. */
    9.70 +IOStream *iostdout = &_iostdout;
    9.71 +
    9.72 +/** IOStream for stderr. */
    9.73 +IOStream *iostderr = &_iostderr;
    9.74 +
    9.75 +/** Get the underlying FILE*.
    9.76 + * 
    9.77 + * @param s file stream
    9.78 + * @return the stream s wraps
    9.79 + */
    9.80 +static inline FILE *get_file(IOStream *s){
    9.81 +    switch((long)s->data){
    9.82 +    case 1: s->data = stdin; break;
    9.83 +    case 2: s->data = stdout; break;
    9.84 +    case 3: s->data = stderr; break;
    9.85 +    }
    9.86 +    return (FILE*)s->data;
    9.87 +}
    9.88 +
    9.89 +/** Control buffering on the underlying stream, like setvbuf().
    9.90 + *
    9.91 + * @param io file stream
    9.92 + * @param buf buffer
    9.93 + * @param mode buffering mode (see man setvbuf())
    9.94 + * @param size buffer size
    9.95 + * @return 0 on success, non-zero otherwise
    9.96 + */
    9.97 +int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size){
    9.98 +    return setvbuf(get_file(io), buf, mode, size);
    9.99 +}
   9.100 +
   9.101 +/** Write to the underlying stream using fwrite();
   9.102 + *
   9.103 + * @param stream input
   9.104 + * @param buf where to put input
   9.105 + * @param n number of bytes to write
   9.106 + * @return number of bytes written
   9.107 + */
   9.108 +static int file_write(IOStream *s, const void *buf, size_t n){
   9.109 +    return fwrite(buf, 1, n, get_file(s));
   9.110 +}
   9.111 +
   9.112 +/** Read from the underlying stream using fread();
   9.113 + *
   9.114 + * @param stream input
   9.115 + * @param buf where to put input
   9.116 + * @param n number of bytes to read
   9.117 + * @return number of bytes read
   9.118 + */
   9.119 +static int file_read(IOStream *s, void *buf, size_t n){
   9.120 +    return fread(buf, 1, n, get_file(s));
   9.121 +}
   9.122 +
   9.123 +/** Fush the underlying stream using fflush().
   9.124 + *
   9.125 + * @param s file stream
   9.126 + * @return 0 on success, error code otherwise
   9.127 + */
   9.128 +static int file_flush(IOStream *s){
   9.129 +    return fflush(get_file(s));
   9.130 +}
   9.131 +
   9.132 +/** Check if a stream has an error.
   9.133 + *
   9.134 + * @param s file stream
   9.135 + * @return 1 if has an error, 0 otherwise
   9.136 + */
   9.137 +static int file_error(IOStream *s){
   9.138 +    return ferror(get_file(s));
   9.139 +}
   9.140 +
   9.141 +/** Close a file stream.
   9.142 + *
   9.143 + * @param s file stream to close
   9.144 + * @return result of the close
   9.145 + */
   9.146 +static int file_close(IOStream *s){
   9.147 +    return fclose(get_file(s));
   9.148 +}
   9.149 +
   9.150 +/** Free a file stream.
   9.151 + *
   9.152 + * @param s file stream
   9.153 + */
   9.154 +static void file_free(IOStream *s){
   9.155 +    // Do nothing - fclose does it all?
   9.156 +}
   9.157 +
   9.158 +/** Create an IOStream for a stream.
   9.159 + *
   9.160 + * @param f stream to wrap
   9.161 + * @return new IOStream using f for i/o
   9.162 + */
   9.163 +IOStream *file_stream_new(FILE *f){
   9.164 +    IOStream *io = ALLOCATE(IOStream);
   9.165 +    if(io){
   9.166 +	io->methods = &file_methods;
   9.167 +	io->data = (void*)f;
   9.168 +    }
   9.169 +    return io;
   9.170 +}
   9.171 +
   9.172 +/** IOStream version of fopen().
   9.173 + *
   9.174 + * @param file name of the file to open
   9.175 + * @param flags giving the mode to open in (as for fopen())
   9.176 + * @return new stream for the open file, or 0 if failed
   9.177 + */
   9.178 +IOStream *file_stream_fopen(const char *file, const char *flags){
   9.179 +    IOStream *io = 0;
   9.180 +    FILE *fin = fopen(file, flags);
   9.181 +    if(fin){
   9.182 +	io = file_stream_new(fin);
   9.183 +	if(!io){
   9.184 +	    fclose(fin);
   9.185 +	    //free(fin); // fclose frees ?
   9.186 +	}
   9.187 +    }
   9.188 +    return io;
   9.189 +}
   9.190 +
   9.191 +/** IOStream version of fdopen().
   9.192 + *
   9.193 + * @param fd file descriptor
   9.194 + * @param flags giving the mode to open in (as for fdopen())
   9.195 + * @return new stream for the open file, or 0 if failed
   9.196 + */
   9.197 +IOStream *file_stream_fdopen(int fd, const char *flags){
   9.198 +    IOStream *io = 0;
   9.199 +    FILE *fin = fdopen(fd, flags);
   9.200 +    if(fin){
   9.201 +	io = file_stream_new(fin);
   9.202 +    }
   9.203 +    return io;
   9.204 +}
   9.205 +#endif
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tools/lib/file_stream.h	Tue Jun 29 12:05:29 2004 +0000
    10.3 @@ -0,0 +1,35 @@
    10.4 +/*
    10.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    10.6 + *
    10.7 + * This library is free software; you can redistribute it and/or modify
    10.8 + * it under the terms of the GNU Lesser General Public License as published by
    10.9 + * the Free Software Foundation; either version 2.1 of the License, or
   10.10 + * (at your option) any later version.
   10.11 + *
   10.12 + * This library is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 + * GNU Lesser General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU Lesser General Public License
   10.18 + * along with this library; if not, write to the Free Software
   10.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   10.20 + */
   10.21 +
   10.22 +#ifndef _XEN_LIB_FILE_STREAM_H_
   10.23 +#define _XEN_LIB_FILE_STREAM_H_
   10.24 +
   10.25 +#ifndef __KERNEL__
   10.26 +#include "iostream.h"
   10.27 +#include <stdio.h>
   10.28 +
   10.29 +extern IOStream *file_stream_new(FILE *f);
   10.30 +extern IOStream *file_stream_fopen(const char *file, const char *flags);
   10.31 +extern IOStream *file_stream_fdopen(int fd, const char *flags);
   10.32 +extern IOStream get_stream_stdout(void);
   10.33 +extern IOStream get_stream_stderr(void);
   10.34 +extern IOStream get_stream_stdin(void);
   10.35 +
   10.36 +extern int file_stream_setvbuf(IOStream *io, char *buf, int mode, size_t size);
   10.37 +#endif
   10.38 +#endif /* !_XEN_LIB_FILE_STREAM_H_ */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/lib/gzip_stream.c	Tue Jun 29 12:05:29 2004 +0000
    11.3 @@ -0,0 +1,171 @@
    11.4 +/* $Id: gzip_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
    11.5 +/*
    11.6 + * Copyright (C) 2003 Hewlett-Packard Company.
    11.7 + *
    11.8 + * This library is free software; you can redistribute it and/or modify
    11.9 + * it under the terms of the GNU Lesser General Public License as published by
   11.10 + * the Free Software Foundation; either version 2.1 of the License, or
   11.11 + * (at your option) any later version.
   11.12 + *
   11.13 + * This library is distributed in the hope that it will be useful,
   11.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.16 + * GNU Lesser General Public License for more details.
   11.17 + *
   11.18 + * You should have received a copy of the GNU Lesser General Public License
   11.19 + * along with this library; if not, write to the Free Software
   11.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   11.21 + */
   11.22 +
   11.23 +/** @file
   11.24 + * An IOStream implementation using zlib gzFile to provide
   11.25 + * compression and decompression.
   11.26 + */
   11.27 +#ifndef __KERNEL__
   11.28 +
   11.29 +#include <stdio.h>
   11.30 +#include <stdlib.h>
   11.31 +
   11.32 +#include "zlib.h"
   11.33 +
   11.34 +#include "allocate.h"
   11.35 +#include "gzip_stream.h"
   11.36 +
   11.37 +static int gzip_read(IOStream *s, void *buf, size_t n);
   11.38 +static int gzip_write(IOStream *s, const void *buf, size_t n);
   11.39 +static int gzip_error(IOStream *s);
   11.40 +static int gzip_close(IOStream *s);
   11.41 +static void gzip_free(IOStream *s);
   11.42 +static int gzip_flush(IOStream *s);
   11.43 +
   11.44 +/** Methods used by a gzFile* IOStream. */
   11.45 +static const IOMethods gzip_methods = {
   11.46 +    read: gzip_read,
   11.47 +    write: gzip_write,
   11.48 +    error: gzip_error,
   11.49 +    close: gzip_close,
   11.50 +    free:  gzip_free,
   11.51 +    flush: gzip_flush,
   11.52 +};
   11.53 +
   11.54 +/** Get the underlying gzFile*.
   11.55 + * 
   11.56 + * @param s gzip stream
   11.57 + * @return the stream s wraps
   11.58 + */
   11.59 +static inline gzFile get_gzfile(IOStream *s){
   11.60 +    return (gzFile)s->data;
   11.61 +}
   11.62 +
   11.63 +/** Write to the underlying stream.
   11.64 + *
   11.65 + * @param stream destination
   11.66 + * @param buf data
   11.67 + * @param n number of bytes to write
   11.68 + * @return number of bytes written
   11.69 + */
   11.70 +static int gzip_write(IOStream *s, const void *buf, size_t n){
   11.71 +    return gzwrite(get_gzfile(s), (void*)buf, n);
   11.72 +}
   11.73 +
   11.74 +/** Read from the underlying stream.
   11.75 + *
   11.76 + * @param stream input
   11.77 + * @param buf where to put input
   11.78 + * @param n number of bytes to read
   11.79 + * @return number of bytes read
   11.80 + */
   11.81 +static int gzip_read(IOStream *s, void *buf, size_t n){
   11.82 +    return gzread(get_gzfile(s), buf, n);
   11.83 +}
   11.84 +
   11.85 +/** Flush the underlying stream.
   11.86 + *
   11.87 + * @param s gzip stream
   11.88 + * @return 0 on success, error code otherwise
   11.89 + */
   11.90 +static int gzip_flush(IOStream *s){
   11.91 +    //return gzflush(get_gzfile(s), Z_NO_FLUSH);
   11.92 +    return gzflush(get_gzfile(s), Z_SYNC_FLUSH);
   11.93 +    //return gzflush(get_gzfile(s), Z_FULL_FLUSH);
   11.94 +}
   11.95 +
   11.96 +/** Check if a stream has an error.
   11.97 + *
   11.98 + * @param s gzip stream
   11.99 + * @return 1 if has an error, 0 otherwise
  11.100 + */
  11.101 +static int gzip_error(IOStream *s){
  11.102 +    int err;
  11.103 +    gzFile *gz = get_gzfile(s);
  11.104 +    gzerror(gz, &err);
  11.105 +    return (err == Z_ERRNO ? 1 /* ferror(gzfile(gz)) */ : err);
  11.106 +}
  11.107 +
  11.108 +/** Close a gzip stream.
  11.109 + *
  11.110 + * @param s gzip stream to close
  11.111 + * @return result of the close
  11.112 + */
  11.113 +static int gzip_close(IOStream *s){
  11.114 +    return gzclose(get_gzfile(s));
  11.115 +}
  11.116 +
  11.117 +/** Free a gzip stream.
  11.118 + *
  11.119 + * @param s gzip stream
  11.120 + */
  11.121 +static void gzip_free(IOStream *s){
  11.122 +    // Do nothing - fclose does it all?
  11.123 +}
  11.124 +
  11.125 +/** Create an IOStream for a gzip stream.
  11.126 + *
  11.127 + * @param f stream to wrap
  11.128 + * @return new IOStream using f for i/o
  11.129 + */
  11.130 +IOStream *gzip_stream_new(gzFile *f){
  11.131 +    IOStream *io = ALLOCATE(IOStream);
  11.132 +    if(io){
  11.133 +	io->methods = &gzip_methods;
  11.134 +	io->data = (void*)f;
  11.135 +    }
  11.136 +    return io;
  11.137 +}
  11.138 +
  11.139 +/** IOStream version of fopen().
  11.140 + *
  11.141 + * @param file name of the file to open
  11.142 + * @param flags giving the mode to open in (as for fopen())
  11.143 + * @return new stream for the open file, or NULL if failed
  11.144 + */
  11.145 +IOStream *gzip_stream_fopen(const char *file, const char *flags){
  11.146 +    IOStream *io = NULL;
  11.147 +    gzFile *fgz;
  11.148 +    fgz = gzopen(file, flags);
  11.149 +    if(fgz){
  11.150 +	io = gzip_stream_new(fgz);
  11.151 +	if(!io){
  11.152 +	    gzclose(fgz);
  11.153 +	    //free(fgz); // gzclose frees ?
  11.154 +	}
  11.155 +    }
  11.156 +    return io;
  11.157 +}
  11.158 +
  11.159 +/** IOStream version of fdopen().
  11.160 + *
  11.161 + * @param fd file descriptor
  11.162 + * @param flags giving the mode to open in (as for fdopen())
  11.163 + * @return new stream for the open file, or NULL if failed
  11.164 + */
  11.165 +IOStream *gzip_stream_fdopen(int fd, const char *flags){
  11.166 +    IOStream *io = NULL;
  11.167 +    gzFile *fgz;
  11.168 +    fgz = gzdopen(fd, flags);
  11.169 +    if(fgz){
  11.170 +	io = gzip_stream_new(fgz);
  11.171 +    }
  11.172 +    return io;
  11.173 +}
  11.174 +#endif
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/lib/gzip_stream.h	Tue Jun 29 12:05:29 2004 +0000
    12.3 @@ -0,0 +1,31 @@
    12.4 +#/* $Id: gzip_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
    12.5 +/*
    12.6 + * Copyright (C) 2003 Hewlett-Packard Company.
    12.7 + *
    12.8 + * This library is free software; you can redistribute it and/or modify
    12.9 + * it under the terms of the GNU Lesser General Public License as published by
   12.10 + * the Free Software Foundation; either version 2.1 of the License, or
   12.11 + * (at your option) any later version.
   12.12 + *
   12.13 + * This library is distributed in the hope that it will be useful,
   12.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.16 + * GNU Lesser General Public License for more details.
   12.17 + *
   12.18 + * You should have received a copy of the GNU Lesser General Public License
   12.19 + * along with this library; if not, write to the Free Software
   12.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   12.21 + */
   12.22 +
   12.23 +#ifndef _SP_GZIP_STREAM_H_
   12.24 +#define _SP_GZIP_STREAM_H_
   12.25 +
   12.26 +#ifndef __KERNEL__
   12.27 +#include "iostream.h"
   12.28 +#include "zlib.h"
   12.29 +
   12.30 +extern IOStream *gzip_stream_new(gzFile *f);
   12.31 +extern IOStream *gzip_stream_fopen(const char *file, const char *flags);
   12.32 +extern IOStream *gzip_stream_fdopen(int fd, const char *flags);
   12.33 +#endif
   12.34 +#endif /* !_SP_FILE_STREAM_H_ */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/lib/hash_table.c	Tue Jun 29 12:05:29 2004 +0000
    13.3 @@ -0,0 +1,640 @@
    13.4 +/*
    13.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    13.6 + *
    13.7 + * This library is free software; you can redistribute it and/or modify
    13.8 + * it under the terms of the GNU Lesser General Public License as published by
    13.9 + * the Free Software Foundation; either version 2.1 of the License, or
   13.10 + * (at your option) any later version.
   13.11 + *
   13.12 + * This library is distributed in the hope that it will be useful,
   13.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.15 + * GNU Lesser General Public License for more details.
   13.16 + *
   13.17 + * You should have received a copy of the GNU Lesser General Public License
   13.18 + * along with this library; if not, write to the Free Software
   13.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   13.20 + */
   13.21 +
   13.22 +#ifdef __KERNEL__
   13.23 +#  include <linux/config.h>
   13.24 +#  include <linux/module.h>
   13.25 +#  include <linux/kernel.h>
   13.26 +#  include <linux/errno.h>
   13.27 +#else
   13.28 +#  include <errno.h>
   13.29 +#  include <stddef.h>
   13.30 +#endif
   13.31 +
   13.32 +//#include <limits.h>
   13.33 +
   13.34 +#include "allocate.h"
   13.35 +#include "hash_table.h"
   13.36 +
   13.37 +/** @file
   13.38 + * Base support for hashtables.
   13.39 + *
   13.40 + * Hash codes are reduced modulo the number of buckets to index tables,
   13.41 + * so there is no need for hash functions to limit the range of hashcodes.
   13.42 + * In fact it is assumed that hashcodes do not change when the number of
   13.43 + * buckets in the table changes.
   13.44 + */
   13.45 +
   13.46 +/*==========================================================================*/
   13.47 +/** Number of bits in half a word. */
   13.48 +//#if __WORDSIZE == 64
   13.49 +//#define HALF_WORD_BITS 32
   13.50 +//#else
   13.51 +#define HALF_WORD_BITS 16
   13.52 +//#endif
   13.53 +
   13.54 +/** Mask for lo half of a word. On 32-bit this is 
   13.55 + * (1<<16) - 1 = 65535 = 0xffff
   13.56 + * It's 4294967295 = 0xffffffff on 64-bit.
   13.57 + */
   13.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
   13.59 +
   13.60 +/** Get the lo half of a word. */
   13.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK)
   13.62 +
   13.63 +/** Get the hi half of a word. */
   13.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
   13.65 +
   13.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling.
   13.67 + * Both inputs are replaced with the results of the hash.
   13.68 + *
   13.69 + * @param pleft input/output word
   13.70 + * @param pright input/output word
   13.71 + */
   13.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){
   13.73 +    // Bit-rich mixing constant.
   13.74 +    static const unsigned long a_mixer[] = {
   13.75 +        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
   13.76 +
   13.77 +    // Bit-rich mixing constant.
   13.78 +    static const unsigned long b_mixer[] = {
   13.79 +        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
   13.80 +
   13.81 +    // Number of iterations - must be 2 or 4.
   13.82 +    static const int ncycle = 4;
   13.83 +    //static const int ncycle = 2;
   13.84 +
   13.85 +    unsigned long left = *pleft, right = *pright;
   13.86 +    unsigned long v, v_hi, v_lo;
   13.87 +    int i;
   13.88 +
   13.89 +    for(i=0; i<ncycle; i++){
   13.90 +        // Flip some bits in right to get v.
   13.91 +        v = right;
   13.92 +        v ^= a_mixer[i];
   13.93 +        // Get lo and hi halves of v.
   13.94 +        v_lo = LO_HALF(v);
   13.95 +        v_hi = HI_HALF(v);
   13.96 +        // Non-linear mix of the halves of v.
   13.97 +        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
   13.98 +        // Swap the halves of v.
   13.99 +        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
  13.100 +        // Flip some bits.
  13.101 +        v ^= b_mixer[i];
  13.102 +        // More non-linear mixing.
  13.103 +        v += (v_lo * v_hi);
  13.104 +        v ^= left;
  13.105 +        left = right;
  13.106 +        right = v;
  13.107 +    }
  13.108 +    *pleft = left;
  13.109 +    *pright = right;
  13.110 +}
  13.111 +
  13.112 +/** Hash a string.
  13.113 + *
  13.114 + * @param s input to hash
  13.115 + * @return hashcode
  13.116 + */
  13.117 +Hashcode hash_string(char *s){
  13.118 +    Hashcode h = 0;
  13.119 +    if(s){
  13.120 +        for( ; *s; s++){
  13.121 +            h = hash_2ul(h, *s);
  13.122 +        }
  13.123 +    }
  13.124 +    return h;
  13.125 +}
  13.126 +
  13.127 +/** Get the bucket for a hashcode in a hash table.
  13.128 + *
  13.129 + * @param table to get bucket from
  13.130 + * @param hashcode to get bucket for
  13.131 + * @return bucket
  13.132 + */
  13.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
  13.134 +    return table->buckets + (hashcode % table->buckets_n);
  13.135 +}
  13.136 +
  13.137 +/** Initialize a hash table.
  13.138 + * Can be safely called more than once.
  13.139 + *
  13.140 + * @param table to initialize
  13.141 + */
  13.142 +void HashTable_init(HashTable *table){
  13.143 +    int i;
  13.144 +
  13.145 +    if(!table->init_done){
  13.146 +        table->init_done = 1;
  13.147 +        table->next_id = 0;
  13.148 +        for(i=0; i<table->buckets_n; i++){
  13.149 +            HTBucket *bucket = get_bucket(table, i);
  13.150 +            bucket->head = 0;
  13.151 +            bucket->count = 0;
  13.152 +        }
  13.153 +        table->entry_count = 0;
  13.154 +    }
  13.155 +}
  13.156 +
  13.157 +/** Allocate a new hashtable.
  13.158 + * If the number of buckets is not positive the default is used.
  13.159 + * The number of buckets should usually be prime.
  13.160 + *
  13.161 + * @param buckets_n number of buckets
  13.162 + * @return new hashtable or null
  13.163 + */
  13.164 +HashTable *HashTable_new(int buckets_n){
  13.165 +    HashTable *z = ALLOCATE(HashTable);
  13.166 +    if(!z) goto exit;
  13.167 +    if(buckets_n <= 0){
  13.168 +        buckets_n = HT_BUCKETS_N;
  13.169 +    }
  13.170 +    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
  13.171 +    if(!z->buckets){
  13.172 +        deallocate(z);
  13.173 +        z = 0;
  13.174 +        goto exit;
  13.175 +    }
  13.176 +    z->buckets_n = buckets_n;
  13.177 +    HashTable_init(z);
  13.178 +  exit:
  13.179 +    return z;
  13.180 +}
  13.181 +
  13.182 +/** Free a hashtable.
  13.183 + * Any entries are removed and freed.
  13.184 + *
  13.185 + * @param h hashtable (ignored if null)
  13.186 + */
  13.187 +void HashTable_free(HashTable *h){
  13.188 +    if(h){
  13.189 +        HashTable_clear(h);
  13.190 +        deallocate(h->buckets);
  13.191 +        deallocate(h);
  13.192 +    }
  13.193 +}
  13.194 +
  13.195 +/** Push an entry on the list in the bucket for a given hashcode.
  13.196 + *
  13.197 + * @param table to add entry to
  13.198 + * @param hashcode for the entry
  13.199 + * @param entry to add
  13.200 + */
  13.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
  13.202 +				  HTEntry *entry){
  13.203 +    HTBucket *bucket;
  13.204 +    HTEntry *old_head;
  13.205 +
  13.206 +    bucket = get_bucket(table, hashcode);
  13.207 +    old_head = bucket->head;
  13.208 +    bucket->count++;
  13.209 +    bucket->head = entry;
  13.210 +    entry->next = old_head;
  13.211 +}
  13.212 +
  13.213 +/** Change the number of buckets in a hashtable.
  13.214 + * No-op if the number of buckets is not positive.
  13.215 + * Existing entries are reallocated to buckets based on their hashcodes.
  13.216 + * The table is unmodified if the number of buckets cannot be changed.
  13.217 + *
  13.218 + * @param table hashtable
  13.219 + * @param buckets_n new number of buckets
  13.220 + * @return 0 on success, error code otherwise
  13.221 + */
  13.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){
  13.223 +    int err = 0;
  13.224 +    HTBucket *old_buckets = table->buckets;
  13.225 +    int old_buckets_n = table->buckets_n;
  13.226 +    int i;
  13.227 +
  13.228 +    if(buckets_n <= 0){
  13.229 +        err = -EINVAL;
  13.230 +        goto exit;
  13.231 +    }
  13.232 +    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
  13.233 +    if(!table->buckets){
  13.234 +        err = -ENOMEM;
  13.235 +        table->buckets = old_buckets;
  13.236 +        goto exit;
  13.237 +    }
  13.238 +    table->buckets_n = buckets_n;
  13.239 +    for(i=0; i<old_buckets_n; i++){
  13.240 +        HTBucket *bucket = old_buckets + i;
  13.241 +        HTEntry *entry, *next;
  13.242 +        for(entry = bucket->head; entry; entry = next){
  13.243 +            next = entry->next;
  13.244 +            push_on_bucket(table, entry->hashcode, entry);
  13.245 +        }
  13.246 +    }
  13.247 +    deallocate(old_buckets);
  13.248 +  exit:
  13.249 +    return err;
  13.250 +}
  13.251 +
  13.252 +/** Adjust the number of buckets so the table is neither too full nor too empty.
  13.253 + * The table is unmodified if adjusting fails.
  13.254 + *
  13.255 + * @param table hash table
  13.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative)
  13.257 + * @return 0 on success, error code otherwise
  13.258 + */
  13.259 +int HashTable_adjust(HashTable *table, int buckets_min){
  13.260 +    int buckets_n = 0;
  13.261 +    int err = 0;
  13.262 +    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
  13.263 +    if(table->entry_count >= table->buckets_n){
  13.264 +        // The table is dense - expand it.
  13.265 +        buckets_n = 2 * table->buckets_n;
  13.266 +    } else if((table->buckets_n > buckets_min) &&
  13.267 +              (4 * table->entry_count < table->buckets_n)){
  13.268 +        // The table is more than minimum size and sparse - shrink it.
  13.269 +        buckets_n = 2 * table->entry_count;
  13.270 +        if(buckets_n < buckets_min) buckets_n = buckets_min;
  13.271 +    }
  13.272 +    if(buckets_n){
  13.273 +        err = HashTable_set_buckets_n(table, buckets_n);
  13.274 +    }
  13.275 +    return err;
  13.276 +}
  13.277 +
  13.278 +/** Allocate a new entry for a given value.
  13.279 + *
  13.280 + * @param value to put in the entry
  13.281 + * @return entry, or 0 on failure
  13.282 + */
  13.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
  13.284 +    HTEntry *z = ALLOCATE(HTEntry);
  13.285 +    if(z){
  13.286 +        z->hashcode = hashcode;
  13.287 +        z->key = key;
  13.288 +        z->value = value;
  13.289 +    }
  13.290 +    return z;
  13.291 +}
  13.292 +
  13.293 +/** Free an entry.
  13.294 + *
  13.295 + * @param z entry to free
  13.296 + */
  13.297 +inline void HTEntry_free(HTEntry *z){
  13.298 +    if(z){
  13.299 +        deallocate(z);
  13.300 +    }
  13.301 +}
  13.302 +
  13.303 +/** Free an entry in a hashtable.
  13.304 + * The table's entry_free_fn is used is defined, otherwise 
  13.305 + * the HTEntry itself is freed.
  13.306 + *
  13.307 + * @param table hashtable
  13.308 + * @param entry to free
  13.309 + */
  13.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
  13.311 +    if(!entry)return;
  13.312 +    if(table && table->entry_free_fn){
  13.313 +        table->entry_free_fn(table, entry);
  13.314 +    } else {
  13.315 +        HTEntry_free(entry);
  13.316 +    }
  13.317 +}
  13.318 +
  13.319 +/** Get the first entry satisfying a test from the bucket for the
  13.320 + * given hashcode.
  13.321 + *
  13.322 + * @param table to look in
  13.323 + * @param hashcode indicates the bucket
  13.324 + * @param test_fn test to apply to elements
  13.325 + * @param arg first argument to calls to test_fn
  13.326 + * @return entry found, or 0
  13.327 + */
  13.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
  13.329 +				      TableTestFn *test_fn, TableArg arg){
  13.330 +    HTBucket *bucket;
  13.331 +    HTEntry *entry = 0;
  13.332 +    HTEntry *next;
  13.333 +
  13.334 +    bucket = get_bucket(table, hashcode);
  13.335 +    for(entry = bucket->head; entry; entry = next){
  13.336 +        next = entry->next;
  13.337 +        if(test_fn(arg, table, entry)){
  13.338 +            break;
  13.339 +        }
  13.340 +    }
  13.341 +    return entry;
  13.342 +}
  13.343 +
  13.344 +/** Test hashtable keys for equality.
  13.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality.
  13.346 + *
  13.347 + * @param key1 key to compare
  13.348 + * @param key2 key to compare
  13.349 + * @return 1 if equal, 0 otherwise
  13.350 + */
  13.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
  13.352 +    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
  13.353 +}
  13.354 +
  13.355 +/** Compute the hashcode of a hashtable key.
  13.356 + * The table's key_hash_fn is used if defined, otherwise the address of
  13.357 + * the key is hashed.
  13.358 + *
  13.359 + * @param table hashtable
  13.360 + * @param key to hash
  13.361 + * @return hashcode
  13.362 + */
  13.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){
  13.364 +    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
  13.365 +}
  13.366 +
  13.367 +/** Test if an entry has a given key.
  13.368 + *
  13.369 + * @param arg containing key to test for
  13.370 + * @param table the entry is in
  13.371 + * @param entry to test
  13.372 + * @return 1 if the entry has the key, 0 otherwise
  13.373 + */
  13.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
  13.375 +    return HashTable_key_equal(table, arg.ptr, entry->key);
  13.376 +}
  13.377 +
  13.378 +/** Get an entry with a given key.
  13.379 + *
  13.380 + * @param table to search
  13.381 + * @param key to look for
  13.382 + * @return entry if found, null otherwise
  13.383 + */
  13.384 +#if 0
  13.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
  13.386 +    TableArg arg = { ptr: key };
  13.387 +    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
  13.388 +}
  13.389 +#else
  13.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
  13.391 +    Hashcode hashcode;
  13.392 +    HTBucket *bucket;
  13.393 +    HTEntry *entry = 0;
  13.394 +    HTEntry *next;
  13.395 +
  13.396 +    hashcode = HashTable_key_hash(table, key);
  13.397 +    bucket = get_bucket(table, hashcode);
  13.398 +    for(entry = bucket->head; entry; entry = next){
  13.399 +        next = entry->next;
  13.400 +        if(HashTable_key_equal(table, key, entry->key)){
  13.401 +            break;
  13.402 +        }
  13.403 +    }
  13.404 +    return entry;
  13.405 +}
  13.406 +#endif
  13.407 +
  13.408 +/** Get the value of an entry with a given key.
  13.409 + *
  13.410 + * @param table to search
  13.411 + * @param key to look for
  13.412 + * @return value if an entry was found, null otherwise
  13.413 + */
  13.414 +inline void * HashTable_get(HashTable *table, void *key){
  13.415 +    HTEntry *entry = HashTable_get_entry(table, key);
  13.416 +    return (entry ? entry->value : 0);
  13.417 +}
  13.418 +
  13.419 +/** Print the buckets in a table.
  13.420 + *
  13.421 + * @param table to print
  13.422 + */
  13.423 +void show_buckets(HashTable *table, IOStream *io){
  13.424 +    int i,j ;
  13.425 +    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
  13.426 +    for(i=0; i<table->buckets_n; i++){
  13.427 +        if(0 || table->buckets[i].count>0){
  13.428 +            IOStream_print(io, "bucket %3d %3d %10p ", i,
  13.429 +                        table->buckets[i].count,
  13.430 +                        table->buckets[i].head);
  13.431 +            for(j = table->buckets[i].count; j>0; j--){
  13.432 +                IOStream_print(io, "+");
  13.433 +            }
  13.434 +            IOStream_print(io, "\n");
  13.435 +        }
  13.436 +    }
  13.437 +    HashTable_print(table, io); 
  13.438 +}
  13.439 +    
  13.440 +/** Print an entry in a table.
  13.441 + *
  13.442 + * @param entry to print
  13.443 + * @param arg a pointer to an IOStream to print to
  13.444 + * @return 0
  13.445 + */
  13.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
  13.447 +    IOStream *io = (IOStream*)arg.ptr;
  13.448 +    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
  13.449 +                entry->hashcode % table->buckets_n,
  13.450 +                entry->hashcode,
  13.451 +                entry->index,
  13.452 +                entry, entry->key, entry->value);
  13.453 +    return 0;
  13.454 +}
  13.455 +
  13.456 +/** Print a hash table.
  13.457 + *
  13.458 + * @param table to print
  13.459 + */
  13.460 +void HashTable_print(HashTable *table, IOStream *io){
  13.461 +    IOStream_print(io, "{\n");
  13.462 +    HashTable_map(table, print_entry, (TableArg){ ptr: io });
  13.463 +    IOStream_print(io, "}\n");
  13.464 +}
  13.465 +/*==========================================================================*/
  13.466 +
  13.467 +/** Get the next entry id to use for a table.
  13.468 + *
  13.469 + * @param table hash table
  13.470 + * @return non-zero entry id
  13.471 + */
  13.472 +static inline unsigned long get_next_id(HashTable *table){
  13.473 +    unsigned long id;
  13.474 +
  13.475 +    if(table->next_id == 0){
  13.476 +        table->next_id = 1;
  13.477 +    }
  13.478 +    id = table->next_id++;
  13.479 +    return id;
  13.480 +}
  13.481 +
  13.482 +/** Add an entry to the bucket for the
  13.483 + * given hashcode.
  13.484 + *
  13.485 + * @param table to insert in
  13.486 + * @param hashcode indicates the bucket
  13.487 + * @param key to add an entry for
  13.488 + * @param value to add an entry for
  13.489 + * @return entry on success, 0 on failure
  13.490 + */
  13.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
  13.492 +    HTEntry *entry = HTEntry_new(hashcode, key, value);
  13.493 +    if(entry){
  13.494 +        entry->index = get_next_id(table);
  13.495 +        push_on_bucket(table, hashcode, entry);
  13.496 +        table->entry_count++;
  13.497 +    }
  13.498 +    return entry;
  13.499 +}
  13.500 +
  13.501 +/** Move the front entry for a bucket to the correct point in the bucket order as
  13.502 + * defined by the order function. If this is called every time a new entry is added
  13.503 + * the bucket will be maintained in sorted order.
  13.504 + *
  13.505 + * @param table to modify
  13.506 + * @param hashcode indicates the bucket
  13.507 + * @param order entry comparison function
  13.508 + * @return 0 if an entry was moved, 1 if not
  13.509 + */
  13.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
  13.511 +    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
  13.512 +    HTBucket *bucket;
  13.513 +    int err = 1;
  13.514 +
  13.515 +    bucket = get_bucket(table, hashcode);
  13.516 +    new_entry = bucket->head;
  13.517 +    if(!new_entry || !new_entry->next) goto exit;
  13.518 +    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
  13.519 +        if(order(new_entry, entry) <= 0) break;
  13.520 +    }
  13.521 +    if(prev){
  13.522 +        err = 0;
  13.523 +        bucket->head = new_entry->next; 
  13.524 +        new_entry->next = entry;
  13.525 +        prev->next = new_entry;
  13.526 +    }
  13.527 +  exit:
  13.528 +    return err;
  13.529 +}
  13.530 +
  13.531 +/** Add an entry to a hashtable.
  13.532 + * The entry is added to the bucket for its key's hashcode.
  13.533 + *
  13.534 + * @param table to insert in
  13.535 + * @param key to add an entry for
  13.536 + * @param value to add an entry for
  13.537 + * @return entry on success, 0 on failure
  13.538 + */
  13.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
  13.540 +    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
  13.541 +}
  13.542 +
  13.543 +
  13.544 +/** Remove entries satisfying a test from the bucket for the
  13.545 + * given hashcode. 
  13.546 + *
  13.547 + * @param table to remove from
  13.548 + * @param hashcode indicates the bucket
  13.549 + * @param test_fn test to apply to elements
  13.550 + * @param arg first argument to calls to test_fn
  13.551 + * @return number of entries removed
  13.552 + */
  13.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
  13.554 +				  TableTestFn *test_fn, TableArg arg){
  13.555 +    HTBucket *bucket;
  13.556 +    HTEntry *entry, *prev = 0, *next;
  13.557 +    int removed_count = 0;
  13.558 +
  13.559 +    bucket = get_bucket(table, hashcode);
  13.560 +    for(entry = bucket->head; entry; entry = next){
  13.561 +        next = entry->next;
  13.562 +        if(test_fn(arg, table, entry)){
  13.563 +            if(prev){
  13.564 +                prev->next = next;
  13.565 +            } else {
  13.566 +                bucket->head = next;
  13.567 +            }
  13.568 +            bucket->count--;
  13.569 +            table->entry_count--;
  13.570 +            removed_count++;
  13.571 +            HashTable_free_entry(table, entry);
  13.572 +            entry = 0;
  13.573 +        }
  13.574 +        prev = entry;
  13.575 +    }
  13.576 +    return removed_count;
  13.577 +}
  13.578 +
  13.579 +/** Remove entries with a given key. 
  13.580 + *
  13.581 + * @param table to remove from
  13.582 + * @param key of entries to remove
  13.583 + * @return number of entries removed
  13.584 + */
  13.585 +inline int HashTable_remove(HashTable *table, void *key){
  13.586 +#if 1
  13.587 +    Hashcode hashcode;
  13.588 +    HTBucket *bucket;
  13.589 +    HTEntry *entry, *prev = 0, *next;
  13.590 +    int removed_count = 0;
  13.591 +
  13.592 +    hashcode = HashTable_key_hash(table, key);
  13.593 +    bucket = get_bucket(table, hashcode);
  13.594 +    for(entry = bucket->head; entry; entry = next){
  13.595 +        next = entry->next;
  13.596 +        if(HashTable_key_equal(table, key, entry->key)){
  13.597 +            if(prev){
  13.598 +                prev->next = next;
  13.599 +            } else {
  13.600 +                bucket->head = next;
  13.601 +            }
  13.602 +            bucket->count--;
  13.603 +            table->entry_count--;
  13.604 +            removed_count++;
  13.605 +            HashTable_free_entry(table, entry);
  13.606 +            entry = 0;
  13.607 +        }
  13.608 +        prev = entry;
  13.609 +    }
  13.610 +    return removed_count;
  13.611 +#else
  13.612 +    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
  13.613 +				  has_key, (TableArg){ ptr: key});
  13.614 +#endif
  13.615 +}
  13.616 +
  13.617 +/** Remove (and free) all the entries in a bucket.
  13.618 + *
  13.619 + * @param bucket to clear
  13.620 + */
  13.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){
  13.622 +    HTEntry *entry, *next;
  13.623 +
  13.624 +    for(entry = bucket->head; entry; entry = next){
  13.625 +        next = entry->next;
  13.626 +        HashTable_free_entry(table, entry);
  13.627 +    }
  13.628 +    bucket->head = 0;
  13.629 +    table->entry_count -= bucket->count;
  13.630 +    bucket->count = 0;
  13.631 +}
  13.632 +
  13.633 +/** Remove (and free) all the entries in a table.
  13.634 + *
  13.635 + * @param table to clear
  13.636 + */
  13.637 +void HashTable_clear(HashTable *table){
  13.638 +    int i, n = table->buckets_n;
  13.639 +
  13.640 +    for(i=0; i<n; i++){
  13.641 +        bucket_clear(table, table->buckets + i);
  13.642 +    }
  13.643 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/lib/hash_table.h	Tue Jun 29 12:05:29 2004 +0000
    14.3 @@ -0,0 +1,295 @@
    14.4 +/* $Id: hash_table.h,v 1.1 2004/03/30 16:21:26 mjw Exp $ */
    14.5 +/*
    14.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    14.7 + *
    14.8 + * This library is free software; you can redistribute it and/or modify
    14.9 + * it under the terms of the GNU Lesser General Public License as published by
   14.10 + * the Free Software Foundation; either version 2.1 of the License, or
   14.11 + * (at your option) any later version.
   14.12 + *
   14.13 + * This library is distributed in the hope that it will be useful,
   14.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.16 + * GNU Lesser General Public License for more details.
   14.17 + *
   14.18 + * You should have received a copy of the GNU Lesser General Public License
   14.19 + * along with this library; if not, write to the Free Software
   14.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   14.21 + */
   14.22 +
   14.23 +#ifndef _XEN_LIB_HASH_TABLE_H_
   14.24 +#define _XEN_LIB_HASH_TABLE_H_
   14.25 +
   14.26 +#include "iostream.h"
   14.27 +
   14.28 +typedef unsigned long Hashcode;
   14.29 +
   14.30 +/** Type used to pass parameters to table functions. */
   14.31 +typedef union TableArg {
   14.32 +    unsigned long ul;
   14.33 +    void *ptr;
   14.34 +} TableArg;
   14.35 +
   14.36 +/** An entry in a bucket list. */
   14.37 +typedef struct HTEntry {
   14.38 +    /** Hashcode of the entry's key. */
   14.39 +    Hashcode hashcode;
   14.40 +    /** Identifier for this entry in the table. */
   14.41 +    int index;
   14.42 +    /** The key for this entry. */
   14.43 +    void *key;
   14.44 +    /** The value in this entry. */
   14.45 +    void *value;
   14.46 +    /** The next entry in the list. */
   14.47 +    struct HTEntry *next;
   14.48 +} HTEntry;
   14.49 +
   14.50 +/** A bucket in a rule table. */
   14.51 +typedef struct HTBucket {
   14.52 +    /** Number of entries in the bucket. */
   14.53 +    int count;
   14.54 +    /** First entry in the bucket (may be null). */
   14.55 +    HTEntry *head;
   14.56 +} HTBucket;
   14.57 +
   14.58 +/** Default number of buckets in a hash table.
   14.59 + * You want enough buckets so the lists in the buckets will typically be short.
   14.60 + * It's a good idea if this is prime, since that will help to spread hashcodes
   14.61 + * around the table.
   14.62 + */
   14.63 +//#define HT_BUCKETS_N 1
   14.64 +//#define HT_BUCKETS_N 3
   14.65 +//#define HT_BUCKETS_N 7
   14.66 +//#define HT_BUCKETS_N 17
   14.67 +//#define HT_BUCKETS_N 97
   14.68 +//#define HT_BUCKETS_N 211
   14.69 +//#define HT_BUCKETS_N 401
   14.70 +#define HT_BUCKETS_N 1021
   14.71 +
   14.72 +typedef struct HashTable HashTable;
   14.73 +
   14.74 +/** Type for a function used to select table entries. */
   14.75 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
   14.76 +
   14.77 +/** Type for a function to map over table entries. */
   14.78 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
   14.79 +
   14.80 +/** Type for a function to free table entries. */
   14.81 +typedef void TableFreeFn(HashTable *table, HTEntry *entry);
   14.82 +
   14.83 +/** Type for a function to hash table keys. */
   14.84 +typedef Hashcode TableHashFn(void *key);
   14.85 +
   14.86 +/** Type for a function to test table keys for equality. */
   14.87 +typedef int TableEqualFn(void *key1, void *key2);
   14.88 +
   14.89 +/** Type for a function to order table entries. */
   14.90 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
   14.91 +
   14.92 +/** General hash table.
   14.93 + * A hash table with a list in each bucket.
   14.94 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
   14.95 + * These all default to 0, when default behaviour treating keys as integers is used.
   14.96 + */
   14.97 +struct HashTable {
   14.98 +    /** Flag indicating whether the table has been initialised. */
   14.99 +    int init_done;
  14.100 +    /** Next value for the id field in inserted rules. */
  14.101 +    unsigned long next_id;
  14.102 +    /** Number of buckets in the bucket array. */
  14.103 +    int buckets_n;
  14.104 +    /** Array of buckets, each with its own list. */
  14.105 +    HTBucket *buckets;
  14.106 +    /** Number of entries in the table. */
  14.107 +    int entry_count;
  14.108 +    /** Function to free keys and values in entries. */
  14.109 +    TableFreeFn *entry_free_fn;
  14.110 +    /** Function to hash keys. */
  14.111 +    TableHashFn *key_hash_fn;
  14.112 +    /** Function to compare keys for equality. */
  14.113 +    TableEqualFn *key_equal_fn;
  14.114 +    /** Place for the user of the table to hang extra data. */
  14.115 +    void *user_data;
  14.116 +};
  14.117 +
  14.118 +extern HashTable *HashTable_new(int bucket_n);
  14.119 +extern void HashTable_free(HashTable *table);
  14.120 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
  14.121 +extern void HTEntry_free(HTEntry *entry);
  14.122 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
  14.123 +extern void HashTable_clear(HashTable *table);
  14.124 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
  14.125 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
  14.126 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
  14.127 +extern void * HashTable_get(HashTable *table, void *key);
  14.128 +extern int HashTable_remove(HashTable *table, void *key);
  14.129 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
  14.130 +                                      TableTestFn *test_fn, TableArg arg);
  14.131 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
  14.132 +                                   TableTestFn *test_fn, TableArg arg);
  14.133 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
  14.134 +extern void HashTable_print(HashTable *table, IOStream *out);
  14.135 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
  14.136 +extern int HashTable_adjust(HashTable *table, int buckets_min);
  14.137 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
  14.138 +extern Hashcode hash_string(char *s);
  14.139 +
  14.140 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
  14.141 +
  14.142 +/** Control whether to use hashing based on DES or simple
  14.143 + * hashing. DES hashing is `more random' but much more expensive.
  14.144 + */
  14.145 +#define HASH_PSEUDO_DES 0
  14.146 +
  14.147 +/** Hash a long using a quick and dirty linear congruential random number generator.
  14.148 + *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
  14.149 + *
  14.150 + * @param a value to hash
  14.151 + * @return hashed input
  14.152 + */
  14.153 +static inline unsigned long lcrng_hash(unsigned long a){
  14.154 +    return (1664525L * a + 1013904223L);
  14.155 +}
  14.156 +
  14.157 +/** Hash an unsigned long.
  14.158 + *
  14.159 + * @param a input to hash
  14.160 + * @return hashcode
  14.161 + */
  14.162 +static inline Hashcode hash_ul(unsigned long a){
  14.163 +#if HASH_PSEUDO_DES
  14.164 +    unsigned long left = a;
  14.165 +    unsigned long right = 0L;
  14.166 +    pseudo_des(&left, &right);
  14.167 +    return right;
  14.168 +#else
  14.169 +    a = lcrng_hash(a);
  14.170 +    a = lcrng_hash(a);
  14.171 +    return a;
  14.172 +#endif
  14.173 +}
  14.174 +
  14.175 +/** Hash two unsigned longs together.
  14.176 + *
  14.177 + * @param a input to hash
  14.178 + * @param b input to hash
  14.179 + * @return hashcode
  14.180 + */
  14.181 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
  14.182 +#if HASH_PSEUDO_DES
  14.183 +    unsigned long left = a;
  14.184 +    unsigned long right = b;
  14.185 +    pseudo_des(&left, &right);
  14.186 +    return right;
  14.187 +#else
  14.188 +    a = lcrng_hash(a);
  14.189 +    a ^= b;
  14.190 +    a = lcrng_hash(a);
  14.191 +    return a;
  14.192 +#endif
  14.193 +}
  14.194 +
  14.195 +/** Hash a hashcode and an unsigned long together.
  14.196 + *
  14.197 + * @param a input hashcode
  14.198 + * @param b input to hash
  14.199 + * @return hashcode
  14.200 + */
  14.201 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){
  14.202 +#if HASH_PSEUDO_DES
  14.203 +    unsigned long left = a;
  14.204 +    unsigned long right = b;
  14.205 +    pseudo_des(&left, &right);
  14.206 +    return right;
  14.207 +#else
  14.208 +    a ^= b;
  14.209 +    a = lcrng_hash(a);
  14.210 +    return a;
  14.211 +#endif
  14.212 +}
  14.213 +
  14.214 +/** Macro to declare variables for HashTable_for_each() to use.
  14.215 + *
  14.216 + * @param entry variable that is set to entries in the table
  14.217 + */
  14.218 +#define HashTable_for_decl(entry) \
  14.219 +  HashTable *_var_table; \
  14.220 +  HTBucket *_var_bucket; \
  14.221 +  HTBucket *_var_end; \
  14.222 +  HTEntry *_var_next; \
  14.223 +  HTEntry *entry
  14.224 +
  14.225 +/** Macro to iterate over the entries in a hashtable.
  14.226 + * Must be in a scope where HashTable_for_decl() has been used to declare
  14.227 + * variables for it to use.
  14.228 + * The variable 'entry' is iterated over entries in the table.
  14.229 + * The code produced is syntactically a loop, so it must be followed by
  14.230 + * a loop body, typically some statements in braces:
  14.231 + * HashTable_for_each(entry, table){ ...loop body... }
  14.232 + *
  14.233 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
  14.234 + * loops as variables will clash.
  14.235 + *
  14.236 + * @note The simplest way to code a direct loop over the entries in a hashtable
  14.237 + * is to use a loop over the buckets, with a nested loop over the entries
  14.238 + * in a bucket. Using this approach in a macro means the macro contains
  14.239 + * an opening brace, and calls to it must be followed by 2 braces!
  14.240 + * To avoid this the code has been restructured so that it is a for loop.
  14.241 + * So that statements could be used in the test expression of the for loop,
  14.242 + * we have used the gcc statement expression extension ({ ... }).
  14.243 + *
  14.244 + * @param entry variable to iterate over the entries
  14.245 + * @param table to iterate over (non-null)
  14.246 + */
  14.247 +#define HashTable_for_each(entry, table) \
  14.248 +  _var_table = table; \
  14.249 +  _var_bucket = _var_table->buckets; \
  14.250 +  _var_end = _var_bucket + _var_table->buckets_n; \
  14.251 +  for(entry=0, _var_next=0; \
  14.252 +      ({ if(_var_next){ \
  14.253 +             entry = _var_next; \
  14.254 +             _var_next = entry->next; \
  14.255 +          } else { \
  14.256 +             while(_var_bucket < _var_end){ \
  14.257 +                 entry = _var_bucket->head; \
  14.258 +                 _var_bucket++; \
  14.259 +                 if(entry){ \
  14.260 +                      _var_next = entry->next; \
  14.261 +                      break; \
  14.262 +                 } \
  14.263 +             } \
  14.264 +          }; \
  14.265 +         entry; }); \
  14.266 +      entry = _var_next )
  14.267 +
  14.268 +/** Map a function over the entries in a table.
  14.269 + * Mapping stops when the function returns a non-zero value.
  14.270 + * Uses the gcc statement expression extension ({ ... }).
  14.271 + *
  14.272 + * @param table to map over
  14.273 + * @param fn function to apply to entries
  14.274 + * @param arg first argument to call the function with
  14.275 + * @return 0 if fn always returned 0, first non-zero value otherwise
  14.276 + */
  14.277 +#define HashTable_map(table, fn, arg) \
  14.278 +  ({ HashTable_for_decl(_var_entry); \
  14.279 +    TableArg _var_arg = arg; \
  14.280 +    int _var_value = 0; \
  14.281 +    HashTable_for_each(_var_entry, table){ \
  14.282 +        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
  14.283 +    } \
  14.284 +    _var_value; })
  14.285 +
  14.286 +/** Cast x to the type for a key or value in a hash table.
  14.287 + * This avoids compiler warnings when using short integers
  14.288 + * as keys or values (especially on 64-bit platforms).
  14.289 + */
  14.290 +#define HKEY(x) ((void*)(unsigned long)(x))
  14.291 +
  14.292 +/** Cast x from the type for a key or value in a hash table.
  14.293 + * to an unsigned long. This avoids compiler warnings when using
  14.294 + * short integers as keys or values (especially on 64-bit platforms).
  14.295 + */
  14.296 +#define HVAL(x) ((unsigned long)(x))
  14.297 +
  14.298 +#endif /* !_XEN_LIB_HASH_TABLE_H_ */
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tools/lib/iostream.c	Tue Jun 29 12:05:29 2004 +0000
    15.3 @@ -0,0 +1,37 @@
    15.4 +#include "iostream.h"
    15.5 +#include "sys_string.h"
    15.6 +
    15.7 +/** Print on a stream, like vfprintf().
    15.8 + *
    15.9 + * @param stream to print to
   15.10 + * @param format for the print (as fprintf())
   15.11 + * @param args arguments to print
   15.12 + * @return result code from the print
   15.13 + */
   15.14 +int IOStream_vprint(IOStream *stream, const char *format, va_list args){
   15.15 +  char buffer[1024];
   15.16 +  int k = sizeof(buffer), n;
   15.17 +
   15.18 +  n = vsnprintf(buffer, k, (char*)format, args);
   15.19 +  if(n < 0 || n > k ){
   15.20 +      n = k;
   15.21 +  }
   15.22 +  n = IOStream_write(stream, buffer, n);
   15.23 +  return n;
   15.24 +}
   15.25 +
   15.26 +/** Print on a stream, like fprintf().
   15.27 + *
   15.28 + * @param stream to print to
   15.29 + * @param format for the print (as fprintf())
   15.30 + * @return result code from the print
   15.31 + */
   15.32 +int IOStream_print(IOStream *stream, const char *format, ...){
   15.33 +  va_list args;
   15.34 +  int result = -1;
   15.35 +
   15.36 +  va_start(args, format);
   15.37 +  result = IOStream_vprint(stream, format, args);
   15.38 +  va_end(args);
   15.39 +  return result;
   15.40 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/tools/lib/iostream.h	Tue Jun 29 12:05:29 2004 +0000
    16.3 @@ -0,0 +1,243 @@
    16.4 +#ifndef _XC_LINUX_SAVE_H_
    16.5 +#define _XC_LINUX_SAVE_H_
    16.6 +
    16.7 +#include <stdarg.h>
    16.8 +#include <stdint.h>
    16.9 +#include <stddef.h>
   16.10 +
   16.11 +#ifdef __KERNEL__
   16.12 +#include <linux/errno.h>
   16.13 +#else
   16.14 +#include <errno.h>
   16.15 +#endif
   16.16 +
   16.17 +#include "allocate.h"
   16.18 +
   16.19 +/** End of input return value. */
   16.20 +#define IOSTREAM_EOF -1
   16.21 +
   16.22 +/** An input/output abstraction.
   16.23 + */
   16.24 +typedef struct IOStream IOStream;
   16.25 +
   16.26 +/** Record of the functions to use for operations on an
   16.27 + * IOStream implementation.
   16.28 + */
   16.29 +typedef struct IOMethods {
   16.30 +    /** Read function.  Called with the user data, buffer to read into
   16.31 +     * and number of bytes to read.  Must return number of bytes read
   16.32 +     * on success, less than zero on error.
   16.33 +     */
   16.34 +    int (*read)(IOStream *stream, void *buf, size_t n);
   16.35 +
   16.36 +    /** Write function. Called with user data, buffer to write and
   16.37 +     * number of bytes to write. Must return number of bytes written on
   16.38 +     * success, less than zero otherwise.
   16.39 +     */
   16.40 +    int (*write)(IOStream *stream, const void *buf, size_t n);
   16.41 +
   16.42 +    int (*flush)(IOStream *s);
   16.43 +
   16.44 +    int (*error)(IOStream *s);
   16.45 +
   16.46 +    int (*close)(IOStream *s);
   16.47 +
   16.48 +    void (*free)(IOStream *s);
   16.49 +
   16.50 +    void (*lock)(IOStream *s);
   16.51 +    void (*unlock)(IOStream *s);
   16.52 +
   16.53 +} IOMethods;
   16.54 +
   16.55 +/** Abstract i/o object.
   16.56 + */
   16.57 +struct IOStream {
   16.58 +    /** Methods to use to implement operations. */
   16.59 +    const IOMethods *methods;
   16.60 +    /** Private state for the implementation. */
   16.61 +    const void *data;
   16.62 +    /** Flag indicating whether the stream is closed. */
   16.63 +    int closed;
   16.64 +    /** Number of bytes written. */
   16.65 +    int written;
   16.66 +    /** Number of bytes read. */
   16.67 +    int read;
   16.68 +};
   16.69 +
   16.70 +
   16.71 +/** IOStream version of stdin. */
   16.72 +extern IOStream *iostdin;
   16.73 +
   16.74 +/** IOStream version of stdout, */
   16.75 +extern IOStream *iostdout;
   16.76 +
   16.77 +/** IOStream version of stderr. */
   16.78 +extern IOStream *iostderr;
   16.79 +
   16.80 +extern int IOStream_print(IOStream *io, const char *format, ...);
   16.81 +extern int IOStream_vprint(IOStream *io, const char *format, va_list args);
   16.82 +
   16.83 +/** Read from a stream.
   16.84 + *
   16.85 + * @param stream input
   16.86 + * @param buf where to put input
   16.87 + * @param n number of bytes to read
   16.88 + * @return if ok, number of bytes read, otherwise negative error code
   16.89 + */
   16.90 +static inline int IOStream_read(IOStream *stream, void *buf, size_t n){
   16.91 +    int result = 0;
   16.92 +    if(stream->closed) goto exit;
   16.93 +    if(!stream->methods || !stream->methods->read){
   16.94 +        result = -EINVAL;
   16.95 +        goto exit;
   16.96 +    }
   16.97 +    result = stream->methods->read(stream, buf, n);
   16.98 +    if(result > 0){
   16.99 +        stream->read += result;
  16.100 +    }
  16.101 +  exit:
  16.102 +    return result;
  16.103 +}
  16.104 +
  16.105 +/** Write to a stream.
  16.106 + *
  16.107 + * @param stream input
  16.108 + * @param buf where to put input
  16.109 + * @param n number of bytes to write
  16.110 + * @return if ok, number of bytes read, otherwise negative error code
  16.111 + */
  16.112 +static inline int IOStream_write(IOStream *stream, const void *buf, size_t n){
  16.113 +    int result = 0;
  16.114 +    if(stream->closed) goto exit;
  16.115 +    if(!stream->methods || !stream->methods->write){
  16.116 +        result = -EINVAL;
  16.117 +        goto exit;
  16.118 +    }
  16.119 +    result = stream->methods->write(stream, buf, n);
  16.120 +    if(result > 0){
  16.121 +        stream->written += result;
  16.122 +    }
  16.123 +  exit:
  16.124 +    return result;
  16.125 +}
  16.126 +
  16.127 +/** Flush the stream.
  16.128 + *
  16.129 + * @param stream stream
  16.130 + * @return 0 on success, IOSTREAM_EOF otherwise
  16.131 + */
  16.132 +static inline int IOStream_flush(IOStream *stream){
  16.133 +    int result = 0;
  16.134 +    if(stream->closed){
  16.135 +        result = IOSTREAM_EOF;
  16.136 +    } else if(stream->methods->flush){
  16.137 +        result = stream->methods->flush(stream);
  16.138 +        if(result < 0) result = IOSTREAM_EOF;
  16.139 +    }
  16.140 +    return result;
  16.141 +}
  16.142 +
  16.143 +/** Check whether the stream has an error.
  16.144 + *
  16.145 + * @param stream to check
  16.146 + * @return 1 for error, 0 otherwise
  16.147 + */
  16.148 +static inline int IOStream_error(IOStream *stream){
  16.149 +    int err = 0;
  16.150 +    if(stream->methods && stream->methods->error){
  16.151 +       err = stream->methods->error(stream);
  16.152 +    }
  16.153 +    return err;
  16.154 +}
  16.155 +
  16.156 +/** Close the stream.
  16.157 + *
  16.158 + * @param stream to close
  16.159 + * @return 1 for error, 0 otherwise
  16.160 + */
  16.161 +static inline int IOStream_close(IOStream *stream){
  16.162 +    int err = 1;
  16.163 +    if(stream->methods && stream->methods->close){
  16.164 +        err = stream->methods->close(stream);
  16.165 +    }
  16.166 +    return err;
  16.167 +}
  16.168 +
  16.169 +/** Test if the stream has been closed.
  16.170 + *
  16.171 + * @param stream to check
  16.172 + * @return 1 if closed, 0 otherwise
  16.173 + */
  16.174 +static inline int IOStream_is_closed(IOStream *stream){
  16.175 +  return stream->closed;
  16.176 +}
  16.177 +
  16.178 +/** Free the memory used by the stream.
  16.179 + *
  16.180 + * @param stream to free
  16.181 + */
  16.182 +static inline void IOStream_free(IOStream *stream){
  16.183 +  if(stream->methods && stream->methods->free){
  16.184 +    stream->methods->free(stream);
  16.185 +  }
  16.186 +  *stream = (IOStream){};
  16.187 +  deallocate(stream);
  16.188 +}
  16.189 +
  16.190 +
  16.191 +/** Print a character to a stream, like fputc().
  16.192 + *
  16.193 + * @param stream to print to
  16.194 + * @param c character to print
  16.195 + * @return result code from the print
  16.196 + */
  16.197 +static inline int IOStream_putc(IOStream *stream, int c){
  16.198 +    int err;
  16.199 +    unsigned char b = (unsigned char)c;
  16.200 +    err = IOStream_write(stream, &b, 1);
  16.201 +    if(err < 1){
  16.202 +        err = IOSTREAM_EOF;
  16.203 +    } else {
  16.204 +        err = b;
  16.205 +    }
  16.206 +    return err;
  16.207 +}
  16.208 +
  16.209 +/** Read from a stream, like fgetc().
  16.210 + *
  16.211 + * @param stream to read from
  16.212 + * @return IOSTREAM_EOF on error, character read otherwise
  16.213 + */
  16.214 +static inline int IOStream_getc(IOStream *stream){
  16.215 +    int err, rc;
  16.216 +    unsigned char b;
  16.217 +
  16.218 +    err = IOStream_read(stream, &b, 1);
  16.219 +    if(err < 1){
  16.220 +        rc = IOSTREAM_EOF;
  16.221 +    } else {
  16.222 +        rc = b;
  16.223 +    }
  16.224 +    return rc;
  16.225 +}
  16.226 +
  16.227 +/** Get number of bytes read.
  16.228 + *
  16.229 + * @param stream to get from
  16.230 + * @return number of bytes read
  16.231 + */
  16.232 +static inline int IOStream_get_read(IOStream *stream){
  16.233 +    return stream->read;
  16.234 +}
  16.235 +
  16.236 +/** Get number of bytes written.
  16.237 + *
  16.238 + * @param stream to get from
  16.239 + * @return number of bytes written
  16.240 + */
  16.241 +static inline int IOStream_get_written(IOStream *stream){
  16.242 +    return stream->written;
  16.243 +}
  16.244 +
  16.245 +
  16.246 +#endif /* ! _XC_LINUX_SAVE_H_ */
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/lib/kernel_stream.c	Tue Jun 29 12:05:29 2004 +0000
    17.3 @@ -0,0 +1,177 @@
    17.4 +/*
    17.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    17.6 + *
    17.7 + * This library is free software; you can redistribute it and/or modify
    17.8 + * it under the terms of the GNU Lesser General Public License as published by
    17.9 + * the Free Software Foundation; either version 2.1 of the License, or
   17.10 + * (at your option) any later version.
   17.11 + *
   17.12 + * This library is distributed in the hope that it will be useful,
   17.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   17.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17.15 + * GNU Lesser General Public License for more details.
   17.16 + *
   17.17 + * You should have received a copy of the GNU Lesser General Public License
   17.18 + * along with this library; if not, write to the Free Software
   17.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   17.20 + */
   17.21 +
   17.22 +/** @file
   17.23 + * An IOStream implementation using printk() for output.
   17.24 + * Input is not implemented.
   17.25 + */
   17.26 +#ifdef __KERNEL__
   17.27 +
   17.28 +#include <linux/config.h>
   17.29 +#include <linux/module.h>
   17.30 +#include <linux/kernel.h>
   17.31 +#include <linux/types.h>
   17.32 +#include <linux/errno.h>
   17.33 +#include <linux/slab.h>
   17.34 +#include <linux/spinlock.h>
   17.35 +
   17.36 +#include "kernel_stream.h"
   17.37 +#include "allocate.h"
   17.38 +
   17.39 +/** Number of characters in the output buffer.
   17.40 + * The kernel uses 1024 for printk, so that should suffice.
   17.41 + */
   17.42 +#define BUF_N 1024
   17.43 +
   17.44 +/** State for a kernel stream. */
   17.45 +typedef struct KernelData {
   17.46 +    /** Stream lock. We need a lock to serialize access to the stream. */
   17.47 +    spinlock_t lock;
   17.48 +    /** Saved flags for locking. */
   17.49 +    unsigned long flags;
   17.50 +    /** Size of the output buffer. */
   17.51 +    int buf_n;
   17.52 +    /** Output buffer. */
   17.53 +    char buf[BUF_N];
   17.54 +} KernelData;
   17.55 +
   17.56 +static int kernel_write(IOStream *s, const char *msg, int n);
   17.57 +static void kernel_free(IOStream *s);
   17.58 +static void kernel_stream_lock(IOStream *s);
   17.59 +static void kernel_stream_unlock(IOStream *s);
   17.60 +
   17.61 +/** Methods for a kernel stream. Output only. */
   17.62 +static const IOMethods kernel_methods = {
   17.63 +  write:  kernel_write,
   17.64 +  free:   kernel_free,
   17.65 +  lock:   kernel_stream_lock,
   17.66 +  unlock: kernel_stream_unlock,
   17.67 +};
   17.68 +
   17.69 +/** Shared state for kernel streams.
   17.70 + * All implementations write using printk, so we can use
   17.71 + * shared state and avoid allocating it.
   17.72 + */
   17.73 +static const KernelData kernel_data = {
   17.74 +  lock: SPIN_LOCK_UNLOCKED,
   17.75 +  flags: 0,
   17.76 +  buf_n: BUF_N,
   17.77 +};
   17.78 +
   17.79 +/** Stream for kernel printk. */
   17.80 +static IOStream iokernel = {
   17.81 +    methods: &kernel_methods,
   17.82 +    data:    &kernel_data,
   17.83 +};
   17.84 +
   17.85 +/** Stream for kernel printk. */
   17.86 +IOStream *iostdout = &iokernel;
   17.87 +
   17.88 +/** Stream for kernel printk. */
   17.89 +IOStream *iostdin = &iokernel;
   17.90 +
   17.91 +/** Stream for kernel printk. */
   17.92 +IOStream *iostderr = &iokernel;
   17.93 +
   17.94 +/** Get an output-only stream implementation using
   17.95 + * printk(). The stream uses static storage, and must not be freed.
   17.96 + *
   17.97 + * @return kernel stream
   17.98 + */
   17.99 +IOStream get_stream_kernel(void){
  17.100 +  return iokernel;
  17.101 +}
  17.102 +
  17.103 +/** Obtain the lock on the stream state.
  17.104 + *
  17.105 + * @param kdata stream state
  17.106 + */
  17.107 +static inline void KernelData_lock(KernelData *kdata){
  17.108 +  spin_lock_irqsave(&kdata->lock, kdata->flags);
  17.109 +}
  17.110 +
  17.111 +/** Release the lock on the stream state.
  17.112 + *
  17.113 + * @param kdata stream state
  17.114 + */
  17.115 +static inline void KernelData_unlock(KernelData *kdata){
  17.116 +  spin_unlock_irqrestore(&kdata->lock, kdata->flags);
  17.117 +}
  17.118 +
  17.119 +/** Get the stream state.
  17.120 + *
  17.121 + * @param s kernel stream
  17.122 + * @return stream state
  17.123 + */
  17.124 +static inline KernelData *get_kernel_data(IOStream *s){
  17.125 +  return (KernelData*)s->data;
  17.126 +}
  17.127 +
  17.128 +/** Obtain the lock on the stream state.
  17.129 + *
  17.130 + * @param s stream
  17.131 + */
  17.132 +void kernel_stream_lock(IOStream *s){
  17.133 +    KernelData_lock(get_kernel_data(s));
  17.134 +}
  17.135 +
  17.136 +/** Release the lock on the stream state.
  17.137 + *
  17.138 + * @param s stream
  17.139 + */
  17.140 +void kernel_stream_unlock(IOStream *s){
  17.141 +    KernelData_unlock(get_kernel_data(s));
  17.142 +}
  17.143 +
  17.144 +/** Write to a kernel stream.
  17.145 + *
  17.146 + * @param stream kernel stream
  17.147 + * @param format print format
  17.148 + * @param args print arguments
  17.149 + * @return result of the print
  17.150 + */
  17.151 +static int kernel_write(IOStream *stream, const char *buf, int n){
  17.152 +  KernelData *kdata = get_kernel_data(stream);
  17.153 +  int k;
  17.154 +  k = kdata->buf_n - 1;
  17.155 +  if(n < k) k = n;
  17.156 +  memcpy(kdata->buf, buf, k);
  17.157 +  kdata->buf[k] = '\0'
  17.158 +  printk(kdata->buf);
  17.159 +  return k;
  17.160 +}
  17.161 +
  17.162 +/** Free a kernel stream.
  17.163 + * Frees the internal state of the stream.
  17.164 + * Do not call this unless the stream was dynamically allocated.
  17.165 + * Do not call this on a stream returned from get_stream_kernel().
  17.166 + *
  17.167 + * @param io stream to free
  17.168 + */
  17.169 +static void kernel_free(IOStream *io){
  17.170 +  KernelData *kdata;
  17.171 +  if(io == &iokernel) return;
  17.172 +  kdata = get_kernel_data(io);
  17.173 +  zero(kdata, sizeof(*kdata));
  17.174 +  deallocate(kdata);
  17.175 +}
  17.176 +#endif /* __KERNEL__ */
  17.177 +
  17.178 +
  17.179 +
  17.180 +
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/lib/kernel_stream.h	Tue Jun 29 12:05:29 2004 +0000
    18.3 @@ -0,0 +1,29 @@
    18.4 +/*
    18.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    18.6 + *
    18.7 + * This library is free software; you can redistribute it and/or modify
    18.8 + * it under the terms of the GNU Lesser General Public License as published by
    18.9 + * the Free Software Foundation; either version 2.1 of the License, or
   18.10 + * (at your option) any later version.
   18.11 + *
   18.12 + * This library is distributed in the hope that it will be useful,
   18.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.15 + * GNU Lesser General Public License for more details.
   18.16 + *
   18.17 + * You should have received a copy of the GNU Lesser General Public License
   18.18 + * along with this library; if not, write to the Free Software
   18.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   18.20 + */
   18.21 +
   18.22 +#ifndef _XEN_LIB_KERNEL_STREAM_H_
   18.23 +#define _XEN_LIB_KERNEL_STREAM_H_
   18.24 +
   18.25 +#ifdef __KERNEL__
   18.26 +#include "iostream.h"
   18.27 +
   18.28 +extern IOStream get_stream_kernel(void);
   18.29 +#define get_stream_stdout get_stream_kernel
   18.30 +
   18.31 +#endif /* __KERNEL__ */
   18.32 +#endif /* !_XEN_LIB_KERNEL_STREAM_H_ */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/lib/lexis.c	Tue Jun 29 12:05:29 2004 +0000
    19.3 @@ -0,0 +1,93 @@
    19.4 +/*
    19.5 + *
    19.6 + * This library is free software; you can redistribute it and/or modify
    19.7 + * it under the terms of the GNU Lesser General Public License as
    19.8 + * published by the Free Software Foundation; either version 2.1 of the
    19.9 + * License, or  (at your option) any later version. This library is 
   19.10 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   19.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.12 + * FITNESS FOR A PARTICULAR PURPOSE.
   19.13 + * See the GNU Lesser General Public License for more details.
   19.14 + *
   19.15 + * You should have received a copy of the GNU Lesser General Public License
   19.16 + * along with this library; if not, write to the Free Software Foundation,
   19.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   19.18 + */
   19.19 +
   19.20 +/** @file
   19.21 + * Lexical analysis.
   19.22 + */
   19.23 +
   19.24 +#include "sys_string.h"
   19.25 +#include "lexis.h"
   19.26 +#include <errno.h>
   19.27 +
   19.28 +/** Check if a value lies in a (closed) range.
   19.29 + *
   19.30 + * @param x value to test
   19.31 + * @param lo low end of the range
   19.32 + * @param hi high end of the range
   19.33 + * @return 1 if x is in the interval [lo, hi], 0 otherwise
   19.34 + */
   19.35 +inline static int in_range(int x, int lo, int hi){
   19.36 +    return (lo <= x) && (x <= hi);
   19.37 +}
   19.38 +
   19.39 +/** Determine if a string is an (unsigned) decimal number.
   19.40 + * 
   19.41 + * @param s pointer to characters to test
   19.42 + * @param n length of string
   19.43 + * @return 1 if s is a decimal number, 0 otherwise.
   19.44 + */
   19.45 +int is_decimal_number(const char *s, int n){
   19.46 +    int i;
   19.47 +    if(n <= 0)return 0;
   19.48 +    for(i = 0; i < n; i++){
   19.49 +        if(!in_decimal_digit_class(s[i])) return 0;
   19.50 +    }
   19.51 +    return 1;
   19.52 +}
   19.53 +
   19.54 +/** Determine if a string is a hex number.
   19.55 + * Hex numbers are 0, or start with 0x or 0X followed
   19.56 + * by a non-zero number of hex digits (0-9,a-f,A-F).
   19.57 + * 
   19.58 + * @param s pointer to characters to test
   19.59 + * @param n length of string
   19.60 + * @return 1 if s is a hex number, 0 otherwise.
   19.61 + */
   19.62 +int is_hex_number(const char *s, int n){
   19.63 +    int i;
   19.64 +    if(n <= 0) return 0;
   19.65 +    if(n == 1){
   19.66 +        return s[0]=='0';
   19.67 +    }
   19.68 +    if(n <= 3) return 0;
   19.69 +    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
   19.70 +    for(i = 2; i < n; i++){
   19.71 +        if(!in_hex_digit_class(s[i])) return 0;
   19.72 +    }
   19.73 +    return 1;
   19.74 +}
   19.75 +
   19.76 +/** Test if a string matches a keyword.
   19.77 + * The comparison is case-insensitive.
   19.78 + * The comparison fails if either argument is null.
   19.79 + *
   19.80 + * @param s string
   19.81 + * @param k keyword
   19.82 + * @return 1 if they match, 0 otherwise
   19.83 + */
   19.84 +int is_keyword(const char *s, const char *k){
   19.85 +  return s && k && !strcasecmp(s, k);
   19.86 +}
   19.87 +
   19.88 +/** Test if a string matches a character.
   19.89 + *
   19.90 + * @param s string
   19.91 + * @param c character (non-null)
   19.92 + * @return 1 if s contains exactly c, 0 otherwise
   19.93 + */
   19.94 +int is_keychar(const char *s, char c){
   19.95 +  return c && (s[0] == c) && !s[1];
   19.96 +}
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/lib/lexis.h	Tue Jun 29 12:05:29 2004 +0000
    20.3 @@ -0,0 +1,122 @@
    20.4 +/*
    20.5 + *
    20.6 + * This library is free software; you can redistribute it and/or modify
    20.7 + * it under the terms of the GNU Lesser General Public License as
    20.8 + * published by the Free Software Foundation; either version 2.1 of the
    20.9 + * License, or  (at your option) any later version. This library is 
   20.10 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   20.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.12 + * FITNESS FOR A PARTICULAR PURPOSE.
   20.13 + * See the GNU Lesser General Public License for more details.
   20.14 + *
   20.15 + * You should have received a copy of the GNU Lesser General Public License
   20.16 + * along with this library; if not, write to the Free Software Foundation,
   20.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   20.18 + */
   20.19 +
   20.20 +#ifndef _SP_LEXIS_H_
   20.21 +#define _SP_LEXIS_H_
   20.22 +
   20.23 +#include "sys_string.h"
   20.24 +#include "sys_ctype.h"
   20.25 +
   20.26 +/** @file
   20.27 + * Lexical analysis.
   20.28 + */
   20.29 +
   20.30 +/** Class of characters treated as space. */
   20.31 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
   20.32 +
   20.33 +/** Class of separator characters. */
   20.34 +#define sep_class "{}()<>[]@!;"
   20.35 +
   20.36 +#define comment_class "#"
   20.37 +
   20.38 +/** Determine if a character is in a given class.
   20.39 + * 
   20.40 + * @param c character to test
   20.41 + * @param s null-terminated string of characters in the class
   20.42 + * @return 1 if c is in the class, 0 otherwise.
   20.43 + */
   20.44 +static inline int in_class(int c, const char *s){
   20.45 +  return s && (strchr(s, c) != 0);
   20.46 +}
   20.47 +
   20.48 +/** Determine if a character is in the space class.
   20.49 + * 
   20.50 + * @param c character to test
   20.51 + * @return 1 if c is in the class, 0 otherwise.
   20.52 + */
   20.53 +static inline int in_space_class(int c){
   20.54 +    return in_class(c, space_class);
   20.55 +}
   20.56 +
   20.57 +static inline int in_comment_class(int c){
   20.58 +    return in_class(c, comment_class);
   20.59 +}
   20.60 +
   20.61 +/** Determine if a character is in the separator class.
   20.62 + * Separator characters terminate tokens, and do not need space
   20.63 + * to separate them.
   20.64 + * 
   20.65 + * @param c character to test
   20.66 + * @return 1 if c is in the class, 0 otherwise.
   20.67 + */
   20.68 +static inline int in_sep_class(int c){
   20.69 +    return in_class(c, sep_class);
   20.70 +}
   20.71 +
   20.72 +/** Determine if a character is in the alpha class.
   20.73 + * 
   20.74 + * @param c character to test
   20.75 + * @return 1 if c is in the class, 0 otherwise.
   20.76 + */
   20.77 +static inline int in_alpha_class(int c){
   20.78 +    return isalpha(c);
   20.79 +}
   20.80 +
   20.81 +/** Determine if a character is in the octal digit class.
   20.82 + * 
   20.83 + * @param c character to test
   20.84 + * @return 1 if c is in the class, 0 otherwise.
   20.85 + */
   20.86 +static inline int in_octal_digit_class(int c){
   20.87 +    return '0' <= c && c <= '7';
   20.88 +}
   20.89 +
   20.90 +/** Determine if a character is in the decimal digit class.
   20.91 + * 
   20.92 + * @param c character to test
   20.93 + * @return 1 if c is in the class, 0 otherwise.
   20.94 + */
   20.95 +static inline int in_decimal_digit_class(int c){
   20.96 +    return isdigit(c);
   20.97 +}
   20.98 +
   20.99 +/** Determine if a character is in the hex digit class.
  20.100 + * 
  20.101 + * @param c character to test
  20.102 + * @return 1 if c is in the class, 0 otherwise.
  20.103 + */
  20.104 +static inline int in_hex_digit_class(int c){
  20.105 +    return isdigit(c) || in_class(c, "abcdefABCDEF");
  20.106 +}
  20.107 +
  20.108 +
  20.109 +static inline int in_string_quote_class(int c){
  20.110 +    return in_class(c, "'\"");
  20.111 +}
  20.112 +
  20.113 +static inline int in_printable_class(int c){
  20.114 +    return ('A' <= c && c <= 'Z')
  20.115 +        || ('a' <= c && c <= 'z')
  20.116 +        || ('0' <= c && c <= '9')
  20.117 +        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
  20.118 +}
  20.119 +
  20.120 +extern int is_decimal_number(const char *s, int n);
  20.121 +extern int is_hex_number(const char *s, int n);
  20.122 +extern int is_keyword(const char *s, const char *k);
  20.123 +extern int is_keychar(const char *s, char c);
  20.124 +
  20.125 +#endif /* !_SP_LEXIS_H_ */
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/tools/lib/lzi_stream.c	Tue Jun 29 12:05:29 2004 +0000
    21.3 @@ -0,0 +1,590 @@
    21.4 +/* $Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
    21.5 +#define __FILE_ID_INFO "$Id: lzi_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $"
    21.6 +#include <what.h>
    21.7 +static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO;
    21.8 +/*
    21.9 + * Copyright (C) 2003 Hewlett-Packard Company.
   21.10 + *
   21.11 + * This library is free software; you can redistribute it and/or modify
   21.12 + * it under the terms of the GNU Lesser General Public License as published by
   21.13 + * the Free Software Foundation; either version 2.1 of the License, or
   21.14 + * (at your option) any later version.
   21.15 + *
   21.16 + * This library is distributed in the hope that it will be useful,
   21.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.19 + * GNU Lesser General Public License for more details.
   21.20 + *
   21.21 + * You should have received a copy of the GNU Lesser General Public License
   21.22 + * along with this library; if not, write to the Free Software
   21.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21.24 + */
   21.25 +
   21.26 +/** @file
   21.27 + * An IOStream implementation using LZI to provide compression and decompression.
   21.28 + * This is designed to provide compression without output latency.
   21.29 + * Flushing an LZI stream flushes all pending data to the underlying stream.
   21.30 + * This is essential for stream-based (e.g. networked) applications.
   21.31 + *
   21.32 + * A compressed data stream is a sequence of blocks.
   21.33 + * Each block is the block size followed by the compressed data.
   21.34 + * The last block has size zero.
   21.35 + * Sizes are 4-byte unsigned in network order.
   21.36 + *
   21.37 + * This format allows compressed data to be read from a stream without reading
   21.38 + * past the logical end of compressed data.
   21.39 + *
   21.40 + * @author Mike Wray <mike.wray@hpl.hp.com>
   21.41 + */
   21.42 +#ifndef __KERNEL__
   21.43 +
   21.44 +#include <stdio.h>
   21.45 +#include <stdlib.h>
   21.46 +#include <errno.h>
   21.47 +#include <string.h>
   21.48 +
   21.49 +#include "zlib.h"
   21.50 +
   21.51 +#include "allocate.h"
   21.52 +#include "lzi_stream.h"
   21.53 +#include "file_stream.h"
   21.54 +#include "marshal.h"
   21.55 +
   21.56 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZI>%s" fmt, __FUNCTION__, ##args)
   21.57 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN]  LZI>%s" fmt, __FUNCTION__, ##args)
   21.58 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO]  LZI>%s" fmt, __FUNCTION__, ##args)
   21.59 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZI>%s" fmt, __FUNCTION__, ##args)
   21.60 +
   21.61 +static int lzi_read(IOStream *s, void *buf, size_t size, size_t count);
   21.62 +static int lzi_write(IOStream *s, const void *buf, size_t size, size_t count);
   21.63 +static int lzi_print(IOStream *s, const char *msg, va_list args);
   21.64 +static int lzi_getc(IOStream *s);
   21.65 +static int lzi_error(IOStream *s);
   21.66 +static int lzi_close(IOStream *s);
   21.67 +static void lzi_free(IOStream *s);
   21.68 +static int lzi_flush(IOStream *s);
   21.69 +
   21.70 +enum {
   21.71 +    LZI_WRITE = 1,
   21.72 +    LZI_READ = 2,
   21.73 +};
   21.74 +
   21.75 +/** Methods used by a gzFile* IOStream. */
   21.76 +static const IOMethods lzi_methods = {
   21.77 +    read: lzi_read,
   21.78 +    write: lzi_write,
   21.79 +    print: lzi_print,
   21.80 +    getc:  lzi_getc,
   21.81 +    error: lzi_error,
   21.82 +    close: lzi_close,
   21.83 +    free:  lzi_free,
   21.84 +    flush: lzi_flush,
   21.85 +};
   21.86 +
   21.87 +#define BUFFER_SIZE (512 * 1024)
   21.88 +
   21.89 +typedef struct LZIState {
   21.90 +    z_stream zstream;
   21.91 +    void *inbuf;
   21.92 +    uint32_t inbuf_size;
   21.93 +    void *outbuf;
   21.94 +    uint32_t outbuf_size;
   21.95 +    /** Underlying stream for I/O. */
   21.96 +    IOStream *io;
   21.97 +    /** Flags. */
   21.98 +    int flags;
   21.99 +    /** Error indicator. */
  21.100 +    int error;
  21.101 +    int eof;
  21.102 +    int plain_bytes;
  21.103 +    int comp_bytes;
  21.104 +    int zstream_initialized;
  21.105 +    int flushed;
  21.106 +} LZIState;
  21.107 +
  21.108 +static inline int LZIState_writeable(LZIState *s){
  21.109 +    return (s->flags & LZI_WRITE) != 0;
  21.110 +}
  21.111 +
  21.112 +static inline int LZIState_readable(LZIState *s){
  21.113 +    return (s->flags & LZI_READ) != 0;
  21.114 +}
  21.115 +
  21.116 +void LZIState_free(LZIState *z){
  21.117 +    if(!z) return;
  21.118 +    if(z->zstream_initialized){
  21.119 +        if(LZIState_writeable(z)){
  21.120 +            deflateEnd(&z->zstream);
  21.121 +        } else if(LZIState_readable(z)){
  21.122 +            inflateEnd(&z->zstream);
  21.123 +        }
  21.124 +    }
  21.125 +    deallocate(z->inbuf);
  21.126 +    deallocate(z->outbuf);
  21.127 +    deallocate(z);
  21.128 +}
  21.129 +
  21.130 +static int mode_flags(const char *mode, int *flags){
  21.131 +    int err = 0;
  21.132 +    int r=0, w=0;
  21.133 +    if(!mode){
  21.134 +        err = -EINVAL;
  21.135 +        goto exit;
  21.136 +    }
  21.137 +    for(; *mode; mode++){
  21.138 +        if(*mode == 'w') w = 1;
  21.139 +        if(*mode == 'r') r = 1;
  21.140 +    }
  21.141 +    if(r + w != 1){
  21.142 +        err = -EINVAL;
  21.143 +        goto exit;
  21.144 +    }
  21.145 +    if(r) *flags |= LZI_READ;
  21.146 +    if(w) *flags |= LZI_WRITE;
  21.147 +  exit:
  21.148 +    return err;
  21.149 +}
  21.150 +
  21.151 +/** Get the stream state.
  21.152 + * 
  21.153 + * @param s lzi stream
  21.154 + * @return stream state.
  21.155 + */
  21.156 +static inline LZIState * lzi_state(IOStream *io){
  21.157 +    return io->data;
  21.158 +}
  21.159 +
  21.160 +IOStream *lzi_stream_io(IOStream *io){
  21.161 +    LZIState *s = lzi_state(io);
  21.162 +    return s->io;
  21.163 +}
  21.164 +
  21.165 +static inline void set_error(LZIState *s, int err){
  21.166 +    if(err < 0 && !s->error){
  21.167 +        s->error = err;
  21.168 +    }
  21.169 +}
  21.170 +
  21.171 +static int zerror(LZIState *s, int err){
  21.172 +    if(err){
  21.173 +        //dprintf("> err=%d\n", err);
  21.174 +        if(err < 0) set_error(s, -EIO);
  21.175 +    }
  21.176 +    return s->error;
  21.177 +}
  21.178 +
  21.179 +int lzi_stream_plain_bytes(IOStream *io){
  21.180 +    LZIState *s = lzi_state(io);
  21.181 +    return s->plain_bytes;
  21.182 +}
  21.183 +
  21.184 +int lzi_stream_comp_bytes(IOStream *io){
  21.185 +    LZIState *s = lzi_state(io);
  21.186 +    return s->comp_bytes;
  21.187 +}
  21.188 +
  21.189 +float lzi_stream_ratio(IOStream *io){
  21.190 +    LZIState *s = lzi_state(io);
  21.191 +    float ratio = 0.0;
  21.192 +    if(s->comp_bytes){
  21.193 +        ratio = ((float) s->comp_bytes)/((float) s->plain_bytes);
  21.194 +    }
  21.195 +    return ratio;
  21.196 +}
  21.197 +
  21.198 +static int alloc(void **p, int n){
  21.199 +    *p = allocate(n);
  21.200 +    return (p ? 0 : -ENOMEM);
  21.201 +}
  21.202 +
  21.203 +LZIState * LZIState_new(IOStream *io, int flags){
  21.204 +    int err = -ENOMEM;
  21.205 +    int zlevel = Z_BEST_SPEED; // Level 1 compression - fastest.
  21.206 +    int zstrategy = Z_DEFAULT_STRATEGY;
  21.207 +    int zwindow = MAX_WBITS;
  21.208 +    int zmemory = 8;
  21.209 +    LZIState *z = ALLOCATE(LZIState);
  21.210 +
  21.211 +    //dprintf(">\n");
  21.212 +    if(!z) goto exit;
  21.213 +    z->io = io;
  21.214 +    z->flags = flags;
  21.215 +
  21.216 +    if(LZIState_writeable(z)){
  21.217 +        z->outbuf_size = BUFFER_SIZE;
  21.218 +        /* windowBits is passed < 0 to suppress zlib header */
  21.219 +        err = deflateInit2(&z->zstream, zlevel, Z_DEFLATED, -zwindow, zmemory, zstrategy);
  21.220 +        if (err != Z_OK) goto exit;
  21.221 +        z->zstream_initialized = 1;
  21.222 +        err = alloc(&z->outbuf, z->outbuf_size);
  21.223 +        if(err) goto exit;
  21.224 +        z->zstream.next_out = z->outbuf;
  21.225 +        z->zstream.avail_out = z->outbuf_size;
  21.226 +    } else {
  21.227 +        z->inbuf_size = BUFFER_SIZE;
  21.228 +        err = alloc(&z->inbuf, z->inbuf_size);
  21.229 +        if(err) goto exit;
  21.230 +        ///z->zstream.next_in  = z->inbuf;
  21.231 +
  21.232 +        /* windowBits is passed < 0 to tell that there is no zlib header.
  21.233 +         * Note that in this case inflate *requires* an extra "dummy" byte
  21.234 +         * after the compressed stream in order to complete decompression and
  21.235 +         * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
  21.236 +         * present after the compressed stream.
  21.237 +         */
  21.238 +        err = inflateInit2(&z->zstream, -zwindow);
  21.239 +        if(err != Z_OK) goto exit;
  21.240 +        z->zstream_initialized = 1;
  21.241 +    }
  21.242 +        
  21.243 +  exit:
  21.244 +    if(err){
  21.245 +        LZIState_free(z);
  21.246 +        z = NULL;
  21.247 +    }
  21.248 +    //dprintf("< z=%p\n", z);
  21.249 +    return z;
  21.250 +}
  21.251 +
  21.252 +int read_block(LZIState *s){
  21.253 +    int err = 0, k = 0;
  21.254 +    //dprintf(">\n");
  21.255 +    if(s->eof) goto exit;
  21.256 +    err = unmarshal_uint32(s->io, &k);
  21.257 +    if(err) goto exit;
  21.258 +    if(k > s->inbuf_size){
  21.259 +        err = -EINVAL;
  21.260 +        goto exit;
  21.261 +    }
  21.262 +    if(k){
  21.263 +        err = unmarshal_bytes(s->io, s->inbuf, k);
  21.264 +        if(err) goto exit;
  21.265 +    } else {
  21.266 +        s->eof = 1;
  21.267 +    }        
  21.268 +    s->zstream.avail_in = k;
  21.269 +    s->zstream.next_in = s->inbuf;
  21.270 +    s->comp_bytes += 4;
  21.271 +    s->comp_bytes += k;
  21.272 +  exit:
  21.273 +    //dprintf("< err=%d\n", err);
  21.274 +    return err;
  21.275 +}
  21.276 +
  21.277 +int write_block(LZIState *s){
  21.278 +    int err = 0;
  21.279 +    int k = ((char*)s->zstream.next_out) - ((char*)s->outbuf);
  21.280 +    int k2 = s->outbuf_size - s->zstream.avail_out;
  21.281 +    //dprintf("> k=%d k2=%d\n", k, k2);
  21.282 +    if(!k) goto exit;
  21.283 +    err = marshal_uint32(s->io, k);
  21.284 +    if(err) goto exit;
  21.285 +    err = marshal_bytes(s->io, s->outbuf, k);
  21.286 +    if(err) goto exit;
  21.287 +    s->zstream.next_out = s->outbuf;
  21.288 +    s->zstream.avail_out = s->outbuf_size;
  21.289 +    s->comp_bytes += 4;
  21.290 +    s->comp_bytes += k;
  21.291 +  exit:
  21.292 +    //dprintf("< err=%d\n", err);
  21.293 +    return err;
  21.294 +}
  21.295 +
  21.296 +int write_terminator(LZIState *s){
  21.297 +    int err = 0;
  21.298 +    char c = 0;
  21.299 +    err = marshal_uint32(s->io, 1);
  21.300 +    if(err) goto exit;
  21.301 +    err = marshal_bytes(s->io, &c, 1);
  21.302 +    if(err) goto exit;
  21.303 +    err = marshal_uint32(s->io, 0);
  21.304 +    if(err) goto exit;
  21.305 +    s->comp_bytes += 9;
  21.306 +  exit:
  21.307 +    return err;
  21.308 +}
  21.309 +
  21.310 +/** Write to the underlying stream using fwrite();
  21.311 + *
  21.312 + * @param io destination
  21.313 + * @param buf data
  21.314 + * @param size size of data elements
  21.315 + * @param count number of data elements to write
  21.316 + * @return number of data elements written
  21.317 + */
  21.318 +static int lzi_write(IOStream *io, const void *buf, size_t size, size_t count){
  21.319 +    int err = 0;
  21.320 +    int n = size * count;
  21.321 +    LZIState *s = lzi_state(io);
  21.322 +
  21.323 +    //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n);
  21.324 +    if(!LZIState_writeable(s)){
  21.325 +        err = -EINVAL;
  21.326 +        goto exit;
  21.327 +    }
  21.328 +    s->flushed = 0;
  21.329 +    s->zstream.next_in = (void*)buf;
  21.330 +    s->zstream.avail_in = n;
  21.331 +    while(s->zstream.avail_in){
  21.332 +        if(s->zstream.avail_out == 0){
  21.333 +            err = write_block(s);
  21.334 +            if(err) goto exit;
  21.335 +        }
  21.336 +        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.337 +        //dprintf("> 1 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out);
  21.338 +        err = zerror(s, deflate(&s->zstream, Z_NO_FLUSH));
  21.339 +        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.340 +        //dprintf("> 2 deflate next_in=%p next_out=%p\n", s->zstream.next_in, s->zstream.next_out);
  21.341 +        if(err) goto exit;
  21.342 +    }
  21.343 +    err = n;
  21.344 +    s->plain_bytes += n;
  21.345 +    if(size != 1) err /= size;
  21.346 +  exit:
  21.347 +    //dprintf("< err=%d\n", err);
  21.348 +    return err;
  21.349 +}
  21.350 +
  21.351 +
  21.352 +/** Read from the underlying stream.
  21.353 + *
  21.354 + * @param io input
  21.355 + * @param buf where to put input
  21.356 + * @param size size of data elements
  21.357 + * @param count number of data elements to read
  21.358 + * @return number of data elements read
  21.359 + */
  21.360 +static int lzi_read(IOStream *io, void *buf, size_t size, size_t count){
  21.361 +    int err, zerr;
  21.362 +    int n = size * count;
  21.363 +    LZIState *s = lzi_state(io);
  21.364 +
  21.365 +    //dprintf("> size=%d count=%d n=%d\n", size, count, n);
  21.366 +    if(!LZIState_readable(s)){
  21.367 +        err = -EINVAL;
  21.368 +        goto exit;
  21.369 +    }
  21.370 +    s->zstream.next_out = buf;
  21.371 +    s->zstream.avail_out = n;
  21.372 +    while(s->zstream.avail_out){
  21.373 +        if(s->zstream.avail_in == 0){
  21.374 +            err = read_block(s);
  21.375 +        }
  21.376 +        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.377 +        zerr = inflate(&s->zstream, Z_NO_FLUSH);
  21.378 +        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.379 +        if(zerr == Z_STREAM_END) break;
  21.380 +        //dprintf("> zerr=%d\n", zerr);
  21.381 +        err = zerror(s, zerr);
  21.382 +        if(err) goto exit;
  21.383 +    }
  21.384 +    err = n - s->zstream.avail_out;
  21.385 +    s->plain_bytes += err;
  21.386 +    if(size != 1) err /= size;
  21.387 +  exit:
  21.388 +    set_error(s, err);
  21.389 +    //dprintf("< err=%d\n", err);
  21.390 +    return err;
  21.391 +}
  21.392 +
  21.393 +/** Print to the underlying stream.
  21.394 + * Returns 0 if the formatted output is too big for the internal buffer.
  21.395 + *
  21.396 + * @param io lzi stream
  21.397 + * @param msg format to use
  21.398 + * @param args arguments
  21.399 + * @return result of the print
  21.400 + */
  21.401 +static int lzi_print(IOStream *io, const char *msg, va_list args){
  21.402 +    char buf[1024];
  21.403 +    int buf_n = sizeof(buf);
  21.404 +    int n;
  21.405 +    LZIState *s = lzi_state(io);
  21.406 +    if(!LZIState_writeable(s)){
  21.407 +        n = -EINVAL;
  21.408 +        goto exit;
  21.409 +    }
  21.410 +    n = vsnprintf(buf, buf_n, (char*)msg, args);
  21.411 +    if(n < 0) goto exit;
  21.412 +    if(n > buf_n){
  21.413 +        n = 0;
  21.414 +    } else {
  21.415 +        n = lzi_write(io, buf, 1, n);
  21.416 +    }
  21.417 +  exit:
  21.418 +    return n;
  21.419 +}
  21.420 +
  21.421 +/** Read a character from the underlying stream
  21.422 + *
  21.423 + * @param io lzi stream
  21.424 + * @return character read, IOSTREAM_EOF on end of file (or error)
  21.425 + */
  21.426 +static int lzi_getc(IOStream *io){
  21.427 +    int err;
  21.428 +    char c;
  21.429 +    err = lzi_read(io, &c, 1, 1);
  21.430 +    if(err < 1) c = EOF;
  21.431 +    err = (c==EOF ? IOSTREAM_EOF : c);
  21.432 +    return err;
  21.433 +}
  21.434 +
  21.435 +static int flush_output(LZIState *s, int mode){
  21.436 +    int err = 0, zerr;
  21.437 +    int done = 0;
  21.438 +    int avail_out_old;
  21.439 +    int count = 10;
  21.440 +
  21.441 +    //dprintf("> avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.442 +    if(s->flushed == 1 + mode) goto exit;
  21.443 +    //s->zstream.avail_in = 0; /* should be zero already anyway */
  21.444 +    for(;;){
  21.445 +        // Write any available output.
  21.446 +        if(done || s->zstream.avail_out == 0){
  21.447 +            err = write_block(s);
  21.448 +            if(err) goto exit;
  21.449 +            if(done) break;
  21.450 +        }
  21.451 +        //dprintf("> 1 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.452 +        avail_out_old = s->zstream.avail_out;
  21.453 +        zerr = deflate(&s->zstream, mode);
  21.454 +        err = zerror(s, zerr);
  21.455 +        //dprintf("> 2 deflate avail_in=%d avail_out=%d\n", s->zstream.avail_in, s->zstream.avail_out);
  21.456 +        //dprintf("> deflate=%d\n", err);
  21.457 +        //done = (s->zstream.avail_out != 0);
  21.458 +        //done = (s->zstream.avail_in == 0) && (s->zstream.avail_out == avail_out_old);
  21.459 +        if(0 && mode == Z_FINISH){
  21.460 +            done = (zerr ==  Z_STREAM_END);
  21.461 +        } else {
  21.462 +            done = (s->zstream.avail_in == 0)
  21.463 +                //&& (s->zstream.avail_out == avail_out_old)
  21.464 +                && (s->zstream.avail_out != 0);
  21.465 +        }
  21.466 +    }
  21.467 +    s->flushed = 1 + mode;
  21.468 +  exit:
  21.469 +    //dprintf("< err=%d\n", err);
  21.470 +    return err;
  21.471 +}
  21.472 +
  21.473 +/** Flush any pending input to the underlying stream.
  21.474 + *
  21.475 + * @param s lzi stream
  21.476 + * @return 0 on success, error code otherwise
  21.477 + */
  21.478 +static int lzi_flush(IOStream *io){
  21.479 +    int err = 0;
  21.480 +    LZIState *s = lzi_state(io);
  21.481 +    //dprintf(">\n");
  21.482 +    if(!LZIState_writeable(s)){
  21.483 +        err = -EINVAL;
  21.484 +        goto exit;
  21.485 +    }
  21.486 +    err = flush_output(s, Z_SYNC_FLUSH);
  21.487 +    if(err) goto exit;
  21.488 +    err = IOStream_flush(s->io);
  21.489 +  exit:
  21.490 +    set_error(s, err);
  21.491 +    //dprintf("< err=%d\n", err);
  21.492 +    return (err < 0 ? err : 0);
  21.493 +}
  21.494 +
  21.495 +/** Check if a stream has an error.
  21.496 + *
  21.497 + * @param s lzi stream
  21.498 + * @return code if has an error, 0 otherwise
  21.499 + */
  21.500 +static int lzi_error(IOStream *s){
  21.501 +    int err = 0;
  21.502 +    LZIState *state = lzi_state(s);
  21.503 +    err = state->error;
  21.504 +    if(err) goto exit;
  21.505 +    err = IOStream_error(state->io);
  21.506 +  exit:
  21.507 +    return err;
  21.508 +}
  21.509 +
  21.510 +/** Close an lzi stream.
  21.511 + *
  21.512 + * @param s lzi stream to close
  21.513 + * @return result of the close
  21.514 + */
  21.515 +static int lzi_close(IOStream *io){
  21.516 +    int err = 0;
  21.517 +    LZIState *s = lzi_state(io);
  21.518 +    if(LZIState_writeable(s)){
  21.519 +        err = flush_output(s, Z_FINISH);
  21.520 +        if(err) goto exit;
  21.521 +        err = write_terminator(s);
  21.522 +        if(err) goto exit;
  21.523 +        err = IOStream_flush(s->io);
  21.524 +    }   
  21.525 +  exit:
  21.526 +    err = IOStream_close(s->io);
  21.527 +    set_error(s, err);
  21.528 +    return err;
  21.529 +}
  21.530 +
  21.531 +/** Free an lzi stream.
  21.532 + *
  21.533 + * @param s lzi stream
  21.534 + */
  21.535 +static void lzi_free(IOStream *s){
  21.536 +    LZIState *state = lzi_state(s);
  21.537 +    IOStream_free(state->io);
  21.538 +    LZIState_free(state);
  21.539 +    s->data = NULL;
  21.540 +}
  21.541 +
  21.542 +/** Create an lzi stream for an IOStream.
  21.543 + *
  21.544 + * @param io stream to wrap
  21.545 + * @return new IOStream using f for i/o
  21.546 + */
  21.547 +IOStream *lzi_stream_new(IOStream *io, const char *mode){
  21.548 +    int err = -ENOMEM;
  21.549 +    int flags = 0;
  21.550 +    IOStream *zio = NULL;
  21.551 +    LZIState *state = NULL;
  21.552 +
  21.553 +    zio = ALLOCATE(IOStream);
  21.554 +    if(!zio) goto exit;
  21.555 +    err = mode_flags(mode, &flags);
  21.556 +    if(err) goto exit;
  21.557 +    state = LZIState_new(io, flags);
  21.558 +    if(!state) goto exit;
  21.559 +    err = 0;
  21.560 +    zio->data = state;
  21.561 +    zio->methods = &lzi_methods;
  21.562 +  exit:
  21.563 +    if(err){
  21.564 +        if(state) LZIState_free(state);
  21.565 +        if(zio) deallocate(zio);
  21.566 +        zio = NULL;
  21.567 +    }
  21.568 +    return zio;
  21.569 +}
  21.570 +
  21.571 +/** IOStream version of fdopen().
  21.572 + *
  21.573 + * @param fd file descriptor
  21.574 + * @param flags giving the mode to open in (as for fdopen())
  21.575 + * @return new stream for the open file, or NULL if failed
  21.576 + */
  21.577 +IOStream *lzi_stream_fdopen(int fd, const char *mode){
  21.578 +    int err = -ENOMEM;
  21.579 +    IOStream *io = NULL, *zio = NULL;
  21.580 +    io = file_stream_fdopen(fd, mode);
  21.581 +    if(!io) goto exit;
  21.582 +    zio = lzi_stream_new(io, mode);
  21.583 +    if(!io) goto exit;
  21.584 +    err = 0;
  21.585 +  exit:
  21.586 +    if(err){
  21.587 +        IOStream_free(io);
  21.588 +        IOStream_free(zio);
  21.589 +        zio = NULL;
  21.590 +    }
  21.591 +    return zio;
  21.592 +}
  21.593 +#endif
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/lib/lzi_stream.h	Tue Jun 29 12:05:29 2004 +0000
    22.3 @@ -0,0 +1,36 @@
    22.4 +#/* $Id: lzi_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
    22.5 +/*
    22.6 + * Copyright (C) 2003 Hewlett-Packard Company.
    22.7 + *
    22.8 + * This library is free software; you can redistribute it and/or modify
    22.9 + * it under the terms of the GNU Lesser General Public License as published by
   22.10 + * the Free Software Foundation; either version 2.1 of the License, or
   22.11 + * (at your option) any later version.
   22.12 + *
   22.13 + * This library is distributed in the hope that it will be useful,
   22.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.16 + * GNU Lesser General Public License for more details.
   22.17 + *
   22.18 + * You should have received a copy of the GNU Lesser General Public License
   22.19 + * along with this library; if not, write to the Free Software
   22.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22.21 + */
   22.22 +
   22.23 +#ifndef _SP_LZI_STREAM_H_
   22.24 +#define _SP_LZI_STREAM_H_
   22.25 +
   22.26 +#ifndef __KERNEL__
   22.27 +#include "iostream.h"
   22.28 +
   22.29 +extern IOStream *lzi_stream_new(IOStream *io, const char *mode);
   22.30 +extern IOStream *lzi_stream_fopen(const char *file, const char *mode);
   22.31 +extern IOStream *lzi_stream_fdopen(int fd, const char *mode);
   22.32 +extern IOStream *lzi_stream_io(IOStream *zio);
   22.33 +
   22.34 +extern int lzi_stream_plain_bytes(IOStream *io);
   22.35 +extern int lzi_stream_comp_bytes(IOStream *io);
   22.36 +extern float lzi_stream_ratio(IOStream *io);
   22.37 +
   22.38 +#endif
   22.39 +#endif /* !_SP_FILE_STREAM_H_ */
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/lib/lzo_stream.c	Tue Jun 29 12:05:29 2004 +0000
    23.3 @@ -0,0 +1,596 @@
    23.4 +/* $Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $ */
    23.5 +#define __FILE_ID_INFO "$Id: lzo_stream.c,v 1.4 2003/09/30 15:22:53 mjw Exp $"
    23.6 +#include <what.h>
    23.7 +static char __rcsid[] __attribute__((unused)) = WHAT_ID __FILE_ID_INFO;
    23.8 +/*
    23.9 + * Copyright (C) 2003 Hewlett-Packard Company.
   23.10 + *
   23.11 + * This library is free software; you can redistribute it and/or modify
   23.12 + * it under the terms of the GNU Lesser General Public License as published by
   23.13 + * the Free Software Foundation; either version 2.1 of the License, or
   23.14 + * (at your option) any later version.
   23.15 + *
   23.16 + * This library is distributed in the hope that it will be useful,
   23.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.19 + * GNU Lesser General Public License for more details.
   23.20 + *
   23.21 + * You should have received a copy of the GNU Lesser General Public License
   23.22 + * along with this library; if not, write to the Free Software
   23.23 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23.24 + */
   23.25 +
   23.26 +/** @file
   23.27 + * An IOStream implementation using LZO to provide compression and decompression.
   23.28 + * This is designed to provide reasonable compression without output latency.
   23.29 + * Flushing an LZO stream flushes all pending data to the underlying stream.
   23.30 + * This is essential for stream-based (e.g. networked) applications.
   23.31 + *
   23.32 + * A compressed data stream is a sequence of blocks.
   23.33 + * Each block except the last is the plain data size followed by the compressed data size
   23.34 + * and the compressed data. The last block has plain data size zero and omits the rest.
   23.35 + * Sizes are 4-byte unsigned in network order. If the compressed size is smaller than
   23.36 + * the plain size the block data is compressed, otherwise it is plain (uncompressed).
   23.37 + *
   23.38 + * This format allows compressed data to be read from a stream without reading
   23.39 + * past the logical end of compressed data.
   23.40 + *
   23.41 + * @author Mike Wray <mike.wray@hpl.hp.com>
   23.42 + */
   23.43 +#ifndef __KERNEL__
   23.44 +
   23.45 +#include <stdio.h>
   23.46 +#include <stdlib.h>
   23.47 +#include <errno.h>
   23.48 +#include <string.h>
   23.49 +
   23.50 +#include "lzo1x.h"
   23.51 +
   23.52 +#include "allocate.h"
   23.53 +#include "lzo_stream.h"
   23.54 +#include "file_stream.h"
   23.55 +#include "marshal.h"
   23.56 +
   23.57 +#define dprintf(fmt, args...) fprintf(stdout, "[DEBUG] LZO>%s" fmt, __FUNCTION__, ##args)
   23.58 +#define wprintf(fmt, args...) fprintf(stderr, "[WARN]  LZO>%s" fmt, __FUNCTION__, ##args)
   23.59 +#define iprintf(fmt, args...) fprintf(stdout, "[INFO]  LZO>%s" fmt, __FUNCTION__, ##args)
   23.60 +#define eprintf(fmt, args...) fprintf(stderr, "[ERROR] LZO>%s" fmt, __FUNCTION__, ##args)
   23.61 +
   23.62 +static int lzo_read(IOStream *s, void *buf, size_t size, size_t count);
   23.63 +static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count);
   23.64 +static int lzo_print(IOStream *s, const char *msg, va_list args);
   23.65 +static int lzo_getc(IOStream *s);
   23.66 +static int lzo_error(IOStream *s);
   23.67 +static int lzo_close(IOStream *s);
   23.68 +static void lzo_free(IOStream *s);
   23.69 +static int lzo_flush(IOStream *s);
   23.70 +
   23.71 +enum {
   23.72 +    LZO_WRITE = 1,
   23.73 +    LZO_READ = 2,
   23.74 +};
   23.75 +
   23.76 +/** Methods used by a gzFile* IOStream. */
   23.77 +static const IOMethods lzo_methods = {
   23.78 +    read: lzo_read,
   23.79 +    write: lzo_write,
   23.80 +    print: lzo_print,
   23.81 +    getc:  lzo_getc,
   23.82 +    error: lzo_error,
   23.83 +    close: lzo_close,
   23.84 +    free:  lzo_free,
   23.85 +    flush: lzo_flush,
   23.86 +};
   23.87 +
   23.88 +//#define PLAIN_SIZE (64 * 1024)
   23.89 +//#define PLAIN_SIZE (128 * 1024)
   23.90 +#define PLAIN_SIZE (512 * 1024)
   23.91 +
   23.92 +//#define NOCOMPRESS
   23.93 +
   23.94 +typedef struct LZOState {
   23.95 +    /** Flags. */
   23.96 +    int flags;
   23.97 +    /** Error indicator. */
   23.98 +    int error;
   23.99 +    /** Underlying stream for I/O. */
  23.100 +    IOStream *io;
  23.101 +    /** Working memory (only needed for compression, not decompression). */
  23.102 +    lzo_byte *memory;
  23.103 +    /** Buffer for plain (uncompressed) data. */
  23.104 +    lzo_byte *plain;
  23.105 +    /** Size of the plain buffer. */
  23.106 +    lzo_uint plain_size;
  23.107 +    /** Pointer into the plain buffer. */
  23.108 +    lzo_byte *plain_ptr;
  23.109 +    /** Number of bytes of plain data available. */
  23.110 +    lzo_uint plain_n;
  23.111 +    /** Buffer for compressed data. */
  23.112 +    lzo_byte *comp;
  23.113 +    /** Size of the compressed buffer. */
  23.114 +    lzo_uint comp_size;
  23.115 +
  23.116 +    int plain_bytes;
  23.117 +    int comp_bytes;
  23.118 +} LZOState;
  23.119 +
  23.120 +void LZOState_free(LZOState *z){
  23.121 +    if(!z) return;
  23.122 +    deallocate(z->memory);
  23.123 +    deallocate(z->plain);
  23.124 +    deallocate(z->comp);
  23.125 +    deallocate(z);
  23.126 +}
  23.127 +
  23.128 +/** Maximum size of compressed data for the given plain data size.
  23.129 + *
  23.130 + * @param plain_size size of plain data
  23.131 + * @return maximum size of compressed data
  23.132 + */
  23.133 +static int comp_size(int plain_size){
  23.134 +    return plain_size + (plain_size / 64) + 16 + 3;
  23.135 +}
  23.136 +
  23.137 +static int mode_flags(const char *mode, int *flags){
  23.138 +    int err = 0;
  23.139 +    int r=0, w=0;
  23.140 +    if(!mode){
  23.141 +        err = -EINVAL;
  23.142 +        goto exit;
  23.143 +    }
  23.144 +    for(; *mode; mode++){
  23.145 +        if(*mode == 'w') w = 1;
  23.146 +        if(*mode == 'r') r = 1;
  23.147 +    }
  23.148 +    if(r + w != 1){
  23.149 +        err = -EINVAL;
  23.150 +        goto exit;
  23.151 +    }
  23.152 +    if(r) *flags |= LZO_READ;
  23.153 +    if(w) *flags |= LZO_WRITE;
  23.154 +  exit:
  23.155 +    return err;
  23.156 +}
  23.157 +
  23.158 +/** Get the stream state.
  23.159 + * 
  23.160 + * @param s lzo stream
  23.161 + * @return stream state.
  23.162 + */
  23.163 +static inline LZOState * lzo_state(IOStream *s){
  23.164 +    return s->data;
  23.165 +}
  23.166 +
  23.167 +IOStream *lzo_stream_io(IOStream *s){
  23.168 +    LZOState *state = lzo_state(s);
  23.169 +    return state->io;
  23.170 +}
  23.171 +
  23.172 +static inline void set_error(LZOState *state, int err){
  23.173 +    if(err < 0 && !state->error){
  23.174 +        state->error = err;
  23.175 +    }
  23.176 +}
  23.177 +
  23.178 +int lzo_stream_plain_bytes(IOStream *s){
  23.179 +    LZOState *state = lzo_state(s);
  23.180 +    return state->plain_bytes;
  23.181 +}
  23.182 +
  23.183 +int lzo_stream_comp_bytes(IOStream *s){
  23.184 +    LZOState *state = lzo_state(s);
  23.185 +    return state->comp_bytes;
  23.186 +}
  23.187 +
  23.188 +float lzo_stream_ratio(IOStream *s){
  23.189 +    LZOState *state = lzo_state(s);
  23.190 +    float ratio = 0.0;
  23.191 +    if(state->comp_bytes){
  23.192 +        ratio = ((float) state->comp_bytes)/((float) state->plain_bytes);
  23.193 +    }
  23.194 +    return ratio;
  23.195 +}
  23.196 +
  23.197 +static inline int LZOState_writeable(LZOState *state){
  23.198 +    return (state->flags & LZO_WRITE) != 0;
  23.199 +}
  23.200 +
  23.201 +static inline int LZOState_readable(LZOState *state){
  23.202 +    return (state->flags & LZO_READ) != 0;
  23.203 +}
  23.204 +
  23.205 +LZOState * LZOState_new(IOStream *io, int flags){
  23.206 +    int err = -ENOMEM;
  23.207 +    LZOState *z = ALLOCATE(LZOState);
  23.208 +    //dprintf(">\n");
  23.209 +    if(!z) goto exit;
  23.210 +    z->io = io;
  23.211 +    z->flags = flags;
  23.212 +    if(LZOState_writeable(z)){
  23.213 +        z->memory = allocate(LZO1X_1_MEM_COMPRESS);
  23.214 +        if(!z->memory) goto exit;
  23.215 +    }
  23.216 +    z->plain_size = PLAIN_SIZE;
  23.217 +    z->plain = allocate(z->plain_size);
  23.218 +    if(!z->plain) goto exit;
  23.219 +    z->plain_ptr = z->plain;
  23.220 +    z->comp_size = comp_size(z->plain_size);
  23.221 +    z->comp = allocate(z->comp_size);
  23.222 +    if(!z->comp) goto exit;
  23.223 +    err = 0;
  23.224 +  exit:
  23.225 +    if(err){
  23.226 +        LZOState_free(z);
  23.227 +        z = NULL;
  23.228 +    }
  23.229 +    //dprintf("< z=%p\n", z);
  23.230 +    return z;
  23.231 +}
  23.232 +
  23.233 +static int lzo_compress(LZOState *state){
  23.234 +    int err = 0;
  23.235 +    int k, comp_n;
  23.236 +    //dprintf(">\n");
  23.237 +    //dprintf(">plain=%p plain_n=%d comp=%p memory=%p\n", state->plain, state->plain_n, state->comp, state->memory);
  23.238 +    // Compress the plain buffer.
  23.239 +    err = lzo1x_1_compress(state->plain, state->plain_n,
  23.240 +                           state->comp, &comp_n,
  23.241 +                           state->memory);
  23.242 +    //dprintf("> err=%d plain_n=%d comp_n=%d\n", err, state->plain_n, comp_n);
  23.243 +    // Write plain size, compressed size.
  23.244 +    err = marshal_uint32(state->io, state->plain_n);
  23.245 +    if(err) goto exit;
  23.246 +    err = marshal_uint32(state->io, comp_n);
  23.247 +    if(err) goto exit;
  23.248 +    //dprintf("> write data...\n");
  23.249 +    // Write the smaller of the compressed and plain data.
  23.250 +    if(state->plain_n < comp_n){
  23.251 +        k = state->plain_n;
  23.252 +        err = marshal_bytes(state->io, state->plain, state->plain_n);
  23.253 +    } else {
  23.254 +        k = comp_n;
  23.255 +        err = marshal_bytes(state->io, state->comp, comp_n);
  23.256 +    }
  23.257 +    if(err) goto exit;
  23.258 +    // Total output bytes.
  23.259 +    k+= 8;
  23.260 +    //dprintf("> wrote %d bytes\n", k);
  23.261 +    state->plain_bytes += state->plain_n;
  23.262 +    state->comp_bytes += k;
  23.263 +    //dprintf("> plain=%d, comp=%d, ratio=%3.2f\n",
  23.264 +    //        state->plain_bytes, state->comp_bytes,
  23.265 +    //        ((float)state->comp_bytes)/((float)state->plain_bytes));
  23.266 +    // Reset the plain buffer.
  23.267 +    state->plain_ptr = state->plain;
  23.268 +    state->plain_n = 0;
  23.269 +    err = k;
  23.270 +  exit:
  23.271 +    //dprintf("< err=%d\n", err);
  23.272 +    return err;
  23.273 +}
  23.274 +
  23.275 +static int lzo_decompress(LZOState *state){
  23.276 +    int plain_n, comp_n;
  23.277 +    int err, k;
  23.278 +    //dprintf(">\n");
  23.279 +    err = unmarshal_uint32(state->io, &plain_n);
  23.280 +    //dprintf("> err=%d plain_n=%d\n", err, plain_n);
  23.281 +    if(err) goto exit;
  23.282 +    state->comp_bytes += 4;
  23.283 +    if(plain_n == 0) goto exit;
  23.284 +    err = unmarshal_uint32(state->io, &comp_n);
  23.285 +    //dprintf("> err=%d comp_n=%d\n", err, comp_n);
  23.286 +    if(err) goto exit;
  23.287 +    state->comp_bytes += 4;
  23.288 +    if(plain_n > state->plain_size){
  23.289 +        err = -EINVAL;
  23.290 +        goto exit;
  23.291 +    }
  23.292 +    if(comp_n > plain_n){
  23.293 +        //dprintf("> reading plain data %d...\n", plain_n);
  23.294 +        k = plain_n;
  23.295 +        err = unmarshal_bytes(state->io, state->plain, plain_n);
  23.296 +        state->plain_n = plain_n;
  23.297 +    } else {
  23.298 +        //dprintf("> reading comp data %d...\n", comp_n);
  23.299 +        k = comp_n;
  23.300 +        err = unmarshal_bytes(state->io, state->comp, comp_n);
  23.301 +        //dprintf("> decompress comp_n=%d\n", comp_n);
  23.302 +        err = lzo1x_decompress(state->comp, comp_n,
  23.303 +                               state->plain, &state->plain_n,
  23.304 +                               state->memory);
  23.305 +        //dprintf("> err=%d plain=%d state->plain_n=%d\n", err, plain_n, state->plain_n);
  23.306 +        if(err != LZO_E_OK || state->plain_n != plain_n){
  23.307 +            // Bad. Corrupted input.
  23.308 +            err = -EINVAL;
  23.309 +            eprintf("> Corrupted!\n");
  23.310 +            goto exit;
  23.311 +        }
  23.312 +    }
  23.313 +    state->comp_bytes += k;
  23.314 +    state->plain_bytes += state->plain_n;
  23.315 +    state->plain_ptr = state->plain;
  23.316 +    err = k;
  23.317 +  exit:
  23.318 +    //dprintf("< err=%d\n", err);
  23.319 +    return err;
  23.320 +}
  23.321 +
  23.322 +/** Write to the underlying stream using fwrite();
  23.323 + *
  23.324 + * @param stream destination
  23.325 + * @param buf data
  23.326 + * @param size size of data elements
  23.327 + * @param count number of data elements to write
  23.328 + * @return number of data elements written
  23.329 + */
  23.330 +static int lzo_write(IOStream *s, const void *buf, size_t size, size_t count){
  23.331 +    int err = 0;
  23.332 +    int n = size * count; // Total number of bytes to write.
  23.333 +    int chunk;            // Size of chunk to write.
  23.334 +    int remaining;        // Number of bytes remaining to write.
  23.335 +    int space;            // Amount of space left in plain buffer.
  23.336 +    LZOState *state = lzo_state(s);
  23.337 +#ifdef NOCOMPRESS
  23.338 +    //dprintf("> buf=%p size=%d count=%d\n", buf, size, count);
  23.339 +    err = IOStream_write(state->io, buf, size, count);
  23.340 +    //dprintf("< err=%d\n", err);
  23.341 +#else
  23.342 +    //dprintf("> buf=%p size=%d count=%d n=%d\n", buf, size, count, n);
  23.343 +    remaining = n;
  23.344 +    space = state->plain_size - state->plain_n;
  23.345 +    //dprintf("> plain=%p plain_ptr=%p plain_n=%d space=%d\n",
  23.346 +    //        state->plain, state->plain_ptr, state->plain_n, space);
  23.347 +    while(remaining){
  23.348 +        chunk = remaining;
  23.349 +        if(chunk > space) chunk = space;
  23.350 +        //dprintf("> memcpy %p %p %d\n", state->plain_ptr, buf, chunk);
  23.351 +        memcpy(state->plain_ptr, buf, chunk);
  23.352 +        remaining -= chunk;
  23.353 +        space -= chunk;
  23.354 +        state->plain_ptr += chunk;
  23.355 +        state->plain_n += chunk;
  23.356 +        if(space == 0){
  23.357 +            // Input buffer is full. Compress and write it.
  23.358 +            err = lzo_compress(state);
  23.359 +            if(err < 0) goto exit;
  23.360 +            space = state->plain_size - state->plain_n;
  23.361 +        }
  23.362 +    }
  23.363 +    err = (size > 1 ? n / size : n);
  23.364 +  exit:
  23.365 +    set_error(state, err);
  23.366 +#endif
  23.367 +    return err;
  23.368 +}
  23.369 +
  23.370 +
  23.371 +/** Read from the underlying stream.
  23.372 + *
  23.373 + * @param stream input
  23.374 + * @param buf where to put input
  23.375 + * @param size size of data elements
  23.376 + * @param count number of data elements to read
  23.377 + * @return number of data elements read
  23.378 + */
  23.379 +static int lzo_read(IOStream *s, void *buf, size_t size, size_t count){
  23.380 +    int err = 0;
  23.381 +    int k = 0;                     // Number of (plain) bytes read.
  23.382 +    int remaining = size * count;  // Number of bytes remaining to read.
  23.383 +    int chunk;                     // Size of chunk to read.
  23.384 +    LZOState *state = lzo_state(s);
  23.385 +#ifdef NOCOMPRESS
  23.386 +    //dprintf("> buf=%p size=%d count=%d\n", buf, size, count);
  23.387 +    err = IOStream_read(state->io, buf, size, count);
  23.388 +    //dprintf("< err=%d\n", err);
  23.389 +#else
  23.390 +    if(!(state->flags & LZO_READ)){
  23.391 +        err = -EINVAL;
  23.392 +        goto exit;
  23.393 +    }
  23.394 +    while(remaining){
  23.395 +        if(state->plain_n == 0){
  23.396 +            // No more plain input, decompress some more.
  23.397 +            err = lzo_decompress(state);
  23.398 +            if(err < 0) goto exit;
  23.399 +            // Stop reading if there is no more input.
  23.400 +            if(err == 0 || state->plain_n == 0) break;
  23.401 +        }
  23.402 +        chunk = remaining;
  23.403 +        if(chunk > state->plain_n) chunk = state->plain_n;
  23.404 +        memcpy(buf, state->plain_ptr, chunk);
  23.405 +        k += chunk;
  23.406 +        buf += chunk;
  23.407 +        state->plain_ptr += chunk;
  23.408 +        state->plain_n -= chunk;
  23.409 +        remaining -= chunk;
  23.410 +    }
  23.411 +    err = k;
  23.412 +  exit:
  23.413 +    set_error(state, err);
  23.414 +#endif
  23.415 +    return err;
  23.416 +}
  23.417 +
  23.418 +/** Print to the underlying stream.
  23.419 + * Returns 0 if the formatted output is too big for the internal buffer.
  23.420 + *
  23.421 + * @param s lzo stream
  23.422 + * @param msg format to use
  23.423 + * @param args arguments
  23.424 + * @return result of the print
  23.425 + */
  23.426 +static int lzo_print(IOStream *s, const char *msg, va_list args){
  23.427 +    char buf[1024];
  23.428 +    int buf_n = sizeof(buf);
  23.429 +    int n;
  23.430 +    LZOState *state = lzo_state(s);
  23.431 +    if(!LZOState_writeable(state)){
  23.432 +        n = -EINVAL;
  23.433 +        goto exit;
  23.434 +    }
  23.435 +    n = vsnprintf(buf, buf_n, (char*)msg, args);
  23.436 +    if(n < 0) goto exit;
  23.437 +    if(n > buf_n){
  23.438 +        n = 0;
  23.439 +    } else {
  23.440 +        n = lzo_write(s, buf, 1, n);
  23.441 +    }
  23.442 +  exit:
  23.443 +    return n;
  23.444 +}
  23.445 +
  23.446 +/** Read a character from the underlying stream
  23.447 + *
  23.448 + * @param s lzo stream
  23.449 + * @return character read, IOSTREAM_EOF on end of file (or error)
  23.450 + */
  23.451 +static int lzo_getc(IOStream *s){
  23.452 +    int err;
  23.453 +    char c;
  23.454 +    err = lzo_read(s, &c, 1, 1);
  23.455 +    if(err < 1) c = EOF;
  23.456 +    err = (c==EOF ? IOSTREAM_EOF : c);
  23.457 +    return err;
  23.458 +}
  23.459 +
  23.460 +/** Flush any pending input to the underlying stream.
  23.461 + *
  23.462 + * @param s lzo stream
  23.463 + * @return 0 on success, error code otherwise
  23.464 + */
  23.465 +static int lzo_flush(IOStream *s){
  23.466 +    int err = 0;
  23.467 +    LZOState *state = lzo_state(s);
  23.468 +    //dprintf(">\n");
  23.469 +#ifdef NOCOMPRESS
  23.470 +    err = IOStream_flush(state->io);
  23.471 +#else    
  23.472 +    if(!LZOState_writeable(state)){
  23.473 +        err = -EINVAL;
  23.474 +        goto exit;
  23.475 +    }
  23.476 +    if(state->plain_n){
  23.477 +        err = lzo_compress(state);
  23.478 +        if(err < 0) goto exit;
  23.479 +    }
  23.480 +    err = IOStream_flush(state->io);
  23.481 +  exit:
  23.482 +    set_error(state, err);
  23.483 +#endif
  23.484 +    //dprintf("< err=%d\n", err);
  23.485 +    return (err < 0 ? err : 0);
  23.486 +}
  23.487 +
  23.488 +/** Check if a stream has an error.
  23.489 + *
  23.490 + * @param s lzo stream
  23.491 + * @return code if has an error, 0 otherwise
  23.492 + */
  23.493 +static int lzo_error(IOStream *s){
  23.494 +    int err = 0;
  23.495 +    LZOState *state = lzo_state(s);
  23.496 +    err = state->error;
  23.497 +    if(err) goto exit;
  23.498 +    err = IOStream_error(state->io);
  23.499 +  exit:
  23.500 +    return err;
  23.501 +}
  23.502 +
  23.503 +int lzo_stream_finish(IOStream *s){
  23.504 +    int err = 0;
  23.505 +    LZOState *state = lzo_state(s);
  23.506 +    if(!LZOState_writeable(state)){
  23.507 +        err = -EINVAL;
  23.508 +        goto exit;
  23.509 +    }
  23.510 +    err = lzo_flush(s);
  23.511 +    if(err < 0) goto exit;
  23.512 +    err = marshal_int32(state->io, 0);
  23.513 +  exit:
  23.514 +    return err;
  23.515 +}        
  23.516 +
  23.517 +/** Close an lzo stream.
  23.518 + *
  23.519 + * @param s lzo stream to close
  23.520 + * @return result of the close
  23.521 + */
  23.522 +static int lzo_close(IOStream *s){
  23.523 +    int err = 0;
  23.524 +    LZOState *state = lzo_state(s);
  23.525 +#ifdef NOCOMPRESS
  23.526 +    err = IOStream_close(state->io);
  23.527 +#else    
  23.528 +    if(LZOState_writeable(state)){
  23.529 +        err = lzo_stream_finish(s);
  23.530 +    }        
  23.531 +    err = IOStream_close(state->io);
  23.532 +    set_error(state, err);
  23.533 +#endif
  23.534 +    return err;
  23.535 +}
  23.536 +
  23.537 +/** Free an lzo stream.
  23.538 + *
  23.539 + * @param s lzo stream
  23.540 + */
  23.541 +static void lzo_free(IOStream *s){
  23.542 +    LZOState *state = lzo_state(s);
  23.543 +    IOStream_free(state->io);
  23.544 +    LZOState_free(state);
  23.545 +    s->data = NULL;
  23.546 +}
  23.547 +
  23.548 +/** Create an lzo stream for an IOStream.
  23.549 + *
  23.550 + * @param io stream to wrap
  23.551 + * @return new IOStream using f for i/o
  23.552 + */
  23.553 +IOStream *lzo_stream_new(IOStream *io, const char *mode){
  23.554 +    int err = -ENOMEM;
  23.555 +    int flags = 0;
  23.556 +    IOStream *zio = NULL;
  23.557 +    LZOState *state = NULL;
  23.558 +
  23.559 +    zio = ALLOCATE(IOStream);
  23.560 +    if(!zio) goto exit;
  23.561 +    err = mode_flags(mode, &flags);
  23.562 +    if(err) goto exit;
  23.563 +    state = LZOState_new(io, flags);
  23.564 +    if(!state) goto exit;
  23.565 +    err = 0;
  23.566 +    zio->data = state;
  23.567 +    zio->methods = &lzo_methods;
  23.568 +  exit:
  23.569 +    if(err){
  23.570 +        if(state) LZOState_free(state);
  23.571 +        if(zio) deallocate(zio);
  23.572 +        zio = NULL;
  23.573 +    }
  23.574 +    return zio;
  23.575 +}
  23.576 +
  23.577 +/** IOStream version of fdopen().
  23.578 + *
  23.579 + * @param fd file descriptor
  23.580 + * @param flags giving the mode to open in (as for fdopen())
  23.581 + * @return new stream for the open file, or NULL if failed
  23.582 + */
  23.583 +IOStream *lzo_stream_fdopen(int fd, const char *mode){
  23.584 +    int err = -ENOMEM;
  23.585 +    IOStream *io = NULL, *zio = NULL;
  23.586 +    io = file_stream_fdopen(fd, mode);
  23.587 +    if(!io) goto exit;
  23.588 +    zio = lzo_stream_new(io, mode);
  23.589 +    if(!io) goto exit;
  23.590 +    err = 0;
  23.591 +  exit:
  23.592 +    if(err){
  23.593 +        IOStream_free(io);
  23.594 +        IOStream_free(zio);
  23.595 +        zio = NULL;
  23.596 +    }
  23.597 +    return zio;
  23.598 +}
  23.599 +#endif
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/tools/lib/lzo_stream.h	Tue Jun 29 12:05:29 2004 +0000
    24.3 @@ -0,0 +1,36 @@
    24.4 +#/* $Id: lzo_stream.h,v 1.3 2003/09/30 15:22:53 mjw Exp $ */
    24.5 +/*
    24.6 + * Copyright (C) 2003 Hewlett-Packard Company.
    24.7 + *
    24.8 + * This library is free software; you can redistribute it and/or modify
    24.9 + * it under the terms of the GNU Lesser General Public License as published by
   24.10 + * the Free Software Foundation; either version 2.1 of the License, or
   24.11 + * (at your option) any later version.
   24.12 + *
   24.13 + * This library is distributed in the hope that it will be useful,
   24.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   24.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24.16 + * GNU Lesser General Public License for more details.
   24.17 + *
   24.18 + * You should have received a copy of the GNU Lesser General Public License
   24.19 + * along with this library; if not, write to the Free Software
   24.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   24.21 + */
   24.22 +
   24.23 +#ifndef _SP_LZO_STREAM_H_
   24.24 +#define _SP_LZO_STREAM_H_
   24.25 +
   24.26 +#ifndef __KERNEL__
   24.27 +#include "iostream.h"
   24.28 +
   24.29 +extern IOStream *lzo_stream_new(IOStream *io, const char *mode);
   24.30 +extern IOStream *lzo_stream_fopen(const char *file, const char *mode);
   24.31 +extern IOStream *lzo_stream_fdopen(int fd, const char *mode);
   24.32 +extern IOStream *lzo_stream_io(IOStream *zio);
   24.33 +
   24.34 +extern int lzo_stream_plain_bytes(IOStream *io);
   24.35 +extern int lzo_stream_comp_bytes(IOStream *io);
   24.36 +extern float lzo_stream_ratio(IOStream *io);
   24.37 +
   24.38 +#endif
   24.39 +#endif /* !_SP_FILE_STREAM_H_ */
    25.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.2 +++ b/tools/lib/marshal.c	Tue Jun 29 12:05:29 2004 +0000
    25.3 @@ -0,0 +1,207 @@
    25.4 +#include <errno.h>
    25.5 +#include "sys_net.h"
    25.6 +#include "allocate.h"
    25.7 +#include "marshal.h"
    25.8 +
    25.9 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
   25.10 +#define wprintf(fmt, args...) IOStream_print(iostderr, "[WARN]  %s" fmt, __FUNCTION__, ##args)
   25.11 +#define iprintf(fmt, args...) IOStream_print(iostdout, "[INFO]  %s" fmt, __FUNCTION__, ##args)
   25.12 +#define eprintf(fmt, args...) IOStream_print(iostderr, "[ERROR] %s" fmt, __FUNCTION__, ##args)
   25.13 +
   25.14 +
   25.15 +#define ARRAY_SIZE(ary) (sizeof(ary)/sizeof((ary)[0]))
   25.16 +
   25.17 +/* Messages are coded as msgid followed by message fields.
   25.18 + * Initial message on any channel is hello - so can check version
   25.19 + * compatibility.
   25.20 + *
   25.21 + * char* -> uint16_t:n <n bytes>
   25.22 + * ints/uints go as suitable number of bytes (e.g. uint16_t is 2 bytes).
   25.23 + * optional fields go as '1' <val> or '0' (the 0/1 is 1 byte).
   25.24 + * lists go as ('1' <elt>)* '0'
   25.25 + */
   25.26 +
   25.27 +int marshal_flush(IOStream *io){
   25.28 +    int err  = 0;
   25.29 +    err = IOStream_flush(io);
   25.30 +    return err;
   25.31 +}
   25.32 +
   25.33 +int marshal_bytes(IOStream *io, void *s, uint32_t s_n){
   25.34 +    int err = 0;
   25.35 +    int n;
   25.36 +    n = IOStream_write(io, s, s_n);
   25.37 +    if(n < 0){
   25.38 +        err = n;
   25.39 +    } else if (n < s_n){
   25.40 +        wprintf("> Wanted %d, got %d\n", s_n, n);
   25.41 +        err = -EIO;
   25.42 +    }
   25.43 +    return err;
   25.44 +}
   25.45 +
   25.46 +int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n){
   25.47 +    int err = 0;
   25.48 +    int n;
   25.49 +    //dprintf("> s_n=%d\n", s_n);
   25.50 +    n = IOStream_read(io, s, s_n);
   25.51 +    //dprintf("> n=%d\n", n);
   25.52 +    if(n < 0){
   25.53 +        err = n;
   25.54 +    } else if(n < s_n){
   25.55 +        wprintf("> Wanted %d, got %d\n", s_n, n);
   25.56 +        err = -EIO;
   25.57 +    }
   25.58 +    //dprintf("< err=%d\n", err);
   25.59 +    return err;
   25.60 +}
   25.61 +
   25.62 +int marshal_uint8(IOStream *io, uint8_t x){
   25.63 +    return marshal_bytes(io, &x, sizeof(x));
   25.64 +}
   25.65 +
   25.66 +int unmarshal_uint8(IOStream *io, uint8_t *x){
   25.67 +    return unmarshal_bytes(io, x, sizeof(*x));
   25.68 +}
   25.69 +
   25.70 +int marshal_uint16(IOStream *io, uint16_t x){
   25.71 +    x = htons(x);
   25.72 +    return marshal_bytes(io, &x, sizeof(x));
   25.73 +}
   25.74 +
   25.75 +int unmarshal_uint16(IOStream *io, uint16_t *x){
   25.76 +    int err = 0;
   25.77 +    err = unmarshal_bytes(io, x, sizeof(*x));
   25.78 +    *x = ntohs(*x);
   25.79 +    return err;
   25.80 +}
   25.81 +
   25.82 +int marshal_int32(IOStream *io, int32_t x){
   25.83 +    int err = 0;
   25.84 +    //dprintf("> x=%d\n", x);
   25.85 +    x = htonl(x);
   25.86 +    err = marshal_bytes(io, &x, sizeof(x));
   25.87 +    //dprintf("< err=%d\n", err);
   25.88 +    return err;
   25.89 +}
   25.90 +
   25.91 +int unmarshal_int32(IOStream *io, int32_t *x){
   25.92 +    int err = 0;
   25.93 +    //dprintf(">\n");
   25.94 +    err = unmarshal_bytes(io, x, sizeof(*x));
   25.95 +    *x = ntohl(*x);
   25.96 +    //dprintf("< err=%d x=%d\n", err, *x);
   25.97 +    return err;
   25.98 +}
   25.99 +
  25.100 +int marshal_uint32(IOStream *io, uint32_t x){
  25.101 +    int err = 0;
  25.102 +    //dprintf("> x=%u\n", x);
  25.103 +    x = htonl(x);
  25.104 +    err = marshal_bytes(io, &x, sizeof(x));
  25.105 +    //dprintf("< err=%d\n", err);
  25.106 +    return err;
  25.107 +}
  25.108 +
  25.109 +int unmarshal_uint32(IOStream *io, uint32_t *x){
  25.110 +    int err = 0;
  25.111 +    //dprintf(">\n");
  25.112 +    err = unmarshal_bytes(io, x, sizeof(*x));
  25.113 +    *x = ntohl(*x);
  25.114 +    //dprintf("< err=%d x=%u\n", err, *x);
  25.115 +    return err;
  25.116 +}
  25.117 +
  25.118 +int marshal_uint64(IOStream *io, uint64_t x){
  25.119 +    int err;
  25.120 +    err = marshal_uint32(io, (uint32_t) ((x >> 32) & 0xffffffff));
  25.121 +    if(err) goto exit;
  25.122 +    err = marshal_uint32(io, (uint32_t) ( x        & 0xffffffff));
  25.123 +  exit:
  25.124 +    return err;
  25.125 +}
  25.126 +
  25.127 +int unmarshal_uint64(IOStream *io, uint64_t *x){
  25.128 +    int err = 0;
  25.129 +    uint32_t hi, lo;
  25.130 +    err = unmarshal_uint32(io, &hi);
  25.131 +    if(err) goto exit;
  25.132 +    err = unmarshal_uint32(io, &lo);
  25.133 +    *x = (((uint64_t) hi) << 32) | lo;
  25.134 +  exit:
  25.135 +    return err;
  25.136 +}
  25.137 +
  25.138 +int marshal_net16(IOStream *io, net16_t x){
  25.139 +    return marshal_bytes(io, &x, sizeof(x));
  25.140 +}
  25.141 +
  25.142 +int unmarshal_net16(IOStream *io, net16_t *x){
  25.143 +    int err = 0;
  25.144 +    err = unmarshal_bytes(io, x, sizeof(*x));
  25.145 +    return err;
  25.146 +}
  25.147 +
  25.148 +int marshal_net32(IOStream *io, net32_t x){
  25.149 +    return marshal_bytes(io, &x, sizeof(x));
  25.150 +}
  25.151 +
  25.152 +int unmarshal_net32(IOStream *io, net32_t *x){
  25.153 +    int err = 0;
  25.154 +    err = unmarshal_bytes(io, x, sizeof(*x));
  25.155 +    return err;
  25.156 +}
  25.157 +
  25.158 +int marshal_string(IOStream *io, char *s, uint32_t s_n){
  25.159 +    int err;
  25.160 +    //dprintf("> s=%s\n", s);
  25.161 +    err = marshal_uint32(io, s_n);
  25.162 +    if(err) goto exit;
  25.163 +    err = marshal_bytes(io, s, s_n);
  25.164 +  exit:
  25.165 +    //dprintf("< err=%d\n", err);
  25.166 +    return err;
  25.167 +}
  25.168 +
  25.169 +int unmarshal_string(IOStream *io, char *s, uint32_t s_n){
  25.170 +    int err = 0, val_n = 0;
  25.171 +    //dprintf(">\n");
  25.172 +    err = unmarshal_uint32(io, &val_n);
  25.173 +    if(err) goto exit;
  25.174 +    if(val_n >= s_n){
  25.175 +        err = -EINVAL;
  25.176 +        goto exit;
  25.177 +    }
  25.178 +    err = unmarshal_bytes(io, s, val_n);
  25.179 +    if(err) goto exit;
  25.180 +    s[val_n] = '\0';
  25.181 +  exit:
  25.182 +    //dprintf("< err=%d s=%s\n", err, s);
  25.183 +    return err;
  25.184 +}
  25.185 +
  25.186 +int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n){
  25.187 +    int err = 0, val_n = 0;
  25.188 +    char *val = NULL;
  25.189 +    //dprintf(">\n");
  25.190 +    err = unmarshal_uint32(io, &val_n);
  25.191 +    if(err) goto exit;
  25.192 +    val = allocate(val_n + 1);
  25.193 +    if(!val){
  25.194 +        err = -ENOMEM;
  25.195 +        goto exit;
  25.196 +    }
  25.197 +    err = unmarshal_bytes(io, val, val_n);
  25.198 +    if(err) goto exit;
  25.199 +    val[val_n] = '\0';
  25.200 +  exit:
  25.201 +    if(err){
  25.202 +        if(val) deallocate(val);
  25.203 +        val = NULL;
  25.204 +        val_n = 0;
  25.205 +    }
  25.206 +    *s = val;
  25.207 +    if(s_n) *s_n = val_n;
  25.208 +    //dprintf("< err=%d s=%s\n", err, *s);
  25.209 +    return err;
  25.210 +}
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/tools/lib/marshal.h	Tue Jun 29 12:05:29 2004 +0000
    26.3 @@ -0,0 +1,43 @@
    26.4 +/* $Id: marshal.h,v 1.1 2003/10/17 15:48:43 mjw Exp $ */
    26.5 +#ifndef _SP_MARSHAL_H_
    26.6 +#define _SP_MARSHAL_H_
    26.7 +
    26.8 +#include "iostream.h"
    26.9 +
   26.10 +/** A 16-bit uint in network order, e.g. a port number. */
   26.11 +typedef uint16_t net16_t;
   26.12 +
   26.13 +/** A 32-bit uint in network order, e.g. an IP address. */
   26.14 +typedef uint32_t net32_t;
   26.15 +
   26.16 +extern int marshal_flush(IOStream *io);
   26.17 +
   26.18 +extern int marshal_bytes(IOStream *io, void *s, uint32_t s_n);
   26.19 +extern int unmarshal_bytes(IOStream *io, void *s, uint32_t s_n);
   26.20 +
   26.21 +extern int marshal_uint8(IOStream *io, uint8_t x);
   26.22 +extern int unmarshal_uint8(IOStream *io, uint8_t *x);
   26.23 +
   26.24 +extern int marshal_uint16(IOStream *io, uint16_t x);
   26.25 +extern int unmarshal_uint16(IOStream *io, uint16_t *x);
   26.26 +
   26.27 +extern int marshal_uint32(IOStream *io, uint32_t x);
   26.28 +extern int unmarshal_uint32(IOStream *io, uint32_t *x);
   26.29 +
   26.30 +extern int marshal_int32(IOStream *io, int32_t x);
   26.31 +extern int unmarshal_int32(IOStream *io, int32_t *x);
   26.32 +
   26.33 +extern int marshal_uint64(IOStream *io, uint64_t x);
   26.34 +extern int unmarshal_uint64(IOStream *io, uint64_t *x);
   26.35 +
   26.36 +extern int marshal_net16(IOStream *io, net16_t x);
   26.37 +extern int unmarshal_net16(IOStream *io, net16_t *x);
   26.38 +
   26.39 +extern int marshal_net32(IOStream *io, net32_t x);
   26.40 +extern int unmarshal_net32(IOStream *io, net32_t *x);
   26.41 +
   26.42 +extern int marshal_string(IOStream *io, char *s, uint32_t s_n);
   26.43 +extern int unmarshal_string(IOStream *io, char *s, uint32_t s_n);
   26.44 +extern int unmarshal_new_string(IOStream *io, char **s, uint32_t *s_n);
   26.45 +
   26.46 +#endif /* ! _SP_MARSHAL_H_ */
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/tools/lib/socket_stream.c	Tue Jun 29 12:05:29 2004 +0000
    27.3 @@ -0,0 +1,259 @@
    27.4 +/* $Id: socket_stream.c,v 1.9 2004/03/05 14:45:34 mjw Exp $ */
    27.5 +/*
    27.6 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    27.7 + *
    27.8 + * This library is free software; you can redistribute it and/or modify
    27.9 + * it under the terms of the GNU Lesser General Public License as published by
   27.10 + * the Free Software Foundation; either version 2.1 of the License, or
   27.11 + * (at your option) any later version.
   27.12 + *
   27.13 + * This library is distributed in the hope that it will be useful,
   27.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.16 + * GNU Lesser General Public License for more details.
   27.17 + *
   27.18 + * You should have received a copy of the GNU Lesser General Public License
   27.19 + * along with this library; if not, write to the Free Software
   27.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27.21 + */
   27.22 +
   27.23 +/** @file
   27.24 + * An IOStream implementation using sockets.
   27.25 + */
   27.26 +
   27.27 +#include <stdio.h>
   27.28 +#include <stdlib.h>
   27.29 +#include <string.h>
   27.30 +#include <unistd.h>
   27.31 +#include <errno.h>
   27.32 +#include "allocate.h"
   27.33 +#include "socket_stream.h"
   27.34 +
   27.35 +#define MODULE_NAME "sock"
   27.36 +#define DEBUG 0
   27.37 +//#undef DEBUG
   27.38 +#include "debug.h"
   27.39 +
   27.40 +static int socket_read(IOStream *s, void *buf, size_t n);
   27.41 +static int socket_write(IOStream *s, const void *buf, size_t n);
   27.42 +static int socket_error(IOStream *s);
   27.43 +static int socket_close(IOStream *s);
   27.44 +static void socket_free(IOStream *s);
   27.45 +static int socket_flush(IOStream *s);
   27.46 +
   27.47 +/** Methods used by a socket IOStream. */
   27.48 +static const IOMethods socket_methods = {
   27.49 +    read:  socket_read,
   27.50 +    write: socket_write,
   27.51 +    error: socket_error,
   27.52 +    close: socket_close,
   27.53 +    free:  socket_free,
   27.54 +    flush: socket_flush,
   27.55 +};
   27.56 +
   27.57 +/** Get the socket data.
   27.58 + * 
   27.59 + * @param io socket stream
   27.60 + * @return data
   27.61 + */
   27.62 +static inline SocketData * socket_data(IOStream *io){
   27.63 +    return (SocketData *)io->data;
   27.64 +}
   27.65 +
   27.66 +/** Test if a stream is a socket stream.
   27.67 + *
   27.68 + * @param io stream
   27.69 + * @return 0 if a socket stream, -EINVAL if not
   27.70 + */
   27.71 +int socket_stream_check(IOStream *io){
   27.72 +    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
   27.73 +}
   27.74 +
   27.75 +/** Get the data for a socket stream.
   27.76 + *
   27.77 + * @param io stream
   27.78 + * @param data return value for the data
   27.79 + * @return 0 if a socket stream, -EINVAL if not
   27.80 + */
   27.81 +int socket_stream_data(IOStream *io, SocketData **data){
   27.82 +    int err = socket_stream_check(io);
   27.83 +    if(err){
   27.84 +        *data = NULL;
   27.85 +    } else {
   27.86 +        *data = socket_data(io);
   27.87 +    }
   27.88 +    return err;
   27.89 +}
   27.90 +
   27.91 +/** Set the destination address for a socket stream.
   27.92 + *
   27.93 + * @param io stream
   27.94 + * @param addr address
   27.95 + * @return 0 if a socket stream, -EINVAL if not
   27.96 + */
   27.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
   27.98 +    int err = 0;
   27.99 +    SocketData *data = NULL;
  27.100 +    err = socket_stream_data(io, &data);
  27.101 +    if(!err){
  27.102 +        data->daddr = *addr;
  27.103 +    }
  27.104 +    return err;
  27.105 +}
  27.106 +
  27.107 +/** Set the send flags for a socket stream.
  27.108 + *
  27.109 + * @param io stream
  27.110 + * @param flags flags
  27.111 + * @return 0 if a socket stream, -EINVAL if not
  27.112 + */
  27.113 +int socket_stream_set_flags(IOStream *io, int flags){
  27.114 +    int err = 0;
  27.115 +    SocketData *data = NULL;
  27.116 +    err = socket_stream_data(io, &data);
  27.117 +    if(!err){
  27.118 +        data->flags = flags;
  27.119 +    }
  27.120 +    return err;
  27.121 +}
  27.122 +
  27.123 +/** Write to the underlying socket using sendto.
  27.124 + *
  27.125 + * @param stream input
  27.126 + * @param buf where to put input
  27.127 + * @param n number of bytes to write
  27.128 + * @return number of bytes written
  27.129 + */
  27.130 +static int socket_write(IOStream *s, const void *buf, size_t n){
  27.131 +    SocketData *data = socket_data(s);
  27.132 +    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
  27.133 +    socklen_t daddr_n = sizeof(data->daddr);
  27.134 +    int k;
  27.135 +    dprintf("> sock=%d addr=%s:%d n=%d\n",
  27.136 +            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
  27.137 +    if(0){
  27.138 +        struct sockaddr_in self = {};
  27.139 +        socklen_t self_n;
  27.140 +        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
  27.141 +        dprintf("> sockname sock=%d %s:%d\n",
  27.142 +                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
  27.143 +    }
  27.144 +    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
  27.145 +    dprintf("> sendto=%d\n", k);
  27.146 +    return k;
  27.147 +}
  27.148 +
  27.149 +/** Read from the underlying stream using recv();
  27.150 + *
  27.151 + * @param stream input
  27.152 + * @param buf where to put input
  27.153 + * @param n number of bytes to read
  27.154 + * @return number of bytes read
  27.155 + */
  27.156 +static int socket_read(IOStream *s, void *buf, size_t n){
  27.157 +    SocketData *data = socket_data(s);
  27.158 +    int k;
  27.159 +    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
  27.160 +    socklen_t saddr_n = sizeof(data->saddr);
  27.161 +    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
  27.162 +    return k;
  27.163 +}
  27.164 +
  27.165 +/** Print to the underlying socket.
  27.166 + *
  27.167 + * @param s socket stream
  27.168 + * @param msg format to use
  27.169 + * @param args arguments
  27.170 + * @return result of the print
  27.171 + */
  27.172 +static int socket_print(IOStream *s, const char *msg, va_list args){
  27.173 +    SocketData *data = socket_data(s);
  27.174 +    int n;
  27.175 +    n = vsnprintf(data->buf, data->buf_n - 1, msg, args);
  27.176 +    if(0 < n && n < data->buf_n){
  27.177 +        socket_write(s, data->buf, n);
  27.178 +    }
  27.179 +    return n;
  27.180 +}
  27.181 +
  27.182 +/** Read a character from the underlying socket
  27.183 + *
  27.184 + * @param s socket stream
  27.185 + * @return character read, IOSTREAM_EOF on end of socket (or error)
  27.186 + */
  27.187 +static int socket_getc(IOStream *s){
  27.188 +    char b;
  27.189 +    int n, c;
  27.190 +    n = socket_read(s, &b, 1);
  27.191 +    c = (n <= 0 ? IOSTREAM_EOF : b);
  27.192 +    return c;
  27.193 +}
  27.194 +
  27.195 +/** Flush the socket (no-op).
  27.196 + *
  27.197 + * @param s socket stream
  27.198 + * @return 0 on success, error code otherwise
  27.199 + */
  27.200 +static int socket_flush(IOStream *s){
  27.201 +    return 0;
  27.202 +}
  27.203 +
  27.204 +/** Check if a socket stream has an error (no-op).
  27.205 + *
  27.206 + * @param s socket stream
  27.207 + * @return 1 if has an error, 0 otherwise
  27.208 + */
  27.209 +static int socket_error(IOStream *s){
  27.210 +    // Read SOL_SOCKET/SO_ERROR ?
  27.211 +    return 0;
  27.212 +}
  27.213 +
  27.214 +/** Close a socket stream.
  27.215 + *
  27.216 + * @param s socket stream to close
  27.217 + * @return result of the close
  27.218 + */
  27.219 +static int socket_close(IOStream *s){
  27.220 +    SocketData *data = socket_data(s);
  27.221 +    return close(data->fd);
  27.222 +}
  27.223 +
  27.224 +/** Free a socket stream.
  27.225 + *
  27.226 + * @param s socket stream
  27.227 + */
  27.228 +static void socket_free(IOStream *s){
  27.229 +    SocketData *data = socket_data(s);
  27.230 +    deallocate(data);
  27.231 +}
  27.232 +
  27.233 +/** Create an IOStream for a socket.
  27.234 + *
  27.235 + * @param fd socket to wtap
  27.236 + * @return new IOStream using fd for i/o
  27.237 + */
  27.238 +IOStream *socket_stream_new(int fd){
  27.239 +    int err = -ENOMEM;
  27.240 +    IOStream *io = NULL;
  27.241 +    SocketData *data = NULL;
  27.242 +
  27.243 +    io = ALLOCATE(IOStream);
  27.244 +    if(!io) goto exit;
  27.245 +    io->methods = &socket_methods;
  27.246 +    data = ALLOCATE(SocketData);
  27.247 +    if(!data) goto exit;
  27.248 +    io->data = data;
  27.249 +    data->fd = fd;
  27.250 +    data->buf_n = sizeof(data->buf);
  27.251 +    err = 0;
  27.252 +  exit:
  27.253 +    if(err){
  27.254 +        if(io){
  27.255 +            if(data) deallocate(data);
  27.256 +            deallocate(io);
  27.257 +            io = NULL;
  27.258 +        }
  27.259 +    }
  27.260 +    return io;
  27.261 +}
  27.262 +
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/tools/lib/socket_stream.h	Tue Jun 29 12:05:29 2004 +0000
    28.3 @@ -0,0 +1,54 @@
    28.4 +/* $Id: socket_stream.h,v 1.2 2004/03/04 17:38:13 mjw Exp $ */
    28.5 +/*
    28.6 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    28.7 + *
    28.8 + * This library is free software; you can redistribute it and/or modify
    28.9 + * it under the terms of the GNU Lesser General Public License as published by
   28.10 + * the Free Software Foundation; either version 2.1 of the License, or
   28.11 + * (at your option) any later version.
   28.12 + *
   28.13 + * This library is distributed in the hope that it will be useful,
   28.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.16 + * GNU Lesser General Public License for more details.
   28.17 + *
   28.18 + * You should have received a copy of the GNU Lesser General Public License
   28.19 + * along with this library; if not, write to the Free Software
   28.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.21 + */
   28.22 +
   28.23 +#ifndef _XEN_LIB_SOCKET_STREAM_H_
   28.24 +#define _XEN_LIB_SOCKET_STREAM_H_
   28.25 +
   28.26 +#ifndef __KERNEL__
   28.27 +#include "iostream.h"
   28.28 +#include <stdio.h>
   28.29 +
   28.30 +#include <sys/socket.h>
   28.31 +#include <netinet/in.h>
   28.32 +#include <arpa/inet.h>
   28.33 +
   28.34 +/** Data associated with a socket stream. */
   28.35 +typedef struct SocketData {
   28.36 +    /** The socket file descriptor. */
   28.37 +    int fd;
   28.38 +    /** Source address from last read (recvfrom). */
   28.39 +    struct sockaddr_in saddr;
   28.40 +    /** Destination address for writes (sendto). */
   28.41 +    struct sockaddr_in daddr;
   28.42 +    /** Write flags (sendto). */
   28.43 +    int flags;
   28.44 +    /** Buffer size. */
   28.45 +    int buf_n;
   28.46 +    /** Buffer for formatted printing. */
   28.47 +    char buf[1024];
   28.48 +} SocketData;
   28.49 +
   28.50 +extern IOStream *socket_stream_new(int fd);
   28.51 +extern int socket_stream_data(IOStream *io, SocketData **data);
   28.52 +extern int socket_stream_check(IOStream *io);
   28.53 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr);
   28.54 +extern int socket_stream_set_flags(IOStream *io, int flags);
   28.55 +
   28.56 +#endif
   28.57 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
    29.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.2 +++ b/tools/lib/string_stream.c	Tue Jun 29 12:05:29 2004 +0000
    29.3 @@ -0,0 +1,174 @@
    29.4 +/*
    29.5 + * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    29.6 + *
    29.7 + * This library is free software; you can redistribute it and/or modify
    29.8 + * it under the terms of the GNU Lesser General Public License as published by
    29.9 + * the Free Software Foundation; either version 2.1 of the License, or
   29.10 + * (at your option) any later version.
   29.11 + *
   29.12 + * This library is distributed in the hope that it will be useful,
   29.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   29.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   29.15 + * GNU Lesser General Public License for more details.
   29.16 + *
   29.17 + * You should have received a copy of the GNU Lesser General Public License
   29.18 + * along with this library; if not, write to the Free Software
   29.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   29.20 + */
   29.21 +
   29.22 +/** @file
   29.23 + * IOStream subtype for input and output to strings.
   29.24 + * Usable from user or kernel code (with __KERNEL__ defined).
   29.25 + */
   29.26 +
   29.27 +#include "sys_string.h"
   29.28 +#include "string_stream.h"
   29.29 +#include "allocate.h"
   29.30 +
   29.31 +static int string_print(IOStream *io, const char *msg, va_list args);
   29.32 +static int string_getc(IOStream *io);
   29.33 +static int string_error(IOStream *io);
   29.34 +static int string_close(IOStream *io);
   29.35 +static void string_free(IOStream *io);
   29.36 +
   29.37 +/** Methods for a string stream. */
   29.38 +static IOMethods string_methods = {
   29.39 +    //print: string_print,
   29.40 +    //getc:  string_getc,
   29.41 +    error: string_error,
   29.42 +    close: string_close,
   29.43 +    free:  string_free,
   29.44 +};
   29.45 +
   29.46 +/** Get the string stream state.
   29.47 + *
   29.48 + * @param io string stream
   29.49 + * @return state
   29.50 + */
   29.51 +static inline StringData *get_string_data(IOStream *io){
   29.52 +    return (StringData*)io->data;
   29.53 +}
   29.54 +
   29.55 +/** Read a character from a string stream.
   29.56 + *
   29.57 + * @param io string stream
   29.58 + * @return character read, IOSTREAM_EOF if no more input
   29.59 + */
   29.60 +static int string_getc(IOStream *io){
   29.61 +    StringData *data = get_string_data(io);
   29.62 +    int c = IOSTREAM_EOF;
   29.63 +    char *s = data->in;
   29.64 +
   29.65 +    if(s && s < data->end){
   29.66 +        c = (unsigned)*s;
   29.67 +        data->in = s+1;
   29.68 +    }
   29.69 +    return c;
   29.70 +}
   29.71 +
   29.72 +/** Print to a string stream.
   29.73 + * Formats the data to an internal buffer and prints it.
   29.74 + * The formatted data must fit into the internal buffer.
   29.75 + *
   29.76 + * @param io string stream
   29.77 + * @param format print format
   29.78 + * @param args print arguments
   29.79 + * @return result of the print
   29.80 + */
   29.81 +static int string_print(IOStream *io, const char *msg, va_list args){
   29.82 +    StringData *data = get_string_data(io);
   29.83 +    int k = data->end - data->out;
   29.84 +    int n = vsnprintf(data->out, k, (char*)msg, args);
   29.85 +    if(n < 0 || n > k ){
   29.86 +        n = k;
   29.87 +        IOStream_close(io);
   29.88 +    } else {
   29.89 +        data->out += n;
   29.90 +    }
   29.91 +    return n;
   29.92 +}
   29.93 +
   29.94 +/** Test if a string stream has an error.
   29.95 + *
   29.96 + * @param io string stream
   29.97 + * @return 0 if ok, error code otherwise
   29.98 + */
   29.99 +static int string_error(IOStream *io){
  29.100 +    StringData *data = get_string_data(io);
  29.101 +    return data->out == NULL;
  29.102 +}
  29.103 +
  29.104 +/** Close a string stream.
  29.105 + *
  29.106 + * @param io string stream
  29.107 + * @return 0
  29.108 + */
  29.109 +static int string_close(IOStream *io){
  29.110 +    StringData *data = get_string_data(io);
  29.111 +    data->in = NULL;
  29.112 +    data->out = NULL;
  29.113 +    return 0;
  29.114 +}
  29.115 +
  29.116 +/** Free a string stream.
  29.117 + * The stream must have been allocated, not statically created.
  29.118 + * The stream state is freed, but the underlying string is not.
  29.119 + *
  29.120 + * @param io string stream
  29.121 + */
  29.122 +static void string_free(IOStream *io){
  29.123 +    StringData *data = get_string_data(io);
  29.124 +    zero(data, sizeof(*data));
  29.125 +    deallocate(data);
  29.126 +}
  29.127 +
  29.128 +/** Get the methods to use for a string stream.
  29.129 + *
  29.130 + * @return methods
  29.131 + */
  29.132 +IOMethods *string_stream_get_methods(void){
  29.133 +    return &string_methods;
  29.134 +}
  29.135 +
  29.136 +/** Initialise a string stream, usually from static data.
  29.137 + *
  29.138 + * @param io address of IOStream to fill in
  29.139 + * @param data address of StringData to fill in
  29.140 + * @param s string to use
  29.141 + * @param n length of the string
  29.142 + */
  29.143 +void string_stream_init(IOStream *io, StringData *data, char *s, int n){
  29.144 +    if(data && io){
  29.145 +        zero(data, sizeof(*data));
  29.146 +        data->string = (char*)s;
  29.147 +        data->in = data->string;
  29.148 +        data->out = data->string;
  29.149 +        data->size = n;
  29.150 +        data->end = data->string + n;
  29.151 +        zero(io, sizeof(*io));
  29.152 +        io->methods = &string_methods;
  29.153 +        io->data = data;
  29.154 +    }
  29.155 +}
  29.156 +
  29.157 +/** Allocate and initialise a string stream.
  29.158 + *
  29.159 + * @param s string to use
  29.160 + * @param n length of the string
  29.161 + * @return new stream (free using IOStream_free)
  29.162 + */
  29.163 +IOStream *string_stream_new(char *s, int n){
  29.164 +    int ok = 0;
  29.165 +    StringData *data = ALLOCATE(StringData);
  29.166 +    IOStream *io = ALLOCATE(IOStream);
  29.167 +    if(data && io){
  29.168 +        ok = 1;
  29.169 +        string_stream_init(io, data, s, n);
  29.170 +    }
  29.171 +    if(!ok){
  29.172 +        deallocate(data);
  29.173 +        deallocate(io);
  29.174 +        io = NULL;
  29.175 +    }
  29.176 +    return io;
  29.177 +}
    30.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.2 +++ b/tools/lib/string_stream.h	Tue Jun 29 12:05:29 2004 +0000
    30.3 @@ -0,0 +1,46 @@
    30.4 +/* $Id: string_stream.h,v 1.1 2003/08/22 14:25:48 mjw Exp $ */
    30.5 +/*
    30.6 + * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    30.7 + *
    30.8 + * This library is free software; you can redistribute it and/or modify
    30.9 + * it under the terms of the GNU Lesser General Public License as published by
   30.10 + * the Free Software Foundation; either version 2.1 of the License, or
   30.11 + * (at your option) any later version.
   30.12 + *
   30.13 + * This library is distributed in the hope that it will be useful,
   30.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   30.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   30.16 + * GNU Lesser General Public License for more details.
   30.17 + *
   30.18 + * You should have received a copy of the GNU Lesser General Public License
   30.19 + * along with this library; if not, write to the Free Software
   30.20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   30.21 + */
   30.22 +
   30.23 +#ifndef _SP_STRING_STREAM_H_
   30.24 +#define _SP_STRING_STREAM_H_
   30.25 +
   30.26 +#include "iostream.h"
   30.27 +
   30.28 +/** Internal state for a string stream.
   30.29 + * Exposed here so that string streams can be statically created, using
   30.30 + * string_stream_init().
   30.31 + */
   30.32 +typedef struct {
   30.33 +    /** The string used for input and ouput. */
   30.34 +    char *string;
   30.35 +    /** Output pointer. */
   30.36 +    char *out;
   30.37 +    /** Input pointer. */
   30.38 +    char *in;
   30.39 +    /** Length of string. */
   30.40 +    int size;
   30.41 +    /** End marker. */
   30.42 +    char *end;
   30.43 +} StringData;
   30.44 +
   30.45 +extern IOMethods *string_stream_get_methods(void);
   30.46 +extern IOStream *string_stream_new(char *s, int n);
   30.47 +extern void string_stream_init(IOStream *stream, StringData *data, char *s, int n);
   30.48 +
   30.49 +#endif /* !_SP_STRING_STREAM_H_ */
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/tools/lib/sxpr.c	Tue Jun 29 12:05:29 2004 +0000
    31.3 @@ -0,0 +1,935 @@
    31.4 +/*
    31.5 + *
    31.6 + * This library is free software; you can redistribute it and/or modify
    31.7 + * it under the terms of the GNU Lesser General Public License as
    31.8 + * published by the Free Software Foundation; either version 2.1 of the
    31.9 + * License, or  (at your option) any later version. This library is 
   31.10 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   31.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   31.12 + * FITNESS FOR A PARTICULAR PURPOSE.
   31.13 + * See the GNU Lesser General Public License for more details.
   31.14 + *
   31.15 + * You should have received a copy of the GNU Lesser General Public License
   31.16 + * along with this library; if not, write to the Free Software Foundation,
   31.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   31.18 + */
   31.19 +
   31.20 +#include <stdarg.h>
   31.21 +#include "sys_string.h"
   31.22 +#include "lexis.h"
   31.23 +#include "sys_net.h"
   31.24 +#include "hash_table.h"
   31.25 +#include "sxpr.h"
   31.26 +
   31.27 +#include <errno.h>
   31.28 +#undef free
   31.29 +
   31.30 +/** @file
   31.31 + * General representation of sxprs.
   31.32 + * Includes print, equal, and free functions for the sxpr types.
   31.33 + *
   31.34 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional.
   31.35 + * When a function returning an sxpr cannot allocate memory we return ONOMEM.
   31.36 + *
   31.37 + */
   31.38 +
   31.39 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
   31.40 +static int atom_equal(Sxpr x, Sxpr y);
   31.41 +static void atom_free(Sxpr obj);
   31.42 +
   31.43 +static int string_print(IOStream *io, Sxpr obj, unsigned flags);
   31.44 +static int string_equal(Sxpr x, Sxpr y);
   31.45 +static void string_free(Sxpr obj);
   31.46 +
   31.47 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
   31.48 +static int cons_equal(Sxpr x, Sxpr y);
   31.49 +static void cons_free(Sxpr obj);
   31.50 +
   31.51 +static int null_print(IOStream *io, Sxpr obj, unsigned flags);
   31.52 +static int none_print(IOStream *io, Sxpr obj, unsigned flags);
   31.53 +static int int_print(IOStream *io, Sxpr obj, unsigned flags);
   31.54 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
   31.55 +
   31.56 +/** Type definitions. */
   31.57 +static SxprType types[1024] = {
   31.58 +    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
   31.59 +    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
   31.60 +    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
   31.61 +    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
   31.62 +    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
   31.63 +		   pointer: TRUE,
   31.64 +		   free:    atom_free,
   31.65 +		   equal:   atom_equal,
   31.66 +		 },
   31.67 +    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
   31.68 +		   pointer: TRUE,
   31.69 +		   free:    string_free,
   31.70 +		   equal:   string_equal,
   31.71 +		 },
   31.72 +    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
   31.73 +		   pointer: TRUE,
   31.74 +		   free:    cons_free,
   31.75 +		   equal:   cons_equal,
   31.76 +		 },
   31.77 +};
   31.78 +
   31.79 +/** Number of entries in the types array. */
   31.80 +static int type_sup = sizeof(types)/sizeof(types[0]);
   31.81 +
   31.82 +/** Get the type definition for a given type code.
   31.83 + *
   31.84 + * @param ty type code
   31.85 + * @return type definition or null
   31.86 + */
   31.87 +SxprType *get_sxpr_type(int ty){
   31.88 +    if(0 <= ty && ty < type_sup){
   31.89 +        return types+ty;
   31.90 +    }
   31.91 +    return NULL;
   31.92 +}
   31.93 +
   31.94 +/** The default print function.
   31.95 + *
   31.96 + * @param io stream to print to
   31.97 + * @param x sxpr to print
   31.98 + * @param flags print flags
   31.99 + * @return number of bytes written on success
  31.100 + */
  31.101 +int default_print(IOStream *io, Sxpr x, unsigned flags){
  31.102 +    return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x));
  31.103 +}
  31.104 +
  31.105 +/** The default equal function.
  31.106 + * Uses eq().
  31.107 + *
  31.108 + * @param x sxpr to compare
  31.109 + * @param y sxpr to compare
  31.110 + * @return 1 if equal, 0 otherwise
  31.111 + */
  31.112 +int default_equal(Sxpr x, Sxpr y){
  31.113 +    return eq(x, y);
  31.114 +}
  31.115 +
  31.116 +/** General sxpr print function.
  31.117 + * Prints an sxpr on a stream using the print function for the sxpr type.
  31.118 + * Printing is controlled by flags from the PrintFlags enum.
  31.119 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr
  31.120 + * (for debugging).
  31.121 + *
  31.122 + * @param io stream to print to
  31.123 + * @param x sxpr to print
  31.124 + * @param flags print flags
  31.125 + * @return number of bytes written
  31.126 + */
  31.127 +int objprint(IOStream *io, Sxpr x, unsigned flags){
  31.128 +    SxprType *def = get_sxpr_type(get_type(x));
  31.129 +    ObjPrintFn *print_fn = (def && def->print ? def->print : default_print);
  31.130 +    int k = 0;
  31.131 +    if(!io) return k;
  31.132 +    if(flags & PRINT_TYPE){
  31.133 +	k += IOStream_print(io, "%s:", def->name);
  31.134 +    }
  31.135 +    k += print_fn(io, x, flags);
  31.136 +    return k;
  31.137 +}
  31.138 +
  31.139 +/** General sxpr free function.
  31.140 + * Frees an sxpr using the free function for its type.
  31.141 + * Free functions must recursively free any subsxprs.
  31.142 + * If no function is defined then the default is to
  31.143 + * free sxprs whose type has pointer true.
  31.144 + * Sxprs must not be used after freeing.
  31.145 + *
  31.146 + * @param x sxpr to free
  31.147 + */
  31.148 +void objfree(Sxpr x){
  31.149 +    SxprType *def = get_sxpr_type(get_type(x));
  31.150 +
  31.151 +    if(def){
  31.152 +	if(def->free){
  31.153 +	    def->free(x);
  31.154 +	} else if (def->pointer){
  31.155 +	    hfree(x);
  31.156 +	}
  31.157 +    }
  31.158 +}
  31.159 +
  31.160 +/** General sxpr equality function.
  31.161 + * Compares x and y using the equal function for x.
  31.162 + * Uses default_equal() if x has no equal function.
  31.163 + *
  31.164 + * @param x sxpr to compare
  31.165 + * @param y sxpr to compare
  31.166 + * @return 1 if equal, 0 otherwise
  31.167 + */
  31.168 +int objequal(Sxpr x, Sxpr y){
  31.169 +    SxprType *def = get_sxpr_type(get_type(x));
  31.170 +    ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal);
  31.171 +    return equal_fn(x, y);
  31.172 +}
  31.173 +
  31.174 +/** Search for a key in an alist.
  31.175 + * An alist is a list of conses, where the cars
  31.176 + * of the conses are the keys. Compares keys using equality.
  31.177 + *
  31.178 + * @param k key
  31.179 + * @param l alist to search
  31.180 + * @return first element of l with car k, or ONULL
  31.181 + */
  31.182 +Sxpr assoc(Sxpr k, Sxpr l){
  31.183 +    for( ; CONSP(l) ; l = CDR(l)){
  31.184 +        Sxpr x = CAR(l);
  31.185 +        if(CONSP(x) && objequal(k, CAR(x))){
  31.186 +            return x;   
  31.187 +        }
  31.188 +    }
  31.189 +    return ONULL;
  31.190 +}
  31.191 +
  31.192 +/** Search for a key in an alist.
  31.193 + * An alist is a list of conses, where the cars
  31.194 + * of the conses are the keys. Compares keys using eq.
  31.195 + *
  31.196 + * @param k key
  31.197 + * @param l alist to search
  31.198 + * @return first element of l with car k, or ONULL
  31.199 + */
  31.200 +Sxpr assocq(Sxpr k, Sxpr l){
  31.201 +    for( ; CONSP(l); l = CDR(l)){
  31.202 +        Sxpr x = CAR(l);
  31.203 +        if(CONSP(x) && eq(k, CAR(x))){
  31.204 +            return x;
  31.205 +        }
  31.206 +    }
  31.207 +    return ONULL;
  31.208 +}
  31.209 +
  31.210 +/** Add a new key and value to an alist.
  31.211 + *
  31.212 + * @param k key
  31.213 + * @param l value
  31.214 + * @param l alist
  31.215 + * @return l with the new cell added to the front
  31.216 + */
  31.217 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){
  31.218 +    Sxpr x, y;
  31.219 +    x = cons_new(k, v);
  31.220 +    if(NOMEMP(x)) return x;
  31.221 +    y = cons_new(x, l);
  31.222 +    if(NOMEMP(y)) cons_free_cells(x);
  31.223 +    return y;
  31.224 +}
  31.225 +
  31.226 +/** Test if a list contains an element.
  31.227 + * Uses sxpr equality.
  31.228 + *
  31.229 + * @param l list
  31.230 + * @param x element to look for
  31.231 + * @return a tail of l with x as car, or ONULL
  31.232 + */
  31.233 +Sxpr cons_member(Sxpr l, Sxpr x){
  31.234 +    for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){}
  31.235 +    return l;
  31.236 +}
  31.237 +
  31.238 +/** Test if a list contains an element satisfying a test.
  31.239 + * The test function is called with v and an element of the list.
  31.240 + *
  31.241 + * @param l list
  31.242 + * @param test_fn test function to use
  31.243 + * @param v value for first argument to the test
  31.244 + * @return a tail of l with car satisfying the test, or 0
  31.245 + */
  31.246 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  31.247 +    for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ }
  31.248 +    return l;
  31.249 +}
  31.250 +
  31.251 +/** Test if the elements of list 't' are a subset of the elements
  31.252 + * of list 's'. Element order is not significant.
  31.253 + *
  31.254 + * @param s element list to check subset of
  31.255 + * @param t element list to check if is a subset
  31.256 + * @return 1 if is a subset, 0 otherwise
  31.257 + */
  31.258 +int cons_subset(Sxpr s, Sxpr t){
  31.259 +    for( ; CONSP(t); t = CDR(t)){
  31.260 +	if(!CONSP(cons_member(s, CAR(t)))){
  31.261 +	    return 0;
  31.262 +	}
  31.263 +    }
  31.264 +    return 1;
  31.265 +}
  31.266 +
  31.267 +/** Test if two lists have equal sets of elements.
  31.268 + * Element order is not significant.
  31.269 + *
  31.270 + * @param s list to check
  31.271 + * @param t list to check
  31.272 + * @return 1 if equal, 0 otherwise
  31.273 + */
  31.274 +int cons_set_equal(Sxpr s, Sxpr t){
  31.275 +    return cons_subset(s, t) && cons_subset(t, s);
  31.276 +}
  31.277 +
  31.278 +#ifdef USE_GC
  31.279 +/*============================================================================*/
  31.280 +/* The functions inside this ifdef are only safe if GC is used.
  31.281 + * Otherwise they may leak memory.
  31.282 + */
  31.283 +
  31.284 +/** Remove an element from a list (GC only).
  31.285 + * Uses sxpr equality and removes all instances, even
  31.286 + * if there are more than one.
  31.287 + *
  31.288 + * @param l list to remove elements from
  31.289 + * @param x element to remove
  31.290 + * @return modified input list
  31.291 + */
  31.292 +Sxpr cons_remove(Sxpr l, Sxpr x){
  31.293 +    return cons_remove_if(l, eq, x);
  31.294 +}
  31.295 +
  31.296 +/** Remove elements satisfying a test (GC only).
  31.297 + * The test function is called with v and an element of the set.
  31.298 + *
  31.299 + * @param l list to remove elements from
  31.300 + * @param test_fn function to use to decide if an element should be removed
  31.301 + * @return modified input list
  31.302 + */
  31.303 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  31.304 +    Sxpr prev = ONULL, elt, next;
  31.305 +
  31.306 +    for(elt = l; CONSP(elt); elt = next){
  31.307 +        next = CDR(elt);
  31.308 +        if(test_fn(v, CAR(elt))){
  31.309 +            if(NULLP(prev)){
  31.310 +                l = next;
  31.311 +            } else {
  31.312 +                CDR(prev) = next;
  31.313 +            }
  31.314 +        }
  31.315 +    }
  31.316 +    return l;
  31.317 +}
  31.318 +
  31.319 +/** Set the value for a key in an alist (GC only).
  31.320 + * If the key is present, changes the value, otherwise
  31.321 + * adds a new cell.
  31.322 + *
  31.323 + * @param k key
  31.324 + * @param v value
  31.325 + * @param l alist
  31.326 + * @return modified or extended list
  31.327 + */
  31.328 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
  31.329 +    Sxpr e = assoc(k, l);
  31.330 +    if(NULLP(e)){
  31.331 +        l = acons(k, v, l);
  31.332 +    } else {
  31.333 +        CAR(CDR(e)) = v;
  31.334 +    }
  31.335 +    return l;
  31.336 +}
  31.337 +/*============================================================================*/
  31.338 +#endif /* USE_GC */
  31.339 +
  31.340 +/** Create a new atom with the given name.
  31.341 + *
  31.342 + * @param name the name
  31.343 + * @return new atom
  31.344 + */
  31.345 +Sxpr atom_new(char *name){
  31.346 +    Sxpr n, obj = ONOMEM;
  31.347 +
  31.348 +    n = string_new(name);
  31.349 +    if(NOMEMP(n)) goto exit;
  31.350 +    obj = HALLOC(ObjAtom, T_ATOM);
  31.351 +    if(NOMEMP(obj)) goto exit;
  31.352 +    OBJ_ATOM(obj)->name = n;
  31.353 +  exit:
  31.354 +    return obj;
  31.355 +}
  31.356 +
  31.357 +/** Free an atom.
  31.358 + *
  31.359 + * @param obj to free
  31.360 + */
  31.361 +void atom_free(Sxpr obj){
  31.362 +    // Interned atoms are shared, so do not free.
  31.363 +    if(OBJ_ATOM(obj)->interned) return;
  31.364 +    objfree(OBJ_ATOM(obj)->name);
  31.365 +    hfree(obj);
  31.366 +}
  31.367 +
  31.368 +/** Print an atom. Prints the atom name.
  31.369 + *
  31.370 + * @param io stream to print to
  31.371 + * @param obj to print
  31.372 + * @param flags print flags
  31.373 + * @return number of bytes printed
  31.374 + */
  31.375 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){
  31.376 +    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
  31.377 +    return string_print(io, OBJ_ATOM(obj)->name, flags);
  31.378 +}
  31.379 +
  31.380 +/** Atom equality.
  31.381 + *
  31.382 + * @param x to compare
  31.383 + * @param y to compare
  31.384 + * @return 1 if equal, 0 otherwise
  31.385 + */
  31.386 +int atom_equal(Sxpr x, Sxpr y){
  31.387 +    int ok;
  31.388 +    ok = eq(x, y);
  31.389 +    if(ok) goto exit;
  31.390 +    ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name);
  31.391 +    if(ok) goto exit;
  31.392 +    ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y);
  31.393 +  exit:
  31.394 +    return ok;
  31.395 +}
  31.396 +
  31.397 +/** Get the name of an atom.
  31.398 + *
  31.399 + * @param obj atom
  31.400 + * @return name
  31.401 + */
  31.402 +char * atom_name(Sxpr obj){
  31.403 +    return string_string(OBJ_ATOM(obj)->name);
  31.404 +}
  31.405 +
  31.406 +/** Get the C string from a string sxpr.
  31.407 + *
  31.408 + * @param obj string sxpr
  31.409 + * @return string
  31.410 + */
  31.411 +char * string_string(Sxpr obj){
  31.412 +    return OBJ_STRING(obj);
  31.413 +}
  31.414 +
  31.415 +/** Get the length of a string.
  31.416 + *
  31.417 + * @param obj string
  31.418 + * @return length
  31.419 + */
  31.420 +int string_length(Sxpr obj){
  31.421 +    return strlen(OBJ_STRING(obj));
  31.422 +}
  31.423 +
  31.424 +/** Create a new string. The input string is copied,
  31.425 + * and must be null-terminated.
  31.426 + *
  31.427 + * @param s characters to put in the string
  31.428 + * @return new sxpr
  31.429 + */
  31.430 +Sxpr string_new(char *s){
  31.431 +    int n = (s ? strlen(s) : 0);
  31.432 +    Sxpr obj;
  31.433 +    obj = halloc(n+1, T_STRING);
  31.434 +    if(!NOMEMP(obj)){
  31.435 +        char *str = OBJ_STRING(obj);
  31.436 +        strncpy(str, s, n);
  31.437 +        str[n] = '\0';
  31.438 +    }
  31.439 +    return obj;
  31.440 +}
  31.441 +
  31.442 +/** Free a string.
  31.443 + *
  31.444 + * @param obj to free
  31.445 + */
  31.446 +void string_free(Sxpr obj){
  31.447 +    hfree(obj);
  31.448 +}
  31.449 +
  31.450 +/** Determine if a string needs escapes when printed
  31.451 + * using the given flags.
  31.452 + *
  31.453 + * @param str string to check
  31.454 + * @param flags print flags
  31.455 + * @return 1 if needs escapes, 0 otherwise
  31.456 + */
  31.457 +int needs_escapes(char *str, unsigned flags){
  31.458 +    char *c;
  31.459 +    int val = 0;
  31.460 +
  31.461 +    if(str){
  31.462 +	for(c=str; *c; c++){
  31.463 +	    if(in_alpha_class(*c)) continue;
  31.464 +	    if(in_decimal_digit_class(*c)) continue;
  31.465 +	    if(in_class(*c, "/._+:@~-")) continue;
  31.466 +	    val = 1;
  31.467 +	    break;
  31.468 +	}
  31.469 +    }
  31.470 +    //printf("\n> val=%d str=|%s|\n", val, str);
  31.471 +    return val;
  31.472 +}
  31.473 +
  31.474 +/** Print a string to a stream, with escapes if necessary.
  31.475 + *
  31.476 + * @param io stream to print to
  31.477 + * @param str string
  31.478 + * @param flags print flags
  31.479 + * @return number of bytes written
  31.480 + */
  31.481 +int _string_print(IOStream *io, char *str, unsigned flags){
  31.482 +    int k = 0;
  31.483 +    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
  31.484 +        k += IOStream_print(io, str);
  31.485 +    } else {
  31.486 +	k += IOStream_print(io, "\"");
  31.487 +	if(str){
  31.488 +            char *s;
  31.489 +            for(s = str; *s; s++){
  31.490 +                if(*s < ' ' || *s >= 127 ){
  31.491 +                    switch(*s){
  31.492 +                    case '\a': k += IOStream_print(io, "\\a");  break;
  31.493 +                    case '\b': k += IOStream_print(io, "\\b");  break;
  31.494 +                    case '\f': k += IOStream_print(io, "\\f");  break;
  31.495 +                    case '\n': k += IOStream_print(io, "\\n");  break;
  31.496 +                    case '\r': k += IOStream_print(io, "\\r");  break;
  31.497 +                    case '\t': k += IOStream_print(io, "\\t");  break;
  31.498 +                    case '\v': k += IOStream_print(io, "\\v");  break;
  31.499 +                    default:
  31.500 +                        // Octal escape;
  31.501 +                        k += IOStream_print(io, "\\%o", *s);
  31.502 +                        break;
  31.503 +                    }
  31.504 +                } else if(*s == c_double_quote ||
  31.505 +                          *s == c_single_quote ||
  31.506 +                          *s == c_escape){
  31.507 +                    k += IOStream_print(io, "\\%c", *s);
  31.508 +                } else {
  31.509 +                    k+= IOStream_print(io, "%c", *s);
  31.510 +                }
  31.511 +            }
  31.512 +	}
  31.513 +	k += IOStream_print(io, "\"");
  31.514 +    }
  31.515 +    return k;
  31.516 +}
  31.517 +
  31.518 +/** Print a string to a stream, with escapes if necessary.
  31.519 + *
  31.520 + * @param io stream to print to
  31.521 + * @param obj string
  31.522 + * @param flags print flags
  31.523 + * @return number of bytes written
  31.524 + */
  31.525 +int string_print(IOStream *io, Sxpr obj, unsigned flags){
  31.526 +    return _string_print(io, OBJ_STRING(obj), flags);
  31.527 +}
  31.528 +
  31.529 +/** Compare an sxpr with a string for equality.
  31.530 + *
  31.531 + * @param x string to compare with
  31.532 + * @param y sxpr to compare
  31.533 + * @return 1 if equal, 0 otherwise
  31.534 + */
  31.535 +int string_equal(Sxpr x, Sxpr y){
  31.536 +    int ok = 0;
  31.537 +    ok = eq(x,y);
  31.538 +    if(ok) goto exit;
  31.539 +    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
  31.540 +    if(ok) goto exit;
  31.541 +    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
  31.542 +  exit:
  31.543 +    return ok;
  31.544 +}
  31.545 +
  31.546 +/** Create a new cons cell.
  31.547 + * The cell is ONOMEM if either argument is.
  31.548 + *
  31.549 + * @param car sxpr for the car
  31.550 + * @param cdr sxpr for the cdr
  31.551 + * @return new cons
  31.552 + */
  31.553 +Sxpr cons_new(Sxpr car, Sxpr cdr){
  31.554 +    Sxpr obj;
  31.555 +    if(NOMEMP(car) || NOMEMP(cdr)){
  31.556 +        obj = ONOMEM;
  31.557 +    } else {
  31.558 +        obj = HALLOC(ObjCons, T_CONS);
  31.559 +        if(!NOMEMP(obj)){
  31.560 +            ObjCons *z = OBJ_CONS(obj);
  31.561 +            z->car = car;
  31.562 +            z->cdr = cdr;
  31.563 +        }
  31.564 +    }
  31.565 +    return obj;
  31.566 +}
  31.567 +
  31.568 +/** Push a new element onto a list.
  31.569 + *
  31.570 + * @param list list to add to
  31.571 + * @param elt element to add
  31.572 + * @return 0 if successful, error code otherwise
  31.573 + */
  31.574 +int cons_push(Sxpr *list, Sxpr elt){
  31.575 +    Sxpr l;
  31.576 +    l = cons_new(elt, *list);
  31.577 +    if(NOMEMP(l)) return -ENOMEM;
  31.578 +    *list = l;
  31.579 +    return 0;
  31.580 +}
  31.581 +
  31.582 +/** Free a cons. Recursively frees the car and cdr.
  31.583 + *
  31.584 + * @param obj to free
  31.585 + */
  31.586 +void cons_free(Sxpr obj){
  31.587 +    Sxpr next;
  31.588 +    for(; CONSP(obj); obj = next){
  31.589 +	next = CDR(obj);
  31.590 +	objfree(CAR(obj));
  31.591 +	hfree(obj);
  31.592 +    }
  31.593 +    if(!NULLP(obj)){
  31.594 +	objfree(obj);
  31.595 +    }
  31.596 +}
  31.597 +
  31.598 +/** Free a cons and its cdr cells, but not the car sxprs.
  31.599 + * Does nothing if called on something that is not a cons.
  31.600 + *
  31.601 + * @param obj to free
  31.602 + */
  31.603 +void cons_free_cells(Sxpr obj){
  31.604 +    Sxpr next;
  31.605 +    for(; CONSP(obj); obj = next){
  31.606 +	next = CDR(obj);
  31.607 +	hfree(obj);
  31.608 +    }
  31.609 +}
  31.610 +
  31.611 +/** Print a cons.
  31.612 + * Prints the cons in list format if the cdrs are conses.
  31.613 + * uses pair (dot) format if the last cdr is not a cons (or null).
  31.614 + *
  31.615 + * @param io stream to print to
  31.616 + * @param obj to print
  31.617 + * @param flags print flags
  31.618 + * @return number of bytes written
  31.619 + */
  31.620 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){
  31.621 +    int first = 1;
  31.622 +    int k = 0;
  31.623 +    k += IOStream_print(io, "(");
  31.624 +    for( ; CONSP(obj) ; obj = CDR(obj)){
  31.625 +        if(first){ 
  31.626 +            first = 0;
  31.627 +        } else {
  31.628 +            k += IOStream_print(io, " ");
  31.629 +        }
  31.630 +        k += objprint(io, CAR(obj), flags);
  31.631 +    }
  31.632 +    if(!NULLP(obj)){
  31.633 +        k += IOStream_print(io, " . ");
  31.634 +        k += objprint(io, obj, flags);
  31.635 +    }
  31.636 +    k += IOStream_print(io, ")");
  31.637 +    return (IOStream_error(io) ? -1 : k);
  31.638 +}
  31.639 +
  31.640 +/** Compare a cons with another sxpr for equality.
  31.641 + * If y is a cons, compares the cars and cdrs recursively.
  31.642 + *
  31.643 + * @param x cons to compare
  31.644 + * @param y sxpr to compare
  31.645 + * @return 1 if equal, 0 otherwise
  31.646 + */
  31.647 +int cons_equal(Sxpr x, Sxpr y){
  31.648 +    return CONSP(y) &&
  31.649 +        objequal(CAR(x), CAR(y)) &&
  31.650 +        objequal(CDR(x), CDR(y));
  31.651 +}
  31.652 +
  31.653 +/** Return the length of a cons list.
  31.654 + *
  31.655 + * @param obj list
  31.656 + * @return length
  31.657 + */
  31.658 +int cons_length(Sxpr obj){
  31.659 +    int count = 0;
  31.660 +    for( ; CONSP(obj); obj = CDR(obj)){
  31.661 +        count++;
  31.662 +    }
  31.663 +    return count;
  31.664 +}
  31.665 +
  31.666 +/** Destructively reverse a cons list in-place.
  31.667 + * If the argument is not a cons it is returned unchanged.
  31.668 + * 
  31.669 + * @param l to reverse
  31.670 + * @return reversed list
  31.671 + */
  31.672 +Sxpr nrev(Sxpr l){
  31.673 +    if(CONSP(l)){
  31.674 +	// Iterate down the cells in the list making the cdr of
  31.675 +	// each cell point to the previous cell. The last cell 
  31.676 +	// is the head of the reversed list.
  31.677 +	Sxpr prev = ONULL;
  31.678 +	Sxpr cell = l;
  31.679 +	Sxpr next;
  31.680 +
  31.681 +	while(1){
  31.682 +	    next = CDR(cell);
  31.683 +	    CDR(cell) = prev;
  31.684 +	    if(!CONSP(next)) break;
  31.685 +	    prev = cell;
  31.686 +	    cell = next;
  31.687 +	}
  31.688 +	l = cell;
  31.689 +    }
  31.690 +    return l;
  31.691 +}
  31.692 +
  31.693 +/** Print the null sxpr.	
  31.694 + *
  31.695 + * @param io stream to print to
  31.696 + * @param obj to print
  31.697 + * @param flags print flags
  31.698 + * @return number of bytes written
  31.699 + */
  31.700 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){
  31.701 +    return IOStream_print(io, "()");
  31.702 +}
  31.703 +
  31.704 +/** Print the `unspecified' sxpr none.
  31.705 + *
  31.706 + * @param io stream to print to
  31.707 + * @param obj to print
  31.708 + * @param flags print flags
  31.709 + * @return number of bytes written
  31.710 + */
  31.711 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){
  31.712 +    return IOStream_print(io, "<none>");
  31.713 +}
  31.714 +
  31.715 +/** Print an integer.
  31.716 + *
  31.717 + * @param io stream to print to
  31.718 + * @param obj to print
  31.719 + * @param flags print flags
  31.720 + * @return number of bytes written
  31.721 + */
  31.722 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){
  31.723 +    return IOStream_print(io, "%d", OBJ_INT(obj));
  31.724 +}
  31.725 +
  31.726 +/** Print a boolean.
  31.727 + *
  31.728 + * @param io stream to print to
  31.729 + * @param obj to print
  31.730 + * @param flags print flags
  31.731 + * @return number of bytes written
  31.732 + */
  31.733 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
  31.734 +    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
  31.735 +}
  31.736 +
  31.737 +int sxprp(Sxpr obj, Sxpr name){
  31.738 +    return CONSP(obj) && objequal(CAR(obj), name);
  31.739 +}
  31.740 +
  31.741 +/** Get the name of an element.
  31.742 + * 
  31.743 + * @param obj element
  31.744 + * @return name
  31.745 + */
  31.746 +Sxpr sxpr_name(Sxpr obj){
  31.747 +    Sxpr val = ONONE;
  31.748 +    if(CONSP(obj)){
  31.749 +        val = CAR(obj);
  31.750 +    } else if(STRINGP(obj) || ATOMP(obj)){
  31.751 +        val = obj;
  31.752 +    }
  31.753 +    return val;
  31.754 +}
  31.755 +
  31.756 +int sxpr_is(Sxpr obj, char *s){
  31.757 +    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
  31.758 +    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
  31.759 +    return 0;
  31.760 +}
  31.761 +
  31.762 +int sxpr_elementp(Sxpr obj, Sxpr name){
  31.763 +    return CONSP(obj) && objequal(CAR(obj), name);
  31.764 +}
  31.765 +
  31.766 +/** Get the attributes of an sxpr.
  31.767 + * 
  31.768 + * @param obj sxpr
  31.769 + * @return attributes
  31.770 + */
  31.771 +Sxpr sxpr_attributes(Sxpr obj){
  31.772 +    Sxpr val = ONULL;
  31.773 +    if(CONSP(obj)){
  31.774 +        obj = CDR(obj);
  31.775 +        if(CONSP(obj)){
  31.776 +            obj = CAR(obj);
  31.777 +            if(sxprp(obj, intern("@"))){
  31.778 +                val = CDR(obj);
  31.779 +            }
  31.780 +        }
  31.781 +    }
  31.782 +    return val;
  31.783 +}
  31.784 +
  31.785 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
  31.786 +    Sxpr val = ONONE;
  31.787 +    val = assoc(sxpr_attributes(obj), key);
  31.788 +    if(CONSP(val) && CONSP(CDR(val))){
  31.789 +        val = CADR(def);
  31.790 +    } else {
  31.791 +        val = def;
  31.792 +    }
  31.793 +    return val;
  31.794 +}
  31.795 +
  31.796 +/** Get the children of an sxpr.
  31.797 + * 
  31.798 + * @param obj sxpr
  31.799 + * @return children
  31.800 + */
  31.801 +Sxpr sxpr_children(Sxpr obj){
  31.802 +    Sxpr val = ONULL;
  31.803 +    if(CONSP(obj)){
  31.804 +        val = CDR(obj);
  31.805 +        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
  31.806 +            val = CDR(val);
  31.807 +        }
  31.808 +    }
  31.809 +    return val;
  31.810 +}
  31.811 +
  31.812 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
  31.813 +    Sxpr val = ONONE;
  31.814 +    Sxpr l;
  31.815 +    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
  31.816 +        if(sxprp(CAR(l), name)){
  31.817 +            val = CAR(l);
  31.818 +            break;
  31.819 +        }
  31.820 +    }
  31.821 +    if(NONEP(val)) val = def;
  31.822 +    return val;
  31.823 +}
  31.824 +
  31.825 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){
  31.826 +    Sxpr val = ONONE;
  31.827 +    Sxpr l = sxpr_children(obj);
  31.828 +    if(CONSP(l)){
  31.829 +        val = CAR(l);
  31.830 +    } else {
  31.831 +        val = def;
  31.832 +    }
  31.833 +    return val;
  31.834 +}
  31.835 +
  31.836 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
  31.837 +    Sxpr val = ONONE;
  31.838 +    val = sxpr_child(obj, name, ONONE);
  31.839 +    if(NONEP(val)){
  31.840 +        val = def;
  31.841 +    } else {
  31.842 +        val = sxpr_child0(val, def);
  31.843 +    }
  31.844 +    return val;
  31.845 +}
  31.846 +
  31.847 +/** Table of interned symbols. Indexed by symbol name. */
  31.848 +static HashTable *symbols = NULL;
  31.849 +
  31.850 +/** Hash function for entries in the symbol table.
  31.851 + *
  31.852 + * @param key to hash
  31.853 + * @return hashcode
  31.854 + */
  31.855 +static Hashcode sym_hash_fn(void *key){
  31.856 +    return hash_string((char*)key);
  31.857 +}
  31.858 +
  31.859 +/** Key equality function for the symbol table.
  31.860 + *
  31.861 + * @param x to compare
  31.862 + * @param y to compare
  31.863 + * @return 1 if equal, 0 otherwise
  31.864 + */
  31.865 +static int sym_equal_fn(void *x, void *y){
  31.866 +    return !strcmp((char*)x, (char*)y);
  31.867 +}
  31.868 +
  31.869 +/** Entry free function for the symbol table.
  31.870 + *
  31.871 + * @param table the entry is in
  31.872 + * @param entry being freed
  31.873 + */
  31.874 +static void sym_free_fn(HashTable *table, HTEntry *entry){
  31.875 +    if(entry){
  31.876 +	objfree(((ObjAtom*)entry->value)->name);
  31.877 +	HTEntry_free(entry);
  31.878 +    }
  31.879 +}
  31.880 +	
  31.881 +/** Initialize the symbol table.
  31.882 + *
  31.883 + * @return 0 on sucess, error code otherwise
  31.884 + */
  31.885 +static int init_symbols(void){
  31.886 +    symbols = HashTable_new(100);
  31.887 +    if(symbols){
  31.888 +        symbols->key_hash_fn = sym_hash_fn;
  31.889 +        symbols->key_equal_fn = sym_equal_fn;
  31.890 +	symbols->entry_free_fn = sym_free_fn;
  31.891 +        return 0;
  31.892 +    }
  31.893 +    return -1;
  31.894 +}
  31.895 +
  31.896 +/** Cleanup the symbol table. Frees the table and all its symbols.
  31.897 + */
  31.898 +void cleanup_symbols(void){
  31.899 +    HashTable_free(symbols);
  31.900 +    symbols = NULL;
  31.901 +}
  31.902 +
  31.903 +/** Get the interned symbol with the given name.
  31.904 + * No new symbol is created.
  31.905 + *
  31.906 + * @return symbol or null
  31.907 + */
  31.908 +Sxpr get_symbol(char *sym){
  31.909 +    HTEntry *entry;
  31.910 +    if(!symbols){
  31.911 +	if(init_symbols()) return ONOMEM;
  31.912 +	return ONULL;
  31.913 +    }
  31.914 +    entry = HashTable_get_entry(symbols, sym);
  31.915 +    if(entry){
  31.916 +        return OBJP(T_ATOM, entry->value);
  31.917 +    } else {
  31.918 +        return ONULL;
  31.919 +    }
  31.920 +}
  31.921 +
  31.922 +/** Get the interned symbol with the given name.
  31.923 + * Creates a new symbol if necessary.
  31.924 + *
  31.925 + * @return symbol
  31.926 + */
  31.927 +Sxpr intern(char *sym){
  31.928 +    Sxpr symbol = get_symbol(sym);
  31.929 +    if(NULLP(symbol)){
  31.930 +	if(!symbols) return ONOMEM;
  31.931 +        symbol = atom_new(sym);
  31.932 +        if(!NOMEMP(symbol)){
  31.933 +	    OBJ_ATOM(symbol)->interned = TRUE;
  31.934 +            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
  31.935 +        }
  31.936 +    }
  31.937 +    return symbol;
  31.938 +}
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/tools/lib/sxpr.h	Tue Jun 29 12:05:29 2004 +0000
    32.3 @@ -0,0 +1,413 @@
    32.4 +/*
    32.5 + *
    32.6 + * This library is free software; you can redistribute it and/or modify
    32.7 + * it under the terms of the GNU Lesser General Public License as
    32.8 + * published by the Free Software Foundation; either version 2.1 of the
    32.9 + * License, or  (at your option) any later version. This library is 
   32.10 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   32.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   32.12 + * FITNESS FOR A PARTICULAR PURPOSE.
   32.13 + * See the GNU Lesser General Public License for more details.
   32.14 + *
   32.15 + * You should have received a copy of the GNU Lesser General Public License
   32.16 + * along with this library; if not, write to the Free Software Foundation,
   32.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   32.18 + */
   32.19 +#ifndef _XEN_LIB_SXPR_H_
   32.20 +#define _XEN_LIB_SXPR_H_
   32.21 +
   32.22 +#include <stdint.h>
   32.23 +
   32.24 +#include "hash_table.h"
   32.25 +#include "iostream.h"
   32.26 +#include "allocate.h"
   32.27 +
   32.28 +/** @file
   32.29 + * Definitions for rules and sxprs.
   32.30 + */
   32.31 +
   32.32 +#ifndef NULL
   32.33 +#define NULL 0
   32.34 +#endif
   32.35 +
   32.36 +#ifndef TRUE
   32.37 +#define TRUE 1
   32.38 +#endif
   32.39 +
   32.40 +#ifndef FALSE
   32.41 +#define FALSE 0
   32.42 +#endif
   32.43 +
   32.44 +/** Sxpr type. */
   32.45 +typedef int16_t TypeCode;
   32.46 +
   32.47 +/** A typed sxpr handle.*/
   32.48 +typedef struct Sxpr {
   32.49 +    /** Sxpr type. */
   32.50 +    TypeCode type;
   32.51 +    union {
   32.52 +	/** Sxpr value. */
   32.53 +        unsigned long ul;
   32.54 +	/** Pointer. */
   32.55 +        void *ptr;
   32.56 +    } v;
   32.57 +} Sxpr;
   32.58 +
   32.59 +/** Sxpr type to indicate out of memory. */
   32.60 +#define T_NOMEM      ((TypeCode)-1)
   32.61 +/** The 'unspecified' sxpr. */
   32.62 +#define T_NONE       ((TypeCode)0)
   32.63 +/** The empty list. */
   32.64 +#define T_NULL       ((TypeCode)1)
   32.65 +/** Unsigned integer. */
   32.66 +#define T_UINT       ((TypeCode)2)
   32.67 +/** A string. */
   32.68 +#define T_STRING     ((TypeCode)3)
   32.69 +/** An atom. */
   32.70 +#define T_ATOM       ((TypeCode)4)
   32.71 +/** A boolean. */
   32.72 +#define T_BOOL       ((TypeCode)5)
   32.73 +
   32.74 +/** A cons (pair or list). */
   32.75 +#define T_CONS       ((TypeCode)10)
   32.76 +
   32.77 +/** An error. */
   32.78 +#define T_ERR        ((TypeCode)40)
   32.79 +
   32.80 +/** An atom. */
   32.81 +typedef struct ObjAtom {
   32.82 +    Sxpr name;
   32.83 +    Hashcode hashcode;
   32.84 +    int interned;
   32.85 +} ObjAtom;
   32.86 +
   32.87 +/** A cons (pair). */
   32.88 +typedef struct ObjCons {
   32.89 +    Sxpr car;
   32.90 +    Sxpr cdr;
   32.91 +} ObjCons;
   32.92 +
   32.93 +/** A vector. */
   32.94 +typedef struct ObjVector {
   32.95 +    int n;
   32.96 +    Sxpr data[0];
   32.97 +} ObjVector;
   32.98 +
   32.99 +/** Flags for sxpr printing. */
  32.100 +enum PrintFlags {
  32.101 +    PRINT_RAW           = 0x001,
  32.102 +    PRINT_TYPE          = 0x002,
  32.103 +    PRINT_PRETTY        = 0x004,
  32.104 +    PRINT_NUM           = 0x008,
  32.105 +};
  32.106 +
  32.107 +/** An integer sxpr.
  32.108 + *
  32.109 + * @param ty type
  32.110 + * @param val integer value
  32.111 + */
  32.112 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
  32.113 +
  32.114 +/** A pointer sxpr.
  32.115 + * If the pointer is non-null, returns an sxpr containing it.
  32.116 + * If the pointer is null, returns ONOMEM.
  32.117 + *
  32.118 + * @param ty type
  32.119 + * @param val pointer
  32.120 + */
  32.121 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
  32.122 +
  32.123 +/** Make an integer sxpr containing a pointer.
  32.124 + *
  32.125 + * @param val pointer
  32.126 + */
  32.127 +#define PTR(val) OBJP(T_UINT, (void*)(val))
  32.128 +
  32.129 +/** Make an integer sxpr.
  32.130 + * @param x value
  32.131 + */
  32.132 +#define OINT(x)       OBJI(T_UINT,  x)
  32.133 +
  32.134 +/** Make an error sxpr.
  32.135 + *
  32.136 + * @param x value
  32.137 + */
  32.138 +#define OERR(x)       OBJI(T_ERR,   x)
  32.139 +
  32.140 +/** Out of memory constant. */
  32.141 +#define ONOMEM        OBJI(T_NOMEM, 0)
  32.142 +
  32.143 +/** The `unspecified' constant. */
  32.144 +#define ONONE         OBJI(T_NONE,  0)
  32.145 +
  32.146 +/** Empty list constant. */
  32.147 +#define ONULL         OBJI(T_NULL,  0)
  32.148 +
  32.149 +/** False constant. */
  32.150 +#define OFALSE        OBJI(T_BOOL,  0)
  32.151 +
  32.152 +/** True constant. */
  32.153 +#define OTRUE         OBJI(T_BOOL,  1)
  32.154 +
  32.155 +/* Recognizers for the various sxpr types.  */
  32.156 +#define ATOMP(obj)        has_type(obj, T_ATOM)
  32.157 +#define BOOLP(obj)        has_type(obj, T_BOOL)
  32.158 +#define CONSP(obj)        has_type(obj, T_CONS)
  32.159 +#define ERRP(obj)         has_type(obj, T_ERR)
  32.160 +#define INTP(obj)         has_type(obj, T_UINT)
  32.161 +#define NOMEMP(obj)       has_type(obj, T_NOMEM)
  32.162 +#define NONEP(obj)        has_type(obj, T_NONE)
  32.163 +#define NULLP(obj)        has_type(obj, T_NULL)
  32.164 +#define STRINGP(obj)      has_type(obj, T_STRING)
  32.165 +
  32.166 +#define TRUEP(obj)    get_ul(obj)
  32.167 +
  32.168 +/** Convert an sxpr to an unsigned integer. */
  32.169 +#define OBJ_UINT(x)   get_ul(x)
  32.170 +/** Convert an sxpr to an integer. */
  32.171 +#define OBJ_INT(x)    (int)get_ul(x)
  32.172 +
  32.173 +/* Conversions of sxprs to their values.
  32.174 + * No checking is done.
  32.175 + */
  32.176 +#define OBJ_STRING(x)  ((char*)get_ptr(x))
  32.177 +#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
  32.178 +#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
  32.179 +#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
  32.180 +#define CAR(x)         (OBJ_CONS(x)->car)
  32.181 +#define CDR(x)         (OBJ_CONS(x)->cdr)
  32.182 +
  32.183 +#define CAAR(x)        (CAR(CAR(x)))
  32.184 +#define CADR(x)        (CAR(CDR(x)))
  32.185 +#define CDAR(x)        (CDR(CAR(x)))
  32.186 +#define CDDR(x)        (CDR(CDR(x)))
  32.187 +
  32.188 +/** Get the integer value from an sxpr.
  32.189 + *
  32.190 + * @param obj sxpr
  32.191 + * @return value
  32.192 + */
  32.193 +static inline unsigned long get_ul(Sxpr obj){
  32.194 +    return obj.v.ul;
  32.195 +}
  32.196 +
  32.197 +/** Get the pointer value from an sxpr.
  32.198 + *
  32.199 + * @param obj sxpr
  32.200 + * @return value
  32.201 + */
  32.202 +static inline void * get_ptr(Sxpr obj){
  32.203 +    return obj.v.ptr;
  32.204 +}
  32.205 +
  32.206 +/** Create an sxpr containing a pointer.
  32.207 + *
  32.208 + * @param type typecode
  32.209 + * @param val pointer
  32.210 + * @return sxpr
  32.211 + */
  32.212 +static inline Sxpr obj_ptr(TypeCode type, void *val){
  32.213 +    return (Sxpr){ type: type, v: { ptr: val } };
  32.214 +}
  32.215 +
  32.216 +/** Create an sxpr containing an integer.
  32.217 + *
  32.218 + * @param type typecode
  32.219 + * @param val integer
  32.220 + * @return sxpr
  32.221 + */
  32.222 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){
  32.223 +    return (Sxpr){ type: type, v: { ul: val } };
  32.224 +}
  32.225 +
  32.226 +/** Get the type of an sxpr.
  32.227 + *
  32.228 + * @param obj sxpr
  32.229 + * @return type
  32.230 + */
  32.231 +static inline TypeCode get_type(Sxpr obj){
  32.232 +    return obj.type;
  32.233 +}
  32.234 +
  32.235 +/** Check the type of an sxpr.
  32.236 + *
  32.237 + * @param obj sxpr
  32.238 + * @param type to check
  32.239 + * @return 1 if has the type, 0 otherwise
  32.240 + */
  32.241 +static inline int has_type(Sxpr obj, TypeCode type){
  32.242 +    return get_type(obj) == type;
  32.243 +}
  32.244 +
  32.245 +/** Compare sxprs for literal equality of type and value.
  32.246 + *
  32.247 + * @param x sxpr to compare
  32.248 + * @param y sxpr to compare
  32.249 + * @return 1 if equal, 0 otherwise
  32.250 + */
  32.251 +static inline int eq(Sxpr x, Sxpr y){
  32.252 +    return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
  32.253 +}
  32.254 +
  32.255 +/** Checked version of CAR
  32.256 + *
  32.257 + * @param x sxpr
  32.258 + * @return CAR if a cons, x otherwise
  32.259 + */
  32.260 +static inline Sxpr car(Sxpr x){
  32.261 +    return (CONSP(x) ? CAR(x) : x);
  32.262 +}
  32.263 +
  32.264 +/** Checked version of CDR.
  32.265 + *
  32.266 + * @param x sxpr
  32.267 + * @return CDR if a cons, null otherwise
  32.268 + */
  32.269 +static inline Sxpr cdr(Sxpr x){
  32.270 +    return (CONSP(x) ? CDR(x) : ONULL);
  32.271 +}
  32.272 +
  32.273 +/** Allocate some memory and return an sxpr containing it.
  32.274 + * Returns ONOMEM if allocation failed.
  32.275 + *
  32.276 + * @param n number of bytes to allocate
  32.277 + * @param ty typecode
  32.278 + * @return sxpr
  32.279 + */
  32.280 +static inline Sxpr halloc(size_t n,  TypeCode ty){
  32.281 +    return OBJP(ty, allocate(n));
  32.282 +}
  32.283 +
  32.284 +/** Allocate an sxpr containing a pointer to the given type.
  32.285 + *
  32.286 + * @param ty type (uses sizeof to determine how many bytes to allocate)
  32.287 + * @param code typecode
  32.288 + * @return sxpr, ONOMEM if allocation failed
  32.289 + */
  32.290 +#define HALLOC(ty, code) halloc(sizeof(ty), code)
  32.291 +
  32.292 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
  32.293 +typedef int ObjEqualFn(Sxpr obj, Sxpr other);
  32.294 +typedef void ObjFreeFn(Sxpr obj);
  32.295 +
  32.296 +/** An sxpr type definition. */
  32.297 +typedef struct SxprType {
  32.298 +    TypeCode type;
  32.299 +    char *name;
  32.300 +    int pointer;
  32.301 +    ObjPrintFn *print;
  32.302 +    ObjEqualFn *equal;
  32.303 +    ObjFreeFn *free;
  32.304 +} SxprType;
  32.305 +
  32.306 +
  32.307 +extern SxprType *get_sxpr_type(int ty);
  32.308 +
  32.309 +/** Free the pointer in an sxpr.
  32.310 + *
  32.311 + * @param x sxpr containing a pointer
  32.312 + */
  32.313 +static inline void hfree(Sxpr x){
  32.314 +    deallocate(get_ptr(x));
  32.315 +}
  32.316 +
  32.317 +extern int objprint(IOStream *io, Sxpr x, unsigned flags);
  32.318 +extern int objequal(Sxpr x, Sxpr y);
  32.319 +extern void objfree(Sxpr x);
  32.320 +
  32.321 +extern void cons_free_cells(Sxpr obj);
  32.322 +extern Sxpr intern(char *s);
  32.323 +
  32.324 +extern Sxpr assoc(Sxpr k, Sxpr l);
  32.325 +extern Sxpr assocq(Sxpr k, Sxpr l);
  32.326 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l);
  32.327 +extern Sxpr nrev(Sxpr l);
  32.328 +extern Sxpr cons_member(Sxpr l, Sxpr x);
  32.329 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  32.330 +extern int cons_subset(Sxpr s, Sxpr t);
  32.331 +extern int cons_set_equal(Sxpr s, Sxpr t);
  32.332 +
  32.333 +#ifdef USE_GC
  32.334 +extern Sxpr cons_remove(Sxpr l, Sxpr x);
  32.335 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  32.336 +#endif
  32.337 +
  32.338 +extern Sxpr atom_new(char *name);
  32.339 +extern char * atom_name(Sxpr obj);
  32.340 +
  32.341 +extern Sxpr string_new(char *s);
  32.342 +extern char * string_string(Sxpr obj);
  32.343 +extern int string_length(Sxpr obj);
  32.344 +
  32.345 +extern Sxpr cons_new(Sxpr car, Sxpr cdr);
  32.346 +extern int cons_push(Sxpr *list, Sxpr elt);
  32.347 +extern int cons_length(Sxpr obj);
  32.348 +
  32.349 +Sxpr sxpr_name(Sxpr obj);
  32.350 +int sxpr_is(Sxpr obj, char *s);
  32.351 +int sxpr_elementp(Sxpr obj, Sxpr name);
  32.352 +Sxpr sxpr_attributes(Sxpr obj);
  32.353 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def);
  32.354 +Sxpr sxpr_children(Sxpr obj);
  32.355 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def);
  32.356 +Sxpr sxpr_child0(Sxpr obj, Sxpr def);
  32.357 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
  32.358 +
  32.359 +/** Create a new atom.
  32.360 + *
  32.361 + * @param s atom name
  32.362 + * @return new atom
  32.363 + */
  32.364 +static inline Sxpr mkatom(char *s){
  32.365 +    return atom_new(s);
  32.366 +}
  32.367 +
  32.368 +/** Create a new string sxpr.
  32.369 + *
  32.370 + * @param s string bytes (copied)
  32.371 + * @return new string
  32.372 + */
  32.373 +static inline Sxpr mkstring(char *s){
  32.374 +    return string_new(s);
  32.375 +}
  32.376 +
  32.377 +/** Create an integer sxpr.
  32.378 + *
  32.379 + * @param i value
  32.380 + * @return sxpr
  32.381 + */
  32.382 +static inline Sxpr mkint(int i){
  32.383 +    return OBJI(T_UINT, i);
  32.384 +}
  32.385 +
  32.386 +/** Create a boolean sxpr.
  32.387 + *
  32.388 + * @param b value
  32.389 + * @return sxpr
  32.390 + */
  32.391 +static inline Sxpr mkbool(int b){
  32.392 +    return OBJI(T_BOOL, (b ? 1 : 0));
  32.393 +}
  32.394 +
  32.395 +/* Constants used in parsing and printing. */
  32.396 +#define k_list_open    "("
  32.397 +#define c_list_open    '('
  32.398 +#define k_list_close   ")"
  32.399 +#define c_list_close   ')'
  32.400 +#define k_true         "true"
  32.401 +#define k_false        "false"
  32.402 +
  32.403 +#define c_var          '$'
  32.404 +#define c_escape       '\\'
  32.405 +#define c_single_quote '\''
  32.406 +#define c_double_quote '"'
  32.407 +#define c_string_open  c_double_quote
  32.408 +#define c_string_close c_double_quote
  32.409 +#define c_data_open    '['
  32.410 +#define c_data_close   ']'
  32.411 +#define c_binary       '*'
  32.412 +#define c_eval         '!'
  32.413 +#define c_concat_open  '{'
  32.414 +#define c_concat_close '}'
  32.415 +
  32.416 +#endif /* ! _XEN_LIB_SXPR_H_ */
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/tools/lib/sxpr_parser.c	Tue Jun 29 12:05:29 2004 +0000
    33.3 @@ -0,0 +1,897 @@
    33.4 +
    33.5 +#ifdef __KERNEL__
    33.6 +#  include <linux/config.h>
    33.7 +#  include <linux/module.h>
    33.8 +#  include <linux/kernel.h>
    33.9 +#  include <linux/string.h>
   33.10 +#  include <linux/errno.h>
   33.11 +#else
   33.12 +#  include <stdlib.h>
   33.13 +#  include <errno.h>
   33.14 +#endif
   33.15 +
   33.16 +#include "iostream.h"
   33.17 +#include "lexis.h"
   33.18 +#include "sxpr_parser.h"
   33.19 +#include "sys_string.h"
   33.20 +
   33.21 +/** @file
   33.22 + * Sxpr parsing.
   33.23 + *
   33.24 + * So that the parser does not leak memory, all sxprs constructed by
   33.25 + * the parser must be freed on error.  On successful parse the sxpr
   33.26 + * returned becomes the responsibility of the caller.
   33.27 + *
   33.28 + * @author Mike Wray <mike.wray@hpl.hp.com>
   33.29 + */
   33.30 +
   33.31 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
   33.32 +#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
   33.33 +
   33.34 +static void reset(Parser *z);
   33.35 +static int inputchar(Parser *p, char c);
   33.36 +static int savechar(Parser *p, char c);
   33.37 +extern void parse_error(Parser *in);
   33.38 +extern void parse_error_id(Parser *in, ParseErrorId id);
   33.39 +
   33.40 +static int begin_start(Parser *p, char c);
   33.41 +static int state_start(Parser *p, char c);
   33.42 +static int end_start(Parser *p);
   33.43 +
   33.44 +static int begin_comment(Parser *p, char c);
   33.45 +static int state_comment(Parser *p, char c);
   33.46 +static int end_comment(Parser *p);
   33.47 +
   33.48 +static int begin_string(Parser *p, char c);
   33.49 +static int state_string(Parser *p, char c);
   33.50 +static int end_string(Parser *p);
   33.51 +static int state_escape(Parser *p, char c);
   33.52 +static int state_octal(Parser *p, char c);
   33.53 +static int state_hex(Parser *p, char c);
   33.54 +
   33.55 +static int begin_atom(Parser *p, char c);
   33.56 +static int state_atom(Parser *p, char c);
   33.57 +static int end_atom(Parser *p);
   33.58 +
   33.59 +static int state_list(Parser *p, char c);
   33.60 +static int begin_list(Parser *p, char c);
   33.61 +static int end_list(Parser *p);
   33.62 +
   33.63 +/** Print a parse error.
   33.64 + *
   33.65 + * @param in parser
   33.66 + * @param msg format followed by printf arguments
   33.67 + */
   33.68 +void eprintf(Parser *in, char *msg, ...){
   33.69 +    va_list args;
   33.70 +    if(in->error_out){
   33.71 +        va_start(args, msg);
   33.72 +        IOStream_vprint(in->error_out, msg, args);
   33.73 +        va_end(args);
   33.74 +    }
   33.75 +}
   33.76 +
   33.77 +/** Print a parse warning.
   33.78 + *
   33.79 + * @param in parser
   33.80 + * @param msg format followed by printf arguments
   33.81 + */
   33.82 +void wprintf(Parser *in, char *msg, ...){
   33.83 +    va_list args;
   33.84 +    if(in->error_out){
   33.85 +        va_start(args, msg);
   33.86 +        IOStream_vprint(in->error_out, msg, args);
   33.87 +        va_end(args);
   33.88 +    }
   33.89 +}
   33.90 +
   33.91 +/*============================================================================*/
   33.92 +
   33.93 +/** Record defining the message for a parse error. */
   33.94 +typedef struct {
   33.95 +  ParseErrorId id;
   33.96 +  char *message;
   33.97 +} ParseError;
   33.98 +
   33.99 +/** Format for printing parse error messages. */
  33.100 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
  33.101 +
  33.102 +/** Message catalog for the parse error codes. */
  33.103 +static ParseError catalog[] = {
  33.104 +  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
  33.105 +  { PARSE_ERR_NOMEM,                  "out of memory" },
  33.106 +  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
  33.107 +  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
  33.108 +  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
  33.109 +  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
  33.110 +  { 0, NULL }
  33.111 +};
  33.112 +
  33.113 +/** Number of entries in the message catalog. */
  33.114 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
  33.115 +
  33.116 +void ParserState_free(ParserState *z){
  33.117 +    if(!z) return;
  33.118 +    objfree(z->val);
  33.119 +    deallocate(z);
  33.120 +}
  33.121 +
  33.122 +int ParserState_new(ParserStateFn *fn, ParserState *parent, ParserState **val){
  33.123 +    int err = 0;
  33.124 +    ParserState *z;
  33.125 +    z = ALLOCATE(ParserState);
  33.126 +    if(z){
  33.127 +        z->fn = fn;
  33.128 +        z->parent = parent;
  33.129 +        z->val = ONULL;
  33.130 +    } else {
  33.131 +        err = -ENOMEM;
  33.132 +    }
  33.133 +    if(!err) *val = z;
  33.134 +    return err;
  33.135 +}
  33.136 +
  33.137 +/** Free a parser.
  33.138 + * No-op if the parser is null.
  33.139 + *
  33.140 + * @param z parser 
  33.141 + */
  33.142 +void Parser_free(Parser *z){
  33.143 +    if(!z) return;
  33.144 +    objfree(z->val);
  33.145 +    z->val = ONONE;
  33.146 +    deallocate(z);
  33.147 +}
  33.148 +
  33.149 +/** Create a new parser. The error stream defaults to null.
  33.150 + */
  33.151 +Parser * Parser_new(void){
  33.152 +    Parser *z = ALLOCATE(Parser);
  33.153 +    int err = -ENOMEM;
  33.154 +  
  33.155 +    if(!z) goto exit;
  33.156 +    err = 0;
  33.157 +    reset(z);
  33.158 +  exit:
  33.159 +    if(err){
  33.160 +        Parser_free(z);
  33.161 +        z = NULL;
  33.162 +    }
  33.163 +    return z;
  33.164 +}
  33.165 +
  33.166 +/** Get the next character.
  33.167 + * Records the character read in the parser,
  33.168 + * and sets the line and character counts.
  33.169 + *
  33.170 + * @param p parser
  33.171 + * @return error flag: 0 on success, non-zero on error
  33.172 + */
  33.173 +static int inputchar(Parser *p, char c){
  33.174 +    int err = 0;
  33.175 +    if(c=='\n'){
  33.176 +        p->line_no++;
  33.177 +        p->char_no = 0;
  33.178 +    } else {
  33.179 +        p->char_no++;
  33.180 +    }
  33.181 +    return err;
  33.182 +}
  33.183 +
  33.184 +static int savechar(Parser *p, char c){
  33.185 +    int err = 0;
  33.186 +    if(p->buf_i >= p->buf_n){
  33.187 +        err = -ENOMEM;
  33.188 +        goto exit;
  33.189 +    }
  33.190 +    p->buf[p->buf_i] = c;
  33.191 +    p->buf_i++;
  33.192 +  exit:
  33.193 +    return err;
  33.194 +}
  33.195 +
  33.196 +int Parser_input_char(Parser *p, char c){
  33.197 +    int err = 0;
  33.198 +    if(at_eof(p)){
  33.199 +        //skip;
  33.200 +    } else {
  33.201 +        inputchar(p, c);
  33.202 +    }
  33.203 +    if(!p->state){
  33.204 +        err = begin_start(p, c);
  33.205 +        if(err) goto exit;
  33.206 +    }
  33.207 +    err = p->state->fn(p, c);
  33.208 +  exit:
  33.209 +    return err;
  33.210 +}
  33.211 +
  33.212 +int Parser_input_eof(Parser *p){
  33.213 +    int err = 0;
  33.214 +    p->eof = 1;
  33.215 +    err = Parser_input_char(p, IOSTREAM_EOF);
  33.216 +    return err;
  33.217 +}
  33.218 +
  33.219 +int Parser_input(Parser *p, char *buf, int buf_n){
  33.220 +    int err = 0;
  33.221 +    int i = 0;
  33.222 +    if(buf_n <= 0){
  33.223 +        err = Parser_input_eof(p);
  33.224 +        goto exit;
  33.225 +    }
  33.226 +    for(i = 0; i<buf_n; i++){
  33.227 +        err = Parser_input_char(p, buf[i]);
  33.228 +        if(err) goto exit;
  33.229 +    }
  33.230 +  exit:
  33.231 +    err = (err < 0 ? err : buf_n);
  33.232 +    return err;
  33.233 +}
  33.234 +
  33.235 +int Parser_push(Parser *p, ParserStateFn *fn){
  33.236 +    int err = 0;
  33.237 +    err = ParserState_new(fn, p->state, &p->state);
  33.238 +    return err;
  33.239 +}
  33.240 +        
  33.241 +int Parser_pop(Parser *p){
  33.242 +    int err = 0;
  33.243 +    ParserState *s = p->state;
  33.244 +    p->state = s->parent;
  33.245 +    ParserState_free(s);
  33.246 +    return err;
  33.247 +}
  33.248 +
  33.249 +int Parser_return(Parser *p){
  33.250 +    int err = 0;
  33.251 +    Sxpr val = ONONE;
  33.252 +    if(!p->state){
  33.253 +        err = -EINVAL;
  33.254 +        goto exit;
  33.255 +    }
  33.256 +    val = p->state->val;
  33.257 +    p->state->val = ONONE;
  33.258 +    err = Parser_pop(p);
  33.259 +    if(err) goto exit;
  33.260 +    if(p->state){
  33.261 +        err = cons_push(&p->state->val, val);
  33.262 +    } else {
  33.263 +        val = nrev(val);
  33.264 +        p->val = val;
  33.265 +    }
  33.266 +  exit:
  33.267 +    if(err){
  33.268 +        objfree(val);
  33.269 +    }
  33.270 +    return err;
  33.271 +}
  33.272 +
  33.273 +/** Determine if a character is a separator.
  33.274 + *
  33.275 + * @param p parser
  33.276 + * @param c character to test
  33.277 + * @return 1 if a separator, 0 otherwise
  33.278 + */
  33.279 +static int is_separator(Parser *p, char c){
  33.280 +    return in_sep_class(c);
  33.281 +}
  33.282 +
  33.283 +/** Return the current token.
  33.284 + * The return value points at the internal buffer, so
  33.285 + * it must not be modified (or freed). Use copy_token() if you need a copy.
  33.286 + *
  33.287 + * @param p parser
  33.288 + * @return token
  33.289 + */
  33.290 +char *peek_token(Parser *p){
  33.291 +    return p->buf;
  33.292 +}
  33.293 +
  33.294 +/** Return a copy of the current token.
  33.295 + * The returned value should be freed when finished with.
  33.296 + *
  33.297 + * @param p parser
  33.298 + * @return copy of token
  33.299 + */
  33.300 +char *copy_token(Parser *p){
  33.301 +    return strdup(peek_token(p));
  33.302 +}
  33.303 +
  33.304 +static int do_intern(Parser *p){
  33.305 +    int err = 0;
  33.306 +    Sxpr obj = intern(peek_token(p));
  33.307 +    if(NOMEMP(obj)){
  33.308 +        err = -ENOMEM;
  33.309 +    } else {
  33.310 +        p->state->val = obj;
  33.311 +    }
  33.312 +    return err;
  33.313 +}
  33.314 +
  33.315 +static int do_string(Parser *p){
  33.316 +    int err = 0;
  33.317 +    Sxpr obj;
  33.318 +    obj = string_new(peek_token(p));
  33.319 +    if(NOMEMP(obj)){
  33.320 +        err = -ENOMEM;
  33.321 +    } else {
  33.322 +        p->state->val = obj;
  33.323 +    }
  33.324 +    return err;
  33.325 +}
  33.326 +
  33.327 +void newtoken(Parser *p){
  33.328 +    memset(p->buf, 0, p->buf_n);
  33.329 +    p->buf_i = 0;
  33.330 +    p->tok_begin_line = p->line_no;
  33.331 +    p->tok_begin_char = p->char_no;
  33.332 +}
  33.333 +
  33.334 +int get_escape(char c, char *d){
  33.335 +    int err = 0;
  33.336 +    switch(c){
  33.337 +    case 'a':            *d = '\a'; break;
  33.338 +    case 'b':            *d = '\b'; break;
  33.339 +    case 'f':            *d = '\f'; break;
  33.340 +    case 'n':            *d = '\n'; break;
  33.341 +    case 'r':            *d = '\r'; break;
  33.342 +    case 't':            *d = '\t'; break;
  33.343 +    case 'v':            *d = '\v'; break;
  33.344 +    case c_escape:       *d = c_escape; break;
  33.345 +    case c_single_quote: *d = c_single_quote; break;
  33.346 +    case c_double_quote: *d = c_double_quote; break;
  33.347 +    default:
  33.348 +        err = -EINVAL;
  33.349 +    }
  33.350 +    return err;
  33.351 +}
  33.352 +
  33.353 +
  33.354 +int begin_start(Parser *p, char c){
  33.355 +    return Parser_push(p, state_start);
  33.356 +}
  33.357 +
  33.358 +int state_start(Parser *p, char c){
  33.359 +    int err = 0;
  33.360 +    if(at_eof(p)){
  33.361 +        err = end_start(p);
  33.362 +    } else if(in_space_class(c)){
  33.363 +        //skip
  33.364 +    } else if(in_comment_class(c)){
  33.365 +        begin_comment(p, c);
  33.366 +    } else if(c == c_list_open){
  33.367 +        begin_list(p, c);
  33.368 +    } else if(c == c_list_close){
  33.369 +        parse_error(p);
  33.370 +        err = -EINVAL;
  33.371 +    } else if(in_string_quote_class(c)){
  33.372 +        begin_string(p, c);
  33.373 +    } else if(in_printable_class(c)){
  33.374 +        begin_atom(p, c);
  33.375 +    } else if(c == 0x04){
  33.376 +        //ctrl-D, EOT: end-of-text.
  33.377 +        Parser_input_eof(p);
  33.378 +    } else {
  33.379 +        parse_error(p);
  33.380 +        err = -EINVAL;
  33.381 +    }
  33.382 +    return err;
  33.383 +}
  33.384 +
  33.385 +int end_start(Parser *p){
  33.386 +    int err = 0;
  33.387 +    err = Parser_return(p);
  33.388 +    return err;
  33.389 +}
  33.390 +
  33.391 +int begin_comment(Parser *p, char c){
  33.392 +    int err = 0;
  33.393 +    err = Parser_push(p, state_comment);
  33.394 +    if(err) goto exit;
  33.395 +    err = inputchar(p, c);
  33.396 +  exit:
  33.397 +    return err;
  33.398 +}
  33.399 +
  33.400 +int state_comment(Parser *p, char c){
  33.401 +    int err = 0;
  33.402 +    if(c == '\n' || at_eof(p)){
  33.403 +        err = end_comment(p);
  33.404 +    } else {
  33.405 +        err = inputchar(p, c);
  33.406 +    }
  33.407 +    return err;
  33.408 +}
  33.409 +
  33.410 +int end_comment(Parser *p){
  33.411 +    return Parser_pop(p);
  33.412 +}
  33.413 +
  33.414 +int begin_string(Parser *p, char c){
  33.415 +    int err = 0;
  33.416 +    err = Parser_push(p, state_string);
  33.417 +    if(err) goto exit;
  33.418 +    newtoken(p);
  33.419 +    p->state->delim = c;
  33.420 +  exit:
  33.421 +    return err;
  33.422 +}
  33.423 +
  33.424 +int state_string(Parser *p, char c){
  33.425 +    int err = 0;
  33.426 +    if(at_eof(p)){
  33.427 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.428 +        err = -EINVAL;
  33.429 +    } else if(c == p->state->delim){
  33.430 +        err = end_string(p);
  33.431 +    } else if(c == '\\'){
  33.432 +        err = Parser_push(p, state_escape);
  33.433 +    } else {
  33.434 +        err = savechar(p, c);
  33.435 +    }
  33.436 +    return err;
  33.437 +}
  33.438 +
  33.439 +int end_string(Parser *p){
  33.440 +    int err = 0;
  33.441 +    err = do_string(p);
  33.442 +    if(err) goto exit;
  33.443 +    err = Parser_return(p);
  33.444 +  exit:
  33.445 +    return err;
  33.446 +}
  33.447 +
  33.448 +int state_escape(Parser *p, char c){
  33.449 +    int err = 0;
  33.450 +    char d;
  33.451 +    if(at_eof(p)){
  33.452 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.453 +        err = -EINVAL;
  33.454 +        goto exit;
  33.455 +    }
  33.456 +    if(get_escape(c, &d) == 0){
  33.457 +        err = savechar(p, d);
  33.458 +        if(err) goto exit;
  33.459 +        err = Parser_pop(p);
  33.460 +    } else if(c == 'x'){
  33.461 +        p->state->fn = state_hex;
  33.462 +        p->state->ival = 0;
  33.463 +        p->state->count = 0;
  33.464 +    } else {
  33.465 +        p->state->fn = state_octal;
  33.466 +        p->state->ival = 0;
  33.467 +        p->state->count = 0;
  33.468 +        err = Parser_input_char(p, c);
  33.469 +    }
  33.470 +  exit:
  33.471 +    return err;
  33.472 +}
  33.473 +
  33.474 +int octaldone(Parser *p){
  33.475 +    int err = 0;
  33.476 +    char d = (char)(p->state->ival & 0xff);
  33.477 +    err = Parser_pop(p);
  33.478 +    if(err) goto exit;
  33.479 +    err = Parser_input_char(p, d);
  33.480 +  exit:
  33.481 +    return err;
  33.482 +}
  33.483 +
  33.484 +int octaldigit(Parser *p, char c){
  33.485 +    int err = 0;
  33.486 +    p->state->ival *= 8;
  33.487 +    p->state->ival += c - '0'; 
  33.488 +    p->state->count++;
  33.489 +    if(err) goto exit;
  33.490 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  33.491 +        parse_error(p);
  33.492 +        err = -EINVAL;
  33.493 +        goto exit;
  33.494 +    }
  33.495 +    if(p->state->count == 3){
  33.496 +        err = octaldone(p);
  33.497 +    }
  33.498 +  exit:
  33.499 +    return err;
  33.500 +}
  33.501 +
  33.502 +int state_octal(Parser *p, char c){
  33.503 +    int err = 0;
  33.504 +    if(at_eof(p)){
  33.505 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.506 +        err = -EINVAL;
  33.507 +        goto exit;
  33.508 +    } else if('0' <= c && c <= '7'){
  33.509 +        err = octaldigit(p, c);
  33.510 +    } else {
  33.511 +        err = octaldone(p);
  33.512 +        if(err) goto exit;
  33.513 +        Parser_input_char(p, c);
  33.514 +    }
  33.515 +  exit:
  33.516 +    return err;
  33.517 +}
  33.518 +
  33.519 +int hexdone(Parser *p){
  33.520 +    int err = 0;
  33.521 +    char d = (char)(p->state->ival & 0xff);
  33.522 +    err = Parser_pop(p);
  33.523 +    if(err) goto exit;
  33.524 +    err = Parser_input_char(p, d);
  33.525 +  exit:
  33.526 +    return err;
  33.527 +}
  33.528 +    
  33.529 +int hexdigit(Parser *p, char c, char d){
  33.530 +    int err = 0;
  33.531 +    p->state->ival *= 16;
  33.532 +    p->state->ival += c - d; 
  33.533 +    p->state->count++;
  33.534 +    if(err) goto exit;
  33.535 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  33.536 +        parse_error(p);
  33.537 +        err = -EINVAL;
  33.538 +        goto exit;
  33.539 +    }
  33.540 +    if(p->state->count == 2){
  33.541 +        err = hexdone(p);
  33.542 +    }
  33.543 +  exit:
  33.544 +    return err;
  33.545 +}
  33.546 +    
  33.547 +int state_hex(Parser *p, char c){
  33.548 +    int err = 0;
  33.549 +    if(at_eof(p)){
  33.550 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.551 +        err = -EINVAL;
  33.552 +        goto exit;
  33.553 +    } else if('0' <= c && c <= '9'){
  33.554 +        err = hexdigit(p, c, '0');
  33.555 +    } else if('A' <= c && c <= 'F'){
  33.556 +        err = hexdigit(p, c, 'A');
  33.557 +    } else if('a' <= c && c <= 'f'){
  33.558 +        err = hexdigit(p, c, 'a');
  33.559 +    } else if(p->state->count){
  33.560 +        err =hexdone(p);
  33.561 +        if(err) goto exit;
  33.562 +        Parser_input_char(p, c);
  33.563 +    }
  33.564 +  exit:
  33.565 +    return err;
  33.566 +}
  33.567 +
  33.568 +int begin_atom(Parser *p, char c){
  33.569 +    int err = 0;
  33.570 +    err = Parser_push(p, state_atom);
  33.571 +    if(err) goto exit;
  33.572 +    newtoken(p);
  33.573 +    err = savechar(p, c);
  33.574 +  exit:
  33.575 +    return err;
  33.576 +}
  33.577 +
  33.578 +int state_atom(Parser *p, char c){
  33.579 +    int err = 0;
  33.580 +    if(at_eof(p)){
  33.581 +        err = end_atom(p);
  33.582 +    } else if(is_separator(p, c) ||
  33.583 +              in_space_class(c) ||
  33.584 +              in_comment_class(c)){
  33.585 +        err = end_atom(p);
  33.586 +        if(err) goto exit;
  33.587 +        err = Parser_input_char(p, c);
  33.588 +    } else {
  33.589 +        err = savechar(p, c);
  33.590 +    }
  33.591 +  exit:
  33.592 +    return err;
  33.593 +}
  33.594 +
  33.595 +int end_atom(Parser *p){
  33.596 +    int err = 0;
  33.597 +    err = do_intern(p);
  33.598 +    if(err) goto exit;
  33.599 +    err = Parser_return(p);
  33.600 +  exit:
  33.601 +    return err;
  33.602 +}
  33.603 +
  33.604 +int state_list(Parser *p, char c){
  33.605 +    int err = 0;
  33.606 +    if(at_eof(p)){
  33.607 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.608 +        err = -EINVAL;
  33.609 +    } else if(c == c_list_close){
  33.610 +        p->state->val = nrev(p->state->val);
  33.611 +        err = end_list(p);
  33.612 +    } else {
  33.613 +        err = state_start(p, c);
  33.614 +    }
  33.615 +    return err;
  33.616 +    
  33.617 +}
  33.618 +
  33.619 +int begin_list(Parser *p, char c){
  33.620 +    return Parser_push(p, state_list);
  33.621 +}
  33.622 +
  33.623 +int end_list(Parser *p){
  33.624 +    return Parser_return(p);
  33.625 +}
  33.626 +
  33.627 +/** Reset the fields of a parser to initial values.
  33.628 + *
  33.629 + * @param z parser
  33.630 + */
  33.631 +static void reset(Parser *z){
  33.632 +  IOStream *error_out = z->error_out;
  33.633 +  int flags = z->flags;
  33.634 +  zero(z, sizeof(Parser));
  33.635 +  z->buf_n = sizeof(z->buf) - 1;
  33.636 +  z->buf_i = 0;
  33.637 +  z->line_no = 1;
  33.638 +  z->char_no = 0;
  33.639 +  z->error_out = error_out;
  33.640 +  z->flags = flags;
  33.641 +}
  33.642 +
  33.643 +/** Set the parser error stream.
  33.644 + * Parse errors are reported on the the error stream if it is non-null.
  33.645 + * 
  33.646 + * @param z parser
  33.647 + * @param error_out error stream
  33.648 + */
  33.649 +void set_error_stream(Parser *z, IOStream *error_out){
  33.650 +  if(z){
  33.651 +    z->error_out = error_out;
  33.652 +  }
  33.653 +}
  33.654 +
  33.655 +/** Get the parser error message for an error code.
  33.656 + *
  33.657 + * @param id error code
  33.658 + * @return error message (empty string if the code is unknown)
  33.659 + */
  33.660 +static char *get_message(ParseErrorId id){
  33.661 +  int i;
  33.662 +  for(i=0; i<catalog_n; i++){
  33.663 +    if(id == catalog[i].id){
  33.664 +      return catalog[i].message;
  33.665 +    }
  33.666 +  }
  33.667 +  return "";
  33.668 +}
  33.669 +
  33.670 +/** Get the line number.
  33.671 + *
  33.672 + * @param in parser
  33.673 + */
  33.674 +int get_line(Parser *in){
  33.675 +  return in->line_no;
  33.676 +}
  33.677 +
  33.678 +/** Get the column number.
  33.679 + *
  33.680 + * @param in parser
  33.681 + */
  33.682 +int get_column(Parser *in){
  33.683 +  return in->char_no;
  33.684 +}
  33.685 +
  33.686 +/** Get the line number the current token started on.
  33.687 + *
  33.688 + * @param in parser
  33.689 + */
  33.690 +int get_tok_line(Parser *in){
  33.691 +  return in->tok_begin_line;
  33.692 +}
  33.693 +
  33.694 +/** Get the column number the current token started on.
  33.695 + *
  33.696 + * @param in parser
  33.697 + */
  33.698 +int get_tok_column(Parser *in){
  33.699 +  return in->tok_begin_char;
  33.700 +}
  33.701 +
  33.702 +/** Report a parse error.
  33.703 + * Does nothing if the error stream is null or there is no error.
  33.704 + *
  33.705 + * @param in parser
  33.706 + */
  33.707 +static void report_error(Parser *in){
  33.708 +  if(in->error_out && in->err){
  33.709 +    char *msg = get_message(in->err);
  33.710 +    char *tok = peek_token(in);
  33.711 +    IOStream_print(in->error_out, PARSE_ERR_FMT,
  33.712 +		   get_tok_line(in), get_tok_column(in), msg);
  33.713 +    if(tok && tok[0]){
  33.714 +        IOStream_print(in->error_out, " '%s'", tok);
  33.715 +    }
  33.716 +    IOStream_print(in->error_out, "\n");
  33.717 +  }
  33.718 +}
  33.719 +
  33.720 +/** Get the error message for the current parse error code.
  33.721 + * Does nothing if there is no error.
  33.722 + *
  33.723 + * @param in parser
  33.724 + * @param buf where to place the message
  33.725 + * @param n maximum number of characters to place in buf
  33.726 + * @return current error code (zero for no error)
  33.727 + */
  33.728 +int parse_error_message(Parser *in, char *buf, int n){
  33.729 +    if(in->err){
  33.730 +        char *msg = get_message(in->err);
  33.731 +        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
  33.732 +    }
  33.733 +    return in->err;
  33.734 +}
  33.735 +
  33.736 +/** Flag an unspecified parse error. All subsequent reads will fail.
  33.737 + *
  33.738 + * @param in parser
  33.739 + */
  33.740 +void parse_error(Parser *in){
  33.741 +    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
  33.742 +}
  33.743 +
  33.744 +/** Flag a parse error. All subsequent reads will fail.
  33.745 + * Does not change the parser error code if it is already set.
  33.746 + *
  33.747 + * @param in parser
  33.748 + * @param id error code
  33.749 + */
  33.750 +void parse_error_id(Parser *in, ParseErrorId id){
  33.751 +    if(!in->err){
  33.752 +        in->err = id;
  33.753 +        report_error(in);
  33.754 +    }
  33.755 +}
  33.756 +
  33.757 +/** Test if the parser's error flag is set.
  33.758 + *
  33.759 + * @param in parser
  33.760 + * @return 1 if set, 0 otherwise
  33.761 + */
  33.762 +int has_error(Parser *in){
  33.763 +    return (in->err > 0);
  33.764 +}
  33.765 +
  33.766 +/** Test if the parser is at end of input.
  33.767 + *
  33.768 + * @param in parser
  33.769 + * @return 1 if at EOF, 0 otherwise
  33.770 + */
  33.771 +int at_eof(Parser *p){
  33.772 +    return p->eof;
  33.773 +}
  33.774 +
  33.775 +#ifdef SXPR_PARSER_MAIN
  33.776 +/* Stuff for standalone testing. */
  33.777 +
  33.778 +#include "file_stream.h"
  33.779 +#include "string_stream.h"
  33.780 +
  33.781 +int stringof(Sxpr exp, char **s){
  33.782 +    int err = 0;
  33.783 +    if(ATOMP(exp)){
  33.784 +        *s = atom_name(exp);
  33.785 +    } else if(STRINGP(exp)){
  33.786 +        *s = string_string(exp);
  33.787 +    } else {
  33.788 +        err = -EINVAL;
  33.789 +        *s = NULL;
  33.790 +    }
  33.791 +    return err;
  33.792 +}
  33.793 +
  33.794 +int child_string(Sxpr exp, Sxpr key, char **s){
  33.795 +    int err = 0;
  33.796 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  33.797 +    err = stringof(val, s);
  33.798 +    return err;
  33.799 +}
  33.800 +
  33.801 +int intof(Sxpr exp, int *v){
  33.802 +    int err = 0;
  33.803 +    char *s;
  33.804 +    unsigned long l;
  33.805 +    if(INTP(exp)){
  33.806 +        *v = OBJ_INT(exp);
  33.807 +    } else {
  33.808 +        err = stringof(exp, &s);
  33.809 +        if(err) goto exit;
  33.810 +        err = convert_atoul(s, &l);
  33.811 +        *v = (int)l;
  33.812 +    }
  33.813 + exit:
  33.814 +    return err;
  33.815 +}
  33.816 +
  33.817 +int child_int(Sxpr exp, Sxpr key, int *v){
  33.818 +    int err = 0;
  33.819 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  33.820 +    err = intof(val, v);
  33.821 +    return err;
  33.822 +}
  33.823 +
  33.824 +int eval_vnet(Sxpr exp){
  33.825 +    int err = 0;
  33.826 +    Sxpr oid = intern("id");
  33.827 +    int id;
  33.828 +    err = child_int(exp, oid, &id);
  33.829 +    if(err) goto exit;
  33.830 +    dprintf("> vnet id=%d\n", id);
  33.831 + exit:
  33.832 +    dprintf("< err=%d\n", err);
  33.833 +    return err;
  33.834 +}
  33.835 +
  33.836 +int eval_connect(Sxpr exp){
  33.837 +    int err = 0;
  33.838 +    Sxpr ovif = intern("vif");
  33.839 +    Sxpr ovnet = intern("vnet");
  33.840 +    char *vif;
  33.841 +    int vnet;
  33.842 +
  33.843 +    err = child_string(exp, ovif, &vif);
  33.844 +    if(err) goto exit;
  33.845 +    err = child_int(exp, ovnet, &vnet);
  33.846 +    if(err) goto exit;
  33.847 +    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
  33.848 + exit:
  33.849 +    dprintf("< err=%d\n", err);
  33.850 +    return err;
  33.851 +}
  33.852 +
  33.853 +int eval(Sxpr exp){
  33.854 +    int err = 0;
  33.855 +    Sxpr oconnect = intern("connect");
  33.856 +    Sxpr ovnet = intern("vnet");
  33.857 +    
  33.858 +    if(sxpr_elementp(exp, ovnet)){
  33.859 +        err = eval_vnet(exp);
  33.860 +    } else if(sxpr_elementp(exp, oconnect)){
  33.861 +        err = eval_connect(exp);
  33.862 +    } else {
  33.863 +        err = -EINVAL;
  33.864 +    }
  33.865 +    return err;
  33.866 +}
  33.867 +
  33.868 +/** Main program for testing.
  33.869 + * Parses input and prints it.
  33.870 + *
  33.871 + * @param argc number of arguments
  33.872 + * @param argv arguments
  33.873 + * @return error code
  33.874 + */
  33.875 +int main(int argc, char *argv[]){
  33.876 +    Parser *pin;
  33.877 +    int err = 0;
  33.878 +    char buf[1024];
  33.879 +    int k;
  33.880 +    Sxpr obj, l, x;
  33.881 +
  33.882 +    pin = Parser_new();
  33.883 +    set_error_stream(pin, iostdout);
  33.884 +    dprintf("> parse...\n");
  33.885 +    while(1){
  33.886 +        k = fread(buf, 1, 1024, stdin);
  33.887 +        err = Parser_input(pin, buf, k);
  33.888 +        dprintf("> Parser_input=%d\n", err);
  33.889 +        if(k <= 0) break;
  33.890 +    }
  33.891 +    obj = pin->val;
  33.892 +    for(l = obj ; CONSP(l); l = CDR(l)){
  33.893 +        x = CAR(l);
  33.894 +        objprint(iostdout, x, 0); printf("\n");
  33.895 +        eval(x);
  33.896 +    }
  33.897 +    dprintf("> err=%d\n", err);
  33.898 +    return 0;
  33.899 +}
  33.900 +#endif
    34.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.2 +++ b/tools/lib/sxpr_parser.h	Tue Jun 29 12:05:29 2004 +0000
    34.3 @@ -0,0 +1,125 @@
    34.4 +/*
    34.5 + *
    34.6 + * This library is free software; you can redistribute it and/or modify
    34.7 + * it under the terms of the GNU Lesser General Public License as
    34.8 + * published by the Free Software Foundation; either version 2.1 of the
    34.9 + * License, or  (at your option) any later version. This library is 
   34.10 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   34.11 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   34.12 + * FITNESS FOR A PARTICULAR PURPOSE.
   34.13 + * See the GNU Lesser General Public License for more details.
   34.14 + *
   34.15 + * You should have received a copy of the GNU Lesser General Public License
   34.16 + * along with this library; if not, write to the Free Software Foundation,
   34.17 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   34.18 + */
   34.19 +
   34.20 +#ifndef _XEN_LIB_SXPR_PARSER_H_
   34.21 +#define _XEN_LIB_SXPR_PARSER_H_
   34.22 +
   34.23 +#include "sxpr.h"
   34.24 +#include "iostream.h"
   34.25 +
   34.26 +/** @file
   34.27 + * Sxpr parsing definitions.
   34.28 + */
   34.29 +
   34.30 +/** Size of a parser input buffer.
   34.31 + * Tokens read must fit into this size (including trailing null).
   34.32 + */
   34.33 +#define PARSER_BUF_SIZE 1024
   34.34 +
   34.35 +struct Parser;
   34.36 +typedef int ParserStateFn(struct Parser *, char c);
   34.37 +
   34.38 +typedef struct ParserState {
   34.39 +    struct ParserState *parent;
   34.40 +    Sxpr val;
   34.41 +    int ival;
   34.42 +    int count;
   34.43 +    char delim;
   34.44 +    ParserStateFn *fn;
   34.45 +} ParserState;
   34.46 +
   34.47 +/** Structure representing an input source for the parser.
   34.48 + * Can read from any IOStream implementation.
   34.49 + */
   34.50 +typedef struct Parser {
   34.51 +    Sxpr val;
   34.52 +    /** Error reporting stream (null for no reports). */
   34.53 +    IOStream *error_out;
   34.54 +    int eof;
   34.55 +    /** Error flag. Non-zero if there has been a read error. */
   34.56 +    int err;
   34.57 +    /** Line number on input (from 1). */
   34.58 +    int line_no;
   34.59 +    /** Column number of input (reset on new line). */
   34.60 +    int char_no;
   34.61 +    /** Lookahead character. */
   34.62 +    char c;
   34.63 +    /** Buffer for reading tokens. */
   34.64 +    char buf[PARSER_BUF_SIZE];
   34.65 +    /** Size of token buffer. */
   34.66 +    int buf_n;
   34.67 +    int buf_i;
   34.68 +    /** Line the last token started on. */
   34.69 +    int tok_begin_line;
   34.70 +    /** Character number the last token started on. */
   34.71 +    int tok_begin_char;
   34.72 +    /** Parsing flags. */
   34.73 +    int flags;
   34.74 +    ParserState *state;
   34.75 +} Parser;
   34.76 +
   34.77 +/** Parser error codes. */
   34.78 +typedef enum {
   34.79 +    PARSE_ERR_NONE=0,
   34.80 +    PARSE_ERR_UNSPECIFIED,
   34.81 +    PARSE_ERR_NOMEM,
   34.82 +    PARSE_ERR_UNEXPECTED_EOF,
   34.83 +    PARSE_ERR_TOKEN_TOO_LONG,
   34.84 +    PARSE_ERR_INVALID_SYNTAX,
   34.85 +    PARSE_ERR_INVALID_ESCAPE,
   34.86 +} ParseErrorId;
   34.87 +
   34.88 +
   34.89 +/** Parser flags. */
   34.90 +//enum {
   34.91 +//};
   34.92 +
   34.93 +/** Raise some parser flags.
   34.94 + *
   34.95 + * @param in parser
   34.96 + * @param flags flags mask
   34.97 + */
   34.98 +inline static void parser_flags_raise(Parser *in, int flags){
   34.99 +    in->flags |= flags;
  34.100 +}
  34.101 +
  34.102 +/** Lower some parser flags.
  34.103 + *
  34.104 + * @param in parser
  34.105 + * @param flags flags mask
  34.106 + */
  34.107 +inline static void parser_flags_lower(Parser *in, int flags){
  34.108 +    in->flags &= ~flags;
  34.109 +}
  34.110 +
  34.111 +/** Clear all parser flags.
  34.112 + *
  34.113 + * @param in parser
  34.114 + */
  34.115 +inline static void parser_flags_clear(Parser *in){
  34.116 +    in->flags = 0;
  34.117 +}
  34.118 +
  34.119 +extern void Parser_free(Parser *z);
  34.120 +extern Parser * Parser_new(void);
  34.121 +extern int Parser_input(Parser *p, char *buf, int buf_n);
  34.122 +extern int Parser_input_eof(Parser *p);
  34.123 +
  34.124 +extern int parse_error_message(Parser *in, char *buf, int n);
  34.125 +extern int has_error(Parser *in);
  34.126 +extern int at_eof(Parser *in);
  34.127 +
  34.128 +#endif /* ! _XEN_LIB_SXPR_PARSER_H_ */
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/tools/lib/sys_ctype.h	Tue Jun 29 12:05:29 2004 +0000
    35.3 @@ -0,0 +1,12 @@
    35.4 +#ifndef _XENO_SYS_CTYPE_H_
    35.5 +#define _XENO_SYS_CTYPE_H_
    35.6 +/** @file
    35.7 + ** Replacement for ctype include that can be used
    35.8 + * from user or kernel code.
    35.9 + */
   35.10 +#ifdef __KERNEL__
   35.11 +#  include <linux/ctype.h>
   35.12 +#else
   35.13 +#  include <ctype.h>
   35.14 +#endif
   35.15 +#endif /* ! _XENO_SYS_CTYPE_H_ */
    36.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    36.2 +++ b/tools/lib/sys_net.c	Tue Jun 29 12:05:29 2004 +0000
    36.3 @@ -0,0 +1,309 @@
    36.4 +/*
    36.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    36.6 + *
    36.7 + * This library is free software; you can redistribute it and/or modify
    36.8 + * it under the terms of the GNU Lesser General Public License as
    36.9 + * published by the Free Software Foundation; either version 2.1 of the
   36.10 + * License, or  (at your option) any later version. This library is 
   36.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   36.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   36.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   36.14 + * See the GNU Lesser General Public License for more details.
   36.15 + *
   36.16 + * You should have received a copy of the GNU Lesser General Public License
   36.17 + * along with this library; if not, write to the Free Software Foundation,
   36.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   36.19 + */
   36.20 +
   36.21 +#include "sys_net.h"
   36.22 +#include "sys_string.h"
   36.23 +
   36.24 +/** @file
   36.25 + * All network data are kept in network order and only converted to
   36.26 + * host order for display. Network data includes IP addresses, port numbers and
   36.27 + * network masks.
   36.28 + */
   36.29 +
   36.30 +/** Maximum value for a port. */
   36.31 +#define PORT_MAX 0xffff
   36.32 +
   36.33 +/** Convert a number of bits to a network mask
   36.34 + * for IP addresses. The number of bits must
   36.35 + * be in the range 1-31.
   36.36 + *
   36.37 + * @param n number of bits to set in the mask
   36.38 + * @return value with n high bits set (in network order)
   36.39 + */
   36.40 +unsigned long bits_to_mask(int n){
   36.41 +    unsigned long mask = (n ? (1 << 31) : 0);
   36.42 +    int i;
   36.43 +    for(i=1; i<n; i++){
   36.44 +        mask |= (mask >> 1);
   36.45 +    }
   36.46 +    return htonl(mask);
   36.47 +}
   36.48 +
   36.49 +/** Convert a network mask to a number of bits.
   36.50 + *
   36.51 + * @param mask network mask in network order
   36.52 + * @return number of bits in mask
   36.53 + */
   36.54 +int mask_to_bits(unsigned long mask){
   36.55 +    // Start with n set to the number of bits in the mask. Then reduce n by
   36.56 +    // the number of low zero bits in the mask.
   36.57 +    int n = 32;
   36.58 +    for(mask = ntohl(mask);
   36.59 +        (mask & 1)==0 && n>0;
   36.60 +        mask >>= 1){
   36.61 +        n--;
   36.62 +    }
   36.63 +    return n;
   36.64 +}
   36.65 +
   36.66 +/** Get the index of the first occurrence of a character in a string.
   36.67 + * Stops at end of string or after n characters.
   36.68 + *
   36.69 + * @param s input string
   36.70 + * @param n maximum number of charactes to search
   36.71 + * @param c character to look for
   36.72 + * @return index of first occurrence, -1 if not found
   36.73 + */
   36.74 +inline static int indexof(const char *s, int n, char c){
   36.75 +    int i;
   36.76 +    for(i=0; i<n && *s; i++, s++){
   36.77 +        if(*s == c) return i;
   36.78 +    }
   36.79 +    return -1;
   36.80 +}
   36.81 +
   36.82 +/** Convert an IPv4 address in dot notation into an unsigned long (in network order).
   36.83 + *
   36.84 + * @param s input string
   36.85 + * @param address where to put the address
   36.86 + * @return 0 on success, -1 on error
   36.87 + */
   36.88 +int get_inet_addr(const char *s, unsigned long *address){
   36.89 +    // Number of bits in a byte.
   36.90 +    const int BYTE_BITS = 8;
   36.91 +    // Number of bytes in a word.
   36.92 +    const int WORD_BYTES = 4;
   36.93 +    // Max value for a component of an address.
   36.94 +    const int ADDR_MAX  = 255;
   36.95 +    // Separator for components of an address.
   36.96 +    const char dot = '.';
   36.97 +
   36.98 +    int n;
   36.99 +    unsigned long addr = 0;
  36.100 +    unsigned long v;
  36.101 +    int i;
  36.102 +    int err = -1;
  36.103 +    // Bit shift for the current byte.
  36.104 +    int shift = BYTE_BITS * (WORD_BYTES - 1);
  36.105 +    char buf[64];
  36.106 +
  36.107 +    n = strlen(s);
  36.108 +    if(n >= sizeof(buf)){
  36.109 +        goto exit;
  36.110 +    }
  36.111 +    for(i=0; i < WORD_BYTES; i++){
  36.112 +        int idx = indexof(s, n, dot);
  36.113 +        idx = (idx < 0 ? strlen(s) : idx);
  36.114 +        strncpy(buf, s, idx); buf[idx]='\0';
  36.115 +        if(convert_atoul(buf, &v)){
  36.116 +            goto exit;
  36.117 +        }
  36.118 +        if(v < 0 || v > ADDR_MAX){
  36.119 +            goto exit;
  36.120 +        }
  36.121 +        addr |= (v << shift);
  36.122 +        if(idx == n) break;
  36.123 +        shift -= BYTE_BITS;
  36.124 +        s += idx+1;
  36.125 +    }
  36.126 +    err = 0;
  36.127 +  exit:
  36.128 +    addr = htonl(addr);
  36.129 +    *address = (err ? 0 : addr);
  36.130 +    return err;
  36.131 +}
  36.132 +
  36.133 +#ifdef __KERNEL__
  36.134 +/** Convert an address in network order to IPv4 dot notation.
  36.135 + * The return value is a static buffer which is overwritten on each call.
  36.136 + *
  36.137 + * @param inaddr address (in network order)
  36.138 + * @return address in dot notation
  36.139 + */
  36.140 +char *inet_ntoa(struct in_addr inaddr){
  36.141 +    static char address[16] = {};
  36.142 +    uint32_t addr = ntohl(inaddr.s_addr);
  36.143 +    snprintf(address, sizeof(address), "%d.%d.%d.%d",
  36.144 +            (unsigned)((addr >> 24) & 0xff),
  36.145 +            (unsigned)((addr >> 16) & 0xff),
  36.146 +            (unsigned)((addr >>  8) & 0xff),
  36.147 +            (unsigned)((addr      ) & 0xff));
  36.148 +    return address;
  36.149 +}
  36.150 +
  36.151 +
  36.152 +/** Convert a string in IPv4 dot notation to an int in network order.
  36.153 + *
  36.154 + * @param address address in dot notation
  36.155 + * @param inp result of conversion (in network order)
  36.156 + * @return 0 on success, error code on error
  36.157 + */
  36.158 +int inet_aton(const char *address, struct in_addr *inp){
  36.159 +    int err = 0; 
  36.160 +    unsigned long addr;
  36.161 +    
  36.162 +    err = get_inet_addr(address, &addr);
  36.163 +    if(err) goto exit;
  36.164 +    inp->s_addr = addr;
  36.165 +  exit:
  36.166 +    return err;
  36.167 +}
  36.168 +#endif
  36.169 +
  36.170 +/** Convert a hostname or IPv4 address string to an address in network order.
  36.171 + *
  36.172 + * @param name input hostname or address string
  36.173 + * @param address where to put the address
  36.174 + * @return 1 if address found OK, 0 otherwise
  36.175 + */
  36.176 +int get_host_address(const char *name, unsigned long *address){
  36.177 +#ifdef __KERNEL__
  36.178 +    return get_inet_addr(name, address) == 0;
  36.179 +#else
  36.180 +    struct hostent *host = gethostbyname(name);
  36.181 +    if(!host){
  36.182 +        return 0;
  36.183 +    }
  36.184 +    *address = ((struct in_addr *)(host->h_addr))->s_addr;
  36.185 +    return 1;
  36.186 +#endif
  36.187 +}
  36.188 +
  36.189 +/** Convert a service name to a port (in network order).
  36.190 + *
  36.191 + * @param name service name
  36.192 + * @param port where to put the port
  36.193 + * @return 1 if service port found OK, 0 otherwise
  36.194 + */
  36.195 +int get_service_port(const char *name, unsigned long *port){
  36.196 +#ifdef __KERNEL__
  36.197 +    return 0;
  36.198 +#else
  36.199 +    struct servent *service;
  36.200 +    service = getservbyname(name, 0);
  36.201 +    if(!service){
  36.202 +        return 0;
  36.203 +    }
  36.204 +    *port = service->s_port;
  36.205 +    return 1;
  36.206 +#endif
  36.207 +}
  36.208 +
  36.209 +/** Convert a port number (in network order) to a service name.
  36.210 + *
  36.211 + * @param port the port number
  36.212 + * @return service name if found OK, 0 otherwise
  36.213 + */
  36.214 +char *get_port_service(unsigned long port){
  36.215 +#ifdef __KERNEL__
  36.216 +    return 0;
  36.217 +#else
  36.218 +    struct servent *service = getservbyport(port, 0);
  36.219 +    return (service ? service->s_name : 0);
  36.220 +#endif
  36.221 +}
  36.222 +
  36.223 +/** Convert a decimal integer or service name to a port (in network order).
  36.224 + *
  36.225 + * @param s input to convert
  36.226 + * @param port where to put the port
  36.227 + * @return 1 if port found OK, 0 otherwise
  36.228 + */
  36.229 +int convert_service_to_port(const char *s, unsigned long *port){
  36.230 +    int ok = 0;
  36.231 +    unsigned long value;
  36.232 +    if(convert_atoul(s, &value)){
  36.233 +        ok = get_service_port(s, &value);
  36.234 +    } else {
  36.235 +        ok = (0 <= value) && (value <= PORT_MAX);
  36.236 +        value = htons((unsigned short)value);
  36.237 +    }
  36.238 +    *port = (ok ? value : 0);
  36.239 +    return ok;
  36.240 +}
  36.241 +
  36.242 +#define MAC_ELEMENT_N  6 // Number of elements in a MAC address.
  36.243 +#define MAC_DIGIT_N    2 // Number of digits in an element in a MAC address.
  36.244 +#define MAC_LENGTH    17 //((MAC_ELEMENT_N * MAC_DIGIT_N) + MAC_ELEMENT_N - 1)
  36.245 +
  36.246 +/** Convert a mac address from a string of the form
  36.247 + * XX:XX:XX:XX:XX:XX to numerical form (an array of 6 unsigned chars).
  36.248 + * Each X denotes a hex digit: 0..9, a..f, A..F.
  36.249 + * Also supports using '-' as the separator instead of ':'.
  36.250 + *
  36.251 + * @param mac_in string to convert
  36.252 + * @param mac destination for the value
  36.253 + * @return 0 on success, -1 on error
  36.254 + */
  36.255 +int mac_aton(const char *mac_in, unsigned char *mac){
  36.256 +    int err = 0;
  36.257 +    int i, j;
  36.258 +    const char *p;
  36.259 +    char sep = 0;
  36.260 +    unsigned char d;
  36.261 +    if(!mac_in || strlen(mac_in) != MAC_LENGTH){
  36.262 +        err = -1;
  36.263 +        goto exit;
  36.264 +    }
  36.265 +    for(i = 0, p = mac_in; i < MAC_ELEMENT_N; i++){
  36.266 +        d = 0;
  36.267 +        if(i){
  36.268 +            if(!sep){
  36.269 +                if(*p == ':' || *p == '-') sep = *p;
  36.270 +            }
  36.271 +            if(sep && *p == sep){
  36.272 +                p++;
  36.273 +            } else {
  36.274 +                err = -1;
  36.275 +                goto exit;
  36.276 +            }
  36.277 +        }
  36.278 +        for(j = 0; j < MAC_DIGIT_N; j++, p++){
  36.279 +            if(j) d <<= 4;
  36.280 +            if(*p >= '0' && *p <= '9'){
  36.281 +                d += (*p - '0');
  36.282 +            } else if(*p >= 'A' && *p <= 'F'){
  36.283 +                d += (*p - 'A') + 10;
  36.284 +            } else if(*p >= 'a' && *p <= 'f'){
  36.285 +                d += (*p - 'a') + 10;
  36.286 +            } else {
  36.287 +                err = -1;
  36.288 +                goto exit;
  36.289 +            }
  36.290 +        }
  36.291 +        mac[i] = d;
  36.292 +    }
  36.293 +  exit:
  36.294 +    return err;
  36.295 +}
  36.296 +
  36.297 +/** Convert a MAC address from numerical form to a string.
  36.298 + *
  36.299 + * @param mac address to convert
  36.300 + * @return static string value
  36.301 + */
  36.302 +char *mac_ntoa(const unsigned char *mac){
  36.303 +    static char buf[MAC_LENGTH + 1];
  36.304 +    int buf_n = sizeof(buf);
  36.305 +
  36.306 +    memset(buf, buf_n, 0);
  36.307 +    snprintf(buf, buf_n, "%02x:%02x:%02x:%02x:%02x:%02x",
  36.308 +             mac[0], mac[1], mac[2],
  36.309 +             mac[3], mac[4], mac[5]);
  36.310 +    buf[buf_n - 1] = '\0';
  36.311 +    return buf;
  36.312 +}
    37.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    37.2 +++ b/tools/lib/sys_net.h	Tue Jun 29 12:05:29 2004 +0000
    37.3 @@ -0,0 +1,78 @@
    37.4 +/*
    37.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    37.6 + *
    37.7 + * This library is free software; you can redistribute it and/or modify
    37.8 + * it under the terms of the GNU Lesser General Public License as published by
    37.9 + * the Free Software Foundation; either version 2.1 of the License, or
   37.10 + * (at your option) any later version.
   37.11 + *
   37.12 + * This library is distributed in the hope that it will be useful,
   37.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   37.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   37.15 + * GNU Lesser General Public License for more details.
   37.16 + *
   37.17 + * You should have received a copy of the GNU Lesser General Public License
   37.18 + * along with this library; if not, write to the Free Software
   37.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   37.20 + */
   37.21 +
   37.22 +#ifndef _XEN_LIB_SYS_NET_H_
   37.23 +#define _XEN_LIB_SYS_NET_H_
   37.24 +/** @file
   37.25 + *
   37.26 + * Replacement for standard network includes.
   37.27 + * Works in user or kernel code.
   37.28 + */
   37.29 +
   37.30 +extern int get_inet_addr(const char *s, unsigned long *address);
   37.31 +extern unsigned long bits_to_mask(int n);
   37.32 +extern int mask_to_bits(unsigned long mask);
   37.33 +extern int get_host_address(const char *name, unsigned long *address);
   37.34 +extern int get_service_port(const char *name, unsigned long *port);
   37.35 +extern char *get_port_service(unsigned long port);
   37.36 +extern int convert_service_to_port(const char *s, unsigned long *port);
   37.37 +
   37.38 +#ifdef __KERNEL__
   37.39 +#include <linux/kernel.h>
   37.40 +#include <linux/types.h>
   37.41 +#include <linux/errno.h>
   37.42 +#include <linux/slab.h>
   37.43 +#include <asm/byteorder.h> 
   37.44 +
   37.45 +#ifndef htonl
   37.46 +#define htonl(x) __constant_htonl(x)
   37.47 +#endif
   37.48 +
   37.49 +#ifndef ntohl
   37.50 +#define ntohl(x) __constant_ntohl(x)
   37.51 +#endif
   37.52 +
   37.53 +#ifndef htons
   37.54 +#define htons(x) __constant_htons(x)
   37.55 +#endif
   37.56 +
   37.57 +#ifndef ntohs
   37.58 +#define ntohs(x) __constant_ntohs(x)
   37.59 +#endif
   37.60 +
   37.61 +#include <linux/in.h>
   37.62 +extern char *inet_ntoa(struct in_addr inaddr);
   37.63 +extern int inet_aton(const char *address, struct in_addr *inp);
   37.64 +
   37.65 +#else
   37.66 +
   37.67 +#include <limits.h>
   37.68 +#include <sys/socket.h>
   37.69 +#include <netinet/in.h>
   37.70 +#include <netdb.h>
   37.71 +#include <arpa/inet.h>
   37.72 +
   37.73 +#endif
   37.74 +
   37.75 +extern char *mac_ntoa(const unsigned char *macaddr);
   37.76 +extern int mac_aton(const char *addr, unsigned char *macaddr);
   37.77 +
   37.78 +#endif /* !_SP_SYS_NET_H_ */
   37.79 +
   37.80 +
   37.81 +
    38.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    38.2 +++ b/tools/lib/sys_string.c	Tue Jun 29 12:05:29 2004 +0000
    38.3 @@ -0,0 +1,138 @@
    38.4 +/*
    38.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    38.6 + *
    38.7 + * This library is free software; you can redistribute it and/or modify
    38.8 + * it under the terms of the GNU Lesser General Public License as published by
    38.9 + * the Free Software Foundation; either version 2.1 of the License, or
   38.10 + * (at your option) any later version.
   38.11 + *
   38.12 + * This library is distributed in the hope that it will be useful,
   38.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   38.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   38.15 + * GNU Lesser General Public License for more details.
   38.16 + *
   38.17 + * You should have received a copy of the GNU Lesser General Public License
   38.18 + * along with this library; if not, write to the Free Software
   38.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   38.20 + */
   38.21 +
   38.22 +#ifdef __KERNEL__
   38.23 +#  include <linux/config.h>
   38.24 +#  include <linux/module.h>
   38.25 +#  include <linux/kernel.h>
   38.26 +#  include <linux/errno.h>
   38.27 +#else
   38.28 +#  include <errno.h>
   38.29 +#endif
   38.30 +
   38.31 +#include "allocate.h"
   38.32 +#include "sys_string.h"
   38.33 +
   38.34 +/** Set the base to use for converting a string to a number.  Base is
   38.35 + * hex if starts with 0x, otherwise decimal.
   38.36 + *
   38.37 + * @param s input string
   38.38 + * @param base where to put the base
   38.39 + * @return rest of s to parse as a number
   38.40 + */
   38.41 +inline static const char * convert_set_base(const char *s, int *base){
   38.42 +    *base = 10;
   38.43 +    if(s){
   38.44 +        if(*s=='0'){
   38.45 +            s++;
   38.46 +            if(*s=='x' || *s=='X'){
   38.47 +                *base = 16;
   38.48 +                s++;
   38.49 +            }
   38.50 +        }
   38.51 +    }
   38.52 +    return s;
   38.53 +}
   38.54 +
   38.55 +/** Get the numerical value of a digit in the given base.
   38.56 + *
   38.57 + * @param c digit character
   38.58 + * @param base to use
   38.59 + * @return numerical value of digit in range 0..base-1 or
   38.60 + * -1 if not in range for the base
   38.61 + */
   38.62 +inline static int convert_get_digit(char c, int base){
   38.63 +    int d;
   38.64 +
   38.65 +    if('0'<=c  && c<='9'){
   38.66 +        d = c - '0';
   38.67 +    } else if('a'<=c && c<='f'){
   38.68 +        d = c - 'a' + 10;
   38.69 +    } else if('A'<=c && c<='F'){
   38.70 +        d = c - 'A' + 10;
   38.71 +    } else {
   38.72 +        d = -1;
   38.73 +    }
   38.74 +    return (d < base ? d : -1);
   38.75 +}
   38.76 +
   38.77 +/** Convert a string to an unsigned long by parsing it as a number.
   38.78 + * Will accept hex or decimal in usual C syntax.
   38.79 + *
   38.80 + * @param str input string
   38.81 + * @param val where to put the result
   38.82 + * @return 0 if converted OK, negative otherwise
   38.83 + */
   38.84 +int convert_atoul(const char *str, unsigned long *val){
   38.85 +    int err = 0;
   38.86 +    unsigned long v = 0;
   38.87 +    int base;
   38.88 +    const char *s = str;
   38.89 +
   38.90 +    if(!s) {
   38.91 +        err = -EINVAL;
   38.92 +        goto exit;
   38.93 +    }
   38.94 +    s = convert_set_base(s, &base);
   38.95 +    for( ; !err && *s; s++){
   38.96 +        int digit = convert_get_digit(*s, base);
   38.97 +        if(digit<0){
   38.98 +            err = -EINVAL;
   38.99 +            goto exit;
  38.100 +        }
  38.101 +        v *= base;
  38.102 +        v += digit;
  38.103 +    } 
  38.104 +  exit:
  38.105 +    *val = (err ? 0 : v);
  38.106 +    return err;
  38.107 +}
  38.108 +
  38.109 +/** Combine a directory path with a relative path to produce
  38.110 + * a new path.
  38.111 + *
  38.112 + * @param s directory path
  38.113 + * @param t relative path
  38.114 + * @return new combined path s/t
  38.115 + */
  38.116 +int path_concat(char *s, char *t, char **val){
  38.117 +    int err = 0;
  38.118 +    int sn, tn, vn;
  38.119 +    char *v;
  38.120 +    sn = strlen(s);
  38.121 +    if(sn > 0 && s[sn-1] == '/'){
  38.122 +        sn--;
  38.123 +    }
  38.124 +    tn = strlen(t);
  38.125 +    if(tn > 0 && t[0] == '/'){
  38.126 +        tn--;
  38.127 +    }
  38.128 +    vn = sn+tn+1;
  38.129 +    v = (char*)allocate(vn+1);
  38.130 +    if(!v){
  38.131 +        err = -ENOMEM;
  38.132 +        goto exit;
  38.133 +    }
  38.134 +    strncpy(v, s, sn);
  38.135 +    v[sn] = '/';
  38.136 +    strncpy(v+sn+1, t, tn);
  38.137 +    v[vn] = '\0';
  38.138 +  exit:
  38.139 +    *val = (err ? NULL : v);
  38.140 +    return err;    
  38.141 +}
    39.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    39.2 +++ b/tools/lib/sys_string.h	Tue Jun 29 12:05:29 2004 +0000
    39.3 @@ -0,0 +1,91 @@
    39.4 +/*
    39.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    39.6 + *
    39.7 + * This library is free software; you can redistribute it and/or modify
    39.8 + * it under the terms of the GNU Lesser General Public License as published by
    39.9 + * the Free Software Foundation; either version 2.1 of the License, or
   39.10 + * (at your option) any later version.
   39.11 + *
   39.12 + * This library is distributed in the hope that it will be useful,
   39.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   39.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   39.15 + * GNU Lesser General Public License for more details.
   39.16 + *
   39.17 + * You should have received a copy of the GNU Lesser General Public License
   39.18 + * along with this library; if not, write to the Free Software
   39.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   39.20 + */
   39.21 +
   39.22 +#ifndef _XEN_LIB_SYS_STRING_H_
   39.23 +#define _XEN_LIB_SYS_STRING_H_
   39.24 +/** @file
   39.25 + * Replacement for standard string includes.
   39.26 + * Works in user or kernel code.
   39.27 + */
   39.28 +/*============================================================================*/
   39.29 +#ifdef __KERNEL__
   39.30 +
   39.31 +#include <linux/config.h>
   39.32 +#include <linux/kernel.h>
   39.33 +#include <linux/string.h>
   39.34 +#include <linux/types.h>
   39.35 +#include <stdarg.h>
   39.36 +#include "allocate.h"
   39.37 +
   39.38 +#if 0
   39.39 +static inline int tolower(int c){
   39.40 +    return (c>='A' && c<='Z' ? (c-'A')+'a' : c);
   39.41 +}
   39.42 +#endif
   39.43 +
   39.44 +static inline int isalpha(int c){
   39.45 +    return (c>='A' && c<='Z') || (c>='a' && c<='z');
   39.46 +}
   39.47 +
   39.48 +static inline int isdigit(int c){
   39.49 +   return (c>='0' && c<='9');
   39.50 +}
   39.51 +
   39.52 +#if 0
   39.53 +static inline int strcasecmp(const char *s1, const char *s2){
   39.54 +	int c1, c2;
   39.55 +
   39.56 +	do {
   39.57 +		c1 = tolower(*s1++);
   39.58 +		c2 = tolower(*s2++);
   39.59 +	} while (c1 && c1 == c2);
   39.60 +	return c1 - c2;
   39.61 +}
   39.62 +#endif
   39.63 +
   39.64 +static inline char * strdup(const char *s){
   39.65 +    int n = (s ? 1+strlen(s) : 0);
   39.66 +    char *copy = (n ? allocate(n) : NULL);
   39.67 +    if(copy){
   39.68 +        strcpy(copy, s);
   39.69 +    }
   39.70 +    return copy;
   39.71 +}
   39.72 +
   39.73 +/*============================================================================*/
   39.74 +#else
   39.75 +#include <string.h>
   39.76 +#include <stdio.h>
   39.77 +
   39.78 +#ifndef _GNU_SOURCE
   39.79 +static inline size_t strnlen(const char *s, size_t n){
   39.80 +    int k = 0;
   39.81 +    if(s){
   39.82 +	for(k=0; *s && k<n; s++, k++){}
   39.83 +    }
   39.84 +    return k;
   39.85 +}
   39.86 +#endif
   39.87 +
   39.88 +#endif
   39.89 +/*============================================================================*/
   39.90 +
   39.91 +extern int convert_atoul(const char *s, unsigned long *v);
   39.92 +extern int path_concat(char *s, char *t, char **val);
   39.93 +
   39.94 +#endif /* !_XEN_LIB_SYS_STRING_H_ */
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/tools/lib/xdr.c	Tue Jun 29 12:05:29 2004 +0000
    40.3 @@ -0,0 +1,246 @@
    40.4 +/* $Id: xdr.c,v 1.3 2003/09/29 13:40:00 mjw Exp $ */
    40.5 +#include "xdr.h"
    40.6 +#include <errno.h>
    40.7 +/** @file
    40.8 + * XDR packer/unpacker for elements.
    40.9 + *
   40.10 + * string -> [T_STRING] [len:u32] <len bytes>
   40.11 + * atom   -> [T_ATOM]   [len:u32] <len bytes>
   40.12 + * uint   -> [T_UINT]   [value]
   40.13 + * cons   -> [T_CONS]   <car> <cdr>
   40.14 + * null   -> [T_NULL]
   40.15 + * none   -> [T_NONE]
   40.16 + * bool   -> [T_BOOL]   { 0:u8 | 1:u8 }
   40.17 + *
   40.18 + * types packed as u16.
   40.19 + *
   40.20 + * So (a b c) -> [T_CONS] a [T_CONS] b [T_CONS] c [T_NULL]
   40.21 + *    ()      -> [T_NULL]
   40.22 + */
   40.23 +
   40.24 +int pack_bool(IOStream *io, int x){
   40.25 +    int err=0;
   40.26 +    err = IOStream_print(io, "%c", 0xff & x);
   40.27 +    if(err > 0) err = 0;
   40.28 +    return err;
   40.29 +}
   40.30 +
   40.31 +int unpack_bool(IOStream *io, int *x){
   40.32 +    int err = 0;
   40.33 +    int c;
   40.34 +    c = IOStream_getc(io);
   40.35 +    *x = (c < 0 ? 0 : c);
   40.36 +    err = IOStream_error(io);
   40.37 +    if(c < 0 && !err) err = -EIO;
   40.38 +    return err;
   40.39 +}
   40.40 +
   40.41 +int pack_ushort(IOStream *io, unsigned short x){
   40.42 +    int err=0;
   40.43 +    err = IOStream_print(io, "%c%c",
   40.44 +                         0xff & (x >>  8),
   40.45 +                         0xff & (x      ));
   40.46 +    if(err > 0) err = 0;
   40.47 +    return err;
   40.48 +}
   40.49 +
   40.50 +int unpack_ushort(IOStream *io, unsigned short *x){
   40.51 +    int err = 0;
   40.52 +    int i, c = 0;
   40.53 +    *x = 0;
   40.54 +    for(i = 0; i< 2; i++){
   40.55 +        c = IOStream_getc(io);
   40.56 +        if(c < 0) break;
   40.57 +        *x <<= 8;
   40.58 +        *x |= (0xff & c);
   40.59 +    }
   40.60 +    err = IOStream_error(io);
   40.61 +    if(c < 0 && !err) err = -EIO;
   40.62 +    return err;
   40.63 +}
   40.64 +
   40.65 +int pack_uint(IOStream *io, unsigned int x){
   40.66 +    int err=0;
   40.67 +    err = IOStream_print(io, "%c%c%c%c",
   40.68 +                         0xff & (x >> 24),
   40.69 +                         0xff & (x >> 16),
   40.70 +                         0xff & (x >>  8),
   40.71 +                         0xff & (x      ));
   40.72 +    if(err > 0) err = 0;
   40.73 +    return err;
   40.74 +}
   40.75 +
   40.76 +int unpack_uint(IOStream *io, unsigned int *x){
   40.77 +    int err = 0;
   40.78 +    int i, c = 0;
   40.79 +    *x = 0;
   40.80 +    for(i = 0; i< 4; i++){
   40.81 +        c = IOStream_getc(io);
   40.82 +        if(c < 0) break;
   40.83 +        *x <<= 8;
   40.84 +        *x |= (0xff & c);
   40.85 +    }
   40.86 +    err = IOStream_error(io);
   40.87 +    if(c < 0 && !err) err = -EIO;
   40.88 +    return err;
   40.89 +}
   40.90 +
   40.91 +int pack_string(IOStream *io, Sxpr x){
   40.92 +    int err = 0;
   40.93 +    int n = string_length(x);
   40.94 +    char *s = string_string(x);
   40.95 +    int i;
   40.96 +    err = pack_uint(io, n);
   40.97 +    if(err) goto exit;
   40.98 +    for(i = 0; i < n; i++){
   40.99 +        err = IOStream_print(io, "%c", s[i]);
  40.100 +        if(err < 0) break;
  40.101 +    }
  40.102 +    if(err > 0) err = 0;
  40.103 +  exit:
  40.104 +    return err;
  40.105 +}
  40.106 +
  40.107 +int unpack_string(IOStream *io, Sxpr *x){
  40.108 +    int err;
  40.109 +    unsigned int n;
  40.110 +    int i, c = 0;
  40.111 +    char *s;
  40.112 +    Sxpr val = ONONE;
  40.113 +    
  40.114 +    err = unpack_uint(io, &n);
  40.115 +    if(err) goto exit;
  40.116 +    val = halloc(n+1, T_STRING);
  40.117 +    if(NOMEMP(val)){
  40.118 +        err = -ENOMEM;
  40.119 +        goto exit;
  40.120 +    }
  40.121 +    s = string_string(val);
  40.122 +    for(i=0; i<n; i++){
  40.123 +        c = IOStream_getc(io);
  40.124 +        if(c < 0) break;
  40.125 +        s[i] = (char)c;
  40.126 +    }
  40.127 +    s[n] = '\0';
  40.128 +  exit:
  40.129 +    err = IOStream_error(io);
  40.130 +    if(c < 0 && !err) err = -EIO;
  40.131 +    if(err){
  40.132 +        objfree(val);
  40.133 +        val = ONONE;
  40.134 +    }
  40.135 +    *x = val;
  40.136 +    return err;
  40.137 +}
  40.138 +
  40.139 +int pack_cons(IOStream *io, Sxpr x){
  40.140 +    int err = 0;
  40.141 +    err = pack_sxpr(io, CAR(x));
  40.142 +    if(err) goto exit;
  40.143 +    err = pack_sxpr(io, CDR(x));
  40.144 +  exit:
  40.145 +    return err;
  40.146 +}
  40.147 +
  40.148 +int unpack_cons(IOStream *io, Sxpr *x){
  40.149 +    int err = 0;
  40.150 +    Sxpr u = ONONE, v = ONONE, val = ONONE;
  40.151 +    err = unpack_sxpr(io, &u);
  40.152 +    if(err) goto exit;
  40.153 +    err = unpack_sxpr(io, &v);
  40.154 +    if(err) goto exit;
  40.155 +    val = cons_new(u, v);
  40.156 +    if(NOMEMP(val)){
  40.157 +        err = -ENOMEM;
  40.158 +    }
  40.159 +  exit:
  40.160 +    if(err){
  40.161 +        objfree(u);
  40.162 +        objfree(v);
  40.163 +        val = ONONE;
  40.164 +    }        
  40.165 +    *x = val;
  40.166 +    return err;
  40.167 +}
  40.168 +
  40.169 +int pack_sxpr(IOStream *io, Sxpr x){
  40.170 +    int err = 0;
  40.171 +    unsigned short type = get_type(x);
  40.172 +    err = pack_ushort(io, type);
  40.173 +    if(err) goto exit;
  40.174 +    switch(type){
  40.175 +    case T_NULL:
  40.176 +        break;
  40.177 +    case T_NONE:
  40.178 +        break;
  40.179 +        break;
  40.180 +    case T_BOOL:
  40.181 +        err = pack_bool(io, get_ul(x));
  40.182 +        break;
  40.183 +    case T_CONS:
  40.184 +        err = pack_cons(io, x);
  40.185 +        break;
  40.186 +    case T_ATOM:
  40.187 +        err = pack_string(io, OBJ_ATOM(x)->name);
  40.188 +        break;
  40.189 +    case T_STRING:
  40.190 +        err = pack_string(io, x);
  40.191 +        break;
  40.192 +    case T_UINT:
  40.193 +        err = pack_uint(io, get_ul(x));
  40.194 +        break;
  40.195 +    default:
  40.196 +        err = -EINVAL;
  40.197 +        IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type);
  40.198 +        break;
  40.199 +    }
  40.200 +  exit:
  40.201 +    return err;
  40.202 +}
  40.203 +
  40.204 +int unpack_sxpr(IOStream *io, Sxpr *x){
  40.205 +    int err = 0;
  40.206 +    unsigned short type;
  40.207 +    unsigned int u;
  40.208 +    Sxpr val = ONONE, y;
  40.209 +
  40.210 +    err = unpack_ushort(io, &type);
  40.211 +    if(err) goto exit;
  40.212 +    switch(type){
  40.213 +    case T_NULL:
  40.214 +        val = ONULL;
  40.215 +        break;
  40.216 +    case T_NONE:
  40.217 +        val = ONONE;
  40.218 +        break;
  40.219 +    case T_CONS:
  40.220 +        err = unpack_cons(io, &val);
  40.221 +        break;
  40.222 +    case T_BOOL:
  40.223 +        err = unpack_bool(io, &u);
  40.224 +        if(err) goto exit;
  40.225 +        val = (u ? OTRUE : OFALSE);
  40.226 +        break;
  40.227 +    case T_ATOM:
  40.228 +        err = unpack_string(io, &y);
  40.229 +        if(err) goto exit;
  40.230 +        val = intern(string_string(y));
  40.231 +        objfree(y);
  40.232 +        break;
  40.233 +    case T_STRING:
  40.234 +        err = unpack_string(io, &val);
  40.235 +        break;
  40.236 +    case T_UINT:
  40.237 +        err = unpack_uint(io, &u);
  40.238 +        if(err) goto exit;
  40.239 +        val = OBJI(type, u);
  40.240 +        break;
  40.241 +    default:
  40.242 +        err = -EINVAL;
  40.243 +        IOStream_print(iostderr, "%s> invalid type %d\n", __FUNCTION__, type);
  40.244 +        break;
  40.245 +    }
  40.246 +  exit:
  40.247 +    *x = (err ? ONONE : val);
  40.248 +    return err;
  40.249 +}
    41.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    41.2 +++ b/tools/lib/xdr.h	Tue Jun 29 12:05:29 2004 +0000
    41.3 @@ -0,0 +1,14 @@
    41.4 +/* $Id: xdr.h,v 1.2 2003/09/29 13:40:00 mjw Exp $ */
    41.5 +#ifndef _SP_XDR_H_
    41.6 +#define _SP_XDR_H_
    41.7 +#include "iostream.h"
    41.8 +#include "sxpr.h"
    41.9 +int pack_uint(IOStream *out, unsigned int x);
   41.10 +int unpack_uint(IOStream *in, unsigned int *x);
   41.11 +int pack_string(IOStream *out, Sxpr x);
   41.12 +int unpack_string(IOStream *in, Sxpr *x);
   41.13 +int pack_cons(IOStream *out, Sxpr x);
   41.14 +int unpack_cons(IOStream *in, Sxpr *x);
   41.15 +int pack_sxpr(IOStream *out, Sxpr x);
   41.16 +int unpack_sxpr(IOStream *in, Sxpr *x);
   41.17 +#endif /* _SP_XDR_H_ */
    42.1 --- a/tools/misc/Makefile	Tue Jun 29 00:51:10 2004 +0000
    42.2 +++ b/tools/misc/Makefile	Tue Jun 29 12:05:29 2004 +0000
    42.3 @@ -4,6 +4,7 @@ CFLAGS     = -Wall -O3
    42.4  EXTRA_INC  = -I../../xen/include/hypervisor-ifs
    42.5  EXTRA_INC += -I../../linux-xen-sparse/include -I../xc/lib
    42.6  EXTRA_INC += -I../xu/lib
    42.7 +EXTRA_INC += -I../lib
    42.8  
    42.9  HDRS     = $(wildcard *.h)
   42.10  SRCS     = $(wildcard *.c)
    43.1 --- a/tools/xc/lib/Makefile	Tue Jun 29 00:51:10 2004 +0000
    43.2 +++ b/tools/xc/lib/Makefile	Tue Jun 29 12:05:29 2004 +0000
    43.3 @@ -4,13 +4,73 @@ MINOR    = 0
    43.4  SONAME   = libxc.so.$(MAJOR)
    43.5  
    43.6  CC       = gcc
    43.7 -CFLAGS   = -c -Werror -O3 -fno-strict-aliasing
    43.8 -CFLAGS  += -I../../../xen/include/hypervisor-ifs
    43.9 -CFLAGS  += -I../../xu/lib
   43.10 -CFLAGS  += -I../../../linux-xen-sparse/include
   43.11 +
   43.12 +XEN_ROOT = ../../..
   43.13 +
   43.14 +vpath %.h      $(XEN_ROOT)/xen/include/hypervisor-ifs
   43.15 +INCLUDES += -I $(XEN_ROOT)/xen/include/hypervisor-ifs
   43.16 +
   43.17 +vpath %.h      $(XEN_ROOT)/tools/xu/lib
   43.18 +INCLUDES += -I $(XEN_ROOT)/tools/xu/lib
   43.19 +
   43.20 +vpath %h       $(XEN_ROOT)/linux-xen-sparse/include
   43.21 +INCLUDES += -I $(XEN_ROOT)/linux-xen-sparse/include
   43.22 +
   43.23 +vpath %c       $(XEN_ROOT)/tools/lib
   43.24 +INCLUDES += -I $(XEN_ROOT)/tools/lib
   43.25  
   43.26 -HDRS     = $(wildcard *.h)
   43.27 -OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
   43.28 +LIB_SRCS :=
   43.29 +LIB_SRCS += allocate.c
   43.30 +#LIB_SRCS += enum.c
   43.31 +LIB_SRCS += file_stream.c
   43.32 +LIB_SRCS += gzip_stream.c
   43.33 +#LIB_SRCS += hash_table.c
   43.34 +LIB_SRCS += iostream.c
   43.35 +#LIB_SRCS += kernel_stream.c
   43.36 +#LIB_SRCS += lexis.c
   43.37 +#LIB_SRCS += lzi_stream.c
   43.38 +#LIB_SRCS += lzo_stream.c
   43.39 +#LIB_SRCS += marshal.c
   43.40 +#LIB_SRCS += socket_stream.c
   43.41 +#LIB_SRCS += string_stream.c
   43.42 +#LIB_SRCS += sxpr.c
   43.43 +#LIB_SRCS += sxpr_parser.c
   43.44 +LIB_SRCS += sys_net.c
   43.45 +LIB_SRCS += sys_string.c
   43.46 +#LIB_SRCS += xdr.c
   43.47 +
   43.48 +SRCS     :=
   43.49 +SRCS     += xc_atropos.c
   43.50 +SRCS     += xc_bvtsched.c
   43.51 +SRCS     += xc_domain.c
   43.52 +SRCS     += xc_evtchn.c
   43.53 +SRCS     += xc_io.c
   43.54 +SRCS     += xc_linux_build.c
   43.55 +SRCS     += xc_linux_restore.c
   43.56 +SRCS     += xc_linux_save.c
   43.57 +SRCS     += xc_misc.c
   43.58 +SRCS     += xc_netbsd_build.c
   43.59 +SRCS     += xc_physdev.c
   43.60 +SRCS     += xc_private.c
   43.61 +SRCS     += xc_rrobin.c
   43.62 +
   43.63 +SRCS     += $(LIB_SRCS)
   43.64 +
   43.65 +#CFLAGS  += -I../../../xen/include/hypervisor-ifs
   43.66 +#CFLAGS  += -I../../xu/lib
   43.67 +#CFLAGS  += -I../../../linux-xen-sparse/include
   43.68 +
   43.69 +CFLAGS   += -Wall
   43.70 +CFLAGS   += -Werror
   43.71 +CFLAGS   += -g
   43.72 +CFLAGS   += -O3
   43.73 +CFLAGS   += -fno-strict-aliasing
   43.74 +CFLAGS   += $(INCLUDES)
   43.75 +# Get gcc to generate the dependencies for us.
   43.76 +CFLAGS   += -Wp,-MD,.$(@F).d
   43.77 +DEPS     = .*.d
   43.78 +
   43.79 +OBJS     = $(patsubst %.c,%.o,$(SRCS))
   43.80  
   43.81  LIB      = libxc.so libxc.so.$(MAJOR) libxc.so.$(MAJOR).$(MINOR)
   43.82  
   43.83 @@ -32,6 +92,8 @@ install: all
   43.84  
   43.85  clean:
   43.86  	$(RM) *.a *.so *.o *.rpm $(LIB)
   43.87 +	$(RM) *~
   43.88 +	$(RM) $(DEPS)
   43.89  
   43.90  rpm: all
   43.91  	rm -rf staging
   43.92 @@ -49,5 +111,8 @@ libxc.so.$(MAJOR):
   43.93  libxc.so.$(MAJOR).$(MINOR): $(OBJS)
   43.94  	$(CC) -Wl,-soname -Wl,$(SONAME) -shared -o $@ $^ -lz
   43.95  
   43.96 -%.o: %.c $(HDRS) Makefile
   43.97 -	$(CC) $(CFLAGS) -o $@ $<
   43.98 +%.o: %.c Makefile
   43.99 +
  43.100 +#	$(CC) $(CFLAGS) -o $@ $<
  43.101 +
  43.102 +-include $(DEPS)
    44.1 --- a/tools/xc/lib/xc.h	Tue Jun 29 00:51:10 2004 +0000
    44.2 +++ b/tools/xc/lib/xc.h	Tue Jun 29 12:05:29 2004 +0000
    44.3 @@ -75,18 +75,9 @@ int xc_shadow_control(int xc_handle,
    44.4  #define XCFLAGS_LIVE    2
    44.5  #define XCFLAGS_DEBUG   4
    44.6  
    44.7 -int xc_linux_save(int xc_handle,
    44.8 -                  u32 domid, 
    44.9 -                  unsigned int flags,
   44.10 -                  int (*writerfn)(void *, const void *, size_t),
   44.11 -                  void *writerst);
   44.12 -
   44.13 -int xc_linux_restore(int xc_handle,
   44.14 -                     u32 domid,
   44.15 -                     unsigned int flags,
   44.16 -                     int (*readerfn)(void *, void *, size_t),
   44.17 -                     void *readerst,
   44.18 -                     u32 *pdomid);
   44.19 +struct XcIOContext;
   44.20 +int xc_linux_save(int xc_handle, struct XcIOContext *ioctxt);
   44.21 +int xc_linux_restore(int xc_handle, struct XcIOContext *ioctxt);
   44.22  
   44.23  int xc_linux_build(int xc_handle,
   44.24                     u32 domid,
    45.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    45.2 +++ b/tools/xc/lib/xc_io.c	Tue Jun 29 12:05:29 2004 +0000
    45.3 @@ -0,0 +1,27 @@
    45.4 +#include "xc_io.h"
    45.5 +
    45.6 +void xcio_error(XcIOContext *ctxt, const char *msg, ...){
    45.7 +  va_list args;
    45.8 +
    45.9 +  va_start(args, msg);
   45.10 +  IOStream_vprint(ctxt->info, msg, args);
   45.11 +  va_end(args);
   45.12 +}
   45.13 +
   45.14 +void xcio_info(XcIOContext *ctxt, const char *msg, ...){
   45.15 +  va_list args;
   45.16 +
   45.17 +  if(!(ctxt->flags & XCFLAGS_VERBOSE)) return;
   45.18 +  va_start(args, msg);
   45.19 +  IOStream_vprint(ctxt->info, msg, args);
   45.20 +  va_end(args);
   45.21 +}
   45.22 +
   45.23 +void xcio_debug(XcIOContext *ctxt, const char *msg, ...){
   45.24 +  va_list args;
   45.25 +
   45.26 +  if(!(ctxt->flags & XCFLAGS_DEBUG)) return;
   45.27 +  va_start(args, msg);
   45.28 +  IOStream_vprint(ctxt->info, msg, args);
   45.29 +  va_end(args);
   45.30 +}
    46.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    46.2 +++ b/tools/xc/lib/xc_io.h	Tue Jun 29 12:05:29 2004 +0000
    46.3 @@ -0,0 +1,44 @@
    46.4 +#ifndef __XC_XC_IO_H__
    46.5 +#define __XC_XC_IO_H__
    46.6 +
    46.7 +#include "xc_private.h"
    46.8 +#include "iostream.h"
    46.9 +
   46.10 +typedef struct XcIOContext {
   46.11 +    u32 domain;
   46.12 +    unsigned flags;
   46.13 +    IOStream *io;
   46.14 +    IOStream *info;
   46.15 +    IOStream *err;
   46.16 +    char *vmconfig;
   46.17 +    int vmconfig_n;
   46.18 +} XcIOContext;
   46.19 +
   46.20 +static inline int xcio_read(XcIOContext *ctxt, void *buf, int n){
   46.21 +    int rc;
   46.22 +
   46.23 +    rc = IOStream_read(ctxt->io, buf, n);
   46.24 +    return (rc == n ? 0 : rc);
   46.25 +}
   46.26 +
   46.27 +static inline int xcio_write(XcIOContext *ctxt, void *buf, int n){
   46.28 +    int rc;
   46.29 +
   46.30 +    rc = IOStream_write(ctxt->io, buf, n);
   46.31 +    return (rc == n ? 0 : rc);
   46.32 +}
   46.33 +
   46.34 +static inline int xcio_flush(XcIOContext *ctxt){
   46.35 +    return IOStream_flush(ctxt->io);
   46.36 +}
   46.37 +
   46.38 +extern void xcio_error(XcIOContext *ctxt, const char *msg, ...);
   46.39 +extern void xcio_info(XcIOContext *ctxt, const char *msg, ...);
   46.40 +
   46.41 +#define xcio_perror(_ctxt, _msg...) \
   46.42 +xcio_error(_ctxt, "(errno %d %s)" _msg, errno, strerror(errno), ## _msg)
   46.43 +
   46.44 +#endif /* ! __XC_XC_IO_H__ */
   46.45 +
   46.46 +
   46.47 +
    47.1 --- a/tools/xc/lib/xc_linux_restore.c	Tue Jun 29 00:51:10 2004 +0000
    47.2 +++ b/tools/xc/lib/xc_linux_restore.c	Tue Jun 29 12:05:29 2004 +0000
    47.3 @@ -8,7 +8,6 @@
    47.4  
    47.5  #include "xc_private.h"
    47.6  #include <asm-xen/suspend.h>
    47.7 -#include <zlib.h>
    47.8  
    47.9  #define MAX_BATCH_SIZE 1024
   47.10  
   47.11 @@ -21,14 +20,6 @@
   47.12  #endif
   47.13  
   47.14  
   47.15 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
   47.16 -#define verbose_printf(_f, _a...) \
   47.17 -    do {                          \
   47.18 -        if ( !verbose ) break;    \
   47.19 -        printf( _f , ## _a );     \
   47.20 -        fflush(stdout);           \
   47.21 -    } while ( 0 )
   47.22 -
   47.23  static int get_pfn_list(int xc_handle,
   47.24                          u32 domain_id, 
   47.25                          unsigned long *pfn_buf, 
   47.26 @@ -54,19 +45,44 @@ static int get_pfn_list(int xc_handle,
   47.27      return (ret < 0) ? -1 : op.u.getmemlist.num_pfns;
   47.28  }
   47.29  
   47.30 +/** Read the vmconfig string from the state input.
   47.31 + * It is stored as a 4-byte count 'n' followed by n bytes.
   47.32 + * The config data is stored in a new string in 'ioctxt->vmconfig',
   47.33 + * and is null-terminated. The count is stored in 'ioctxt->vmconfig_n'.
   47.34 + *
   47.35 + * @param ioctxt i/o context
   47.36 + * @return 0 on success, non-zero on error.
   47.37 + */
   47.38 +static int read_vmconfig(XcIOContext *ioctxt){
   47.39 +    int err = -1;
   47.40 +    if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){
   47.41 +        goto exit;
   47.42 +    }
   47.43 +    ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1);
   47.44 +    if(!ioctxt->vmconfig) goto exit;
   47.45 +    if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){
   47.46 +        goto exit;
   47.47 +    }
   47.48 +    ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0';
   47.49 +    err = 0;
   47.50 +  exit:
   47.51 +    if(err){
   47.52 +        if(ioctxt->vmconfig){
   47.53 +            free(ioctxt->vmconfig);
   47.54 +        }
   47.55 +        ioctxt->vmconfig = NULL;
   47.56 +        ioctxt->vmconfig_n = 0;
   47.57 +    }
   47.58 +    return err;
   47.59 +}
   47.60  
   47.61 -int xc_linux_restore(int xc_handle,
   47.62 -                     u32 dom,
   47.63 -                     unsigned int flags,
   47.64 -                     int (*readerfn)(void *, void *, size_t),
   47.65 -                     void *readerst,
   47.66 -                     u32 *pdomid)
   47.67 +int xc_linux_restore(int xc_handle, XcIOContext *ioctxt)
   47.68  {
   47.69      dom0_op_t op;
   47.70 -    int rc = 1, i, j, n, k;
   47.71 +    int rc = 1, i, n, k;
   47.72      unsigned long mfn, pfn, xpfn;
   47.73      unsigned int prev_pc, this_pc;
   47.74 -    int verbose = flags & XCFLAGS_VERBOSE;
   47.75 +    u32 dom = ioctxt->domain;
   47.76      int verify = 0; 
   47.77  
   47.78      /* Number of page frames in use by this Linux session. */
   47.79 @@ -115,8 +131,7 @@ int xc_linux_restore(int xc_handle,
   47.80      /* used by debug verify code */
   47.81      unsigned long buf[PAGE_SIZE/sizeof(unsigned long)];
   47.82  
   47.83 -    if ( mlock(&ctxt, sizeof(ctxt) ) )
   47.84 -    {   
   47.85 +    if ( mlock(&ctxt, sizeof(ctxt) ) ) {   
   47.86          /* needed for when we do the build dom0 op, 
   47.87             but might as well do early */
   47.88          PERROR("Unable to mlock ctxt");
   47.89 @@ -124,35 +139,36 @@ int xc_linux_restore(int xc_handle,
   47.90      }
   47.91  
   47.92      /* Start writing out the saved-domain record. */
   47.93 -    if ( (*readerfn)(readerst, signature, 16) ||
   47.94 -         (memcmp(signature, "LinuxGuestRecord", 16) != 0) )
   47.95 -    {
   47.96 -        ERROR("Unrecognised state format -- no signature found");
   47.97 +    if ( xcio_read(ioctxt, signature, 16) ||
   47.98 +         (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) {
   47.99 +        xcio_error(ioctxt, "Unrecognised state format -- no signature found");
  47.100          goto out;
  47.101      }
  47.102  
  47.103 -    if ( (*readerfn)(readerst, name,                  sizeof(name)) ||
  47.104 -         (*readerfn)(readerst, &nr_pfns,              sizeof(unsigned long)) ||
  47.105 -         (*readerfn)(readerst, pfn_to_mfn_frame_list, PAGE_SIZE) )
  47.106 -    {
  47.107 -        ERROR("Error when reading from state file");
  47.108 +    if ( xcio_read(ioctxt, name,                  sizeof(name)) ||
  47.109 +         xcio_read(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
  47.110 +         xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) {
  47.111 +        xcio_error(ioctxt, "Error reading header");
  47.112          goto out;
  47.113      }
  47.114  
  47.115 -    for ( i = 0; i < MAX_DOMAIN_NAME; i++ )
  47.116 -    {
  47.117 +    if(read_vmconfig(ioctxt)){
  47.118 +        xcio_error(ioctxt, "Error writing vmconfig");
  47.119 +        goto out;
  47.120 +    }
  47.121 +
  47.122 +    for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) {
  47.123          if ( name[i] == '\0' ) break;
  47.124          if ( name[i] & 0x80 )
  47.125          {
  47.126 -            ERROR("Random characters in domain name");
  47.127 +            xcio_error(ioctxt, "Random characters in domain name");
  47.128              goto out;
  47.129          }
  47.130      }
  47.131      name[MAX_DOMAIN_NAME-1] = '\0';
  47.132  
  47.133 -    if ( nr_pfns > 1024*1024 )
  47.134 -    {
  47.135 -        ERROR("Invalid state file -- pfn count out of range");
  47.136 +    if ( nr_pfns > 1024*1024 ) {
  47.137 +        xcio_error(ioctxt, "Invalid state file -- pfn count out of range");
  47.138          goto out;
  47.139      }
  47.140  
  47.141 @@ -162,22 +178,19 @@ int xc_linux_restore(int xc_handle,
  47.142      region_mfn       = calloc(1, 4 * MAX_BATCH_SIZE);    
  47.143  
  47.144      if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || 
  47.145 -         (region_mfn == NULL) )
  47.146 -    {
  47.147 +         (region_mfn == NULL) ) {
  47.148          errno = ENOMEM;
  47.149          goto out;
  47.150      }
  47.151      
  47.152 -    if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) )
  47.153 -    {
  47.154 -        ERROR("Could not mlock region_mfn");
  47.155 +    if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) {
  47.156 +        xcio_error(ioctxt, "Could not mlock region_mfn");
  47.157          goto out;
  47.158      }
  47.159  
  47.160      /* Set the domain's name to that from the restore file */
  47.161 -    if ( xc_domain_setname( xc_handle, dom, name ) )
  47.162 -    {
  47.163 -        ERROR("Could not set domain name");
  47.164 +    if ( xc_domain_setname( xc_handle, dom, name ) ) {
  47.165 +        xcio_error(ioctxt, "Could not set domain name");
  47.166          goto out;
  47.167      }
  47.168  
  47.169 @@ -187,7 +200,7 @@ int xc_linux_restore(int xc_handle,
  47.170      if ( xc_domain_setinitialmem(xc_handle, dom, 
  47.171                                   nr_pfns * (PAGE_SIZE / 1024)) )
  47.172      {
  47.173 -        ERROR("Could not set domain initial memory");
  47.174 +        xcio_error(ioctxt, "Could not set domain initial memory");
  47.175          goto out;
  47.176      }
  47.177  
  47.178 @@ -195,9 +208,8 @@ int xc_linux_restore(int xc_handle,
  47.179      op.cmd = DOM0_GETDOMAININFO;
  47.180      op.u.getdomaininfo.domain = (domid_t)dom;
  47.181      op.u.getdomaininfo.ctxt = NULL;
  47.182 -    if ( do_dom0_op(xc_handle, &op) < 0 )
  47.183 -    {
  47.184 -        ERROR("Could not get information on new domain");
  47.185 +    if ( do_dom0_op(xc_handle, &op) < 0 ) {
  47.186 +        xcio_error(ioctxt, "Could not get information on new domain");
  47.187          goto out;
  47.188      }
  47.189      shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  47.190 @@ -208,19 +220,17 @@ int xc_linux_restore(int xc_handle,
  47.191  
  47.192  
  47.193      /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */
  47.194 -    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns )
  47.195 -    {
  47.196 -        ERROR("Did not read correct number of frame numbers for new dom");
  47.197 +    if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) {
  47.198 +        xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom");
  47.199          goto out;
  47.200      }
  47.201  
  47.202 -    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL )
  47.203 -    {
  47.204 -        ERROR("Could not initialise for MMU updates");
  47.205 +    if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) {
  47.206 +        xcio_error(ioctxt, "Could not initialise for MMU updates");
  47.207          goto out;
  47.208      }
  47.209  
  47.210 -    verbose_printf("Reloading memory pages:   0%%");
  47.211 +    xcio_info(ioctxt, "Reloading memory pages:   0%%");
  47.212  
  47.213      /*
  47.214       * Now simply read each saved frame into its new machine frame.
  47.215 @@ -229,56 +239,45 @@ int xc_linux_restore(int xc_handle,
  47.216      prev_pc = 0;
  47.217  
  47.218      n=0;
  47.219 -    while(1)
  47.220 -    {
  47.221 +    while(1) {
  47.222          int j;
  47.223          unsigned long region_pfn_type[MAX_BATCH_SIZE];
  47.224  
  47.225          this_pc = (n * 100) / nr_pfns;
  47.226 -        if ( (this_pc - prev_pc) >= 5 )
  47.227 -        {
  47.228 -            verbose_printf("\b\b\b\b%3d%%", this_pc);
  47.229 +        if ( (this_pc - prev_pc) >= 5 ) {
  47.230 +            xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
  47.231              prev_pc = this_pc;
  47.232          }
  47.233  
  47.234 -        if ( (*readerfn)(readerst, &j, sizeof(int)) )
  47.235 -        {
  47.236 -            ERROR("Error when reading from state file");
  47.237 +        if ( xcio_read(ioctxt, &j, sizeof(int)) ) {
  47.238 +            xcio_error(ioctxt, "Error when reading from state file");
  47.239              goto out;
  47.240          }
  47.241  
  47.242          DPRINTF("batch %d\n",j);
  47.243   
  47.244 -        if ( j == -1 )
  47.245 -        {
  47.246 +        if ( j == -1 ) {
  47.247              verify = 1;
  47.248              printf("Entering page verify mode\n");
  47.249              continue;
  47.250          }
  47.251  
  47.252 -        if ( j == 0 ) 
  47.253 -            break;  /* our work here is done */
  47.254 +        if ( j == 0 ) break;  /* our work here is done */
  47.255  
  47.256 -        if( j > MAX_BATCH_SIZE )
  47.257 -        {
  47.258 -            ERROR("Max batch size exceeded. Giving up.");
  47.259 +        if( j > MAX_BATCH_SIZE ) {
  47.260 +            xcio_error(ioctxt, "Max batch size exceeded. Giving up.");
  47.261              goto out;
  47.262          }
  47.263   
  47.264 -        if ( (*readerfn)(readerst, region_pfn_type, j*sizeof(unsigned long)) )
  47.265 -        {
  47.266 -            ERROR("Error when reading from state file");
  47.267 +        if ( xcio_read(ioctxt, region_pfn_type, j*sizeof(unsigned long)) ) {
  47.268 +            xcio_error(ioctxt, "Error when reading from state file");
  47.269              goto out;
  47.270          }
  47.271  
  47.272 -        for(i=0;i<j;i++)
  47.273 -        {
  47.274 -            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB)
  47.275 -            {
  47.276 +        for(i=0; i<j; i++) {
  47.277 +            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) {
  47.278                  region_mfn[i] = 0; /* we know map will fail, but don't care */
  47.279 -            }
  47.280 -            else
  47.281 -            {  
  47.282 +            } else {  
  47.283                  pfn = region_pfn_type[i] & ~LTAB_MASK;
  47.284                  region_mfn[i] = pfn_to_mfn_table[pfn];
  47.285              }          
  47.286 @@ -287,24 +286,20 @@ int xc_linux_restore(int xc_handle,
  47.287          if ( (region_base = mfn_mapper_map_batch( xc_handle, dom, 
  47.288                                                    PROT_WRITE,
  47.289                                                    region_mfn,
  47.290 -                                                  j )) == 0)
  47.291 -        {
  47.292 -            PERROR("map batch failed");
  47.293 +                                                  j )) == 0) {
  47.294 +            xcio_error(ioctxt, "map batch failed");
  47.295              goto out;
  47.296          }
  47.297  
  47.298 -        for(i=0;i<j;i++)
  47.299 -        {
  47.300 +        for(i=0;i<j;i++) {
  47.301              unsigned long *ppage;
  47.302  
  47.303              pfn = region_pfn_type[i] & ~LTAB_MASK;
  47.304  
  47.305 -            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB)
  47.306 -                continue;
  47.307 +            if ( (region_pfn_type[i] & LTAB_MASK) == XTAB) continue;
  47.308  
  47.309 -            if (pfn>nr_pfns)
  47.310 -            {
  47.311 -                ERROR("pfn out of range");
  47.312 +            if (pfn>nr_pfns) {
  47.313 +                xcio_error(ioctxt, "pfn out of range");
  47.314                  goto out;
  47.315              }
  47.316  
  47.317 @@ -314,36 +309,32 @@ int xc_linux_restore(int xc_handle,
  47.318  
  47.319              mfn = pfn_to_mfn_table[pfn];
  47.320  
  47.321 -            if ( verify )
  47.322 +            if ( verify ) {
  47.323                  ppage = (unsigned long*) buf;  /* debug case */
  47.324 -            else
  47.325 +            } else {
  47.326                  ppage = (unsigned long*) (region_base + i*PAGE_SIZE);
  47.327 +            }
  47.328  
  47.329 -            if ( (*readerfn)(readerst, ppage, PAGE_SIZE) )
  47.330 -            {
  47.331 -                ERROR("Error when reading from state file");
  47.332 +            if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) {
  47.333 +                xcio_error(ioctxt, "Error when reading from state file");
  47.334                  goto out;
  47.335              }
  47.336  
  47.337 -            switch( region_pfn_type[i] )
  47.338 -            {
  47.339 +            switch( region_pfn_type[i] ) {
  47.340              case 0:
  47.341                  break;
  47.342  
  47.343              case L1TAB:
  47.344              {
  47.345 -                for ( k = 0; k < 1024; k++ )
  47.346 -                {
  47.347 -                    if ( ppage[k] & _PAGE_PRESENT )
  47.348 -                    {
  47.349 +                for ( k = 0; k < 1024; k++ ) {
  47.350 +                    if ( ppage[k] & _PAGE_PRESENT ) {
  47.351                          xpfn = ppage[k] >> PAGE_SHIFT;
  47.352  
  47.353 -                        if ( xpfn >= nr_pfns )
  47.354 -                        {
  47.355 -                            ERROR("Frame number in type %d page table is "
  47.356 -                                  "out of range. i=%d k=%d pfn=0x%x "
  47.357 -                                  "nr_pfns=%d", region_pfn_type[i]>>28, i, 
  47.358 -                                  k, xpfn,nr_pfns);
  47.359 +                        if ( xpfn >= nr_pfns ) {
  47.360 +                            xcio_error(ioctxt, "Frame number in type %lu page table is "
  47.361 +                                  "out of range. i=%d k=%d pfn=0x%lx "
  47.362 +                                  "nr_pfns=%lu", region_pfn_type[i]>>28, i, 
  47.363 +                                  k, xpfn, nr_pfns);
  47.364                              goto out;
  47.365                          }
  47.366  
  47.367 @@ -359,16 +350,13 @@ int xc_linux_restore(int xc_handle,
  47.368              {
  47.369                  for ( k = 0; 
  47.370                        k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); 
  47.371 -                      k++ )
  47.372 -                {
  47.373 -                    if ( ppage[k] & _PAGE_PRESENT )
  47.374 -                    {
  47.375 +                      k++ ) {
  47.376 +                    if ( ppage[k] & _PAGE_PRESENT ) {
  47.377                          xpfn = ppage[k] >> PAGE_SHIFT;
  47.378  
  47.379 -                        if ( xpfn >= nr_pfns )
  47.380 -                        {
  47.381 -                            ERROR("Frame number in type %d page table is "
  47.382 -                                  "out of range. i=%d k=%d pfn=%d nr_pfns=%d",
  47.383 +                        if ( xpfn >= nr_pfns ) {
  47.384 +                            xcio_error(ioctxt, "Frame number in type %lu page table is "
  47.385 +                                  "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu",
  47.386                                    region_pfn_type[i]>>28, i, k, xpfn, nr_pfns);
  47.387  
  47.388                              goto out;
  47.389 @@ -383,24 +371,21 @@ int xc_linux_restore(int xc_handle,
  47.390              break;
  47.391  
  47.392              default:
  47.393 -                ERROR("Bogus page type %x page table is out of range."
  47.394 -                      " i=%d nr_pfns=%d", region_pfn_type[i], i, nr_pfns);
  47.395 +                xcio_error(ioctxt, "Bogus page type %lx page table is out of range."
  47.396 +                      " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns);
  47.397                  goto out;
  47.398  
  47.399              } /* end of page type switch statement */
  47.400  
  47.401 -            if ( verify )
  47.402 -            {
  47.403 +            if ( verify ) {
  47.404                  int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE );
  47.405 -                if (res)
  47.406 -                {
  47.407 +                if (res) {
  47.408                      int v;
  47.409 -                    printf("************** pfn=%x type=%x gotcs=%08lx "
  47.410 +                    printf("************** pfn=%lx type=%lx gotcs=%08lx "
  47.411                             "actualcs=%08lx\n", pfn, pfn_type[pfn], 
  47.412                             csum_page(region_base + i*PAGE_SIZE), 
  47.413                             csum_page(buf));
  47.414 -                    for ( v = 0; v < 4; v++ )
  47.415 -                    {
  47.416 +                    for ( v = 0; v < 4; v++ ) {
  47.417                          unsigned long *p = (unsigned long *)
  47.418                              (region_base + i*PAGE_SIZE);
  47.419                          if ( buf[v] != p[v] )
  47.420 @@ -411,8 +396,7 @@ int xc_linux_restore(int xc_handle,
  47.421              }
  47.422  
  47.423              if ( add_mmu_update(xc_handle, mmu,
  47.424 -                                (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) )
  47.425 -            {
  47.426 +                                (mfn<<PAGE_SHIFT) | MMU_MACHPHYS_UPDATE, pfn) ) {
  47.427                  printf("machpys mfn=%ld pfn=%ld\n",mfn,pfn);
  47.428                  goto out;
  47.429              }
  47.430 @@ -431,44 +415,36 @@ int xc_linux_restore(int xc_handle,
  47.431       * Pin page tables. Do this after writing to them as otherwise Xen
  47.432       * will barf when doing the type-checking.
  47.433       */
  47.434 -    for ( i = 0; i < nr_pfns; i++ )
  47.435 -    {
  47.436 -        if ( pfn_type[i] == L1TAB )
  47.437 -        {
  47.438 +    for ( i = 0; i < nr_pfns; i++ ) {
  47.439 +        if ( pfn_type[i] == L1TAB ) {
  47.440              if ( add_mmu_update(xc_handle, mmu,
  47.441                                  (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 
  47.442                                  MMU_EXTENDED_COMMAND,
  47.443 -                                MMUEXT_PIN_L1_TABLE) )
  47.444 -            {
  47.445 +                                MMUEXT_PIN_L1_TABLE) ) {
  47.446                  printf("ERR pin L1 pfn=%lx mfn=%lx\n",
  47.447 -                       i, pfn_to_mfn_table[i]);
  47.448 +                       (unsigned long)i, pfn_to_mfn_table[i]);
  47.449                  goto out;
  47.450              }
  47.451 -        }
  47.452 -        else if ( pfn_type[i] == L2TAB )
  47.453 -        {
  47.454 +        } else if ( pfn_type[i] == L2TAB ) {
  47.455              if ( add_mmu_update(xc_handle, mmu,
  47.456                                  (pfn_to_mfn_table[i]<<PAGE_SHIFT) | 
  47.457                                  MMU_EXTENDED_COMMAND,
  47.458 -                                MMUEXT_PIN_L2_TABLE) )
  47.459 -            {
  47.460 +                                MMUEXT_PIN_L2_TABLE) ) {
  47.461                  printf("ERR pin L2 pfn=%lx mfn=%lx\n",
  47.462 -                       i, pfn_to_mfn_table[i]);
  47.463 +                       (unsigned long)i, pfn_to_mfn_table[i]);
  47.464                  goto out;
  47.465              }
  47.466          }
  47.467      }
  47.468  
  47.469 -    if ( finish_mmu_updates(xc_handle, mmu) )
  47.470 -        goto out;
  47.471 +    if ( finish_mmu_updates(xc_handle, mmu) ) goto out;
  47.472  
  47.473 -    verbose_printf("\b\b\b\b100%%\nMemory reloaded.\n");
  47.474 +    xcio_info(ioctxt, "\b\b\b\b100%%\nMemory reloaded.\n");
  47.475  
  47.476  
  47.477 -    if ( (*readerfn)(readerst, &ctxt,                 sizeof(ctxt)) ||
  47.478 -         (*readerfn)(readerst, shared_info,           PAGE_SIZE) )
  47.479 -    {
  47.480 -        ERROR("Error when reading from state file");
  47.481 +    if ( xcio_read(ioctxt, &ctxt,                 sizeof(ctxt)) ||
  47.482 +         xcio_read(ioctxt, shared_info,           PAGE_SIZE) ) {
  47.483 +        xcio_error(ioctxt, "Error when reading from state file");
  47.484          goto out;
  47.485      }
  47.486  
  47.487 @@ -476,7 +452,7 @@ int xc_linux_restore(int xc_handle,
  47.488      pfn = ctxt.cpu_ctxt.esi;
  47.489      if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
  47.490      {
  47.491 -        ERROR("Suspend record frame number is bad");
  47.492 +        xcio_error(ioctxt, "Suspend record frame number is bad");
  47.493          goto out;
  47.494      }
  47.495      ctxt.cpu_ctxt.esi = mfn = pfn_to_mfn_table[pfn];
  47.496 @@ -487,17 +463,14 @@ int xc_linux_restore(int xc_handle,
  47.497      unmap_pfn(pm_handle, p_srec);
  47.498  
  47.499      /* Uncanonicalise each GDT frame number. */
  47.500 -    if ( ctxt.gdt_ents > 8192 )
  47.501 -    {
  47.502 -        ERROR("GDT entry count out of range");
  47.503 +    if ( ctxt.gdt_ents > 8192 ) {
  47.504 +        xcio_error(ioctxt, "GDT entry count out of range");
  47.505          goto out;
  47.506      }
  47.507 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  47.508 -    {
  47.509 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
  47.510          pfn = ctxt.gdt_frames[i];
  47.511 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
  47.512 -        {
  47.513 -            ERROR("GDT frame number is bad");
  47.514 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) {
  47.515 +            xcio_error(ioctxt, "GDT frame number is bad");
  47.516              goto out;
  47.517          }
  47.518          ctxt.gdt_frames[i] = pfn_to_mfn_table[pfn];
  47.519 @@ -505,11 +478,10 @@ int xc_linux_restore(int xc_handle,
  47.520  
  47.521      /* Uncanonicalise the page table base pointer. */
  47.522      pfn = ctxt.pt_base >> PAGE_SHIFT;
  47.523 -    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) )
  47.524 -    {
  47.525 -        printf("PT base is bad. pfn=%d nr=%d type=%08lx %08lx\n",
  47.526 -               pfn, nr_pfns, pfn_type[pfn], L2TAB);
  47.527 -        ERROR("PT base is bad.");
  47.528 +    if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) {
  47.529 +        printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n",
  47.530 +               pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB);
  47.531 +        xcio_error(ioctxt, "PT base is bad.");
  47.532          goto out;
  47.533      }
  47.534      ctxt.pt_base = pfn_to_mfn_table[pfn] << PAGE_SHIFT;
  47.535 @@ -527,14 +499,12 @@ int xc_linux_restore(int xc_handle,
  47.536  
  47.537  
  47.538      /* Uncanonicalise the pfn-to-mfn table frame-number list. */
  47.539 -    for ( i = 0; i < (nr_pfns+1023)/1024; i++ )
  47.540 -    {
  47.541 +    for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) {
  47.542          unsigned long pfn, mfn;
  47.543  
  47.544          pfn = pfn_to_mfn_frame_list[i];
  47.545 -        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) )
  47.546 -        {
  47.547 -            ERROR("PFN-to-MFN frame number is bad");
  47.548 +        if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) {
  47.549 +            xcio_error(ioctxt, "PFN-to-MFN frame number is bad");
  47.550              goto out;
  47.551          }
  47.552          mfn = pfn_to_mfn_table[pfn];
  47.553 @@ -545,9 +515,8 @@ int xc_linux_restore(int xc_handle,
  47.554            mfn_mapper_map_batch(xc_handle, dom, 
  47.555                                 PROT_WRITE,
  47.556                                 pfn_to_mfn_frame_list,
  47.557 -                               (nr_pfns+1023)/1024 )) == 0 )
  47.558 -    {
  47.559 -        ERROR("Couldn't map pfn_to_mfn table");
  47.560 +                               (nr_pfns+1023)/1024 )) == 0 ) {
  47.561 +        xcio_error(ioctxt, "Couldn't map pfn_to_mfn table");
  47.562          goto out;
  47.563      }
  47.564  
  47.565 @@ -569,24 +538,26 @@ int xc_linux_restore(int xc_handle,
  47.566       *  9. debugregs are checked by Xen.
  47.567       *  10. callback code selectors need checking.
  47.568       */
  47.569 -    for ( i = 0; i < 256; i++ )
  47.570 -    {
  47.571 +    for ( i = 0; i < 256; i++ ) {
  47.572          ctxt.trap_ctxt[i].vector = i;
  47.573          if ( (ctxt.trap_ctxt[i].cs & 3) == 0 )
  47.574              ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS;
  47.575      }
  47.576 -    if ( (ctxt.guestos_ss & 3) == 0 )
  47.577 +    if ( (ctxt.guestos_ss & 3) == 0 ){
  47.578          ctxt.guestos_ss = FLAT_GUESTOS_DS;
  47.579 -    if ( (ctxt.event_callback_cs & 3) == 0 )
  47.580 +    }
  47.581 +    if ( (ctxt.event_callback_cs & 3) == 0 ){
  47.582          ctxt.event_callback_cs = FLAT_GUESTOS_CS;
  47.583 -    if ( (ctxt.failsafe_callback_cs & 3) == 0 )
  47.584 +    }
  47.585 +    if ( (ctxt.failsafe_callback_cs & 3) == 0 ){
  47.586          ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS;
  47.587 +    }
  47.588      if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) ||
  47.589           (ctxt.ldt_ents > 8192) ||
  47.590           (ctxt.ldt_base > HYPERVISOR_VIRT_START) ||
  47.591           ((ctxt.ldt_base + ctxt.ldt_ents*8) > HYPERVISOR_VIRT_START) )
  47.592      {
  47.593 -        ERROR("Bad LDT base or size");
  47.594 +        xcio_error(ioctxt, "Bad LDT base or size");
  47.595          goto out;
  47.596      }
  47.597     
  47.598 @@ -597,34 +568,33 @@ int xc_linux_restore(int xc_handle,
  47.599  
  47.600      /* don't start the domain as we have console etc to set up */
  47.601    
  47.602 -    if( rc == 0 )
  47.603 -    {
  47.604 +    if( rc == 0 ) {
  47.605          /* Success: print the domain id. */
  47.606 -        verbose_printf("DOM=%u\n", dom);
  47.607 +        xcio_info(ioctxt, "DOM=%lu\n", dom);
  47.608          return 0;
  47.609      }
  47.610  
  47.611  
  47.612   out:
  47.613 -    if ( (rc != 0) && (dom != 0) )
  47.614 +    if ( (rc != 0) && (dom != 0) ){
  47.615          xc_domain_destroy(xc_handle, dom);
  47.616 -
  47.617 -    if ( mmu != NULL )
  47.618 +    }
  47.619 +    if ( mmu != NULL ){
  47.620          free(mmu);
  47.621 -
  47.622 -    if ( pm_handle >= 0 )
  47.623 +    }
  47.624 +    if ( pm_handle >= 0 ){
  47.625          (void)close_pfn_mapper(pm_handle);
  47.626 +    }
  47.627 +    if ( pfn_to_mfn_table != NULL ){
  47.628 +        free(pfn_to_mfn_table);
  47.629 +    }
  47.630 +    if ( pfn_type != NULL ){
  47.631 +        free(pfn_type);
  47.632 +    }
  47.633  
  47.634 -    if ( pfn_to_mfn_table != NULL )
  47.635 -        free(pfn_to_mfn_table);
  47.636 -    if ( pfn_type != NULL )
  47.637 -        free(pfn_type);
  47.638 -
  47.639 -
  47.640 -    if ( rc == 0 )
  47.641 -        *pdomid = dom;
  47.642 -
  47.643 +    if ( rc == 0 ){
  47.644 +        ioctxt->domain = dom;
  47.645 +    }
  47.646      DPRINTF("Restore exit with rc=%d\n",rc);
  47.647 -
  47.648      return rc;
  47.649  }
    48.1 --- a/tools/xc/lib/xc_linux_save.c	Tue Jun 29 00:51:10 2004 +0000
    48.2 +++ b/tools/xc/lib/xc_linux_save.c	Tue Jun 29 12:05:29 2004 +0000
    48.3 @@ -6,6 +6,7 @@
    48.4   * Copyright (c) 2003, K A Fraser.
    48.5   */
    48.6  
    48.7 +#include <sys/time.h>
    48.8  #include "xc_private.h"
    48.9  #include <asm-xen/suspend.h>
   48.10  
   48.11 @@ -26,14 +27,6 @@
   48.12  #define DDPRINTF(_f, _a...) ((void)0)
   48.13  #endif
   48.14  
   48.15 -/* This may allow us to create a 'quiet' command-line option, if necessary. */
   48.16 -#define verbose_printf(_f, _a...) \
   48.17 -    do {                          \
   48.18 -        if ( !verbose ) break;    \
   48.19 -        printf( _f , ## _a );     \
   48.20 -        fflush(stdout);           \
   48.21 -    } while ( 0 )
   48.22 -
   48.23  /*
   48.24   * Returns TRUE if the given machine frame number has a unique mapping
   48.25   * in the guest's pseudophysical map.
   48.26 @@ -189,6 +182,20 @@ static int print_stats( int xc_handle, u
   48.27      return 0;
   48.28  }
   48.29  
   48.30 +/** Write the vmconfig string.
   48.31 + * It is stored as a 4-byte count 'n' followed by n bytes.
   48.32 + *
   48.33 + * @param ioctxt i/o context
   48.34 + * @return 0 on success, non-zero on error.
   48.35 + */
   48.36 +static int write_vmconfig(XcIOContext *ioctxt){
   48.37 +    int err = -1;
   48.38 +    if(xcio_write(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))) goto exit;
   48.39 +    if(xcio_write(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)) goto exit;
   48.40 +    err = 0;
   48.41 +  exit:
   48.42 +    return err;
   48.43 +}
   48.44  
   48.45  static int analysis_phase( int xc_handle, u32 domid, 
   48.46                             int nr_pfns, unsigned long *arr )
   48.47 @@ -225,19 +232,15 @@ static int analysis_phase( int xc_handle
   48.48      return -1;
   48.49  }
   48.50  
   48.51 -int xc_linux_save(int xc_handle,
   48.52 -                  u32 domid, 
   48.53 -                  unsigned int flags,
   48.54 -                  int (*writerfn)(void *, const void *, size_t),
   48.55 -                  void *writerst )
   48.56 +int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
   48.57  {
   48.58      dom0_op_t op;
   48.59      int rc = 1, i, j, k, last_iter, iter = 0;
   48.60      unsigned long mfn;
   48.61 -    int verbose = flags & XCFLAGS_VERBOSE;
   48.62 -    int live = flags & XCFLAGS_LIVE;
   48.63 -    int debug = flags & XCFLAGS_DEBUG;
   48.64 -    int sent_last_iter, sent_this_iter, skip_this_iter;
   48.65 +    u32 domid = ioctxt->domain;
   48.66 +    int live = (ioctxt->flags & XCFLAGS_LIVE);
   48.67 +    int debug = (ioctxt->flags & XCFLAGS_DEBUG);
   48.68 +    int sent_last_iter, skip_this_iter;
   48.69  
   48.70      /* Important tuning parameters */
   48.71      int max_iters  = 29; /* limit us to 30 times round loop */
   48.72 @@ -272,7 +275,7 @@ int xc_linux_save(int xc_handle,
   48.73      unsigned long *live_shinfo;
   48.74  
   48.75      /* base of the region in which domain memory is mapped */
   48.76 -    unsigned char *region_base;
   48.77 +    unsigned char *region_base = NULL;
   48.78  
   48.79      /* A temporary mapping, and a copy, of the guest's suspend record. */
   48.80      suspend_record_t *p_srec;
   48.81 @@ -294,17 +297,14 @@ int xc_linux_save(int xc_handle,
   48.82      int needed_to_fix = 0;
   48.83      int total_sent    = 0;
   48.84      
   48.85 -    if ( mlock(&ctxt, sizeof(ctxt) ) )
   48.86 -    {
   48.87 -        PERROR("Unable to mlock ctxt");
   48.88 +    if (mlock(&ctxt, sizeof(ctxt))) {
   48.89 +        xcio_perror(ioctxt, "Unable to mlock ctxt");
   48.90          return 1;
   48.91      }
   48.92  
   48.93      /* Ensure that the domain exists, and that it is stopped. */
   48.94 -
   48.95 -    if ( xc_domain_pause( xc_handle, domid ) )
   48.96 -    {
   48.97 -        PERROR("Could not pause domain");
   48.98 +    if ( xc_domain_pause(xc_handle, domid) ){
   48.99 +        xcio_perror(ioctxt, "Could not pause domain");
  48.100          goto out;
  48.101      }
  48.102  
  48.103 @@ -317,9 +317,8 @@ int xc_linux_save(int xc_handle,
  48.104      shared_info_frame = op.u.getdomaininfo.shared_info_frame;
  48.105  
  48.106      /* A cheesy test to see whether the domain contains valid state. */
  48.107 -    if ( ctxt.pt_base == 0 )
  48.108 -    {
  48.109 -        ERROR("Domain is not in a valid Linux guest OS state");
  48.110 +    if ( ctxt.pt_base == 0 ){
  48.111 +        xcio_error(ioctxt, "Domain is not in a valid Linux guest OS state");
  48.112          goto out;
  48.113      }
  48.114  
  48.115 @@ -327,20 +326,17 @@ int xc_linux_save(int xc_handle,
  48.116         domid for this to succeed. */
  48.117      p_srec = mfn_mapper_map_single(xc_handle, domid,
  48.118                                     sizeof(*p_srec), PROT_READ, 
  48.119 -                                   ctxt.cpu_ctxt.esi );
  48.120 -
  48.121 -    if (!p_srec)
  48.122 -    {
  48.123 -        ERROR("Couldn't map state record");
  48.124 +                                   ctxt.cpu_ctxt.esi);
  48.125 +    if (!p_srec){
  48.126 +        xcio_error(ioctxt, "Couldn't map state record");
  48.127          goto out;
  48.128      }
  48.129  
  48.130      nr_pfns = p_srec->nr_pfns;
  48.131  
  48.132      /* cheesy sanity check */
  48.133 -    if ( nr_pfns > 1024*1024 )
  48.134 -    {
  48.135 -        ERROR("Invalid state record -- pfn count out of range");
  48.136 +    if ( nr_pfns > 1024*1024 ){
  48.137 +        xcio_error(ioctxt, "Invalid state record -- pfn count out of range");
  48.138          goto out;
  48.139      }
  48.140  
  48.141 @@ -350,9 +346,8 @@ int xc_linux_save(int xc_handle,
  48.142                                PAGE_SIZE, PROT_READ, 
  48.143                                p_srec->pfn_to_mfn_frame_list );
  48.144  
  48.145 -    if (!live_pfn_to_mfn_frame_list)
  48.146 -    {
  48.147 -        ERROR("Couldn't map pfn_to_mfn_frame_list");
  48.148 +    if (!live_pfn_to_mfn_frame_list){
  48.149 +        xcio_error(ioctxt, "Couldn't map pfn_to_mfn_frame_list");
  48.150          goto out;
  48.151      }
  48.152  
  48.153 @@ -379,24 +374,21 @@ int xc_linux_save(int xc_handle,
  48.154         (its not clear why it would want to change them, and we'll be OK
  48.155         from a safety POV anyhow. */
  48.156  
  48.157 -    live_pfn_to_mfn_table = mfn_mapper_map_batch( xc_handle, domid, 
  48.158 -                                                  PROT_READ,
  48.159 -                                                  live_pfn_to_mfn_frame_list,
  48.160 -                                                  (nr_pfns+1023)/1024 );  
  48.161 -    if( !live_pfn_to_mfn_table )
  48.162 -    {
  48.163 -        PERROR("Couldn't map pfn_to_mfn table");
  48.164 +    live_pfn_to_mfn_table = mfn_mapper_map_batch(xc_handle, domid, 
  48.165 +                                                 PROT_READ,
  48.166 +                                                 live_pfn_to_mfn_frame_list,
  48.167 +                                                 (nr_pfns+1023)/1024 );  
  48.168 +    if( !live_pfn_to_mfn_table ){
  48.169 +        xcio_perror(ioctxt, "Couldn't map pfn_to_mfn table");
  48.170          goto out;
  48.171      }
  48.172  
  48.173  
  48.174      /* Canonicalise the pfn-to-mfn table frame-number list. */
  48.175      memcpy( pfn_to_mfn_frame_list, live_pfn_to_mfn_frame_list, PAGE_SIZE );
  48.176 -    for ( i = 0; i < nr_pfns; i += 1024 )
  48.177 -    {
  48.178 -        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) )
  48.179 -        {
  48.180 -            ERROR("Frame # in pfn-to-mfn frame list is not in pseudophys");
  48.181 +    for ( i = 0; i < nr_pfns; i += 1024 ){
  48.182 +        if ( !translate_mfn_to_pfn(&pfn_to_mfn_frame_list[i/1024]) ){
  48.183 +            xcio_error(ioctxt, "Frame # in pfn-to-mfn frame list is not in pseudophys");
  48.184              goto out;
  48.185          }
  48.186      }
  48.187 @@ -404,27 +396,24 @@ int xc_linux_save(int xc_handle,
  48.188      /* At this point, we can start the domain again if we're doing a
  48.189         live suspend */
  48.190  
  48.191 -    if( live )
  48.192 -    { 
  48.193 +    if( live ){ 
  48.194          if ( xc_shadow_control( xc_handle, domid, 
  48.195                                  DOM0_SHADOW_CONTROL_OP_ENABLE_LOGDIRTY,
  48.196 -                                NULL, 0, NULL ) < 0 )
  48.197 -        {
  48.198 -            ERROR("Couldn't enable shadow mode");
  48.199 +                                NULL, 0, NULL ) < 0 ) {
  48.200 +            xcio_error(ioctxt, "Couldn't enable shadow mode");
  48.201              goto out;
  48.202          }
  48.203  
  48.204 -        if ( xc_domain_unpause( xc_handle, domid ) < 0 )
  48.205 -        {
  48.206 -            ERROR("Couldn't unpause domain");
  48.207 +        if ( xc_domain_unpause(xc_handle, domid) < 0 ){
  48.208 +            xcio_error(ioctxt, "Couldn't unpause domain");
  48.209              goto out;
  48.210          }
  48.211  
  48.212          last_iter = 0;
  48.213          sent_last_iter = 1<<20; /* 4GB of pages */
  48.214 +    } else{
  48.215 +        last_iter = 1;
  48.216      }
  48.217 -    else
  48.218 -        last_iter = 1;
  48.219  
  48.220      /* calculate the power of 2 order of nr_pfns, e.g.
  48.221         15->4 16->4 17->5 */
  48.222 @@ -438,25 +427,22 @@ int xc_linux_save(int xc_handle,
  48.223          to_fix  = calloc( 1, sz );
  48.224          to_skip = malloc( sz );
  48.225  
  48.226 -        if (!to_send || !to_fix || !to_skip)
  48.227 -        {
  48.228 -            ERROR("Couldn't allocate to_send array");
  48.229 +        if (!to_send || !to_fix || !to_skip){
  48.230 +            xcio_error(ioctxt, "Couldn't allocate to_send array");
  48.231              goto out;
  48.232          }
  48.233  
  48.234          memset( to_send, 0xff, sz );
  48.235  
  48.236 -        if ( mlock( to_send, sz ) )
  48.237 -        {
  48.238 -            PERROR("Unable to mlock to_send");
  48.239 +        if ( mlock( to_send, sz ) ){
  48.240 +            xcio_perror(ioctxt, "Unable to mlock to_send");
  48.241              return 1;
  48.242          }
  48.243  
  48.244          /* (to fix is local only) */
  48.245  
  48.246 -        if ( mlock( to_skip, sz ) )
  48.247 -        {
  48.248 -            PERROR("Unable to mlock to_skip");
  48.249 +        if ( mlock( to_skip, sz ) ){
  48.250 +            xcio_perror(ioctxt, "Unable to mlock to_skip");
  48.251              return 1;
  48.252          }
  48.253  
  48.254 @@ -468,15 +454,13 @@ int xc_linux_save(int xc_handle,
  48.255      pfn_type = calloc(BATCH_SIZE, sizeof(unsigned long));
  48.256      pfn_batch = calloc(BATCH_SIZE, sizeof(unsigned long));
  48.257  
  48.258 -    if ( (pfn_type == NULL) || (pfn_batch == NULL) )
  48.259 -    {
  48.260 +    if ( (pfn_type == NULL) || (pfn_batch == NULL) ){
  48.261          errno = ENOMEM;
  48.262          goto out;
  48.263      }
  48.264  
  48.265 -    if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) )
  48.266 -    {
  48.267 -        ERROR("Unable to mlock");
  48.268 +    if ( mlock( pfn_type, BATCH_SIZE * sizeof(unsigned long) ) ){
  48.269 +        xcio_error(ioctxt, "Unable to mlock");
  48.270          goto out;
  48.271      }
  48.272  
  48.273 @@ -485,8 +469,7 @@ int xc_linux_save(int xc_handle,
  48.274       * Quick belt and braces sanity check.
  48.275       */
  48.276  #if DEBUG
  48.277 -    for ( i = 0; i < nr_pfns; i++ )
  48.278 -    {
  48.279 +    for ( i = 0; i < nr_pfns; i++ ){
  48.280          mfn = live_pfn_to_mfn_table[i];
  48.281  
  48.282          if( (live_mfn_to_pfn_table[mfn] != i) && (mfn != 0x80000004) )
  48.283 @@ -500,20 +483,22 @@ int xc_linux_save(int xc_handle,
  48.284                                          PAGE_SIZE, PROT_READ,
  48.285                                          shared_info_frame);
  48.286  
  48.287 -    if (!live_shinfo)
  48.288 -    {
  48.289 -        ERROR("Couldn't map live_shinfo");
  48.290 +    if (!live_shinfo){
  48.291 +        xcio_error(ioctxt, "Couldn't map live_shinfo");
  48.292          goto out;
  48.293      }
  48.294  
  48.295      /* Start writing out the saved-domain record. */
  48.296  
  48.297 -    if ( (*writerfn)(writerst, "LinuxGuestRecord",    16) ||
  48.298 -         (*writerfn)(writerst, name,                  sizeof(name)) ||
  48.299 -         (*writerfn)(writerst, &nr_pfns,              sizeof(unsigned long)) ||
  48.300 -         (*writerfn)(writerst, pfn_to_mfn_frame_list, PAGE_SIZE) )
  48.301 -    {
  48.302 -        ERROR("Error when writing to state file (1)");
  48.303 +    if ( xcio_write(ioctxt, "LinuxGuestRecord",    16) ||
  48.304 +         xcio_write(ioctxt, name,                  sizeof(name)) ||
  48.305 +         xcio_write(ioctxt, &nr_pfns,              sizeof(unsigned long)) ||
  48.306 +         xcio_write(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ){
  48.307 +        xcio_error(ioctxt, "Error writing header");
  48.308 +        goto out;
  48.309 +    }
  48.310 +    if(write_vmconfig(ioctxt)){
  48.311 +        xcio_error(ioctxt, "Error writing vmconfig");
  48.312          goto out;
  48.313      }
  48.314  
  48.315 @@ -521,8 +506,7 @@ int xc_linux_save(int xc_handle,
  48.316  
  48.317      /* Now write out each data page, canonicalising page tables as we go... */
  48.318      
  48.319 -    while(1)
  48.320 -    {
  48.321 +    while(1){
  48.322          unsigned int prev_pc, sent_this_iter, N, batch;
  48.323  
  48.324          iter++;
  48.325 @@ -531,15 +515,13 @@ int xc_linux_save(int xc_handle,
  48.326          prev_pc = 0;
  48.327          N=0;
  48.328  
  48.329 -        verbose_printf("Saving memory pages: iter %d   0%%", iter);
  48.330 +        xcio_info(ioctxt, "Saving memory pages: iter %d   0%%", iter);
  48.331  
  48.332 -        while( N < nr_pfns )
  48.333 -        {
  48.334 +        while( N < nr_pfns ){
  48.335              unsigned int this_pc = (N * 100) / nr_pfns;
  48.336  
  48.337 -            if ( (this_pc - prev_pc) >= 5 )
  48.338 -            {
  48.339 -                verbose_printf("\b\b\b\b%3d%%", this_pc);
  48.340 +            if ( (this_pc - prev_pc) >= 5 ){
  48.341 +                xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc);
  48.342                  prev_pc = this_pc;
  48.343              }
  48.344  
  48.345 @@ -549,9 +531,8 @@ int xc_linux_save(int xc_handle,
  48.346              if ( !last_iter && 
  48.347                   xc_shadow_control(xc_handle, domid, 
  48.348                                     DOM0_SHADOW_CONTROL_OP_PEEK,
  48.349 -                                   to_skip, nr_pfns, NULL) != nr_pfns ) 
  48.350 -            {
  48.351 -                ERROR("Error peeking shadow bitmap");
  48.352 +                                   to_skip, nr_pfns, NULL) != nr_pfns ) {
  48.353 +                xcio_error(ioctxt, "Error peeking shadow bitmap");
  48.354                  goto out;
  48.355              }
  48.356       
  48.357 @@ -563,23 +544,26 @@ int xc_linux_save(int xc_handle,
  48.358              {
  48.359                  int n = permute(N, nr_pfns, order_nr );
  48.360  
  48.361 -                if ( 0 && debug )
  48.362 +                if ( 0 && debug ) {
  48.363                      fprintf(stderr,"%d pfn= %08lx mfn= %08lx %d  "
  48.364                              " [mfn]= %08lx\n",
  48.365 -                            iter, n, live_pfn_to_mfn_table[n],
  48.366 +                            iter, (unsigned long)n, live_pfn_to_mfn_table[n],
  48.367                              test_bit(n,to_send),
  48.368                              live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&
  48.369                                                   0xFFFFF]);
  48.370 +                }
  48.371  
  48.372                  if ( !last_iter && 
  48.373                       test_bit(n, to_send) && 
  48.374 -                     test_bit(n, to_skip) )
  48.375 +                     test_bit(n, to_skip) ) {
  48.376                      skip_this_iter++; /* stats keeping */
  48.377 +                }
  48.378  
  48.379                  if ( !((test_bit(n, to_send) && !test_bit(n, to_skip)) ||
  48.380                         (test_bit(n, to_send) && last_iter) ||
  48.381 -                       (test_bit(n, to_fix)  && last_iter)) )
  48.382 +                       (test_bit(n, to_fix)  && last_iter)) ) {
  48.383                      continue;
  48.384 +                }
  48.385  
  48.386                  /* we get here if:
  48.387                     1. page is marked to_send & hasn't already been re-dirtied
  48.388 @@ -590,8 +574,7 @@ int xc_linux_save(int xc_handle,
  48.389                  pfn_batch[batch] = n;
  48.390                  pfn_type[batch] = live_pfn_to_mfn_table[n];
  48.391  
  48.392 -                if( pfn_type[batch] == 0x80000004 )
  48.393 -                {
  48.394 +                if( pfn_type[batch] == 0x80000004 ){
  48.395                      /* not currently in pusedo-physical map -- set bit
  48.396                         in to_fix that we must send this page in last_iter
  48.397                         unless its sent sooner anyhow */
  48.398 @@ -625,22 +608,18 @@ int xc_linux_save(int xc_handle,
  48.399              if ( (region_base = mfn_mapper_map_batch(xc_handle, domid, 
  48.400                                                       PROT_READ,
  48.401                                                       pfn_type,
  48.402 -                                                     batch)) == 0 )
  48.403 -            {
  48.404 -                PERROR("map batch failed");
  48.405 +                                                     batch)) == 0 ){
  48.406 +                xcio_perror(ioctxt, "map batch failed");
  48.407                  goto out;
  48.408              }
  48.409       
  48.410 -            if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) )
  48.411 -            {
  48.412 -                ERROR("get_pfn_type_batch failed");
  48.413 +            if ( get_pfn_type_batch(xc_handle, domid, batch, pfn_type) ){
  48.414 +                xcio_error(ioctxt, "get_pfn_type_batch failed");
  48.415                  goto out;
  48.416              }
  48.417       
  48.418 -            for ( j = 0; j < batch; j++ )
  48.419 -            {
  48.420 -                if ( (pfn_type[j] & LTAB_MASK) == XTAB )
  48.421 -                {
  48.422 +            for ( j = 0; j < batch; j++ ){
  48.423 +                if ( (pfn_type[j] & LTAB_MASK) == XTAB ){
  48.424                      DDPRINTF("type fail: page %i mfn %08lx\n",j,pfn_type[j]);
  48.425                      continue;
  48.426                  }
  48.427 @@ -658,39 +637,33 @@ int xc_linux_save(int xc_handle,
  48.428                  pfn_type[j] = (pfn_type[j] & LTAB_MASK) | pfn_batch[j];
  48.429              }
  48.430  
  48.431 -            if ( (*writerfn)(writerst, &batch, sizeof(int) ) )
  48.432 -            {
  48.433 -                ERROR("Error when writing to state file (2)");
  48.434 +            if ( xcio_write(ioctxt, &batch, sizeof(int) ) ){
  48.435 +                xcio_error(ioctxt, "Error when writing to state file (2)");
  48.436                  goto out;
  48.437              }
  48.438  
  48.439 -            if ( (*writerfn)(writerst, pfn_type, sizeof(unsigned long)*j ) )
  48.440 -            {
  48.441 -                ERROR("Error when writing to state file (3)");
  48.442 +            if ( xcio_write(ioctxt, pfn_type, sizeof(unsigned long)*j ) ){
  48.443 +                xcio_error(ioctxt, "Error when writing to state file (3)");
  48.444                  goto out;
  48.445              }
  48.446       
  48.447              /* entering this loop, pfn_type is now in pfns (Not mfns) */
  48.448 -            for( j = 0; j < batch; j++ )
  48.449 -            {
  48.450 +            for( j = 0; j < batch; j++ ){
  48.451                  /* write out pages in batch */
  48.452 -                if( (pfn_type[j] & LTAB_MASK) == XTAB)
  48.453 -                {
  48.454 +                if( (pfn_type[j] & LTAB_MASK) == XTAB){
  48.455                      DDPRINTF("SKIP BOGUS page %i mfn %08lx\n",j,pfn_type[j]);
  48.456                      continue;
  48.457                  }
  48.458    
  48.459                  if ( ((pfn_type[j] & LTAB_MASK) == L1TAB) || 
  48.460 -                     ((pfn_type[j] & LTAB_MASK) == L2TAB) )
  48.461 -                {
  48.462 +                     ((pfn_type[j] & LTAB_MASK) == L2TAB) ){
  48.463                      memcpy(page, region_base + (PAGE_SIZE*j), PAGE_SIZE);
  48.464        
  48.465                      for ( k = 0; 
  48.466                            k < (((pfn_type[j] & LTAB_MASK) == L2TAB) ? 
  48.467                                 (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT) :
  48.468                                 1024); 
  48.469 -                          k++ )
  48.470 -                    {
  48.471 +                          k++ ){
  48.472                          unsigned long pfn;
  48.473  
  48.474                          if ( !(page[k] & _PAGE_PRESENT) )
  48.475 @@ -726,20 +699,16 @@ int xc_linux_save(int xc_handle,
  48.476     
  48.477                      } /* end of page table rewrite for loop */
  48.478        
  48.479 -                    if ( (*writerfn)(writerst, page, PAGE_SIZE) )
  48.480 -                    {
  48.481 -                        ERROR("Error when writing to state file (4)");
  48.482 +                    if ( xcio_write(ioctxt, page, PAGE_SIZE) ){
  48.483 +                        xcio_error(ioctxt, "Error when writing to state file (4)");
  48.484                          goto out;
  48.485                      }
  48.486        
  48.487 -                }  /* end of it's a PT page */
  48.488 -                else
  48.489 -                {  /* normal page */
  48.490 +                }  /* end of it's a PT page */ else {  /* normal page */
  48.491  
  48.492 -                    if ( (*writerfn)(writerst, region_base + (PAGE_SIZE*j),
  48.493 -                                     PAGE_SIZE) )
  48.494 -                    {
  48.495 -                        ERROR("Error when writing to state file (5)");
  48.496 +                    if ( xcio_write(ioctxt, region_base + (PAGE_SIZE*j), 
  48.497 +                                     PAGE_SIZE) ){
  48.498 +                        xcio_error(ioctxt, "Error when writing to state file (5)");
  48.499                          goto out;
  48.500                      }
  48.501                  }
  48.502 @@ -755,37 +724,34 @@ int xc_linux_save(int xc_handle,
  48.503  
  48.504          total_sent += sent_this_iter;
  48.505  
  48.506 -        verbose_printf("\r %d: sent %d, skipped %d, ", 
  48.507 +        xcio_info(ioctxt, "\r %d: sent %d, skipped %d, ", 
  48.508                         iter, sent_this_iter, skip_this_iter );
  48.509  
  48.510 -        if ( last_iter )
  48.511 -        {
  48.512 +        if ( last_iter ) {
  48.513              print_stats( xc_handle, domid, sent_this_iter, &stats, 1);
  48.514  
  48.515 -            verbose_printf("Total pages sent= %d (%.2fx)\n", 
  48.516 +            xcio_info(ioctxt, "Total pages sent= %d (%.2fx)\n", 
  48.517                             total_sent, ((float)total_sent)/nr_pfns );
  48.518 -            verbose_printf("(of which %d were fixups)\n", needed_to_fix  );
  48.519 +            xcio_info(ioctxt, "(of which %d were fixups)\n", needed_to_fix  );
  48.520          }       
  48.521  
  48.522 -        if ( debug && last_iter )
  48.523 -        {
  48.524 +        if (last_iter && debug){
  48.525              int minusone = -1;
  48.526              memset( to_send, 0xff, (nr_pfns+8)/8 );
  48.527              debug = 0;
  48.528              printf("Entering debug resend-all mode\n");
  48.529      
  48.530              /* send "-1" to put receiver into debug mode */
  48.531 -            if ( (*writerfn)(writerst, &minusone, sizeof(int)) )
  48.532 +            if ( xcio_write(ioctxt, &minusone, sizeof(int)) )
  48.533              {
  48.534 -                ERROR("Error when writing to state file (6)");
  48.535 +                xcio_error(ioctxt, "Error when writing to state file (6)");
  48.536                  goto out;
  48.537              }
  48.538  
  48.539              continue;
  48.540          }
  48.541  
  48.542 -        if ( last_iter )
  48.543 -            break;
  48.544 +        if ( last_iter ) break;
  48.545  
  48.546          if ( live )
  48.547          {
  48.548 @@ -805,7 +771,7 @@ int xc_linux_save(int xc_handle,
  48.549                                      DOM0_SHADOW_CONTROL_OP_CLEAN2,
  48.550                                      to_send, nr_pfns, &stats ) != nr_pfns ) 
  48.551              {
  48.552 -                ERROR("Error flushing shadow PT");
  48.553 +                xcio_error(ioctxt, "Error flushing shadow PT");
  48.554                  goto out;
  48.555              }
  48.556  
  48.557 @@ -824,60 +790,51 @@ int xc_linux_save(int xc_handle,
  48.558      rc = 0;
  48.559      
  48.560      /* Zero terminate */
  48.561 -    if ( (*writerfn)(writerst, &rc, sizeof(int)) )
  48.562 +    if ( xcio_write(ioctxt, &rc, sizeof(int)) )
  48.563      {
  48.564 -        ERROR("Error when writing to state file (6)");
  48.565 +        xcio_error(ioctxt, "Error when writing to state file (6)");
  48.566          goto out;
  48.567      }
  48.568  
  48.569      /* Get the final execution context */
  48.570      if ( xc_domain_getfullinfo( xc_handle, domid, &op, &ctxt) )
  48.571      {
  48.572 -        PERROR("Could not get full domain info");
  48.573 +        xcio_perror(ioctxt, "Could not get full domain info");
  48.574          goto out;
  48.575      }
  48.576  
  48.577      /* Canonicalise the suspend-record frame number. */
  48.578 -    if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) )
  48.579 -    {
  48.580 -        ERROR("State record is not in range of pseudophys map");
  48.581 +    if ( !translate_mfn_to_pfn(&ctxt.cpu_ctxt.esi) ){
  48.582 +        xcio_error(ioctxt, "State record is not in range of pseudophys map");
  48.583          goto out;
  48.584      }
  48.585  
  48.586      /* Canonicalise each GDT frame number. */
  48.587 -    for ( i = 0; i < ctxt.gdt_ents; i += 512 )
  48.588 -    {
  48.589 -        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) )
  48.590 -        {
  48.591 -            ERROR("GDT frame is not in range of pseudophys map");
  48.592 +    for ( i = 0; i < ctxt.gdt_ents; i += 512 ) {
  48.593 +        if ( !translate_mfn_to_pfn(&ctxt.gdt_frames[i]) ) {
  48.594 +            xcio_error(ioctxt, "GDT frame is not in range of pseudophys map");
  48.595              goto out;
  48.596          }
  48.597      }
  48.598  
  48.599      /* Canonicalise the page table base pointer. */
  48.600 -    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) )
  48.601 -    {
  48.602 -        ERROR("PT base is not in range of pseudophys map");
  48.603 +    if ( !MFN_IS_IN_PSEUDOPHYS_MAP(ctxt.pt_base >> PAGE_SHIFT) ) {
  48.604 +        xcio_error(ioctxt, "PT base is not in range of pseudophys map");
  48.605          goto out;
  48.606      }
  48.607      ctxt.pt_base = live_mfn_to_pfn_table[ctxt.pt_base >> PAGE_SHIFT] <<
  48.608          PAGE_SHIFT;
  48.609  
  48.610 -    if ( (*writerfn)(writerst, &ctxt,       sizeof(ctxt)) ||
  48.611 -         (*writerfn)(writerst, live_shinfo, PAGE_SIZE) )
  48.612 -    {
  48.613 -        ERROR("Error when writing to state file (1)");
  48.614 +    if ( xcio_write(ioctxt, &ctxt,       sizeof(ctxt)) ||
  48.615 +         xcio_write(ioctxt, live_shinfo, PAGE_SIZE) ) {
  48.616 +        xcio_error(ioctxt, "Error when writing to state file (1)");
  48.617          goto out;
  48.618      }
  48.619      munmap(live_shinfo, PAGE_SIZE);
  48.620  
  48.621   out:
  48.622 -
  48.623 -    if ( pfn_type != NULL )
  48.624 -        free(pfn_type);
  48.625 -
  48.626 +    if ( pfn_type != NULL ) free(pfn_type);
  48.627      DPRINTF("Save exit rc=%d\n",rc);
  48.628 -    
  48.629      return !!rc;
  48.630  
  48.631  }
    49.1 --- a/tools/xc/lib/xc_private.h	Tue Jun 29 00:51:10 2004 +0000
    49.2 +++ b/tools/xc/lib/xc_private.h	Tue Jun 29 12:05:29 2004 +0000
    49.3 @@ -136,6 +136,8 @@ int close_pfn_mapper(int pm_handle);
    49.4  void *map_pfn_writeable(int pm_handle, unsigned long pfn);
    49.5  void *map_pfn_readonly(int pm_handle, unsigned long pfn);
    49.6  void unmap_pfn(int pm_handle, void *vaddr);
    49.7 +int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
    49.8 +unsigned long csum_page (void * page);
    49.9  
   49.10  /*
   49.11   * MMU updates.
   49.12 @@ -202,4 +204,10 @@ void * mfn_mapper_queue_entry(mfn_mapper
   49.13  
   49.14  long long  xc_domain_get_cpu_usage( int xc_handle, domid_t domid );
   49.15  
   49.16 +#include "xc_io.h"
   49.17 +
   49.18 +int xc_domain_getfullinfo(int xc_handle,
   49.19 +                          u32 domid,
   49.20 +                          dom0_op_t *op,
   49.21 +                          full_execution_context_t *ctxt );
   49.22  #endif /* __XC_PRIVATE_H__ */
    50.1 --- a/tools/xc/py/Xc.c	Tue Jun 29 00:51:10 2004 +0000
    50.2 +++ b/tools/xc/py/Xc.c	Tue Jun 29 12:05:29 2004 +0000
    50.3 @@ -14,6 +14,8 @@
    50.4  #include <sys/socket.h>
    50.5  #include <netdb.h>
    50.6  #include <arpa/inet.h>
    50.7 +#include "xc_private.h"
    50.8 +#include "gzip_stream.h"
    50.9  
   50.10  /* Needed for Python versions earlier than 2.3. */
   50.11  #ifndef PyMODINIT_FUNC
   50.12 @@ -189,115 +191,35 @@ static PyObject *pyxc_domain_getinfo(PyO
   50.13      return list;
   50.14  }
   50.15  
   50.16 -static PyObject *tcp_save(XcObject *xc, u32 dom, char *url, unsigned flags){
   50.17 -#define max_namelen 64
   50.18 -    char server[max_namelen];
   50.19 -    char *port_s;
   50.20 -    int port=777;
   50.21 -    int sd = -1;
   50.22 -    struct hostent *h;
   50.23 -    struct sockaddr_in s;
   50.24 -    int sockbufsize;
   50.25 +static int file_save(XcObject *xc, XcIOContext *ctxt, char *state_file){
   50.26      int rc = -1;
   50.27 -    
   50.28 -    int writerfn(void *fd, const void *buf, size_t count) {
   50.29 -        int tot = 0, rc;
   50.30 -        do {
   50.31 -            rc = write( (int) fd, ((char*)buf)+tot, count-tot );
   50.32 -            if ( rc < 0 ) { perror("WRITE"); return rc; };
   50.33 -            tot += rc;
   50.34 -        }
   50.35 -        while ( tot < count );
   50.36 -        return 0;
   50.37 -    }
   50.38 -    
   50.39 -    strncpy( server, url+strlen("tcp://"), max_namelen);
   50.40 -    server[max_namelen-1]='\0';
   50.41 -    if ( (port_s = strchr(server,':')) != NULL ) {
   50.42 -        *port_s = '\0';
   50.43 -        port = atoi(port_s+1);
   50.44 -    }
   50.45 -    printf("X server=%s port=%d\n",server,port);
   50.46 -    h = gethostbyname(server);
   50.47 -    sd = socket(AF_INET, SOCK_STREAM,0);
   50.48 -    if (sd < 0) goto serr;
   50.49 -    s.sin_family = AF_INET;
   50.50 -    bcopy ( h->h_addr, &(s.sin_addr.s_addr), h->h_length);
   50.51 -    s.sin_port = htons(port);
   50.52 -    if ( connect(sd, (struct sockaddr *) &s, sizeof(s)) ) goto serr;
   50.53 -    sockbufsize=128*1024;
   50.54 -    if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, sizeof sockbufsize) < 0 ) goto serr;
   50.55 -
   50.56 -    if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, (void*)sd) == 0 ) {
   50.57 -        if ( read( sd, &rc, sizeof(int) ) != sizeof(int) ) goto serr;
   50.58 -  
   50.59 -        if ( rc == 0 ) {
   50.60 -                printf("Migration succesful -- destroy local copy\n");
   50.61 -                xc_domain_destroy(xc->xc_handle, dom);
   50.62 -                close(sd);
   50.63 -                Py_INCREF(zero);
   50.64 -                return zero;
   50.65 -        } else {
   50.66 -            errno = rc;
   50.67 -        }
   50.68 -    }
   50.69 +    int fd = -1;
   50.70 +    int open_flags = (O_CREAT | O_EXCL | O_WRONLY);
   50.71 +    int open_mode = 0644;
   50.72  
   50.73 -  serr:
   50.74 -    printf("Migration failed -- restart local copy\n");
   50.75 -    xc_domain_unpause(xc->xc_handle, dom);
   50.76 -    PyErr_SetFromErrno(xc_error);
   50.77 -    if ( sd >= 0 ) close(sd);
   50.78 -    return NULL;
   50.79 -
   50.80 -}
   50.81 -
   50.82 -static PyObject *file_save(XcObject *xc, u32 dom, char *state_file, unsigned flags){
   50.83 -        int fd = -1;
   50.84 -        gzFile gfd = NULL;
   50.85 -
   50.86 -        int writerfn(void *fd, const void *buf, size_t count) {
   50.87 -            int rc;
   50.88 -            while ( ((rc = gzwrite( (gzFile*)fd, (void*)buf, count)) == -1) && 
   50.89 -                    (errno = EINTR) )
   50.90 -                continue;
   50.91 -            return ! (rc == count);
   50.92 -        }
   50.93 -
   50.94 -        if (strncmp(state_file,"file:",strlen("file:")) == 0){
   50.95 -            state_file += strlen("file:");
   50.96 -        }
   50.97 -
   50.98 -        if ( (fd = open(state_file, O_CREAT|O_EXCL|O_WRONLY, 0644)) == -1 ) {
   50.99 -            perror("Could not open file for writing");
  50.100 -            goto err;
  50.101 -        }
  50.102 -        /*
  50.103 -         * Compression rate 1: we want speed over compression. 
  50.104 -         * We're mainly going for those zero pages, after all.
  50.105 -         */
  50.106 -        if ( (gfd = gzdopen(fd, "wb1")) == NULL ) {
  50.107 -            perror("Could not allocate compression state for state file");
  50.108 -            close(fd);
  50.109 -            goto err;
  50.110 -        }
  50.111 -        if ( xc_linux_save(xc->xc_handle, dom, flags, writerfn, gfd) == 0 ) {
  50.112 -            /* kill domain. We don't want to do this for checkpointing, but
  50.113 -               if we don't do it here I think people will hurt themselves
  50.114 -               by accident... */
  50.115 -            xc_domain_destroy(xc->xc_handle, dom);
  50.116 -            gzclose(gfd);
  50.117 -            close(fd);
  50.118 -
  50.119 -            Py_INCREF(zero);
  50.120 -            return zero;
  50.121 -        }
  50.122 -
  50.123 -    err:
  50.124 -        PyErr_SetFromErrno(xc_error);
  50.125 -        if ( gfd != NULL ) gzclose(gfd);
  50.126 -        if ( fd >= 0 ) close(fd);
  50.127 -        unlink(state_file);
  50.128 -        return NULL;
  50.129 +    printf("%s>\n", __FUNCTION__);
  50.130 +    fd = open(state_file, open_flags, open_mode);
  50.131 +    if(fd < 0){
  50.132 +        xcio_perror(ctxt, "Could not open file for writing");
  50.133 +        goto exit;
  50.134 +    }
  50.135 +    /* Compression rate 1: we want speed over compression. 
  50.136 +     * We're mainly going for those zero pages, after all.
  50.137 +     */
  50.138 +    printf("%s>gzip_stream_fdopen... \n", __FUNCTION__);
  50.139 +    ctxt->io = gzip_stream_fdopen(fd, "wb1");
  50.140 +    if(!ctxt->io){
  50.141 +        xcio_perror(ctxt, "Could not allocate compression state");
  50.142 +        goto exit;
  50.143 +    }
  50.144 +    printf("%s> xc_linux_save...\n", __FUNCTION__);
  50.145 +    rc = xc_linux_save(xc->xc_handle, ctxt);
  50.146 +  exit:
  50.147 +    if(ctxt->io) IOStream_close(ctxt->io);
  50.148 +    if(fd >= 0) close(fd);
  50.149 +    unlink(state_file);
  50.150 +    printf("%s> rc=%d\n", __FUNCTION__, rc);
  50.151 +    return rc;
  50.152  }
  50.153  
  50.154  static PyObject *pyxc_linux_save(PyObject *self,
  50.155 @@ -306,195 +228,92 @@ static PyObject *pyxc_linux_save(PyObjec
  50.156  {
  50.157      XcObject *xc = (XcObject *)self;
  50.158  
  50.159 -    u32   dom;
  50.160 +    u32 dom;
  50.161      char *state_file;
  50.162 -    int   progress = 1, live = -1, debug = 0;
  50.163 +    int progress = 1, debug = 0;
  50.164      unsigned int flags = 0;
  50.165      PyObject *val = NULL;
  50.166 -
  50.167 -    static char *kwd_list[] = { "dom", "state_file", "progress", 
  50.168 -                                "live", "debug", NULL };
  50.169 +    int rc = -1;
  50.170 +    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
  50.171  
  50.172 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|iii", kwd_list, 
  50.173 -                                      &dom, &state_file, &progress, 
  50.174 -                                      &live, &debug) )
  50.175 -        goto exit;
  50.176 +    static char *kwd_list[] = { "dom", "state_file", "vmconfig", "progress", "debug", NULL };
  50.177  
  50.178 -    if (progress)  flags |= XCFLAGS_VERBOSE;
  50.179 -    if (live == 1) flags |= XCFLAGS_LIVE;
  50.180 -    if (debug)     flags |= XCFLAGS_DEBUG;
  50.181 -
  50.182 -    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 ) {
  50.183 -        /* default to live for tcp */
  50.184 -        if (live == -1) flags |= XCFLAGS_LIVE;
  50.185 -        val = tcp_save(xc, dom, state_file, flags);
  50.186 -    } else {
  50.187 -        val = file_save(xc, dom, state_file, flags);
  50.188 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|sii", kwd_list, 
  50.189 +                                     &ioctxt.domain,
  50.190 +                                     &state_file,
  50.191 +                                     &ioctxt.vmconfig,
  50.192 +                                     &progress, 
  50.193 +                                     &debug)){
  50.194 +        goto exit;
  50.195      }
  50.196 +    ioctxt.vmconfig_n = (ioctxt.vmconfig ? strlen(ioctxt.vmconfig) : 0);
  50.197 +    if (progress)  ioctxt.flags |= XCFLAGS_VERBOSE;
  50.198 +    if (debug)     ioctxt.flags |= XCFLAGS_DEBUG;
  50.199 +    if(!state_file || state_file[0] == '\0') goto exit;
  50.200 +    rc = file_save(xc, &ioctxt, state_file);
  50.201 +    if(rc){
  50.202 +        PyErr_SetFromErrno(xc_error);
  50.203 +        goto exit;
  50.204 +    } 
  50.205 +    //xc_domain_destroy(xc->xc_handle, dom);
  50.206 +    Py_INCREF(zero);
  50.207 +    val = zero;
  50.208    exit:
  50.209      return val;
  50.210  }
  50.211  
  50.212 +
  50.213 +static int file_restore(XcObject *xc, XcIOContext *ioctxt, char *state_file){
  50.214 +    int rc = -1;
  50.215 +
  50.216 +    ioctxt->io = gzip_stream_fopen(state_file, "rb");
  50.217 +    if (!ioctxt->io) {
  50.218 +        xcio_perror(ioctxt, "Could not open file for reading");
  50.219 +        goto exit;
  50.220 +    }
  50.221 +
  50.222 +    rc = xc_linux_restore(xc->xc_handle, ioctxt);
  50.223 +  exit:
  50.224 +    if(ioctxt->io) IOStream_close(ioctxt->io);
  50.225 +    return rc;
  50.226 +}
  50.227 +
  50.228  static PyObject *pyxc_linux_restore(PyObject *self,
  50.229                                      PyObject *args,
  50.230                                      PyObject *kwds)
  50.231  {
  50.232      XcObject *xc = (XcObject *)self;
  50.233 -
  50.234 -    char        *state_file;
  50.235 -    int          progress = 1;
  50.236 -    u32          dom;
  50.237 -    unsigned int flags = 0;
  50.238 -
  50.239 -    static char *kwd_list[] = { "dom", "state_file", "progress", NULL };
  50.240 -
  50.241 -    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "is|i", kwd_list, 
  50.242 -                                      &dom, &state_file, &progress) )
  50.243 -        return NULL;
  50.244 -
  50.245 -    if ( progress )
  50.246 -        flags |= XCFLAGS_VERBOSE;
  50.247 -
  50.248 -    if ( strncmp(state_file,"tcp:", strlen("tcp:")) == 0 )
  50.249 -    {
  50.250 -#define max_namelen 64
  50.251 -        char server[max_namelen];
  50.252 -        char *port_s;
  50.253 -        int port=777;
  50.254 -        int ld = -1, sd = -1;
  50.255 -        struct hostent *h;
  50.256 -        struct sockaddr_in s, d, p;
  50.257 -        socklen_t dlen, plen;
  50.258 -        int sockbufsize;
  50.259 -        int on = 1, rc = -1;
  50.260 +    char *state_file;
  50.261 +    int progress = 1, debug = 0;
  50.262 +    u32 dom;
  50.263 +    PyObject *val = NULL;
  50.264 +    XcIOContext ioctxt = { .info = iostdout, .err = iostderr };
  50.265 +    int rc =-1;
  50.266  
  50.267 -        int readerfn(void *fd, void *buf, size_t count)
  50.268 -        {
  50.269 -            int rc, tot = 0;
  50.270 -            do { 
  50.271 -                rc = read( (int) fd, ((char*)buf)+tot, count-tot ); 
  50.272 -                if ( rc < 0 ) { perror("READ"); return rc; }
  50.273 -                if ( rc == 0 ) { printf("read: need %d, tot=%d got zero\n",
  50.274 -                                        count-tot, tot); return -1; }
  50.275 -                tot += rc;
  50.276 -            } 
  50.277 -            while ( tot < count );
  50.278 -            return 0;
  50.279 -        }
  50.280 -
  50.281 -        strncpy( server, state_file+strlen("tcp://"), max_namelen);
  50.282 -        server[max_namelen-1]='\0';
  50.283 -        if ( (port_s = strchr(server,':')) != NULL )
  50.284 -        {
  50.285 -            *port_s = '\0';
  50.286 -            port = atoi(port_s+1);
  50.287 -        }
  50.288 -
  50.289 -        printf("X server=%s port=%d\n",server,port);
  50.290 - 
  50.291 -        h = gethostbyname(server);
  50.292 -        ld = socket (AF_INET,SOCK_STREAM,0);
  50.293 -        if ( ld < 0 ) goto serr;
  50.294 -        s.sin_family = AF_INET;
  50.295 -        s.sin_addr.s_addr = htonl(INADDR_ANY);
  50.296 -        s.sin_port = htons(port);
  50.297 -
  50.298 -        if ( setsockopt(ld, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0 )
  50.299 -            goto serr;
  50.300 -
  50.301 -        if ( bind(ld, (struct sockaddr *) &s, sizeof(s)) ) 
  50.302 -            goto serr;
  50.303 -
  50.304 -        if ( listen(ld, 1) )
  50.305 -            goto serr;
  50.306 -
  50.307 -        dlen=sizeof(struct sockaddr);
  50.308 -        if ( (sd = accept(ld, (struct sockaddr *) &d, &dlen )) < 0 )
  50.309 -            goto serr;
  50.310 -
  50.311 -        plen = sizeof(p);
  50.312 -        if ( getpeername(sd, (struct sockaddr_in *) &p, 
  50.313 -                         &plen) < 0 )
  50.314 -            goto serr;
  50.315 +    static char *kwd_list[] = { "state_file", "progress", "debug", NULL };
  50.316  
  50.317 -        printf("Accepted connection from %s\n", inet_ntoa(p.sin_addr));
  50.318 - 
  50.319 -        sockbufsize=128*1024;
  50.320 -        if ( setsockopt(sd, SOL_SOCKET, SO_SNDBUF, &sockbufsize, 
  50.321 -                        sizeof sockbufsize) < 0 ) 
  50.322 -            goto serr;
  50.323 -
  50.324 -        rc = xc_linux_restore(xc->xc_handle, dom, flags, 
  50.325 -                              readerfn, (void*)sd, &dom);
  50.326 -
  50.327 -        write( sd, &rc, sizeof(int) ); 
  50.328 -
  50.329 -        if (rc == 0)
  50.330 -        {
  50.331 -            close(sd);
  50.332 -            Py_INCREF(zero);
  50.333 -            return zero;
  50.334 -        }
  50.335 -        errno = rc;
  50.336 -
  50.337 -    serr:
  50.338 -        PyErr_SetFromErrno(xc_error);
  50.339 -        if ( ld >= 0 ) close(ld);
  50.340 -        if ( sd >= 0 ) close(sd);
  50.341 -        return NULL;
  50.342 -    }    
  50.343 -    else
  50.344 -    {
  50.345 -        int fd = -1;
  50.346 -        gzFile gfd = NULL;
  50.347 +    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is|ii", kwd_list, 
  50.348 +                                     &ioctxt.domain,
  50.349 +                                     &state_file,
  50.350 +                                     &progress,
  50.351 +                                     &debug)){
  50.352 +        goto exit;
  50.353 +    }
  50.354 +    if (progress) ioctxt.flags |= XCFLAGS_VERBOSE;
  50.355 +    if (debug)    ioctxt.flags |= XCFLAGS_DEBUG;
  50.356  
  50.357 -        int readerfn(void *fd, void *buf, size_t count)
  50.358 -        {
  50.359 -            int rc;
  50.360 -            while ( ((rc = gzread( (gzFile*)fd, (void*)buf, count)) == -1) && 
  50.361 -                    (errno = EINTR) )
  50.362 -                continue;
  50.363 -            return ! (rc == count);
  50.364 -        }
  50.365 -
  50.366 -        if ( strncmp(state_file,"file:",strlen("file:")) == 0 )
  50.367 -            state_file += strlen("file:");
  50.368 -
  50.369 -        if ( (fd = open(state_file, O_RDONLY)) == -1 )
  50.370 -        {
  50.371 -            perror("Could not open file for writing");
  50.372 -            goto err;
  50.373 -        }
  50.374 -
  50.375 -        /*
  50.376 -         * Compression rate 1: we want speed over compression. 
  50.377 -         * We're mainly going for those zero pages, after all.
  50.378 -         */
  50.379 -        if ( (gfd = gzdopen(fd, "rb")) == NULL )
  50.380 -        {
  50.381 -            perror("Could not allocate compression state for state file");
  50.382 -            close(fd);
  50.383 -            goto err;
  50.384 -        }
  50.385 -
  50.386 -
  50.387 -        if ( xc_linux_restore(xc->xc_handle, dom, flags, 
  50.388 -                              readerfn, gfd, &dom) == 0 )
  50.389 -        {
  50.390 -            gzclose(gfd);
  50.391 -            close(fd);
  50.392 -
  50.393 -            Py_INCREF(zero);
  50.394 -            return zero;
  50.395 -        }
  50.396 -
  50.397 -    err:
  50.398 +    if(!state_file || state_file[0] == '\0') goto exit;
  50.399 +    rc = file_restore(xc, &ioctxt, state_file);
  50.400 +    if(rc){
  50.401          PyErr_SetFromErrno(xc_error);
  50.402 -        if ( gfd != NULL ) gzclose(gfd);
  50.403 -        if ( fd >= 0 ) close(fd);
  50.404 -        return NULL;
  50.405 +        goto exit;
  50.406      }
  50.407 -
  50.408 +    val = Py_BuildValue("{s:i,s:s}",
  50.409 +                        "dom", ioctxt.domain,
  50.410 +                        "vmconfig", ioctxt.vmconfig);
  50.411 +    //? free(ioctxt.vmconfig);
  50.412 +  exit:
  50.413 +    return val;
  50.414  }
  50.415  
  50.416  static PyObject *pyxc_linux_build(PyObject *self,
    51.1 --- a/tools/xc/py/setup.py	Tue Jun 29 00:51:10 2004 +0000
    51.2 +++ b/tools/xc/py/setup.py	Tue Jun 29 12:05:29 2004 +0000
    51.3 @@ -3,12 +3,17 @@ from distutils.core import setup, Extens
    51.4  
    51.5  module = Extension("xc",
    51.6                     extra_compile_args   = ["-fno-strict-aliasing"],
    51.7 -                   include_dirs         = ["../lib"],
    51.8 -                   library_dirs         = ["../lib"],
    51.9 +                   include_dirs         = ["../lib",
   51.10 +                                           "../../../xen/include/hypervisor-ifs",
   51.11 +                                           "../../../linux-xen-sparse/include",
   51.12 +                                           "../../xu/lib",
   51.13 +                                           "../../lib" ],
   51.14 +                   library_dirs         = ["../lib",
   51.15 +                                           "../../lib" ],
   51.16                     libraries            = ["xc"],
   51.17                     sources              = ["Xc.c"])
   51.18  
   51.19  setup(name = "xc",
   51.20 -      version = "1.0",
   51.21 +      version = "2.0",
   51.22        ext_package = "xen.ext",
   51.23        ext_modules = [module])
    52.1 --- a/tools/xen/lib/xend/XendDomain.py	Tue Jun 29 00:51:10 2004 +0000
    52.2 +++ b/tools/xen/lib/xend/XendDomain.py	Tue Jun 29 12:05:29 2004 +0000
    52.3 @@ -9,7 +9,6 @@ import sys
    52.4  from twisted.internet import defer
    52.5  
    52.6  import xen.ext.xc; xc = xen.ext.xc.new()
    52.7 -import xenctl.ip
    52.8  
    52.9  import sxp
   52.10  import XendRoot
   52.11 @@ -235,7 +234,7 @@ class XendDomain:
   52.12      def domain_get(self, id):
   52.13          id = str(id)
   52.14          self.refresh_domain(id)
   52.15 -        return self.domain[id]
   52.16 +        return self.domain.get(id)
   52.17      
   52.18      def domain_unpause(self, id):
   52.19          """(Re)start domain running.
   52.20 @@ -278,22 +277,26 @@ class XendDomain:
   52.21          """
   52.22          # Need a cancel too?
   52.23          pass
   52.24 -    
   52.25 +
   52.26      def domain_save(self, id, dst, progress=0):
   52.27          """Save domain state to file, destroy domain.
   52.28          """
   52.29          dom = int(id)
   52.30 +        dominfo = self.domain_get(id)
   52.31 +        if not dominfo:
   52.32 +            return -1
   52.33 +        vmconfig = sxp.to_string(dominfo.sxpr())
   52.34          self.domain_pause(id)
   52.35          eserver.inject('xend.domain.save', id)
   52.36 -        rc = xc.linux_save(dom=dom, state_file=dst, progress=progress)
   52.37 +        rc = xc.linux_save(dom=dom, state_file=dst, vmconfig=vmconfig, progress=progress)
   52.38          if rc == 0:
   52.39              self.domain_destroy(id)
   52.40          return rc
   52.41      
   52.42 -    def domain_restore(self, src, config, progress=0):
   52.43 +    def domain_restore(self, src, progress=0):
   52.44          """Restore domain from file.
   52.45          """
   52.46 -        dominfo = XendDomainInfo.dom_restore(dom, config)
   52.47 +        dominfo = XendDomainInfo.vm_restore(src, progress=progress)
   52.48          self._add_domain(dominfo.id, dominfo)
   52.49          return dominfo
   52.50      
   52.51 @@ -332,9 +335,9 @@ class XendDomain:
   52.52          if not dominfo: return None
   52.53          return dominfo.get_device_by_index(vif)
   52.54  
   52.55 -    def domain_vif_ip_add(self, dom, vif, ip):
   52.56 -        dom = int(dom)
   52.57 -        return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
   52.58 +##     def domain_vif_ip_add(self, dom, vif, ip):
   52.59 +##         dom = int(dom)
   52.60 +##         return xenctl.ip.setup_vfr_rules_for_vif(dom, vif, ip)
   52.61  
   52.62      def domain_vbd_ls(self, dom):
   52.63          dominfo = self.domain_get(dom)
    53.1 --- a/tools/xen/lib/xend/XendDomainInfo.py	Tue Jun 29 00:51:10 2004 +0000
    53.2 +++ b/tools/xen/lib/xend/XendDomainInfo.py	Tue Jun 29 12:05:29 2004 +0000
    53.3 @@ -17,7 +17,7 @@ import os
    53.4  from twisted.internet import defer
    53.5  
    53.6  import xen.ext.xc; xc = xen.ext.xc.new()
    53.7 -import xenctl.ip
    53.8 +import xen.util.ip
    53.9  
   53.10  import sxp
   53.11  
   53.12 @@ -167,14 +167,14 @@ def vif_up(iplist):
   53.13          print >> open(IP_NONLOCAL_BIND, 'w'), str(v)
   53.14  
   53.15      def link_local(ip):
   53.16 -        return xenctl.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
   53.17 +        return xen.util.ip.check_subnet(ip, '169.254.0.0', '255.255.0.0')
   53.18  
   53.19      def arping(ip, gw):
   53.20          cmd = '/usr/sbin/arping -A -b -I eth0 -c 1 -s %s %s' % (ip, gw)
   53.21          print cmd
   53.22          os.system(cmd)
   53.23          
   53.24 -    gateway = xenctl.ip.get_current_ipgw() or '255.255.255.255'
   53.25 +    gateway = xen.util.ip.get_current_ipgw() or '255.255.255.255'
   53.26      nlb = get_ip_nonlocal_bind()
   53.27      if not nlb: set_ip_nonlocal_bind(1)
   53.28      try:
   53.29 @@ -272,22 +272,23 @@ def vm_recreate(config, info):
   53.30          d.callback(vm)
   53.31      return d
   53.32  
   53.33 -def vm_restore(src, config, progress=0):
   53.34 +def vm_restore(src, progress=0):
   53.35      """Restore a VM from a disk image.
   53.36  
   53.37      src      saved state to restore
   53.38 -    config   configuration
   53.39      progress progress reporting flag
   53.40      returns  deferred
   53.41      raises   VmError for invalid configuration
   53.42      """
   53.43      vm = XendDomainInfo()
   53.44 -    vm.config = config
   53.45 -    ostype = "linux" #todo set from config
   53.46 +    ostype = "linux" #todo Set from somewhere (store in the src?).
   53.47      restorefn = getattr(xc, "%s_restore" % ostype)
   53.48 -    dom = restorefn(state_file=src, progress=progress)
   53.49 +    d = restorefn(state_file=src, progress=progress)
   53.50 +    dom = int(d['dom'])
   53.51      if dom < 0:
   53.52          raise VMError('restore failed')
   53.53 +    vmconfig = sxp.from_string(d['vmconfig'])
   53.54 +    vm.config = sxp.child_value(vmconfig, 'config')
   53.55      deferred = vm.dom_configure(dom)
   53.56      def vifs_cb(val, vm):
   53.57          vif_up(vm.ipaddrs)
   53.58 @@ -855,9 +856,7 @@ def vm_field_vfr(vm, config, val, index)
   53.59          if not ip:
   53.60              raise VmError('vfr: missing ip address')
   53.61          ipaddrs.append(ip);
   53.62 -        #Don't do this in new i/o model.
   53.63 -        #print 'vm_field_vfr> add rule', 'dom=', vm.dom, 'vif=', vif, 'ip=', ip
   53.64 -        #xenctl.ip.setup_vfr_rules_for_vif(vm.dom, vif, ip)
   53.65 +        # todo: Configure the ipaddrs.
   53.66      vm.ipaddrs = ipaddrs
   53.67  
   53.68  def vnet_bridge(vnet, vmac, dom, idx):
    54.1 --- a/tools/xen/lib/xend/server/SrvDomain.py	Tue Jun 29 00:51:10 2004 +0000
    54.2 +++ b/tools/xen/lib/xend/server/SrvDomain.py	Tue Jun 29 12:05:29 2004 +0000
    54.3 @@ -44,13 +44,6 @@ class SrvDomain(SrvDir):
    54.4          val = fn(req.args, {'dom': self.dom.id})
    54.5          return val
    54.6  
    54.7 -    def op_restore(self, op, req):
    54.8 -        fn = FormFn(self.xd.domain_restore,
    54.9 -                    [['dom', 'int'],
   54.10 -                     ['file', 'str']])
   54.11 -        val = fn(req.args, {'dom': self.dom.id})
   54.12 -        return val
   54.13 -        
   54.14      def op_migrate(self, op, req):
   54.15          fn = FormFn(self.xd.domain_migrate,
   54.16                      [['dom', 'int'],
    55.1 --- a/tools/xen/lib/xend/server/SrvDomainDir.py	Tue Jun 29 00:51:10 2004 +0000
    55.2 +++ b/tools/xen/lib/xend/server/SrvDomainDir.py	Tue Jun 29 12:05:29 2004 +0000
    55.3 @@ -7,6 +7,7 @@ from twisted.web import error
    55.4  
    55.5  from xen.xend import sxp
    55.6  from xen.xend import XendDomain
    55.7 +from xen.xend.Args import FormFn
    55.8  
    55.9  from SrvDir import SrvDir
   55.10  from SrvDomain import SrvDomain
   55.11 @@ -88,6 +89,12 @@ class SrvDomainDir(SrvDir):
   55.12              out.close()
   55.13              return val
   55.14  
   55.15 +    def op_restore(self, op, req):
   55.16 +        fn = FormFn(self.xd.domain_restore,
   55.17 +                    [['file', 'str']])
   55.18 +        val = fn(req.args)
   55.19 +        return val
   55.20 +        
   55.21      def render_POST(self, req):
   55.22          return self.perform(req)
   55.23  
   55.24 @@ -129,3 +136,9 @@ class SrvDomainDir(SrvDir):
   55.25          req.write('<button type="submit" name="op" value="create">Create Domain</button>')
   55.26          req.write('Config <input type="file" name="config"><br>')
   55.27          req.write('</form>')
   55.28 +        req.write('<form method="post" action="%s" enctype="multipart/form-data">'
   55.29 +                  % req.prePathURL())
   55.30 +        req.write('<button type="submit" name="op" value="create">Restore Domain</button>')
   55.31 +        req.write('State <input type="string" name="state"><br>')
   55.32 +        req.write('</form>')
   55.33 +        
    56.1 --- a/tools/xen/lib/xend/sxp.py	Tue Jun 29 00:51:10 2004 +0000
    56.2 +++ b/tools/xen/lib/xend/sxp.py	Tue Jun 29 12:05:29 2004 +0000
    56.3 @@ -16,6 +16,7 @@ import sys
    56.4  import types
    56.5  import errno
    56.6  import string
    56.7 +from StringIO import StringIO
    56.8  
    56.9  __all__ = [
   56.10      "mime_type", 
   56.11 @@ -521,6 +522,28 @@ def elements(sxpr, ctxt=None):
   56.12                  yield v
   56.13          i += 1
   56.14  
   56.15 +def to_string(sxpr):
   56.16 +    """Convert an sxpr to a string.
   56.17 +
   56.18 +    sxpr sxpr
   56.19 +    returns string
   56.20 +    """
   56.21 +    io = StringIO()
   56.22 +    show(sxpr, io)
   56.23 +    io.seek(0)
   56.24 +    val = io.getvalue()
   56.25 +    io.close()
   56.26 +    return val
   56.27 +
   56.28 +def from_string(str):
   56.29 +    """Create an sxpr by parsing a string.
   56.30 +
   56.31 +    str string
   56.32 +    returns sxpr
   56.33 +    """
   56.34 +    io = StringIO(str)
   56.35 +    return parse(io)
   56.36 +
   56.37  def parse(io):
   56.38      """Completely parse all input from 'io'.
   56.39  
    57.1 --- a/tools/xen/lib/xm/create.py	Tue Jun 29 00:51:10 2004 +0000
    57.2 +++ b/tools/xen/lib/xm/create.py	Tue Jun 29 12:05:29 2004 +0000
    57.3 @@ -8,7 +8,7 @@ from xen.xend import sxp
    57.4  from xen.xend import PrettyPrint
    57.5  from xen.xend.XendClient import server
    57.6  
    57.7 -from xen.xend.xm.opts import *
    57.8 +from xen.xm.opts import *
    57.9  
   57.10  gopts = Opts(use="""[options]
   57.11  
    58.1 --- a/tools/xen/lib/xm/main.py	Tue Jun 29 00:51:10 2004 +0000
    58.2 +++ b/tools/xen/lib/xm/main.py	Tue Jun 29 12:05:29 2004 +0000
    58.3 @@ -9,7 +9,7 @@ from getopt import getopt
    58.4  from xen.xend import PrettyPrint
    58.5  from xen.xend import sxp
    58.6  from xen.xend.XendClient import server
    58.7 -from xen.xend.xm import create, shutdown
    58.8 +from xen.xm import create, shutdown
    58.9  
   58.10  class Prog:
   58.11      """Base class for sub-programs.
    59.1 --- a/tools/xen/lib/xm/opts.py	Tue Jun 29 00:51:10 2004 +0000
    59.2 +++ b/tools/xen/lib/xm/opts.py	Tue Jun 29 12:05:29 2004 +0000
    59.3 @@ -290,6 +290,7 @@ class Opts:
    59.4          cmd = '\n'.join(["import sys",
    59.5                           "import os",
    59.6                           "import os.path",
    59.7 +                         "import xen.util.ip",
    59.8                           "xm_file = '%s'" % defaults,
    59.9                           "xm_help = %d" % help ])
   59.10          exec cmd in globals, locals
    60.1 --- a/tools/xen/lib/xm/shutdown.py	Tue Jun 29 00:51:10 2004 +0000
    60.2 +++ b/tools/xen/lib/xm/shutdown.py	Tue Jun 29 12:05:29 2004 +0000
    60.3 @@ -6,7 +6,7 @@ import sys
    60.4  import time
    60.5  
    60.6  from xen.xend.XendClient import server
    60.7 -from xen.xend.xm.opts import *
    60.8 +from xen.xm.opts import *
    60.9  
   60.10  gopts = Opts(use="""[options] [DOM]
   60.11  
    61.1 --- a/tools/xen/xend	Tue Jun 29 00:51:10 2004 +0000
    61.2 +++ b/tools/xen/xend	Tue Jun 29 12:05:29 2004 +0000
    61.3 @@ -13,8 +13,8 @@
    61.4  
    61.5     xend stop
    61.6  
    61.7 -   Unfortunately restarting it upsets the channel to dom0 and
    61.8 -   domain management stops working - needs a reboot to fix.
    61.9 +   The daemon should reconnect to device control interfaces
   61.10 +   and recover its state when restarted.
   61.11  """
   61.12  import os
   61.13  import sys
    62.1 --- a/tools/xentrace/Makefile	Tue Jun 29 00:51:10 2004 +0000
    62.2 +++ b/tools/xentrace/Makefile	Tue Jun 29 12:05:29 2004 +0000
    62.3 @@ -4,6 +4,7 @@ CFLAGS   = -Wall -O3 -Werror
    62.4  CFLAGS  += -I../../xen/include/hypervisor-ifs
    62.5  CFLAGS  += -I../../linux-xen-sparse/include
    62.6  CFLAGS  += -I../xu/lib
    62.7 +CFLAGS  += -I../lib
    62.8  
    62.9  HDRS     = $(wildcard *.h)
   62.10  OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))