summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bremner <bremner@debian.org>2023-09-28 07:36:42 -0300
committerDavid Bremner <bremner@debian.org>2023-09-28 07:36:42 -0300
commiteddd5ffb8f75d13597fb931ff03ebd3b41dc6ed6 (patch)
tree56e0a55e4265ee080d43e70eca34a7fe8de4525d
parent2b63855415d8e6d05d4ff0015417e1c2da56e022 (diff)
parentb7d3bea0effb6663a6d69897bc1c4ea3cc08b682 (diff)
Merge tag 'v1.4.1'
-rw-r--r--INSTALL1
-rw-r--r--Makefile.am5
-rw-r--r--README.md32
-rw-r--r--README_cmake.txt12
-rw-r--r--configure.ac8
-rw-r--r--examples/Makefile.am2
-rwxr-xr-xexamples/check_leaks.sh15
-rwxr-xr-xpython/test.py2
-rw-r--r--siloon/README14
-rw-r--r--siloon/setup.pl129
-rw-r--r--src/Makefile.am3
-rwxr-xr-xtest_builds.sh10
-rwxr-xr-xtests/check_leaks.sh16
-rw-r--r--www/index.html544
14 files changed, 69 insertions, 724 deletions
diff --git a/INSTALL b/INSTALL
index be75258..9dbd11a 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,3 +1,4 @@
+To build, you'll need: autoconf automake libtool m4.
To try things out, just type:
diff --git a/Makefile.am b/Makefile.am
index d0b88ca..99d18a8 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,7 @@
SUBDIRS = src examples tests
-EXTRA_DIST = Doxyfile README.md README_cmake.txt win32
+EXTRA_DIST = Doxyfile LICENSE_LGPL README.md README_cmake.txt win32
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = sfsexp.pc
ACLOCAL_AMFLAGS = -I m4
diff --git a/README.md b/README.md
index 2f3c9cc..3a0fc69 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ sfsexp
This library is intended for developers who wish to manipulate (read,
parse, modify, and create) symbolic expressions from C or C++
programs. A symbolic expression, or s-expression, is essentially a
-LISP-like expression such as (a (b c)). S-expressions are able to
+LISP-like expression such as `(a (b c))`. S-expressions are able to
represent complex, structured data without requiring additional
meta-data describing the structure. They are recursively defined: an
s-expression is a list of either atoms or s-expressions. In the
@@ -17,7 +17,13 @@ data structures for the four functions listed above: reading
s-expressions (I/O), parsing strings containing them into an AST
equivalent, modifying the AST representation, and converting the AST
back into a well formatted string. The primary goals are efficiency
-and simplicity. This library forms the basis of the data
+and simplicity. Beyond basic s-expression handling, the library
+supports a mode to inline binary data within an expression. The
+continuation-based parser is designed to efficiently handle
+parsing multiple streams. The library is also designed with a
+limited memory mode for use in embedded systems.
+
+This library forms the basis of the data
representation and transmission protocol for the
[Supermon](https://dl.acm.org/doi/10.5555/792762.793324) high-speed
cluster monitoring system from the LANL Advanced Computing
@@ -38,15 +44,19 @@ Configure the sources via autoconf.
% ./configure
```
-Currently, the only feature that can be enabled via autoconf is to
-enable any debugging code in the library by specifying
-"--enable-debug". Other features such as disabling memory management
-by the library are toggled by setting appropriate options in the
-CFLAGS:
+Currently, the major features that can be enabled via autoconf are:
+
+- "--enable-debug" to enable any debugging code in the library,
+- "--enable-thread-unsafe-memory-management" to enable caching of
+ s-expressions in a thread-unsafe way.
+
+Other features are toggled by setting appropriate options in the CFLAGS,
+such as the memory-limiting mode.
```
-% CFLAGS=-D_NO_MEMORY_MANAGEMENT_ ./configure
+% CFLAGS=-D_SEXP_LIMIT_MEMORY_ ./configure
```
+
Note that you should use the vanilla configuration unless you know that you
want to use debug mode or other options, and understand precisely what they
mean.
@@ -72,7 +82,7 @@ consolidated header that encapsulates all of the headers currently
included in the library. If you do not want to aim your project that
uses the library into the library source and build directories
directly, creating a separate installation prefix and installing there
-is recommended. For example, from the root of the sexpr tree:
+is recommended. For example, from the root of the sfsexp tree:
```
% mkdir installTree
@@ -133,10 +143,10 @@ incomplete and needs more data to complete it."
are reading data encoded as sexps. For example, it's not uncommon for
a big hunk o' data to be encoded as a single sexp in a file. One way
to handle this situation is to get the file size, dynamically allocate
-a buffer big enought to hold it, and then use `parse_sexp`. Here's a
+a buffer big enough to hold it, and then use `parse_sexp`. Here's a
minimal example (error checking omitted):
-```
+```c
int fd;
FILE *fp = fopen(fname, "r");
fseek(fp, 0, SEEK_END);
diff --git a/README_cmake.txt b/README_cmake.txt
index db89aa5..9fdfb7b 100644
--- a/README_cmake.txt
+++ b/README_cmake.txt
@@ -1,17 +1,17 @@
-Using sexpr library from cmake-based projects:
+Using sfsexp library from cmake-based projects:
----------------------------------------------
-Presently, the library does not come with a proper FindSexpr.cmake module
+Presently, the library does not come with a proper FindSfsexp.cmake module
file. In the meantime, you can add the following lines to a CMakeLists.txt
-file. Assuming the source tree for the sexpr library exists in
-/Users/matt/Research/sexpr/src :
+file. Assuming the source tree for the sfsexp library exists in
+/Users/matt/Research/sfsexp/src :
INCLUDE_DIRECTORIES(
- /Users/matt/Research/sexpr/src/src
+ /Users/matt/Research/sfsexp/src/src
)
LINK_DIRECTORIES(
- /Users/matt/Research/sexpr/src/src
+ /Users/matt/Research/sfsexp/src/src
)
And then just add "sexp" to the TARGET_LINK_LIBRARIES list.
diff --git a/configure.ac b/configure.ac
index ca4606b..ffa619e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.61)
-AC_INIT(sexpr, 1.3.1, mjsottile@me.com)
+AC_INIT(sfsexp, 1.4.1, mjsottile@me.com)
AM_INIT_AUTOMAKE(foreign)
AC_OUTPUT([Makefile src/Makefile examples/Makefile tests/Makefile])
AC_CONFIG_SRCDIR([examples/binmode.c])
@@ -20,7 +20,11 @@ AC_ARG_ENABLE(debug,
[AS_HELP_STRING([--enable-debug],[turn on debug options and code (disabled by default)])],
[SX_CPPFLAGS="" SX_CFLAGS="$CFLAGS -g -O0 -Wall"],
[])
-
+
+AC_ARG_ENABLE(thread-unsafe-memory-management,
+ [AS_HELP_STRING([--enable-thread-unsafe-memory-management],[turn on thread-unsafe memory management (disabled by default)])],
+ [],
+ [SX_CFLAGS="$SX_CFLAGS -D_NO_MEMORY_MANAGEMENT_"])
# Export flags
AC_SUBST([SFSEXP_CPPFLAGS], $SX_CPPFLAGS)
diff --git a/examples/Makefile.am b/examples/Makefile.am
index e19d334..4afd2fc 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -4,7 +4,7 @@ LDFLAGS =
EXTRA_DIST = testrc vis.in sexps.in edgelist.dat conttest
noinst_PROGRAMS = binmode callbacks continuations packunpack paultest rcfile sexpvis simple_interp
-include_HEADERS = ../src/sexp.h
+noinst_HEADERS = ../src/sexp.h
LDADD = ../src/libsexp.la
binmode_SOURCES = binmode.c ../src/sexp.h
callbacks_SOURCES = callbacks.c ../src/sexp.h
diff --git a/examples/check_leaks.sh b/examples/check_leaks.sh
index 29836e0..ab6f405 100755
--- a/examples/check_leaks.sh
+++ b/examples/check_leaks.sh
@@ -1,12 +1,20 @@
-#!/bin/bash
+#!/usr/bin/env bash
+
+# if valgrind isn't present we can't proceed - otherwise
+# we get a cascade of command not found failures
+if ! command -v valgrind &> /dev/null
+then
+ echo "cannot continue: valgrind could not be found"
+ exit
+fi
function test {
- valgrind --leak-check=full --show-reachable=yes -q "$@" > /dev/null
+ libtool --mode=execute valgrind --leak-check=full --show-reachable=yes -q "$@" > /dev/null
status=$?
if [ $status -ne 0 ]; then
echo "error with $1"
else
- echo "no error with $1"
+ echo "no error with $1"
fi
return $status
}
@@ -19,4 +27,3 @@ test ./paultest
test ./rcfile
test ./sexpvis
test ./simple_interp
-
diff --git a/python/test.py b/python/test.py
index 59cbe06..ad3eea9 100755
--- a/python/test.py
+++ b/python/test.py
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/env python
import os
import socket
diff --git a/siloon/README b/siloon/README
deleted file mode 100644
index b701f47..0000000
--- a/siloon/README
+++ /dev/null
@@ -1,14 +0,0 @@
-*******
-NOTICE: 10-1-2004 ::: This directory should be considered dead code now.
- IGNORE IT.
-*******
-
-
-This directory contains bindings for SILOON, allowing testing of the library
-from Python or Perl instead of through the existing C interface alone.
-
-SILOON can be found at http://www.acl.lanl.gov/siloon/
-
-This is NOT intended for real use, and the author (Matt) won't even respond
-to support questions. It was an experiment, and still is. (And hasn't been
-looked at in months.)
diff --git a/siloon/setup.pl b/siloon/setup.pl
deleted file mode 100644
index e42a0d6..0000000
--- a/siloon/setup.pl
+++ /dev/null
@@ -1,129 +0,0 @@
-#!/usr/bin/perl
-# ACL:license
-#
-#This software and ancillary information (herein called "SOFTWARE")
-#called Supermon is made available under the terms described
-#here. The SOFTWARE has been approved for release with associated
-#LA-CC Number LA-CC 99-51.
-#
-#Unless otherwise indicated, this SOFTWARE has been authored by an
-#employee or employees of the University of California, operator of the
-#Los Alamos National Laboratory under Contract No. W-7405-ENG-36 with
-#the U.S. Department of Energy. The U.S. Government has rights to use,
-#reproduce, and distribute this SOFTWARE, and to allow others to do so.
-#The public may copy, distribute, prepare derivative works and publicly
-#display this SOFTWARE without charge, provided that this Notice and
-#any statement of authorship are reproduced on all copies. Neither the
-#Government nor the University makes any warranty, express or implied,
-#or assumes any liability or responsibility for the use of this
-#SOFTWARE.
-#
-#If SOFTWARE is modified to produce derivative works, such modified
-#SOFTWARE should be clearly marked, so as not to confuse it with the
-#version available from LANL.
-#
-# ACL:license
-
-##
-## setup for siloon
-##
-
-# directory where siloon was installed
-$siloon = "/Users/matt/siloon";
-
-# current directory
-$curdir = `pwd`;
-$curdir =~ s/\n//g;
-$curdir =~ s/\r//g;
-
-# list of source files in src directory
-@sources = ("sexpr.c","parser.c","io.c","faststack.c");
-
-# list of functions we want to have callable from python
-@functions = ("parse_sexp","find_sexp","destroy_sexp","print_sexp");
-
-##
-## remove module if it exists
-##
-if (-d "./siloon-sexpr") {
- print "Removing existing module...\n";
- system("rm -Rf ./siloon-sexpr");
-}
-
-##
-## init
-##
-system($siloon."/bin/siloon-init sexpr");
-
-##
-## cd into the module dir
-##
-chdir("./siloon-sexpr");
-
-##
-## tweak the user.defs file
-##
-$tempfile = "/tmp/__user.defs";
-open(USERDEF,"< user.defs");
-open(TMPUSERDEF,"> $tempfile");
-
-print TMPUSERDEF "SEXPRROOT=".$curdir."/../src\n";
-
-while (<USERDEF>) {
- if (/^SILOON_PARSE_INCLUDES=/) {
- print TMPUSERDEF "SILOON_PARSE_INCLUDES=-I\${SEXPRROOT}\n";
- } else {
- if (/^SILOON_USER_SOURCES=/) {
- $srclist = "";
- foreach $src (@sources) {
- $srclist .= "\${SEXPRROOT}/$src ";
- }
- print TMPUSERDEF "SILOON_USER_SOURCES=$srclist\n";
- } else {
- if (/^SILOON_USER_LIBRARIES=/) {
- print TMPUSERDEF "SILOON_USER_LIBRARIES=-L\${SEXPRROOT} ".
- "-lsexpr\n";
- } else {
- print TMPUSERDEF $_;
- }
- }
- }
-}
-
-close(USERDEF);
-close(TMPUSERDEF);
-
-# move the temp user.defs into place
-system("mv /tmp/__user.defs ./user.defs");
-
-##
-## run siloon parse on each source file
-##
-system("make pdb");
-
-# now, for the version I'm using we need to fix the files...
-
-$srcdir = $curdir."/../src";
-
-foreach $src (@sources) {
- if (-e $srcdir."/".$src.".pdb") {
- print "Fixing $src.pdb\n";
- $src =~ s/.c$//g;
- $cmd = "mv ".$srcdir."/".$src.".c.pdb ./".$src.".pdb";
- system($cmd);
- }
-}
-
-##
-## run siloon-gen
-##
-
-system($siloon."/bin/siloon-gen sexpr.pdb");
-
-##
-## build prototypes.doinclude
-##
-
-foreach $fn (@functions) {
- system("grep $fn prototypes.excluded >> prototypes.doinclude");
-}
diff --git a/src/Makefile.am b/src/Makefile.am
index f577ba3..462ee03 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,8 +1,7 @@
CFLAGS = $(SFSEXP_CFLAGS)
CPPFLAGS = $(SFSEXP_CPPFLAGS)
-LDFLAGS =
lib_LTLIBRARIES = libsexp.la
-include_HEADERS = sexp.h sexp_vis.h sexp_ops.h sexp_memory.h sexp_errors.h cstring.h faststack.h
+pkginclude_HEADERS = sexp.h sexp_vis.h sexp_ops.h sexp_memory.h sexp_errors.h cstring.h faststack.h
libsexp_la_SOURCES = cstring.c cstring.h event_temp.c faststack.c faststack.h io.c parser.c sexp.c sexp.h sexp_memory.c sexp_memory.h sexp_errors.h sexp_ops.c sexp_ops.h sexp_vis.c sexp_vis.h
libsexp_la_LDFLAGS = -version-info 1:0:0
diff --git a/test_builds.sh b/test_builds.sh
index e44df37..76223b1 100755
--- a/test_builds.sh
+++ b/test_builds.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
if [ ! -f ./configure ]; then
echo "Generate configure first. See INSTALL."
@@ -9,7 +9,7 @@ if [ -f ./Makefile ]; then
make distclean
fi
-./configure
+./configure --enable-thread-unsafe-memory-management
make
cd tests
./check_leaks.sh
@@ -18,7 +18,7 @@ cd ../examples
cd ..
make distclean
-./configure --enable-debug
+./configure --enable-debug --enable-thread-unsafe-memory-management
make
cd tests
./check_leaks.sh
@@ -27,7 +27,7 @@ cd ../examples
cd ..
make distclean
-CFLAGS=-D_NO_MEMORY_MANAGEMENT_ ./configure
+./configure
make
cd tests
./check_leaks.sh
@@ -36,7 +36,7 @@ cd ../examples
cd ..
make distclean
-CFLAGS=-D_NO_MEMORY_MANAGEMENT_ ./configure --enable-debug
+./configure --enable-debug
make
cd tests
./check_leaks.sh
diff --git a/tests/check_leaks.sh b/tests/check_leaks.sh
index a2d73ff..dcecf23 100755
--- a/tests/check_leaks.sh
+++ b/tests/check_leaks.sh
@@ -1,12 +1,20 @@
-#!/bin/bash
+#!/usr/bin/env bash
+
+# if valgrind isn't present we can't proceed - otherwise
+# we get a cascade of command not found failures
+if ! command -v valgrind &> /dev/null
+then
+ echo "cannot continue: valgrind could not be found"
+ exit
+fi
function test {
- valgrind --leak-check=full --show-reachable=yes -q "$@" > /dev/null
+ libtool --mode=execute valgrind --leak-check=full --show-reachable=yes -q "$@" > /dev/null
status=$?
if [ $status -ne 0 ]; then
echo "error with $1"
else
- echo "no error with $1"
+ echo "no error with $1"
fi
return $status
}
@@ -14,7 +22,7 @@ function test {
test ./ctest
## note: need to keep iteration count for ctorture low here
-## due to performance overhead of valgrind.
+## due to performance overhead of valgrind.
perl ./randsexp.pl 200 40000 0.4 > /tmp/SEXP.SKINNY
test ./ctorture -i 10 -f /tmp/SEXP.SKINNY
rm -f /tmp/SEXP.SKINNY
diff --git a/www/index.html b/www/index.html
deleted file mode 100644
index 11d41db..0000000
--- a/www/index.html
+++ /dev/null
@@ -1,544 +0,0 @@
-<HTML>
-<HEAD>
- <TITLE>sfsexp home page</TITLE>
-</HEAD>
-
-<BODY>
-
-<A NAME="top"></A>
-<CENTER>
-<TABLE WIDTH=75% BORDER=2>
-<TR><TD BGCOLOR="#d0d0ff">
-<CENTER>
-<H2>sfsexp</H2>
-<h3>the small, fast s-expression library</H3><br>
-
-Written by Matthew Sottile (<A HREF="mailto:matt@cs.uoregon.edu">matt@cs.uoregon.edu</A>)<BR>
-<A HREF="http://www.cs.uoregon.edu/">Univ. of Oregon Computer Science Dept.</A><P>
-<I>Latest version: 1.2 (October 25, 2007)</I><BR>
-[<A HREF="http://sourceforge.net/projects/sexpr/">Return to Project Page</A>]
-<P>
-</CENTER>
-</TD></TR></TABLE><P>
-
-<TABLE WIDTH=50% BORDER=1>
-<TR><TH BGCOLOR="#ffffff"><B>Table of Contents</B></TH></TR>
-<TR><TD>
-<OL>
-<LI><A HREF="#sec1">Overview</A></LI>
-<LI><A HREF="#sec2">Use Cases</A></LI>
-<LI><A HREF="#sec3">Implementation details</A></LI>
-<LI><A HREF="#sec4">API documentation</A></LI>
-<LI><A HREF="#sec5">Questions</A></LI>
-</OL>
-</TD></TR>
-</TABLE><P>
-</CENTER>
-
-<CENTER><HR WIDTH=65%></CENTER>
-<P>
-
-<A NAME="sec1"></A>
-<H3>1. Overview</H3>
-
-<BLOCKQUOTE>
-
-This library is intended for developers who wish to manipulate (read, parse,
-modify, and create) symbolic expressions from C or C++ programs. A symbolic
-expression, or s-expression, is essentially a LISP-like expression such as
-<B>(a (b c))</B>. S-expressions are able to represent complex, structured data
-without requiring additional meta-data describing the structure. They are
-recursively defined: an s-expression is a list of either <I>atoms</I> or
-s-expressions. In the example above, the expression contains an atom "a" and
-an s-expression, which in turn contains two atoms, "b" and "c". They are
-simple, useful, and well understood.<P>
-
-This library is intended to be a minimal set of functions and structures for
-the four functions listed above: reading s-expressions (I/O), parsing strings
-containing them into an AST equivalent, modifying the AST representation,
-and converting the AST back into a well formatted string. The primary goals
-are <B>efficiency</B> and <B>simplicity</B>. This library forms the basis
-of the data representation and transmission protocol for the
-<A HREF="http://www.acl.lanl.gov/supermon/">supermon</A> high-speed
-cluster monitoring system from the LANL ACL. The usefulness and lack of
-choice in available, open source s-expression libraries motivated the
-independent (from supermon) release of this library. Although the number
-of potential users represents a rather small community, the author felt
-it was a valuable contribution. As of March 2005, this library has actually
-received more interest in terms of downloads and page views than it's
-parent project! <P>
-<I>Update July 2007:</I> sfsexp is still ahead of it's
-parent project. Not bad considering that the parent project was published
-a few times, part of a 2005 R&D 100 award winning project, and somewhat known
-in the high-performance computing community -- while sfsexp
-has not been advertised at all! Cool!<P>
-
-This work was funded by the Department of Energy, Office of Science.
-It is currently maintained independently of any funding source for
-the community.
-
-</BLOCKQUOTE>
-
-<H4>1.1. Revision Information</H4>
-
-Starting with version 1.2 (October 2007), I will provide documentation
-of the most recent revisions here. Detailed notes are available from
-the file releases and news items, but the most important items will be
-highlighted here.
-
-
-<B> Version 1.1 -> 1.2 </B><P>
-
-<UL>
-<LI>Introduction of <tt>sexp_errors.h</tt>, corresponding
- <tt>sexp_errcode_t</tt> type, the library errno variable
- <tt>sexp_errno</tt> and the <tt>error</tt> field in the
- <tt>pcont_t</tt> structure. This is the biggest revision to the
- library. Instead of asserting or <tt>fprintf()</tt> and exiting,
- the library attempts to gracefully return to the caller providing
- error cause information via the <tt>sexp_errno</tt> and error
- fields.</LI>
-
-<LI>Removed deprecated functions, removed testers for corresponding
- functions. Functions removed were <tt>cons</tt>, <tt>car</tt> and
- <tt>cdr</tt>.</LI>
-
-<LI>Event-based parsing is removed for now from the main source files.
- callbacks still exist, but the full parser based on events was
- removed. the original implementation essentially required a
- duplicate <tt>parse_sexp()</tt> function, which seemed like a recipe
- for version skew and disaster. this limits the ability to parse
- infinite streams of s-expressions, but I'd rather get it right than
- to have the suboptimal solution in the distribution. the code is
- still available in the <tt>src/event_temp.c</tt> file, but not in
- the main parser files.</LI>
-
-<LI> Revised comments and documentation to reflect my new location at
- the University of Oregon, Computer Science Department after departing
- Los Alamos National Laboratory in September 2007.</LI>
-
-<LI> Patched multiple bugs related to missed <tt>NULL</tt> checks and
- memory management issues. Most users will not have encountered these,
- as many occurred in unusual circumstances.</LI>
-
-</UL>
-
-[<A HREF="#top">Return to top</A>]<P>
-
-
-<A NAME="sec2"></A>
-<H3>2. Use Cases</H3>
-
-The two most appropriate and common uses of this library are for data
-structure representation and network protocols. It's a trivial step
-from a data structure (C struct, C++ class, or F95 user-defined type)
-to s-expression representation. For example, the following are very easy
-to represent as s-expressions:
-
-<UL>
-<LI>Trees
-<LI>Arbitrary directed or un-directed graphs
-<LI>Lists
-<LI>Dictionaries, or hash-tables
-</UL>
-
-Quite often one will want to have a way to save and restore structures
-to and from disk, or transmit a data structure over a network between
-two applications. This naturally leads to network protocols where
-structurally non-trivial data is passed back and forth. The
-s-expression allows data to be stored internally in a format that
-mimics the original data structure, and transmitted in an efficiently
-parsed and unparsed format. Furthermore, this library extends the
-basic s-expression to allow inlined binary data, removing the need to
-encode binary data (such as images) before sending. Such binary
-payloads are easily encapsulated in the s-expression format without
-marshalling to ASCII or other non-binary formats.<P>
-
-Furthermore, data structures sent over the wire as s-expressions are
-not prone to differences in architecture. Unlike systems that send
-pure binary and are based on the assumption that structures are laid
-out consistently between languages and platforms, the s-expression is
-<I>portable</I> with minimal overhead to achive this portable
-representation. There is an innevitable trade-off in byte efficiency
-with s-expressions versus raw-binary, but unlike other representations (such
-as XML) it is mininal. Parsing is also simpler than XML or other 'document
-markup languages'. Also note that portability goes out the window with
-inlined binary, at least in terms of byte ordering. <P>
-
-Example uses of this library that have been made available to the author
-include:<P>
-
-<UL>
-<LI>Tools for teaching high-school geometry (examples/simple_interp.c)
-<LI>Interpreters for subsets of LISP or Scheme
-<LI>Neural network state storage and retrieval
-<LI>Simulation geometry setup for cellular automata
-<LI>"Input deck" parameter files for simulations
-<LI>Wire protocol for cluster monitoring (Supermon)
-<LI>Wire protocol for transmitting image data from source to processor.
-</UL><P>
-
-Feel free to send your applications along to include here!<P>
-
-<P>
-[<A HREF="#top">Return to top</A>]<P>
-
-<A NAME="sec3"></A>
-<H3>3. Implementation details</H3>
-
-<BLOCKQUOTE>
-An s-expression is an expression composed of elements that are either
-atoms or s-expressions. For example, the following are s-expressions
-containing two elements:
-
-<PRE>
- (a b)
- (a (b c))
- ((a b) (c d))
- (() ())
-</PRE>
-
-In the first case, the s-expression contains two atoms, the strings "a" and
-"b". The second example is contains an atom and another s-expression (which
-contains two atoms). The third example is composed of two other s-expressions.
-The final contains two empty s-expressions.
-
-One possible representation of these expressions is as nested lists, where
-a single element of a list is captured in the structure:
-
-<PRE>
- struct elt {
- int type;
- char *val;
- struct elt *list;
- struct elt *next;
- };
-</PRE>
-
-Since an element can be either a list or atom, the element structure has a
-type indicator that can be either LIST or VALUE. If the type indicator is
-LIST, then the structure member "list" will be a pointer to the head of the
-list represented by this element. If the type indicator is VALUE, then the
-structure member "val" will contain the atom represented by the element
-as a string. In both cases, the "next" pointer will point at the next element
-of the current s-expression.
-
-The following rough illustration shows how the expression (a (b c)) is
-translated to the structures above.
-
-<PRE>
-+----+------+-------+
-|LIST|list=o|next=o--->NULL
-+----+-----|+-------+
- |
- +-------+
- |
- v
-+-----+-------+-------+ +----+------+-------+
-|VALUE|val="a"|next=o--->|LIST|list=o|next=o--->NULL
-+-----+-------+-------+ +----+-----|+-------+
- |
- +----------+
- |
- v
- +-----+-------+-------+ +-----+-------+-------+
- +VALUE|val="b"|next=o--->|VALUE|val="c"|next=o--->NULL
- +-----+-------+-------+ +-----+-------+-------+
-</PRE>
-
-(note: o---> represents a pointer)
-
-The actual structures are slightly more complex to deal with variable size
-values in atoms, but those fields aren't necessary to express the basic
-idea of the structures.<P>
-
-<I><B>New! (12/20/04)</B></I>: A new function, <tt>sexp_to_dotfile()</tt> has
-been added to allow visualization of the sexp_t structures that represent
-the s-expressions using <a href="http://www.graphviz.org/">Graphviz</A>.
-This is very useful for debugging. To further illustrate how the structure
-of an s-expression is represented by the library, the
-<A HREf="sexpexample.png">example available here</A> shows the structure
-corresponding with the following:<P>
-
-<PRE>
-;
-; example input for sexpvis sample code
-;
-(
- (this (is a nested) list)
- (and this "has a dquote" in it)
- '(squote here)
-)
-</PRE>
-
-</BLOCKQUOTE>
-
-[<A HREF="#top">Return to top</A>]<P>
-
-
-
-<A NAME="sec4"></A>
-<H3>4. API documentation</H3>
-
-<BLOCKQUOTE>
-All of the API docs are now produced by DOxygen in two formats:<BR>
-
-<UL>
-<LI><A HREF="sexpr_1.1.pdf">PDF</A>
-<LI><A HREF="refman/index.html">HTML</A> (online only - not downloadable)
-</UL>
-
-</BLOCKQUOTE>
-
-<A NAME="ruby"></A>
-<H4>3.1. Ruby language bindings</H4>
-
-<BLOCKQUOTE>
-
-The ruby bindings are available in the src/ruby subdirectory of the
-source distribution.
-The following
-is a transcript of an interactive ruby session using the s-expression
-library:<P>
-
-<PRE>
-irb(main):001:0> require "Sexp";
-irb(main):002:0* s = Sexp.new("(simple s-expression (int 42) (float 22.3))");
-irb(main):003:0* s.getStr
-"(simple s-expression (int 42) (float 22.3))"
-irb(main):004:0> sary = s.getAry
-["simple", "s-expression", ["int", 42], ["float", 22.3]]
-irb(main):005:0> sary[3][1] = 33.2;
-irb(main):006:0* sary[3][0] = "newfloat";
-irb(main):007:0* sary
-["simple", "s-expression", ["int", 42], ["newfloat", 33.2]]
-irb(main):008:0> s.setAry(sary);
-irb(main):009:0* s.unparse;
-irb(main):010:0* s.getStr
-"(simple s-expression (int 42) (newfloat 33.200000))"
-irb(main):011:0>
-</PRE>
-<P>
-
-</BLOCKQUOTE>
-
-[<A HREF="#top">Return to top</A>]<P>
-
-
-
-<A NAME="sec5"></A>
-<H3>5. Questions</H3>
-
-<BLOCKQUOTE>
-<B>Why is it called "Smaller"?</B><BR>
-
-Well, when I initially started looking for a way to manipulate
-s-expressions from C, I found some libraries that existed.
-Unfortunately, they were big. All I wanted was the ability to take a
-string representation of an s-expression, turn it into a linked data
-structure that is easy to walk and modify in C, and then turn that
-back into a string. So, this library lets you do exactly that. It's
-a bit bigger than before, but for most purposes a developer will only
-use three or four of the routines it provides - parse, print, destroy,
-and find. Others exist for different types of parsing or operations
-on the linked sexp_t data structure, but they're not necessary for
-all users.<P>
-
-<B>What is a continuation?</B><BR>
-
-Many definitions probably exist out there for this, and most people
-have likely seen continuations in languages like Scheme, ML, or others
-that have a little function called <tt>callcc</tt>. The idea is that
-a continuation represents state - in our case, the continuation
-contains the state of the parser when it exits. For example, if you
-have a very large s-expression being read off of a socket, you might
-not get the entire string in a single read call. Now, you can either
-accumulate the string into a buffer until it is complete, or you can
-tell the parser to start parsing the incomplete string. The trick is,
-when the next string-chunk comes in, you want to tell the parser
-"here's more data, and pick up where you left off." This involves
-restoring the stack the parser uses to put the linked structures onto
-while it works, restore the proper state (IE: was it parsing a simple
-atom or a quoted string?), and do other things to get it going again.
-Once the continuation has restored the state, the parser picks up and
-acts just like it would as if the whole s-expression string had been
-passed in at once. Clear? If not, you *probably* don't need to use
-this feature. In our case, we wanted to have multiple sockets all
-providing partial s-expressions, so the parser had to 1) not have any
-global state and 2) be able to pick up where each socket left off on
-each incomplete string. In addition, it had to be able to do this
-with minimal performance loss. So, we have a continuation based
-parser that takes a continuation and returns one, and the contents of
-the structure tell you about the state of the parser and the string
-being parsed.<P>
-
-<B>Why would I use this library instead of just using
-LISP/Scheme/Emacs/etc.?</B><BR>
-
-A few reasons - it's small, it has a tiny API, and it is fast. It
-isn't a language interpreter. It is just a way of efficiently
-manipulating LISP like expressions in a language like C. How many
-times have you wished for a <tt>cons</tt> operator in C? Or maybe a
-way of having lists of lists and atoms that was easy to deal with?
-Well, s-expressions are good for that. How about structured data? A
-tree in s-expression land is trivial to represent, as are more complex
-structures. In many ways, the structure of an s-expression might look
-close to XML, with parentheses in place of angle-bracketed tags. If
-you have an application that wants to pass around, parse, and
-manipulate complex data structures in a platform independent
-(non-binary) way, s-expressions are the easy way to do it. And again,
-they're fast. Oh yes, since you can create valid s-expressions with
-this library, there's no reason why you can't just feed them to a
-program in LISP or Emacs and start using them from there. It might
-involve a strategically placed <tt>setq</tt> or the like, but it's
-easy.<P>
-
-<B>Why not XML?</B><BR>
-
-The goal of any project should be to solve a problem in an elegant, well
-designed manner. Buzzword compliance rarely achieves this, other than
-allowing a lowly programmer or software engineer to appease higher-ups
-who read that "XML is the latest great thing!" XML suffers from
-certain flaws that make it worthless in an environment where speed and
-efficiency (memory and time complexity) are key requirements. Compare
-the performance, footprint, and developer complexity of Xerces and this
-s-expression library, and you'll see that for hierarchical data
-representation, one is significantly simpler than the other without losing
-the ability to do its job (represent data!). After working with XML for
-a while (~3-4 years) on multiple projects, I find that since starting to
-use s-expressions again as a data format has allowed me to spend less time
-debugging my data representation code and more time on problems that
-matter. <P>
-
-<B>How fast is this library?</B><BR>
-
-<B><I>Updated 11/5/02</I></B>: I've been meaning to update the
-answer to this question for a while. The library has undergone many
-optimizations since continuations were added, including self-contained
-memory management to avoid excessive malloc/free calls. The while
-loop of the parser now really does examine each character just once.
-Testing using the <TT>{c}torture.c</TT> tester included with the package
-yielded these results, which I give for each version released for
-comparison.<P>
-
-<CENTER>
-<TABLE CELLPADDING=5 CELLSPACING=5 BORDER=1>
-<TR><TH>Version</TH><TH>Average time(5 runs)</TH></TR>
-<TR><TD>0.1.1</TD><TD>1.61s</TD></TR>
-<TR><TD>0.1.2</TD><TD>1.12s</TD></TR>
-<TR><TD>0.2.0</TD><TD>1.07s</TD></TR>
-<TR><TD>0.2.1</TD><TD>1.09s</TD></TR>
-<TR><TD>0.2.2</TD><TD>1.09s</TD></TR>
-<TR><TD>0.2.3</TD><TD>1.11s</TD></TR>
-<TR><TD>0.3.0</TD><TD>0.42s</TD></TR>
-<TR><TD>0.3.1</TD><TD>0.70s</TD></TR>
-</TABLE><BR>
-<I>* Expression contained 380 elements, roughly equivalent to a full data
-set sample of 4 nodes using supermon</I><P>
-</CENTER>
-
-Each iteration of the test would parse the expression, unparse the AST
-back into a string and destroy the AST. This was performed 1,000 times
-and the required time averaged over 5 runs is shown above. Version
-0.3.0 has every optimization thus far applied, although the one that
-proved most beneficial was the efficient memory management addition.
-Version 0.3.1 is slightly slower due to memory allocation operations that
-do NOT take advantage of the faster memory management but were added
-to remove the need for fixed-length buffers in sexp_t elements.
-<P>
-
-<B>So why is this project on sourceforge?</B><BR>
-To tell the truth, it's not really necessary to have it up here but I did
-so for two big reasons:<BR>
-<OL>
-<LI>I wanted to learn how to use sourceforge before putting a really big,
-complicated project up on it.
-<LI>The library is useful for more than just supermon - so if anyone wants
-to play with it, they can get the standalone version.
-</OL><BR>
-So there it is.<P>
-
-<B>Why did you bother writing this?</B><BR>
-
-This is one of those annoying questions that pops up occasionally. A
-quick search on google yields only one other obvious candidate: <A
-HREF="http://theory.lcs.mit.edu/~rivest/sexp.html">Rivest's SEXP
-Library</A>. A quick look at the example code and guide to using this
-library shows that his library is far more complex due to it's purpose
-in cryptographic applications. All other references that I found for
-libraries to deal with s-expressions from C or C++ involve embedding
-GUILE or some other scheme/LISP interpreter in the application. For
-most purposes, this is overkill. In other languages, solutions exist.
-For example, in Java, the W3C web pages have references to a java
-package for dealing with s-expressions. In LISP or Scheme, the answer
-is obvious. In ML, a basic translation of LISP to ML should work fine
-since ML lists act in many ways like s-expressions. So no, this
-library isn't a waste of time in my opinion. Besides, how many times
-have you found many implementations of things like arbitrary precision
-arithmetic, window managers, GUI toolkits, etc... Each has its place
-and purpose and was written for a real reason. A final reason is that
-it is doubtful that many (if any) other s-expression parsers support
-continuations or some other form of partial parsing to be implemented.
-This is exceptionally useful when parsing off of a socket stream where
-the programmer doesn't have the space or desire to wait until the
-entire expression has been received before starting the parsing
-process.<P>
-
-<B>Why is an unquoted word not a valid atom on its own?</B><BR>
-
-The following are atoms that do not exist within parenthesis:<P>
-<OL>
-<LI>"example one"
-<LI>'(example two)
-<LI>example_three
-</OL><P>
-
-The first and second are valid and will be returned if those string are
-passed into the parser. Furthermore, they can be parsed and unparsed
-repeatedly and remain valid and unchanged over a number of iterations.
-The third example will ONLY parse if the last character of the string is
-whitespace or a carriage return. This is the only way to cue the parser into
-knowing that the string is in fact complete, and not to wait to see if the
-next call with the current continuation will introduce more characters to
-parse. Unfortunately, since whitespace and carriage returns are not considered
-part of the atom itself, when an atom is parsed that is followed by those
-characters, they do not appear in the unparsed version of that atom! This
-means that although it is possible to parse an expression such as:<P>
-
-<BLOCKQUOTE>
-<PRE>simple_atom\n</PRE>
-</BLOCKQUOTE><P>
-
-Unparsing it will result in:
-
-<BLOCKQUOTE>
-<PRE>simple_atom</PRE>
-</BLOCKQUOTE><P>
-
-Which will not parse to the same result as the first. This is valid
-behaviour due to the semantics of the continuation based parser.
-<P>
-
-<B>My code crashes in the parser with a core dump, segementation fault,
-assertion, or mysterious parser error message.</B><BR>
-
-First, make sure you're passing a valid s-expression in. If this is the
-case (or you believe it to be the case), send me the s-expression
-and the code (or some code) that can reproduce the error. A note saying
-"the parser died with such-and-such error message" is of little use
-in tracking the problem. I'm not psychic! :)
-<P>
-
-</BLOCKQUOTE>
-
-[<A HREF="#top">Return to top</A>]<P>
-
-<CENTER><HR WIDTH=65%></CENTER>
-
-<A href="http://sourceforge.net"> <IMG
- src="http://sourceforge.net/sflogo.php?group_id=48119"
- width="210" height="62" border="0" alt="SourceForge Logo"></A>
-
-</BODY>
-
-</HTML>