ia64/xen-unstable

changeset 3078:beb02da3f69f

bitkeeper revision 1.1159.183.2 (41a216ce6YIv6IWbateVWedQylK5rA)

Restructure libxutil to prepare for adding vnets.
Move common files from xfrd into libxutil.
author mjw@wray-m-3.hpl.hp.com
date Mon Nov 22 16:41:50 2004 +0000 (2004-11-22)
parents fef4b77be191
children 0dfcf477fdd3
files .rootkeys tools/libxutil/Makefile tools/libxutil/debug.h tools/libxutil/enum.c tools/libxutil/enum.h tools/libxutil/hash_table.c tools/libxutil/hash_table.h tools/libxutil/iostream.c tools/libxutil/iostream.h tools/libxutil/kernel_stream.c tools/libxutil/lexis.c tools/libxutil/lexis.h tools/libxutil/socket_stream.c tools/libxutil/socket_stream.h tools/libxutil/string_stream.c tools/libxutil/string_stream.h tools/libxutil/sxpr.c tools/libxutil/sxpr.h tools/libxutil/sxpr_parser.c tools/libxutil/sxpr_parser.h tools/libxutil/sys_net.c tools/libxutil/util.c tools/libxutil/util.h tools/xfrd/Make.xfrd tools/xfrd/enum.c tools/xfrd/enum.h tools/xfrd/hash_table.c tools/xfrd/hash_table.h tools/xfrd/lexis.c tools/xfrd/lexis.h tools/xfrd/sxpr.c tools/xfrd/sxpr.h tools/xfrd/sxpr_parser.c tools/xfrd/sxpr_parser.h
line diff
     1.1 --- a/.rootkeys	Sun Nov 21 20:41:00 2004 +0000
     1.2 +++ b/.rootkeys	Mon Nov 22 16:41:50 2004 +0000
     1.3 @@ -336,20 +336,35 @@ 40589968UQFnJeOMn8UIFLbXBuwXjw tools/lib
     1.4  40e1b09dMYB4ItGCqcMIzirdMd9I-w tools/libxutil/Makefile
     1.5  40e033325Sjqs-_4TuzeUEprP_gYFg tools/libxutil/allocate.c
     1.6  40e03332KYz7o1bn2MG_KPbBlyoIMA tools/libxutil/allocate.h
     1.7 +41a216cav5JJbtDQnusfuMa_1x_Xpw tools/libxutil/debug.h
     1.8 +40e9808eyjiahG5uF6AMelNVujBzCg tools/libxutil/enum.c
     1.9 +40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/libxutil/enum.h
    1.10  40e03332p5Dc_owJQRuN72ymJZddFQ tools/libxutil/file_stream.c
    1.11  40e03332jWfB2viAhLSkq1WK0r_iDQ tools/libxutil/file_stream.h
    1.12  40e03332rUjNMGg11n2rN6V4DCrvOg tools/libxutil/gzip_stream.c
    1.13  40e033321O5Qg22haLoq5lpmk4tooQ tools/libxutil/gzip_stream.h
    1.14 +40e9808easXCzzAZQodEfKAhgUXSPA tools/libxutil/hash_table.c
    1.15 +40e9808e94BNXIVVKBFHC3rnkvwtJg tools/libxutil/hash_table.h
    1.16  40e03332ihnBGzHykVwZnFmkAppb4g tools/libxutil/iostream.c
    1.17  40e03332UGwbLR4wsw4ft14p0Yw5pg tools/libxutil/iostream.h
    1.18  40e0333245DLDzJemeSVBLuutHtzEQ tools/libxutil/kernel_stream.c
    1.19  40e03332aK0GkgpDdc-PVTkWKTeOBg tools/libxutil/kernel_stream.h
    1.20 +40e9808epW9iHcLXuO3QfUfLzB7onw tools/libxutil/lexis.c
    1.21 +40e9808egccMhCizayQRGtpBA3L5MQ tools/libxutil/lexis.h
    1.22 +41a216caM4z39Fzjb91rv9Ed_4By1A tools/libxutil/socket_stream.c
    1.23 +41a216caqinvF1I5FQMHA4HTRz8MSA tools/libxutil/socket_stream.h
    1.24  40e03332KT_tnnoAMbPVAZBB7kSOAQ tools/libxutil/string_stream.c
    1.25  40e03332-VtK6_OZa1vMHXFil8uq6w tools/libxutil/string_stream.h
    1.26 +40e9808e5_PLdodqVOSx0b4T_f5aeg tools/libxutil/sxpr.c
    1.27 +40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/libxutil/sxpr.h
    1.28 +40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/libxutil/sxpr_parser.c
    1.29 +40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/libxutil/sxpr_parser.h
    1.30  40e03332Rkvq6nn_UNjzAAK_Tk9v1g tools/libxutil/sys_net.c
    1.31  40e03332lQHvQHw4Rh7VsT1_sui29A tools/libxutil/sys_net.h
    1.32  40e033321smklZd7bDSdWvQCeIshtg tools/libxutil/sys_string.c
    1.33  40e03332h5V611rRWURRLqb1Ekatxg tools/libxutil/sys_string.h
    1.34 +41a216cayFe2FQroFuzvNPw1AvNiqQ tools/libxutil/util.c
    1.35 +41a216ca7mgVSnCBHPCLkGOIqPS1CQ tools/libxutil/util.h
    1.36  3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
    1.37  40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
    1.38  3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
    1.39 @@ -544,23 +559,13 @@ 40e9808epTR4zWrYjGUnaaynK20Q5A tools/xfr
    1.40  40e9808eysqT4VNDlJFqsZB2rdg4Qw tools/xfrd/connection.c
    1.41  40e9808eyXfJUi4E0C3WSgrEXqQ1sQ tools/xfrd/connection.h
    1.42  40e9808eULGwffNOE4kBrAfZ9YAVMA tools/xfrd/debug.h
    1.43 -40e9808eyjiahG5uF6AMelNVujBzCg tools/xfrd/enum.c
    1.44 -40e9808eZpbdn9q2KSSMGCNvY_ZgpQ tools/xfrd/enum.h
    1.45 -40e9808easXCzzAZQodEfKAhgUXSPA tools/xfrd/hash_table.c
    1.46 -40e9808e94BNXIVVKBFHC3rnkvwtJg tools/xfrd/hash_table.h
    1.47  411b5139tfKZfWs1LQHmwDR_wjKoxQ tools/xfrd/http.h
    1.48 -40e9808epW9iHcLXuO3QfUfLzB7onw tools/xfrd/lexis.c
    1.49 -40e9808egccMhCizayQRGtpBA3L5MQ tools/xfrd/lexis.h
    1.50  40e9808ePADCSKL1YgGCt2TbYPnYkw tools/xfrd/lzi_stream.c
    1.51  40e9808eDNAdpF71o5teYb9DTT-PRw tools/xfrd/lzi_stream.h
    1.52  40e9808eQxi0EzTcPJtosrzxEIjA-Q tools/xfrd/marshal.c
    1.53  40e9808etg13xfRm0Lqd8vY-jHOoTg tools/xfrd/marshal.h
    1.54  40e9808eCsmywryb036TdtRMJHDMmQ tools/xfrd/select.c
    1.55  40e9808e99OcM547cKMTfmCVSoWVAw tools/xfrd/select.h
    1.56 -40e9808e5_PLdodqVOSx0b4T_f5aeg tools/xfrd/sxpr.c
    1.57 -40e9808e0O4sHZtkDv5hlSqjYcdQAQ tools/xfrd/sxpr.h
    1.58 -40ec1cc6SIiGbynOi-1NtPesOlzF-Q tools/xfrd/sxpr_parser.c
    1.59 -40ec1cc6wpvvGxZiq4EFvNOcw0tUFg tools/xfrd/sxpr_parser.h
    1.60  40e9808eF3NVldqRNS5IHM8gbFAvpw tools/xfrd/xdr.c
    1.61  40e9808ezXzoRHm7pybXU69NtnjimA tools/xfrd/xdr.h
    1.62  40e9808edpUtf4bJ8IbqClPJj_OvbA tools/xfrd/xen_domain.c
     2.1 --- a/tools/libxutil/Makefile	Sun Nov 21 20:41:00 2004 +0000
     2.2 +++ b/tools/libxutil/Makefile	Mon Nov 22 16:41:50 2004 +0000
     2.3 @@ -5,11 +5,18 @@ CC = gcc
     2.4  
     2.5  LIB_SRCS :=
     2.6  LIB_SRCS += allocate.c
     2.7 +LIB_SRCS += enum.c
     2.8  LIB_SRCS += file_stream.c
     2.9  LIB_SRCS += gzip_stream.c
    2.10 +LIB_SRCS += hash_table.c
    2.11  LIB_SRCS += iostream.c
    2.12 -#LIB_SRCS += sys_net.c
    2.13 +LIB_SRCS += lexis.c
    2.14 +LIB_SRCS += string_stream.c
    2.15 +LIB_SRCS += sxpr.c
    2.16 +LIB_SRCS += sxpr_parser.c
    2.17 +LIB_SRCS += sys_net.c
    2.18  LIB_SRCS += sys_string.c
    2.19 +LIB_SRCS += util.c
    2.20  
    2.21  LIB_OBJS := $(LIB_SRCS:.c=.o)
    2.22  
    2.23 @@ -29,6 +36,7 @@ LIB_NAME := libxutil
    2.24  LIB      := $(LIB_NAME).so 
    2.25  LIB      += $(LIB_NAME).so.$(MAJOR)
    2.26  LIB      += $(LIB_NAME).so.$(MAJOR).$(MINOR)
    2.27 +LIB      += $(LIB_NAME).a
    2.28  
    2.29  all: check-for-zlib
    2.30  	$(MAKE) $(LIB)
    2.31 @@ -42,6 +50,9 @@ all: check-for-zlib
    2.32  $(LIB_NAME).so.$(MAJOR).$(MINOR): $(LIB_OBJS)
    2.33  	$(CC) -Wl,-soname -Wl,$(LIB_NAME).so.$(MAJOR) -shared -o $@ $^
    2.34  
    2.35 +$(LIB_NAME).a: $(LIB_OBJS)
    2.36 +	$(AR) rc $@ $^
    2.37 +
    2.38  check-for-zlib:
    2.39  	@if [ ! -e /usr/include/zlib.h ]; then \
    2.40  	echo "***********************************************************"; \
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/tools/libxutil/debug.h	Mon Nov 22 16:41:50 2004 +0000
     3.3 @@ -0,0 +1,72 @@
     3.4 +/*
     3.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
     3.6 + *
     3.7 + * This library is free software; you can redistribute it and/or modify
     3.8 + * it under the terms of the GNU Lesser General Public License as published by
     3.9 + * the Free Software Foundation; either version 2.1 of the License, or
    3.10 + * (at your option) any later version.
    3.11 + *
    3.12 + * This library is distributed in the hope that it will be useful,
    3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.15 + * GNU Lesser General Public License for more details.
    3.16 + *
    3.17 + * You should have received a copy of the GNU Lesser General Public License
    3.18 + * along with this library; if not, write to the Free Software
    3.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    3.20 + */
    3.21 +#ifndef _XUTIL_DEBUG_H_
    3.22 +#define _XUTIL_DEBUG_H_
    3.23 +
    3.24 +#ifndef MODULE_NAME
    3.25 +#define MODULE_NAME ""
    3.26 +#endif
    3.27 +
    3.28 +#ifdef __KERNEL__
    3.29 +#include <linux/config.h>
    3.30 +#include <linux/kernel.h>
    3.31 +
    3.32 +#ifdef DEBUG
    3.33 +
    3.34 +#define dprintf(fmt, args...) printk(KERN_DEBUG   "[DBG] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    3.35 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    3.36 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    3.37 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME ">%s" fmt, __FUNCTION__, ##args)
    3.38 +
    3.39 +#else
    3.40 +
    3.41 +#define dprintf(fmt, args...) do {} while(0)
    3.42 +#define wprintf(fmt, args...) printk(KERN_WARNING "[WRN] " MODULE_NAME fmt, ##args)
    3.43 +#define iprintf(fmt, args...) printk(KERN_INFO    "[INF] " MODULE_NAME fmt, ##args)
    3.44 +#define eprintf(fmt, args...) printk(KERN_ERR     "[ERR] " MODULE_NAME fmt, ##args)
    3.45 +
    3.46 +#endif
    3.47 +
    3.48 +#else
    3.49 +
    3.50 +#include <stdio.h>
    3.51 +
    3.52 +#ifdef DEBUG
    3.53 +
    3.54 +#define dprintf(fmt, args...) fprintf(stdout, "%d [DBG] " MODULE_NAME ">%s" fmt, getpid(), __FUNCTION__, ##args)
    3.55 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
    3.56 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
    3.57 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME ">%s" fmt, getpid(),__FUNCTION__, ##args)
    3.58 +
    3.59 +#else
    3.60 +
    3.61 +#define dprintf(fmt, args...) do {} while(0)
    3.62 +#define wprintf(fmt, args...) fprintf(stderr, "%d [WRN] " MODULE_NAME fmt, getpid(), ##args)
    3.63 +#define iprintf(fmt, args...) fprintf(stderr, "%d [INF] " MODULE_NAME fmt, getpid(), ##args)
    3.64 +#define eprintf(fmt, args...) fprintf(stderr, "%d [ERR] " MODULE_NAME fmt, getpid(), ##args)
    3.65 +
    3.66 +#endif
    3.67 +
    3.68 +#endif
    3.69 +
    3.70 +/** Print format for an IP address.
    3.71 + * See NIPQUAD(), HIPQUAD()
    3.72 + */
    3.73 +#define IPFMT "%u.%u.%u.%u"
    3.74 +
    3.75 +#endif /* ! _XUTIL_DEBUG_H_ */
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/tools/libxutil/enum.c	Mon Nov 22 16:41:50 2004 +0000
     4.3 @@ -0,0 +1,61 @@
     4.4 +/*
     4.5 + * Copyright (C) 2002, 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
     4.9 + * published by the Free Software Foundation; either version 2.1 of the
    4.10 + * License, or  (at your option) any later version. This library is 
    4.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
    4.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.13 + * FITNESS FOR A PARTICULAR PURPOSE.
    4.14 + * See the GNU Lesser General Public License for more details.
    4.15 + *
    4.16 + * You should have received a copy of the GNU Lesser General Public License
    4.17 + * along with this library; if not, write to the Free Software Foundation,
    4.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    4.19 + */
    4.20 +
    4.21 +#ifdef __KERNEL__
    4.22 +#include <linux/errno.h>
    4.23 +#else
    4.24 +#include <errno.h>
    4.25 +#endif
    4.26 +
    4.27 +#include "sys_string.h"
    4.28 +#include "enum.h"
    4.29 +
    4.30 +/** Map an enum name to its value using a table.
    4.31 + *
    4.32 + * @param name enum name
    4.33 + * @param defs enum definitions
    4.34 + * @return enum value or -1 if not known
    4.35 + */
    4.36 +int enum_name_to_val(char *name, EnumDef *defs){
    4.37 +    int val = -1;
    4.38 +    for(; defs->name; defs++){
    4.39 +	if(!strcmp(defs->name, name)){
    4.40 +	    val = defs->val;
    4.41 +	    break;
    4.42 +	}
    4.43 +    }
    4.44 +    return val;
    4.45 +}
    4.46 +
    4.47 +/** Map an enum value to its name using a table.
    4.48 + *
    4.49 + * @param val enum value
    4.50 + * @param defs enum definitions
    4.51 + * @param defs_n number of definitions
    4.52 + * @return enum name or NULL if not known
    4.53 + */
    4.54 +char *enum_val_to_name(int val, EnumDef *defs){
    4.55 +    char *name = NULL;
    4.56 +    for(; defs->name; defs++){
    4.57 +	if(val == defs->val){
    4.58 +	    name = defs->name;
    4.59 +	    break;
    4.60 +	}
    4.61 +    }
    4.62 +    return name;
    4.63 +}
    4.64 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/tools/libxutil/enum.h	Mon Nov 22 16:41:50 2004 +0000
     5.3 @@ -0,0 +1,30 @@
     5.4 +/*
     5.5 + * Copyright (C) 2002, 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
     5.9 + * published by the Free Software Foundation; either version 2.1 of the
    5.10 + * License, or  (at your option) any later version. This library is 
    5.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
    5.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
    5.13 + * FITNESS FOR A PARTICULAR PURPOSE.
    5.14 + * See the GNU Lesser General Public License for more details.
    5.15 + *
    5.16 + * You should have received a copy of the GNU Lesser General Public License
    5.17 + * along with this library; if not, write to the Free Software Foundation,
    5.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
    5.19 + */
    5.20 +
    5.21 +#ifndef _XUTIL_ENUM_H_
    5.22 +#define _XUTIL_ENUM_H_
    5.23 +
    5.24 +/** Mapping of an enum value to a name. */
    5.25 +typedef struct EnumDef {
    5.26 +    int val;
    5.27 +    char *name;
    5.28 +} EnumDef;
    5.29 +
    5.30 +extern int enum_name_to_val(char *name, EnumDef *defs);
    5.31 +extern char *enum_val_to_name(int val, EnumDef *defs);
    5.32 +
    5.33 +#endif /* _XUTIL_ENUM_H_ */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/tools/libxutil/hash_table.c	Mon Nov 22 16:41:50 2004 +0000
     6.3 @@ -0,0 +1,640 @@
     6.4 +/*
     6.5 + * Copyright (C) 2001 - 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 +
    6.22 +#ifdef __KERNEL__
    6.23 +#  include <linux/config.h>
    6.24 +#  include <linux/module.h>
    6.25 +#  include <linux/kernel.h>
    6.26 +#  include <linux/errno.h>
    6.27 +#else
    6.28 +#  include <errno.h>
    6.29 +#  include <stddef.h>
    6.30 +#endif
    6.31 +
    6.32 +//#include <limits.h>
    6.33 +
    6.34 +#include "allocate.h"
    6.35 +#include "hash_table.h"
    6.36 +
    6.37 +/** @file
    6.38 + * Base support for hashtables.
    6.39 + *
    6.40 + * Hash codes are reduced modulo the number of buckets to index tables,
    6.41 + * so there is no need for hash functions to limit the range of hashcodes.
    6.42 + * In fact it is assumed that hashcodes do not change when the number of
    6.43 + * buckets in the table changes.
    6.44 + */
    6.45 +
    6.46 +/*==========================================================================*/
    6.47 +/** Number of bits in half a word. */
    6.48 +//#if __WORDSIZE == 64
    6.49 +//#define HALF_WORD_BITS 32
    6.50 +//#else
    6.51 +#define HALF_WORD_BITS 16
    6.52 +//#endif
    6.53 +
    6.54 +/** Mask for lo half of a word. On 32-bit this is 
    6.55 + * (1<<16) - 1 = 65535 = 0xffff
    6.56 + * It's 4294967295 = 0xffffffff on 64-bit.
    6.57 + */
    6.58 +#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
    6.59 +
    6.60 +/** Get the lo half of a word. */
    6.61 +#define LO_HALF(x) ((x) & LO_HALF_MASK)
    6.62 +
    6.63 +/** Get the hi half of a word. */
    6.64 +#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
    6.65 +
    6.66 +/** Do a full hash on both inputs, using DES-style non-linear scrambling.
    6.67 + * Both inputs are replaced with the results of the hash.
    6.68 + *
    6.69 + * @param pleft input/output word
    6.70 + * @param pright input/output word
    6.71 + */
    6.72 +void pseudo_des(unsigned long *pleft, unsigned long *pright){
    6.73 +    // Bit-rich mixing constant.
    6.74 +    static const unsigned long a_mixer[] = {
    6.75 +        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
    6.76 +
    6.77 +    // Bit-rich mixing constant.
    6.78 +    static const unsigned long b_mixer[] = {
    6.79 +        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
    6.80 +
    6.81 +    // Number of iterations - must be 2 or 4.
    6.82 +    static const int ncycle = 4;
    6.83 +    //static const int ncycle = 2;
    6.84 +
    6.85 +    unsigned long left = *pleft, right = *pright;
    6.86 +    unsigned long v, v_hi, v_lo;
    6.87 +    int i;
    6.88 +
    6.89 +    for(i=0; i<ncycle; i++){
    6.90 +        // Flip some bits in right to get v.
    6.91 +        v = right;
    6.92 +        v ^= a_mixer[i];
    6.93 +        // Get lo and hi halves of v.
    6.94 +        v_lo = LO_HALF(v);
    6.95 +        v_hi = HI_HALF(v);
    6.96 +        // Non-linear mix of the halves of v.
    6.97 +        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
    6.98 +        // Swap the halves of v.
    6.99 +        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
   6.100 +        // Flip some bits.
   6.101 +        v ^= b_mixer[i];
   6.102 +        // More non-linear mixing.
   6.103 +        v += (v_lo * v_hi);
   6.104 +        v ^= left;
   6.105 +        left = right;
   6.106 +        right = v;
   6.107 +    }
   6.108 +    *pleft = left;
   6.109 +    *pright = right;
   6.110 +}
   6.111 +
   6.112 +/** Hash a string.
   6.113 + *
   6.114 + * @param s input to hash
   6.115 + * @return hashcode
   6.116 + */
   6.117 +Hashcode hash_string(char *s){
   6.118 +    Hashcode h = 0;
   6.119 +    if(s){
   6.120 +        for( ; *s; s++){
   6.121 +            h = hash_2ul(h, *s);
   6.122 +        }
   6.123 +    }
   6.124 +    return h;
   6.125 +}
   6.126 +
   6.127 +/** Get the bucket for a hashcode in a hash table.
   6.128 + *
   6.129 + * @param table to get bucket from
   6.130 + * @param hashcode to get bucket for
   6.131 + * @return bucket
   6.132 + */
   6.133 +inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
   6.134 +    return table->buckets + (hashcode % table->buckets_n);
   6.135 +}
   6.136 +
   6.137 +/** Initialize a hash table.
   6.138 + * Can be safely called more than once.
   6.139 + *
   6.140 + * @param table to initialize
   6.141 + */
   6.142 +void HashTable_init(HashTable *table){
   6.143 +    int i;
   6.144 +
   6.145 +    if(!table->init_done){
   6.146 +        table->init_done = 1;
   6.147 +        table->next_id = 0;
   6.148 +        for(i=0; i<table->buckets_n; i++){
   6.149 +            HTBucket *bucket = get_bucket(table, i);
   6.150 +            bucket->head = 0;
   6.151 +            bucket->count = 0;
   6.152 +        }
   6.153 +        table->entry_count = 0;
   6.154 +    }
   6.155 +}
   6.156 +
   6.157 +/** Allocate a new hashtable.
   6.158 + * If the number of buckets is not positive the default is used.
   6.159 + * The number of buckets should usually be prime.
   6.160 + *
   6.161 + * @param buckets_n number of buckets
   6.162 + * @return new hashtable or null
   6.163 + */
   6.164 +HashTable *HashTable_new(int buckets_n){
   6.165 +    HashTable *z = ALLOCATE(HashTable);
   6.166 +    if(!z) goto exit;
   6.167 +    if(buckets_n <= 0){
   6.168 +        buckets_n = HT_BUCKETS_N;
   6.169 +    }
   6.170 +    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
   6.171 +    if(!z->buckets){
   6.172 +        deallocate(z);
   6.173 +        z = 0;
   6.174 +        goto exit;
   6.175 +    }
   6.176 +    z->buckets_n = buckets_n;
   6.177 +    HashTable_init(z);
   6.178 +  exit:
   6.179 +    return z;
   6.180 +}
   6.181 +
   6.182 +/** Free a hashtable.
   6.183 + * Any entries are removed and freed.
   6.184 + *
   6.185 + * @param h hashtable (ignored if null)
   6.186 + */
   6.187 +void HashTable_free(HashTable *h){
   6.188 +    if(h){
   6.189 +        HashTable_clear(h);
   6.190 +        deallocate(h->buckets);
   6.191 +        deallocate(h);
   6.192 +    }
   6.193 +}
   6.194 +
   6.195 +/** Push an entry on the list in the bucket for a given hashcode.
   6.196 + *
   6.197 + * @param table to add entry to
   6.198 + * @param hashcode for the entry
   6.199 + * @param entry to add
   6.200 + */
   6.201 +static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
   6.202 +				  HTEntry *entry){
   6.203 +    HTBucket *bucket;
   6.204 +    HTEntry *old_head;
   6.205 +
   6.206 +    bucket = get_bucket(table, hashcode);
   6.207 +    old_head = bucket->head;
   6.208 +    bucket->count++;
   6.209 +    bucket->head = entry;
   6.210 +    entry->next = old_head;
   6.211 +}
   6.212 +
   6.213 +/** Change the number of buckets in a hashtable.
   6.214 + * No-op if the number of buckets is not positive.
   6.215 + * Existing entries are reallocated to buckets based on their hashcodes.
   6.216 + * The table is unmodified if the number of buckets cannot be changed.
   6.217 + *
   6.218 + * @param table hashtable
   6.219 + * @param buckets_n new number of buckets
   6.220 + * @return 0 on success, error code otherwise
   6.221 + */
   6.222 +int HashTable_set_buckets_n(HashTable *table, int buckets_n){
   6.223 +    int err = 0;
   6.224 +    HTBucket *old_buckets = table->buckets;
   6.225 +    int old_buckets_n = table->buckets_n;
   6.226 +    int i;
   6.227 +
   6.228 +    if(buckets_n <= 0){
   6.229 +        err = -EINVAL;
   6.230 +        goto exit;
   6.231 +    }
   6.232 +    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
   6.233 +    if(!table->buckets){
   6.234 +        err = -ENOMEM;
   6.235 +        table->buckets = old_buckets;
   6.236 +        goto exit;
   6.237 +    }
   6.238 +    table->buckets_n = buckets_n;
   6.239 +    for(i=0; i<old_buckets_n; i++){
   6.240 +        HTBucket *bucket = old_buckets + i;
   6.241 +        HTEntry *entry, *next;
   6.242 +        for(entry = bucket->head; entry; entry = next){
   6.243 +            next = entry->next;
   6.244 +            push_on_bucket(table, entry->hashcode, entry);
   6.245 +        }
   6.246 +    }
   6.247 +    deallocate(old_buckets);
   6.248 +  exit:
   6.249 +    return err;
   6.250 +}
   6.251 +
   6.252 +/** Adjust the number of buckets so the table is neither too full nor too empty.
   6.253 + * The table is unmodified if adjusting fails.
   6.254 + *
   6.255 + * @param table hash table
   6.256 + * @param buckets_min minimum number of buckets (use default if 0 or negative)
   6.257 + * @return 0 on success, error code otherwise
   6.258 + */
   6.259 +int HashTable_adjust(HashTable *table, int buckets_min){
   6.260 +    int buckets_n = 0;
   6.261 +    int err = 0;
   6.262 +    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
   6.263 +    if(table->entry_count >= table->buckets_n){
   6.264 +        // The table is dense - expand it.
   6.265 +        buckets_n = 2 * table->buckets_n;
   6.266 +    } else if((table->buckets_n > buckets_min) &&
   6.267 +              (4 * table->entry_count < table->buckets_n)){
   6.268 +        // The table is more than minimum size and sparse - shrink it.
   6.269 +        buckets_n = 2 * table->entry_count;
   6.270 +        if(buckets_n < buckets_min) buckets_n = buckets_min;
   6.271 +    }
   6.272 +    if(buckets_n){
   6.273 +        err = HashTable_set_buckets_n(table, buckets_n);
   6.274 +    }
   6.275 +    return err;
   6.276 +}
   6.277 +
   6.278 +/** Allocate a new entry for a given value.
   6.279 + *
   6.280 + * @param value to put in the entry
   6.281 + * @return entry, or 0 on failure
   6.282 + */
   6.283 +HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
   6.284 +    HTEntry *z = ALLOCATE(HTEntry);
   6.285 +    if(z){
   6.286 +        z->hashcode = hashcode;
   6.287 +        z->key = key;
   6.288 +        z->value = value;
   6.289 +    }
   6.290 +    return z;
   6.291 +}
   6.292 +
   6.293 +/** Free an entry.
   6.294 + *
   6.295 + * @param z entry to free
   6.296 + */
   6.297 +inline void HTEntry_free(HTEntry *z){
   6.298 +    if(z){
   6.299 +        deallocate(z);
   6.300 +    }
   6.301 +}
   6.302 +
   6.303 +/** Free an entry in a hashtable.
   6.304 + * The table's entry_free_fn is used is defined, otherwise 
   6.305 + * the HTEntry itself is freed.
   6.306 + *
   6.307 + * @param table hashtable
   6.308 + * @param entry to free
   6.309 + */
   6.310 +inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
   6.311 +    if(!entry)return;
   6.312 +    if(table && table->entry_free_fn){
   6.313 +        table->entry_free_fn(table, entry);
   6.314 +    } else {
   6.315 +        HTEntry_free(entry);
   6.316 +    }
   6.317 +}
   6.318 +
   6.319 +/** Get the first entry satisfying a test from the bucket for the
   6.320 + * given hashcode.
   6.321 + *
   6.322 + * @param table to look in
   6.323 + * @param hashcode indicates the bucket
   6.324 + * @param test_fn test to apply to elements
   6.325 + * @param arg first argument to calls to test_fn
   6.326 + * @return entry found, or 0
   6.327 + */
   6.328 +inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
   6.329 +				      TableTestFn *test_fn, TableArg arg){
   6.330 +    HTBucket *bucket;
   6.331 +    HTEntry *entry = 0;
   6.332 +    HTEntry *next;
   6.333 +
   6.334 +    bucket = get_bucket(table, hashcode);
   6.335 +    for(entry = bucket->head; entry; entry = next){
   6.336 +        next = entry->next;
   6.337 +        if(test_fn(arg, table, entry)){
   6.338 +            break;
   6.339 +        }
   6.340 +    }
   6.341 +    return entry;
   6.342 +}
   6.343 +
   6.344 +/** Test hashtable keys for equality.
   6.345 + * Uses the table's key_equal_fn if defined, otherwise pointer equality.
   6.346 + *
   6.347 + * @param key1 key to compare
   6.348 + * @param key2 key to compare
   6.349 + * @return 1 if equal, 0 otherwise
   6.350 + */
   6.351 +inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
   6.352 +    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
   6.353 +}
   6.354 +
   6.355 +/** Compute the hashcode of a hashtable key.
   6.356 + * The table's key_hash_fn is used if defined, otherwise the address of
   6.357 + * the key is hashed.
   6.358 + *
   6.359 + * @param table hashtable
   6.360 + * @param key to hash
   6.361 + * @return hashcode
   6.362 + */
   6.363 +inline Hashcode HashTable_key_hash(HashTable *table, void *key){
   6.364 +    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
   6.365 +}
   6.366 +
   6.367 +/** Test if an entry has a given key.
   6.368 + *
   6.369 + * @param arg containing key to test for
   6.370 + * @param table the entry is in
   6.371 + * @param entry to test
   6.372 + * @return 1 if the entry has the key, 0 otherwise
   6.373 + */
   6.374 +static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
   6.375 +    return HashTable_key_equal(table, arg.ptr, entry->key);
   6.376 +}
   6.377 +
   6.378 +/** Get an entry with a given key.
   6.379 + *
   6.380 + * @param table to search
   6.381 + * @param key to look for
   6.382 + * @return entry if found, null otherwise
   6.383 + */
   6.384 +#if 0
   6.385 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
   6.386 +    TableArg arg = { ptr: key };
   6.387 +    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
   6.388 +}
   6.389 +#else
   6.390 +inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
   6.391 +    Hashcode hashcode;
   6.392 +    HTBucket *bucket;
   6.393 +    HTEntry *entry = 0;
   6.394 +    HTEntry *next;
   6.395 +
   6.396 +    hashcode = HashTable_key_hash(table, key);
   6.397 +    bucket = get_bucket(table, hashcode);
   6.398 +    for(entry = bucket->head; entry; entry = next){
   6.399 +        next = entry->next;
   6.400 +        if(HashTable_key_equal(table, key, entry->key)){
   6.401 +            break;
   6.402 +        }
   6.403 +    }
   6.404 +    return entry;
   6.405 +}
   6.406 +#endif
   6.407 +
   6.408 +/** Get the value of an entry with a given key.
   6.409 + *
   6.410 + * @param table to search
   6.411 + * @param key to look for
   6.412 + * @return value if an entry was found, null otherwise
   6.413 + */
   6.414 +inline void * HashTable_get(HashTable *table, void *key){
   6.415 +    HTEntry *entry = HashTable_get_entry(table, key);
   6.416 +    return (entry ? entry->value : 0);
   6.417 +}
   6.418 +
   6.419 +/** Print the buckets in a table.
   6.420 + *
   6.421 + * @param table to print
   6.422 + */
   6.423 +void show_buckets(HashTable *table, IOStream *io){
   6.424 +    int i,j ;
   6.425 +    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
   6.426 +    for(i=0; i<table->buckets_n; i++){
   6.427 +        if(0 || table->buckets[i].count>0){
   6.428 +            IOStream_print(io, "bucket %3d %3d %10p ", i,
   6.429 +                        table->buckets[i].count,
   6.430 +                        table->buckets[i].head);
   6.431 +            for(j = table->buckets[i].count; j>0; j--){
   6.432 +                IOStream_print(io, "+");
   6.433 +            }
   6.434 +            IOStream_print(io, "\n");
   6.435 +        }
   6.436 +    }
   6.437 +    HashTable_print(table, io); 
   6.438 +}
   6.439 +    
   6.440 +/** Print an entry in a table.
   6.441 + *
   6.442 + * @param entry to print
   6.443 + * @param arg a pointer to an IOStream to print to
   6.444 + * @return 0
   6.445 + */
   6.446 +static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
   6.447 +    IOStream *io = (IOStream*)arg.ptr;
   6.448 +    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
   6.449 +                entry->hashcode % table->buckets_n,
   6.450 +                entry->hashcode,
   6.451 +                entry->index,
   6.452 +                entry, entry->key, entry->value);
   6.453 +    return 0;
   6.454 +}
   6.455 +
   6.456 +/** Print a hash table.
   6.457 + *
   6.458 + * @param table to print
   6.459 + */
   6.460 +void HashTable_print(HashTable *table, IOStream *io){
   6.461 +    IOStream_print(io, "{\n");
   6.462 +    HashTable_map(table, print_entry, (TableArg){ ptr: io });
   6.463 +    IOStream_print(io, "}\n");
   6.464 +}
   6.465 +/*==========================================================================*/
   6.466 +
   6.467 +/** Get the next entry id to use for a table.
   6.468 + *
   6.469 + * @param table hash table
   6.470 + * @return non-zero entry id
   6.471 + */
   6.472 +static inline unsigned long get_next_id(HashTable *table){
   6.473 +    unsigned long id;
   6.474 +
   6.475 +    if(table->next_id == 0){
   6.476 +        table->next_id = 1;
   6.477 +    }
   6.478 +    id = table->next_id++;
   6.479 +    return id;
   6.480 +}
   6.481 +
   6.482 +/** Add an entry to the bucket for the
   6.483 + * given hashcode.
   6.484 + *
   6.485 + * @param table to insert in
   6.486 + * @param hashcode indicates the bucket
   6.487 + * @param key to add an entry for
   6.488 + * @param value to add an entry for
   6.489 + * @return entry on success, 0 on failure
   6.490 + */
   6.491 +inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
   6.492 +    HTEntry *entry = HTEntry_new(hashcode, key, value);
   6.493 +    if(entry){
   6.494 +        entry->index = get_next_id(table);
   6.495 +        push_on_bucket(table, hashcode, entry);
   6.496 +        table->entry_count++;
   6.497 +    }
   6.498 +    return entry;
   6.499 +}
   6.500 +
   6.501 +/** Move the front entry for a bucket to the correct point in the bucket order as
   6.502 + * defined by the order function. If this is called every time a new entry is added
   6.503 + * the bucket will be maintained in sorted order.
   6.504 + *
   6.505 + * @param table to modify
   6.506 + * @param hashcode indicates the bucket
   6.507 + * @param order entry comparison function
   6.508 + * @return 0 if an entry was moved, 1 if not
   6.509 + */
   6.510 +int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
   6.511 +    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
   6.512 +    HTBucket *bucket;
   6.513 +    int err = 1;
   6.514 +
   6.515 +    bucket = get_bucket(table, hashcode);
   6.516 +    new_entry = bucket->head;
   6.517 +    if(!new_entry || !new_entry->next) goto exit;
   6.518 +    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
   6.519 +        if(order(new_entry, entry) <= 0) break;
   6.520 +    }
   6.521 +    if(prev){
   6.522 +        err = 0;
   6.523 +        bucket->head = new_entry->next; 
   6.524 +        new_entry->next = entry;
   6.525 +        prev->next = new_entry;
   6.526 +    }
   6.527 +  exit:
   6.528 +    return err;
   6.529 +}
   6.530 +
   6.531 +/** Add an entry to a hashtable.
   6.532 + * The entry is added to the bucket for its key's hashcode.
   6.533 + *
   6.534 + * @param table to insert in
   6.535 + * @param key to add an entry for
   6.536 + * @param value to add an entry for
   6.537 + * @return entry on success, 0 on failure
   6.538 + */
   6.539 +inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
   6.540 +    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
   6.541 +}
   6.542 +
   6.543 +
   6.544 +/** Remove entries satisfying a test from the bucket for the
   6.545 + * given hashcode. 
   6.546 + *
   6.547 + * @param table to remove from
   6.548 + * @param hashcode indicates the bucket
   6.549 + * @param test_fn test to apply to elements
   6.550 + * @param arg first argument to calls to test_fn
   6.551 + * @return number of entries removed
   6.552 + */
   6.553 +inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
   6.554 +				  TableTestFn *test_fn, TableArg arg){
   6.555 +    HTBucket *bucket;
   6.556 +    HTEntry *entry, *prev = 0, *next;
   6.557 +    int removed_count = 0;
   6.558 +
   6.559 +    bucket = get_bucket(table, hashcode);
   6.560 +    for(entry = bucket->head; entry; entry = next){
   6.561 +        next = entry->next;
   6.562 +        if(test_fn(arg, table, entry)){
   6.563 +            if(prev){
   6.564 +                prev->next = next;
   6.565 +            } else {
   6.566 +                bucket->head = next;
   6.567 +            }
   6.568 +            bucket->count--;
   6.569 +            table->entry_count--;
   6.570 +            removed_count++;
   6.571 +            HashTable_free_entry(table, entry);
   6.572 +            entry = 0;
   6.573 +        }
   6.574 +        prev = entry;
   6.575 +    }
   6.576 +    return removed_count;
   6.577 +}
   6.578 +
   6.579 +/** Remove entries with a given key. 
   6.580 + *
   6.581 + * @param table to remove from
   6.582 + * @param key of entries to remove
   6.583 + * @return number of entries removed
   6.584 + */
   6.585 +inline int HashTable_remove(HashTable *table, void *key){
   6.586 +#if 1
   6.587 +    Hashcode hashcode;
   6.588 +    HTBucket *bucket;
   6.589 +    HTEntry *entry, *prev = 0, *next;
   6.590 +    int removed_count = 0;
   6.591 +
   6.592 +    hashcode = HashTable_key_hash(table, key);
   6.593 +    bucket = get_bucket(table, hashcode);
   6.594 +    for(entry = bucket->head; entry; entry = next){
   6.595 +        next = entry->next;
   6.596 +        if(HashTable_key_equal(table, key, entry->key)){
   6.597 +            if(prev){
   6.598 +                prev->next = next;
   6.599 +            } else {
   6.600 +                bucket->head = next;
   6.601 +            }
   6.602 +            bucket->count--;
   6.603 +            table->entry_count--;
   6.604 +            removed_count++;
   6.605 +            HashTable_free_entry(table, entry);
   6.606 +            entry = 0;
   6.607 +        }
   6.608 +        prev = entry;
   6.609 +    }
   6.610 +    return removed_count;
   6.611 +#else
   6.612 +    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
   6.613 +				  has_key, (TableArg){ ptr: key});
   6.614 +#endif
   6.615 +}
   6.616 +
   6.617 +/** Remove (and free) all the entries in a bucket.
   6.618 + *
   6.619 + * @param bucket to clear
   6.620 + */
   6.621 +static inline void bucket_clear(HashTable *table, HTBucket *bucket){
   6.622 +    HTEntry *entry, *next;
   6.623 +
   6.624 +    for(entry = bucket->head; entry; entry = next){
   6.625 +        next = entry->next;
   6.626 +        HashTable_free_entry(table, entry);
   6.627 +    }
   6.628 +    bucket->head = 0;
   6.629 +    table->entry_count -= bucket->count;
   6.630 +    bucket->count = 0;
   6.631 +}
   6.632 +
   6.633 +/** Remove (and free) all the entries in a table.
   6.634 + *
   6.635 + * @param table to clear
   6.636 + */
   6.637 +void HashTable_clear(HashTable *table){
   6.638 +    int i, n = table->buckets_n;
   6.639 +
   6.640 +    for(i=0; i<n; i++){
   6.641 +        bucket_clear(table, table->buckets + i);
   6.642 +    }
   6.643 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/libxutil/hash_table.h	Mon Nov 22 16:41:50 2004 +0000
     7.3 @@ -0,0 +1,294 @@
     7.4 +/*
     7.5 + * Copyright (C) 2001 - 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 published by
     7.9 + * the Free Software Foundation; either version 2.1 of the License, or
    7.10 + * (at your option) any later version.
    7.11 + *
    7.12 + * This library is distributed in the hope that it will be useful,
    7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.15 + * GNU Lesser General Public License for more details.
    7.16 + *
    7.17 + * You should have received a copy of the GNU Lesser General Public License
    7.18 + * along with this library; if not, write to the Free Software
    7.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    7.20 + */
    7.21 +
    7.22 +#ifndef _XUTIL_HASH_TABLE_H_
    7.23 +#define _XUTIL_HASH_TABLE_H_
    7.24 +
    7.25 +#include "iostream.h"
    7.26 +
    7.27 +typedef unsigned long Hashcode;
    7.28 +
    7.29 +/** Type used to pass parameters to table functions. */
    7.30 +typedef union TableArg {
    7.31 +    unsigned long ul;
    7.32 +    void *ptr;
    7.33 +} TableArg;
    7.34 +
    7.35 +/** An entry in a bucket list. */
    7.36 +typedef struct HTEntry {
    7.37 +    /** Hashcode of the entry's key. */
    7.38 +    Hashcode hashcode;
    7.39 +    /** Identifier for this entry in the table. */
    7.40 +    int index;
    7.41 +    /** The key for this entry. */
    7.42 +    void *key;
    7.43 +    /** The value in this entry. */
    7.44 +    void *value;
    7.45 +    /** The next entry in the list. */
    7.46 +    struct HTEntry *next;
    7.47 +} HTEntry;
    7.48 +
    7.49 +/** A bucket in a rule table. */
    7.50 +typedef struct HTBucket {
    7.51 +    /** Number of entries in the bucket. */
    7.52 +    int count;
    7.53 +    /** First entry in the bucket (may be null). */
    7.54 +    HTEntry *head;
    7.55 +} HTBucket;
    7.56 +
    7.57 +/** Default number of buckets in a hash table.
    7.58 + * You want enough buckets so the lists in the buckets will typically be short.
    7.59 + * It's a good idea if this is prime, since that will help to spread hashcodes
    7.60 + * around the table.
    7.61 + */
    7.62 +//#define HT_BUCKETS_N 1
    7.63 +//#define HT_BUCKETS_N 3
    7.64 +//#define HT_BUCKETS_N 7
    7.65 +//#define HT_BUCKETS_N 17
    7.66 +//#define HT_BUCKETS_N 97
    7.67 +//#define HT_BUCKETS_N 211
    7.68 +//#define HT_BUCKETS_N 401
    7.69 +#define HT_BUCKETS_N 1021
    7.70 +
    7.71 +typedef struct HashTable HashTable;
    7.72 +
    7.73 +/** Type for a function used to select table entries. */
    7.74 +typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
    7.75 +
    7.76 +/** Type for a function to map over table entries. */
    7.77 +typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
    7.78 +
    7.79 +/** Type for a function to free table entries. */
    7.80 +typedef void TableFreeFn(HashTable *table, HTEntry *entry);
    7.81 +
    7.82 +/** Type for a function to hash table keys. */
    7.83 +typedef Hashcode TableHashFn(void *key);
    7.84 +
    7.85 +/** Type for a function to test table keys for equality. */
    7.86 +typedef int TableEqualFn(void *key1, void *key2);
    7.87 +
    7.88 +/** Type for a function to order table entries. */
    7.89 +typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
    7.90 +
    7.91 +/** General hash table.
    7.92 + * A hash table with a list in each bucket.
    7.93 + * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
    7.94 + * These all default to 0, when default behaviour treating keys as integers is used.
    7.95 + */
    7.96 +struct HashTable {
    7.97 +    /** Flag indicating whether the table has been initialised. */
    7.98 +    int init_done;
    7.99 +    /** Next value for the id field in inserted rules. */
   7.100 +    unsigned long next_id;
   7.101 +    /** Number of buckets in the bucket array. */
   7.102 +    int buckets_n;
   7.103 +    /** Array of buckets, each with its own list. */
   7.104 +    HTBucket *buckets;
   7.105 +    /** Number of entries in the table. */
   7.106 +    int entry_count;
   7.107 +    /** Function to free keys and values in entries. */
   7.108 +    TableFreeFn *entry_free_fn;
   7.109 +    /** Function to hash keys. */
   7.110 +    TableHashFn *key_hash_fn;
   7.111 +    /** Function to compare keys for equality. */
   7.112 +    TableEqualFn *key_equal_fn;
   7.113 +    /** Place for the user of the table to hang extra data. */
   7.114 +    void *user_data;
   7.115 +};
   7.116 +
   7.117 +extern HashTable *HashTable_new(int bucket_n);
   7.118 +extern void HashTable_free(HashTable *table);
   7.119 +extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
   7.120 +extern void HTEntry_free(HTEntry *entry);
   7.121 +extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
   7.122 +extern void HashTable_clear(HashTable *table);
   7.123 +extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
   7.124 +extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
   7.125 +extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
   7.126 +extern void * HashTable_get(HashTable *table, void *key);
   7.127 +extern int HashTable_remove(HashTable *table, void *key);
   7.128 +extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
   7.129 +                                      TableTestFn *test_fn, TableArg arg);
   7.130 +extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
   7.131 +                                   TableTestFn *test_fn, TableArg arg);
   7.132 +//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
   7.133 +extern void HashTable_print(HashTable *table, IOStream *out);
   7.134 +extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
   7.135 +extern int HashTable_adjust(HashTable *table, int buckets_min);
   7.136 +extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
   7.137 +extern Hashcode hash_string(char *s);
   7.138 +
   7.139 +extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
   7.140 +
   7.141 +/** Control whether to use hashing based on DES or simple
   7.142 + * hashing. DES hashing is `more random' but much more expensive.
   7.143 + */
   7.144 +#define HASH_PSEUDO_DES 0
   7.145 +
   7.146 +/** Hash a long using a quick and dirty linear congruential random number generator.
   7.147 + *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
   7.148 + *
   7.149 + * @param a value to hash
   7.150 + * @return hashed input
   7.151 + */
   7.152 +static inline unsigned long lcrng_hash(unsigned long a){
   7.153 +    return (1664525L * a + 1013904223L);
   7.154 +}
   7.155 +
   7.156 +/** Hash an unsigned long.
   7.157 + *
   7.158 + * @param a input to hash
   7.159 + * @return hashcode
   7.160 + */
   7.161 +static inline Hashcode hash_ul(unsigned long a){
   7.162 +#if HASH_PSEUDO_DES
   7.163 +    unsigned long left = a;
   7.164 +    unsigned long right = 0L;
   7.165 +    pseudo_des(&left, &right);
   7.166 +    return right;
   7.167 +#else
   7.168 +    a = lcrng_hash(a);
   7.169 +    a = lcrng_hash(a);
   7.170 +    return a;
   7.171 +#endif
   7.172 +}
   7.173 +
   7.174 +/** Hash two unsigned longs together.
   7.175 + *
   7.176 + * @param a input to hash
   7.177 + * @param b input to hash
   7.178 + * @return hashcode
   7.179 + */
   7.180 +static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
   7.181 +#if HASH_PSEUDO_DES
   7.182 +    unsigned long left = a;
   7.183 +    unsigned long right = b;
   7.184 +    pseudo_des(&left, &right);
   7.185 +    return right;
   7.186 +#else
   7.187 +    a = lcrng_hash(a);
   7.188 +    a ^= b;
   7.189 +    a = lcrng_hash(a);
   7.190 +    return a;
   7.191 +#endif
   7.192 +}
   7.193 +
   7.194 +/** Hash a hashcode and an unsigned long together.
   7.195 + *
   7.196 + * @param a input hashcode
   7.197 + * @param b input to hash
   7.198 + * @return hashcode
   7.199 + */
   7.200 +static inline Hashcode hash_hul(Hashcode a, unsigned long b){
   7.201 +#if HASH_PSEUDO_DES
   7.202 +    unsigned long left = a;
   7.203 +    unsigned long right = b;
   7.204 +    pseudo_des(&left, &right);
   7.205 +    return right;
   7.206 +#else
   7.207 +    a ^= b;
   7.208 +    a = lcrng_hash(a);
   7.209 +    return a;
   7.210 +#endif
   7.211 +}
   7.212 +
   7.213 +/** Macro to declare variables for HashTable_for_each() to use.
   7.214 + *
   7.215 + * @param entry variable that is set to entries in the table
   7.216 + */
   7.217 +#define HashTable_for_decl(entry) \
   7.218 +  HashTable *_var_table; \
   7.219 +  HTBucket *_var_bucket; \
   7.220 +  HTBucket *_var_end; \
   7.221 +  HTEntry *_var_next; \
   7.222 +  HTEntry *entry
   7.223 +
   7.224 +/** Macro to iterate over the entries in a hashtable.
   7.225 + * Must be in a scope where HashTable_for_decl() has been used to declare
   7.226 + * variables for it to use.
   7.227 + * The variable 'entry' is iterated over entries in the table.
   7.228 + * The code produced is syntactically a loop, so it must be followed by
   7.229 + * a loop body, typically some statements in braces:
   7.230 + * HashTable_for_each(entry, table){ ...loop body... }
   7.231 + *
   7.232 + * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
   7.233 + * loops as variables will clash.
   7.234 + *
   7.235 + * @note The simplest way to code a direct loop over the entries in a hashtable
   7.236 + * is to use a loop over the buckets, with a nested loop over the entries
   7.237 + * in a bucket. Using this approach in a macro means the macro contains
   7.238 + * an opening brace, and calls to it must be followed by 2 braces!
   7.239 + * To avoid this the code has been restructured so that it is a for loop.
   7.240 + * So that statements could be used in the test expression of the for loop,
   7.241 + * we have used the gcc statement expression extension ({ ... }).
   7.242 + *
   7.243 + * @param entry variable to iterate over the entries
   7.244 + * @param table to iterate over (non-null)
   7.245 + */
   7.246 +#define HashTable_for_each(entry, table) \
   7.247 +  _var_table = table; \
   7.248 +  _var_bucket = _var_table->buckets; \
   7.249 +  _var_end = _var_bucket + _var_table->buckets_n; \
   7.250 +  for(entry=0, _var_next=0; \
   7.251 +      ({ if(_var_next){ \
   7.252 +             entry = _var_next; \
   7.253 +             _var_next = entry->next; \
   7.254 +          } else { \
   7.255 +             while(_var_bucket < _var_end){ \
   7.256 +                 entry = _var_bucket->head; \
   7.257 +                 _var_bucket++; \
   7.258 +                 if(entry){ \
   7.259 +                      _var_next = entry->next; \
   7.260 +                      break; \
   7.261 +                 } \
   7.262 +             } \
   7.263 +          }; \
   7.264 +         entry; }); \
   7.265 +      entry = _var_next )
   7.266 +
   7.267 +/** Map a function over the entries in a table.
   7.268 + * Mapping stops when the function returns a non-zero value.
   7.269 + * Uses the gcc statement expression extension ({ ... }).
   7.270 + *
   7.271 + * @param table to map over
   7.272 + * @param fn function to apply to entries
   7.273 + * @param arg first argument to call the function with
   7.274 + * @return 0 if fn always returned 0, first non-zero value otherwise
   7.275 + */
   7.276 +#define HashTable_map(table, fn, arg) \
   7.277 +  ({ HashTable_for_decl(_var_entry); \
   7.278 +    TableArg _var_arg = arg; \
   7.279 +    int _var_value = 0; \
   7.280 +    HashTable_for_each(_var_entry, table){ \
   7.281 +        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
   7.282 +    } \
   7.283 +    _var_value; })
   7.284 +
   7.285 +/** Cast x to the type for a key or value in a hash table.
   7.286 + * This avoids compiler warnings when using short integers
   7.287 + * as keys or values (especially on 64-bit platforms).
   7.288 + */
   7.289 +#define HKEY(x) ((void*)(unsigned long)(x))
   7.290 +
   7.291 +/** Cast x from the type for a key or value in a hash table.
   7.292 + * to an unsigned long. This avoids compiler warnings when using
   7.293 + * short integers as keys or values (especially on 64-bit platforms).
   7.294 + */
   7.295 +#define HVAL(x) ((unsigned long)(x))
   7.296 +
   7.297 +#endif /* !_XUTIL_HASH_TABLE_H_ */
     8.1 --- a/tools/libxutil/iostream.c	Sun Nov 21 20:41:00 2004 +0000
     8.2 +++ b/tools/libxutil/iostream.c	Mon Nov 22 16:41:50 2004 +0000
     8.3 @@ -1,3 +1,21 @@
     8.4 +/*
     8.5 + * Copyright (C) 2001 - 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 published by
     8.9 + * the Free Software Foundation; either version 2.1 of the License, or
    8.10 + * (at your option) any later version.
    8.11 + *
    8.12 + * This library is distributed in the hope that it will be useful,
    8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.15 + * GNU Lesser General Public License for more details.
    8.16 + *
    8.17 + * You should have received a copy of the GNU Lesser General Public License
    8.18 + * along with this library; if not, write to the Free Software
    8.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    8.20 + */
    8.21 +
    8.22  #include "iostream.h"
    8.23  #include "sys_string.h"
    8.24  
     9.1 --- a/tools/libxutil/iostream.h	Sun Nov 21 20:41:00 2004 +0000
     9.2 +++ b/tools/libxutil/iostream.h	Mon Nov 22 16:41:50 2004 +0000
     9.3 @@ -1,14 +1,34 @@
     9.4 -#ifndef _XC_LINUX_SAVE_H_
     9.5 -#define _XC_LINUX_SAVE_H_
     9.6 +/*
     9.7 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
     9.8 + *
     9.9 + * This library is free software; you can redistribute it and/or modify
    9.10 + * it under the terms of the GNU Lesser General Public License as published by
    9.11 + * the Free Software Foundation; either version 2.1 of the License, or
    9.12 + * (at your option) any later version.
    9.13 + *
    9.14 + * This library is distributed in the hope that it will be useful,
    9.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    9.17 + * GNU Lesser General Public License for more details.
    9.18 + *
    9.19 + * You should have received a copy of the GNU Lesser General Public License
    9.20 + * along with this library; if not, write to the Free Software
    9.21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    9.22 + */
    9.23 +
    9.24 +#ifndef _XUTIL_IOSTREAM_H_
    9.25 +#define _XUTIL_IOSTREAM_H_
    9.26  
    9.27  #include <stdarg.h>
    9.28 -#include <stdint.h>
    9.29 -#include <stddef.h>
    9.30  
    9.31  #ifdef __KERNEL__
    9.32 +#include <linux/config.h>
    9.33 +#include <linux/types.h>
    9.34  #include <linux/errno.h>
    9.35  #else
    9.36  #include <errno.h>
    9.37 +#include <stdint.h>
    9.38 +#include <stddef.h>
    9.39  #endif
    9.40  
    9.41  #include "allocate.h"
    9.42 @@ -240,4 +260,4 @@ static inline int IOStream_get_written(I
    9.43  }
    9.44  
    9.45  
    9.46 -#endif /* ! _XC_LINUX_SAVE_H_ */
    9.47 +#endif /* ! _XUTIL_IOSTREAM_H_ */
    10.1 --- a/tools/libxutil/kernel_stream.c	Sun Nov 21 20:41:00 2004 +0000
    10.2 +++ b/tools/libxutil/kernel_stream.c	Mon Nov 22 16:41:50 2004 +0000
    10.3 @@ -50,7 +50,7 @@ typedef struct KernelData {
    10.4      char buf[BUF_N];
    10.5  } KernelData;
    10.6  
    10.7 -static int kernel_write(IOStream *s, const char *msg, int n);
    10.8 +static int kernel_write(IOStream *s, const void *msg, size_t n);
    10.9  static void kernel_free(IOStream *s);
   10.10  static void kernel_stream_lock(IOStream *s);
   10.11  static void kernel_stream_unlock(IOStream *s);
   10.12 @@ -145,13 +145,13 @@ void kernel_stream_unlock(IOStream *s){
   10.13   * @param args print arguments
   10.14   * @return result of the print
   10.15   */
   10.16 -static int kernel_write(IOStream *stream, const char *buf, int n){
   10.17 +static int kernel_write(IOStream *stream, const void *buf, size_t n){
   10.18    KernelData *kdata = get_kernel_data(stream);
   10.19    int k;
   10.20    k = kdata->buf_n - 1;
   10.21    if(n < k) k = n;
   10.22    memcpy(kdata->buf, buf, k);
   10.23 -  kdata->buf[k] = '\0'
   10.24 +  kdata->buf[k] = '\0';
   10.25    printk(kdata->buf);
   10.26    return k;
   10.27  }
   10.28 @@ -167,7 +167,7 @@ static void kernel_free(IOStream *io){
   10.29    KernelData *kdata;
   10.30    if(io == &iokernel) return;
   10.31    kdata = get_kernel_data(io);
   10.32 -  zero(kdata, sizeof(*kdata));
   10.33 +  memset(kdata, 0, sizeof(*kdata));
   10.34    deallocate(kdata);
   10.35  }
   10.36  #endif /* __KERNEL__ */
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tools/libxutil/lexis.c	Mon Nov 22 16:41:50 2004 +0000
    11.3 @@ -0,0 +1,94 @@
    11.4 +/*
    11.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    11.6 + *
    11.7 + * This library is free software; you can redistribute it and/or modify
    11.8 + * it under the terms of the GNU Lesser General Public License as
    11.9 + * published by the Free Software Foundation; either version 2.1 of the
   11.10 + * License, or  (at your option) any later version. This library is 
   11.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   11.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   11.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   11.14 + * See the GNU Lesser General Public License for more details.
   11.15 + *
   11.16 + * You should have received a copy of the GNU Lesser General Public License
   11.17 + * along with this library; if not, write to the Free Software Foundation,
   11.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   11.19 + */
   11.20 +
   11.21 +/** @file
   11.22 + * Lexical analysis.
   11.23 + */
   11.24 +
   11.25 +#include "sys_string.h"
   11.26 +#include "lexis.h"
   11.27 +#include <errno.h>
   11.28 +
   11.29 +/** Check if a value lies in a (closed) range.
   11.30 + *
   11.31 + * @param x value to test
   11.32 + * @param lo low end of the range
   11.33 + * @param hi high end of the range
   11.34 + * @return 1 if x is in the interval [lo, hi], 0 otherwise
   11.35 + */
   11.36 +inline static int in_range(int x, int lo, int hi){
   11.37 +    return (lo <= x) && (x <= hi);
   11.38 +}
   11.39 +
   11.40 +/** Determine if a string is an (unsigned) decimal number.
   11.41 + * 
   11.42 + * @param s pointer to characters to test
   11.43 + * @param n length of string
   11.44 + * @return 1 if s is a decimal number, 0 otherwise.
   11.45 + */
   11.46 +int is_decimal_number(const char *s, int n){
   11.47 +    int i;
   11.48 +    if(n <= 0)return 0;
   11.49 +    for(i = 0; i < n; i++){
   11.50 +        if(!in_decimal_digit_class(s[i])) return 0;
   11.51 +    }
   11.52 +    return 1;
   11.53 +}
   11.54 +
   11.55 +/** Determine if a string is a hex number.
   11.56 + * Hex numbers are 0, or start with 0x or 0X followed
   11.57 + * by a non-zero number of hex digits (0-9,a-f,A-F).
   11.58 + * 
   11.59 + * @param s pointer to characters to test
   11.60 + * @param n length of string
   11.61 + * @return 1 if s is a hex number, 0 otherwise.
   11.62 + */
   11.63 +int is_hex_number(const char *s, int n){
   11.64 +    int i;
   11.65 +    if(n <= 0) return 0;
   11.66 +    if(n == 1){
   11.67 +        return s[0]=='0';
   11.68 +    }
   11.69 +    if(n <= 3) return 0;
   11.70 +    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
   11.71 +    for(i = 2; i < n; i++){
   11.72 +        if(!in_hex_digit_class(s[i])) return 0;
   11.73 +    }
   11.74 +    return 1;
   11.75 +}
   11.76 +
   11.77 +/** Test if a string matches a keyword.
   11.78 + * The comparison is case-insensitive.
   11.79 + * The comparison fails if either argument is null.
   11.80 + *
   11.81 + * @param s string
   11.82 + * @param k keyword
   11.83 + * @return 1 if they match, 0 otherwise
   11.84 + */
   11.85 +int is_keyword(const char *s, const char *k){
   11.86 +  return s && k && !strcasecmp(s, k);
   11.87 +}
   11.88 +
   11.89 +/** Test if a string matches a character.
   11.90 + *
   11.91 + * @param s string
   11.92 + * @param c character (non-null)
   11.93 + * @return 1 if s contains exactly c, 0 otherwise
   11.94 + */
   11.95 +int is_keychar(const char *s, char c){
   11.96 +  return c && (s[0] == c) && !s[1];
   11.97 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/tools/libxutil/lexis.h	Mon Nov 22 16:41:50 2004 +0000
    12.3 @@ -0,0 +1,128 @@
    12.4 +/*
    12.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    12.6 + *
    12.7 + * This library is free software; you can redistribute it and/or modify
    12.8 + * it under the terms of the GNU Lesser General Public License as
    12.9 + * published by the Free Software Foundation; either version 2.1 of the
   12.10 + * License, or  (at your option) any later version. This library is 
   12.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   12.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   12.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   12.14 + * See the GNU Lesser General Public License for more details.
   12.15 + *
   12.16 + * You should have received a copy of the GNU Lesser General Public License
   12.17 + * along with this library; if not, write to the Free Software Foundation,
   12.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   12.19 + */
   12.20 +
   12.21 +#ifndef _XUTIL_LEXIS_H_
   12.22 +#define _XUTIL_LEXIS_H_
   12.23 +
   12.24 +#include "sys_string.h"
   12.25 +
   12.26 +#ifdef __KERNEL__
   12.27 +#  include <linux/ctype.h>
   12.28 +#else
   12.29 +#  include <ctype.h>
   12.30 +#endif
   12.31 +
   12.32 +/** @file
   12.33 + * Lexical analysis.
   12.34 + */
   12.35 +
   12.36 +/** Class of characters treated as space. */
   12.37 +#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
   12.38 +
   12.39 +/** Class of separator characters. */
   12.40 +#define sep_class "{}()<>[]@!;"
   12.41 +
   12.42 +#define comment_class "#"
   12.43 +
   12.44 +/** Determine if a character is in a given class.
   12.45 + * 
   12.46 + * @param c character to test
   12.47 + * @param s null-terminated string of characters in the class
   12.48 + * @return 1 if c is in the class, 0 otherwise.
   12.49 + */
   12.50 +static inline int in_class(int c, const char *s){
   12.51 +  return s && (strchr(s, c) != 0);
   12.52 +}
   12.53 +
   12.54 +/** Determine if a character is in the space class.
   12.55 + * 
   12.56 + * @param c character to test
   12.57 + * @return 1 if c is in the class, 0 otherwise.
   12.58 + */
   12.59 +static inline int in_space_class(int c){
   12.60 +    return in_class(c, space_class);
   12.61 +}
   12.62 +
   12.63 +static inline int in_comment_class(int c){
   12.64 +    return in_class(c, comment_class);
   12.65 +}
   12.66 +
   12.67 +/** Determine if a character is in the separator class.
   12.68 + * Separator characters terminate tokens, and do not need space
   12.69 + * to separate them.
   12.70 + * 
   12.71 + * @param c character to test
   12.72 + * @return 1 if c is in the class, 0 otherwise.
   12.73 + */
   12.74 +static inline int in_sep_class(int c){
   12.75 +    return in_class(c, sep_class);
   12.76 +}
   12.77 +
   12.78 +/** Determine if a character is in the alpha class.
   12.79 + * 
   12.80 + * @param c character to test
   12.81 + * @return 1 if c is in the class, 0 otherwise.
   12.82 + */
   12.83 +static inline int in_alpha_class(int c){
   12.84 +    return isalpha(c);
   12.85 +}
   12.86 +
   12.87 +/** Determine if a character is in the octal digit class.
   12.88 + * 
   12.89 + * @param c character to test
   12.90 + * @return 1 if c is in the class, 0 otherwise.
   12.91 + */
   12.92 +static inline int in_octal_digit_class(int c){
   12.93 +    return '0' <= c && c <= '7';
   12.94 +}
   12.95 +
   12.96 +/** Determine if a character is in the decimal digit class.
   12.97 + * 
   12.98 + * @param c character to test
   12.99 + * @return 1 if c is in the class, 0 otherwise.
  12.100 + */
  12.101 +static inline int in_decimal_digit_class(int c){
  12.102 +    return isdigit(c);
  12.103 +}
  12.104 +
  12.105 +/** Determine if a character is in the hex digit class.
  12.106 + * 
  12.107 + * @param c character to test
  12.108 + * @return 1 if c is in the class, 0 otherwise.
  12.109 + */
  12.110 +static inline int in_hex_digit_class(int c){
  12.111 +    return isdigit(c) || in_class(c, "abcdefABCDEF");
  12.112 +}
  12.113 +
  12.114 +
  12.115 +static inline int in_string_quote_class(int c){
  12.116 +    return in_class(c, "'\"");
  12.117 +}
  12.118 +
  12.119 +static inline int in_printable_class(int c){
  12.120 +    return ('A' <= c && c <= 'Z')
  12.121 +        || ('a' <= c && c <= 'z')
  12.122 +        || ('0' <= c && c <= '9')
  12.123 +        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
  12.124 +}
  12.125 +
  12.126 +extern int is_decimal_number(const char *s, int n);
  12.127 +extern int is_hex_number(const char *s, int n);
  12.128 +extern int is_keyword(const char *s, const char *k);
  12.129 +extern int is_keychar(const char *s, char c);
  12.130 +
  12.131 +#endif /* !_XUTIL_LEXIS_H_ */
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/tools/libxutil/socket_stream.c	Mon Nov 22 16:41:50 2004 +0000
    13.3 @@ -0,0 +1,230 @@
    13.4 +/*
    13.5 + * Copyright (C) 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 +/** @file
   13.23 + * An IOStream implementation using sockets.
   13.24 + */
   13.25 +#ifndef __KERNEL__
   13.26 +
   13.27 +#include <stdio.h>
   13.28 +#include <stdlib.h>
   13.29 +#include <string.h>
   13.30 +#include <unistd.h>
   13.31 +#include <errno.h>
   13.32 +#include "allocate.h"
   13.33 +#include "socket_stream.h"
   13.34 +
   13.35 +#define MODULE_NAME "sock"
   13.36 +#define DEBUG 0
   13.37 +//#undef DEBUG
   13.38 +#include "debug.h"
   13.39 +
   13.40 +static int socket_read(IOStream *s, void *buf, size_t n);
   13.41 +static int socket_write(IOStream *s, const void *buf, size_t n);
   13.42 +static int socket_error(IOStream *s);
   13.43 +static int socket_close(IOStream *s);
   13.44 +static void socket_free(IOStream *s);
   13.45 +static int socket_flush(IOStream *s);
   13.46 +
   13.47 +/** Methods used by a socket IOStream. */
   13.48 +static const IOMethods socket_methods = {
   13.49 +    read:  socket_read,
   13.50 +    write: socket_write,
   13.51 +    error: socket_error,
   13.52 +    close: socket_close,
   13.53 +    free:  socket_free,
   13.54 +    flush: socket_flush,
   13.55 +};
   13.56 +
   13.57 +/** Get the socket data.
   13.58 + * 
   13.59 + * @param io socket stream
   13.60 + * @return data
   13.61 + */
   13.62 +static inline SocketData * socket_data(IOStream *io){
   13.63 +    return (SocketData *)io->data;
   13.64 +}
   13.65 +
   13.66 +/** Test if a stream is a socket stream.
   13.67 + *
   13.68 + * @param io stream
   13.69 + * @return 0 if a socket stream, -EINVAL if not
   13.70 + */
   13.71 +int socket_stream_check(IOStream *io){
   13.72 +    return (io && io->methods == &socket_methods ? 0 : -EINVAL);
   13.73 +}
   13.74 +
   13.75 +/** Get the data for a socket stream.
   13.76 + *
   13.77 + * @param io stream
   13.78 + * @param data return value for the data
   13.79 + * @return 0 if a socket stream, -EINVAL if not
   13.80 + */
   13.81 +int socket_stream_data(IOStream *io, SocketData **data){
   13.82 +    int err = socket_stream_check(io);
   13.83 +    if(err){
   13.84 +        *data = NULL;
   13.85 +    } else {
   13.86 +        *data = socket_data(io);
   13.87 +    }
   13.88 +    return err;
   13.89 +}
   13.90 +
   13.91 +/** Set the destination address for a socket stream.
   13.92 + *
   13.93 + * @param io stream
   13.94 + * @param addr address
   13.95 + * @return 0 if a socket stream, -EINVAL if not
   13.96 + */
   13.97 +int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr){
   13.98 +    int err = 0;
   13.99 +    SocketData *data = NULL;
  13.100 +    err = socket_stream_data(io, &data);
  13.101 +    if(!err){
  13.102 +        data->daddr = *addr;
  13.103 +    }
  13.104 +    return err;
  13.105 +}
  13.106 +
  13.107 +/** Set the send flags for a socket stream.
  13.108 + *
  13.109 + * @param io stream
  13.110 + * @param flags flags
  13.111 + * @return 0 if a socket stream, -EINVAL if not
  13.112 + */
  13.113 +int socket_stream_set_flags(IOStream *io, int flags){
  13.114 +    int err = 0;
  13.115 +    SocketData *data = NULL;
  13.116 +    err = socket_stream_data(io, &data);
  13.117 +    if(!err){
  13.118 +        data->flags = flags;
  13.119 +    }
  13.120 +    return err;
  13.121 +}
  13.122 +
  13.123 +/** Write to the underlying socket using sendto.
  13.124 + *
  13.125 + * @param stream input
  13.126 + * @param buf where to put input
  13.127 + * @param n number of bytes to write
  13.128 + * @return number of bytes written
  13.129 + */
  13.130 +static int socket_write(IOStream *s, const void *buf, size_t n){
  13.131 +    SocketData *data = socket_data(s);
  13.132 +    struct sockaddr *daddr = (struct sockaddr *)&data->daddr;
  13.133 +    socklen_t daddr_n = sizeof(data->daddr);
  13.134 +    int k;
  13.135 +    dprintf("> sock=%d addr=%s:%d n=%d\n",
  13.136 +            data->fd, inet_ntoa(data->daddr.sin_addr), ntohs(data->daddr.sin_port), n);
  13.137 +    if(0){
  13.138 +        struct sockaddr_in self = {};
  13.139 +        socklen_t self_n;
  13.140 +        getsockname(data->fd, (struct sockaddr *)&self, &self_n);
  13.141 +        dprintf("> sockname sock=%d %s:%d\n",
  13.142 +                data->fd, inet_ntoa(self.sin_addr), ntohs(self.sin_port));
  13.143 +    }
  13.144 +    k = sendto(data->fd, buf, n, data->flags, daddr, daddr_n);
  13.145 +    dprintf("> sendto=%d\n", k);
  13.146 +    return k;
  13.147 +}
  13.148 +
  13.149 +/** Read from the underlying stream using recv();
  13.150 + *
  13.151 + * @param stream input
  13.152 + * @param buf where to put input
  13.153 + * @param n number of bytes to read
  13.154 + * @return number of bytes read
  13.155 + */
  13.156 +static int socket_read(IOStream *s, void *buf, size_t n){
  13.157 +    SocketData *data = socket_data(s);
  13.158 +    int k;
  13.159 +    struct sockaddr *saddr = (struct sockaddr *)&data->saddr;
  13.160 +    socklen_t saddr_n = sizeof(data->saddr);
  13.161 +    k = recvfrom(data->fd, buf, n, data->flags, saddr, &saddr_n);
  13.162 +    return k;
  13.163 +}
  13.164 +
  13.165 +/** Flush the socket (no-op).
  13.166 + *
  13.167 + * @param s socket stream
  13.168 + * @return 0 on success, error code otherwise
  13.169 + */
  13.170 +static int socket_flush(IOStream *s){
  13.171 +    return 0;
  13.172 +}
  13.173 +
  13.174 +/** Check if a socket stream has an error (no-op).
  13.175 + *
  13.176 + * @param s socket stream
  13.177 + * @return 1 if has an error, 0 otherwise
  13.178 + */
  13.179 +static int socket_error(IOStream *s){
  13.180 +    // Read SOL_SOCKET/SO_ERROR ?
  13.181 +    return 0;
  13.182 +}
  13.183 +
  13.184 +/** Close a socket stream.
  13.185 + *
  13.186 + * @param s socket stream to close
  13.187 + * @return result of the close
  13.188 + */
  13.189 +static int socket_close(IOStream *s){
  13.190 +    SocketData *data = socket_data(s);
  13.191 +    return close(data->fd);
  13.192 +}
  13.193 +
  13.194 +/** Free a socket stream.
  13.195 + *
  13.196 + * @param s socket stream
  13.197 + */
  13.198 +static void socket_free(IOStream *s){
  13.199 +    SocketData *data = socket_data(s);
  13.200 +    deallocate(data);
  13.201 +}
  13.202 +
  13.203 +/** Create an IOStream for a socket.
  13.204 + *
  13.205 + * @param fd socket to wtap
  13.206 + * @return new IOStream using fd for i/o
  13.207 + */
  13.208 +IOStream *socket_stream_new(int fd){
  13.209 +    int err = -ENOMEM;
  13.210 +    IOStream *io = NULL;
  13.211 +    SocketData *data = NULL;
  13.212 +
  13.213 +    io = ALLOCATE(IOStream);
  13.214 +    if(!io) goto exit;
  13.215 +    io->methods = &socket_methods;
  13.216 +    data = ALLOCATE(SocketData);
  13.217 +    if(!data) goto exit;
  13.218 +    io->data = data;
  13.219 +    data->fd = fd;
  13.220 +    data->buf_n = sizeof(data->buf);
  13.221 +    err = 0;
  13.222 +  exit:
  13.223 +    if(err){
  13.224 +        if(io){
  13.225 +            if(data) deallocate(data);
  13.226 +            deallocate(io);
  13.227 +            io = NULL;
  13.228 +        }
  13.229 +    }
  13.230 +    return io;
  13.231 +}
  13.232 +
  13.233 +#endif
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/tools/libxutil/socket_stream.h	Mon Nov 22 16:41:50 2004 +0000
    14.3 @@ -0,0 +1,53 @@
    14.4 +/*
    14.5 + * Copyright (C) 2004 Mike Wray <mike.wray@hp.com>
    14.6 + *
    14.7 + * This library is free software; you can redistribute it and/or modify
    14.8 + * it under the terms of the GNU Lesser General Public License as published by
    14.9 + * the Free Software Foundation; either version 2.1 of the License, or
   14.10 + * (at your option) any later version.
   14.11 + *
   14.12 + * This library is distributed in the hope that it will be useful,
   14.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.15 + * GNU Lesser General Public License for more details.
   14.16 + *
   14.17 + * You should have received a copy of the GNU Lesser General Public License
   14.18 + * along with this library; if not, write to the Free Software
   14.19 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   14.20 + */
   14.21 +
   14.22 +#ifndef _XEN_LIB_SOCKET_STREAM_H_
   14.23 +#define _XEN_LIB_SOCKET_STREAM_H_
   14.24 +
   14.25 +#ifndef __KERNEL__
   14.26 +#include "iostream.h"
   14.27 +#include <stdio.h>
   14.28 +
   14.29 +#include <sys/socket.h>
   14.30 +#include <netinet/in.h>
   14.31 +#include <arpa/inet.h>
   14.32 +
   14.33 +/** Data associated with a socket stream. */
   14.34 +typedef struct SocketData {
   14.35 +    /** The socket file descriptor. */
   14.36 +    int fd;
   14.37 +    /** Source address from last read (recvfrom). */
   14.38 +    struct sockaddr_in saddr;
   14.39 +    /** Destination address for writes (sendto). */
   14.40 +    struct sockaddr_in daddr;
   14.41 +    /** Write flags (sendto). */
   14.42 +    int flags;
   14.43 +    /** Buffer size. */
   14.44 +    int buf_n;
   14.45 +    /** Buffer for formatted printing. */
   14.46 +    char buf[1024];
   14.47 +} SocketData;
   14.48 +
   14.49 +extern IOStream *socket_stream_new(int fd);
   14.50 +extern int socket_stream_data(IOStream *io, SocketData **data);
   14.51 +extern int socket_stream_check(IOStream *io);
   14.52 +extern int socket_stream_set_addr(IOStream *io, struct sockaddr_in *addr);
   14.53 +extern int socket_stream_set_flags(IOStream *io, int flags);
   14.54 +
   14.55 +#endif
   14.56 +#endif /* !_XEN_LIB_SOCKET_STREAM_H_ */
    15.1 --- a/tools/libxutil/string_stream.c	Sun Nov 21 20:41:00 2004 +0000
    15.2 +++ b/tools/libxutil/string_stream.c	Mon Nov 22 16:41:50 2004 +0000
    15.3 @@ -1,5 +1,5 @@
    15.4  /*
    15.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    15.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    15.7   *
    15.8   * This library is free software; you can redistribute it and/or modify
    15.9   * it under the terms of the GNU Lesser General Public License as published by
    16.1 --- a/tools/libxutil/string_stream.h	Sun Nov 21 20:41:00 2004 +0000
    16.2 +++ b/tools/libxutil/string_stream.h	Mon Nov 22 16:41:50 2004 +0000
    16.3 @@ -1,5 +1,5 @@
    16.4  /*
    16.5 - * Copyright (C) 2001, 2002 Hewlett-Packard Company.
    16.6 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    16.7   *
    16.8   * This library is free software; you can redistribute it and/or modify
    16.9   * it under the terms of the GNU Lesser General Public License as published by
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/tools/libxutil/sxpr.c	Mon Nov 22 16:41:50 2004 +0000
    17.3 @@ -0,0 +1,956 @@
    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
    17.9 + * published by the Free Software Foundation; either version 2.1 of the
   17.10 + * License, or  (at your option) any later version. This library is 
   17.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   17.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   17.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   17.14 + * See the GNU Lesser General Public License for more details.
   17.15 + *
   17.16 + * You should have received a copy of the GNU Lesser General Public License
   17.17 + * along with this library; if not, write to the Free Software Foundation,
   17.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   17.19 + */
   17.20 +
   17.21 +#include <stdarg.h>
   17.22 +#include "sys_string.h"
   17.23 +#include "lexis.h"
   17.24 +#include "sys_net.h"
   17.25 +#include "hash_table.h"
   17.26 +#include "sxpr.h"
   17.27 +
   17.28 +#ifdef __KERNEL__
   17.29 +#include <linux/errno.h>
   17.30 +#else
   17.31 +#include <errno.h>
   17.32 +#endif
   17.33 +
   17.34 +#undef free
   17.35 +
   17.36 +/** @file
   17.37 + * General representation of sxprs.
   17.38 + * Includes print, equal, and free functions for the sxpr types.
   17.39 + *
   17.40 + * Zero memory containing an Sxpr will have the value ONONE - this is intentional.
   17.41 + * When a function returning an sxpr cannot allocate memory we return ONOMEM.
   17.42 + *
   17.43 + */
   17.44 +
   17.45 +static int atom_print(IOStream *io, Sxpr obj, unsigned flags);
   17.46 +static int atom_equal(Sxpr x, Sxpr y);
   17.47 +static void atom_free(Sxpr obj);
   17.48 +
   17.49 +static int string_print(IOStream *io, Sxpr obj, unsigned flags);
   17.50 +static int string_equal(Sxpr x, Sxpr y);
   17.51 +static void string_free(Sxpr obj);
   17.52 +
   17.53 +static int cons_print(IOStream *io, Sxpr obj, unsigned flags);
   17.54 +static int cons_equal(Sxpr x, Sxpr y);
   17.55 +static void cons_free(Sxpr obj);
   17.56 +
   17.57 +static int null_print(IOStream *io, Sxpr obj, unsigned flags);
   17.58 +static int none_print(IOStream *io, Sxpr obj, unsigned flags);
   17.59 +static int int_print(IOStream *io, Sxpr obj, unsigned flags);
   17.60 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags);
   17.61 +
   17.62 +/** Type definitions. */
   17.63 +static SxprType types[1024] = {
   17.64 +    [T_NONE]     { type:    T_NONE,     name: "none",       print: none_print      },
   17.65 +    [T_NULL]     { type:    T_NULL,     name: "null",       print: null_print      },
   17.66 +    [T_UINT]     { type:    T_UINT,     name: "int",        print: int_print,      },
   17.67 +    [T_BOOL]     { type:    T_BOOL,     name: "bool",       print: bool_print,     },
   17.68 +    [T_ATOM]     { type:    T_ATOM,     name: "atom",       print: atom_print,
   17.69 +		   pointer: TRUE,
   17.70 +		   free:    atom_free,
   17.71 +		   equal:   atom_equal,
   17.72 +		 },
   17.73 +    [T_STRING]   { type:    T_STRING,   name: "string",     print: string_print,
   17.74 +		   pointer: TRUE,
   17.75 +		   free:    string_free,
   17.76 +		   equal:   string_equal,
   17.77 +		 },
   17.78 +    [T_CONS]     { type:    T_CONS,     name: "cons",       print: cons_print,
   17.79 +		   pointer: TRUE,
   17.80 +		   free:    cons_free,
   17.81 +		   equal:   cons_equal,
   17.82 +		 },
   17.83 +};
   17.84 +
   17.85 +/** Number of entries in the types array. */
   17.86 +static int type_sup = sizeof(types)/sizeof(types[0]);
   17.87 +
   17.88 +/** Get the type definition for a given type code.
   17.89 + *
   17.90 + * @param ty type code
   17.91 + * @return type definition or null
   17.92 + */
   17.93 +SxprType *get_sxpr_type(int ty){
   17.94 +    if(0 <= ty && ty < type_sup){
   17.95 +        return types+ty;
   17.96 +    }
   17.97 +    return NULL;
   17.98 +}
   17.99 +
  17.100 +/** The default print function.
  17.101 + *
  17.102 + * @param io stream to print to
  17.103 + * @param x sxpr to print
  17.104 + * @param flags print flags
  17.105 + * @return number of bytes written on success
  17.106 + */
  17.107 +int default_print(IOStream *io, Sxpr x, unsigned flags){
  17.108 +    return IOStream_print(io, "#<%u %lu>\n", get_type(x), get_ul(x));
  17.109 +}
  17.110 +
  17.111 +/** The default equal function.
  17.112 + * Uses eq().
  17.113 + *
  17.114 + * @param x sxpr to compare
  17.115 + * @param y sxpr to compare
  17.116 + * @return 1 if equal, 0 otherwise
  17.117 + */
  17.118 +int default_equal(Sxpr x, Sxpr y){
  17.119 +    return eq(x, y);
  17.120 +}
  17.121 +
  17.122 +/** General sxpr print function.
  17.123 + * Prints an sxpr on a stream using the print function for the sxpr type.
  17.124 + * Printing is controlled by flags from the PrintFlags enum.
  17.125 + * If PRINT_TYPE is in the flags the sxpr type is printed before the sxpr
  17.126 + * (for debugging).
  17.127 + *
  17.128 + * @param io stream to print to
  17.129 + * @param x sxpr to print
  17.130 + * @param flags print flags
  17.131 + * @return number of bytes written
  17.132 + */
  17.133 +int objprint(IOStream *io, Sxpr x, unsigned flags){
  17.134 +    SxprType *def = get_sxpr_type(get_type(x));
  17.135 +    ObjPrintFn *print_fn = (def && def->print ? def->print : default_print);
  17.136 +    int k = 0;
  17.137 +    if(!io) return k;
  17.138 +    if(flags & PRINT_TYPE){
  17.139 +	k += IOStream_print(io, "%s:", def->name);
  17.140 +    }
  17.141 +    k += print_fn(io, x, flags);
  17.142 +    return k;
  17.143 +}
  17.144 +
  17.145 +/** General sxpr free function.
  17.146 + * Frees an sxpr using the free function for its type.
  17.147 + * Free functions must recursively free any subsxprs.
  17.148 + * If no function is defined then the default is to
  17.149 + * free sxprs whose type has pointer true.
  17.150 + * Sxprs must not be used after freeing.
  17.151 + *
  17.152 + * @param x sxpr to free
  17.153 + */
  17.154 +void objfree(Sxpr x){
  17.155 +    SxprType *def = get_sxpr_type(get_type(x));
  17.156 +
  17.157 +    if(def){
  17.158 +	if(def->free){
  17.159 +	    def->free(x);
  17.160 +	} else if (def->pointer){
  17.161 +	    hfree(x);
  17.162 +	}
  17.163 +    }
  17.164 +}
  17.165 +
  17.166 +/** General sxpr equality function.
  17.167 + * Compares x and y using the equal function for x.
  17.168 + * Uses default_equal() if x has no equal function.
  17.169 + *
  17.170 + * @param x sxpr to compare
  17.171 + * @param y sxpr to compare
  17.172 + * @return 1 if equal, 0 otherwise
  17.173 + */
  17.174 +int objequal(Sxpr x, Sxpr y){
  17.175 +    SxprType *def = get_sxpr_type(get_type(x));
  17.176 +    ObjEqualFn *equal_fn = (def && def->equal ? def->equal : default_equal);
  17.177 +    return equal_fn(x, y);
  17.178 +}
  17.179 +
  17.180 +/** Search for a key in an alist.
  17.181 + * An alist is a list of conses, where the cars
  17.182 + * of the conses are the keys. Compares keys using equality.
  17.183 + *
  17.184 + * @param k key
  17.185 + * @param l alist to search
  17.186 + * @return first element of l with car k, or ONULL
  17.187 + */
  17.188 +Sxpr assoc(Sxpr k, Sxpr l){
  17.189 +    for( ; CONSP(l) ; l = CDR(l)){
  17.190 +        Sxpr x = CAR(l);
  17.191 +        if(CONSP(x) && objequal(k, CAR(x))){
  17.192 +            return x;   
  17.193 +        }
  17.194 +    }
  17.195 +    return ONULL;
  17.196 +}
  17.197 +
  17.198 +/** Search for a key in an alist.
  17.199 + * An alist is a list of conses, where the cars
  17.200 + * of the conses are the keys. Compares keys using eq.
  17.201 + *
  17.202 + * @param k key
  17.203 + * @param l alist to search
  17.204 + * @return first element of l with car k, or ONULL
  17.205 + */
  17.206 +Sxpr assocq(Sxpr k, Sxpr l){
  17.207 +    for( ; CONSP(l); l = CDR(l)){
  17.208 +        Sxpr x = CAR(l);
  17.209 +        if(CONSP(x) && eq(k, CAR(x))){
  17.210 +            return x;
  17.211 +        }
  17.212 +    }
  17.213 +    return ONULL;
  17.214 +}
  17.215 +
  17.216 +/** Add a new key and value to an alist.
  17.217 + *
  17.218 + * @param k key
  17.219 + * @param l value
  17.220 + * @param l alist
  17.221 + * @return l with the new cell added to the front
  17.222 + */
  17.223 +Sxpr acons(Sxpr k, Sxpr v, Sxpr l){
  17.224 +    Sxpr x, y;
  17.225 +    x = cons_new(k, v);
  17.226 +    if(NOMEMP(x)) return x;
  17.227 +    y = cons_new(x, l);
  17.228 +    if(NOMEMP(y)) cons_free_cells(x);
  17.229 +    return y;
  17.230 +}
  17.231 +
  17.232 +/** Test if a list contains an element.
  17.233 + * Uses sxpr equality.
  17.234 + *
  17.235 + * @param l list
  17.236 + * @param x element to look for
  17.237 + * @return a tail of l with x as car, or ONULL
  17.238 + */
  17.239 +Sxpr cons_member(Sxpr l, Sxpr x){
  17.240 +    for( ; CONSP(l) && !eq(x, CAR(l)); l = CDR(l)){}
  17.241 +    return l;
  17.242 +}
  17.243 +
  17.244 +/** Test if a list contains an element satisfying a test.
  17.245 + * The test function is called with v and an element of the list.
  17.246 + *
  17.247 + * @param l list
  17.248 + * @param test_fn test function to use
  17.249 + * @param v value for first argument to the test
  17.250 + * @return a tail of l with car satisfying the test, or 0
  17.251 + */
  17.252 +Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  17.253 +    for( ; CONSP(l) && !test_fn(v, CAR(l)); l = CDR(l)){ }
  17.254 +    return l;
  17.255 +}
  17.256 +
  17.257 +/** Test if the elements of list 't' are a subset of the elements
  17.258 + * of list 's'. Element order is not significant.
  17.259 + *
  17.260 + * @param s element list to check subset of
  17.261 + * @param t element list to check if is a subset
  17.262 + * @return 1 if is a subset, 0 otherwise
  17.263 + */
  17.264 +int cons_subset(Sxpr s, Sxpr t){
  17.265 +    for( ; CONSP(t); t = CDR(t)){
  17.266 +	if(!CONSP(cons_member(s, CAR(t)))){
  17.267 +	    return 0;
  17.268 +	}
  17.269 +    }
  17.270 +    return 1;
  17.271 +}
  17.272 +
  17.273 +/** Test if two lists have equal sets of elements.
  17.274 + * Element order is not significant.
  17.275 + *
  17.276 + * @param s list to check
  17.277 + * @param t list to check
  17.278 + * @return 1 if equal, 0 otherwise
  17.279 + */
  17.280 +int cons_set_equal(Sxpr s, Sxpr t){
  17.281 +    return cons_subset(s, t) && cons_subset(t, s);
  17.282 +}
  17.283 +
  17.284 +#ifdef USE_GC
  17.285 +/*============================================================================*/
  17.286 +/* The functions inside this ifdef are only safe if GC is used.
  17.287 + * Otherwise they may leak memory.
  17.288 + */
  17.289 +
  17.290 +/** Remove an element from a list (GC only).
  17.291 + * Uses sxpr equality and removes all instances, even
  17.292 + * if there are more than one.
  17.293 + *
  17.294 + * @param l list to remove elements from
  17.295 + * @param x element to remove
  17.296 + * @return modified input list
  17.297 + */
  17.298 +Sxpr cons_remove(Sxpr l, Sxpr x){
  17.299 +    return cons_remove_if(l, eq, x);
  17.300 +}
  17.301 +
  17.302 +/** Remove elements satisfying a test (GC only).
  17.303 + * The test function is called with v and an element of the set.
  17.304 + *
  17.305 + * @param l list to remove elements from
  17.306 + * @param test_fn function to use to decide if an element should be removed
  17.307 + * @return modified input list
  17.308 + */
  17.309 +Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v){
  17.310 +    Sxpr prev = ONULL, elt, next;
  17.311 +
  17.312 +    for(elt = l; CONSP(elt); elt = next){
  17.313 +        next = CDR(elt);
  17.314 +        if(test_fn(v, CAR(elt))){
  17.315 +            if(NULLP(prev)){
  17.316 +                l = next;
  17.317 +            } else {
  17.318 +                CDR(prev) = next;
  17.319 +            }
  17.320 +        }
  17.321 +    }
  17.322 +    return l;
  17.323 +}
  17.324 +
  17.325 +/** Set the value for a key in an alist (GC only).
  17.326 + * If the key is present, changes the value, otherwise
  17.327 + * adds a new cell.
  17.328 + *
  17.329 + * @param k key
  17.330 + * @param v value
  17.331 + * @param l alist
  17.332 + * @return modified or extended list
  17.333 + */
  17.334 +Sxpr setf(Sxpr k, Sxpr v, Sxpr l){
  17.335 +    Sxpr e = assoc(k, l);
  17.336 +    if(NULLP(e)){
  17.337 +        l = acons(k, v, l);
  17.338 +    } else {
  17.339 +        CAR(CDR(e)) = v;
  17.340 +    }
  17.341 +    return l;
  17.342 +}
  17.343 +/*============================================================================*/
  17.344 +#endif /* USE_GC */
  17.345 +
  17.346 +/** Create a new atom with the given name.
  17.347 + *
  17.348 + * @param name the name
  17.349 + * @return new atom
  17.350 + */
  17.351 +Sxpr atom_new(char *name){
  17.352 +    Sxpr n, obj = ONOMEM;
  17.353 +
  17.354 +    n = string_new(name);
  17.355 +    if(NOMEMP(n)) goto exit;
  17.356 +    obj = HALLOC(ObjAtom, T_ATOM);
  17.357 +    if(NOMEMP(obj)) goto exit;
  17.358 +    OBJ_ATOM(obj)->name = n;
  17.359 +  exit:
  17.360 +    return obj;
  17.361 +}
  17.362 +
  17.363 +/** Free an atom.
  17.364 + *
  17.365 + * @param obj to free
  17.366 + */
  17.367 +void atom_free(Sxpr obj){
  17.368 +    // Interned atoms are shared, so do not free.
  17.369 +    if(OBJ_ATOM(obj)->interned) return;
  17.370 +    objfree(OBJ_ATOM(obj)->name);
  17.371 +    hfree(obj);
  17.372 +}
  17.373 +
  17.374 +/** Print an atom. Prints the atom name.
  17.375 + *
  17.376 + * @param io stream to print to
  17.377 + * @param obj to print
  17.378 + * @param flags print flags
  17.379 + * @return number of bytes printed
  17.380 + */
  17.381 +int atom_print(IOStream *io, Sxpr obj, unsigned flags){
  17.382 +    //return string_print(io, OBJ_ATOM(obj)->name, (flags | PRINT_RAW));
  17.383 +    return string_print(io, OBJ_ATOM(obj)->name, flags);
  17.384 +}
  17.385 +
  17.386 +/** Atom equality.
  17.387 + *
  17.388 + * @param x to compare
  17.389 + * @param y to compare
  17.390 + * @return 1 if equal, 0 otherwise
  17.391 + */
  17.392 +int atom_equal(Sxpr x, Sxpr y){
  17.393 +    int ok;
  17.394 +    ok = eq(x, y);
  17.395 +    if(ok) goto exit;
  17.396 +    ok = ATOMP(y) && string_equal(OBJ_ATOM(x)->name, OBJ_ATOM(y)->name);
  17.397 +    if(ok) goto exit;
  17.398 +    ok = STRINGP(y) && string_equal(OBJ_ATOM(x)->name, y);
  17.399 +  exit:
  17.400 +    return ok;
  17.401 +}
  17.402 +
  17.403 +/** Get the name of an atom.
  17.404 + *
  17.405 + * @param obj atom
  17.406 + * @return name
  17.407 + */
  17.408 +char * atom_name(Sxpr obj){
  17.409 +    return string_string(OBJ_ATOM(obj)->name);
  17.410 +}
  17.411 +
  17.412 +/** Get the C string from a string sxpr.
  17.413 + *
  17.414 + * @param obj string sxpr
  17.415 + * @return string
  17.416 + */
  17.417 +char * string_string(Sxpr obj){
  17.418 +    return OBJ_STRING(obj);
  17.419 +}
  17.420 +
  17.421 +/** Get the length of a string.
  17.422 + *
  17.423 + * @param obj string
  17.424 + * @return length
  17.425 + */
  17.426 +int string_length(Sxpr obj){
  17.427 +    return strlen(OBJ_STRING(obj));
  17.428 +}
  17.429 +
  17.430 +/** Create a new string. The input string is copied,
  17.431 + * and must be null-terminated.
  17.432 + *
  17.433 + * @param s characters to put in the string
  17.434 + * @return new sxpr
  17.435 + */
  17.436 +Sxpr string_new(char *s){
  17.437 +    int n = (s ? strlen(s) : 0);
  17.438 +    Sxpr obj;
  17.439 +    obj = halloc(n+1, T_STRING);
  17.440 +    if(!NOMEMP(obj)){
  17.441 +        char *str = OBJ_STRING(obj);
  17.442 +        strncpy(str, s, n);
  17.443 +        str[n] = '\0';
  17.444 +    }
  17.445 +    return obj;
  17.446 +}
  17.447 +
  17.448 +/** Free a string.
  17.449 + *
  17.450 + * @param obj to free
  17.451 + */
  17.452 +void string_free(Sxpr obj){
  17.453 +    hfree(obj);
  17.454 +}
  17.455 +
  17.456 +/** Determine if a string needs escapes when printed
  17.457 + * using the given flags.
  17.458 + *
  17.459 + * @param str string to check
  17.460 + * @param flags print flags
  17.461 + * @return 1 if needs escapes, 0 otherwise
  17.462 + */
  17.463 +int needs_escapes(char *str, unsigned flags){
  17.464 +    char *c;
  17.465 +    int val = 0;
  17.466 +
  17.467 +    if(str){
  17.468 +	for(c=str; *c; c++){
  17.469 +	    if(in_alpha_class(*c)) continue;
  17.470 +	    if(in_decimal_digit_class(*c)) continue;
  17.471 +	    if(in_class(*c, "/._+:@~-")) continue;
  17.472 +	    val = 1;
  17.473 +	    break;
  17.474 +	}
  17.475 +    }
  17.476 +    //printf("\n> val=%d str=|%s|\n", val, str);
  17.477 +    return val;
  17.478 +}
  17.479 +
  17.480 +/** Print a string to a stream, with escapes if necessary.
  17.481 + *
  17.482 + * @param io stream to print to
  17.483 + * @param str string
  17.484 + * @param flags print flags
  17.485 + * @return number of bytes written
  17.486 + */
  17.487 +int _string_print(IOStream *io, char *str, unsigned flags){
  17.488 +    int k = 0;
  17.489 +    if((flags & PRINT_RAW) || !needs_escapes(str, flags)){
  17.490 +        k += IOStream_print(io, str);
  17.491 +    } else {
  17.492 +	k += IOStream_print(io, "\"");
  17.493 +	if(str){
  17.494 +            char *s;
  17.495 +            for(s = str; *s; s++){
  17.496 +                if(*s < ' ' || *s >= 127 ){
  17.497 +                    switch(*s){
  17.498 +                    case '\a': k += IOStream_print(io, "\\a");  break;
  17.499 +                    case '\b': k += IOStream_print(io, "\\b");  break;
  17.500 +                    case '\f': k += IOStream_print(io, "\\f");  break;
  17.501 +                    case '\n': k += IOStream_print(io, "\\n");  break;
  17.502 +                    case '\r': k += IOStream_print(io, "\\r");  break;
  17.503 +                    case '\t': k += IOStream_print(io, "\\t");  break;
  17.504 +                    case '\v': k += IOStream_print(io, "\\v");  break;
  17.505 +                    default:
  17.506 +                        // Octal escape;
  17.507 +                        k += IOStream_print(io, "\\%o", *s);
  17.508 +                        break;
  17.509 +                    }
  17.510 +                } else if(*s == c_double_quote ||
  17.511 +                          *s == c_single_quote ||
  17.512 +                          *s == c_escape){
  17.513 +                    k += IOStream_print(io, "\\%c", *s);
  17.514 +                } else {
  17.515 +                    k+= IOStream_print(io, "%c", *s);
  17.516 +                }
  17.517 +            }
  17.518 +	}
  17.519 +	k += IOStream_print(io, "\"");
  17.520 +    }
  17.521 +    return k;
  17.522 +}
  17.523 +
  17.524 +/** Print a string to a stream, with escapes if necessary.
  17.525 + *
  17.526 + * @param io stream to print to
  17.527 + * @param obj string
  17.528 + * @param flags print flags
  17.529 + * @return number of bytes written
  17.530 + */
  17.531 +int string_print(IOStream *io, Sxpr obj, unsigned flags){
  17.532 +    return _string_print(io, OBJ_STRING(obj), flags);
  17.533 +}
  17.534 +
  17.535 +/** Compare an sxpr with a string for equality.
  17.536 + *
  17.537 + * @param x string to compare with
  17.538 + * @param y sxpr to compare
  17.539 + * @return 1 if equal, 0 otherwise
  17.540 + */
  17.541 +int string_equal(Sxpr x, Sxpr y){
  17.542 +    int ok = 0;
  17.543 +    ok = eq(x,y);
  17.544 +    if(ok) goto exit;
  17.545 +    ok = has_type(y, T_STRING) && !strcmp(OBJ_STRING(x), OBJ_STRING(y));
  17.546 +    if(ok) goto exit;
  17.547 +    ok = has_type(y, T_ATOM) && !strcmp(OBJ_STRING(x), atom_name(y));
  17.548 +  exit:
  17.549 +    return ok;
  17.550 +}
  17.551 +
  17.552 +/** Create a new cons cell.
  17.553 + * The cell is ONOMEM if either argument is.
  17.554 + *
  17.555 + * @param car sxpr for the car
  17.556 + * @param cdr sxpr for the cdr
  17.557 + * @return new cons
  17.558 + */
  17.559 +Sxpr cons_new(Sxpr car, Sxpr cdr){
  17.560 +    Sxpr obj;
  17.561 +    if(NOMEMP(car) || NOMEMP(cdr)){
  17.562 +        obj = ONOMEM;
  17.563 +    } else {
  17.564 +        obj = HALLOC(ObjCons, T_CONS);
  17.565 +        if(!NOMEMP(obj)){
  17.566 +            ObjCons *z = OBJ_CONS(obj);
  17.567 +            z->car = car;
  17.568 +            z->cdr = cdr;
  17.569 +        }
  17.570 +    }
  17.571 +    return obj;
  17.572 +}
  17.573 +
  17.574 +/** Push a new element onto a list.
  17.575 + *
  17.576 + * @param list list to add to
  17.577 + * @param elt element to add
  17.578 + * @return 0 if successful, error code otherwise
  17.579 + */
  17.580 +int cons_push(Sxpr *list, Sxpr elt){
  17.581 +    Sxpr l;
  17.582 +    l = cons_new(elt, *list);
  17.583 +    if(NOMEMP(l)) return -ENOMEM;
  17.584 +    *list = l;
  17.585 +    return 0;
  17.586 +}
  17.587 +
  17.588 +/** Free a cons. Recursively frees the car and cdr.
  17.589 + *
  17.590 + * @param obj to free
  17.591 + */
  17.592 +void cons_free(Sxpr obj){
  17.593 +    Sxpr next;
  17.594 +    for(; CONSP(obj); obj = next){
  17.595 +	next = CDR(obj);
  17.596 +	objfree(CAR(obj));
  17.597 +	hfree(obj);
  17.598 +    }
  17.599 +    if(!NULLP(obj)){
  17.600 +	objfree(obj);
  17.601 +    }
  17.602 +}
  17.603 +
  17.604 +/** Free a cons and its cdr cells, but not the car sxprs.
  17.605 + * Does nothing if called on something that is not a cons.
  17.606 + *
  17.607 + * @param obj to free
  17.608 + */
  17.609 +void cons_free_cells(Sxpr obj){
  17.610 +    Sxpr next;
  17.611 +    for(; CONSP(obj); obj = next){
  17.612 +	next = CDR(obj);
  17.613 +	hfree(obj);
  17.614 +    }
  17.615 +}
  17.616 +
  17.617 +/** Print a cons.
  17.618 + * Prints the cons in list format if the cdrs are conses.
  17.619 + * uses pair (dot) format if the last cdr is not a cons (or null).
  17.620 + *
  17.621 + * @param io stream to print to
  17.622 + * @param obj to print
  17.623 + * @param flags print flags
  17.624 + * @return number of bytes written
  17.625 + */
  17.626 +int cons_print(IOStream *io, Sxpr obj, unsigned flags){
  17.627 +    int first = 1;
  17.628 +    int k = 0;
  17.629 +    k += IOStream_print(io, "(");
  17.630 +    for( ; CONSP(obj) ; obj = CDR(obj)){
  17.631 +        if(first){ 
  17.632 +            first = 0;
  17.633 +        } else {
  17.634 +            k += IOStream_print(io, " ");
  17.635 +        }
  17.636 +        k += objprint(io, CAR(obj), flags);
  17.637 +    }
  17.638 +    if(!NULLP(obj)){
  17.639 +        k += IOStream_print(io, " . ");
  17.640 +        k += objprint(io, obj, flags);
  17.641 +    }
  17.642 +    k += IOStream_print(io, ")");
  17.643 +    return (IOStream_error(io) ? -1 : k);
  17.644 +}
  17.645 +
  17.646 +/** Compare a cons with another sxpr for equality.
  17.647 + * If y is a cons, compares the cars and cdrs recursively.
  17.648 + *
  17.649 + * @param x cons to compare
  17.650 + * @param y sxpr to compare
  17.651 + * @return 1 if equal, 0 otherwise
  17.652 + */
  17.653 +int cons_equal(Sxpr x, Sxpr y){
  17.654 +    return CONSP(y) &&
  17.655 +        objequal(CAR(x), CAR(y)) &&
  17.656 +        objequal(CDR(x), CDR(y));
  17.657 +}
  17.658 +
  17.659 +/** Return the length of a cons list.
  17.660 + *
  17.661 + * @param obj list
  17.662 + * @return length
  17.663 + */
  17.664 +int cons_length(Sxpr obj){
  17.665 +    int count = 0;
  17.666 +    for( ; CONSP(obj); obj = CDR(obj)){
  17.667 +        count++;
  17.668 +    }
  17.669 +    return count;
  17.670 +}
  17.671 +
  17.672 +/** Destructively reverse a cons list in-place.
  17.673 + * If the argument is not a cons it is returned unchanged.
  17.674 + * 
  17.675 + * @param l to reverse
  17.676 + * @return reversed list
  17.677 + */
  17.678 +Sxpr nrev(Sxpr l){
  17.679 +    if(CONSP(l)){
  17.680 +	// Iterate down the cells in the list making the cdr of
  17.681 +	// each cell point to the previous cell. The last cell 
  17.682 +	// is the head of the reversed list.
  17.683 +	Sxpr prev = ONULL;
  17.684 +	Sxpr cell = l;
  17.685 +	Sxpr next;
  17.686 +
  17.687 +	while(1){
  17.688 +	    next = CDR(cell);
  17.689 +	    CDR(cell) = prev;
  17.690 +	    if(!CONSP(next)) break;
  17.691 +	    prev = cell;
  17.692 +	    cell = next;
  17.693 +	}
  17.694 +	l = cell;
  17.695 +    }
  17.696 +    return l;
  17.697 +}
  17.698 +
  17.699 +/** Print the null sxpr.	
  17.700 + *
  17.701 + * @param io stream to print to
  17.702 + * @param obj to print
  17.703 + * @param flags print flags
  17.704 + * @return number of bytes written
  17.705 + */
  17.706 +static int null_print(IOStream *io, Sxpr obj, unsigned flags){
  17.707 +    return IOStream_print(io, "()");
  17.708 +}
  17.709 +
  17.710 +/** Print the `unspecified' sxpr none.
  17.711 + *
  17.712 + * @param io stream to print to
  17.713 + * @param obj to print
  17.714 + * @param flags print flags
  17.715 + * @return number of bytes written
  17.716 + */
  17.717 +static int none_print(IOStream *io, Sxpr obj, unsigned flags){
  17.718 +    return IOStream_print(io, "<none>");
  17.719 +}
  17.720 +
  17.721 +/** Print an integer.
  17.722 + *
  17.723 + * @param io stream to print to
  17.724 + * @param obj to print
  17.725 + * @param flags print flags
  17.726 + * @return number of bytes written
  17.727 + */
  17.728 +static int int_print(IOStream *io, Sxpr obj, unsigned flags){
  17.729 +    return IOStream_print(io, "%d", OBJ_INT(obj));
  17.730 +}
  17.731 +
  17.732 +/** Print a boolean.
  17.733 + *
  17.734 + * @param io stream to print to
  17.735 + * @param obj to print
  17.736 + * @param flags print flags
  17.737 + * @return number of bytes written
  17.738 + */
  17.739 +static int bool_print(IOStream *io, Sxpr obj, unsigned flags){
  17.740 +    return IOStream_print(io, (OBJ_UINT(obj) ? k_true : k_false));
  17.741 +}
  17.742 +
  17.743 +int sxprp(Sxpr obj, Sxpr name){
  17.744 +    return CONSP(obj) && objequal(CAR(obj), name);
  17.745 +}
  17.746 +
  17.747 +/** Get the name of an element.
  17.748 + * 
  17.749 + * @param obj element
  17.750 + * @return name
  17.751 + */
  17.752 +Sxpr sxpr_name(Sxpr obj){
  17.753 +    Sxpr val = ONONE;
  17.754 +    if(CONSP(obj)){
  17.755 +        val = CAR(obj);
  17.756 +    } else if(STRINGP(obj) || ATOMP(obj)){
  17.757 +        val = obj;
  17.758 +    }
  17.759 +    return val;
  17.760 +}
  17.761 +
  17.762 +int sxpr_is(Sxpr obj, char *s){
  17.763 +    if(ATOMP(obj)) return !strcmp(atom_name(obj), s);
  17.764 +    if(STRINGP(obj)) return !strcmp(string_string(obj), s);
  17.765 +    return 0;
  17.766 +}
  17.767 +
  17.768 +int sxpr_elementp(Sxpr obj, Sxpr name){
  17.769 +    int ok = 0;
  17.770 +    ok = CONSP(obj) && objequal(CAR(obj), name);
  17.771 +    return ok;
  17.772 +}
  17.773 +
  17.774 +/** Get the attributes of an sxpr.
  17.775 + * 
  17.776 + * @param obj sxpr
  17.777 + * @return attributes
  17.778 + */
  17.779 +Sxpr sxpr_attributes(Sxpr obj){
  17.780 +    Sxpr val = ONULL;
  17.781 +    if(CONSP(obj)){
  17.782 +        obj = CDR(obj);
  17.783 +        if(CONSP(obj)){
  17.784 +            obj = CAR(obj);
  17.785 +            if(sxprp(obj, intern("@"))){
  17.786 +                val = CDR(obj);
  17.787 +            }
  17.788 +        }
  17.789 +    }
  17.790 +    return val;
  17.791 +}
  17.792 +
  17.793 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
  17.794 +    Sxpr val = ONONE;
  17.795 +    val = assoc(sxpr_attributes(obj), key);
  17.796 +    if(CONSP(val) && CONSP(CDR(val))){
  17.797 +        val = CADR(def);
  17.798 +    } else {
  17.799 +        val = def;
  17.800 +    }
  17.801 +    return val;
  17.802 +}
  17.803 +
  17.804 +/** Get the children of an sxpr.
  17.805 + * 
  17.806 + * @param obj sxpr
  17.807 + * @return children
  17.808 + */
  17.809 +Sxpr sxpr_children(Sxpr obj){
  17.810 +    Sxpr val = ONULL;
  17.811 +    if(CONSP(obj)){
  17.812 +        val = CDR(obj);
  17.813 +        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
  17.814 +            val = CDR(val);
  17.815 +        }
  17.816 +    }
  17.817 +    return val;
  17.818 +}
  17.819 +
  17.820 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
  17.821 +    Sxpr val = ONONE;
  17.822 +    Sxpr l;
  17.823 +    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
  17.824 +        if(sxprp(CAR(l), name)){
  17.825 +            val = CAR(l);
  17.826 +            break;
  17.827 +        }
  17.828 +    }
  17.829 +    if(NONEP(val)) val = def;
  17.830 +    return val;
  17.831 +}
  17.832 +
  17.833 +Sxpr sxpr_child0(Sxpr obj, Sxpr def){
  17.834 +    Sxpr val = ONONE;
  17.835 +    Sxpr l = sxpr_children(obj);
  17.836 +    if(CONSP(l)){
  17.837 +        val = CAR(l);
  17.838 +    } else {
  17.839 +        val = def;
  17.840 +    }
  17.841 +    return val;
  17.842 +}
  17.843 +
  17.844 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){
  17.845 +    Sxpr val = def;
  17.846 +    Sxpr l;
  17.847 +    int i;
  17.848 +    for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){
  17.849 +        if(i == n){
  17.850 +            val = CAR(l);
  17.851 +            break;
  17.852 +        }
  17.853 +    }
  17.854 +    return val;
  17.855 +}
  17.856 +    
  17.857 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
  17.858 +    Sxpr val = ONONE;
  17.859 +    val = sxpr_child(obj, name, ONONE);
  17.860 +    if(NONEP(val)){
  17.861 +        val = def;
  17.862 +    } else {
  17.863 +        val = sxpr_child0(val, def);
  17.864 +    }
  17.865 +    return val;
  17.866 +}
  17.867 +
  17.868 +/** Table of interned symbols. Indexed by symbol name. */
  17.869 +static HashTable *symbols = NULL;
  17.870 +
  17.871 +/** Hash function for entries in the symbol table.
  17.872 + *
  17.873 + * @param key to hash
  17.874 + * @return hashcode
  17.875 + */
  17.876 +static Hashcode sym_hash_fn(void *key){
  17.877 +    return hash_string((char*)key);
  17.878 +}
  17.879 +
  17.880 +/** Key equality function for the symbol table.
  17.881 + *
  17.882 + * @param x to compare
  17.883 + * @param y to compare
  17.884 + * @return 1 if equal, 0 otherwise
  17.885 + */
  17.886 +static int sym_equal_fn(void *x, void *y){
  17.887 +    return !strcmp((char*)x, (char*)y);
  17.888 +}
  17.889 +
  17.890 +/** Entry free function for the symbol table.
  17.891 + *
  17.892 + * @param table the entry is in
  17.893 + * @param entry being freed
  17.894 + */
  17.895 +static void sym_free_fn(HashTable *table, HTEntry *entry){
  17.896 +    if(entry){
  17.897 +	objfree(((ObjAtom*)entry->value)->name);
  17.898 +	HTEntry_free(entry);
  17.899 +    }
  17.900 +}
  17.901 +	
  17.902 +/** Initialize the symbol table.
  17.903 + *
  17.904 + * @return 0 on sucess, error code otherwise
  17.905 + */
  17.906 +static int init_symbols(void){
  17.907 +    symbols = HashTable_new(100);
  17.908 +    if(symbols){
  17.909 +        symbols->key_hash_fn = sym_hash_fn;
  17.910 +        symbols->key_equal_fn = sym_equal_fn;
  17.911 +	symbols->entry_free_fn = sym_free_fn;
  17.912 +        return 0;
  17.913 +    }
  17.914 +    return -1;
  17.915 +}
  17.916 +
  17.917 +/** Cleanup the symbol table. Frees the table and all its symbols.
  17.918 + */
  17.919 +void cleanup_symbols(void){
  17.920 +    HashTable_free(symbols);
  17.921 +    symbols = NULL;
  17.922 +}
  17.923 +
  17.924 +/** Get the interned symbol with the given name.
  17.925 + * No new symbol is created.
  17.926 + *
  17.927 + * @return symbol or null
  17.928 + */
  17.929 +Sxpr get_symbol(char *sym){
  17.930 +    HTEntry *entry;
  17.931 +    if(!symbols){
  17.932 +	if(init_symbols()) return ONOMEM;
  17.933 +	return ONULL;
  17.934 +    }
  17.935 +    entry = HashTable_get_entry(symbols, sym);
  17.936 +    if(entry){
  17.937 +        return OBJP(T_ATOM, entry->value);
  17.938 +    } else {
  17.939 +        return ONULL;
  17.940 +    }
  17.941 +}
  17.942 +
  17.943 +/** Get the interned symbol with the given name.
  17.944 + * Creates a new symbol if necessary.
  17.945 + *
  17.946 + * @return symbol
  17.947 + */
  17.948 +Sxpr intern(char *sym){
  17.949 +    Sxpr symbol = get_symbol(sym);
  17.950 +    if(NULLP(symbol)){
  17.951 +	if(!symbols) return ONOMEM;
  17.952 +        symbol = atom_new(sym);
  17.953 +        if(!NOMEMP(symbol)){
  17.954 +	    OBJ_ATOM(symbol)->interned = TRUE;
  17.955 +            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
  17.956 +        }
  17.957 +    }
  17.958 +    return symbol;
  17.959 +}
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/tools/libxutil/sxpr.h	Mon Nov 22 16:41:50 2004 +0000
    18.3 @@ -0,0 +1,420 @@
    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
    18.9 + * published by the Free Software Foundation; either version 2.1 of the
   18.10 + * License, or  (at your option) any later version. This library is 
   18.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   18.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   18.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   18.14 + * See the GNU Lesser General Public License for more details.
   18.15 + *
   18.16 + * You should have received a copy of the GNU Lesser General Public License
   18.17 + * along with this library; if not, write to the Free Software Foundation,
   18.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   18.19 + */
   18.20 +#ifndef _XUTIL_SXPR_H_
   18.21 +#define _XUTIL_SXPR_H_
   18.22 +
   18.23 +#ifdef __KERNEL__
   18.24 +#include <linux/config.h>
   18.25 +#include <linux/types.h>
   18.26 +#else
   18.27 +#include <stdint.h>
   18.28 +#endif
   18.29 +
   18.30 +#include "hash_table.h"
   18.31 +#include "iostream.h"
   18.32 +#include "allocate.h"
   18.33 +
   18.34 +/** @file
   18.35 + * Definitions for rules and sxprs.
   18.36 + */
   18.37 +
   18.38 +#ifndef NULL
   18.39 +#define NULL 0
   18.40 +#endif
   18.41 +
   18.42 +#ifndef TRUE
   18.43 +#define TRUE 1
   18.44 +#endif
   18.45 +
   18.46 +#ifndef FALSE
   18.47 +#define FALSE 0
   18.48 +#endif
   18.49 +
   18.50 +/** Sxpr type. */
   18.51 +typedef int16_t TypeCode;
   18.52 +
   18.53 +/** A typed sxpr handle.*/
   18.54 +typedef struct Sxpr {
   18.55 +    /** Sxpr type. */
   18.56 +    TypeCode type;
   18.57 +    union {
   18.58 +	/** Sxpr value. */
   18.59 +        unsigned long ul;
   18.60 +	/** Pointer. */
   18.61 +        void *ptr;
   18.62 +    } v;
   18.63 +} Sxpr;
   18.64 +
   18.65 +/** Sxpr type to indicate out of memory. */
   18.66 +#define T_NOMEM      ((TypeCode)-1)
   18.67 +/** The 'unspecified' sxpr. */
   18.68 +#define T_NONE       ((TypeCode)0)
   18.69 +/** The empty list. */
   18.70 +#define T_NULL       ((TypeCode)1)
   18.71 +/** Unsigned integer. */
   18.72 +#define T_UINT       ((TypeCode)2)
   18.73 +/** A string. */
   18.74 +#define T_STRING     ((TypeCode)3)
   18.75 +/** An atom. */
   18.76 +#define T_ATOM       ((TypeCode)4)
   18.77 +/** A boolean. */
   18.78 +#define T_BOOL       ((TypeCode)5)
   18.79 +
   18.80 +/** A cons (pair or list). */
   18.81 +#define T_CONS       ((TypeCode)10)
   18.82 +
   18.83 +/** An error. */
   18.84 +#define T_ERR        ((TypeCode)40)
   18.85 +
   18.86 +/** An atom. */
   18.87 +typedef struct ObjAtom {
   18.88 +    Sxpr name;
   18.89 +    Hashcode hashcode;
   18.90 +    int interned;
   18.91 +} ObjAtom;
   18.92 +
   18.93 +/** A cons (pair). */
   18.94 +typedef struct ObjCons {
   18.95 +    Sxpr car;
   18.96 +    Sxpr cdr;
   18.97 +} ObjCons;
   18.98 +
   18.99 +/** A vector. */
  18.100 +typedef struct ObjVector {
  18.101 +    int n;
  18.102 +    Sxpr data[0];
  18.103 +} ObjVector;
  18.104 +
  18.105 +/** Flags for sxpr printing. */
  18.106 +enum PrintFlags {
  18.107 +    PRINT_RAW           = 0x001,
  18.108 +    PRINT_TYPE          = 0x002,
  18.109 +    PRINT_PRETTY        = 0x004,
  18.110 +    PRINT_NUM           = 0x008,
  18.111 +};
  18.112 +
  18.113 +/** An integer sxpr.
  18.114 + *
  18.115 + * @param ty type
  18.116 + * @param val integer value
  18.117 + */
  18.118 +#define OBJI(ty, val) (Sxpr){ type: (ty), v: { ul: (val) }}
  18.119 +
  18.120 +/** A pointer sxpr.
  18.121 + * If the pointer is non-null, returns an sxpr containing it.
  18.122 + * If the pointer is null, returns ONOMEM.
  18.123 + *
  18.124 + * @param ty type
  18.125 + * @param val pointer
  18.126 + */
  18.127 +#define OBJP(ty, val) ((val) ? (Sxpr){ type: (ty), v: { ptr: (val) }} : ONOMEM)
  18.128 +
  18.129 +/** Make an integer sxpr containing a pointer.
  18.130 + *
  18.131 + * @param val pointer
  18.132 + */
  18.133 +#define PTR(val) OBJP(T_UINT, (void*)(val))
  18.134 +
  18.135 +/** Make an integer sxpr.
  18.136 + * @param x value
  18.137 + */
  18.138 +#define OINT(x)       OBJI(T_UINT,  x)
  18.139 +
  18.140 +/** Make an error sxpr.
  18.141 + *
  18.142 + * @param x value
  18.143 + */
  18.144 +#define OERR(x)       OBJI(T_ERR,   x)
  18.145 +
  18.146 +/** Out of memory constant. */
  18.147 +#define ONOMEM        OBJI(T_NOMEM, 0)
  18.148 +
  18.149 +/** The `unspecified' constant. */
  18.150 +#define ONONE         OBJI(T_NONE,  0)
  18.151 +
  18.152 +/** Empty list constant. */
  18.153 +#define ONULL         OBJI(T_NULL,  0)
  18.154 +
  18.155 +/** False constant. */
  18.156 +#define OFALSE        OBJI(T_BOOL,  0)
  18.157 +
  18.158 +/** True constant. */
  18.159 +#define OTRUE         OBJI(T_BOOL,  1)
  18.160 +
  18.161 +/* Recognizers for the various sxpr types.  */
  18.162 +#define ATOMP(obj)        has_type(obj, T_ATOM)
  18.163 +#define BOOLP(obj)        has_type(obj, T_BOOL)
  18.164 +#define CONSP(obj)        has_type(obj, T_CONS)
  18.165 +#define ERRP(obj)         has_type(obj, T_ERR)
  18.166 +#define INTP(obj)         has_type(obj, T_UINT)
  18.167 +#define NOMEMP(obj)       has_type(obj, T_NOMEM)
  18.168 +#define NONEP(obj)        has_type(obj, T_NONE)
  18.169 +#define NULLP(obj)        has_type(obj, T_NULL)
  18.170 +#define STRINGP(obj)      has_type(obj, T_STRING)
  18.171 +
  18.172 +#define TRUEP(obj)    get_ul(obj)
  18.173 +
  18.174 +/** Convert an sxpr to an unsigned integer. */
  18.175 +#define OBJ_UINT(x)   get_ul(x)
  18.176 +/** Convert an sxpr to an integer. */
  18.177 +#define OBJ_INT(x)    (int)get_ul(x)
  18.178 +
  18.179 +/* Conversions of sxprs to their values.
  18.180 + * No checking is done.
  18.181 + */
  18.182 +#define OBJ_STRING(x)  ((char*)get_ptr(x))
  18.183 +#define OBJ_CONS(x)    ((ObjCons*)get_ptr(x))
  18.184 +#define OBJ_ATOM(x)    ((ObjAtom*)get_ptr(x))
  18.185 +#define OBJ_SET(x)     ((ObjSet*)get_ptr(x))
  18.186 +#define CAR(x)         (OBJ_CONS(x)->car)
  18.187 +#define CDR(x)         (OBJ_CONS(x)->cdr)
  18.188 +
  18.189 +#define CAAR(x)        (CAR(CAR(x)))
  18.190 +#define CADR(x)        (CAR(CDR(x)))
  18.191 +#define CDAR(x)        (CDR(CAR(x)))
  18.192 +#define CDDR(x)        (CDR(CDR(x)))
  18.193 +
  18.194 +/** Get the integer value from an sxpr.
  18.195 + *
  18.196 + * @param obj sxpr
  18.197 + * @return value
  18.198 + */
  18.199 +static inline unsigned long get_ul(Sxpr obj){
  18.200 +    return obj.v.ul;
  18.201 +}
  18.202 +
  18.203 +/** Get the pointer value from an sxpr.
  18.204 + *
  18.205 + * @param obj sxpr
  18.206 + * @return value
  18.207 + */
  18.208 +static inline void * get_ptr(Sxpr obj){
  18.209 +    return obj.v.ptr;
  18.210 +}
  18.211 +
  18.212 +/** Create an sxpr containing a pointer.
  18.213 + *
  18.214 + * @param type typecode
  18.215 + * @param val pointer
  18.216 + * @return sxpr
  18.217 + */
  18.218 +static inline Sxpr obj_ptr(TypeCode type, void *val){
  18.219 +    return (Sxpr){ type: type, v: { ptr: val } };
  18.220 +}
  18.221 +
  18.222 +/** Create an sxpr containing an integer.
  18.223 + *
  18.224 + * @param type typecode
  18.225 + * @param val integer
  18.226 + * @return sxpr
  18.227 + */
  18.228 +static inline Sxpr obj_ul(TypeCode type, unsigned long val){
  18.229 +    return (Sxpr){ type: type, v: { ul: val } };
  18.230 +}
  18.231 +
  18.232 +/** Get the type of an sxpr.
  18.233 + *
  18.234 + * @param obj sxpr
  18.235 + * @return type
  18.236 + */
  18.237 +static inline TypeCode get_type(Sxpr obj){
  18.238 +    return obj.type;
  18.239 +}
  18.240 +
  18.241 +/** Check the type of an sxpr.
  18.242 + *
  18.243 + * @param obj sxpr
  18.244 + * @param type to check
  18.245 + * @return 1 if has the type, 0 otherwise
  18.246 + */
  18.247 +static inline int has_type(Sxpr obj, TypeCode type){
  18.248 +    return get_type(obj) == type;
  18.249 +}
  18.250 +
  18.251 +/** Compare sxprs for literal equality of type and value.
  18.252 + *
  18.253 + * @param x sxpr to compare
  18.254 + * @param y sxpr to compare
  18.255 + * @return 1 if equal, 0 otherwise
  18.256 + */
  18.257 +static inline int eq(Sxpr x, Sxpr y){
  18.258 +    return ((get_type(x) == get_type(y)) && (get_ul(x) == get_ul(y)));
  18.259 +}
  18.260 +
  18.261 +/** Checked version of CAR
  18.262 + *
  18.263 + * @param x sxpr
  18.264 + * @return CAR if a cons, x otherwise
  18.265 + */
  18.266 +static inline Sxpr car(Sxpr x){
  18.267 +    return (CONSP(x) ? CAR(x) : x);
  18.268 +}
  18.269 +
  18.270 +/** Checked version of CDR.
  18.271 + *
  18.272 + * @param x sxpr
  18.273 + * @return CDR if a cons, null otherwise
  18.274 + */
  18.275 +static inline Sxpr cdr(Sxpr x){
  18.276 +    return (CONSP(x) ? CDR(x) : ONULL);
  18.277 +}
  18.278 +
  18.279 +/** Allocate some memory and return an sxpr containing it.
  18.280 + * Returns ONOMEM if allocation failed.
  18.281 + *
  18.282 + * @param n number of bytes to allocate
  18.283 + * @param ty typecode
  18.284 + * @return sxpr
  18.285 + */
  18.286 +static inline Sxpr halloc(size_t n,  TypeCode ty){
  18.287 +    return OBJP(ty, allocate(n));
  18.288 +}
  18.289 +
  18.290 +/** Allocate an sxpr containing a pointer to the given type.
  18.291 + *
  18.292 + * @param ty type (uses sizeof to determine how many bytes to allocate)
  18.293 + * @param code typecode
  18.294 + * @return sxpr, ONOMEM if allocation failed
  18.295 + */
  18.296 +#define HALLOC(ty, code) halloc(sizeof(ty), code)
  18.297 +
  18.298 +typedef int ObjPrintFn(IOStream *io, Sxpr obj, unsigned flags);
  18.299 +typedef int ObjEqualFn(Sxpr obj, Sxpr other);
  18.300 +typedef void ObjFreeFn(Sxpr obj);
  18.301 +
  18.302 +/** An sxpr type definition. */
  18.303 +typedef struct SxprType {
  18.304 +    TypeCode type;
  18.305 +    char *name;
  18.306 +    int pointer;
  18.307 +    ObjPrintFn *print;
  18.308 +    ObjEqualFn *equal;
  18.309 +    ObjFreeFn *free;
  18.310 +} SxprType;
  18.311 +
  18.312 +
  18.313 +extern SxprType *get_sxpr_type(int ty);
  18.314 +
  18.315 +/** Free the pointer in an sxpr.
  18.316 + *
  18.317 + * @param x sxpr containing a pointer
  18.318 + */
  18.319 +static inline void hfree(Sxpr x){
  18.320 +    deallocate(get_ptr(x));
  18.321 +}
  18.322 +
  18.323 +extern int objprint(IOStream *io, Sxpr x, unsigned flags);
  18.324 +extern int objequal(Sxpr x, Sxpr y);
  18.325 +extern void objfree(Sxpr x);
  18.326 +
  18.327 +extern void cons_free_cells(Sxpr obj);
  18.328 +extern Sxpr intern(char *s);
  18.329 +
  18.330 +extern Sxpr assoc(Sxpr k, Sxpr l);
  18.331 +extern Sxpr assocq(Sxpr k, Sxpr l);
  18.332 +extern Sxpr acons(Sxpr k, Sxpr v, Sxpr l);
  18.333 +extern Sxpr nrev(Sxpr l);
  18.334 +extern Sxpr cons_member(Sxpr l, Sxpr x);
  18.335 +extern Sxpr cons_member_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  18.336 +extern int cons_subset(Sxpr s, Sxpr t);
  18.337 +extern int cons_set_equal(Sxpr s, Sxpr t);
  18.338 +
  18.339 +#ifdef USE_GC
  18.340 +extern Sxpr cons_remove(Sxpr l, Sxpr x);
  18.341 +extern Sxpr cons_remove_if(Sxpr l, ObjEqualFn *test_fn, Sxpr v);
  18.342 +#endif
  18.343 +
  18.344 +extern Sxpr atom_new(char *name);
  18.345 +extern char * atom_name(Sxpr obj);
  18.346 +
  18.347 +extern Sxpr string_new(char *s);
  18.348 +extern char * string_string(Sxpr obj);
  18.349 +extern int string_length(Sxpr obj);
  18.350 +
  18.351 +extern Sxpr cons_new(Sxpr car, Sxpr cdr);
  18.352 +extern int cons_push(Sxpr *list, Sxpr elt);
  18.353 +extern int cons_length(Sxpr obj);
  18.354 +
  18.355 +Sxpr sxpr_name(Sxpr obj);
  18.356 +int sxpr_is(Sxpr obj, char *s);
  18.357 +int sxpr_elementp(Sxpr obj, Sxpr name);
  18.358 +Sxpr sxpr_attributes(Sxpr obj);
  18.359 +Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def);
  18.360 +Sxpr sxpr_children(Sxpr obj);
  18.361 +Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def);
  18.362 +Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def);
  18.363 +Sxpr sxpr_child0(Sxpr obj, Sxpr def);
  18.364 +Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
  18.365 +
  18.366 +/** Create a new atom.
  18.367 + *
  18.368 + * @param s atom name
  18.369 + * @return new atom
  18.370 + */
  18.371 +static inline Sxpr mkatom(char *s){
  18.372 +    return atom_new(s);
  18.373 +}
  18.374 +
  18.375 +/** Create a new string sxpr.
  18.376 + *
  18.377 + * @param s string bytes (copied)
  18.378 + * @return new string
  18.379 + */
  18.380 +static inline Sxpr mkstring(char *s){
  18.381 +    return string_new(s);
  18.382 +}
  18.383 +
  18.384 +/** Create an integer sxpr.
  18.385 + *
  18.386 + * @param i value
  18.387 + * @return sxpr
  18.388 + */
  18.389 +static inline Sxpr mkint(int i){
  18.390 +    return OBJI(T_UINT, i);
  18.391 +}
  18.392 +
  18.393 +/** Create a boolean sxpr.
  18.394 + *
  18.395 + * @param b value
  18.396 + * @return sxpr
  18.397 + */
  18.398 +static inline Sxpr mkbool(int b){
  18.399 +    return OBJI(T_BOOL, (b ? 1 : 0));
  18.400 +}
  18.401 +
  18.402 +/* Constants used in parsing and printing. */
  18.403 +#define k_list_open    "("
  18.404 +#define c_list_open    '('
  18.405 +#define k_list_close   ")"
  18.406 +#define c_list_close   ')'
  18.407 +#define k_true         "true"
  18.408 +#define k_false        "false"
  18.409 +
  18.410 +#define c_var          '$'
  18.411 +#define c_escape       '\\'
  18.412 +#define c_single_quote '\''
  18.413 +#define c_double_quote '"'
  18.414 +#define c_string_open  c_double_quote
  18.415 +#define c_string_close c_double_quote
  18.416 +#define c_data_open    '['
  18.417 +#define c_data_close   ']'
  18.418 +#define c_binary       '*'
  18.419 +#define c_eval         '!'
  18.420 +#define c_concat_open  '{'
  18.421 +#define c_concat_close '}'
  18.422 +
  18.423 +#endif /* ! _XUTIL_SXPR_H_ */
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/tools/libxutil/sxpr_parser.c	Mon Nov 22 16:41:50 2004 +0000
    19.3 @@ -0,0 +1,959 @@
    19.4 +/*
    19.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    19.6 + *
    19.7 + * This library is free software; you can redistribute it and/or modify
    19.8 + * it under the terms of the GNU Lesser General Public License as
    19.9 + * published by the Free Software Foundation; either version 2.1 of the
   19.10 + * License, or  (at your option) any later version. This library is 
   19.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   19.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   19.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   19.14 + * See the GNU Lesser General Public License for more details.
   19.15 + *
   19.16 + * You should have received a copy of the GNU Lesser General Public License
   19.17 + * along with this library; if not, write to the Free Software Foundation,
   19.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   19.19 + */
   19.20 +
   19.21 +#ifdef __KERNEL__
   19.22 +#  include <linux/config.h>
   19.23 +#  include <linux/module.h>
   19.24 +#  include <linux/kernel.h>
   19.25 +#  include <linux/string.h>
   19.26 +#  include <linux/errno.h>
   19.27 +#else
   19.28 +#  include <stdlib.h>
   19.29 +#  include <errno.h>
   19.30 +#endif
   19.31 +
   19.32 +#include "iostream.h"
   19.33 +#include "lexis.h"
   19.34 +#include "sxpr_parser.h"
   19.35 +#include "sys_string.h"
   19.36 +#include "enum.h"
   19.37 +
   19.38 +/** @file
   19.39 + * Sxpr parsing.
   19.40 + *
   19.41 + * So that the parser does not leak memory, all sxprs constructed by
   19.42 + * the parser must be freed on error.  On successful parse the sxpr
   19.43 + * returned becomes the responsibility of the caller.
   19.44 + *
   19.45 + * @author Mike Wray <mike.wray@hpl.hp.com>
   19.46 + */
   19.47 +
   19.48 +#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
   19.49 +#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
   19.50 +
   19.51 +static void reset(Parser *z);
   19.52 +static int inputchar(Parser *p, char c);
   19.53 +static int savechar(Parser *p, char c);
   19.54 +extern void parse_error(Parser *in);
   19.55 +extern void parse_error_id(Parser *in, ParseErrorId id);
   19.56 +
   19.57 +static int begin_start(Parser *p, char c);
   19.58 +static int state_start(Parser *p, char c);
   19.59 +static int end_start(Parser *p);
   19.60 +
   19.61 +static int begin_comment(Parser *p, char c);
   19.62 +static int state_comment(Parser *p, char c);
   19.63 +static int end_comment(Parser *p);
   19.64 +
   19.65 +static int begin_string(Parser *p, char c);
   19.66 +static int state_string(Parser *p, char c);
   19.67 +static int end_string(Parser *p);
   19.68 +static int state_escape(Parser *p, char c);
   19.69 +static int state_octal(Parser *p, char c);
   19.70 +static int state_hex(Parser *p, char c);
   19.71 +
   19.72 +static int begin_atom(Parser *p, char c);
   19.73 +static int state_atom(Parser *p, char c);
   19.74 +static int end_atom(Parser *p);
   19.75 +
   19.76 +static int state_list(Parser *p, char c);
   19.77 +static int begin_list(Parser *p, char c);
   19.78 +static int end_list(Parser *p);
   19.79 +
   19.80 +/** Print a parse error.
   19.81 + *
   19.82 + * @param in parser
   19.83 + * @param msg format followed by printf arguments
   19.84 + */
   19.85 +void eprintf(Parser *in, char *msg, ...){
   19.86 +    va_list args;
   19.87 +    if(in->error_out){
   19.88 +        va_start(args, msg);
   19.89 +        IOStream_vprint(in->error_out, msg, args);
   19.90 +        va_end(args);
   19.91 +    }
   19.92 +}
   19.93 +
   19.94 +/** Print a parse warning.
   19.95 + *
   19.96 + * @param in parser
   19.97 + * @param msg format followed by printf arguments
   19.98 + */
   19.99 +void wprintf(Parser *in, char *msg, ...){
  19.100 +    va_list args;
  19.101 +    if(in->error_out){
  19.102 +        va_start(args, msg);
  19.103 +        IOStream_vprint(in->error_out, msg, args);
  19.104 +        va_end(args);
  19.105 +    }
  19.106 +}
  19.107 +
  19.108 +/*============================================================================*/
  19.109 +
  19.110 +/** Record defining the message for a parse error. */
  19.111 +typedef struct {
  19.112 +  ParseErrorId id;
  19.113 +  char *message;
  19.114 +} ParseError;
  19.115 +
  19.116 +/** Format for printing parse error messages. */
  19.117 +#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
  19.118 +
  19.119 +/** Message catalog for the parse error codes. */
  19.120 +static ParseError catalog[] = {
  19.121 +  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
  19.122 +  { PARSE_ERR_NOMEM,                  "out of memory" },
  19.123 +  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
  19.124 +  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
  19.125 +  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
  19.126 +  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
  19.127 +  { 0, NULL }
  19.128 +};
  19.129 +
  19.130 +/** Number of entries in the message catalog. */
  19.131 +const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
  19.132 +
  19.133 +void ParserState_free(ParserState *z){
  19.134 +    if(!z) return;
  19.135 +    objfree(z->val);
  19.136 +    deallocate(z);
  19.137 +}
  19.138 +
  19.139 +int ParserState_new(ParserStateFn *fn, char *name,
  19.140 +                    ParserState *parent, ParserState **val){
  19.141 +    int err = 0;
  19.142 +    ParserState *z;
  19.143 +    z = ALLOCATE(ParserState);
  19.144 +    if(z){
  19.145 +        z->name = name;
  19.146 +        z->fn = fn;
  19.147 +        z->parent = parent;
  19.148 +        z->val = ONULL;
  19.149 +    } else {
  19.150 +        err = -ENOMEM;
  19.151 +    }
  19.152 +    if(!err) *val = z;
  19.153 +    return err;
  19.154 +}
  19.155 +
  19.156 +/** Free a parser.
  19.157 + * No-op if the parser is null.
  19.158 + *
  19.159 + * @param z parser 
  19.160 + */
  19.161 +void Parser_free(Parser *z){
  19.162 +    if(!z) return;
  19.163 +    objfree(z->val);
  19.164 +    z->val = ONONE;
  19.165 +    deallocate(z);
  19.166 +}
  19.167 +
  19.168 +/** Create a new parser. The error stream defaults to null.
  19.169 + */
  19.170 +Parser * Parser_new(void){
  19.171 +    Parser *z = ALLOCATE(Parser);
  19.172 +    int err = -ENOMEM;
  19.173 +  
  19.174 +    if(!z) goto exit;
  19.175 +    err = 0;
  19.176 +    reset(z);
  19.177 +  exit:
  19.178 +    if(err){
  19.179 +        Parser_free(z);
  19.180 +        z = NULL;
  19.181 +    }
  19.182 +    return z;
  19.183 +}
  19.184 +
  19.185 +/** Get the next character.
  19.186 + * Records the character read in the parser,
  19.187 + * and sets the line and character counts.
  19.188 + *
  19.189 + * @param p parser
  19.190 + * @return error flag: 0 on success, non-zero on error
  19.191 + */
  19.192 +static int inputchar(Parser *p, char c){
  19.193 +    int err = 0;
  19.194 +    if(c=='\n'){
  19.195 +        p->line_no++;
  19.196 +        p->char_no = 0;
  19.197 +    } else {
  19.198 +        p->char_no++;
  19.199 +    }
  19.200 +    return err;
  19.201 +}
  19.202 +
  19.203 +static int savechar(Parser *p, char c){
  19.204 +    int err = 0;
  19.205 +    if(p->buf_i >= p->buf_n){
  19.206 +        err = -ENOMEM;
  19.207 +        goto exit;
  19.208 +    }
  19.209 +    p->buf[p->buf_i] = c;
  19.210 +    p->buf_i++;
  19.211 +  exit:
  19.212 +    return err;
  19.213 +}
  19.214 +
  19.215 +int Parser_input_char(Parser *p, char c){
  19.216 +    int err = 0;
  19.217 +    if(at_eof(p)){
  19.218 +        //skip;
  19.219 +    } else {
  19.220 +        inputchar(p, c);
  19.221 +    }
  19.222 +    if(!p->state){
  19.223 +        err = begin_start(p, c);
  19.224 +        if(err) goto exit;
  19.225 +    }
  19.226 +    err = p->state->fn(p, c);
  19.227 +  exit:
  19.228 +    return err;
  19.229 +}
  19.230 +
  19.231 +int Parser_input_eof(Parser *p){
  19.232 +    int err = 0;
  19.233 +    p->eof = 1;
  19.234 +    err = Parser_input_char(p, IOSTREAM_EOF);
  19.235 +    return err;
  19.236 +}
  19.237 +
  19.238 +int Parser_input(Parser *p, char *buf, int buf_n){
  19.239 +    int err = 0;
  19.240 +    int i = 0;
  19.241 +    if(buf_n <= 0){
  19.242 +        err = Parser_input_eof(p);
  19.243 +        goto exit;
  19.244 +    }
  19.245 +    for(i = 0; i<buf_n; i++){
  19.246 +        err = Parser_input_char(p, buf[i]);
  19.247 +        if(err) goto exit;
  19.248 +    }
  19.249 +  exit:
  19.250 +    err = (err < 0 ? err : buf_n);
  19.251 +    return err;
  19.252 +}
  19.253 +
  19.254 +int Parser_push(Parser *p, ParserStateFn *fn, char *name){
  19.255 +    int err = 0;
  19.256 +    err = ParserState_new(fn, name, p->state, &p->state);
  19.257 +    return err;
  19.258 +}
  19.259 +        
  19.260 +int Parser_pop(Parser *p){
  19.261 +    int err = 0;
  19.262 +    ParserState *s = p->state;
  19.263 +    p->state = s->parent;
  19.264 +    ParserState_free(s);
  19.265 +    return err;
  19.266 +}
  19.267 +
  19.268 +int Parser_return(Parser *p){
  19.269 +    int err = 0;
  19.270 +    Sxpr val = ONONE;
  19.271 +    if(!p->state){
  19.272 +        err = -EINVAL;
  19.273 +        goto exit;
  19.274 +    }
  19.275 +    val = p->state->val;
  19.276 +    p->state->val = ONONE;
  19.277 +    err = Parser_pop(p);
  19.278 +    if(err) goto exit;
  19.279 +    if(p->state){
  19.280 +        err = cons_push(&p->state->val, val);
  19.281 +    } else {
  19.282 +        val = nrev(val);
  19.283 +        p->val = val;
  19.284 +    }
  19.285 +  exit:
  19.286 +    if(err){
  19.287 +        objfree(val);
  19.288 +    }
  19.289 +    return err;
  19.290 +}
  19.291 +
  19.292 +/** Determine if a character is a separator.
  19.293 + *
  19.294 + * @param p parser
  19.295 + * @param c character to test
  19.296 + * @return 1 if a separator, 0 otherwise
  19.297 + */
  19.298 +static int is_separator(Parser *p, char c){
  19.299 +    return in_sep_class(c);
  19.300 +}
  19.301 +
  19.302 +/** Return the current token.
  19.303 + * The return value points at the internal buffer, so
  19.304 + * it must not be modified (or freed). Use copy_token() if you need a copy.
  19.305 + *
  19.306 + * @param p parser
  19.307 + * @return token
  19.308 + */
  19.309 +char *peek_token(Parser *p){
  19.310 +    return p->buf;
  19.311 +}
  19.312 +
  19.313 +/** Return a copy of the current token.
  19.314 + * The returned value should be freed when finished with.
  19.315 + *
  19.316 + * @param p parser
  19.317 + * @return copy of token
  19.318 + */
  19.319 +char *copy_token(Parser *p){
  19.320 +    return strdup(peek_token(p));
  19.321 +}
  19.322 +
  19.323 +static int do_intern(Parser *p){
  19.324 +    int err = 0;
  19.325 +    Sxpr obj = intern(peek_token(p));
  19.326 +    if(NOMEMP(obj)){
  19.327 +        err = -ENOMEM;
  19.328 +    } else {
  19.329 +        p->state->val = obj;
  19.330 +    }
  19.331 +    return err;
  19.332 +}
  19.333 +
  19.334 +static int do_string(Parser *p){
  19.335 +    int err = 0;
  19.336 +    Sxpr obj;
  19.337 +    obj = string_new(peek_token(p));
  19.338 +    if(NOMEMP(obj)){
  19.339 +        err = -ENOMEM;
  19.340 +    } else {
  19.341 +        p->state->val = obj;
  19.342 +    }
  19.343 +    return err;
  19.344 +}
  19.345 +
  19.346 +void newtoken(Parser *p){
  19.347 +    memset(p->buf, 0, p->buf_n);
  19.348 +    p->buf_i = 0;
  19.349 +    p->tok_begin_line = p->line_no;
  19.350 +    p->tok_begin_char = p->char_no;
  19.351 +}
  19.352 +
  19.353 +int get_escape(char c, char *d){
  19.354 +    int err = 0;
  19.355 +    switch(c){
  19.356 +    case 'a':            *d = '\a'; break;
  19.357 +    case 'b':            *d = '\b'; break;
  19.358 +    case 'f':            *d = '\f'; break;
  19.359 +    case 'n':            *d = '\n'; break;
  19.360 +    case 'r':            *d = '\r'; break;
  19.361 +    case 't':            *d = '\t'; break;
  19.362 +    case 'v':            *d = '\v'; break;
  19.363 +    case c_escape:       *d = c_escape; break;
  19.364 +    case c_single_quote: *d = c_single_quote; break;
  19.365 +    case c_double_quote: *d = c_double_quote; break;
  19.366 +    default:
  19.367 +        err = -EINVAL;
  19.368 +    }
  19.369 +    return err;
  19.370 +}
  19.371 +
  19.372 +int Parser_ready(Parser *p){
  19.373 +    return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
  19.374 +}
  19.375 +
  19.376 +Sxpr Parser_get_val(Parser *p){
  19.377 +    Sxpr v = ONONE;
  19.378 +    if(CONSP(p->val)){
  19.379 +        v = CAR(p->val);
  19.380 +        p->val = CDR(p->val);
  19.381 +    } else if (CONSP(p->start_state->val)){
  19.382 +        p->val = p->start_state->val;
  19.383 +        p->val = nrev(p->val);
  19.384 +        p->start_state->val = ONULL;
  19.385 +        v = CAR(p->val);
  19.386 +        p->val = CDR(p->val);
  19.387 +    }        
  19.388 +    return v;
  19.389 +}
  19.390 +
  19.391 +Sxpr Parser_get_all(Parser *p){
  19.392 +    Sxpr v = ONULL;
  19.393 +    if(CONSP(p->val)){
  19.394 +        v = p->val;
  19.395 +        p->val = ONONE;
  19.396 +    } else if(CONSP(p->start_state->val)){
  19.397 +        v = p->start_state->val;
  19.398 +        p->start_state->val = ONULL;
  19.399 +        v = nrev(v);
  19.400 +    }
  19.401 +    return v;
  19.402 +}
  19.403 +    
  19.404 +int begin_start(Parser *p, char c){
  19.405 +    int err = 0;
  19.406 +    err = Parser_push(p, state_start, "start");
  19.407 +    if(err) goto exit;
  19.408 +    p->start_state = p->state;
  19.409 +  exit:
  19.410 +    return err;
  19.411 +}
  19.412 +
  19.413 +int state_start(Parser *p, char c){
  19.414 +    int err = 0;
  19.415 +    if(at_eof(p)){
  19.416 +        err = end_start(p);
  19.417 +    } else if(in_space_class(c)){
  19.418 +        //skip
  19.419 +    } else if(in_comment_class(c)){
  19.420 +        begin_comment(p, c);
  19.421 +    } else if(c == c_list_open){
  19.422 +        begin_list(p, c);
  19.423 +    } else if(c == c_list_close){
  19.424 +        parse_error(p);
  19.425 +        err = -EINVAL;
  19.426 +    } else if(in_string_quote_class(c)){
  19.427 +        begin_string(p, c);
  19.428 +    } else if(in_printable_class(c)){
  19.429 +        begin_atom(p, c);
  19.430 +    } else if(c == 0x04){
  19.431 +        //ctrl-D, EOT: end-of-text.
  19.432 +        Parser_input_eof(p);
  19.433 +    } else {
  19.434 +        parse_error(p);
  19.435 +        err = -EINVAL;
  19.436 +    }
  19.437 +    return err;
  19.438 +}
  19.439 +
  19.440 +int end_start(Parser *p){
  19.441 +    int err = 0;
  19.442 +    err = Parser_return(p);
  19.443 +    return err;
  19.444 +}
  19.445 +
  19.446 +int begin_comment(Parser *p, char c){
  19.447 +    int err = 0;
  19.448 +    err = Parser_push(p, state_comment, "comment");
  19.449 +    if(err) goto exit;
  19.450 +    err = inputchar(p, c);
  19.451 +  exit:
  19.452 +    return err;
  19.453 +}
  19.454 +
  19.455 +int state_comment(Parser *p, char c){
  19.456 +    int err = 0;
  19.457 +    if(c == '\n' || at_eof(p)){
  19.458 +        err = end_comment(p);
  19.459 +    } else {
  19.460 +        err = inputchar(p, c);
  19.461 +    }
  19.462 +    return err;
  19.463 +}
  19.464 +
  19.465 +int end_comment(Parser *p){
  19.466 +    return Parser_pop(p);
  19.467 +}
  19.468 +
  19.469 +int begin_string(Parser *p, char c){
  19.470 +    int err = 0;
  19.471 +    err = Parser_push(p, state_string, "string");
  19.472 +    if(err) goto exit;
  19.473 +    newtoken(p);
  19.474 +    p->state->delim = c;
  19.475 +  exit:
  19.476 +    return err;
  19.477 +}
  19.478 +
  19.479 +int state_string(Parser *p, char c){
  19.480 +    int err = 0;
  19.481 +    if(at_eof(p)){
  19.482 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  19.483 +        err = -EINVAL;
  19.484 +    } else if(c == p->state->delim){
  19.485 +        err = end_string(p);
  19.486 +    } else if(c == '\\'){
  19.487 +        err = Parser_push(p, state_escape, "escape");
  19.488 +    } else {
  19.489 +        err = savechar(p, c);
  19.490 +    }
  19.491 +    return err;
  19.492 +}
  19.493 +
  19.494 +int end_string(Parser *p){
  19.495 +    int err = 0;
  19.496 +    err = do_string(p);
  19.497 +    if(err) goto exit;
  19.498 +    err = Parser_return(p);
  19.499 +  exit:
  19.500 +    return err;
  19.501 +}
  19.502 +
  19.503 +int state_escape(Parser *p, char c){
  19.504 +    int err = 0;
  19.505 +    char d;
  19.506 +    if(at_eof(p)){
  19.507 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  19.508 +        err = -EINVAL;
  19.509 +        goto exit;
  19.510 +    }
  19.511 +    if(get_escape(c, &d) == 0){
  19.512 +        err = savechar(p, d);
  19.513 +        if(err) goto exit;
  19.514 +        err = Parser_pop(p);
  19.515 +    } else if(c == 'x'){
  19.516 +        p->state->fn = state_hex;
  19.517 +        p->state->ival = 0;
  19.518 +        p->state->count = 0;
  19.519 +    } else {
  19.520 +        p->state->fn = state_octal;
  19.521 +        p->state->ival = 0;
  19.522 +        p->state->count = 0;
  19.523 +        err = Parser_input_char(p, c);
  19.524 +    }
  19.525 +  exit:
  19.526 +    return err;
  19.527 +}
  19.528 +
  19.529 +int octaldone(Parser *p){
  19.530 +    int err = 0;
  19.531 +    char d = (char)(p->state->ival & 0xff);
  19.532 +    err = Parser_pop(p);
  19.533 +    if(err) goto exit;
  19.534 +    err = Parser_input_char(p, d);
  19.535 +  exit:
  19.536 +    return err;
  19.537 +}
  19.538 +
  19.539 +int octaldigit(Parser *p, char c){
  19.540 +    int err = 0;
  19.541 +    p->state->ival *= 8;
  19.542 +    p->state->ival += c - '0'; 
  19.543 +    p->state->count++;
  19.544 +    if(err) goto exit;
  19.545 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  19.546 +        parse_error(p);
  19.547 +        err = -EINVAL;
  19.548 +        goto exit;
  19.549 +    }
  19.550 +    if(p->state->count == 3){
  19.551 +        err = octaldone(p);
  19.552 +    }
  19.553 +  exit:
  19.554 +    return err;
  19.555 +}
  19.556 +
  19.557 +int state_octal(Parser *p, char c){
  19.558 +    int err = 0;
  19.559 +    if(at_eof(p)){
  19.560 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  19.561 +        err = -EINVAL;
  19.562 +        goto exit;
  19.563 +    } else if('0' <= c && c <= '7'){
  19.564 +        err = octaldigit(p, c);
  19.565 +    } else {
  19.566 +        err = octaldone(p);
  19.567 +        if(err) goto exit;
  19.568 +        Parser_input_char(p, c);
  19.569 +    }
  19.570 +  exit:
  19.571 +    return err;
  19.572 +}
  19.573 +
  19.574 +int hexdone(Parser *p){
  19.575 +    int err = 0;
  19.576 +    char d = (char)(p->state->ival & 0xff);
  19.577 +    err = Parser_pop(p);
  19.578 +    if(err) goto exit;
  19.579 +    err = Parser_input_char(p, d);
  19.580 +  exit:
  19.581 +    return err;
  19.582 +}
  19.583 +    
  19.584 +int hexdigit(Parser *p, char c, char d){
  19.585 +    int err = 0;
  19.586 +    p->state->ival *= 16;
  19.587 +    p->state->ival += c - d; 
  19.588 +    p->state->count++;
  19.589 +    if(err) goto exit;
  19.590 +    if(p->state->ival < 0 || p->state->ival > 0xff){
  19.591 +        parse_error(p);
  19.592 +        err = -EINVAL;
  19.593 +        goto exit;
  19.594 +    }
  19.595 +    if(p->state->count == 2){
  19.596 +        err = hexdone(p);
  19.597 +    }
  19.598 +  exit:
  19.599 +    return err;
  19.600 +}
  19.601 +    
  19.602 +int state_hex(Parser *p, char c){
  19.603 +    int err = 0;
  19.604 +    if(at_eof(p)){
  19.605 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  19.606 +        err = -EINVAL;
  19.607 +        goto exit;
  19.608 +    } else if('0' <= c && c <= '9'){
  19.609 +        err = hexdigit(p, c, '0');
  19.610 +    } else if('A' <= c && c <= 'F'){
  19.611 +        err = hexdigit(p, c, 'A');
  19.612 +    } else if('a' <= c && c <= 'f'){
  19.613 +        err = hexdigit(p, c, 'a');
  19.614 +    } else if(p->state->count){
  19.615 +        err =hexdone(p);
  19.616 +        if(err) goto exit;
  19.617 +        Parser_input_char(p, c);
  19.618 +    }
  19.619 +  exit:
  19.620 +    return err;
  19.621 +}
  19.622 +
  19.623 +int begin_atom(Parser *p, char c){
  19.624 +    int err = 0;
  19.625 +    err = Parser_push(p, state_atom, "atom");
  19.626 +    if(err) goto exit;
  19.627 +    newtoken(p);
  19.628 +    err = savechar(p, c);
  19.629 +  exit:
  19.630 +    return err;
  19.631 +}
  19.632 +
  19.633 +int state_atom(Parser *p, char c){
  19.634 +    int err = 0;
  19.635 +    if(at_eof(p)){
  19.636 +        err = end_atom(p);
  19.637 +    } else if(is_separator(p, c) ||
  19.638 +              in_space_class(c) ||
  19.639 +              in_comment_class(c)){
  19.640 +        err = end_atom(p);
  19.641 +        if(err) goto exit;
  19.642 +        err = Parser_input_char(p, c);
  19.643 +    } else {
  19.644 +        err = savechar(p, c);
  19.645 +    }
  19.646 +  exit:
  19.647 +    return err;
  19.648 +}
  19.649 +
  19.650 +int end_atom(Parser *p){
  19.651 +    int err = 0;
  19.652 +    err = do_intern(p);
  19.653 +    if(err) goto exit;
  19.654 +    err = Parser_return(p);
  19.655 +  exit:
  19.656 +    return err;
  19.657 +}
  19.658 +
  19.659 +int state_list(Parser *p, char c){
  19.660 +    int err = 0;
  19.661 +    if(at_eof(p)){
  19.662 +        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  19.663 +        err = -EINVAL;
  19.664 +    } else if(c == c_list_close){
  19.665 +        p->state->val = nrev(p->state->val);
  19.666 +        err = end_list(p);
  19.667 +    } else {
  19.668 +        err = state_start(p, c);
  19.669 +    }
  19.670 +    return err;
  19.671 +    
  19.672 +}
  19.673 +
  19.674 +int begin_list(Parser *p, char c){
  19.675 +    return Parser_push(p, state_list, "list");
  19.676 +}
  19.677 +
  19.678 +int end_list(Parser *p){
  19.679 +    return Parser_return(p);
  19.680 +}
  19.681 +
  19.682 +/** Reset the fields of a parser to initial values.
  19.683 + *
  19.684 + * @param z parser
  19.685 + */
  19.686 +static void reset(Parser *z){
  19.687 +  IOStream *error_out = z->error_out;
  19.688 +  int flags = z->flags;
  19.689 +  memzero(z, sizeof(Parser));
  19.690 +  z->buf_n = sizeof(z->buf) - 1;
  19.691 +  z->buf_i = 0;
  19.692 +  z->line_no = 1;
  19.693 +  z->char_no = 0;
  19.694 +  z->error_out = error_out;
  19.695 +  z->flags = flags;
  19.696 +}
  19.697 +
  19.698 +/** Set the parser error stream.
  19.699 + * Parse errors are reported on the the error stream if it is non-null.
  19.700 + * 
  19.701 + * @param z parser
  19.702 + * @param error_out error stream
  19.703 + */
  19.704 +void set_error_stream(Parser *z, IOStream *error_out){
  19.705 +  if(z){
  19.706 +    z->error_out = error_out;
  19.707 +  }
  19.708 +}
  19.709 +
  19.710 +/** Get the parser error message for an error code.
  19.711 + *
  19.712 + * @param id error code
  19.713 + * @return error message (empty string if the code is unknown)
  19.714 + */
  19.715 +static char *get_message(ParseErrorId id){
  19.716 +  int i;
  19.717 +  for(i=0; i<catalog_n; i++){
  19.718 +    if(id == catalog[i].id){
  19.719 +      return catalog[i].message;
  19.720 +    }
  19.721 +  }
  19.722 +  return "";
  19.723 +}
  19.724 +
  19.725 +/** Get the line number.
  19.726 + *
  19.727 + * @param in parser
  19.728 + */
  19.729 +int get_line(Parser *in){
  19.730 +  return in->line_no;
  19.731 +}
  19.732 +
  19.733 +/** Get the column number.
  19.734 + *
  19.735 + * @param in parser
  19.736 + */
  19.737 +int get_column(Parser *in){
  19.738 +  return in->char_no;
  19.739 +}
  19.740 +
  19.741 +/** Get the line number the current token started on.
  19.742 + *
  19.743 + * @param in parser
  19.744 + */
  19.745 +int get_tok_line(Parser *in){
  19.746 +  return in->tok_begin_line;
  19.747 +}
  19.748 +
  19.749 +/** Get the column number the current token started on.
  19.750 + *
  19.751 + * @param in parser
  19.752 + */
  19.753 +int get_tok_column(Parser *in){
  19.754 +  return in->tok_begin_char;
  19.755 +}
  19.756 +
  19.757 +/** Report a parse error.
  19.758 + * Does nothing if the error stream is null or there is no error.
  19.759 + *
  19.760 + * @param in parser
  19.761 + */
  19.762 +static void report_error(Parser *in){
  19.763 +  if(in->error_out && in->err){
  19.764 +    char *msg = get_message(in->err);
  19.765 +    char *tok = peek_token(in);
  19.766 +    IOStream_print(in->error_out, PARSE_ERR_FMT,
  19.767 +		   get_tok_line(in), get_tok_column(in), msg);
  19.768 +    if(tok && tok[0]){
  19.769 +        IOStream_print(in->error_out, " '%s'", tok);
  19.770 +    }
  19.771 +    IOStream_print(in->error_out, "\n");
  19.772 +  }
  19.773 +}
  19.774 +
  19.775 +/** Get the error message for the current parse error code.
  19.776 + * Does nothing if there is no error.
  19.777 + *
  19.778 + * @param in parser
  19.779 + * @param buf where to place the message
  19.780 + * @param n maximum number of characters to place in buf
  19.781 + * @return current error code (zero for no error)
  19.782 + */
  19.783 +int parse_error_message(Parser *in, char *buf, int n){
  19.784 +    if(in->err){
  19.785 +        char *msg = get_message(in->err);
  19.786 +        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
  19.787 +    }
  19.788 +    return in->err;
  19.789 +}
  19.790 +
  19.791 +/** Flag an unspecified parse error. All subsequent reads will fail.
  19.792 + *
  19.793 + * @param in parser
  19.794 + */
  19.795 +void parse_error(Parser *in){
  19.796 +    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
  19.797 +}
  19.798 +
  19.799 +/** Flag a parse error. All subsequent reads will fail.
  19.800 + * Does not change the parser error code if it is already set.
  19.801 + *
  19.802 + * @param in parser
  19.803 + * @param id error code
  19.804 + */
  19.805 +void parse_error_id(Parser *in, ParseErrorId id){
  19.806 +    if(!in->err){
  19.807 +        in->err = id;
  19.808 +        report_error(in);
  19.809 +    }
  19.810 +}
  19.811 +
  19.812 +/** Test if the parser's error flag is set.
  19.813 + *
  19.814 + * @param in parser
  19.815 + * @return 1 if set, 0 otherwise
  19.816 + */
  19.817 +int has_error(Parser *in){
  19.818 +    return (in->err > 0);
  19.819 +}
  19.820 +
  19.821 +/** Test if the parser is at end of input.
  19.822 + *
  19.823 + * @param in parser
  19.824 + * @return 1 if at EOF, 0 otherwise
  19.825 + */
  19.826 +int at_eof(Parser *p){
  19.827 +    return p->eof;
  19.828 +}
  19.829 +
  19.830 +//#define SXPR_PARSER_MAIN
  19.831 +#ifdef SXPR_PARSER_MAIN
  19.832 +/* Stuff for standalone testing. */
  19.833 +
  19.834 +#include "file_stream.h"
  19.835 +#include "string_stream.h"
  19.836 +
  19.837 +int stringof(Sxpr exp, char **s){
  19.838 +    int err = 0;
  19.839 +    if(ATOMP(exp)){
  19.840 +        *s = atom_name(exp);
  19.841 +    } else if(STRINGP(exp)){
  19.842 +        *s = string_string(exp);
  19.843 +    } else {
  19.844 +        err = -EINVAL;
  19.845 +        *s = NULL;
  19.846 +    }
  19.847 +    return err;
  19.848 +}
  19.849 +
  19.850 +int child_string(Sxpr exp, Sxpr key, char **s){
  19.851 +    int err = 0;
  19.852 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  19.853 +    err = stringof(val, s);
  19.854 +    return err;
  19.855 +}
  19.856 +
  19.857 +int intof(Sxpr exp, int *v){
  19.858 +    int err = 0;
  19.859 +    char *s;
  19.860 +    unsigned long l;
  19.861 +    if(INTP(exp)){
  19.862 +        *v = OBJ_INT(exp);
  19.863 +    } else {
  19.864 +        err = stringof(exp, &s);
  19.865 +        if(err) goto exit;
  19.866 +        err = convert_atoul(s, &l);
  19.867 +        *v = (int)l;
  19.868 +    }
  19.869 + exit:
  19.870 +    return err;
  19.871 +}
  19.872 +
  19.873 +int child_int(Sxpr exp, Sxpr key, int *v){
  19.874 +    int err = 0;
  19.875 +    Sxpr val = sxpr_child_value(exp, key, ONONE);
  19.876 +    err = intof(val, v);
  19.877 +    return err;
  19.878 +}
  19.879 +
  19.880 +int eval_vnet(Sxpr exp){
  19.881 +    int err = 0;
  19.882 +    Sxpr oid = intern("id");
  19.883 +    int id;
  19.884 +    err = child_int(exp, oid, &id);
  19.885 +    if(err) goto exit;
  19.886 +    dprintf("> vnet id=%d\n", id);
  19.887 + exit:
  19.888 +    dprintf("< err=%d\n", err);
  19.889 +    return err;
  19.890 +}
  19.891 +
  19.892 +int eval_connect(Sxpr exp){
  19.893 +    int err = 0;
  19.894 +    Sxpr ovif = intern("vif");
  19.895 +    Sxpr ovnet = intern("vnet");
  19.896 +    char *vif;
  19.897 +    int vnet;
  19.898 +
  19.899 +    err = child_string(exp, ovif, &vif);
  19.900 +    if(err) goto exit;
  19.901 +    err = child_int(exp, ovnet, &vnet);
  19.902 +    if(err) goto exit;
  19.903 +    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
  19.904 + exit:
  19.905 +    dprintf("< err=%d\n", err);
  19.906 +    return err;
  19.907 +}
  19.908 +
  19.909 +int eval(Sxpr exp){
  19.910 +    int err = 0;
  19.911 +    Sxpr oconnect = intern("connect");
  19.912 +    Sxpr ovnet = intern("vnet");
  19.913 +    
  19.914 +    if(sxpr_elementp(exp, ovnet)){
  19.915 +        err = eval_vnet(exp);
  19.916 +    } else if(sxpr_elementp(exp, oconnect)){
  19.917 +        err = eval_connect(exp);
  19.918 +    } else {
  19.919 +        err = -EINVAL;
  19.920 +    }
  19.921 +    return err;
  19.922 +}
  19.923 +
  19.924 +/** Main program for testing.
  19.925 + * Parses input and prints it.
  19.926 + *
  19.927 + * @param argc number of arguments
  19.928 + * @param argv arguments
  19.929 + * @return error code
  19.930 + */
  19.931 +int main(int argc, char *argv[]){
  19.932 +    Parser *pin;
  19.933 +    int err = 0;
  19.934 +    char buf[1024];
  19.935 +    int k;
  19.936 +    Sxpr obj;
  19.937 +    //Sxpr l, x;
  19.938 +    int i = 0;
  19.939 +
  19.940 +    pin = Parser_new();
  19.941 +    set_error_stream(pin, iostdout);
  19.942 +    dprintf("> parse...\n");
  19.943 +    while(1){
  19.944 +        k = fread(buf, 1, 1, stdin);
  19.945 +        err = Parser_input(pin, buf, k);
  19.946 +        while(Parser_ready(pin)){
  19.947 +            obj = Parser_get_val(pin);
  19.948 +            printf("obj %d\n", i++);
  19.949 +            objprint(iostdout, obj, 0); printf("\n");
  19.950 +        }
  19.951 +        if(k <= 0) break;
  19.952 +    }
  19.953 +/*     obj = Parser_get_all(pin); */
  19.954 +/*     for(l = obj ; CONSP(l); l = CDR(l)){ */
  19.955 +/*         x = CAR(l); */
  19.956 +/*         objprint(iostdout, x, 0); printf("\n"); */
  19.957 +/*         eval(x); */
  19.958 +/*     } */
  19.959 +    dprintf("> err=%d\n", err);
  19.960 +    return 0;
  19.961 +}
  19.962 +#endif
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/tools/libxutil/sxpr_parser.h	Mon Nov 22 16:41:50 2004 +0000
    20.3 @@ -0,0 +1,134 @@
    20.4 +/*
    20.5 + * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    20.6 + *
    20.7 + * This library is free software; you can redistribute it and/or modify
    20.8 + * it under the terms of the GNU Lesser General Public License as
    20.9 + * published by the Free Software Foundation; either version 2.1 of the
   20.10 + * License, or  (at your option) any later version. This library is 
   20.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   20.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   20.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   20.14 + * See the GNU Lesser General Public License for more details.
   20.15 + *
   20.16 + * You should have received a copy of the GNU Lesser General Public License
   20.17 + * along with this library; if not, write to the Free Software Foundation,
   20.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   20.19 + */
   20.20 +
   20.21 +#ifndef _XUTIL_SXPR_PARSER_H_
   20.22 +#define _XUTIL_SXPR_PARSER_H_
   20.23 +
   20.24 +#include "sxpr.h"
   20.25 +#include "iostream.h"
   20.26 +
   20.27 +/** @file
   20.28 + * Sxpr parsing definitions.
   20.29 + */
   20.30 +
   20.31 +/** Size of a parser input buffer.
   20.32 + * Tokens read must fit into this size (including trailing null).
   20.33 + */
   20.34 +#define PARSER_BUF_SIZE 1024
   20.35 +
   20.36 +struct Parser;
   20.37 +typedef int ParserStateFn(struct Parser *, char c);
   20.38 +
   20.39 +typedef struct ParserState {
   20.40 +    struct ParserState *parent;
   20.41 +    Sxpr val;
   20.42 +    int ival;
   20.43 +    int count;
   20.44 +    char delim;
   20.45 +    ParserStateFn *fn;
   20.46 +    char *name;
   20.47 +} ParserState;
   20.48 +
   20.49 +/** Structure representing an input source for the parser.
   20.50 + * Can read from any IOStream implementation.
   20.51 + */
   20.52 +typedef struct Parser {
   20.53 +    Sxpr val;
   20.54 +    /** Error reporting stream (null for no reports). */
   20.55 +    IOStream *error_out;
   20.56 +    int eof;
   20.57 +    /** Error flag. Non-zero if there has been a read error. */
   20.58 +    int err;
   20.59 +    /** Line number on input (from 1). */
   20.60 +    int line_no;
   20.61 +    /** Column number of input (reset on new line). */
   20.62 +    int char_no;
   20.63 +    /** Lookahead character. */
   20.64 +    char c;
   20.65 +    /** Buffer for reading tokens. */
   20.66 +    char buf[PARSER_BUF_SIZE];
   20.67 +    /** Size of token buffer. */
   20.68 +    int buf_n;
   20.69 +    int buf_i;
   20.70 +    /** Line the last token started on. */
   20.71 +    int tok_begin_line;
   20.72 +    /** Character number the last token started on. */
   20.73 +    int tok_begin_char;
   20.74 +    /** Parsing flags. */
   20.75 +    int flags;
   20.76 +    ParserState *state;
   20.77 +    ParserState *start_state;
   20.78 +} Parser;
   20.79 +
   20.80 +/** Parser error codes. */
   20.81 +typedef enum {
   20.82 +    PARSE_ERR_NONE=0,
   20.83 +    PARSE_ERR_UNSPECIFIED,
   20.84 +    PARSE_ERR_NOMEM,
   20.85 +    PARSE_ERR_UNEXPECTED_EOF,
   20.86 +    PARSE_ERR_TOKEN_TOO_LONG,
   20.87 +    PARSE_ERR_INVALID_SYNTAX,
   20.88 +    PARSE_ERR_INVALID_ESCAPE,
   20.89 +} ParseErrorId;
   20.90 +
   20.91 +
   20.92 +/** Parser flags. */
   20.93 +//enum {
   20.94 +//};
   20.95 +
   20.96 +/** Raise some parser flags.
   20.97 + *
   20.98 + * @param in parser
   20.99 + * @param flags flags mask
  20.100 + */
  20.101 +inline static void parser_flags_raise(Parser *in, int flags){
  20.102 +    in->flags |= flags;
  20.103 +}
  20.104 +
  20.105 +/** Lower some parser flags.
  20.106 + *
  20.107 + * @param in parser
  20.108 + * @param flags flags mask
  20.109 + */
  20.110 +inline static void parser_flags_lower(Parser *in, int flags){
  20.111 +    in->flags &= ~flags;
  20.112 +}
  20.113 +
  20.114 +/** Clear all parser flags.
  20.115 + *
  20.116 + * @param in parser
  20.117 + */
  20.118 +inline static void parser_flags_clear(Parser *in){
  20.119 +    in->flags = 0;
  20.120 +}
  20.121 +
  20.122 +extern void Parser_free(Parser *z);
  20.123 +extern Parser * Parser_new(void);
  20.124 +extern int Parser_input(Parser *p, char *buf, int buf_n);
  20.125 +extern int Parser_input_eof(Parser *p);
  20.126 +extern int Parser_input_char(Parser *p, char c);
  20.127 +extern void set_error_stream(Parser *z, IOStream *error_out);
  20.128 +
  20.129 +extern int parse_error_message(Parser *in, char *buf, int n);
  20.130 +extern int has_error(Parser *in);
  20.131 +extern int at_eof(Parser *in);
  20.132 +
  20.133 +int Parser_ready(Parser *p);
  20.134 +Sxpr Parser_get_val(Parser *p);
  20.135 +Sxpr Parser_get_all(Parser *p);
  20.136 +
  20.137 +#endif /* ! _XUTIL_SXPR_PARSER_H_ */
    21.1 --- a/tools/libxutil/sys_net.c	Sun Nov 21 20:41:00 2004 +0000
    21.2 +++ b/tools/libxutil/sys_net.c	Mon Nov 22 16:41:50 2004 +0000
    21.3 @@ -232,21 +232,17 @@ char *get_port_service(unsigned long por
    21.4  int convert_service_to_port(const char *s, unsigned long *port){
    21.5      int err = 0;
    21.6      unsigned long value;
    21.7 -    printf("%s> %s\n", __FUNCTION__, s);
    21.8      if(convert_atoul(s, &value) == 0){
    21.9          int ok = (0 <= value) && (value <= PORT_MAX);
   21.10 -        printf("> value = %ld\n", value);
   21.11          if(ok){
   21.12              value = htons((unsigned short)value);
   21.13          } else {
   21.14              err = -EINVAL;
   21.15          }
   21.16      } else {
   21.17 -        printf("> get_service_port...\n");
   21.18          err = get_service_port(s, &value);
   21.19      }
   21.20      *port = (err ? 0: value);
   21.21 -    printf("%s< err=%d\n", __FUNCTION__, err);
   21.22      return err;
   21.23  }
   21.24  
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/tools/libxutil/util.c	Mon Nov 22 16:41:50 2004 +0000
    22.3 @@ -0,0 +1,106 @@
    22.4 +/*
    22.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>.
    22.6 + *
    22.7 + * This library is free software; you can redistribute it and/or modify
    22.8 + * it under the terms of the GNU Lesser General Public License as
    22.9 + * published by the Free Software Foundation; either version 2.1 of the
   22.10 + * License, or  (at your option) any later version. This library is 
   22.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   22.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   22.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   22.14 + * See the GNU Lesser General Public License for more details.
   22.15 + *
   22.16 + * You should have received a copy of the GNU Lesser General Public License
   22.17 + * along with this library; if not, write to the Free Software Foundation,
   22.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   22.19 + */
   22.20 +
   22.21 +#include "sys_net.h"
   22.22 +#include "sys_string.h"
   22.23 +
   22.24 +#ifndef __KERNEL__
   22.25 +#  include <grp.h>   
   22.26 +#  include <pwd.h>  
   22.27 +#endif
   22.28 +
   22.29 +#include "util.h"
   22.30 +
   22.31 +
   22.32 +/** @file Various utility functions.
   22.33 + */
   22.34 +
   22.35 +/** Print an address (in network order) as an IPv4 address string
   22.36 + * in dot notation.
   22.37 + *
   22.38 + * @param io where to print address
   22.39 + * @param address to print (in network order)
   22.40 + * @return bytes printed
   22.41 + */
   22.42 +int print_address(IOStream *io, unsigned long address){
   22.43 +#ifdef __KERNEL__
   22.44 +    address = ntohl(address);
   22.45 +    return IOStream_print(io, "%u.%u.%u.%u", 
   22.46 +                          (unsigned)((address >> 24) & 0xff),
   22.47 +                          (unsigned)((address >> 16) & 0xff),
   22.48 +                          (unsigned)((address >>  8) & 0xff),
   22.49 +                          (unsigned)((address      ) & 0xff));
   22.50 +#else
   22.51 +    struct in_addr inaddr = { s_addr: address };
   22.52 +    return IOStream_print(io, inet_ntoa(inaddr));
   22.53 +#endif
   22.54 +}
   22.55 +
   22.56 +/** Get the protocol number for a protocol.
   22.57 + *
   22.58 + * @param name protocol name
   22.59 + * @param protocol where to put the protocol number
   22.60 + * @return 0 if OK, error otherwise
   22.61 + */  
   22.62 +int get_protocol_number(char *name, unsigned long *protocol){
   22.63 +#ifdef __KERNEL__
   22.64 +    return -1;
   22.65 +#else
   22.66 +    struct protoent *proto = getprotobyname(name);
   22.67 +    if(!proto){
   22.68 +	return -1;
   22.69 +    }
   22.70 +    *protocol = proto->p_proto;
   22.71 +    return 0;
   22.72 +#endif
   22.73 +}
   22.74 +
   22.75 +/** Get the protocol name for a protocol number.
   22.76 + *
   22.77 + * @param protocol number
   22.78 + * @return name or null
   22.79 + */
   22.80 +char *get_protocol_name(unsigned long protocol){
   22.81 +#ifdef __KERNEL__
   22.82 +    return 0;
   22.83 +#else
   22.84 +    struct protoent *proto = getprotobynumber(protocol);
   22.85 +    if(!proto){
   22.86 +	return 0;
   22.87 +    }
   22.88 +    return proto->p_name;
   22.89 +#endif
   22.90 +}
   22.91 +
   22.92 +/** Get the host name for an address.
   22.93 + *
   22.94 + * @param addr address
   22.95 + * @return host name or null
   22.96 + */
   22.97 +char *get_host_name(unsigned long addr){
   22.98 +#ifdef __KERNEL__
   22.99 +    return 0;
  22.100 +#else
  22.101 +    struct in_addr inaddr;
  22.102 +    struct hostent *host = 0;
  22.103 +
  22.104 +    inaddr.s_addr = addr;
  22.105 +    host = gethostbyaddr((char*)&inaddr, sizeof(inaddr), AF_INET);
  22.106 +    if(!host) return NULL;
  22.107 +    return host->h_name;
  22.108 +#endif
  22.109 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/tools/libxutil/util.h	Mon Nov 22 16:41:50 2004 +0000
    23.3 @@ -0,0 +1,28 @@
    23.4 +/*
    23.5 + * Copyright (C) 2002 - 2004 Mike Wray <mike.wray@hp.com>.
    23.6 + *
    23.7 + * This library is free software; you can redistribute it and/or modify
    23.8 + * it under the terms of the GNU Lesser General Public License as
    23.9 + * published by the Free Software Foundation; either version 2.1 of the
   23.10 + * License, or  (at your option) any later version. This library is 
   23.11 + * distributed in the  hope that it will be useful, but WITHOUT ANY
   23.12 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   23.13 + * FITNESS FOR A PARTICULAR PURPOSE.
   23.14 + * See the GNU Lesser General Public License for more details.
   23.15 + *
   23.16 + * You should have received a copy of the GNU Lesser General Public License
   23.17 + * along with this library; if not, write to the Free Software Foundation,
   23.18 + * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   23.19 + */
   23.20 +
   23.21 +#ifndef _XEN_LIB_UTIL_H_
   23.22 +#define _XEN_LIB_UTIL_H_
   23.23 +
   23.24 +#include "iostream.h"
   23.25 +
   23.26 +extern int print_address(IOStream *io, unsigned long address);
   23.27 +extern int get_protocol_number(char *name, unsigned long *protocol);
   23.28 +extern char *get_protocol_name(unsigned long protocol);
   23.29 +extern char *get_host_name(unsigned long addr);
   23.30 +
   23.31 +#endif /* ! _XEN_LIB_UTIL_H_ */
    24.1 --- a/tools/xfrd/Make.xfrd	Sun Nov 21 20:41:00 2004 +0000
    24.2 +++ b/tools/xfrd/Make.xfrd	Mon Nov 22 16:41:50 2004 +0000
    24.3 @@ -26,7 +26,6 @@ UTIL_LIB_SRC += xdr.c
    24.4  
    24.5  XFRD_PROG_SRC =
    24.6  XFRD_PROG_SRC += xfrd.c
    24.7 -#XFRD_PROG_SRC += xfr_msg.c
    24.8  XFRD_PROG_SRC += xen_domain.c
    24.9  XFRD_PROG_SRC += select.c
   24.10  XFRD_PROG_SRC += connection.c
    25.1 --- a/tools/xfrd/enum.c	Sun Nov 21 20:41:00 2004 +0000
    25.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    25.3 @@ -1,61 +0,0 @@
    25.4 -/*
    25.5 - * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
    25.6 - *
    25.7 - * This library is free software; you can redistribute it and/or modify
    25.8 - * it under the terms of the GNU Lesser General Public License as
    25.9 - * published by the Free Software Foundation; either version 2.1 of the
   25.10 - * License, or  (at your option) any later version. This library is 
   25.11 - * distributed in the  hope that it will be useful, but WITHOUT ANY
   25.12 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   25.13 - * FITNESS FOR A PARTICULAR PURPOSE.
   25.14 - * See the GNU Lesser General Public License for more details.
   25.15 - *
   25.16 - * You should have received a copy of the GNU Lesser General Public License
   25.17 - * along with this library; if not, write to the Free Software Foundation,
   25.18 - * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   25.19 - */
   25.20 -
   25.21 -#ifdef __KERNEL__
   25.22 -#include <linux/errno.h>
   25.23 -#else
   25.24 -#include <errno.h>
   25.25 -#endif
   25.26 -
   25.27 -#include "sys_string.h"
   25.28 -#include "enum.h"
   25.29 -
   25.30 -/** Map an enum name to its value using a table.
   25.31 - *
   25.32 - * @param name enum name
   25.33 - * @param defs enum definitions
   25.34 - * @return enum value or -1 if not known
   25.35 - */
   25.36 -int enum_name_to_val(char *name, EnumDef *defs){
   25.37 -    int val = -1;
   25.38 -    for(; defs->name; defs++){
   25.39 -	if(!strcmp(defs->name, name)){
   25.40 -	    val = defs->val;
   25.41 -	    break;
   25.42 -	}
   25.43 -    }
   25.44 -    return val;
   25.45 -}
   25.46 -
   25.47 -/** Map an enum value to its name using a table.
   25.48 - *
   25.49 - * @param val enum value
   25.50 - * @param defs enum definitions
   25.51 - * @param defs_n number of definitions
   25.52 - * @return enum name or NULL if not known
   25.53 - */
   25.54 -char *enum_val_to_name(int val, EnumDef *defs){
   25.55 -    char *name = NULL;
   25.56 -    for(; defs->name; defs++){
   25.57 -	if(val == defs->val){
   25.58 -	    name = defs->name;
   25.59 -	    break;
   25.60 -	}
   25.61 -    }
   25.62 -    return name;
   25.63 -}
   25.64 -
    26.1 --- a/tools/xfrd/enum.h	Sun Nov 21 20:41:00 2004 +0000
    26.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.3 @@ -1,30 +0,0 @@
    26.4 -/*
    26.5 - * Copyright (C) 2002, 2004 Mike Wray <mike.wray@hp.com>
    26.6 - *
    26.7 - * This library is free software; you can redistribute it and/or modify
    26.8 - * it under the terms of the GNU Lesser General Public License as
    26.9 - * published by the Free Software Foundation; either version 2.1 of the
   26.10 - * License, or  (at your option) any later version. This library is 
   26.11 - * distributed in the  hope that it will be useful, but WITHOUT ANY
   26.12 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   26.13 - * FITNESS FOR A PARTICULAR PURPOSE.
   26.14 - * See the GNU Lesser General Public License for more details.
   26.15 - *
   26.16 - * You should have received a copy of the GNU Lesser General Public License
   26.17 - * along with this library; if not, write to the Free Software Foundation,
   26.18 - * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   26.19 - */
   26.20 -
   26.21 -#ifndef _XUTIL_ENUM_H_
   26.22 -#define _XUTIL_ENUM_H_
   26.23 -
   26.24 -/** Mapping of an enum value to a name. */
   26.25 -typedef struct EnumDef {
   26.26 -    int val;
   26.27 -    char *name;
   26.28 -} EnumDef;
   26.29 -
   26.30 -extern int enum_name_to_val(char *name, EnumDef *defs);
   26.31 -extern char *enum_val_to_name(int val, EnumDef *defs);
   26.32 -
   26.33 -#endif /* _XUTIL_ENUM_H_ */
    27.1 --- a/tools/xfrd/hash_table.c	Sun Nov 21 20:41:00 2004 +0000
    27.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.3 @@ -1,640 +0,0 @@
    27.4 -/*
    27.5 - * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    27.6 - *
    27.7 - * This library is free software; you can redistribute it and/or modify
    27.8 - * it under the terms of the GNU Lesser General Public License as published by
    27.9 - * the Free Software Foundation; either version 2.1 of the License, or
   27.10 - * (at your option) any later version.
   27.11 - *
   27.12 - * This library is distributed in the hope that it will be useful,
   27.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.15 - * GNU Lesser General Public License for more details.
   27.16 - *
   27.17 - * You should have received a copy of the GNU Lesser General Public License
   27.18 - * along with this library; if not, write to the Free Software
   27.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   27.20 - */
   27.21 -
   27.22 -#ifdef __KERNEL__
   27.23 -#  include <linux/config.h>
   27.24 -#  include <linux/module.h>
   27.25 -#  include <linux/kernel.h>
   27.26 -#  include <linux/errno.h>
   27.27 -#else
   27.28 -#  include <errno.h>
   27.29 -#  include <stddef.h>
   27.30 -#endif
   27.31 -
   27.32 -//#include <limits.h>
   27.33 -
   27.34 -#include "allocate.h"
   27.35 -#include "hash_table.h"
   27.36 -
   27.37 -/** @file
   27.38 - * Base support for hashtables.
   27.39 - *
   27.40 - * Hash codes are reduced modulo the number of buckets to index tables,
   27.41 - * so there is no need for hash functions to limit the range of hashcodes.
   27.42 - * In fact it is assumed that hashcodes do not change when the number of
   27.43 - * buckets in the table changes.
   27.44 - */
   27.45 -
   27.46 -/*==========================================================================*/
   27.47 -/** Number of bits in half a word. */
   27.48 -//#if __WORDSIZE == 64
   27.49 -//#define HALF_WORD_BITS 32
   27.50 -//#else
   27.51 -#define HALF_WORD_BITS 16
   27.52 -//#endif
   27.53 -
   27.54 -/** Mask for lo half of a word. On 32-bit this is 
   27.55 - * (1<<16) - 1 = 65535 = 0xffff
   27.56 - * It's 4294967295 = 0xffffffff on 64-bit.
   27.57 - */
   27.58 -#define LO_HALF_MASK ((1 << HALF_WORD_BITS) - 1)
   27.59 -
   27.60 -/** Get the lo half of a word. */
   27.61 -#define LO_HALF(x) ((x) & LO_HALF_MASK)
   27.62 -
   27.63 -/** Get the hi half of a word. */
   27.64 -#define HI_HALF(x) ((x) >> HALF_WORD_BITS)
   27.65 -
   27.66 -/** Do a full hash on both inputs, using DES-style non-linear scrambling.
   27.67 - * Both inputs are replaced with the results of the hash.
   27.68 - *
   27.69 - * @param pleft input/output word
   27.70 - * @param pright input/output word
   27.71 - */
   27.72 -void pseudo_des(unsigned long *pleft, unsigned long *pright){
   27.73 -    // Bit-rich mixing constant.
   27.74 -    static const unsigned long a_mixer[] = {
   27.75 -        0xbaa96887L, 0x1e17d32cL, 0x03bcdc3cL, 0x0f33d1b2L, };
   27.76 -
   27.77 -    // Bit-rich mixing constant.
   27.78 -    static const unsigned long b_mixer[] = {
   27.79 -        0x4b0f3b58L, 0xe874f0c3L, 0x6955c5a6L, 0x55a7ca46L, };
   27.80 -
   27.81 -    // Number of iterations - must be 2 or 4.
   27.82 -    static const int ncycle = 4;
   27.83 -    //static const int ncycle = 2;
   27.84 -
   27.85 -    unsigned long left = *pleft, right = *pright;
   27.86 -    unsigned long v, v_hi, v_lo;
   27.87 -    int i;
   27.88 -
   27.89 -    for(i=0; i<ncycle; i++){
   27.90 -        // Flip some bits in right to get v.
   27.91 -        v = right;
   27.92 -        v ^= a_mixer[i];
   27.93 -        // Get lo and hi halves of v.
   27.94 -        v_lo = LO_HALF(v);
   27.95 -        v_hi = HI_HALF(v);
   27.96 -        // Non-linear mix of the halves of v.
   27.97 -        v = ((v_lo * v_lo) + ~(v_hi * v_hi));
   27.98 -        // Swap the halves of v.
   27.99 -        v = (HI_HALF(v) | (LO_HALF(v) << HALF_WORD_BITS));
  27.100 -        // Flip some bits.
  27.101 -        v ^= b_mixer[i];
  27.102 -        // More non-linear mixing.
  27.103 -        v += (v_lo * v_hi);
  27.104 -        v ^= left;
  27.105 -        left = right;
  27.106 -        right = v;
  27.107 -    }
  27.108 -    *pleft = left;
  27.109 -    *pright = right;
  27.110 -}
  27.111 -
  27.112 -/** Hash a string.
  27.113 - *
  27.114 - * @param s input to hash
  27.115 - * @return hashcode
  27.116 - */
  27.117 -Hashcode hash_string(char *s){
  27.118 -    Hashcode h = 0;
  27.119 -    if(s){
  27.120 -        for( ; *s; s++){
  27.121 -            h = hash_2ul(h, *s);
  27.122 -        }
  27.123 -    }
  27.124 -    return h;
  27.125 -}
  27.126 -
  27.127 -/** Get the bucket for a hashcode in a hash table.
  27.128 - *
  27.129 - * @param table to get bucket from
  27.130 - * @param hashcode to get bucket for
  27.131 - * @return bucket
  27.132 - */
  27.133 -inline HTBucket * get_bucket(HashTable *table, Hashcode hashcode){
  27.134 -    return table->buckets + (hashcode % table->buckets_n);
  27.135 -}
  27.136 -
  27.137 -/** Initialize a hash table.
  27.138 - * Can be safely called more than once.
  27.139 - *
  27.140 - * @param table to initialize
  27.141 - */
  27.142 -void HashTable_init(HashTable *table){
  27.143 -    int i;
  27.144 -
  27.145 -    if(!table->init_done){
  27.146 -        table->init_done = 1;
  27.147 -        table->next_id = 0;
  27.148 -        for(i=0; i<table->buckets_n; i++){
  27.149 -            HTBucket *bucket = get_bucket(table, i);
  27.150 -            bucket->head = 0;
  27.151 -            bucket->count = 0;
  27.152 -        }
  27.153 -        table->entry_count = 0;
  27.154 -    }
  27.155 -}
  27.156 -
  27.157 -/** Allocate a new hashtable.
  27.158 - * If the number of buckets is not positive the default is used.
  27.159 - * The number of buckets should usually be prime.
  27.160 - *
  27.161 - * @param buckets_n number of buckets
  27.162 - * @return new hashtable or null
  27.163 - */
  27.164 -HashTable *HashTable_new(int buckets_n){
  27.165 -    HashTable *z = ALLOCATE(HashTable);
  27.166 -    if(!z) goto exit;
  27.167 -    if(buckets_n <= 0){
  27.168 -        buckets_n = HT_BUCKETS_N;
  27.169 -    }
  27.170 -    z->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
  27.171 -    if(!z->buckets){
  27.172 -        deallocate(z);
  27.173 -        z = 0;
  27.174 -        goto exit;
  27.175 -    }
  27.176 -    z->buckets_n = buckets_n;
  27.177 -    HashTable_init(z);
  27.178 -  exit:
  27.179 -    return z;
  27.180 -}
  27.181 -
  27.182 -/** Free a hashtable.
  27.183 - * Any entries are removed and freed.
  27.184 - *
  27.185 - * @param h hashtable (ignored if null)
  27.186 - */
  27.187 -void HashTable_free(HashTable *h){
  27.188 -    if(h){
  27.189 -        HashTable_clear(h);
  27.190 -        deallocate(h->buckets);
  27.191 -        deallocate(h);
  27.192 -    }
  27.193 -}
  27.194 -
  27.195 -/** Push an entry on the list in the bucket for a given hashcode.
  27.196 - *
  27.197 - * @param table to add entry to
  27.198 - * @param hashcode for the entry
  27.199 - * @param entry to add
  27.200 - */
  27.201 -static inline void push_on_bucket(HashTable *table, Hashcode hashcode,
  27.202 -				  HTEntry *entry){
  27.203 -    HTBucket *bucket;
  27.204 -    HTEntry *old_head;
  27.205 -
  27.206 -    bucket = get_bucket(table, hashcode);
  27.207 -    old_head = bucket->head;
  27.208 -    bucket->count++;
  27.209 -    bucket->head = entry;
  27.210 -    entry->next = old_head;
  27.211 -}
  27.212 -
  27.213 -/** Change the number of buckets in a hashtable.
  27.214 - * No-op if the number of buckets is not positive.
  27.215 - * Existing entries are reallocated to buckets based on their hashcodes.
  27.216 - * The table is unmodified if the number of buckets cannot be changed.
  27.217 - *
  27.218 - * @param table hashtable
  27.219 - * @param buckets_n new number of buckets
  27.220 - * @return 0 on success, error code otherwise
  27.221 - */
  27.222 -int HashTable_set_buckets_n(HashTable *table, int buckets_n){
  27.223 -    int err = 0;
  27.224 -    HTBucket *old_buckets = table->buckets;
  27.225 -    int old_buckets_n = table->buckets_n;
  27.226 -    int i;
  27.227 -
  27.228 -    if(buckets_n <= 0){
  27.229 -        err = -EINVAL;
  27.230 -        goto exit;
  27.231 -    }
  27.232 -    table->buckets = (HTBucket*)allocate(buckets_n * sizeof(HTBucket));
  27.233 -    if(!table->buckets){
  27.234 -        err = -ENOMEM;
  27.235 -        table->buckets = old_buckets;
  27.236 -        goto exit;
  27.237 -    }
  27.238 -    table->buckets_n = buckets_n;
  27.239 -    for(i=0; i<old_buckets_n; i++){
  27.240 -        HTBucket *bucket = old_buckets + i;
  27.241 -        HTEntry *entry, *next;
  27.242 -        for(entry = bucket->head; entry; entry = next){
  27.243 -            next = entry->next;
  27.244 -            push_on_bucket(table, entry->hashcode, entry);
  27.245 -        }
  27.246 -    }
  27.247 -    deallocate(old_buckets);
  27.248 -  exit:
  27.249 -    return err;
  27.250 -}
  27.251 -
  27.252 -/** Adjust the number of buckets so the table is neither too full nor too empty.
  27.253 - * The table is unmodified if adjusting fails.
  27.254 - *
  27.255 - * @param table hash table
  27.256 - * @param buckets_min minimum number of buckets (use default if 0 or negative)
  27.257 - * @return 0 on success, error code otherwise
  27.258 - */
  27.259 -int HashTable_adjust(HashTable *table, int buckets_min){
  27.260 -    int buckets_n = 0;
  27.261 -    int err = 0;
  27.262 -    if(buckets_min <= 0) buckets_min = HT_BUCKETS_N;
  27.263 -    if(table->entry_count >= table->buckets_n){
  27.264 -        // The table is dense - expand it.
  27.265 -        buckets_n = 2 * table->buckets_n;
  27.266 -    } else if((table->buckets_n > buckets_min) &&
  27.267 -              (4 * table->entry_count < table->buckets_n)){
  27.268 -        // The table is more than minimum size and sparse - shrink it.
  27.269 -        buckets_n = 2 * table->entry_count;
  27.270 -        if(buckets_n < buckets_min) buckets_n = buckets_min;
  27.271 -    }
  27.272 -    if(buckets_n){
  27.273 -        err = HashTable_set_buckets_n(table, buckets_n);
  27.274 -    }
  27.275 -    return err;
  27.276 -}
  27.277 -
  27.278 -/** Allocate a new entry for a given value.
  27.279 - *
  27.280 - * @param value to put in the entry
  27.281 - * @return entry, or 0 on failure
  27.282 - */
  27.283 -HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value){
  27.284 -    HTEntry *z = ALLOCATE(HTEntry);
  27.285 -    if(z){
  27.286 -        z->hashcode = hashcode;
  27.287 -        z->key = key;
  27.288 -        z->value = value;
  27.289 -    }
  27.290 -    return z;
  27.291 -}
  27.292 -
  27.293 -/** Free an entry.
  27.294 - *
  27.295 - * @param z entry to free
  27.296 - */
  27.297 -inline void HTEntry_free(HTEntry *z){
  27.298 -    if(z){
  27.299 -        deallocate(z);
  27.300 -    }
  27.301 -}
  27.302 -
  27.303 -/** Free an entry in a hashtable.
  27.304 - * The table's entry_free_fn is used is defined, otherwise 
  27.305 - * the HTEntry itself is freed.
  27.306 - *
  27.307 - * @param table hashtable
  27.308 - * @param entry to free
  27.309 - */
  27.310 -inline void HashTable_free_entry(HashTable *table, HTEntry *entry){
  27.311 -    if(!entry)return;
  27.312 -    if(table && table->entry_free_fn){
  27.313 -        table->entry_free_fn(table, entry);
  27.314 -    } else {
  27.315 -        HTEntry_free(entry);
  27.316 -    }
  27.317 -}
  27.318 -
  27.319 -/** Get the first entry satisfying a test from the bucket for the
  27.320 - * given hashcode.
  27.321 - *
  27.322 - * @param table to look in
  27.323 - * @param hashcode indicates the bucket
  27.324 - * @param test_fn test to apply to elements
  27.325 - * @param arg first argument to calls to test_fn
  27.326 - * @return entry found, or 0
  27.327 - */
  27.328 -inline HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
  27.329 -				      TableTestFn *test_fn, TableArg arg){
  27.330 -    HTBucket *bucket;
  27.331 -    HTEntry *entry = 0;
  27.332 -    HTEntry *next;
  27.333 -
  27.334 -    bucket = get_bucket(table, hashcode);
  27.335 -    for(entry = bucket->head; entry; entry = next){
  27.336 -        next = entry->next;
  27.337 -        if(test_fn(arg, table, entry)){
  27.338 -            break;
  27.339 -        }
  27.340 -    }
  27.341 -    return entry;
  27.342 -}
  27.343 -
  27.344 -/** Test hashtable keys for equality.
  27.345 - * Uses the table's key_equal_fn if defined, otherwise pointer equality.
  27.346 - *
  27.347 - * @param key1 key to compare
  27.348 - * @param key2 key to compare
  27.349 - * @return 1 if equal, 0 otherwise
  27.350 - */
  27.351 -inline int HashTable_key_equal(HashTable *table, void *key1, void *key2){
  27.352 -    return (table->key_equal_fn ? table->key_equal_fn(key1, key2) : key1==key2);
  27.353 -}
  27.354 -
  27.355 -/** Compute the hashcode of a hashtable key.
  27.356 - * The table's key_hash_fn is used if defined, otherwise the address of
  27.357 - * the key is hashed.
  27.358 - *
  27.359 - * @param table hashtable
  27.360 - * @param key to hash
  27.361 - * @return hashcode
  27.362 - */
  27.363 -inline Hashcode HashTable_key_hash(HashTable *table, void *key){
  27.364 -    return (table->key_hash_fn ? table->key_hash_fn(key) : hash_ul((unsigned long)key));
  27.365 -}
  27.366 -
  27.367 -/** Test if an entry has a given key.
  27.368 - *
  27.369 - * @param arg containing key to test for
  27.370 - * @param table the entry is in
  27.371 - * @param entry to test
  27.372 - * @return 1 if the entry has the key, 0 otherwise
  27.373 - */
  27.374 -static inline int has_key(TableArg arg, HashTable *table, HTEntry *entry){
  27.375 -    return HashTable_key_equal(table, arg.ptr, entry->key);
  27.376 -}
  27.377 -
  27.378 -/** Get an entry with a given key.
  27.379 - *
  27.380 - * @param table to search
  27.381 - * @param key to look for
  27.382 - * @return entry if found, null otherwise
  27.383 - */
  27.384 -#if 0
  27.385 -inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
  27.386 -    TableArg arg = { ptr: key };
  27.387 -    return HashTable_find_entry(table, HashTable_key_hash(table, key), has_key, arg);
  27.388 -}
  27.389 -#else
  27.390 -inline HTEntry * HashTable_get_entry(HashTable *table, void *key){
  27.391 -    Hashcode hashcode;
  27.392 -    HTBucket *bucket;
  27.393 -    HTEntry *entry = 0;
  27.394 -    HTEntry *next;
  27.395 -
  27.396 -    hashcode = HashTable_key_hash(table, key);
  27.397 -    bucket = get_bucket(table, hashcode);
  27.398 -    for(entry = bucket->head; entry; entry = next){
  27.399 -        next = entry->next;
  27.400 -        if(HashTable_key_equal(table, key, entry->key)){
  27.401 -            break;
  27.402 -        }
  27.403 -    }
  27.404 -    return entry;
  27.405 -}
  27.406 -#endif
  27.407 -
  27.408 -/** Get the value of an entry with a given key.
  27.409 - *
  27.410 - * @param table to search
  27.411 - * @param key to look for
  27.412 - * @return value if an entry was found, null otherwise
  27.413 - */
  27.414 -inline void * HashTable_get(HashTable *table, void *key){
  27.415 -    HTEntry *entry = HashTable_get_entry(table, key);
  27.416 -    return (entry ? entry->value : 0);
  27.417 -}
  27.418 -
  27.419 -/** Print the buckets in a table.
  27.420 - *
  27.421 - * @param table to print
  27.422 - */
  27.423 -void show_buckets(HashTable *table, IOStream *io){
  27.424 -    int i,j ;
  27.425 -    IOStream_print(io, "entry_count=%d buckets_n=%d\n", table->entry_count, table->buckets_n);
  27.426 -    for(i=0; i<table->buckets_n; i++){
  27.427 -        if(0 || table->buckets[i].count>0){
  27.428 -            IOStream_print(io, "bucket %3d %3d %10p ", i,
  27.429 -                        table->buckets[i].count,
  27.430 -                        table->buckets[i].head);
  27.431 -            for(j = table->buckets[i].count; j>0; j--){
  27.432 -                IOStream_print(io, "+");
  27.433 -            }
  27.434 -            IOStream_print(io, "\n");
  27.435 -        }
  27.436 -    }
  27.437 -    HashTable_print(table, io); 
  27.438 -}
  27.439 -    
  27.440 -/** Print an entry in a table.
  27.441 - *
  27.442 - * @param entry to print
  27.443 - * @param arg a pointer to an IOStream to print to
  27.444 - * @return 0
  27.445 - */
  27.446 -static int print_entry(TableArg arg, HashTable *table, HTEntry *entry){
  27.447 -    IOStream *io = (IOStream*)arg.ptr;
  27.448 -    IOStream_print(io, " b=%4lx h=%08lx i=%08lx |-> e=%8p k=%8p v=%8p\n",
  27.449 -                entry->hashcode % table->buckets_n,
  27.450 -                entry->hashcode,
  27.451 -                entry->index,
  27.452 -                entry, entry->key, entry->value);
  27.453 -    return 0;
  27.454 -}
  27.455 -
  27.456 -/** Print a hash table.
  27.457 - *
  27.458 - * @param table to print
  27.459 - */
  27.460 -void HashTable_print(HashTable *table, IOStream *io){
  27.461 -    IOStream_print(io, "{\n");
  27.462 -    HashTable_map(table, print_entry, (TableArg){ ptr: io });
  27.463 -    IOStream_print(io, "}\n");
  27.464 -}
  27.465 -/*==========================================================================*/
  27.466 -
  27.467 -/** Get the next entry id to use for a table.
  27.468 - *
  27.469 - * @param table hash table
  27.470 - * @return non-zero entry id
  27.471 - */
  27.472 -static inline unsigned long get_next_id(HashTable *table){
  27.473 -    unsigned long id;
  27.474 -
  27.475 -    if(table->next_id == 0){
  27.476 -        table->next_id = 1;
  27.477 -    }
  27.478 -    id = table->next_id++;
  27.479 -    return id;
  27.480 -}
  27.481 -
  27.482 -/** Add an entry to the bucket for the
  27.483 - * given hashcode.
  27.484 - *
  27.485 - * @param table to insert in
  27.486 - * @param hashcode indicates the bucket
  27.487 - * @param key to add an entry for
  27.488 - * @param value to add an entry for
  27.489 - * @return entry on success, 0 on failure
  27.490 - */
  27.491 -inline HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value){
  27.492 -    HTEntry *entry = HTEntry_new(hashcode, key, value);
  27.493 -    if(entry){
  27.494 -        entry->index = get_next_id(table);
  27.495 -        push_on_bucket(table, hashcode, entry);
  27.496 -        table->entry_count++;
  27.497 -    }
  27.498 -    return entry;
  27.499 -}
  27.500 -
  27.501 -/** Move the front entry for a bucket to the correct point in the bucket order as
  27.502 - * defined by the order function. If this is called every time a new entry is added
  27.503 - * the bucket will be maintained in sorted order.
  27.504 - *
  27.505 - * @param table to modify
  27.506 - * @param hashcode indicates the bucket
  27.507 - * @param order entry comparison function
  27.508 - * @return 0 if an entry was moved, 1 if not
  27.509 - */
  27.510 -int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order){
  27.511 -    HTEntry *new_entry = NULL, *prev = NULL, *entry = NULL;
  27.512 -    HTBucket *bucket;
  27.513 -    int err = 1;
  27.514 -
  27.515 -    bucket = get_bucket(table, hashcode);
  27.516 -    new_entry = bucket->head;
  27.517 -    if(!new_entry || !new_entry->next) goto exit;
  27.518 -    for(entry = new_entry->next; entry; prev = entry, entry = entry->next){
  27.519 -        if(order(new_entry, entry) <= 0) break;
  27.520 -    }
  27.521 -    if(prev){
  27.522 -        err = 0;
  27.523 -        bucket->head = new_entry->next; 
  27.524 -        new_entry->next = entry;
  27.525 -        prev->next = new_entry;
  27.526 -    }
  27.527 -  exit:
  27.528 -    return err;
  27.529 -}
  27.530 -
  27.531 -/** Add an entry to a hashtable.
  27.532 - * The entry is added to the bucket for its key's hashcode.
  27.533 - *
  27.534 - * @param table to insert in
  27.535 - * @param key to add an entry for
  27.536 - * @param value to add an entry for
  27.537 - * @return entry on success, 0 on failure
  27.538 - */
  27.539 -inline HTEntry * HashTable_add(HashTable *table, void *key, void *value){
  27.540 -    return HashTable_add_entry(table, HashTable_key_hash(table, key), key, value);
  27.541 -}
  27.542 -
  27.543 -
  27.544 -/** Remove entries satisfying a test from the bucket for the
  27.545 - * given hashcode. 
  27.546 - *
  27.547 - * @param table to remove from
  27.548 - * @param hashcode indicates the bucket
  27.549 - * @param test_fn test to apply to elements
  27.550 - * @param arg first argument to calls to test_fn
  27.551 - * @return number of entries removed
  27.552 - */
  27.553 -inline int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
  27.554 -				  TableTestFn *test_fn, TableArg arg){
  27.555 -    HTBucket *bucket;
  27.556 -    HTEntry *entry, *prev = 0, *next;
  27.557 -    int removed_count = 0;
  27.558 -
  27.559 -    bucket = get_bucket(table, hashcode);
  27.560 -    for(entry = bucket->head; entry; entry = next){
  27.561 -        next = entry->next;
  27.562 -        if(test_fn(arg, table, entry)){
  27.563 -            if(prev){
  27.564 -                prev->next = next;
  27.565 -            } else {
  27.566 -                bucket->head = next;
  27.567 -            }
  27.568 -            bucket->count--;
  27.569 -            table->entry_count--;
  27.570 -            removed_count++;
  27.571 -            HashTable_free_entry(table, entry);
  27.572 -            entry = 0;
  27.573 -        }
  27.574 -        prev = entry;
  27.575 -    }
  27.576 -    return removed_count;
  27.577 -}
  27.578 -
  27.579 -/** Remove entries with a given key. 
  27.580 - *
  27.581 - * @param table to remove from
  27.582 - * @param key of entries to remove
  27.583 - * @return number of entries removed
  27.584 - */
  27.585 -inline int HashTable_remove(HashTable *table, void *key){
  27.586 -#if 1
  27.587 -    Hashcode hashcode;
  27.588 -    HTBucket *bucket;
  27.589 -    HTEntry *entry, *prev = 0, *next;
  27.590 -    int removed_count = 0;
  27.591 -
  27.592 -    hashcode = HashTable_key_hash(table, key);
  27.593 -    bucket = get_bucket(table, hashcode);
  27.594 -    for(entry = bucket->head; entry; entry = next){
  27.595 -        next = entry->next;
  27.596 -        if(HashTable_key_equal(table, key, entry->key)){
  27.597 -            if(prev){
  27.598 -                prev->next = next;
  27.599 -            } else {
  27.600 -                bucket->head = next;
  27.601 -            }
  27.602 -            bucket->count--;
  27.603 -            table->entry_count--;
  27.604 -            removed_count++;
  27.605 -            HashTable_free_entry(table, entry);
  27.606 -            entry = 0;
  27.607 -        }
  27.608 -        prev = entry;
  27.609 -    }
  27.610 -    return removed_count;
  27.611 -#else
  27.612 -    return HashTable_remove_entry(table, HashTable_key_hash(table, key),
  27.613 -				  has_key, (TableArg){ ptr: key});
  27.614 -#endif
  27.615 -}
  27.616 -
  27.617 -/** Remove (and free) all the entries in a bucket.
  27.618 - *
  27.619 - * @param bucket to clear
  27.620 - */
  27.621 -static inline void bucket_clear(HashTable *table, HTBucket *bucket){
  27.622 -    HTEntry *entry, *next;
  27.623 -
  27.624 -    for(entry = bucket->head; entry; entry = next){
  27.625 -        next = entry->next;
  27.626 -        HashTable_free_entry(table, entry);
  27.627 -    }
  27.628 -    bucket->head = 0;
  27.629 -    table->entry_count -= bucket->count;
  27.630 -    bucket->count = 0;
  27.631 -}
  27.632 -
  27.633 -/** Remove (and free) all the entries in a table.
  27.634 - *
  27.635 - * @param table to clear
  27.636 - */
  27.637 -void HashTable_clear(HashTable *table){
  27.638 -    int i, n = table->buckets_n;
  27.639 -
  27.640 -    for(i=0; i<n; i++){
  27.641 -        bucket_clear(table, table->buckets + i);
  27.642 -    }
  27.643 -}
    28.1 --- a/tools/xfrd/hash_table.h	Sun Nov 21 20:41:00 2004 +0000
    28.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.3 @@ -1,294 +0,0 @@
    28.4 -/*
    28.5 - * Copyright (C) 2001 - 2004 Mike Wray <mike.wray@hp.com>
    28.6 - *
    28.7 - * This library is free software; you can redistribute it and/or modify
    28.8 - * it under the terms of the GNU Lesser General Public License as published by
    28.9 - * the Free Software Foundation; either version 2.1 of the License, or
   28.10 - * (at your option) any later version.
   28.11 - *
   28.12 - * This library is distributed in the hope that it will be useful,
   28.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.15 - * GNU Lesser General Public License for more details.
   28.16 - *
   28.17 - * You should have received a copy of the GNU Lesser General Public License
   28.18 - * along with this library; if not, write to the Free Software
   28.19 - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   28.20 - */
   28.21 -
   28.22 -#ifndef _XUTIL_HASH_TABLE_H_
   28.23 -#define _XUTIL_HASH_TABLE_H_
   28.24 -
   28.25 -#include "iostream.h"
   28.26 -
   28.27 -typedef unsigned long Hashcode;
   28.28 -
   28.29 -/** Type used to pass parameters to table functions. */
   28.30 -typedef union TableArg {
   28.31 -    unsigned long ul;
   28.32 -    void *ptr;
   28.33 -} TableArg;
   28.34 -
   28.35 -/** An entry in a bucket list. */
   28.36 -typedef struct HTEntry {
   28.37 -    /** Hashcode of the entry's key. */
   28.38 -    Hashcode hashcode;
   28.39 -    /** Identifier for this entry in the table. */
   28.40 -    int index;
   28.41 -    /** The key for this entry. */
   28.42 -    void *key;
   28.43 -    /** The value in this entry. */
   28.44 -    void *value;
   28.45 -    /** The next entry in the list. */
   28.46 -    struct HTEntry *next;
   28.47 -} HTEntry;
   28.48 -
   28.49 -/** A bucket in a rule table. */
   28.50 -typedef struct HTBucket {
   28.51 -    /** Number of entries in the bucket. */
   28.52 -    int count;
   28.53 -    /** First entry in the bucket (may be null). */
   28.54 -    HTEntry *head;
   28.55 -} HTBucket;
   28.56 -
   28.57 -/** Default number of buckets in a hash table.
   28.58 - * You want enough buckets so the lists in the buckets will typically be short.
   28.59 - * It's a good idea if this is prime, since that will help to spread hashcodes
   28.60 - * around the table.
   28.61 - */
   28.62 -//#define HT_BUCKETS_N 1
   28.63 -//#define HT_BUCKETS_N 3
   28.64 -//#define HT_BUCKETS_N 7
   28.65 -//#define HT_BUCKETS_N 17
   28.66 -//#define HT_BUCKETS_N 97
   28.67 -//#define HT_BUCKETS_N 211
   28.68 -//#define HT_BUCKETS_N 401
   28.69 -#define HT_BUCKETS_N 1021
   28.70 -
   28.71 -typedef struct HashTable HashTable;
   28.72 -
   28.73 -/** Type for a function used to select table entries. */
   28.74 -typedef int TableTestFn(TableArg arg, HashTable *table, HTEntry *entry);
   28.75 -
   28.76 -/** Type for a function to map over table entries. */
   28.77 -typedef int TableMapFn(TableArg arg, HashTable *table, HTEntry *entry);
   28.78 -
   28.79 -/** Type for a function to free table entries. */
   28.80 -typedef void TableFreeFn(HashTable *table, HTEntry *entry);
   28.81 -
   28.82 -/** Type for a function to hash table keys. */
   28.83 -typedef Hashcode TableHashFn(void *key);
   28.84 -
   28.85 -/** Type for a function to test table keys for equality. */
   28.86 -typedef int TableEqualFn(void *key1, void *key2);
   28.87 -
   28.88 -/** Type for a function to order table entries. */
   28.89 -typedef int TableOrderFn(HTEntry *e1, HTEntry *e2);
   28.90 -
   28.91 -/** General hash table.
   28.92 - * A hash table with a list in each bucket.
   28.93 - * Functions can be supplied for freeing entries, hashing keys, and comparing keys.
   28.94 - * These all default to 0, when default behaviour treating keys as integers is used.
   28.95 - */
   28.96 -struct HashTable {
   28.97 -    /** Flag indicating whether the table has been initialised. */
   28.98 -    int init_done;
   28.99 -    /** Next value for the id field in inserted rules. */
  28.100 -    unsigned long next_id;
  28.101 -    /** Number of buckets in the bucket array. */
  28.102 -    int buckets_n;
  28.103 -    /** Array of buckets, each with its own list. */
  28.104 -    HTBucket *buckets;
  28.105 -    /** Number of entries in the table. */
  28.106 -    int entry_count;
  28.107 -    /** Function to free keys and values in entries. */
  28.108 -    TableFreeFn *entry_free_fn;
  28.109 -    /** Function to hash keys. */
  28.110 -    TableHashFn *key_hash_fn;
  28.111 -    /** Function to compare keys for equality. */
  28.112 -    TableEqualFn *key_equal_fn;
  28.113 -    /** Place for the user of the table to hang extra data. */
  28.114 -    void *user_data;
  28.115 -};
  28.116 -
  28.117 -extern HashTable *HashTable_new(int bucket_n);
  28.118 -extern void HashTable_free(HashTable *table);
  28.119 -extern HTEntry * HTEntry_new(Hashcode hashcode, void *key, void *value);
  28.120 -extern void HTEntry_free(HTEntry *entry);
  28.121 -extern int HashTable_set_bucket_n(HashTable *table, int bucket_n);
  28.122 -extern void HashTable_clear(HashTable *table);
  28.123 -extern HTEntry * HashTable_add_entry(HashTable *table, Hashcode hashcode, void *key, void *value);
  28.124 -extern HTEntry * HashTable_get_entry(HashTable *table, void *key);
  28.125 -extern HTEntry * HashTable_add(HashTable *table, void *key, void *value);
  28.126 -extern void * HashTable_get(HashTable *table, void *key);
  28.127 -extern int HashTable_remove(HashTable *table, void *key);
  28.128 -extern HTEntry * HashTable_find_entry(HashTable *table, Hashcode hashcode,
  28.129 -                                      TableTestFn *test_fn, TableArg arg);
  28.130 -extern int HashTable_remove_entry(HashTable *table, Hashcode hashcode,
  28.131 -                                   TableTestFn *test_fn, TableArg arg);
  28.132 -//extern int HashTable_map(HashTable *table, TableMapFn *map_fn, TableArg arg);
  28.133 -extern void HashTable_print(HashTable *table, IOStream *out);
  28.134 -extern int HashTable_set_buckets_n(HashTable *table, int buckets_n);
  28.135 -extern int HashTable_adjust(HashTable *table, int buckets_min);
  28.136 -extern void pseudo_des(unsigned long *pleft, unsigned long *pright);
  28.137 -extern Hashcode hash_string(char *s);
  28.138 -
  28.139 -extern int HashTable_order_bucket(HashTable *table, Hashcode hashcode, TableOrderFn *order);
  28.140 -
  28.141 -/** Control whether to use hashing based on DES or simple
  28.142 - * hashing. DES hashing is `more random' but much more expensive.
  28.143 - */
  28.144 -#define HASH_PSEUDO_DES 0
  28.145 -
  28.146 -/** Hash a long using a quick and dirty linear congruential random number generator.
  28.147 - *  See `Numerical Recipes in C', Chapter 7, "An Even Quicker Generator".
  28.148 - *
  28.149 - * @param a value to hash
  28.150 - * @return hashed input
  28.151 - */
  28.152 -static inline unsigned long lcrng_hash(unsigned long a){
  28.153 -    return (1664525L * a + 1013904223L);
  28.154 -}
  28.155 -
  28.156 -/** Hash an unsigned long.
  28.157 - *
  28.158 - * @param a input to hash
  28.159 - * @return hashcode
  28.160 - */
  28.161 -static inline Hashcode hash_ul(unsigned long a){
  28.162 -#if HASH_PSEUDO_DES
  28.163 -    unsigned long left = a;
  28.164 -    unsigned long right = 0L;
  28.165 -    pseudo_des(&left, &right);
  28.166 -    return right;
  28.167 -#else
  28.168 -    a = lcrng_hash(a);
  28.169 -    a = lcrng_hash(a);
  28.170 -    return a;
  28.171 -#endif
  28.172 -}
  28.173 -
  28.174 -/** Hash two unsigned longs together.
  28.175 - *
  28.176 - * @param a input to hash
  28.177 - * @param b input to hash
  28.178 - * @return hashcode
  28.179 - */
  28.180 -static inline Hashcode hash_2ul(unsigned long a, unsigned long b){
  28.181 -#if HASH_PSEUDO_DES
  28.182 -    unsigned long left = a;
  28.183 -    unsigned long right = b;
  28.184 -    pseudo_des(&left, &right);
  28.185 -    return right;
  28.186 -#else
  28.187 -    a = lcrng_hash(a);
  28.188 -    a ^= b;
  28.189 -    a = lcrng_hash(a);
  28.190 -    return a;
  28.191 -#endif
  28.192 -}
  28.193 -
  28.194 -/** Hash a hashcode and an unsigned long together.
  28.195 - *
  28.196 - * @param a input hashcode
  28.197 - * @param b input to hash
  28.198 - * @return hashcode
  28.199 - */
  28.200 -static inline Hashcode hash_hul(Hashcode a, unsigned long b){
  28.201 -#if HASH_PSEUDO_DES
  28.202 -    unsigned long left = a;
  28.203 -    unsigned long right = b;
  28.204 -    pseudo_des(&left, &right);
  28.205 -    return right;
  28.206 -#else
  28.207 -    a ^= b;
  28.208 -    a = lcrng_hash(a);
  28.209 -    return a;
  28.210 -#endif
  28.211 -}
  28.212 -
  28.213 -/** Macro to declare variables for HashTable_for_each() to use.
  28.214 - *
  28.215 - * @param entry variable that is set to entries in the table
  28.216 - */
  28.217 -#define HashTable_for_decl(entry) \
  28.218 -  HashTable *_var_table; \
  28.219 -  HTBucket *_var_bucket; \
  28.220 -  HTBucket *_var_end; \
  28.221 -  HTEntry *_var_next; \
  28.222 -  HTEntry *entry
  28.223 -
  28.224 -/** Macro to iterate over the entries in a hashtable.
  28.225 - * Must be in a scope where HashTable_for_decl() has been used to declare
  28.226 - * variables for it to use.
  28.227 - * The variable 'entry' is iterated over entries in the table.
  28.228 - * The code produced is syntactically a loop, so it must be followed by
  28.229 - * a loop body, typically some statements in braces:
  28.230 - * HashTable_for_each(entry, table){ ...loop body... }
  28.231 - *
  28.232 - * HashTable_for_each() and HashTable_for_decl() cannot be used for nested
  28.233 - * loops as variables will clash.
  28.234 - *
  28.235 - * @note The simplest way to code a direct loop over the entries in a hashtable
  28.236 - * is to use a loop over the buckets, with a nested loop over the entries
  28.237 - * in a bucket. Using this approach in a macro means the macro contains
  28.238 - * an opening brace, and calls to it must be followed by 2 braces!
  28.239 - * To avoid this the code has been restructured so that it is a for loop.
  28.240 - * So that statements could be used in the test expression of the for loop,
  28.241 - * we have used the gcc statement expression extension ({ ... }).
  28.242 - *
  28.243 - * @param entry variable to iterate over the entries
  28.244 - * @param table to iterate over (non-null)
  28.245 - */
  28.246 -#define HashTable_for_each(entry, table) \
  28.247 -  _var_table = table; \
  28.248 -  _var_bucket = _var_table->buckets; \
  28.249 -  _var_end = _var_bucket + _var_table->buckets_n; \
  28.250 -  for(entry=0, _var_next=0; \
  28.251 -      ({ if(_var_next){ \
  28.252 -             entry = _var_next; \
  28.253 -             _var_next = entry->next; \
  28.254 -          } else { \
  28.255 -             while(_var_bucket < _var_end){ \
  28.256 -                 entry = _var_bucket->head; \
  28.257 -                 _var_bucket++; \
  28.258 -                 if(entry){ \
  28.259 -                      _var_next = entry->next; \
  28.260 -                      break; \
  28.261 -                 } \
  28.262 -             } \
  28.263 -          }; \
  28.264 -         entry; }); \
  28.265 -      entry = _var_next )
  28.266 -
  28.267 -/** Map a function over the entries in a table.
  28.268 - * Mapping stops when the function returns a non-zero value.
  28.269 - * Uses the gcc statement expression extension ({ ... }).
  28.270 - *
  28.271 - * @param table to map over
  28.272 - * @param fn function to apply to entries
  28.273 - * @param arg first argument to call the function with
  28.274 - * @return 0 if fn always returned 0, first non-zero value otherwise
  28.275 - */
  28.276 -#define HashTable_map(table, fn, arg) \
  28.277 -  ({ HashTable_for_decl(_var_entry); \
  28.278 -    TableArg _var_arg = arg; \
  28.279 -    int _var_value = 0; \
  28.280 -    HashTable_for_each(_var_entry, table){ \
  28.281 -        if((_var_value = fn(_var_arg, _var_table, _var_entry))) break; \
  28.282 -    } \
  28.283 -    _var_value; })
  28.284 -
  28.285 -/** Cast x to the type for a key or value in a hash table.
  28.286 - * This avoids compiler warnings when using short integers
  28.287 - * as keys or values (especially on 64-bit platforms).
  28.288 - */
  28.289 -#define HKEY(x) ((void*)(unsigned long)(x))
  28.290 -
  28.291 -/** Cast x from the type for a key or value in a hash table.
  28.292 - * to an unsigned long. This avoids compiler warnings when using
  28.293 - * short integers as keys or values (especially on 64-bit platforms).
  28.294 - */
  28.295 -#define HVAL(x) ((unsigned long)(x))
  28.296 -
  28.297 -#endif /* !_XUTIL_HASH_TABLE_H_ */
    29.1 --- a/tools/xfrd/lexis.c	Sun Nov 21 20:41:00 2004 +0000
    29.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    29.3 @@ -1,93 +0,0 @@
    29.4 -/*
    29.5 - *
    29.6 - * This library is free software; you can redistribute it and/or modify
    29.7 - * it under the terms of the GNU Lesser General Public License as
    29.8 - * published by the Free Software Foundation; either version 2.1 of the
    29.9 - * License, or  (at your option) any later version. This library is 
   29.10 - * distributed in the  hope that it will be useful, but WITHOUT ANY
   29.11 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   29.12 - * FITNESS FOR A PARTICULAR PURPOSE.
   29.13 - * See the GNU Lesser General Public License for more details.
   29.14 - *
   29.15 - * You should have received a copy of the GNU Lesser General Public License
   29.16 - * along with this library; if not, write to the Free Software Foundation,
   29.17 - * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   29.18 - */
   29.19 -
   29.20 -/** @file
   29.21 - * Lexical analysis.
   29.22 - */
   29.23 -
   29.24 -#include "sys_string.h"
   29.25 -#include "lexis.h"
   29.26 -#include <errno.h>
   29.27 -
   29.28 -/** Check if a value lies in a (closed) range.
   29.29 - *
   29.30 - * @param x value to test
   29.31 - * @param lo low end of the range
   29.32 - * @param hi high end of the range
   29.33 - * @return 1 if x is in the interval [lo, hi], 0 otherwise
   29.34 - */
   29.35 -inline static int in_range(int x, int lo, int hi){
   29.36 -    return (lo <= x) && (x <= hi);
   29.37 -}
   29.38 -
   29.39 -/** Determine if a string is an (unsigned) decimal number.
   29.40 - * 
   29.41 - * @param s pointer to characters to test
   29.42 - * @param n length of string
   29.43 - * @return 1 if s is a decimal number, 0 otherwise.
   29.44 - */
   29.45 -int is_decimal_number(const char *s, int n){
   29.46 -    int i;
   29.47 -    if(n <= 0)return 0;
   29.48 -    for(i = 0; i < n; i++){
   29.49 -        if(!in_decimal_digit_class(s[i])) return 0;
   29.50 -    }
   29.51 -    return 1;
   29.52 -}
   29.53 -
   29.54 -/** Determine if a string is a hex number.
   29.55 - * Hex numbers are 0, or start with 0x or 0X followed
   29.56 - * by a non-zero number of hex digits (0-9,a-f,A-F).
   29.57 - * 
   29.58 - * @param s pointer to characters to test
   29.59 - * @param n length of string
   29.60 - * @return 1 if s is a hex number, 0 otherwise.
   29.61 - */
   29.62 -int is_hex_number(const char *s, int n){
   29.63 -    int i;
   29.64 -    if(n <= 0) return 0;
   29.65 -    if(n == 1){
   29.66 -        return s[0]=='0';
   29.67 -    }
   29.68 -    if(n <= 3) return 0;
   29.69 -    if(s[0] != '0' || (s[1] != 'x' && s[1] != 'X')) return 0;
   29.70 -    for(i = 2; i < n; i++){
   29.71 -        if(!in_hex_digit_class(s[i])) return 0;
   29.72 -    }
   29.73 -    return 1;
   29.74 -}
   29.75 -
   29.76 -/** Test if a string matches a keyword.
   29.77 - * The comparison is case-insensitive.
   29.78 - * The comparison fails if either argument is null.
   29.79 - *
   29.80 - * @param s string
   29.81 - * @param k keyword
   29.82 - * @return 1 if they match, 0 otherwise
   29.83 - */
   29.84 -int is_keyword(const char *s, const char *k){
   29.85 -  return s && k && !strcasecmp(s, k);
   29.86 -}
   29.87 -
   29.88 -/** Test if a string matches a character.
   29.89 - *
   29.90 - * @param s string
   29.91 - * @param c character (non-null)
   29.92 - * @return 1 if s contains exactly c, 0 otherwise
   29.93 - */
   29.94 -int is_keychar(const char *s, char c){
   29.95 -  return c && (s[0] == c) && !s[1];
   29.96 -}
    30.1 --- a/tools/xfrd/lexis.h	Sun Nov 21 20:41:00 2004 +0000
    30.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    30.3 @@ -1,127 +0,0 @@
    30.4 -/*
    30.5 - *
    30.6 - * This library is free software; you can redistribute it and/or modify
    30.7 - * it under the terms of the GNU Lesser General Public License as
    30.8 - * published by the Free Software Foundation; either version 2.1 of the
    30.9 - * License, or  (at your option) any later version. This library is 
   30.10 - * distributed in the  hope that it will be useful, but WITHOUT ANY
   30.11 - * WARRANTY; without even the implied warranty of MERCHANTABILITY or
   30.12 - * FITNESS FOR A PARTICULAR PURPOSE.
   30.13 - * See the GNU Lesser General Public License for more details.
   30.14 - *
   30.15 - * You should have received a copy of the GNU Lesser General Public License
   30.16 - * along with this library; if not, write to the Free Software Foundation,
   30.17 - * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   30.18 - */
   30.19 -
   30.20 -#ifndef _XUTIL_LEXIS_H_
   30.21 -#define _XUTIL_LEXIS_H_
   30.22 -
   30.23 -#include "sys_string.h"
   30.24 -
   30.25 -#ifdef __KERNEL__
   30.26 -#  include <linux/ctype.h>
   30.27 -#else
   30.28 -#  include <ctype.h>
   30.29 -#endif
   30.30 -
   30.31 -/** @file
   30.32 - * Lexical analysis.
   30.33 - */
   30.34 -
   30.35 -/** Class of characters treated as space. */
   30.36 -#define space_class ((char []){ '\n', '\r', '\t', ' ', '\f' , 0 })
   30.37 -
   30.38 -/** Class of separator characters. */
   30.39 -#define sep_class "{}()<>[]@!;"
   30.40 -
   30.41 -#define comment_class "#"
   30.42 -
   30.43 -/** Determine if a character is in a given class.
   30.44 - * 
   30.45 - * @param c character to test
   30.46 - * @param s null-terminated string of characters in the class
   30.47 - * @return 1 if c is in the class, 0 otherwise.
   30.48 - */
   30.49 -static inline int in_class(int c, const char *s){
   30.50 -  return s && (strchr(s, c) != 0);
   30.51 -}
   30.52 -
   30.53 -/** Determine if a character is in the space class.
   30.54 - * 
   30.55 - * @param c character to test
   30.56 - * @return 1 if c is in the class, 0 otherwise.
   30.57 - */
   30.58 -static inline int in_space_class(int c){
   30.59 -    return in_class(c, space_class);
   30.60 -}
   30.61 -
   30.62 -static inline int in_comment_class(int c){
   30.63 -    return in_class(c, comment_class);
   30.64 -}
   30.65 -
   30.66 -/** Determine if a character is in the separator class.
   30.67 - * Separator characters terminate tokens, and do not need space
   30.68 - * to separate them.
   30.69 - * 
   30.70 - * @param c character to test
   30.71 - * @return 1 if c is in the class, 0 otherwise.
   30.72 - */
   30.73 -static inline int in_sep_class(int c){
   30.74 -    return in_class(c, sep_class);
   30.75 -}
   30.76 -
   30.77 -/** Determine if a character is in the alpha class.
   30.78 - * 
   30.79 - * @param c character to test
   30.80 - * @return 1 if c is in the class, 0 otherwise.
   30.81 - */
   30.82 -static inline int in_alpha_class(int c){
   30.83 -    return isalpha(c);
   30.84 -}
   30.85 -
   30.86 -/** Determine if a character is in the octal digit class.
   30.87 - * 
   30.88 - * @param c character to test
   30.89 - * @return 1 if c is in the class, 0 otherwise.
   30.90 - */
   30.91 -static inline int in_octal_digit_class(int c){
   30.92 -    return '0' <= c && c <= '7';
   30.93 -}
   30.94 -
   30.95 -/** Determine if a character is in the decimal digit class.
   30.96 - * 
   30.97 - * @param c character to test
   30.98 - * @return 1 if c is in the class, 0 otherwise.
   30.99 - */
  30.100 -static inline int in_decimal_digit_class(int c){
  30.101 -    return isdigit(c);
  30.102 -}
  30.103 -
  30.104 -/** Determine if a character is in the hex digit class.
  30.105 - * 
  30.106 - * @param c character to test
  30.107 - * @return 1 if c is in the class, 0 otherwise.
  30.108 - */
  30.109 -static inline int in_hex_digit_class(int c){
  30.110 -    return isdigit(c) || in_class(c, "abcdefABCDEF");
  30.111 -}
  30.112 -
  30.113 -
  30.114 -static inline int in_string_quote_class(int c){
  30.115 -    return in_class(c, "'\"");
  30.116 -}
  30.117 -
  30.118 -static inline int in_printable_class(int c){
  30.119 -    return ('A' <= c && c <= 'Z')
  30.120 -        || ('a' <= c && c <= 'z')
  30.121 -        || ('0' <= c && c <= '9')
  30.122 -        || in_class(c, "!$%&*+,-./:;<=>?@^_`{|}~");
  30.123 -}
  30.124 -
  30.125 -extern int is_decimal_number(const char *s, int n);
  30.126 -extern int is_hex_number(const char *s, int n);
  30.127 -extern int is_keyword(const char *s, const char *k);
  30.128 -extern int is_keychar(const char *s, char c);
  30.129 -
  30.130 -#endif /* !_XUTIL_LEXIS_H_ */
    31.1 --- a/tools/xfrd/sxpr.c	Sun Nov 21 20:41:00 2004 +0000
    31.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.3 @@ -1,950 +0,0 @@
    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 -    int ok = 0;
  31.764 -    ok = CONSP(obj) && objequal(CAR(obj), name);
  31.765 -    return ok;
  31.766 -}
  31.767 -
  31.768 -/** Get the attributes of an sxpr.
  31.769 - * 
  31.770 - * @param obj sxpr
  31.771 - * @return attributes
  31.772 - */
  31.773 -Sxpr sxpr_attributes(Sxpr obj){
  31.774 -    Sxpr val = ONULL;
  31.775 -    if(CONSP(obj)){
  31.776 -        obj = CDR(obj);
  31.777 -        if(CONSP(obj)){
  31.778 -            obj = CAR(obj);
  31.779 -            if(sxprp(obj, intern("@"))){
  31.780 -                val = CDR(obj);
  31.781 -            }
  31.782 -        }
  31.783 -    }
  31.784 -    return val;
  31.785 -}
  31.786 -
  31.787 -Sxpr sxpr_attribute(Sxpr obj, Sxpr key, Sxpr def){
  31.788 -    Sxpr val = ONONE;
  31.789 -    val = assoc(sxpr_attributes(obj), key);
  31.790 -    if(CONSP(val) && CONSP(CDR(val))){
  31.791 -        val = CADR(def);
  31.792 -    } else {
  31.793 -        val = def;
  31.794 -    }
  31.795 -    return val;
  31.796 -}
  31.797 -
  31.798 -/** Get the children of an sxpr.
  31.799 - * 
  31.800 - * @param obj sxpr
  31.801 - * @return children
  31.802 - */
  31.803 -Sxpr sxpr_children(Sxpr obj){
  31.804 -    Sxpr val = ONULL;
  31.805 -    if(CONSP(obj)){
  31.806 -        val = CDR(obj);
  31.807 -        if(CONSP(val) && sxprp(CAR(val), intern("@"))){
  31.808 -            val = CDR(val);
  31.809 -        }
  31.810 -    }
  31.811 -    return val;
  31.812 -}
  31.813 -
  31.814 -Sxpr sxpr_child(Sxpr obj, Sxpr name, Sxpr def){
  31.815 -    Sxpr val = ONONE;
  31.816 -    Sxpr l;
  31.817 -    for(l = sxpr_children(obj); CONSP(l); l = CDR(l)){
  31.818 -        if(sxprp(CAR(l), name)){
  31.819 -            val = CAR(l);
  31.820 -            break;
  31.821 -        }
  31.822 -    }
  31.823 -    if(NONEP(val)) val = def;
  31.824 -    return val;
  31.825 -}
  31.826 -
  31.827 -Sxpr sxpr_child0(Sxpr obj, Sxpr def){
  31.828 -    Sxpr val = ONONE;
  31.829 -    Sxpr l = sxpr_children(obj);
  31.830 -    if(CONSP(l)){
  31.831 -        val = CAR(l);
  31.832 -    } else {
  31.833 -        val = def;
  31.834 -    }
  31.835 -    return val;
  31.836 -}
  31.837 -
  31.838 -Sxpr sxpr_childN(Sxpr obj, int n, Sxpr def){
  31.839 -    Sxpr val = def;
  31.840 -    Sxpr l;
  31.841 -    int i;
  31.842 -    for (i = 0, l = sxpr_children(obj); CONSP(l); i++, l = CDR(l)){
  31.843 -        if(i == n){
  31.844 -            val = CAR(l);
  31.845 -            break;
  31.846 -        }
  31.847 -    }
  31.848 -    return val;
  31.849 -}
  31.850 -    
  31.851 -Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def){
  31.852 -    Sxpr val = ONONE;
  31.853 -    val = sxpr_child(obj, name, ONONE);
  31.854 -    if(NONEP(val)){
  31.855 -        val = def;
  31.856 -    } else {
  31.857 -        val = sxpr_child0(val, def);
  31.858 -    }
  31.859 -    return val;
  31.860 -}
  31.861 -
  31.862 -/** Table of interned symbols. Indexed by symbol name. */
  31.863 -static HashTable *symbols = NULL;
  31.864 -
  31.865 -/** Hash function for entries in the symbol table.
  31.866 - *
  31.867 - * @param key to hash
  31.868 - * @return hashcode
  31.869 - */
  31.870 -static Hashcode sym_hash_fn(void *key){
  31.871 -    return hash_string((char*)key);
  31.872 -}
  31.873 -
  31.874 -/** Key equality function for the symbol table.
  31.875 - *
  31.876 - * @param x to compare
  31.877 - * @param y to compare
  31.878 - * @return 1 if equal, 0 otherwise
  31.879 - */
  31.880 -static int sym_equal_fn(void *x, void *y){
  31.881 -    return !strcmp((char*)x, (char*)y);
  31.882 -}
  31.883 -
  31.884 -/** Entry free function for the symbol table.
  31.885 - *
  31.886 - * @param table the entry is in
  31.887 - * @param entry being freed
  31.888 - */
  31.889 -static void sym_free_fn(HashTable *table, HTEntry *entry){
  31.890 -    if(entry){
  31.891 -	objfree(((ObjAtom*)entry->value)->name);
  31.892 -	HTEntry_free(entry);
  31.893 -    }
  31.894 -}
  31.895 -	
  31.896 -/** Initialize the symbol table.
  31.897 - *
  31.898 - * @return 0 on sucess, error code otherwise
  31.899 - */
  31.900 -static int init_symbols(void){
  31.901 -    symbols = HashTable_new(100);
  31.902 -    if(symbols){
  31.903 -        symbols->key_hash_fn = sym_hash_fn;
  31.904 -        symbols->key_equal_fn = sym_equal_fn;
  31.905 -	symbols->entry_free_fn = sym_free_fn;
  31.906 -        return 0;
  31.907 -    }
  31.908 -    return -1;
  31.909 -}
  31.910 -
  31.911 -/** Cleanup the symbol table. Frees the table and all its symbols.
  31.912 - */
  31.913 -void cleanup_symbols(void){
  31.914 -    HashTable_free(symbols);
  31.915 -    symbols = NULL;
  31.916 -}
  31.917 -
  31.918 -/** Get the interned symbol with the given name.
  31.919 - * No new symbol is created.
  31.920 - *
  31.921 - * @return symbol or null
  31.922 - */
  31.923 -Sxpr get_symbol(char *sym){
  31.924 -    HTEntry *entry;
  31.925 -    if(!symbols){
  31.926 -	if(init_symbols()) return ONOMEM;
  31.927 -	return ONULL;
  31.928 -    }
  31.929 -    entry = HashTable_get_entry(symbols, sym);
  31.930 -    if(entry){
  31.931 -        return OBJP(T_ATOM, entry->value);
  31.932 -    } else {
  31.933 -        return ONULL;
  31.934 -    }
  31.935 -}
  31.936 -
  31.937 -/** Get the interned symbol with the given name.
  31.938 - * Creates a new symbol if necessary.
  31.939 - *
  31.940 - * @return symbol
  31.941 - */
  31.942 -Sxpr intern(char *sym){
  31.943 -    Sxpr symbol = get_symbol(sym);
  31.944 -    if(NULLP(symbol)){
  31.945 -	if(!symbols) return ONOMEM;
  31.946 -        symbol = atom_new(sym);
  31.947 -        if(!NOMEMP(symbol)){
  31.948 -	    OBJ_ATOM(symbol)->interned = TRUE;
  31.949 -            HashTable_add(symbols, atom_name(symbol), get_ptr(symbol));
  31.950 -        }
  31.951 -    }
  31.952 -    return symbol;
  31.953 -}
    32.1 --- a/tools/xfrd/sxpr.h	Sun Nov 21 20:41:00 2004 +0000
    32.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.3 @@ -1,414 +0,0 @@
    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 _XUTIL_SXPR_H_
   32.20 -#define _XUTIL_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_childN(Sxpr obj, int n, Sxpr def);
  32.357 -Sxpr sxpr_child0(Sxpr obj, Sxpr def);
  32.358 -Sxpr sxpr_child_value(Sxpr obj, Sxpr name, Sxpr def);
  32.359 -
  32.360 -/** Create a new atom.
  32.361 - *
  32.362 - * @param s atom name
  32.363 - * @return new atom
  32.364 - */
  32.365 -static inline Sxpr mkatom(char *s){
  32.366 -    return atom_new(s);
  32.367 -}
  32.368 -
  32.369 -/** Create a new string sxpr.
  32.370 - *
  32.371 - * @param s string bytes (copied)
  32.372 - * @return new string
  32.373 - */
  32.374 -static inline Sxpr mkstring(char *s){
  32.375 -    return string_new(s);
  32.376 -}
  32.377 -
  32.378 -/** Create an integer sxpr.
  32.379 - *
  32.380 - * @param i value
  32.381 - * @return sxpr
  32.382 - */
  32.383 -static inline Sxpr mkint(int i){
  32.384 -    return OBJI(T_UINT, i);
  32.385 -}
  32.386 -
  32.387 -/** Create a boolean sxpr.
  32.388 - *
  32.389 - * @param b value
  32.390 - * @return sxpr
  32.391 - */
  32.392 -static inline Sxpr mkbool(int b){
  32.393 -    return OBJI(T_BOOL, (b ? 1 : 0));
  32.394 -}
  32.395 -
  32.396 -/* Constants used in parsing and printing. */
  32.397 -#define k_list_open    "("
  32.398 -#define c_list_open    '('
  32.399 -#define k_list_close   ")"
  32.400 -#define c_list_close   ')'
  32.401 -#define k_true         "true"
  32.402 -#define k_false        "false"
  32.403 -
  32.404 -#define c_var          '$'
  32.405 -#define c_escape       '\\'
  32.406 -#define c_single_quote '\''
  32.407 -#define c_double_quote '"'
  32.408 -#define c_string_open  c_double_quote
  32.409 -#define c_string_close c_double_quote
  32.410 -#define c_data_open    '['
  32.411 -#define c_data_close   ']'
  32.412 -#define c_binary       '*'
  32.413 -#define c_eval         '!'
  32.414 -#define c_concat_open  '{'
  32.415 -#define c_concat_close '}'
  32.416 -
  32.417 -#endif /* ! _XUTIL_SXPR_H_ */
    33.1 --- a/tools/xfrd/sxpr_parser.c	Sun Nov 21 20:41:00 2004 +0000
    33.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.3 @@ -1,943 +0,0 @@
    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 -#include "enum.h"
   33.21 -
   33.22 -/** @file
   33.23 - * Sxpr parsing.
   33.24 - *
   33.25 - * So that the parser does not leak memory, all sxprs constructed by
   33.26 - * the parser must be freed on error.  On successful parse the sxpr
   33.27 - * returned becomes the responsibility of the caller.
   33.28 - *
   33.29 - * @author Mike Wray <mike.wray@hpl.hp.com>
   33.30 - */
   33.31 -
   33.32 -#define dprintf(fmt, args...) IOStream_print(iostdout, "[DEBUG] %s" fmt, __FUNCTION__, ##args)
   33.33 -#define printf(fmt, args...)   IOStream_print(iostdout, fmt, ##args)
   33.34 -
   33.35 -static void reset(Parser *z);
   33.36 -static int inputchar(Parser *p, char c);
   33.37 -static int savechar(Parser *p, char c);
   33.38 -extern void parse_error(Parser *in);
   33.39 -extern void parse_error_id(Parser *in, ParseErrorId id);
   33.40 -
   33.41 -static int begin_start(Parser *p, char c);
   33.42 -static int state_start(Parser *p, char c);
   33.43 -static int end_start(Parser *p);
   33.44 -
   33.45 -static int begin_comment(Parser *p, char c);
   33.46 -static int state_comment(Parser *p, char c);
   33.47 -static int end_comment(Parser *p);
   33.48 -
   33.49 -static int begin_string(Parser *p, char c);
   33.50 -static int state_string(Parser *p, char c);
   33.51 -static int end_string(Parser *p);
   33.52 -static int state_escape(Parser *p, char c);
   33.53 -static int state_octal(Parser *p, char c);
   33.54 -static int state_hex(Parser *p, char c);
   33.55 -
   33.56 -static int begin_atom(Parser *p, char c);
   33.57 -static int state_atom(Parser *p, char c);
   33.58 -static int end_atom(Parser *p);
   33.59 -
   33.60 -static int state_list(Parser *p, char c);
   33.61 -static int begin_list(Parser *p, char c);
   33.62 -static int end_list(Parser *p);
   33.63 -
   33.64 -/** Print a parse error.
   33.65 - *
   33.66 - * @param in parser
   33.67 - * @param msg format followed by printf arguments
   33.68 - */
   33.69 -void eprintf(Parser *in, char *msg, ...){
   33.70 -    va_list args;
   33.71 -    if(in->error_out){
   33.72 -        va_start(args, msg);
   33.73 -        IOStream_vprint(in->error_out, msg, args);
   33.74 -        va_end(args);
   33.75 -    }
   33.76 -}
   33.77 -
   33.78 -/** Print a parse warning.
   33.79 - *
   33.80 - * @param in parser
   33.81 - * @param msg format followed by printf arguments
   33.82 - */
   33.83 -void wprintf(Parser *in, char *msg, ...){
   33.84 -    va_list args;
   33.85 -    if(in->error_out){
   33.86 -        va_start(args, msg);
   33.87 -        IOStream_vprint(in->error_out, msg, args);
   33.88 -        va_end(args);
   33.89 -    }
   33.90 -}
   33.91 -
   33.92 -/*============================================================================*/
   33.93 -
   33.94 -/** Record defining the message for a parse error. */
   33.95 -typedef struct {
   33.96 -  ParseErrorId id;
   33.97 -  char *message;
   33.98 -} ParseError;
   33.99 -
  33.100 -/** Format for printing parse error messages. */
  33.101 -#define PARSE_ERR_FMT "parse error> line %3d, column %2d: %s"
  33.102 -
  33.103 -/** Message catalog for the parse error codes. */
  33.104 -static ParseError catalog[] = {
  33.105 -  { PARSE_ERR_UNSPECIFIED,            "unspecified error" },
  33.106 -  { PARSE_ERR_NOMEM,                  "out of memory" },
  33.107 -  { PARSE_ERR_UNEXPECTED_EOF,         "unexpected end of input" },
  33.108 -  { PARSE_ERR_TOKEN_TOO_LONG,         "token too long" },
  33.109 -  { PARSE_ERR_INVALID_SYNTAX,         "syntax error" },
  33.110 -  { PARSE_ERR_INVALID_ESCAPE,         "invalid escape" },
  33.111 -  { 0, NULL }
  33.112 -};
  33.113 -
  33.114 -/** Number of entries in the message catalog. */
  33.115 -const static int catalog_n = sizeof(catalog)/sizeof(ParseError);
  33.116 -
  33.117 -void ParserState_free(ParserState *z){
  33.118 -    if(!z) return;
  33.119 -    objfree(z->val);
  33.120 -    deallocate(z);
  33.121 -}
  33.122 -
  33.123 -int ParserState_new(ParserStateFn *fn, char *name,
  33.124 -                    ParserState *parent, ParserState **val){
  33.125 -    int err = 0;
  33.126 -    ParserState *z;
  33.127 -    z = ALLOCATE(ParserState);
  33.128 -    if(z){
  33.129 -        z->name = name;
  33.130 -        z->fn = fn;
  33.131 -        z->parent = parent;
  33.132 -        z->val = ONULL;
  33.133 -    } else {
  33.134 -        err = -ENOMEM;
  33.135 -    }
  33.136 -    if(!err) *val = z;
  33.137 -    return err;
  33.138 -}
  33.139 -
  33.140 -/** Free a parser.
  33.141 - * No-op if the parser is null.
  33.142 - *
  33.143 - * @param z parser 
  33.144 - */
  33.145 -void Parser_free(Parser *z){
  33.146 -    if(!z) return;
  33.147 -    objfree(z->val);
  33.148 -    z->val = ONONE;
  33.149 -    deallocate(z);
  33.150 -}
  33.151 -
  33.152 -/** Create a new parser. The error stream defaults to null.
  33.153 - */
  33.154 -Parser * Parser_new(void){
  33.155 -    Parser *z = ALLOCATE(Parser);
  33.156 -    int err = -ENOMEM;
  33.157 -  
  33.158 -    if(!z) goto exit;
  33.159 -    err = 0;
  33.160 -    reset(z);
  33.161 -  exit:
  33.162 -    if(err){
  33.163 -        Parser_free(z);
  33.164 -        z = NULL;
  33.165 -    }
  33.166 -    return z;
  33.167 -}
  33.168 -
  33.169 -/** Get the next character.
  33.170 - * Records the character read in the parser,
  33.171 - * and sets the line and character counts.
  33.172 - *
  33.173 - * @param p parser
  33.174 - * @return error flag: 0 on success, non-zero on error
  33.175 - */
  33.176 -static int inputchar(Parser *p, char c){
  33.177 -    int err = 0;
  33.178 -    if(c=='\n'){
  33.179 -        p->line_no++;
  33.180 -        p->char_no = 0;
  33.181 -    } else {
  33.182 -        p->char_no++;
  33.183 -    }
  33.184 -    return err;
  33.185 -}
  33.186 -
  33.187 -static int savechar(Parser *p, char c){
  33.188 -    int err = 0;
  33.189 -    if(p->buf_i >= p->buf_n){
  33.190 -        err = -ENOMEM;
  33.191 -        goto exit;
  33.192 -    }
  33.193 -    p->buf[p->buf_i] = c;
  33.194 -    p->buf_i++;
  33.195 -  exit:
  33.196 -    return err;
  33.197 -}
  33.198 -
  33.199 -int Parser_input_char(Parser *p, char c){
  33.200 -    int err = 0;
  33.201 -    if(at_eof(p)){
  33.202 -        //skip;
  33.203 -    } else {
  33.204 -        inputchar(p, c);
  33.205 -    }
  33.206 -    if(!p->state){
  33.207 -        err = begin_start(p, c);
  33.208 -        if(err) goto exit;
  33.209 -    }
  33.210 -    err = p->state->fn(p, c);
  33.211 -  exit:
  33.212 -    return err;
  33.213 -}
  33.214 -
  33.215 -int Parser_input_eof(Parser *p){
  33.216 -    int err = 0;
  33.217 -    p->eof = 1;
  33.218 -    err = Parser_input_char(p, IOSTREAM_EOF);
  33.219 -    return err;
  33.220 -}
  33.221 -
  33.222 -int Parser_input(Parser *p, char *buf, int buf_n){
  33.223 -    int err = 0;
  33.224 -    int i = 0;
  33.225 -    if(buf_n <= 0){
  33.226 -        err = Parser_input_eof(p);
  33.227 -        goto exit;
  33.228 -    }
  33.229 -    for(i = 0; i<buf_n; i++){
  33.230 -        err = Parser_input_char(p, buf[i]);
  33.231 -        if(err) goto exit;
  33.232 -    }
  33.233 -  exit:
  33.234 -    err = (err < 0 ? err : buf_n);
  33.235 -    return err;
  33.236 -}
  33.237 -
  33.238 -int Parser_push(Parser *p, ParserStateFn *fn, char *name){
  33.239 -    int err = 0;
  33.240 -    err = ParserState_new(fn, name, p->state, &p->state);
  33.241 -    return err;
  33.242 -}
  33.243 -        
  33.244 -int Parser_pop(Parser *p){
  33.245 -    int err = 0;
  33.246 -    ParserState *s = p->state;
  33.247 -    p->state = s->parent;
  33.248 -    ParserState_free(s);
  33.249 -    return err;
  33.250 -}
  33.251 -
  33.252 -int Parser_return(Parser *p){
  33.253 -    int err = 0;
  33.254 -    Sxpr val = ONONE;
  33.255 -    if(!p->state){
  33.256 -        err = -EINVAL;
  33.257 -        goto exit;
  33.258 -    }
  33.259 -    val = p->state->val;
  33.260 -    p->state->val = ONONE;
  33.261 -    err = Parser_pop(p);
  33.262 -    if(err) goto exit;
  33.263 -    if(p->state){
  33.264 -        err = cons_push(&p->state->val, val);
  33.265 -    } else {
  33.266 -        val = nrev(val);
  33.267 -        p->val = val;
  33.268 -    }
  33.269 -  exit:
  33.270 -    if(err){
  33.271 -        objfree(val);
  33.272 -    }
  33.273 -    return err;
  33.274 -}
  33.275 -
  33.276 -/** Determine if a character is a separator.
  33.277 - *
  33.278 - * @param p parser
  33.279 - * @param c character to test
  33.280 - * @return 1 if a separator, 0 otherwise
  33.281 - */
  33.282 -static int is_separator(Parser *p, char c){
  33.283 -    return in_sep_class(c);
  33.284 -}
  33.285 -
  33.286 -/** Return the current token.
  33.287 - * The return value points at the internal buffer, so
  33.288 - * it must not be modified (or freed). Use copy_token() if you need a copy.
  33.289 - *
  33.290 - * @param p parser
  33.291 - * @return token
  33.292 - */
  33.293 -char *peek_token(Parser *p){
  33.294 -    return p->buf;
  33.295 -}
  33.296 -
  33.297 -/** Return a copy of the current token.
  33.298 - * The returned value should be freed when finished with.
  33.299 - *
  33.300 - * @param p parser
  33.301 - * @return copy of token
  33.302 - */
  33.303 -char *copy_token(Parser *p){
  33.304 -    return strdup(peek_token(p));
  33.305 -}
  33.306 -
  33.307 -static int do_intern(Parser *p){
  33.308 -    int err = 0;
  33.309 -    Sxpr obj = intern(peek_token(p));
  33.310 -    if(NOMEMP(obj)){
  33.311 -        err = -ENOMEM;
  33.312 -    } else {
  33.313 -        p->state->val = obj;
  33.314 -    }
  33.315 -    return err;
  33.316 -}
  33.317 -
  33.318 -static int do_string(Parser *p){
  33.319 -    int err = 0;
  33.320 -    Sxpr obj;
  33.321 -    obj = string_new(peek_token(p));
  33.322 -    if(NOMEMP(obj)){
  33.323 -        err = -ENOMEM;
  33.324 -    } else {
  33.325 -        p->state->val = obj;
  33.326 -    }
  33.327 -    return err;
  33.328 -}
  33.329 -
  33.330 -void newtoken(Parser *p){
  33.331 -    memset(p->buf, 0, p->buf_n);
  33.332 -    p->buf_i = 0;
  33.333 -    p->tok_begin_line = p->line_no;
  33.334 -    p->tok_begin_char = p->char_no;
  33.335 -}
  33.336 -
  33.337 -int get_escape(char c, char *d){
  33.338 -    int err = 0;
  33.339 -    switch(c){
  33.340 -    case 'a':            *d = '\a'; break;
  33.341 -    case 'b':            *d = '\b'; break;
  33.342 -    case 'f':            *d = '\f'; break;
  33.343 -    case 'n':            *d = '\n'; break;
  33.344 -    case 'r':            *d = '\r'; break;
  33.345 -    case 't':            *d = '\t'; break;
  33.346 -    case 'v':            *d = '\v'; break;
  33.347 -    case c_escape:       *d = c_escape; break;
  33.348 -    case c_single_quote: *d = c_single_quote; break;
  33.349 -    case c_double_quote: *d = c_double_quote; break;
  33.350 -    default:
  33.351 -        err = -EINVAL;
  33.352 -    }
  33.353 -    return err;
  33.354 -}
  33.355 -
  33.356 -int Parser_ready(Parser *p){
  33.357 -    return CONSP(p->val) || (p->start_state && CONSP(p->start_state->val));
  33.358 -}
  33.359 -
  33.360 -Sxpr Parser_get_val(Parser *p){
  33.361 -    Sxpr v = ONONE;
  33.362 -    if(CONSP(p->val)){
  33.363 -        v = CAR(p->val);
  33.364 -        p->val = CDR(p->val);
  33.365 -    } else if (CONSP(p->start_state->val)){
  33.366 -        p->val = p->start_state->val;
  33.367 -        p->val = nrev(p->val);
  33.368 -        p->start_state->val = ONULL;
  33.369 -        v = CAR(p->val);
  33.370 -        p->val = CDR(p->val);
  33.371 -    }        
  33.372 -    return v;
  33.373 -}
  33.374 -
  33.375 -Sxpr Parser_get_all(Parser *p){
  33.376 -    Sxpr v = ONULL;
  33.377 -    if(CONSP(p->val)){
  33.378 -        v = p->val;
  33.379 -        p->val = ONONE;
  33.380 -    } else if(CONSP(p->start_state->val)){
  33.381 -        v = p->start_state->val;
  33.382 -        p->start_state->val = ONULL;
  33.383 -        v = nrev(v);
  33.384 -    }
  33.385 -    return v;
  33.386 -}
  33.387 -    
  33.388 -int begin_start(Parser *p, char c){
  33.389 -    int err = 0;
  33.390 -    err = Parser_push(p, state_start, "start");
  33.391 -    if(err) goto exit;
  33.392 -    p->start_state = p->state;
  33.393 -  exit:
  33.394 -    return err;
  33.395 -}
  33.396 -
  33.397 -int state_start(Parser *p, char c){
  33.398 -    int err = 0;
  33.399 -    if(at_eof(p)){
  33.400 -        err = end_start(p);
  33.401 -    } else if(in_space_class(c)){
  33.402 -        //skip
  33.403 -    } else if(in_comment_class(c)){
  33.404 -        begin_comment(p, c);
  33.405 -    } else if(c == c_list_open){
  33.406 -        begin_list(p, c);
  33.407 -    } else if(c == c_list_close){
  33.408 -        parse_error(p);
  33.409 -        err = -EINVAL;
  33.410 -    } else if(in_string_quote_class(c)){
  33.411 -        begin_string(p, c);
  33.412 -    } else if(in_printable_class(c)){
  33.413 -        begin_atom(p, c);
  33.414 -    } else if(c == 0x04){
  33.415 -        //ctrl-D, EOT: end-of-text.
  33.416 -        Parser_input_eof(p);
  33.417 -    } else {
  33.418 -        parse_error(p);
  33.419 -        err = -EINVAL;
  33.420 -    }
  33.421 -    return err;
  33.422 -}
  33.423 -
  33.424 -int end_start(Parser *p){
  33.425 -    int err = 0;
  33.426 -    err = Parser_return(p);
  33.427 -    return err;
  33.428 -}
  33.429 -
  33.430 -int begin_comment(Parser *p, char c){
  33.431 -    int err = 0;
  33.432 -    err = Parser_push(p, state_comment, "comment");
  33.433 -    if(err) goto exit;
  33.434 -    err = inputchar(p, c);
  33.435 -  exit:
  33.436 -    return err;
  33.437 -}
  33.438 -
  33.439 -int state_comment(Parser *p, char c){
  33.440 -    int err = 0;
  33.441 -    if(c == '\n' || at_eof(p)){
  33.442 -        err = end_comment(p);
  33.443 -    } else {
  33.444 -        err = inputchar(p, c);
  33.445 -    }
  33.446 -    return err;
  33.447 -}
  33.448 -
  33.449 -int end_comment(Parser *p){
  33.450 -    return Parser_pop(p);
  33.451 -}
  33.452 -
  33.453 -int begin_string(Parser *p, char c){
  33.454 -    int err = 0;
  33.455 -    err = Parser_push(p, state_string, "string");
  33.456 -    if(err) goto exit;
  33.457 -    newtoken(p);
  33.458 -    p->state->delim = c;
  33.459 -  exit:
  33.460 -    return err;
  33.461 -}
  33.462 -
  33.463 -int state_string(Parser *p, char c){
  33.464 -    int err = 0;
  33.465 -    if(at_eof(p)){
  33.466 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.467 -        err = -EINVAL;
  33.468 -    } else if(c == p->state->delim){
  33.469 -        err = end_string(p);
  33.470 -    } else if(c == '\\'){
  33.471 -        err = Parser_push(p, state_escape, "escape");
  33.472 -    } else {
  33.473 -        err = savechar(p, c);
  33.474 -    }
  33.475 -    return err;
  33.476 -}
  33.477 -
  33.478 -int end_string(Parser *p){
  33.479 -    int err = 0;
  33.480 -    err = do_string(p);
  33.481 -    if(err) goto exit;
  33.482 -    err = Parser_return(p);
  33.483 -  exit:
  33.484 -    return err;
  33.485 -}
  33.486 -
  33.487 -int state_escape(Parser *p, char c){
  33.488 -    int err = 0;
  33.489 -    char d;
  33.490 -    if(at_eof(p)){
  33.491 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.492 -        err = -EINVAL;
  33.493 -        goto exit;
  33.494 -    }
  33.495 -    if(get_escape(c, &d) == 0){
  33.496 -        err = savechar(p, d);
  33.497 -        if(err) goto exit;
  33.498 -        err = Parser_pop(p);
  33.499 -    } else if(c == 'x'){
  33.500 -        p->state->fn = state_hex;
  33.501 -        p->state->ival = 0;
  33.502 -        p->state->count = 0;
  33.503 -    } else {
  33.504 -        p->state->fn = state_octal;
  33.505 -        p->state->ival = 0;
  33.506 -        p->state->count = 0;
  33.507 -        err = Parser_input_char(p, c);
  33.508 -    }
  33.509 -  exit:
  33.510 -    return err;
  33.511 -}
  33.512 -
  33.513 -int octaldone(Parser *p){
  33.514 -    int err = 0;
  33.515 -    char d = (char)(p->state->ival & 0xff);
  33.516 -    err = Parser_pop(p);
  33.517 -    if(err) goto exit;
  33.518 -    err = Parser_input_char(p, d);
  33.519 -  exit:
  33.520 -    return err;
  33.521 -}
  33.522 -
  33.523 -int octaldigit(Parser *p, char c){
  33.524 -    int err = 0;
  33.525 -    p->state->ival *= 8;
  33.526 -    p->state->ival += c - '0'; 
  33.527 -    p->state->count++;
  33.528 -    if(err) goto exit;
  33.529 -    if(p->state->ival < 0 || p->state->ival > 0xff){
  33.530 -        parse_error(p);
  33.531 -        err = -EINVAL;
  33.532 -        goto exit;
  33.533 -    }
  33.534 -    if(p->state->count == 3){
  33.535 -        err = octaldone(p);
  33.536 -    }
  33.537 -  exit:
  33.538 -    return err;
  33.539 -}
  33.540 -
  33.541 -int state_octal(Parser *p, char c){
  33.542 -    int err = 0;
  33.543 -    if(at_eof(p)){
  33.544 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.545 -        err = -EINVAL;
  33.546 -        goto exit;
  33.547 -    } else if('0' <= c && c <= '7'){
  33.548 -        err = octaldigit(p, c);
  33.549 -    } else {
  33.550 -        err = octaldone(p);
  33.551 -        if(err) goto exit;
  33.552 -        Parser_input_char(p, c);
  33.553 -    }
  33.554 -  exit:
  33.555 -    return err;
  33.556 -}
  33.557 -
  33.558 -int hexdone(Parser *p){
  33.559 -    int err = 0;
  33.560 -    char d = (char)(p->state->ival & 0xff);
  33.561 -    err = Parser_pop(p);
  33.562 -    if(err) goto exit;
  33.563 -    err = Parser_input_char(p, d);
  33.564 -  exit:
  33.565 -    return err;
  33.566 -}
  33.567 -    
  33.568 -int hexdigit(Parser *p, char c, char d){
  33.569 -    int err = 0;
  33.570 -    p->state->ival *= 16;
  33.571 -    p->state->ival += c - d; 
  33.572 -    p->state->count++;
  33.573 -    if(err) goto exit;
  33.574 -    if(p->state->ival < 0 || p->state->ival > 0xff){
  33.575 -        parse_error(p);
  33.576 -        err = -EINVAL;
  33.577 -        goto exit;
  33.578 -    }
  33.579 -    if(p->state->count == 2){
  33.580 -        err = hexdone(p);
  33.581 -    }
  33.582 -  exit:
  33.583 -    return err;
  33.584 -}
  33.585 -    
  33.586 -int state_hex(Parser *p, char c){
  33.587 -    int err = 0;
  33.588 -    if(at_eof(p)){
  33.589 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.590 -        err = -EINVAL;
  33.591 -        goto exit;
  33.592 -    } else if('0' <= c && c <= '9'){
  33.593 -        err = hexdigit(p, c, '0');
  33.594 -    } else if('A' <= c && c <= 'F'){
  33.595 -        err = hexdigit(p, c, 'A');
  33.596 -    } else if('a' <= c && c <= 'f'){
  33.597 -        err = hexdigit(p, c, 'a');
  33.598 -    } else if(p->state->count){
  33.599 -        err =hexdone(p);
  33.600 -        if(err) goto exit;
  33.601 -        Parser_input_char(p, c);
  33.602 -    }
  33.603 -  exit:
  33.604 -    return err;
  33.605 -}
  33.606 -
  33.607 -int begin_atom(Parser *p, char c){
  33.608 -    int err = 0;
  33.609 -    err = Parser_push(p, state_atom, "atom");
  33.610 -    if(err) goto exit;
  33.611 -    newtoken(p);
  33.612 -    err = savechar(p, c);
  33.613 -  exit:
  33.614 -    return err;
  33.615 -}
  33.616 -
  33.617 -int state_atom(Parser *p, char c){
  33.618 -    int err = 0;
  33.619 -    if(at_eof(p)){
  33.620 -        err = end_atom(p);
  33.621 -    } else if(is_separator(p, c) ||
  33.622 -              in_space_class(c) ||
  33.623 -              in_comment_class(c)){
  33.624 -        err = end_atom(p);
  33.625 -        if(err) goto exit;
  33.626 -        err = Parser_input_char(p, c);
  33.627 -    } else {
  33.628 -        err = savechar(p, c);
  33.629 -    }
  33.630 -  exit:
  33.631 -    return err;
  33.632 -}
  33.633 -
  33.634 -int end_atom(Parser *p){
  33.635 -    int err = 0;
  33.636 -    err = do_intern(p);
  33.637 -    if(err) goto exit;
  33.638 -    err = Parser_return(p);
  33.639 -  exit:
  33.640 -    return err;
  33.641 -}
  33.642 -
  33.643 -int state_list(Parser *p, char c){
  33.644 -    int err = 0;
  33.645 -    if(at_eof(p)){
  33.646 -        parse_error_id(p, PARSE_ERR_UNEXPECTED_EOF);
  33.647 -        err = -EINVAL;
  33.648 -    } else if(c == c_list_close){
  33.649 -        p->state->val = nrev(p->state->val);
  33.650 -        err = end_list(p);
  33.651 -    } else {
  33.652 -        err = state_start(p, c);
  33.653 -    }
  33.654 -    return err;
  33.655 -    
  33.656 -}
  33.657 -
  33.658 -int begin_list(Parser *p, char c){
  33.659 -    return Parser_push(p, state_list, "list");
  33.660 -}
  33.661 -
  33.662 -int end_list(Parser *p){
  33.663 -    return Parser_return(p);
  33.664 -}
  33.665 -
  33.666 -/** Reset the fields of a parser to initial values.
  33.667 - *
  33.668 - * @param z parser
  33.669 - */
  33.670 -static void reset(Parser *z){
  33.671 -  IOStream *error_out = z->error_out;
  33.672 -  int flags = z->flags;
  33.673 -  memzero(z, sizeof(Parser));
  33.674 -  z->buf_n = sizeof(z->buf) - 1;
  33.675 -  z->buf_i = 0;
  33.676 -  z->line_no = 1;
  33.677 -  z->char_no = 0;
  33.678 -  z->error_out = error_out;
  33.679 -  z->flags = flags;
  33.680 -}
  33.681 -
  33.682 -/** Set the parser error stream.
  33.683 - * Parse errors are reported on the the error stream if it is non-null.
  33.684 - * 
  33.685 - * @param z parser
  33.686 - * @param error_out error stream
  33.687 - */
  33.688 -void set_error_stream(Parser *z, IOStream *error_out){
  33.689 -  if(z){
  33.690 -    z->error_out = error_out;
  33.691 -  }
  33.692 -}
  33.693 -
  33.694 -/** Get the parser error message for an error code.
  33.695 - *
  33.696 - * @param id error code
  33.697 - * @return error message (empty string if the code is unknown)
  33.698 - */
  33.699 -static char *get_message(ParseErrorId id){
  33.700 -  int i;
  33.701 -  for(i=0; i<catalog_n; i++){
  33.702 -    if(id == catalog[i].id){
  33.703 -      return catalog[i].message;
  33.704 -    }
  33.705 -  }
  33.706 -  return "";
  33.707 -}
  33.708 -
  33.709 -/** Get the line number.
  33.710 - *
  33.711 - * @param in parser
  33.712 - */
  33.713 -int get_line(Parser *in){
  33.714 -  return in->line_no;
  33.715 -}
  33.716 -
  33.717 -/** Get the column number.
  33.718 - *
  33.719 - * @param in parser
  33.720 - */
  33.721 -int get_column(Parser *in){
  33.722 -  return in->char_no;
  33.723 -}
  33.724 -
  33.725 -/** Get the line number the current token started on.
  33.726 - *
  33.727 - * @param in parser
  33.728 - */
  33.729 -int get_tok_line(Parser *in){
  33.730 -  return in->tok_begin_line;
  33.731 -}
  33.732 -
  33.733 -/** Get the column number the current token started on.
  33.734 - *
  33.735 - * @param in parser
  33.736 - */
  33.737 -int get_tok_column(Parser *in){
  33.738 -  return in->tok_begin_char;
  33.739 -}
  33.740 -
  33.741 -/** Report a parse error.
  33.742 - * Does nothing if the error stream is null or there is no error.
  33.743 - *
  33.744 - * @param in parser
  33.745 - */
  33.746 -static void report_error(Parser *in){
  33.747 -  if(in->error_out && in->err){
  33.748 -    char *msg = get_message(in->err);
  33.749 -    char *tok = peek_token(in);
  33.750 -    IOStream_print(in->error_out, PARSE_ERR_FMT,
  33.751 -		   get_tok_line(in), get_tok_column(in), msg);
  33.752 -    if(tok && tok[0]){
  33.753 -        IOStream_print(in->error_out, " '%s'", tok);
  33.754 -    }
  33.755 -    IOStream_print(in->error_out, "\n");
  33.756 -  }
  33.757 -}
  33.758 -
  33.759 -/** Get the error message for the current parse error code.
  33.760 - * Does nothing if there is no error.
  33.761 - *
  33.762 - * @param in parser
  33.763 - * @param buf where to place the message
  33.764 - * @param n maximum number of characters to place in buf
  33.765 - * @return current error code (zero for no error)
  33.766 - */
  33.767 -int parse_error_message(Parser *in, char *buf, int n){
  33.768 -    if(in->err){
  33.769 -        char *msg = get_message(in->err);
  33.770 -        snprintf(buf, n, PARSE_ERR_FMT, get_tok_line(in), get_tok_column(in), msg);
  33.771 -    }
  33.772 -    return in->err;
  33.773 -}
  33.774 -
  33.775 -/** Flag an unspecified parse error. All subsequent reads will fail.
  33.776 - *
  33.777 - * @param in parser
  33.778 - */
  33.779 -void parse_error(Parser *in){
  33.780 -    parse_error_id(in, PARSE_ERR_INVALID_SYNTAX);
  33.781 -}
  33.782 -
  33.783 -/** Flag a parse error. All subsequent reads will fail.
  33.784 - * Does not change the parser error code if it is already set.
  33.785 - *
  33.786 - * @param in parser
  33.787 - * @param id error code
  33.788 - */
  33.789 -void parse_error_id(Parser *in, ParseErrorId id){
  33.790 -    if(!in->err){
  33.791 -        in->err = id;
  33.792 -        report_error(in);
  33.793 -    }
  33.794 -}
  33.795 -
  33.796 -/** Test if the parser's error flag is set.
  33.797 - *
  33.798 - * @param in parser
  33.799 - * @return 1 if set, 0 otherwise
  33.800 - */
  33.801 -int has_error(Parser *in){
  33.802 -    return (in->err > 0);
  33.803 -}
  33.804 -
  33.805 -/** Test if the parser is at end of input.
  33.806 - *
  33.807 - * @param in parser
  33.808 - * @return 1 if at EOF, 0 otherwise
  33.809 - */
  33.810 -int at_eof(Parser *p){
  33.811 -    return p->eof;
  33.812 -}
  33.813 -
  33.814 -//#define SXPR_PARSER_MAIN
  33.815 -#ifdef SXPR_PARSER_MAIN
  33.816 -/* Stuff for standalone testing. */
  33.817 -
  33.818 -#include "file_stream.h"
  33.819 -#include "string_stream.h"
  33.820 -
  33.821 -int stringof(Sxpr exp, char **s){
  33.822 -    int err = 0;
  33.823 -    if(ATOMP(exp)){
  33.824 -        *s = atom_name(exp);
  33.825 -    } else if(STRINGP(exp)){
  33.826 -        *s = string_string(exp);
  33.827 -    } else {
  33.828 -        err = -EINVAL;
  33.829 -        *s = NULL;
  33.830 -    }
  33.831 -    return err;
  33.832 -}
  33.833 -
  33.834 -int child_string(Sxpr exp, Sxpr key, char **s){
  33.835 -    int err = 0;
  33.836 -    Sxpr val = sxpr_child_value(exp, key, ONONE);
  33.837 -    err = stringof(val, s);
  33.838 -    return err;
  33.839 -}
  33.840 -
  33.841 -int intof(Sxpr exp, int *v){
  33.842 -    int err = 0;
  33.843 -    char *s;
  33.844 -    unsigned long l;
  33.845 -    if(INTP(exp)){
  33.846 -        *v = OBJ_INT(exp);
  33.847 -    } else {
  33.848 -        err = stringof(exp, &s);
  33.849 -        if(err) goto exit;
  33.850 -        err = convert_atoul(s, &l);
  33.851 -        *v = (int)l;
  33.852 -    }
  33.853 - exit:
  33.854 -    return err;
  33.855 -}
  33.856 -
  33.857 -int child_int(Sxpr exp, Sxpr key, int *v){
  33.858 -    int err = 0;
  33.859 -    Sxpr val = sxpr_child_value(exp, key, ONONE);
  33.860 -    err = intof(val, v);
  33.861 -    return err;
  33.862 -}
  33.863 -
  33.864 -int eval_vnet(Sxpr exp){
  33.865 -    int err = 0;
  33.866 -    Sxpr oid = intern("id");
  33.867 -    int id;
  33.868 -    err = child_int(exp, oid, &id);
  33.869 -    if(err) goto exit;
  33.870 -    dprintf("> vnet id=%d\n", id);
  33.871 - exit:
  33.872 -    dprintf("< err=%d\n", err);
  33.873 -    return err;
  33.874 -}
  33.875 -
  33.876 -int eval_connect(Sxpr exp){
  33.877 -    int err = 0;
  33.878 -    Sxpr ovif = intern("vif");
  33.879 -    Sxpr ovnet = intern("vnet");
  33.880 -    char *vif;
  33.881 -    int vnet;
  33.882 -
  33.883 -    err = child_string(exp, ovif, &vif);
  33.884 -    if(err) goto exit;
  33.885 -    err = child_int(exp, ovnet, &vnet);
  33.886 -    if(err) goto exit;
  33.887 -    dprintf("> connect vif=%s vnet=%d\n", vif, vnet);
  33.888 - exit:
  33.889 -    dprintf("< err=%d\n", err);
  33.890 -    return err;
  33.891 -}
  33.892 -
  33.893 -int eval(Sxpr exp){
  33.894 -    int err = 0;
  33.895 -    Sxpr oconnect = intern("connect");
  33.896 -    Sxpr ovnet = intern("vnet");
  33.897 -    
  33.898 -    if(sxpr_elementp(exp, ovnet)){
  33.899 -        err = eval_vnet(exp);
  33.900 -    } else if(sxpr_elementp(exp, oconnect)){
  33.901 -        err = eval_connect(exp);
  33.902 -    } else {
  33.903 -        err = -EINVAL;
  33.904 -    }
  33.905 -    return err;
  33.906 -}
  33.907 -
  33.908 -/** Main program for testing.
  33.909 - * Parses input and prints it.
  33.910 - *
  33.911 - * @param argc number of arguments
  33.912 - * @param argv arguments
  33.913 - * @return error code
  33.914 - */
  33.915 -int main(int argc, char *argv[]){
  33.916 -    Parser *pin;
  33.917 -    int err = 0;
  33.918 -    char buf[1024];
  33.919 -    int k;
  33.920 -    Sxpr obj;
  33.921 -    //Sxpr l, x;
  33.922 -    int i = 0;
  33.923 -
  33.924 -    pin = Parser_new();
  33.925 -    set_error_stream(pin, iostdout);
  33.926 -    dprintf("> parse...\n");
  33.927 -    while(1){
  33.928 -        k = fread(buf, 1, 1, stdin);
  33.929 -        err = Parser_input(pin, buf, k);
  33.930 -        while(Parser_ready(pin)){
  33.931 -            obj = Parser_get_val(pin);
  33.932 -            printf("obj %d\n", i++);
  33.933 -            objprint(iostdout, obj, 0); printf("\n");
  33.934 -        }
  33.935 -        if(k <= 0) break;
  33.936 -    }
  33.937 -/*     obj = Parser_get_all(pin); */
  33.938 -/*     for(l = obj ; CONSP(l); l = CDR(l)){ */
  33.939 -/*         x = CAR(l); */
  33.940 -/*         objprint(iostdout, x, 0); printf("\n"); */
  33.941 -/*         eval(x); */
  33.942 -/*     } */
  33.943 -    dprintf("> err=%d\n", err);
  33.944 -    return 0;
  33.945 -}
  33.946 -#endif
    34.1 --- a/tools/xfrd/sxpr_parser.h	Sun Nov 21 20:41:00 2004 +0000
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,133 +0,0 @@
    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 _XUTIL_SXPR_PARSER_H_
   34.21 -#define _XUTIL_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 -    char *name;
   34.46 -} ParserState;
   34.47 -
   34.48 -/** Structure representing an input source for the parser.
   34.49 - * Can read from any IOStream implementation.
   34.50 - */
   34.51 -typedef struct Parser {
   34.52 -    Sxpr val;
   34.53 -    /** Error reporting stream (null for no reports). */
   34.54 -    IOStream *error_out;
   34.55 -    int eof;
   34.56 -    /** Error flag. Non-zero if there has been a read error. */
   34.57 -    int err;
   34.58 -    /** Line number on input (from 1). */
   34.59 -    int line_no;
   34.60 -    /** Column number of input (reset on new line). */
   34.61 -    int char_no;
   34.62 -    /** Lookahead character. */
   34.63 -    char c;
   34.64 -    /** Buffer for reading tokens. */
   34.65 -    char buf[PARSER_BUF_SIZE];
   34.66 -    /** Size of token buffer. */
   34.67 -    int buf_n;
   34.68 -    int buf_i;
   34.69 -    /** Line the last token started on. */
   34.70 -    int tok_begin_line;
   34.71 -    /** Character number the last token started on. */
   34.72 -    int tok_begin_char;
   34.73 -    /** Parsing flags. */
   34.74 -    int flags;
   34.75 -    ParserState *state;
   34.76 -    ParserState *start_state;
   34.77 -} Parser;
   34.78 -
   34.79 -/** Parser error codes. */
   34.80 -typedef enum {
   34.81 -    PARSE_ERR_NONE=0,
   34.82 -    PARSE_ERR_UNSPECIFIED,
   34.83 -    PARSE_ERR_NOMEM,
   34.84 -    PARSE_ERR_UNEXPECTED_EOF,
   34.85 -    PARSE_ERR_TOKEN_TOO_LONG,
   34.86 -    PARSE_ERR_INVALID_SYNTAX,
   34.87 -    PARSE_ERR_INVALID_ESCAPE,
   34.88 -} ParseErrorId;
   34.89 -
   34.90 -
   34.91 -/** Parser flags. */
   34.92 -//enum {
   34.93 -//};
   34.94 -
   34.95 -/** Raise some parser flags.
   34.96 - *
   34.97 - * @param in parser
   34.98 - * @param flags flags mask
   34.99 - */
  34.100 -inline static void parser_flags_raise(Parser *in, int flags){
  34.101 -    in->flags |= flags;
  34.102 -}
  34.103 -
  34.104 -/** Lower some parser flags.
  34.105 - *
  34.106 - * @param in parser
  34.107 - * @param flags flags mask
  34.108 - */
  34.109 -inline static void parser_flags_lower(Parser *in, int flags){
  34.110 -    in->flags &= ~flags;
  34.111 -}
  34.112 -
  34.113 -/** Clear all parser flags.
  34.114 - *
  34.115 - * @param in parser
  34.116 - */
  34.117 -inline static void parser_flags_clear(Parser *in){
  34.118 -    in->flags = 0;
  34.119 -}
  34.120 -
  34.121 -extern void Parser_free(Parser *z);
  34.122 -extern Parser * Parser_new(void);
  34.123 -extern int Parser_input(Parser *p, char *buf, int buf_n);
  34.124 -extern int Parser_input_eof(Parser *p);
  34.125 -extern int Parser_input_char(Parser *p, char c);
  34.126 -extern void set_error_stream(Parser *z, IOStream *error_out);
  34.127 -
  34.128 -extern int parse_error_message(Parser *in, char *buf, int n);
  34.129 -extern int has_error(Parser *in);
  34.130 -extern int at_eof(Parser *in);
  34.131 -
  34.132 -int Parser_ready(Parser *p);
  34.133 -Sxpr Parser_get_val(Parser *p);
  34.134 -Sxpr Parser_get_all(Parser *p);
  34.135 -
  34.136 -#endif /* ! _XUTIL_SXPR_PARSER_H_ */