GC_PROTECT some variables.
This commit is contained in:
parent
37210efdc5
commit
3e397f65c5
|
|
@ -26,3 +26,11 @@ _$*
|
||||||
*.ln
|
*.ln
|
||||||
core
|
core
|
||||||
# CVS default ignores end
|
# CVS default ignores end
|
||||||
|
Makefile
|
||||||
|
configure
|
||||||
|
config.log
|
||||||
|
config.cache
|
||||||
|
config.status
|
||||||
|
scsh.image
|
||||||
|
scshvm
|
||||||
|
go
|
||||||
|
|
|
||||||
7
COPYING
7
COPYING
|
|
@ -1,4 +1,8 @@
|
||||||
Copyright (c) 1993-1999 Richard Kelsey and Jonathan Rees
|
Copyright (c) 1993-2002 Richard Kelsey and Jonathan Rees
|
||||||
|
Copyright (c) 1994-2002 by Olin Shivers and Brian D. Carlstrom.
|
||||||
|
Copyright (c) 1999-2002 by Martin Gasbichler.
|
||||||
|
Copyright (c) 2001-2002 by Michael Sperber.
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
|
@ -23,7 +27,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
|
||||||
Distributing Autoconf Output
|
Distributing Autoconf Output
|
||||||
****************************
|
****************************
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Welcome to the Scsh CVS Repository !!!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
This file contains some instructions about how to build Scsh after you
|
||||||
|
freshly checked out the "scsh-0.6" module. These instructions do *not*
|
||||||
|
apply to the module named "scsh" or the Scsh distribution itself.
|
||||||
|
|
||||||
|
There is currently no scheme to tag working snapshots of the
|
||||||
|
repository, so anything may happen during the build process. The scsh
|
||||||
|
team does in general *not* provide support for code obtained from the
|
||||||
|
CVS repository.
|
||||||
|
|
||||||
|
During the build process a number of auto-generated files not included
|
||||||
|
in the CVS repository are built. It is highly recommended to follow
|
||||||
|
these instructions carefully as otherwise incompatible versions of
|
||||||
|
generated files may result. Note that you need GNU make for this
|
||||||
|
process.
|
||||||
|
|
||||||
|
To build Scsh, proceed as follows:
|
||||||
|
|
||||||
|
1.) You must have a working version of Scheme 48, version 0.53. Nothing
|
||||||
|
older, nothing newer. Just 0.53. If you don't have, get it from
|
||||||
|
http://www.s48.org/0.53/scheme48-0.53.tgz and install Scheme
|
||||||
|
48. Change to value of the variable BUILD_RUNNABLE in Makefile.in
|
||||||
|
so that it will point to the Scheme 48 executable.
|
||||||
|
|
||||||
|
2.) "cd" into the directory which contains the source code (normally
|
||||||
|
scsh-0.6) and run the script autogen.sh:
|
||||||
|
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
This will take several minutes and generate the source code for
|
||||||
|
the virtual machine and two images the Makefile relies
|
||||||
|
on. Furthermore the configure file will be generated. This script
|
||||||
|
calls autoheader and autoconf from the GNU Autoconf package. You
|
||||||
|
will need a recent version of Autoconf. Version 2.52 is okay,
|
||||||
|
version 2.13 is too old.
|
||||||
|
|
||||||
|
3.) Configure the system:
|
||||||
|
|
||||||
|
./configure
|
||||||
|
|
||||||
|
You presumably want to add the --prefix flag here to determine the
|
||||||
|
installation directory. This will generate the Makefile.
|
||||||
|
|
||||||
|
4.) Build the system:
|
||||||
|
|
||||||
|
make
|
||||||
|
|
||||||
|
If anything fails here, fix the problem and/or contact the authors.
|
||||||
|
|
||||||
|
5.) You should have a runnable version of the system that can be
|
||||||
|
started in the main directory like this:
|
||||||
|
|
||||||
|
./go
|
||||||
|
|
||||||
|
6.) To install Scsh, type:
|
||||||
|
|
||||||
|
make install
|
||||||
|
|
||||||
|
Note that it is not recommended to have a CVS version of Scsh for
|
||||||
|
daily use.
|
||||||
|
|
||||||
|
7.) If you intend to build on a different platform later, do a
|
||||||
|
|
||||||
|
make distclean
|
||||||
|
|
||||||
|
and restart at step 3.
|
||||||
|
|
||||||
|
|
||||||
|
You should repeat the whole build process whenever there are changes
|
||||||
|
to files in the directories scheme/vm, scheme/rts or
|
||||||
|
scheme/bcomp. Watch the run of cvs update carefully and/or subscribe
|
||||||
|
to the list scsh-checkins@lists.sourceforge.net.
|
||||||
|
|
||||||
|
|
||||||
|
Enjoy!!!
|
||||||
|
|
||||||
|
|
||||||
|
The Scsh developers
|
||||||
|
|
||||||
133
INSTALL
133
INSTALL
|
|
@ -1,120 +1,49 @@
|
||||||
This is a generic INSTALL file for utilities distributions.
|
Installing scsh
|
||||||
If this package does not come with, e.g., installable documentation or
|
|
||||||
data files, please ignore the references to them below.
|
|
||||||
|
|
||||||
[For information specific to Scheme 48, see doc/install.txt.]
|
This file describes how to install scsh from the source package. If
|
||||||
|
you have obtained the source tree from CVS refer to the file
|
||||||
The `configure' shell script attempts to guess correct values for
|
CVS_README.
|
||||||
various system-dependent variables used during compilation, and
|
|
||||||
creates the Makefile(s) (one in each subdirectory of the source
|
|
||||||
directory). In some packages it creates a C header file containing
|
|
||||||
system-dependent definitions. It also creates a file `config.status'
|
|
||||||
that you can run in the future to recreate the current configuration.
|
|
||||||
|
|
||||||
To compile this package:
|
|
||||||
|
|
||||||
1. Configure the package for your system.
|
1. Configure the package for your system.
|
||||||
|
|
||||||
Normally, you just `cd' to the directory containing the package's
|
Just `cd' to the directory containing this README file and type
|
||||||
source code and type `./configure'. If you're using `csh' on an old
|
|
||||||
version of System V, you might need to type `sh configure' instead to
|
|
||||||
prevent `csh' from trying to execute `configure' itself.
|
|
||||||
|
|
||||||
Running `configure' takes a minute or two. While it is running, it
|
./configure
|
||||||
prints some messages that tell what it is doing. If you don't want to
|
|
||||||
see the messages, run `configure' with its standard output redirected
|
|
||||||
to `/dev/null'; for example, `./configure >/dev/null'.
|
|
||||||
|
|
||||||
To compile the package in a different directory from the one
|
You can pass some additional options to the configure script, along
|
||||||
containing the source code, you must use a version of `make' that
|
them the installation directory with the
|
||||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
--prefix=/my/install/location option. Type ./configure --help to
|
||||||
directory where you want the object files and executables to go and run
|
get a list of all switches.
|
||||||
the `configure' script. `configure' automatically checks for the
|
Running `configure' takes a minute or two. While it is running, it
|
||||||
source code in the directory that `configure' is in and in `..'. If
|
prints some messages that tell what it is doing. Consult the file
|
||||||
for some reason `configure' is not in the source code directory that
|
config.log if anything went wrong.
|
||||||
you are configuring, then it will report that it can't find the source
|
|
||||||
code. In that case, run `configure' with the option `--srcdir=DIR',
|
|
||||||
where DIR is the directory that contains the source code.
|
|
||||||
|
|
||||||
By default, `make install' will install the package's files in
|
2. Type
|
||||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
|
||||||
installation prefix other than `/usr/local' by giving `configure' the
|
|
||||||
option `--prefix=PATH'. Alternately, you can do so by consistently
|
|
||||||
giving a value for the `prefix' variable when you run `make', e.g.,
|
|
||||||
make prefix=/usr/gnu
|
|
||||||
make prefix=/usr/gnu install
|
|
||||||
|
|
||||||
You can specify separate installation prefixes for
|
make
|
||||||
architecture-specific files and architecture-independent files. If you
|
|
||||||
give `configure' the option `--exec-prefix=PATH' or set the `make'
|
|
||||||
variable `exec_prefix' to PATH, the package will use PATH as the prefix
|
|
||||||
for installing programs and libraries. Data files and documentation
|
|
||||||
will still use the regular prefix. Normally, all files are installed
|
|
||||||
using the same prefix.
|
|
||||||
|
|
||||||
Some packages pay attention to `--with-PACKAGE' options to
|
to compile scsh.
|
||||||
`configure', where PACKAGE is something like `gnu-as' or `x' (for the X
|
|
||||||
Window System). The README should mention any `--with-' options that
|
|
||||||
the package recognizes.
|
|
||||||
|
|
||||||
`configure' ignores any other arguments that you give it.
|
3. After a successful build you can invoke scsh by typing
|
||||||
|
|
||||||
On systems that require unusual options for compilation or linking
|
./go
|
||||||
that the package's `configure' script does not know about, you can give
|
|
||||||
`configure' initial values for variables by setting them in the
|
|
||||||
environment. In Bourne-compatible shells, you can do that on the
|
|
||||||
command line like this:
|
|
||||||
|
|
||||||
CC='gcc -traditional' LIBS=-lposix ./configure
|
You should see the command prompt of scsh which you can exit by
|
||||||
|
typing `,exit'.
|
||||||
|
|
||||||
Here are the `make' variables that you might want to override with
|
4. Type
|
||||||
environment variables when running `configure'.
|
|
||||||
|
|
||||||
For these variables, any value given in the environment overrides the
|
make install
|
||||||
value that `configure' would choose:
|
|
||||||
|
|
||||||
- Variable: CC
|
to install programs, data files, and documentation.
|
||||||
C compiler program. The default is `cc'.
|
|
||||||
|
|
||||||
- Variable: INSTALL
|
|
||||||
Program to use to install files. The default is `install' if you
|
|
||||||
have it, `cp' otherwise.
|
|
||||||
|
|
||||||
For these variables, any value given in the environment is added to
|
|
||||||
the value that `configure' chooses:
|
|
||||||
|
|
||||||
- Variable: DEFS
|
|
||||||
Configuration options, in the form `-Dfoo -Dbar...'. Do not use
|
|
||||||
this variable in packages that create a configuration header file.
|
|
||||||
|
|
||||||
- Variable: LIBS
|
|
||||||
Libraries to link with, in the form `-lfoo -lbar...'.
|
|
||||||
|
|
||||||
If you need to do unusual things to compile the package, we encourage
|
|
||||||
you to figure out how `configure' could check whether to do them, and
|
|
||||||
mail diffs or instructions to the address given in the README so we
|
|
||||||
can include them in the next release.
|
|
||||||
|
|
||||||
2. Type `make' to compile the package. If you want, you can override
|
|
||||||
the `make' variables CFLAGS and LDFLAGS like this:
|
|
||||||
|
|
||||||
make CFLAGS=-O2 LDFLAGS=-s
|
|
||||||
|
|
||||||
3. If the package comes with self-tests and you want to run them,
|
|
||||||
type `make check'. If you're not sure whether there are any, try it;
|
|
||||||
if `make' responds with something like
|
|
||||||
make: *** No way to make target `check'. Stop.
|
|
||||||
then the package does not come with self-tests.
|
|
||||||
|
|
||||||
4. Type `make install' to install programs, data files, and
|
|
||||||
documentation.
|
|
||||||
|
|
||||||
5. You can remove the program binaries and object files from the
|
5. You can remove the program binaries and object files from the
|
||||||
source directory by typing `make clean'. To also remove the
|
source directory by typing `make clean'. To also remove the
|
||||||
Makefile(s), the header file containing system-dependent definitions
|
Makefile, the header file containing system-dependent definitions
|
||||||
(if the package uses one), and `config.status' (all the files that
|
, `config.status' and `config.cache' (all the files that
|
||||||
`configure' created), type `make distclean'.
|
`configure' created), type `make distclean'.
|
||||||
|
|
||||||
The file `configure.in' is used to create `configure' by a program
|
For more information about scsh have a look into the README file and
|
||||||
called `autoconf'. You only need it if you want to regenerate
|
the documentation in the `doc/' directory. There you can also read
|
||||||
`configure' using a newer version of `autoconf'.
|
documentation about Scheme 48, the Scheme implementation scsh is based
|
||||||
|
on.
|
||||||
|
|
|
||||||
546
Makefile.in
546
Makefile.in
|
|
@ -1,4 +1,4 @@
|
||||||
# Scheme 48 Makefile
|
# Scsh Makefile
|
||||||
# Documentation in files INSTALL and doc/install.txt
|
# Documentation in files INSTALL and doc/install.txt
|
||||||
|
|
||||||
SHELL = /bin/sh
|
SHELL = /bin/sh
|
||||||
|
|
@ -14,18 +14,24 @@ INSTALL = @INSTALL@
|
||||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||||
INSTALL_DATA = @INSTALL_DATA@
|
INSTALL_DATA = @INSTALL_DATA@
|
||||||
|
|
||||||
LDFLAGS = @LDFLAGS@
|
LDFLAGS = -g @LDFLAGS@
|
||||||
LIBOBJS = @LIBOBJS@
|
LIBOBJS = @LIBOBJS@
|
||||||
|
|
||||||
|
RM = rm -f
|
||||||
|
|
||||||
|
AR = @AR@
|
||||||
|
RANLIB = @RANLIB@
|
||||||
|
|
||||||
prefix = @prefix@
|
prefix = @prefix@
|
||||||
exec_prefix = @exec_prefix@
|
exec_prefix = @exec_prefix@
|
||||||
|
bindir = @bindir@
|
||||||
|
libdir = @libdir@
|
||||||
|
incdir = @includedir@
|
||||||
|
manext = 1
|
||||||
|
mandir = @mandir@/man$(manext)
|
||||||
### End of `configure' section###
|
### End of `configure' section###
|
||||||
|
|
||||||
bindir = $(exec_prefix)/bin
|
htmldir = $(libdir)/scsh/doc/scsh-manual/html
|
||||||
libdir = $(exec_prefix)/lib
|
|
||||||
incdir = $(exec_prefix)/include
|
|
||||||
manext = 1
|
|
||||||
mandir = $(prefix)/man/man$(manext)
|
|
||||||
|
|
||||||
# HP 9000 series, if you don't have gcc
|
# HP 9000 series, if you don't have gcc
|
||||||
# CC = cc
|
# CC = cc
|
||||||
|
|
@ -36,10 +42,13 @@ mandir = $(prefix)/man/man$(manext)
|
||||||
# LDFLAGS = -N
|
# LDFLAGS = -N
|
||||||
|
|
||||||
.c.o:
|
.c.o:
|
||||||
$(CC) -c $(CPPFLAGS) $(DEFS) -I$(srcdir)/c $(CFLAGS) -o $@ $<
|
$(CC) -g -c $(DEFS) -I$(srcdir)/c -I$(srcdir)/cig $(CPPFLAGS) $(CFLAGS) -o $@ $<
|
||||||
|
|
||||||
# You might want to change RUNNABLE to "s48"
|
# BUILD_RUNNABLE has to be Scheme 48 0.53. This is used for builds directly
|
||||||
RUNNABLE = scheme48
|
# out of the CVS repository.
|
||||||
|
# We cannot use Scsh here since -i is not understood.
|
||||||
|
BUILD_RUNNABLE = /afs/wsi/i386_fbsd32/bin/scheme48
|
||||||
|
RUNNABLE = scsh
|
||||||
MANPAGE = $(RUNNABLE).$(manext)
|
MANPAGE = $(RUNNABLE).$(manext)
|
||||||
LIB = $(libdir)/$(RUNNABLE)
|
LIB = $(libdir)/$(RUNNABLE)
|
||||||
|
|
||||||
|
|
@ -68,13 +77,19 @@ include $(srcdir)/build/filenames.make
|
||||||
# LINKER_RUNNABLE = $(RUNNABLE)
|
# LINKER_RUNNABLE = $(RUNNABLE)
|
||||||
# These settings requires you to already have a $(RUNNABLE)
|
# These settings requires you to already have a $(RUNNABLE)
|
||||||
# command. This is desirable if you are making changes to the
|
# command. This is desirable if you are making changes to the
|
||||||
# system that might break scheme48vm and/or scheme48.image. But it
|
# system that might break scshvm and/or scsh/scsh.image. But it
|
||||||
# requires you to have squirreled away a previous working version
|
# requires you to have squirreled away a previous working version
|
||||||
# of scheme48.
|
# of scsh.
|
||||||
|
|
||||||
|
BIG_HEAP = -h 5500000
|
||||||
|
# 1. is broken if you build from CVS
|
||||||
|
# LINKER_VM = ./$(VM) $(BIG_HEAP)
|
||||||
|
# LINKER_RUNNABLE = $(LINKER_VM) -i $(IMAGE)
|
||||||
|
|
||||||
|
# therefore according to 2. but we cannot use scsh since -i is not understood
|
||||||
|
LINKER_VM = $(BUILD_RUNNABLE) $(BIG_HEAP)
|
||||||
|
LINKER_RUNNABLE = $(BUILD_RUNNABLE)
|
||||||
|
|
||||||
BIG_HEAP = -h 5000000
|
|
||||||
LINKER_VM = ./$(VM) $(BIG_HEAP)
|
|
||||||
LINKER_RUNNABLE = $(LINKER_VM) -i $(IMAGE)
|
|
||||||
LINKER_IMAGE = build/linker.image
|
LINKER_IMAGE = build/linker.image
|
||||||
LINKER = $(LINKER_VM) -i $(LINKER_IMAGE)
|
LINKER = $(LINKER_VM) -i $(LINKER_IMAGE)
|
||||||
START_LINKER = echo ',batch' && echo ',bench on'
|
START_LINKER = echo ',batch' && echo ',bench on'
|
||||||
|
|
@ -87,9 +102,55 @@ START_LINKER = echo ',batch' && echo ',bench on'
|
||||||
|
|
||||||
IMAGE = scheme48.image
|
IMAGE = scheme48.image
|
||||||
INITIAL = build/initial.image
|
INITIAL = build/initial.image
|
||||||
VM = scheme48vm
|
VM = scshvm
|
||||||
|
LIBCIG = cig/lib$(VM).a
|
||||||
|
CIG = cig/cig
|
||||||
|
CIGOBJS = cig/libcig.o cig/libcig1.o
|
||||||
|
|
||||||
|
#scsh-lib
|
||||||
|
LIBSCSHVM = scsh/lib$(VM).a
|
||||||
|
LIBSCSH = scsh/libscsh.a
|
||||||
|
SCSHVMHACKS = scsh/proc2.o
|
||||||
|
|
||||||
|
#
|
||||||
|
#
|
||||||
|
SCSHOBJS = \
|
||||||
|
scsh/cstuff.o \
|
||||||
|
scsh/dirstuff1.o \
|
||||||
|
scsh/fdports1.o \
|
||||||
|
scsh/flock1.o \
|
||||||
|
scsh/machine/time_dep1.o \
|
||||||
|
scsh/signals1.o \
|
||||||
|
scsh/machine/libansi.o \
|
||||||
|
scsh/network1.o \
|
||||||
|
scsh/putenv.o \
|
||||||
|
scsh/rx/regexp1.o \
|
||||||
|
scsh/sleep1.o \
|
||||||
|
scsh/syscalls1.o \
|
||||||
|
scsh/syslog1.o \
|
||||||
|
scsh/time1.o \
|
||||||
|
scsh/tty1.o \
|
||||||
|
scsh/userinfo1.o \
|
||||||
|
scsh/sighandlers1.o \
|
||||||
|
scsh/libscsh.o \
|
||||||
|
scsh/md5.o
|
||||||
|
|
||||||
|
SCSH_INITIALIZERS = s48_init_syslog s48_init_posix_regexp \
|
||||||
|
s48_init_userinfo s48_init_sighandlers \
|
||||||
|
s48_init_syscalls s48_init_network s48_init_flock \
|
||||||
|
s48_init_dirstuff s48_init_time s48_init_tty \
|
||||||
|
s48_init_cig s48_init_libscsh s48_init_md5
|
||||||
|
|
||||||
UNIX_OBJS = c/unix/misc.o c/unix/io.o c/unix/fd-io.o c/unix/event.o
|
UNIX_OBJS = c/unix/misc.o c/unix/io.o c/unix/fd-io.o c/unix/event.o
|
||||||
OBJS = c/scheme48vm.o c/scheme48heap.o c/extension.o c/external.o
|
|
||||||
|
SRFI_OBJS = c/srfi/srfi-27.o
|
||||||
|
|
||||||
|
SRFI_INITIALIZERS = s48_init_srfi_27
|
||||||
|
|
||||||
|
S48OBJS = c/scheme48vm.o c/scheme48heap.o c/extension.o c/external.o
|
||||||
|
OBJS = scsh/process_args.o c/init.o $(S48OBJS) $(CIGOBJS) $(SCSHOBJS) \
|
||||||
|
$(SCSHVMHACKS) $(SRFI_OBJS)
|
||||||
|
|
||||||
FAKEHS = c/fake/dlfcn.h c/fake/sigact.h c/fake/strerror.h \
|
FAKEHS = c/fake/dlfcn.h c/fake/sigact.h c/fake/strerror.h \
|
||||||
c/fake/sys-select.h
|
c/fake/sys-select.h
|
||||||
|
|
||||||
|
|
@ -102,7 +163,7 @@ CONFIG_FILES = scheme/interfaces.scm scheme/low-packages.scm \
|
||||||
|
|
||||||
# The following is the first rule and therefore the "make" command's
|
# The following is the first rule and therefore the "make" command's
|
||||||
# default target.
|
# default target.
|
||||||
enough: $(VM) $(IMAGE) go .notify
|
enough: $(VM) $(IMAGE) go $(LIBCIG) scsh $(LIBSCSH) $(LIBSCSHVM)
|
||||||
|
|
||||||
# --------------------
|
# --------------------
|
||||||
# External code to include in the VM
|
# External code to include in the VM
|
||||||
|
|
@ -110,7 +171,11 @@ enough: $(VM) $(IMAGE) go .notify
|
||||||
|
|
||||||
EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS)
|
EXTERNAL_OBJECTS = $(SOCKET_OBJECTS) $(LOOKUP_OBJECTS)
|
||||||
EXTERNAL_FLAGS = $(SOCKET_FLAGS)
|
EXTERNAL_FLAGS = $(SOCKET_FLAGS)
|
||||||
EXTERNAL_INITIALIZERS = $(SOCKET_INITIALIZERS) $(LOOKUP_INITIALIZERS)
|
EXTERNAL_INITIALIZERS = $(ADDITIONAL_INITIALIZER) $(SOCKET_INITIALIZERS) \
|
||||||
|
$(LOOKUP_INITIALIZERS) \
|
||||||
|
$(SCSH_INITIALIZERS) $(SRFI_INITIALIZERS) \
|
||||||
|
s48_init_cig
|
||||||
|
|
||||||
|
|
||||||
# Rules for any external code.
|
# Rules for any external code.
|
||||||
|
|
||||||
|
|
@ -132,15 +197,48 @@ LOOKUP_OBJECTS = c/unix/dynamo.o
|
||||||
LOOKUP_INITIALIZERS = s48_init_external_lookup
|
LOOKUP_INITIALIZERS = s48_init_external_lookup
|
||||||
|
|
||||||
# End of lookup rules
|
# End of lookup rules
|
||||||
|
|
||||||
|
# Initializer for s48_add_external_init
|
||||||
|
|
||||||
|
ADDITIONAL_INITIALIZER = s48_init_additional_inits
|
||||||
|
|
||||||
# End of external rules
|
# End of external rules
|
||||||
# --------------------
|
# --------------------
|
||||||
|
|
||||||
# The developers are curious to know. Don't be concerned if this fails.
|
# The developers are curious to know. Don't be concerned if this fails.
|
||||||
.notify: build/minor-version-number
|
.notify: build/minor-version-number
|
||||||
touch .notify
|
touch .notify
|
||||||
-echo Another 0.`cat $(srcdir)/build/minor-version-number` \
|
-echo SCSH 0.`cat $(srcdir)/scsh/minor-version-number` \
|
||||||
installation. \
|
Scheme48 0.`cat $(srcdir)/minor-version-number` infestation. \
|
||||||
| mail scheme-48-notifications@martigny.ai.mit.edu
|
| mail scheme-48-notifications@zurich.ai.mit.edu
|
||||||
|
-echo Another scsh 0.`cat $(srcdir)/scsh/minor-version-number` \
|
||||||
|
infestation. | mail scsh-notifications@zurich.ai.mit.edu
|
||||||
|
|
||||||
|
|
||||||
|
# This says how to process .scm files with cig to make .c stubs.
|
||||||
|
#.SUFFIXES: .scm
|
||||||
|
#.scm.c:
|
||||||
|
# $(srcdir)/$(VM) -o $(srcdir)/$(VM) -i $(CIG) < $< > $*.c
|
||||||
|
|
||||||
|
# These .h files mediate between the code exported from foo1.c
|
||||||
|
# and imported into foo.scm's stub foo.c.
|
||||||
|
|
||||||
|
scsh/dirstuff1.o: scsh/dirstuff1.h
|
||||||
|
scsh/userinfo1.o: scsh/userinfo1.h
|
||||||
|
scsh/network1o: scsh/network1.h
|
||||||
|
scsh/flock1.o: scsh/flock1.h
|
||||||
|
|
||||||
|
scsh/fdports1.o scsh/fdports.o: scsh/fdports1.h
|
||||||
|
|
||||||
|
scsh/rx/regexp1.o: c/scheme48.h
|
||||||
|
|
||||||
|
scsh/sighandlers1.o: scsh/sighandlers1.h
|
||||||
|
|
||||||
|
scsh/syslog1.o: c/scheme48.h
|
||||||
|
|
||||||
|
include $(srcdir)/scsh/machine/Makefile.inc
|
||||||
|
# Berkeley make wants to see this instead: (or use GNU make on BSD. -bri)
|
||||||
|
#.include "$(srcdir)/scsh/machine/Makefile.inc"
|
||||||
|
|
||||||
$(VM): c/main.o $(OBJS) $(UNIX_OBJS) $(LIBOBJS) $(EXTERNAL_OBJECTS)
|
$(VM): c/main.o $(OBJS) $(UNIX_OBJS) $(LIBOBJS) $(EXTERNAL_OBJECTS)
|
||||||
rm -f /tmp/s48_external_$$$$.c && \
|
rm -f /tmp/s48_external_$$$$.c && \
|
||||||
|
|
@ -148,15 +246,47 @@ $(VM): c/main.o $(OBJS) $(UNIX_OBJS) $(LIBOBJS) $(EXTERNAL_OBJECTS)
|
||||||
$(EXTERNAL_INITIALIZERS) && \
|
$(EXTERNAL_INITIALIZERS) && \
|
||||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ c/main.o $(OBJS) $(UNIX_OBJS) \
|
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ c/main.o $(OBJS) $(UNIX_OBJS) \
|
||||||
/tmp/s48_external_$$$$.c \
|
/tmp/s48_external_$$$$.c \
|
||||||
$(LIBOBJS) $(LIBS) \
|
$(EXTERNAL_OBJECTS) $(EXTERNAL_LD_FLAGS) \
|
||||||
$(EXTERNAL_OBJECTS) $(EXTERNAL_LD_FLAGS) && \
|
$(LIBOBJS) $(LIBS) && \
|
||||||
rm -f /tmp/s48_external_$$$$.c
|
rm -f /tmp/s48_external_$$$$.c
|
||||||
|
|
||||||
c/main.o: c/main.c c/scheme48vm.h c/scheme48heap.h
|
|
||||||
|
|
||||||
|
|
||||||
|
#JMG: again cig and scsh-lib
|
||||||
|
$(LIBCIG): c/main.o $(OBJS)
|
||||||
|
# $(CC) -r -o $@ main.o $(OBJS)
|
||||||
|
$(RM) $@
|
||||||
|
$(AR) $@ c/main.o $(OBJS)
|
||||||
|
$(RANLIB) $@
|
||||||
|
|
||||||
|
$(LIBSCSHVM): c/smain.o $(OBJS)
|
||||||
|
$(RM) $@
|
||||||
|
$(AR) $@ c/smain.o $(OBJS)
|
||||||
|
$(RANLIB) $@
|
||||||
|
|
||||||
|
$(LIBSCSH): $(OBJS) $(UNIX_OBJS) $(LIBOBJS) $(EXTERNAL_OBJECTS)
|
||||||
|
$(RM) $@ \
|
||||||
|
rm -f /tmp/s48_external_$$$$.c && \
|
||||||
|
build/build-external-modules /tmp/s48_external_$$$$.c \
|
||||||
|
$(EXTERNAL_INITIALIZERS) && \
|
||||||
|
$(CC) -c $(CFLAGS) -o /tmp/s48_external_$$$$.o \
|
||||||
|
/tmp/s48_external_$$$$.c && \
|
||||||
|
$(AR) $@ $(OBJS) $(UNIX_OBJS) $(LIBOBJS) $(EXTERNAL_OBJECTS) \
|
||||||
|
/tmp/s48_external_$$$$.o && \
|
||||||
|
$(RANLIB) $@ && \
|
||||||
|
rm -f /tmp/s48_external_$$$$.c /tmp/s48_external_$$$$.o
|
||||||
|
|
||||||
|
c/main.o: c/main.c
|
||||||
$(CC) -c $(CFLAGS) -o $@ \
|
$(CC) -c $(CFLAGS) -o $@ \
|
||||||
-DDEFAULT_IMAGE_NAME=\"$(LIB)/$(IMAGE)\" \
|
-DDEFAULT_IMAGE_NAME=\"$(LIB)/$(IMAGE)\" \
|
||||||
$(CPPFLAGS) $(DEFS) c/main.c
|
$(CPPFLAGS) $(DEFS) c/main.c
|
||||||
|
|
||||||
|
c/init.o: c/init.c c/scheme48vm.h c/scheme48heap.h
|
||||||
|
$(CC) -c $(CFLAGS) -o $@ \
|
||||||
|
-DDEFAULT_IMAGE_NAME=\"$(LIB)/$(IMAGE)\" \
|
||||||
|
$(CPPFLAGS) $(DEFS) c/init.c
|
||||||
|
|
||||||
c/scheme48vm.o: c/prescheme.h c/scheme48vm.h c/scheme48heap.h c/event.h \
|
c/scheme48vm.o: c/prescheme.h c/scheme48vm.h c/scheme48heap.h c/event.h \
|
||||||
c/io.h c/fd-io.h c/scheme48vm-prelude.h
|
c/io.h c/fd-io.h c/scheme48vm-prelude.h
|
||||||
c/scheme48heap.o: c/prescheme.h c/scheme48vm.h c/scheme48heap.h c/event.h \
|
c/scheme48heap.o: c/prescheme.h c/scheme48vm.h c/scheme48heap.h c/event.h \
|
||||||
|
|
@ -187,35 +317,36 @@ $(IMAGE): $(VM) scheme/env/init-defpackage.scm scheme/more-interfaces.scm \
|
||||||
|
|
||||||
### Fake targets: all clean install man dist
|
### Fake targets: all clean install man dist
|
||||||
|
|
||||||
install: enough dirs inst-script inst-vm inst-misc inst-man inst-inc inst-image
|
install: enough dirs inst-script inst-vm inst-misc inst-man inst-inc \
|
||||||
|
inst-doc install-scsh
|
||||||
|
|
||||||
inst-vm:
|
inst-vm: $(VM)
|
||||||
$(INSTALL_PROGRAM) $(VM) $(LIB)
|
$(INSTALL_PROGRAM) $(VM) $(LIB)
|
||||||
|
|
||||||
inst-image:
|
|
||||||
rm -f '/tmp/$(IMAGE)' && \
|
|
||||||
build/build-usual-image . '$(LIB)' '/tmp/$(IMAGE)' './$(VM)' \
|
|
||||||
'$(INITIAL)' && \
|
|
||||||
$(INSTALL_DATA) /tmp/$(IMAGE) $(LIB) && \
|
|
||||||
rm /tmp/$(IMAGE)
|
|
||||||
|
|
||||||
inst-man:
|
inst-man:
|
||||||
if [ -d $(mandir) -a -w $(mandir) ]; then \
|
if [ -d $(mandir) -a -w $(mandir) ]; then \
|
||||||
sed 's=LBIN=$(bindir)=g' doc/scheme48.man | \
|
sed 's=LBIN=$(bindir)=g' doc/scsh.man | \
|
||||||
sed 's=LLIB=$(LIB)=g' | \
|
sed 's=LLIB=$(LIB)=g' | \
|
||||||
sed 's=LS48=$(RUNNABLE)=g' >$(MANPAGE) && \
|
sed 's=LSCSH=$(RUNNABLE)=g' >$(MANPAGE) && \
|
||||||
$(INSTALL_DATA) $(MANPAGE) $(mandir) && \
|
$(INSTALL_DATA) $(MANPAGE) $(mandir) && \
|
||||||
rm $(MANPAGE); \
|
$(RM) $(MANPAGE); \
|
||||||
else \
|
else \
|
||||||
echo "$(mandir) not writable dir, not installing man page" \
|
echo "$(mandir) not writable dir, not installing man page" \
|
||||||
>&2; \
|
>&2; \
|
||||||
fi
|
fi
|
||||||
|
|
||||||
inst-inc:
|
inst-inc:
|
||||||
$(INSTALL_DATA) c/scheme48.h $(incdir)
|
$(INSTALL_DATA) $(srcdir)/c/scheme48.h $(incdir)
|
||||||
|
$(INSTALL_DATA) $(srcdir)/c/write-barrier.h $(incdir)
|
||||||
|
|
||||||
|
install-cig: cig
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/$(CIG) $(LIB)/cig
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/$(CIG).image $(LIB)/cig
|
||||||
|
$(INSTALL_DATA) $(srcdir)/$(LIBCIG) $(LIB)/cig
|
||||||
|
$(INSTALL_DATA) $(srcdir)/cig/libcig.h $(LIB)/cig
|
||||||
|
|
||||||
inst-misc:
|
inst-misc:
|
||||||
for stub in env big opt misc link; do \
|
for stub in env big opt misc link srfi; do \
|
||||||
for f in scheme/$$stub/*.scm; do \
|
for f in scheme/$$stub/*.scm; do \
|
||||||
$(INSTALL_DATA) $$f $(LIB)/$$stub || exit 1; \
|
$(INSTALL_DATA) $$f $(LIB)/$$stub || exit 1; \
|
||||||
done; \
|
done; \
|
||||||
|
|
@ -224,6 +355,42 @@ inst-misc:
|
||||||
$(INSTALL_DATA) $$f $(LIB)/rts || exit 1; \
|
$(INSTALL_DATA) $$f $(LIB)/rts || exit 1; \
|
||||||
done
|
done
|
||||||
|
|
||||||
|
inst-doc:
|
||||||
|
for f in $(srcdir)/doc/*.txt $(srcdir)/doc/*.ps; do \
|
||||||
|
$(INSTALL_DATA) $$f $(LIB)/doc/; \
|
||||||
|
done && \
|
||||||
|
for f in $(srcdir)/doc/src/*.tex \
|
||||||
|
$(srcdir)/doc/src/*.dvi \
|
||||||
|
$(srcdir)/doc/src/*.ps; \
|
||||||
|
do $(INSTALL_DATA) $$f $(LIB)/doc/s48-manual/; \
|
||||||
|
done && \
|
||||||
|
for f in $(srcdir)/doc/src/manual/*.html; \
|
||||||
|
do $(INSTALL_DATA) $$f $(LIB)/doc/s48-manual/html/; \
|
||||||
|
done && \
|
||||||
|
for f in $(srcdir)/doc/scsh-manual/*.tex \
|
||||||
|
$(srcdir)/doc/scsh-manual/*.sty \
|
||||||
|
$(srcdir)/doc/scsh-manual/*.dvi \
|
||||||
|
$(srcdir)/doc/scsh-manual/*.ps \
|
||||||
|
$(srcdir)/doc/scsh-manual/*.pdf; \
|
||||||
|
do $(INSTALL_DATA) $$f $(LIB)/doc/scsh-manual/; \
|
||||||
|
done && \
|
||||||
|
for f in $(srcdir)/doc/scsh-manual/html/*.html \
|
||||||
|
$(srcdir)/doc/scsh-manual/html/*.gif \
|
||||||
|
$(srcdir)/doc/scsh-manual/html/*.css; \
|
||||||
|
do $(INSTALL_DATA) $$f $(htmldir)/; \
|
||||||
|
done && \
|
||||||
|
for f in $(srcdir)/doc/scsh-paper/*.tex \
|
||||||
|
$(srcdir)/doc/scsh-paper/*.sty \
|
||||||
|
$(srcdir)/doc/scsh-paper/*.dvi \
|
||||||
|
$(srcdir)/doc/scsh-paper/*.ps; \
|
||||||
|
do $(INSTALL_DATA) $$f $(LIB)/doc/scsh-paper/; \
|
||||||
|
done && \
|
||||||
|
for f in $(srcdir)/doc/scsh-paper/html/*.html \
|
||||||
|
$(srcdir)/doc/scsh-paper/html/*.css; \
|
||||||
|
do $(INSTALL_DATA) $$f $(LIB)/doc/scsh-paper/html; \
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
inst-script:
|
inst-script:
|
||||||
script=$(bindir)/$(RUNNABLE) && \
|
script=$(bindir)/$(RUNNABLE) && \
|
||||||
echo '#!/bin/sh' >$$script && \
|
echo '#!/bin/sh' >$$script && \
|
||||||
|
|
@ -233,46 +400,52 @@ inst-script:
|
||||||
>>$$script && \
|
>>$$script && \
|
||||||
chmod +x $$script
|
chmod +x $$script
|
||||||
|
|
||||||
# Script to run scheme48 in this directory.
|
# Script to run scsh in this directory.
|
||||||
go:
|
go:
|
||||||
echo '#!/bin/sh' >$@ && \
|
echo '#!/bin/sh' >$@ && \
|
||||||
echo >>$@ && \
|
echo >>$@ && \
|
||||||
echo "lib=`pwd`" >>$@ && \
|
echo "lib=`pwd`" >>$@ && \
|
||||||
echo 'exec $$lib/$(VM) -o $$lib/$(VM) -i $$lib/$(IMAGE) "$$@"' \
|
echo 'exec $$lib/$(VM) -o $$lib/$(VM) -i $$lib/scsh/scsh.image "$$@"' \
|
||||||
>>$@ && \
|
>>$@ && \
|
||||||
chmod +x $@
|
chmod +x $@
|
||||||
|
|
||||||
dirs:
|
dirs:
|
||||||
for dir in $(libdir) $(bindir) $(incdir); do \
|
for dir in $(libdir) $(bindir) $(incdir) $(LIB) $(mandir) $(htmldir); do\
|
||||||
[ -d $$dir -a -w $$dir ] || { \
|
{ mkdir -p $$dir && [ -w $$dir ]; } || { \
|
||||||
echo "$$dir not a writable directory" >&2; \
|
echo "$$dir not a writable directory" >&2; \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
}; \
|
} \
|
||||||
done
|
done && \
|
||||||
{ mkdir -p $(LIB) && [ -w $(LIB) ]; } || { \
|
for dir in \
|
||||||
echo "$(LIB) not a writable directory" >&2; \
|
rts env big opt misc link srfi scsh doc/scsh-manual \
|
||||||
exit 1; \
|
doc/s48-manual/html doc/scsh-paper/html cig; do \
|
||||||
}
|
{ mkdir -p $(LIB)/$$dir && [ -w $(LIB)/$$dir ]; } || { \
|
||||||
for dir in rts env big opt misc link; do \
|
echo "$(LIB)/$$dir not a writable directory" >&2; \
|
||||||
{ mkdir -p $(LIB)/$$dir && [ -w $(LIB)/$$dir ]; } || { \
|
exit 1; \
|
||||||
echo "$(LIB)/$$dir not a writable directory" >&2; \
|
}; \
|
||||||
exit 1; \
|
|
||||||
}; \
|
|
||||||
done
|
done
|
||||||
|
|
||||||
configure: configure.in
|
configure: configure.in
|
||||||
autoheader && autoconf
|
autoheader && autoconf
|
||||||
|
|
||||||
clean:
|
clean: clean-cig clean-scsh
|
||||||
-rm -f $(VM) *.o c/unix/*.o c/*.o c/fake/*.o \
|
-rm -f $(VM) *.o c/*/*.o c/*.o \
|
||||||
TAGS $(IMAGE) \
|
$(IMAGE) \
|
||||||
build/*.tmp $(MANPAGE) build/linker.image \
|
build/*.tmp $(MANPAGE) build/linker.image \
|
||||||
scheme/debug/*.image scheme/debug/*.debug config.cache \
|
scheme/debug/*.image scheme/debug/*.debug \
|
||||||
scheme/vm/scheme48vm.c scheme/vm/scheme48heap.c \
|
scheme/vm/scheme48vm.c scheme/vm/scheme48heap.c \
|
||||||
go $(distname)
|
go $(distname)
|
||||||
|
|
||||||
|
clean-cig:
|
||||||
|
-rm -f cig/*.o $(CIG) $(CIG).image $(LIBCIG)
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
rm -f Makefile config.log config.status c/sysdep.h
|
rm -f Makefile config.log config.status c/sysdep.h config.cache \
|
||||||
|
scsh/machine \
|
||||||
|
scsh/endian.scm \
|
||||||
|
exportlist.aix
|
||||||
|
$(RM) a.exe $(VM).base $(VM).def $(VM).exp
|
||||||
|
-find . -name '*~' -o -name '#*' -o -name core -exec rm {} \;
|
||||||
|
|
||||||
check: $(VM) $(IMAGE) scheme/debug/check.scm
|
check: $(VM) $(IMAGE) scheme/debug/check.scm
|
||||||
( \
|
( \
|
||||||
|
|
@ -296,18 +469,17 @@ image: $(INITIAL)
|
||||||
$(MAKE) $(IMAGE)
|
$(MAKE) $(IMAGE)
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
etags scheme/vm/arch.scm scheme/rts/*.scm scheme/bcomp/*.scm \
|
find . -name "*.scm" -o -name "*.c" -o -name "*.h" | etags -
|
||||||
scheme/*.scm scheme/env/*.scm scheme/big/*.scm scheme/link/*.scm \
|
|
||||||
scheme/opt/*.scm scheme/debug/*.scm scheme/misc/*.scm
|
|
||||||
|
|
||||||
# --------------------
|
# --------------------
|
||||||
# Distribution...
|
# Distribution...
|
||||||
|
|
||||||
# DISTFILES should include all sources.
|
# DISTFILES should include all sources.
|
||||||
DISTFILES = README COPYING INSTALL configure \
|
DISTFILES = README COPYING INSTALL RELEASE configure config.sub config.guess \
|
||||||
acconfig.h configure.in Makefile.in install-sh \
|
scsh-config.in configure.in Makefile.in install-sh \
|
||||||
doc/*.ps doc/*.txt doc/html/*.html doc/scheme48.man \
|
doc/*.ps doc/*.txt \
|
||||||
doc/src/*.tex doc/src/*.sty \
|
doc/src/*.tex doc/src/*.sty doc/src/manual.dvi \
|
||||||
|
doc/src/manual.ps \
|
||||||
emacs/README build/*-version-number build/*.exec \
|
emacs/README build/*-version-number build/*.exec \
|
||||||
build/*.lisp build/build-usual-image build/filenames.make \
|
build/*.lisp build/build-usual-image build/filenames.make \
|
||||||
build/filenames.scm build/initial.debug \
|
build/filenames.scm build/initial.debug \
|
||||||
|
|
@ -316,14 +488,40 @@ DISTFILES = README COPYING INSTALL configure \
|
||||||
c/*.[ch] c/*/*.[ch] c/scheme48.h.in \
|
c/*.[ch] c/*/*.[ch] c/scheme48.h.in \
|
||||||
emacs/*.el gdbinit \
|
emacs/*.el gdbinit \
|
||||||
scheme/*.scm scheme/*/*.scm \
|
scheme/*.scm scheme/*/*.scm \
|
||||||
ps-compiler \
|
ps-compiler/*.scm ps-compiler/minor-version-number \
|
||||||
c/sysdep.h.in
|
ps-compiler/doc/*.txt ps-compiler/*/*.scm \
|
||||||
|
ps-compiler/*/*/*.scm \
|
||||||
|
ps-compiler/prescheme/test/fact.cps \
|
||||||
|
ps-compiler/prescheme/test/prescheme.h \
|
||||||
|
ps-compiler/prescheme/c-stuff \
|
||||||
|
c/sysdep.h.in \
|
||||||
|
scsh/*.scm scsh/*/*.scm \
|
||||||
|
scsh/*.[ch] scsh/*/*.[ch] \
|
||||||
|
scsh/*.scm.in scsh/*/Makefile.inc \
|
||||||
|
cig/*.scm cig/*.[ch] \
|
||||||
|
doc/scsh.man \
|
||||||
|
doc/scsh-manual/*.tex doc/scsh-manual/*.sty \
|
||||||
|
doc/scsh-manual/man.ps doc/scsh-manual/man.pdf \
|
||||||
|
doc/scsh-manual/man.dvi doc/scsh-manual/Makefile \
|
||||||
|
doc/scsh-manual/THANKS doc/scsh-manual/html/*.html \
|
||||||
|
doc/scsh-manual/html/*.gif doc/scsh-manual/html/*.css \
|
||||||
|
doc/src/manual/*.html \
|
||||||
|
doc/scsh-paper/*.sty doc/scsh-paper/*.tex \
|
||||||
|
doc/scsh-paper/mitlogo.ps doc/scsh-paper/scsh-paper.ps \
|
||||||
|
doc/scsh-paper/scsh-paper.dvi \
|
||||||
|
doc/scsh-paper/html/*.html doc/scsh-paper/html/*.css
|
||||||
|
|
||||||
|
|
||||||
distname = $(RUNNABLE)-0.`cat build/minor-version-number`
|
distname = $(RUNNABLE)-0.`cat build/minor-version-number`
|
||||||
|
|
||||||
dist: build/initial.image
|
dist: build/initial.image
|
||||||
|
(cd doc/src && latex manual.tex && latex manual.tex && \
|
||||||
|
dvips manual -o manual.ps && hyperlatex manual.tex) && \
|
||||||
|
(cd doc/scsh-manual && makeindex man && make man.ps && \
|
||||||
|
make man.pdf && make html) && \
|
||||||
|
(cd doc/scsh-paper && make scsh-paper.ps && make html) && \
|
||||||
distname=$(distname) && \
|
distname=$(distname) && \
|
||||||
distfile=$(distdir)/$$distname.tgz && \
|
distfile=$(distdir)/$$distname.tar.gz && \
|
||||||
if [ -d $(distdir) ] && \
|
if [ -d $(distdir) ] && \
|
||||||
[ -w $$distfile -o -w $(distdir) ]; then \
|
[ -w $$distfile -o -w $(distdir) ]; then \
|
||||||
rm -f $$distname && \
|
rm -f $$distname && \
|
||||||
|
|
@ -378,9 +576,7 @@ PACKAGES=scheme/packages.scm scheme/rts-packages.scm scheme/alt-packages.scm \
|
||||||
build/filenames.scm
|
build/filenames.scm
|
||||||
|
|
||||||
build/filenames.make: $(PACKAGES)
|
build/filenames.make: $(PACKAGES)
|
||||||
$(MAKE) $(VM) PACKAGES=
|
$(BUILD_RUNNABLE) -a batch <build/filenames.scm
|
||||||
./$(VM) -i $(srcdir)/$(INITIAL) -a batch <build/filenames.scm
|
|
||||||
# or: $(RUNNABLE) -a batch <build/filenames.scm
|
|
||||||
|
|
||||||
# --------------------
|
# --------------------
|
||||||
# Static linker
|
# Static linker
|
||||||
|
|
@ -418,7 +614,8 @@ link/linker-in-lucid: build/lucid-script.lisp $(linker-files) \
|
||||||
# Scheme, the byte-code compiler, and a minimal command processor, but
|
# Scheme, the byte-code compiler, and a minimal command processor, but
|
||||||
# no debugging environment to speak of.
|
# no debugging environment to speak of.
|
||||||
|
|
||||||
$(INITIAL): $(LINKER_IMAGE) $(CONFIG_FILES) build/initial.scm $(initial-files)
|
$(INITIAL): $(LINKER_IMAGE) $(CONFIG_FILES) build/initial.scm $(initial-files) \
|
||||||
|
scsh/here.scm # gross and Olin hates it -bri
|
||||||
($(START_LINKER); \
|
($(START_LINKER); \
|
||||||
echo '(load-configuration "scheme/interfaces.scm")'; \
|
echo '(load-configuration "scheme/interfaces.scm")'; \
|
||||||
echo '(load-configuration "scheme/packages.scm")'; \
|
echo '(load-configuration "scheme/packages.scm")'; \
|
||||||
|
|
@ -466,9 +663,9 @@ scheme/debug/medium.image: $(LINKER_IMAGE) $(CONFIG_FILES)
|
||||||
# The following have not been updated for the new directory organization
|
# The following have not been updated for the new directory organization
|
||||||
|
|
||||||
c/smain.o: c/main.c
|
c/smain.o: c/main.c
|
||||||
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DSTATIC_AREAS -o $@ c/main.c
|
$(CC) -c $(CPPFLAGS) $(DEFS) $(CFLAGS) -DSTATIC_AREAS -o $@ $(srcdir)/c/main.c
|
||||||
|
|
||||||
mini: mini-heap.o smain.o
|
mini: mini-heap.o c/smain.o
|
||||||
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ c/smain.o mini-heap.o $(OBJS) $(LIBS)
|
$(CC) $(LDFLAGS) $(CFLAGS) -o $@ c/smain.o mini-heap.o $(OBJS) $(LIBS)
|
||||||
|
|
||||||
mini-heap.o: mini-heap.c
|
mini-heap.o: mini-heap.c
|
||||||
|
|
@ -477,7 +674,7 @@ mini-heap.o: mini-heap.c
|
||||||
mini-heap.c: scheme/debug/mini1.image
|
mini-heap.c: scheme/debug/mini1.image
|
||||||
(echo ,exec ,load misc/load-static.scm; \
|
(echo ,exec ,load misc/load-static.scm; \
|
||||||
echo \(do-it 150000 \"$(srcdir)/scheme/debug/mini1.image\" \"$@\"\)) \
|
echo \(do-it 150000 \"$(srcdir)/scheme/debug/mini1.image\" \"$@\"\)) \
|
||||||
| $(RUNNABLE) -h 3000000 -a batch
|
| $(BUILD_RUNNABLE) -h 3000000 -a batch
|
||||||
|
|
||||||
scheme/debug/mini1.image: $(VM) scheme/debug/mini.image
|
scheme/debug/mini1.image: $(VM) scheme/debug/mini.image
|
||||||
echo "(write-image \"scheme/debug/mini1.image\" \
|
echo "(write-image \"scheme/debug/mini1.image\" \
|
||||||
|
|
@ -502,7 +699,7 @@ c/scheme48.h: c/scheme48.h.in scheme/vm/arch.scm scheme/vm/data.scm \
|
||||||
\"$(srcdir)/scheme/vm/arch.scm\" \
|
\"$(srcdir)/scheme/vm/arch.scm\" \
|
||||||
\"$(srcdir)/scheme/vm/data.scm\" \
|
\"$(srcdir)/scheme/vm/data.scm\" \
|
||||||
\"$(srcdir)/scheme/rts/record.scm\")" \
|
\"$(srcdir)/scheme/rts/record.scm\")" \
|
||||||
) | $(RUNNABLE)
|
) | $(BUILD_RUNNABLE)
|
||||||
|
|
||||||
# An old version of the above for legacy code.
|
# An old version of the above for legacy code.
|
||||||
|
|
||||||
|
|
@ -516,7 +713,7 @@ c/old-scheme48.h: scheme/vm/arch.scm scheme/vm/data.scm \
|
||||||
echo "(make-c-header-file \"$@\" \
|
echo "(make-c-header-file \"$@\" \
|
||||||
\"$(srcdir)/scheme/vm/arch.scm\" \
|
\"$(srcdir)/scheme/vm/arch.scm\" \
|
||||||
\"$(srcdir)/scheme/vm/data.scm\")" \
|
\"$(srcdir)/scheme/vm/data.scm\")" \
|
||||||
) | $(RUNNABLE)
|
) | $(BUILD_RUNNABLE)
|
||||||
|
|
||||||
# Generate vm (scheme48vm.c and scheme48heap.c) from VM sources.
|
# Generate vm (scheme48vm.c and scheme48heap.c) from VM sources.
|
||||||
# Never called automatically. Do not use unless you are sure you
|
# Never called automatically. Do not use unless you are sure you
|
||||||
|
|
@ -531,5 +728,192 @@ i-know-what-i-am-doing:
|
||||||
echo ',exec ,load compile-vm-no-gc.scm'; \
|
echo ',exec ,load compile-vm-no-gc.scm'; \
|
||||||
echo ',exec ,load compile-gc.scm'; \
|
echo ',exec ,load compile-gc.scm'; \
|
||||||
echo ',exit' \
|
echo ',exit' \
|
||||||
) | $(RUNNABLE) -h 8000000 && \
|
) | $(BUILD_RUNNABLE) -h 5000000 && \
|
||||||
mv ../scheme/vm/scheme48vm.c ../scheme/vm/scheme48heap.c ../c
|
mv ../scheme/vm/scheme48vm.c ../scheme/vm/scheme48heap.c ../c
|
||||||
|
|
||||||
|
cig: $(CIG) $(CIG).image $(LIBCIG)
|
||||||
|
|
||||||
|
|
||||||
|
$(CIG): $(VM) $(IMAGE) $(srcdir)/cig/cig.scm $(srcdir)/cig/libcig.scm
|
||||||
|
(echo ",batch"; \
|
||||||
|
echo ",translate =scheme48/ $(srcdir)/scheme/"; \
|
||||||
|
echo ",config ,load $(srcdir)/cig/cig.scm"; \
|
||||||
|
echo ",config ,load $(srcdir)/cig/libcig.scm"; \
|
||||||
|
echo ",load-package cig-standalone"; \
|
||||||
|
echo ",in cig-standalone"; \
|
||||||
|
echo ",translate =scheme48/ $(LIB)/"; \
|
||||||
|
echo ",build cig-standalone-toplevel /tmp/cig") \
|
||||||
|
| ./$(VM) -i ./$(IMAGE)
|
||||||
|
$(srcdir)/cig/image2script $(LIB)/$(VM) </tmp/cig > $(CIG)
|
||||||
|
-chmod +x $(CIG)
|
||||||
|
mv /tmp/cig $(srcdir)/cig/cig_bootstrap
|
||||||
|
$(RM) /tmp/cig
|
||||||
|
|
||||||
|
$(CIG).image: $(IMAGE) $(VM) $(srcdir)/cig/cig.scm $(srcdir)/cig/libcig.scm
|
||||||
|
(echo ",batch"; \
|
||||||
|
echo ",translate =scheme48/ $(srcdir)/scheme/"; \
|
||||||
|
echo ",config ,load $(srcdir)/cig/cig.scm"; \
|
||||||
|
echo ",config ,load $(srcdir)/cig/libcig.scm"; \
|
||||||
|
echo ",load-package cig-aux"; \
|
||||||
|
echo ",open define-foreign-syntax"; \
|
||||||
|
echo ",translate =scheme48/ $(LIB)/"; \
|
||||||
|
echo ",dump /tmp/cig \"(CIG Preloaded -bri)\"") \
|
||||||
|
| ./$(VM) -o ./$(VM) -i ./$(IMAGE)
|
||||||
|
$(srcdir)/cig/image2script $(LIB)/$(VM) \
|
||||||
|
-o $(LIB)/$(VM) \
|
||||||
|
</tmp/cig > $(CIG).image
|
||||||
|
-chmod +x $(CIG).image
|
||||||
|
$(RM) /tmp/cig
|
||||||
|
|
||||||
|
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
# SCSH Specifics
|
||||||
|
#-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
scsh: scsh/scsh scsh/scsh.image
|
||||||
|
|
||||||
|
SCHEME =scsh/awk.scm \
|
||||||
|
scsh/defrec.scm \
|
||||||
|
scsh/endian.scm \
|
||||||
|
scsh/enumconst.scm \
|
||||||
|
scsh/event.scm \
|
||||||
|
scsh/low-interrupt.scm \
|
||||||
|
scsh/fdports.scm \
|
||||||
|
scsh/fileinfo.scm \
|
||||||
|
scsh/filemtch.scm \
|
||||||
|
scsh/filesys.scm \
|
||||||
|
scsh/flock.scm \
|
||||||
|
scsh/fname.scm \
|
||||||
|
scsh/fr.scm \
|
||||||
|
scsh/glob.scm \
|
||||||
|
scsh/dot-locking.scm \
|
||||||
|
scsh/here.scm \
|
||||||
|
scsh/libscsh.scm \
|
||||||
|
scsh/machine/bufpol.scm \
|
||||||
|
scsh/machine/errno.scm \
|
||||||
|
scsh/machine/fdflags.scm \
|
||||||
|
scsh/machine/netconst.scm \
|
||||||
|
scsh/machine/packages.scm \
|
||||||
|
scsh/machine/signals.scm \
|
||||||
|
scsh/machine/time_dep.scm \
|
||||||
|
scsh/machine/tty-consts.scm \
|
||||||
|
scsh/machine/waitcodes.scm \
|
||||||
|
scsh/md5.scm \
|
||||||
|
scsh/meta-arg.scm \
|
||||||
|
scsh/network.scm \
|
||||||
|
scsh/newports.scm \
|
||||||
|
scsh/procobj.scm \
|
||||||
|
scsh/pty.scm \
|
||||||
|
scsh/rdelim.scm \
|
||||||
|
scsh/rw.scm \
|
||||||
|
scsh/scsh-condition.scm \
|
||||||
|
scsh/scsh-interfaces.scm \
|
||||||
|
scsh/scsh-package.scm \
|
||||||
|
scsh/scsh-read.scm \
|
||||||
|
scsh/scsh-version.scm \
|
||||||
|
scsh/scsh.scm \
|
||||||
|
scsh/sighandlers.scm \
|
||||||
|
scsh/startup.scm \
|
||||||
|
scsh/stringcoll.scm \
|
||||||
|
scsh/syntax-helpers.scm \
|
||||||
|
scsh/syntax.scm \
|
||||||
|
scsh/syscalls.scm \
|
||||||
|
scsh/time.scm \
|
||||||
|
scsh/top.scm \
|
||||||
|
scsh/tty.scm \
|
||||||
|
scsh/utilities.scm \
|
||||||
|
scsh/weaktables.scm \
|
||||||
|
scsh/rx/packages.scm \
|
||||||
|
scsh/rx/re-match-syntax.scm \
|
||||||
|
scsh/rx/rx-lib.scm \
|
||||||
|
scsh/rx/parse.scm \
|
||||||
|
scsh/rx/re-subst.scm \
|
||||||
|
scsh/rx/simp.scm \
|
||||||
|
scsh/rx/posixstr.scm \
|
||||||
|
scsh/rx/re-syntax.scm \
|
||||||
|
scsh/rx/spencer.scm \
|
||||||
|
scsh/rx/oldfuns.scm \
|
||||||
|
scsh/rx/re-fold.scm \
|
||||||
|
scsh/rx/re.scm \
|
||||||
|
scsh/rx/test.scm \
|
||||||
|
scsh/rx/re-high.scm \
|
||||||
|
scsh/rx/regexp.scm \
|
||||||
|
scsh/rx/re-low.scm \
|
||||||
|
scsh/rx/regress.scm
|
||||||
|
# scsh/dbm.scm db.scm ndbm.scm
|
||||||
|
# jcontrol
|
||||||
|
|
||||||
|
# Bogus, but it makes the scm->c->o two-ply dependency work.
|
||||||
|
# Explicitly giving the .o/.c dependency also makes it go.
|
||||||
|
############################################################
|
||||||
|
cig/libcig.c: cig/libcig.scm
|
||||||
|
|
||||||
|
scsh/scsh: scsh/scsh-tramp.c
|
||||||
|
$(CC) -o $@ $(CPPFLAGS) $(CFLAGS) \
|
||||||
|
-DVM=\"$(LIB)/$(VM)\" \
|
||||||
|
-DIMAGE=\"$(LIB)/scsh.image\" \
|
||||||
|
scsh/scsh-tramp.c
|
||||||
|
|
||||||
|
bs: build/build-scsh-image
|
||||||
|
sh $(srcdir)/build/build-scsh-image "$(srcdir)" "$(LIB)" "$(IMAGE)" \
|
||||||
|
"$(VM)" cig/cig.image
|
||||||
|
|
||||||
|
loads = $(srcdir)/scsh/let-opt.scm $(srcdir)/scsh/scsh-interfaces.scm \
|
||||||
|
$(srcdir)/scsh/machine/packages.scm \
|
||||||
|
$(srcdir)/scsh/rx/packages.scm \
|
||||||
|
$(srcdir)/scsh/scsh-package.scm \
|
||||||
|
$(srcdir)/scsh/lib/ccp-pack.scm \
|
||||||
|
$(srcdir)/scsh/lib/char-package.scm
|
||||||
|
|
||||||
|
opens = floatnums scsh ccp-lib scsh-top-package scsh-here-string-hax \
|
||||||
|
srfi-1 srfi-13 srfi-14 # srfi-14 is also exported by scsh
|
||||||
|
|
||||||
|
scsh/scsh.image: $(VM) $(SCHEME) $(IMAGE)
|
||||||
|
(echo ",translate =scheme48/ `pwd`/scheme/"; \
|
||||||
|
echo ",batch on"; \
|
||||||
|
echo ",config ,load $(loads)"; \
|
||||||
|
echo ",open $(opens)"; \
|
||||||
|
echo "(dump-scsh \"$@\")"; \
|
||||||
|
) \
|
||||||
|
| ./$(VM) -o ./$(VM) -i $(IMAGE) -h 10000000
|
||||||
|
|
||||||
|
# ,flush files => 0k
|
||||||
|
# ,flush names => -= 17k
|
||||||
|
# ,flush maps => -= 350K
|
||||||
|
# ,flush source => -= 1117k
|
||||||
|
# ,flush => 550k
|
||||||
|
scsh/stripped-scsh.image: $(VM) $(SCHEME) $(IMAGE)
|
||||||
|
(echo ",flush maps source";\
|
||||||
|
echo ",translate =scheme48/ `pwd`/scheme/"; \
|
||||||
|
echo ",batch on"; \
|
||||||
|
echo ",config ,load $(loads)"; \
|
||||||
|
echo ",open $(opens)"; \
|
||||||
|
echo ",flush"; \
|
||||||
|
echo "(dump-scsh \"$@\")";) \
|
||||||
|
| ./$(VM) -o ./$(VM) -i $(IMAGE) -h 10000000
|
||||||
|
|
||||||
|
install-scsh: scsh install-scsh-image install-stripped-scsh-image
|
||||||
|
$(RM) $(bindir)/$(RUNNABLE)
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/scsh/scsh $(bindir)/$(RUNNABLE)
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/$(LIBSCSHVM) $(libdir)/$(LIBSCSHVM)
|
||||||
|
$(INSTALL_PROGRAM) $(srcdir)/$(LIBSCSH) $(libdir)/$(LIBSCSH)
|
||||||
|
$(RANLIB) $(libdir)/$(LIBSCSH)
|
||||||
|
for f in $(srcdir)/scsh/*.scm $(srcdir)/scsh/*/*.scm; \
|
||||||
|
do $(INSTALL_DATA) $$f $(LIB)/scsh/; done
|
||||||
|
|
||||||
|
install-scsh-image: $(VM) scsh/scsh.image
|
||||||
|
( echo ',translate =scheme48 $(LIB)'; \
|
||||||
|
echo '(dump-scsh "$(LIB)/scsh.image")'; \
|
||||||
|
echo ',exit'; \
|
||||||
|
) | ./$(VM) -i scsh/scsh.image
|
||||||
|
|
||||||
|
install-stripped-scsh-image: $(VM) scsh/stripped-scsh.image
|
||||||
|
( echo ',translate =scheme48 $(LIB)'; \
|
||||||
|
echo '(dump-scsh "$(LIB)/stripped-scsh.image")'; \
|
||||||
|
echo ',exit'; \
|
||||||
|
) | ./$(VM) -i scsh/stripped-scsh.image
|
||||||
|
|
||||||
|
clean-scsh:
|
||||||
|
$(RM) scsh/*.o scsh/rx/*.o scsh/machine/*.o
|
||||||
|
$(RM) scsh/*.image
|
||||||
|
$(RM) $(LIBSCSHVM) $(LIBSCSH) scsh/scsh$(EXEEXT)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
92
README
92
README
|
|
@ -1,93 +1,19 @@
|
||||||
; Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees. See file COPYING.
|
-*- Mode: Text; -*-
|
||||||
|
|
||||||
Please report bugs to scheme-48-bugs@martigny.ai.mit.edu, and include
|
Copyright (c) 1994 Brian D. Carlstrom
|
||||||
|
See file COPYING for copying information.
|
||||||
|
|
||||||
|
Please report bugs to scsh-bugs@zurich.ai.mit.edu, and include
|
||||||
the version number in your message.
|
the version number in your message.
|
||||||
|
|
||||||
Installation instructions in file INSTALL.
|
Installation instructions in file INSTALL.
|
||||||
|
|
||||||
A user's guide is in file doc/user-guide.txt.
|
A scsh manual is in directory doc/scsh-manual/.
|
||||||
|
A scsh paper is in directory doc/scsh-paper/.
|
||||||
|
A scsh quick reference is in file doc/cheat.txt.
|
||||||
|
|
||||||
Recent changes are listed in file doc/news.txt.
|
Send mail to scsh-request@zurich.ai.mit.edu to be put on a
|
||||||
|
|
||||||
Known bugs and things to do in the future are listed in doc/todo.txt.
|
|
||||||
|
|
||||||
Send mail to scheme-48-request@martigny.ai.mit.edu to be put on a
|
|
||||||
mailing list for announcements, discussion, bug reports, and bug
|
mailing list for announcements, discussion, bug reports, and bug
|
||||||
fixes.
|
fixes.
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
When running "make", don't worry if the ".notify" target fails. Its
|
|
||||||
only purpose is to send an email message to
|
|
||||||
scheme-48-notifications@martigny.ai.mit.edu, so that we can get a
|
|
||||||
rough idea of how much Scheme 48 is being used and by whom. We
|
|
||||||
promise not to use your name or email address for any commercial
|
|
||||||
purpose. If you don't want us to know, just do "make -t .notify"
|
|
||||||
first (after running "configure").
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
The Scheme 48 root directory is organized as follows (not all files are
|
|
||||||
listed here):
|
|
||||||
|
|
||||||
README this file
|
|
||||||
INSTALL installation instructions
|
|
||||||
COPYING copyright notice
|
|
||||||
configure configuration script
|
|
||||||
Makefile.in input to configure
|
|
||||||
doc/ some documentation
|
|
||||||
scheme48.man a Unix-style manual page
|
|
||||||
user-guide.txt general guide to using Scheme 48
|
|
||||||
todo.txt list of improvements we hope to make someday
|
|
||||||
news.txt list of improvements we have already made
|
|
||||||
module.ps description of Scheme 48's module system
|
|
||||||
big-scheme.txt extensions to Scheme
|
|
||||||
threads.txt multiprocessing
|
|
||||||
io.txt how the I/O system works
|
|
||||||
scheme/ scheme source files
|
|
||||||
packages.scm meta-module definitions
|
|
||||||
interfaces.scm system interface definitions
|
|
||||||
more-interfaces.scm system interface definitions
|
|
||||||
*-packages.scm module definitions
|
|
||||||
bcomp/ the byte-code compiler
|
|
||||||
vm/ virtual machine sources (written in Pre-Scheme)
|
|
||||||
rts/ run-time system sources
|
|
||||||
link/ static linker
|
|
||||||
env/ development environment modules (debugger, etc.)
|
|
||||||
big/ useful Scheme libraries and extensions ("Big Scheme")
|
|
||||||
alt/ portable implementations of some Scheme 48 features
|
|
||||||
opt/ optional code optimizer for the byte-code compiler
|
|
||||||
prescheme/ code for running the VM using Scheme 48
|
|
||||||
debug/ debugging utilities, tests, etc.
|
|
||||||
misc/ very miscellaneous things (e.g. AMB operator)
|
|
||||||
posix/ unfinished interface to POSIX system calls
|
|
||||||
ps-compiler/ Pre-Scheme -> C compiler
|
|
||||||
c/ c source files
|
|
||||||
sysdep.h.in input to configure
|
|
||||||
scheme48vm.c most of the VM (generated by Pre-Scheme compiler)
|
|
||||||
scheme48vm.h extern declarations for scheme48vm.c
|
|
||||||
scheme48heap.c storage management (generated by Pre-Scheme compiler)
|
|
||||||
scheme48heap.h extern declarations for scheme48heap.c
|
|
||||||
main.c entry point for the VM
|
|
||||||
prescheme.h part of the VM
|
|
||||||
extension.c default definition of vm_extension()
|
|
||||||
scheme48.h C declarations and macros for Scheme 48 data structures
|
|
||||||
old-scheme48.h old version, included for compatibility
|
|
||||||
c-mods.h minor additions to the C language
|
|
||||||
event.h header file for OS interface
|
|
||||||
io.h ditto
|
|
||||||
fd-io.h ditto
|
|
||||||
socket.c socket support
|
|
||||||
dynamo.c dynamic loading support
|
|
||||||
unix/ Unix-specific source files
|
|
||||||
posix/ C half of an unfinished interface to POSIX system calls
|
|
||||||
fake/ C files for insufficiently POSIX-compliant systems
|
|
||||||
build/ code for building the system
|
|
||||||
filenames.make included by Makefile, generated automatically
|
|
||||||
filenames.scm code for generating filenames.make
|
|
||||||
initial.image an image file containing a minimal Scheme system
|
|
||||||
initial.debug debugging database for same
|
|
||||||
initial.scm script for creating initial.image
|
|
||||||
build-usual-image script for creating scheme48.image
|
|
||||||
build-external-modules script for creating external-module initializer
|
|
||||||
emacs/ gnu emacs support
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
; Copyright (c) 1993-2001 by Richard Kelsey and Jonathan Rees.
|
||||||
|
; Copyright (c) 1994-2000 by Olin Shivers and Brian D. Carlstrom.
|
||||||
|
; Copyright (c) 1999-2000 by Martin Gasbichler.
|
||||||
|
See file COPYING.
|
||||||
|
|
||||||
|
Please report bugs to scsh-bugs@zurich.ai.mit.edu, and include
|
||||||
|
the version number in your message.
|
||||||
|
|
||||||
|
Installation instructions in file INSTALL.
|
||||||
|
|
||||||
|
A user's guide is in file doc/user-guide.txt.
|
||||||
|
|
||||||
|
Recent changes are listed in file doc/news.txt.
|
||||||
|
|
||||||
|
Known bugs and things to do in the future are listed in doc/todo.txt.
|
||||||
|
|
||||||
|
Send mail to scheme-48-request@martigny.ai.mit.edu to be put on a
|
||||||
|
mailing list for announcements, discussion, bug reports, and bug
|
||||||
|
fixes.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
The Scheme 48 root directory is organized as follows (not all files are
|
||||||
|
listed here):
|
||||||
|
|
||||||
|
README this file
|
||||||
|
INSTALL installation instructions
|
||||||
|
COPYING copyright notice
|
||||||
|
configure configuration script
|
||||||
|
Makefile.in input to configure
|
||||||
|
doc/ some documentation
|
||||||
|
scheme48.man a Unix-style manual page
|
||||||
|
user-guide.txt general guide to using Scheme 48
|
||||||
|
todo.txt list of improvements we hope to make someday
|
||||||
|
news.txt list of improvements we have already made
|
||||||
|
module.ps description of Scheme 48's module system
|
||||||
|
big-scheme.txt extensions to Scheme
|
||||||
|
threads.txt multiprocessing
|
||||||
|
io.txt how the I/O system works
|
||||||
|
scheme/ scheme source files
|
||||||
|
packages.scm meta-module definitions
|
||||||
|
interfaces.scm system interface definitions
|
||||||
|
more-interfaces.scm system interface definitions
|
||||||
|
*-packages.scm module definitions
|
||||||
|
bcomp/ the byte-code compiler
|
||||||
|
vm/ virtual machine sources (written in Pre-Scheme)
|
||||||
|
rts/ run-time system sources
|
||||||
|
link/ static linker
|
||||||
|
env/ development environment modules (debugger, etc.)
|
||||||
|
big/ useful Scheme libraries and extensions ("Big Scheme")
|
||||||
|
alt/ portable implementations of some Scheme 48 features
|
||||||
|
opt/ optional code optimizer for the byte-code compiler
|
||||||
|
prescheme/ code for running the VM using Scheme 48
|
||||||
|
debug/ debugging utilities, tests, etc.
|
||||||
|
misc/ very miscellaneous things (e.g. AMB operator)
|
||||||
|
posix/ unfinished interface to POSIX system calls
|
||||||
|
ps-compiler/ Pre-Scheme -> C compiler
|
||||||
|
c/ c source files
|
||||||
|
sysdep.h.in input to configure
|
||||||
|
scheme48vm.c most of the VM (generated by Pre-Scheme compiler)
|
||||||
|
scheme48vm.h extern declarations for scheme48vm.c
|
||||||
|
scheme48heap.c storage management (generated by Pre-Scheme compiler)
|
||||||
|
scheme48heap.h extern declarations for scheme48heap.c
|
||||||
|
main.c entry point for the VM
|
||||||
|
prescheme.h part of the VM
|
||||||
|
extension.c default definition of vm_extension()
|
||||||
|
scheme48.h C declarations and macros for Scheme 48 data structures
|
||||||
|
old-scheme48.h old version, included for compatibility
|
||||||
|
c-mods.h minor additions to the C language
|
||||||
|
event.h header file for OS interface
|
||||||
|
io.h ditto
|
||||||
|
fd-io.h ditto
|
||||||
|
socket.c socket support
|
||||||
|
dynamo.c dynamic loading support
|
||||||
|
unix/ Unix-specific source files
|
||||||
|
posix/ C half of an unfinished interface to POSIX system calls
|
||||||
|
fake/ C files for insufficiently POSIX-compliant systems
|
||||||
|
build/ code for building the system
|
||||||
|
filenames.make included by Makefile, generated automatically
|
||||||
|
filenames.scm code for generating filenames.make
|
||||||
|
initial.image an image file containing a minimal Scheme system
|
||||||
|
initial.debug debugging database for same
|
||||||
|
initial.scm script for creating initial.image
|
||||||
|
build-usual-image script for creating scheme48.image
|
||||||
|
build-external-modules script for creating external-module initializer
|
||||||
|
emacs/ gnu emacs support
|
||||||
|
|
@ -0,0 +1,389 @@
|
||||||
|
Scsh 0.6.4 Release notes -*- outline -*-
|
||||||
|
|
||||||
|
We are pleased to release scsh version 0.6.4. The new version is
|
||||||
|
mainly a bug-fix release, the only new features are command-line
|
||||||
|
switches for loading exec scripts and support for some more SRFIs.
|
||||||
|
|
||||||
|
The text below gives a general description of scsh, instructions for obtaining
|
||||||
|
it, pointers to discussion forums, and a description of the new features in
|
||||||
|
release 0.6.3. (Emacs should display this document is in outline mode. Say
|
||||||
|
c-h m for instructions on how to move through it by sections (e.g., c-c c-n,
|
||||||
|
c-c c-p).)
|
||||||
|
|
||||||
|
* Contents
|
||||||
|
==========
|
||||||
|
What is scsh
|
||||||
|
Scsh as a scripting language
|
||||||
|
Scsh as a systems-programming language
|
||||||
|
Scsh is a portable programming environment
|
||||||
|
Obtaining and installing scsh
|
||||||
|
Getting in touch
|
||||||
|
The World-Wide What?
|
||||||
|
New in this release
|
||||||
|
Switches to load exec scripts
|
||||||
|
Bug fixes
|
||||||
|
API changes
|
||||||
|
New in 0.6.3
|
||||||
|
New in 0.6.2
|
||||||
|
New in 0.6.1
|
||||||
|
New in 0.6.0
|
||||||
|
Thanks
|
||||||
|
|
||||||
|
|
||||||
|
* What is scsh
|
||||||
|
==============
|
||||||
|
Scsh is a broad-spectrum systems-programming environment for Unix embedded
|
||||||
|
in R5RS Scheme. It has an open-source copyright, and runs on most major
|
||||||
|
Unix systems.
|
||||||
|
|
||||||
|
** Scsh as a scripting language
|
||||||
|
-------------------------------
|
||||||
|
Scsh has a high-level process notation for doing shell-script like tasks:
|
||||||
|
running programs, establishing pipelines and I/O redirection. For example, the
|
||||||
|
shell pipeline
|
||||||
|
|
||||||
|
gunzip < paper.tex.gz | detex | spell | lpr -Ppulp &
|
||||||
|
|
||||||
|
would be written in scsh as
|
||||||
|
|
||||||
|
(& (| (gunzip) (detex) (spell) (lpr -Ppulp)) ; Background a pipeline
|
||||||
|
(< paper.tex.gz)) ; with this redirection
|
||||||
|
|
||||||
|
Scsh embeds this process notation within a full Scheme implementation.
|
||||||
|
The process notation is realized as a set of macro definitions, and is
|
||||||
|
carefully designed to allow full integration with standard Scheme code.
|
||||||
|
Scsh isn't Scheme-like; it is Scheme.
|
||||||
|
|
||||||
|
At the scripting level, scsh also has an Awk design, also implemented
|
||||||
|
as a macro that can be embedded inside general Scheme code.
|
||||||
|
|
||||||
|
Scripts can be written as standalone Scheme source files, with a leading
|
||||||
|
#!/usr/local/bin/scsh -s
|
||||||
|
trigger line.
|
||||||
|
|
||||||
|
|
||||||
|
** Scsh as a systems-programming language
|
||||||
|
-----------------------------------------
|
||||||
|
Scsh additionally provides the low-level access to the operating system
|
||||||
|
normally associated with C. The current release provides full access to Posix,
|
||||||
|
plus important non-Posix extensions, such as complete sockets support.
|
||||||
|
"Complete Posix" means: fork, exec & wait, sockets, full read, write, open &
|
||||||
|
close, seek & tell, complete file-system access, including stat,
|
||||||
|
chmod/chgrp/chown, symlink, FIFO & directory access, tty & pty support, file
|
||||||
|
locking, pipes, select, file-name pattern-matching, time & date, environment
|
||||||
|
variables, signal handlers, and more.
|
||||||
|
|
||||||
|
In brief, you can now write Unix systems programs in Scheme instead of C.
|
||||||
|
For example, we have implemented an extensible HTTP server at MIT entirely
|
||||||
|
in scsh.
|
||||||
|
|
||||||
|
As important as full access to the OS is the manner in which it is provided.
|
||||||
|
Scsh integrates the OS support into Scheme in a manner which respects the
|
||||||
|
general structure of the language. The details of the design are discussed
|
||||||
|
in a joint MIT Lab for Computer Science/University of Hong Kong technical
|
||||||
|
report, "A Scheme Shell," also to appear in a revised format in the "Journal
|
||||||
|
syof Lisp and Symbolic Computation." This paper is also available by ftp:
|
||||||
|
ftp://ftp.scsh.net/pub/scsh/papers/scsh-paper.ps
|
||||||
|
|
||||||
|
|
||||||
|
** Scsh is a portable programming environment
|
||||||
|
---------------------------------------------
|
||||||
|
Scsh is designed for portability. It is implemented on top of Scheme 48,
|
||||||
|
a byte-code-interpreter Scheme implementation. The Scheme 48 virtual machine
|
||||||
|
can be compiled on any system with a C compiler; the rest of Scheme 48 is
|
||||||
|
machine-independent across 32-bit processors. Scsh's OS interface is
|
||||||
|
also quite portable, providing a consistent interface across different
|
||||||
|
Unix platforms. We currently have scsh implementations for:
|
||||||
|
AIX
|
||||||
|
BSD/OS
|
||||||
|
CXUX
|
||||||
|
FreeBSD
|
||||||
|
HP-UX
|
||||||
|
IRIX
|
||||||
|
Linux
|
||||||
|
NetBSD
|
||||||
|
OpenBSD
|
||||||
|
Solaris
|
||||||
|
SunOS
|
||||||
|
Ultrix
|
||||||
|
Win32
|
||||||
|
Darwin/Mac OS X
|
||||||
|
|
||||||
|
Scsh code should run without change across these systems.
|
||||||
|
Porting to new platforms is usually not difficult.
|
||||||
|
|
||||||
|
|
||||||
|
* Obtaining and installing scsh
|
||||||
|
===============================
|
||||||
|
You can get a copy of scsh via anonymous ftp, from
|
||||||
|
ftp://ftp.scsh.net/pub/scsh/scsh.tar.gz
|
||||||
|
The tar file includes a detailed manual and a paper describing
|
||||||
|
the design of the system.
|
||||||
|
|
||||||
|
For the lazily curious, we also have the manual separately available as
|
||||||
|
ftp://ftp.scsh.net/pub/scsh/0.6/scsh-manual.ps
|
||||||
|
Just click 'n view.
|
||||||
|
|
||||||
|
You *should* be able to build scsh on the standard platforms with exactly five
|
||||||
|
commands: gunzip, tar, cd, ./configure, and make. The configure script figures
|
||||||
|
out the special flags and switches needed to make the build work (thanks to
|
||||||
|
the GNU project for the autoconfig tool that makes this possible).
|
||||||
|
|
||||||
|
After doing the make, you can start up a Scheme shell and try it out
|
||||||
|
by saying
|
||||||
|
./go
|
||||||
|
See the manual for full details on the command-line switches.
|
||||||
|
|
||||||
|
If it's harder than this, and your system is standard, we'd like to know
|
||||||
|
about it.
|
||||||
|
|
||||||
|
|
||||||
|
* Getting in touch
|
||||||
|
==================
|
||||||
|
There are two main ways to join in scsh-related discussion: the mailing-list
|
||||||
|
scsh@zurich.ai.mit.edu
|
||||||
|
and the netnews group
|
||||||
|
comp.lang.scheme.scsh
|
||||||
|
These two forums should be equivalent, being bi-directionally gatewayed
|
||||||
|
at MIT, but due to technical problems it's better to read them both.
|
||||||
|
|
||||||
|
Bugs can be reported to
|
||||||
|
scsh-bugs@zurich.ai.mit.edu
|
||||||
|
or via the Scsh project's bugs section on SourceForge:
|
||||||
|
http://sourceforge.net/projects/scsh/
|
||||||
|
|
||||||
|
If you do not netnews hierarchy, or wish to join the mailing
|
||||||
|
list for other reasons, send mail to
|
||||||
|
scsh-request@zurich.ai.mit.edu
|
||||||
|
|
||||||
|
|
||||||
|
* The World-Wide What?
|
||||||
|
======================
|
||||||
|
We even have one of those dot-com cyberweb things:
|
||||||
|
http://www.scsh.net
|
||||||
|
We manage the project using SourceForge:
|
||||||
|
http://sourceforge.net/projects/scsh/
|
||||||
|
|
||||||
|
* New in this release
|
||||||
|
=====================
|
||||||
|
|
||||||
|
** Switches to load exec scripts
|
||||||
|
The new switch -le loads a file into the exec package, the new
|
||||||
|
switch -de loads the "-s" script into the exec package.
|
||||||
|
|
||||||
|
** Bug fixes
|
||||||
|
- Other select bug
|
||||||
|
- Timeout for select is in seconds, not milliseconds
|
||||||
|
- Load package md5 before dumping scsh.image
|
||||||
|
- Revised implementation of SRFI-19
|
||||||
|
- -sfd switch called bogus procedures
|
||||||
|
- Ooopsify write-string/partial
|
||||||
|
- Clean up get_groups
|
||||||
|
- Check for "." in file-name-{sans-}extension
|
||||||
|
- Bug fix for let-match: variables may be #f
|
||||||
|
- Fix some problems with WAIT-FOR-CHANNELS
|
||||||
|
- Fixes in the time zone code
|
||||||
|
- Fix a bug in SEND-MESSAGE: There is such a thing as an empty datagram
|
||||||
|
- Renamed string-filter to make-string-filter and char-filter to
|
||||||
|
make-char-port-filter
|
||||||
|
|
||||||
|
** API changes
|
||||||
|
pause-until-interrupt has been removed because it is not compatible
|
||||||
|
with the thread system
|
||||||
|
|
||||||
|
* New in 0.6.3
|
||||||
|
==============
|
||||||
|
|
||||||
|
** Shorter startup times
|
||||||
|
By a couple of small fixes we could diminish the startup
|
||||||
|
time by 10-30%.
|
||||||
|
|
||||||
|
** stripped-scsh.image
|
||||||
|
In addition to the standard heap image scsh.image, scsh now ships
|
||||||
|
with an additional image stripped-scsh.image. This image contains
|
||||||
|
the same code as the standard image but has almost all debugging
|
||||||
|
information removed. It is therefore much smaller (2.5 MB vs. 4.5
|
||||||
|
MB) which also allows shorter startup times. The image is intended
|
||||||
|
for use in scripts but not for interactive development. See the
|
||||||
|
manual for more information.
|
||||||
|
|
||||||
|
** MD5 support
|
||||||
|
The package md5 contains a bunch of procedures to compute MD5
|
||||||
|
checksums.
|
||||||
|
|
||||||
|
** New SRFIs
|
||||||
|
This release adds support for SRFI 25, 26, 27, 28 and 30.
|
||||||
|
|
||||||
|
** API changes
|
||||||
|
select and select! are supported again.
|
||||||
|
Note however, that we recommend to use the new select-ports and
|
||||||
|
select-port-channels procedures instead whenever possible.
|
||||||
|
New interface to the uname function.
|
||||||
|
New direct interface to the directory stream operations
|
||||||
|
New structure scheme-with-scsh which combines the exports of the
|
||||||
|
modules scsh and scheme, avoiding duplicates
|
||||||
|
New procdures to work directly on file-info records
|
||||||
|
The repl procedure has been removed
|
||||||
|
New procedures connect-socket-no-wait, connect-socket-successful?
|
||||||
|
Add lookup-external from recent S48
|
||||||
|
|
||||||
|
** Bugfixes
|
||||||
|
LET-MATCH, IF-MATCH, and COND-MATCH now behave according to the
|
||||||
|
documentation.
|
||||||
|
Many bug fixes for the SRE system, specifically for dynamic
|
||||||
|
submatches.
|
||||||
|
PORT->SOCKET uses dups both ports of the socket
|
||||||
|
Added missing process resource alignments
|
||||||
|
No reaping for stopped children
|
||||||
|
Initialize t.c_lflag before reading it.
|
||||||
|
Fix to allow single character here strings.
|
||||||
|
Add a whole bunch of S48_GC_PROTECT against s48_extract_integer.
|
||||||
|
Added MAP, FOR-EACH, MEMBER, ASSOC to SRFI 1 interface
|
||||||
|
Fixed a subtle bug in the macro for the << redirection
|
||||||
|
Use "compare" und "rename" to compare symbols in lots of macros
|
||||||
|
Fixed the close method for string-input-ports
|
||||||
|
... and many others.
|
||||||
|
|
||||||
|
* New in 0.6.2
|
||||||
|
==============
|
||||||
|
|
||||||
|
** SRFIs
|
||||||
|
In addition to SRFIs 1, 8, 13, 14 and 23 scsh now features SRFIs 2,
|
||||||
|
5, 6, 7, 9, 11, 16, 17 and 19. See http://srfi.schemers.org/ for a
|
||||||
|
detailed description. The SRFIs are available in packages srfi-N
|
||||||
|
where N is the number of the SRFI.
|
||||||
|
|
||||||
|
** port->socket
|
||||||
|
New procedure port->socket to turn a port into a socket object was
|
||||||
|
added to the network code.
|
||||||
|
|
||||||
|
** New forms in the module language
|
||||||
|
The module language supports the new forms modify, subset and
|
||||||
|
with-prefix from Scheme 48 version 0.57.
|
||||||
|
|
||||||
|
** API changes
|
||||||
|
Fork, fork/pipe, fork/pipe+ take an optional argument
|
||||||
|
continue-threads? to determine whether all threads should continue
|
||||||
|
to run in the child.
|
||||||
|
|
||||||
|
exec-path-list is now a preseved thread fluid
|
||||||
|
|
||||||
|
** PDF version of the manual
|
||||||
|
There is now a PDF version of the manual generated by pdflatex.
|
||||||
|
|
||||||
|
** Bugfixes
|
||||||
|
- Added default argument to tty-info as described in the manual
|
||||||
|
- Conversion to s48_value in tty1.c
|
||||||
|
- Fixed another hygiene problem in SRE
|
||||||
|
- Plugged space leak in bind-listen-accept-loop
|
||||||
|
- Aligned CWD and umask in various file operations
|
||||||
|
- Better releasing of port locks
|
||||||
|
- Corrected exception of time
|
||||||
|
- Set-cloexec to #t for unrevealed ports.
|
||||||
|
- Included scsh paper in the distribution.
|
||||||
|
- Fixed accept for AF_UNIX
|
||||||
|
- (setenv var #f) now deletes var from environment
|
||||||
|
- Quoted { and } within literal strings of regexps
|
||||||
|
|
||||||
|
* New in 0.6.1
|
||||||
|
==============
|
||||||
|
|
||||||
|
** API changes
|
||||||
|
For sre's, BOW, EOW, WORD, and WORD+ (which were already unsupported
|
||||||
|
in 0.6.0 on most platforms) are gone for good.
|
||||||
|
|
||||||
|
** Bugfixes
|
||||||
|
Most of the known bugs of version 0.6.0 have been fixed, many thanks for
|
||||||
|
the precise reports! See the project page on SourceForge for a list
|
||||||
|
of the remaining known bugs. Here is a brief overview of the fixes:
|
||||||
|
|
||||||
|
- GC_PROTECT'ed the necessary variables (specifically, where >1 arg to
|
||||||
|
a function 'may GC') (Thanks to Steven Jenkins for dealing with this)
|
||||||
|
- Fixed various race conditons in the signal handling and process reaping code
|
||||||
|
- Fixed bug in set-process-group
|
||||||
|
- If $HOME is unset, consult (user-info (user-uid)) for the value of
|
||||||
|
home-directory
|
||||||
|
- Fix external-call-from-callback problem leading to spurious
|
||||||
|
gc-protection-mismatch exceptions.
|
||||||
|
- Let s48-do-gc return 0 so the PreScheme compiler will emit the correct
|
||||||
|
signature of the function.
|
||||||
|
- scsh/linux/tty-consts.scm: num-ttychars seems to be 32 not 19.
|
||||||
|
- scsh/top.scm: Return 0 exit status for -c and -e.
|
||||||
|
- *.c: Replaced // comments.
|
||||||
|
- scsh/syslog1.c: Remove LOG_LPR from list of syslog levels.
|
||||||
|
- scsh/network1.c: Pass SYSCALL argument to ERRNO-ERROR.
|
||||||
|
- scsh/syscalls1.c: Disable timer interrupts before execve
|
||||||
|
- scsh/network.scm: Correct name extraction in bind-socket
|
||||||
|
- Added export for with-error-output-port
|
||||||
|
- Install HTML version of manual under $(libdir)
|
||||||
|
- ./configure is more rebost wrt $(srcdir)
|
||||||
|
- Fixed installation of the S48 manual
|
||||||
|
- Replaced several /tmp by /var/tmp
|
||||||
|
- Catch EISDIR in delete-filesys-object
|
||||||
|
- flush-all-ports is now non-blocking
|
||||||
|
|
||||||
|
* New in 0.6.0
|
||||||
|
==============
|
||||||
|
|
||||||
|
** Scsh is now based on Scheme 48 0.53
|
||||||
|
With the move from Scheme 48 version 0.36 to version 0.53 in this
|
||||||
|
release the underlying system received a massive update. The most
|
||||||
|
significant changes include:
|
||||||
|
User level threads
|
||||||
|
Advanced garbage collector
|
||||||
|
Improved foreign function interface to C
|
||||||
|
|
||||||
|
The most significant change for Scsh users is the addition of a
|
||||||
|
user-level thread system. Scsh provides various features to deal
|
||||||
|
with this new power in a system programming environment: An event
|
||||||
|
based interface to interrupts, thread local process state and
|
||||||
|
thread-safe system calls.
|
||||||
|
|
||||||
|
** A manual for Scheme 48 has been included
|
||||||
|
Richard Kelsey, the author of Scheme 48, has graciously allowed us
|
||||||
|
to retrofit the current Scheme 48 manual for inclusion in this scsh
|
||||||
|
release.
|
||||||
|
|
||||||
|
** Interfaces to dot-locking, crypt and syslog
|
||||||
|
Scsh now provides advisory file locking via the dot-locking scheme
|
||||||
|
and a direct binding to the crypt function. Furthermore we added
|
||||||
|
a complete, system-independent and thread-safe interface to syslog.
|
||||||
|
|
||||||
|
** API changes
|
||||||
|
Some features of the previous releases are currently not
|
||||||
|
supported as we did not have the time to implement them. Please tell
|
||||||
|
us, if you can't get along without them. Here is a listing of these
|
||||||
|
currently dereleased features:
|
||||||
|
select
|
||||||
|
select!
|
||||||
|
ODBC support
|
||||||
|
bufpol/line
|
||||||
|
|
||||||
|
The following procedures received new names in this release:
|
||||||
|
sleep (now process-sleep)
|
||||||
|
sleep-until (now process-sleep-until)
|
||||||
|
|
||||||
|
network-info, service-info and protocol-info now return #f on non-success.
|
||||||
|
|
||||||
|
The default directory for creating temporary files has changed: It's
|
||||||
|
now the value of $TMPDIR if set and /var/tmp otherwise.
|
||||||
|
|
||||||
|
The nth procedure is still there but is now officially obsolete. It
|
||||||
|
will go away in a future release.
|
||||||
|
|
||||||
|
** HTML version of the manual
|
||||||
|
There is now a HTML version of the scsh manual generated by tex2page
|
||||||
|
|
||||||
|
* Thanks
|
||||||
|
========
|
||||||
|
|
||||||
|
We would like to thank the members of local-resistance cells for the
|
||||||
|
Underground everywhere for bug reports, bug fixes, design review and comments
|
||||||
|
that were incorporated into this release. We really appreciate their help,
|
||||||
|
particularly in the task of porting scsh to new platforms.
|
||||||
|
|
||||||
|
|
||||||
|
Brought to you by the Scheme Underground. Go forth and write elegant systems
|
||||||
|
programs.
|
||||||
|
-Olin Shivers, Brian Carlstrom, Martin Gasbichler & Mike Sperber
|
||||||
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
0.6.1 release-critical:
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Non-critical: [Martin]
|
||||||
|
=============
|
||||||
|
S48_EXTRACT_BOOLEAN is defined several times
|
||||||
|
|
||||||
|
create-file-thing should report a better error message.
|
||||||
|
|
||||||
|
/* Sorry, we only have a version with 5 arguments..*/.
|
||||||
|
s48_raise_os_error_5 (errno, sec, min, hour, mday, month);
|
||||||
|
|
||||||
|
|
||||||
|
how do i make the scheme48 heap larger? preferably without having to write
|
||||||
|
scripts that start like this:
|
||||||
|
|
||||||
|
#!/usr/local/lib/scsh/scshvm \
|
||||||
|
-o /usr/local/lib/scsh/scshvm -i /usr/local/lib/scsh/scsh.image -h <large-value>
|
||||||
|
-s
|
||||||
|
!#
|
||||||
|
|
||||||
|
Check whether we have remove the extern char *tzname[] declaration in time1.c
|
||||||
|
|
||||||
|
implement bufpol/line's flush on stdin
|
||||||
|
|
||||||
|
|
||||||
|
Move the code of time_plus_ticks to time1.c as it is not machine dependent
|
||||||
|
|
||||||
|
--->
|
||||||
|
The module system doesn't maintain a cwd of its own:
|
||||||
|
|
||||||
|
> ,config ,load ../sunet/xml/xml-packages.scm
|
||||||
|
../sunet/xml/xml-packages.scm
|
||||||
|
> (chdir "/tmp")
|
||||||
|
> ,open xml
|
||||||
|
Load structure xml (y/n)? y
|
||||||
|
[plt-compat
|
||||||
|
Error: exception
|
||||||
|
cannot-open-channel
|
||||||
|
(open-channel "../sunet/xml/plt.scm" 1)
|
||||||
|
<---
|
||||||
|
|
||||||
|
split up newports.scm (part that overwrites s48 defs, port-buffering, ...)
|
||||||
|
|
||||||
|
disallow cig to produce more than 12 arguments
|
||||||
|
|
||||||
|
libcig1.c : cig_string_body is probably extract_string
|
||||||
|
IsChar is used nowhere
|
||||||
|
|
||||||
|
Add .h.c rule to Makefile
|
||||||
|
|
||||||
|
--->
|
||||||
|
(define-syntax bla
|
||||||
|
(syntax-rules ()
|
||||||
|
((bla)
|
||||||
|
(rx any))))
|
||||||
|
> (bla)
|
||||||
|
|
||||||
|
Error: Illegal regular expression
|
||||||
|
#{Generated any 1276}
|
||||||
|
|
||||||
|
(Because "any" is imported from scsh-utilities in rx/parse.scm)
|
||||||
|
<---
|
||||||
|
|
||||||
|
Set port policy for input to bufpol/line via isatty
|
||||||
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
Post-0.5.2-release bug reports:
|
||||||
|
Friedrich Dominicus
|
||||||
|
Jay Nietling
|
||||||
|
Tim Bradshaw
|
||||||
|
Robert Brown
|
||||||
|
Eric Marsden
|
||||||
|
Paul Emsley
|
||||||
|
Pawel Turnau
|
||||||
|
Hannu Koivisto
|
||||||
|
Andy Gaynor
|
||||||
|
Francisco Vides Fernandez
|
||||||
|
Tim Burgess
|
||||||
|
Brian Denheyer
|
||||||
|
Harvey Stein
|
||||||
|
Eric Hilsdale
|
||||||
|
Andreas Bernauer
|
||||||
|
Chris Beggy
|
||||||
|
Ed Kademan
|
||||||
|
Michal Maruska
|
||||||
|
Noel Hunt
|
||||||
|
David Reiss
|
||||||
|
Chad R Dougherty
|
||||||
|
Michel Schinz
|
||||||
|
Alan Bawden
|
||||||
|
Bengt Kleberg
|
||||||
|
RT Happe
|
||||||
|
Dorai Sitaram
|
||||||
32
acconfig.h
32
acconfig.h
|
|
@ -1,32 +0,0 @@
|
||||||
/*
|
|
||||||
* HAVE_SIGACTION is defined iff sigaction() is available.
|
|
||||||
*/
|
|
||||||
#undef HAVE_SIGACTION
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HAVE_STRERROR is defined iff the standard libraries provide strerror().
|
|
||||||
*/
|
|
||||||
#undef HAVE_STRERROR
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NLIST_HAS_N_NAME is defined iff a struct nlist has an n_name member.
|
|
||||||
* If it doesn't then we assume it has an n_un member which, in turn,
|
|
||||||
* has an n_name member.
|
|
||||||
*/
|
|
||||||
#undef NLIST_HAS_N_NAME
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HAVE_SYS_SELECT_H is defined iff we have the include file sys/select.h.
|
|
||||||
*/
|
|
||||||
#undef HAVE_SYS_SELECT_H
|
|
||||||
|
|
||||||
/*
|
|
||||||
* USCORE is defined iff C externals are prepended with an underscore.
|
|
||||||
*/
|
|
||||||
#undef USCORE
|
|
||||||
|
|
||||||
@BOTTOM@
|
|
||||||
|
|
||||||
#include "fake/sigact.h"
|
|
||||||
#include "fake/strerror.h"
|
|
||||||
#include "fake/sys-select.h"
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
autoheader &&
|
||||||
|
autoconf &&
|
||||||
|
./configure &&
|
||||||
|
touch scsh/*.c &&
|
||||||
|
touch build/filenames.scm &&
|
||||||
|
rm -f scheme48.image cig/cig.image scsh/scsh.image &&
|
||||||
|
rm -f build/linker.image build/initial.image &&
|
||||||
|
rm -f c/scheme48.h &&
|
||||||
|
make build/filenames.make &&
|
||||||
|
make i-know-what-i-am-doing &&
|
||||||
|
make c/scheme48.h&&
|
||||||
|
make linker &&
|
||||||
|
make build/initial.image &&
|
||||||
|
make distclean
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Build external-modules.c.
|
||||||
|
|
||||||
|
target="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
(
|
||||||
|
cat <<!
|
||||||
|
|
||||||
|
!
|
||||||
|
for i in "s48_initialize_external" "$@"; do
|
||||||
|
cat <<!
|
||||||
|
extern void $i(void);
|
||||||
|
!
|
||||||
|
done
|
||||||
|
cat <<!
|
||||||
|
|
||||||
|
void s48_initialize_external_modules (void) {
|
||||||
|
!
|
||||||
|
for i in "s48_initialize_external" "$@"; do
|
||||||
|
cat <<!
|
||||||
|
$i();
|
||||||
|
!
|
||||||
|
done
|
||||||
|
cat <<!
|
||||||
|
};
|
||||||
|
!
|
||||||
|
) >"$target"
|
||||||
|
|
@ -9,7 +9,7 @@ vm=$4
|
||||||
initial=$5
|
initial=$5
|
||||||
USER=${USER-`logname 2>/dev/null || echo '*GOK*'`}
|
USER=${USER-`logname 2>/dev/null || echo '*GOK*'`}
|
||||||
|
|
||||||
$vm -i $initial -a batch <<EOF
|
./$vm -o ./$vm -i $initial batch <<EOF
|
||||||
,load $srcdir/scheme/env/init-defpackage.scm
|
,load $srcdir/scheme/env/init-defpackage.scm
|
||||||
((*structure-ref filenames 'set-translation!)
|
((*structure-ref filenames 'set-translation!)
|
||||||
"=scheme48/" "$srcdir/scheme/")
|
"=scheme48/" "$srcdir/scheme/")
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
#### This file was generated automatically. ####
|
|
||||||
|
|
||||||
initial-files = scheme/rts/low.scm scheme/rts/signal.scm scheme/rts/base.scm scheme/rts/util.scm scheme/rts/number.scm scheme/rts/lize.scm scheme/rts/record.scm scheme/rts/jar-defrecord.scm scheme/rts/method.scm scheme/rts/numio.scm scheme/rts/fluid.scm scheme/rts/defenum.scm scheme/vm/arch.scm scheme/big/queue.scm scheme/rts/condition.scm scheme/rts/session.scm scheme/rts/interrupt.scm scheme/rts/wind.scm scheme/rts/template.scm scheme/rts/continuation.scm scheme/rts/exception.scm scheme/rts/thread.scm scheme/rts/sleep.scm scheme/rts/lock.scm scheme/rts/port.scm scheme/rts/current-port.scm scheme/rts/write.scm scheme/rts/read.scm scheme/rts/channel.scm scheme/rts/channel-port.scm scheme/rts/channel-io.scm scheme/big/general-table.scm scheme/rts/population.scm scheme/bcomp/mtype.scm scheme/bcomp/interface.scm scheme/bcomp/binding.scm scheme/bcomp/name.scm scheme/bcomp/transform.scm scheme/bcomp/cenv.scm scheme/bcomp/thingie.scm scheme/bcomp/package.scm scheme/bcomp/package-undef.scm scheme/rts/env.scm scheme/big/filename.scm scheme/bcomp/read-form.scm scheme/bcomp/node.scm scheme/bcomp/schemify.scm scheme/bcomp/var-util.scm scheme/bcomp/syntax.scm scheme/bcomp/primop.scm scheme/bcomp/ddata.scm scheme/bcomp/stack-check.scm scheme/bcomp/state.scm scheme/bcomp/segment.scm scheme/bcomp/recon.scm scheme/bcomp/comp-exp.scm scheme/bcomp/comp-prim.scm scheme/bcomp/comp.scm scheme/rts/eval.scm scheme/env/dispcond.scm scheme/debug/mini-command.scm scheme/rts/scheduler.scm scheme/rts/root-scheduler.scm scheme/rts/init.scm scheme/env/start.scm scheme/bcomp/usual.scm scheme/bcomp/rules.scm scheme/bcomp/type.scm scheme/bcomp/module-language.scm scheme/bcomp/config.scm scheme/bcomp/scan-package.scm scheme/bcomp/optimize.scm scheme/bcomp/comp-package.scm scheme/env/load-package.scm scheme/big/strong.scm scheme/opt/usage.scm scheme/opt/sort.scm scheme/opt/inline.scm scheme/bcomp/for-reify.scm
|
|
||||||
|
|
||||||
usual-files = scheme/opt/analyze.scm scheme/env/disclosers.scm scheme/env/command-level.scm scheme/env/version-info.scm scheme/env/command.scm scheme/env/read-command.scm scheme/env/debuginfo.scm scheme/rts/xnum.scm scheme/rts/bignum.scm scheme/rts/ratnum.scm scheme/rts/recnum.scm scheme/rts/innum.scm scheme/env/basic-command.scm scheme/env/build.scm scheme/env/shadow.scm scheme/env/pedit.scm scheme/env/pacman.scm scheme/rts/time.scm scheme/env/debug.scm scheme/env/inspect.scm scheme/env/disasm.scm
|
|
||||||
|
|
||||||
linker-files = scheme/rts/util.scm scheme/alt/fluid.scm scheme/rts/defenum.scm scheme/vm/arch.scm scheme/alt/jar-defrecord.scm scheme/big/general-table.scm scheme/bcomp/mtype.scm scheme/alt/locations.scm scheme/bcomp/binding.scm scheme/bcomp/name.scm scheme/bcomp/transform.scm scheme/bcomp/node.scm scheme/bcomp/schemify.scm scheme/bcomp/var-util.scm scheme/bcomp/primop.scm scheme/alt/template.scm scheme/rts/template.scm scheme/bcomp/ddata.scm scheme/bcomp/thingie.scm scheme/bcomp/stack-check.scm scheme/bcomp/state.scm scheme/bcomp/segment.scm scheme/bcomp/recon.scm scheme/bcomp/comp-exp.scm scheme/bcomp/comp-prim.scm scheme/bcomp/comp.scm scheme/alt/closure.scm scheme/link/data.scm scheme/link/transport.scm scheme/link/write-image.scm scheme/alt/weak.scm scheme/rts/population.scm scheme/bcomp/interface.scm scheme/bcomp/cenv.scm scheme/bcomp/package.scm scheme/bcomp/package-undef.scm scheme/bcomp/syntax.scm scheme/env/debuginfo.scm scheme/big/filename.scm scheme/bcomp/read-form.scm scheme/bcomp/scan-package.scm scheme/bcomp/optimize.scm scheme/bcomp/usual.scm scheme/bcomp/rules.scm scheme/bcomp/comp-package.scm scheme/big/strong.scm scheme/opt/usage.scm scheme/opt/sort.scm scheme/opt/inline.scm scheme/link/reify.scm scheme/link/link.scm scheme/alt/loophole.scm scheme/bcomp/type.scm scheme/alt/low.scm scheme/bcomp/module-language.scm scheme/bcomp/config.scm scheme/opt/analyze.scm scheme/alt/environments.scm scheme/link/loadc.scm scheme/env/flatload.scm
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
; Define DEFINE-STRUCTURE and friends
|
; Define DEFINE-STRUCTURE and friends
|
||||||
(for-each load
|
(for-each load
|
||||||
'("scheme/bcomp/module-language.scm"
|
'("scheme/bcomp/module-language.scm"
|
||||||
|
"scheme/alt/dummy-interface.scm"
|
||||||
"scheme/alt/config.scm"
|
"scheme/alt/config.scm"
|
||||||
"scheme/env/flatload.scm"))
|
"scheme/env/flatload.scm"))
|
||||||
|
|
||||||
|
|
|
||||||
6351
build/initial.debug
6351
build/initial.debug
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
|
@ -1,4 +1,4 @@
|
||||||
; Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees. See file COPYING.
|
; Copyright (c) 1993-2000 by Richard Kelsey and Jonathan Rees. See file COPYING.
|
||||||
|
|
||||||
; Link script.
|
; Link script.
|
||||||
|
|
||||||
|
|
@ -30,7 +30,7 @@
|
||||||
(l '()))
|
(l '()))
|
||||||
(for-each (lambda (int)
|
(for-each (lambda (int)
|
||||||
(for-each-declaration
|
(for-each-declaration
|
||||||
(lambda (name type)
|
(lambda (name package-name type)
|
||||||
(if (not (assq name l))
|
(if (not (assq name l))
|
||||||
(let ((s (eval name env)))
|
(let ((s (eval name env)))
|
||||||
(if (structure? s)
|
(if (structure? s)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
; Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees. See file COPYING.
|
||||||
|
|
||||||
|
; Load the linker. -*- Mode: Scheme; -*-
|
||||||
|
|
||||||
|
; Run this script with ,exec ,load l.exec.
|
||||||
|
; After the script is loaded, you can, in principle, do whatever
|
||||||
|
; you might do in the usual linker image. For example, you might do
|
||||||
|
; (this is from the Makefile)
|
||||||
|
;
|
||||||
|
; ,in link-config
|
||||||
|
; (load-configuration "interfaces.scm")
|
||||||
|
; (load-configuration "packages.scm")
|
||||||
|
; (flatload initial-structures)
|
||||||
|
; (load "initial.scm")
|
||||||
|
; (link-initial-system)
|
||||||
|
;
|
||||||
|
; This is intended to be used to debug new versions of the compiler or
|
||||||
|
; static linker.
|
||||||
|
|
||||||
|
(config '(run (define :arguments :values))) ;temporary hack
|
||||||
|
|
||||||
|
(translate "=scheme48/" "./")
|
||||||
|
|
||||||
|
(load-package 'flatloading)
|
||||||
|
(open 'flatloading)
|
||||||
|
|
||||||
|
(define (r x) (config `(run ,x)))
|
||||||
|
|
||||||
|
(r '(define-structure source-file-names (export (%file-name% :syntax))
|
||||||
|
(open scheme-level-1
|
||||||
|
syntactic
|
||||||
|
fluids)
|
||||||
|
(begin (define-syntax %file-name%
|
||||||
|
(syntax-rules ()
|
||||||
|
((%file-name%) (fluid $source-file-name)))))))
|
||||||
|
|
||||||
|
(r '(define-structure enumerated enumerated-interface
|
||||||
|
(open scheme-level-1 signals)
|
||||||
|
(files (rts defenum scm))))
|
||||||
|
|
||||||
|
(r '(define-structure architecture architecture-interface
|
||||||
|
(open scheme-level-1 signals enumerated)
|
||||||
|
(files (rts arch))))
|
||||||
|
|
||||||
|
(config '(structure reflective-tower-maker
|
||||||
|
(export-reflective-tower-maker)))
|
||||||
|
|
||||||
|
; Make the new linker obtain its table, record, etc. structures from
|
||||||
|
; the currently running Scheme.
|
||||||
|
|
||||||
|
(config '(load "packages.scm"))
|
||||||
|
(config '(structure %run-time-structures run-time-structures-interface))
|
||||||
|
(config '(structure %features-structures features-structures-interface))
|
||||||
|
|
||||||
|
(r
|
||||||
|
'(define-structure %linker-structures
|
||||||
|
(make-linker-structures %run-time-structures
|
||||||
|
%features-structures
|
||||||
|
(make-compiler-structures %run-time-structures
|
||||||
|
%features-structures))))
|
||||||
|
|
||||||
|
; Load the linker's interface and structure definitions.
|
||||||
|
(config '(load "interfaces.scm" "more-interfaces.scm"))
|
||||||
|
(let ((z (config '(run %linker-structures)))
|
||||||
|
(env (config interaction-environment)))
|
||||||
|
(config (lambda () (flatload z env))))
|
||||||
|
|
||||||
|
; Load the linker.
|
||||||
|
(load-package 'link-config)
|
||||||
|
|
||||||
|
; Initialize
|
||||||
|
(in 'link-config
|
||||||
|
'(open scheme packages packages-internal
|
||||||
|
reflective-tower-maker))
|
||||||
|
|
||||||
|
(in 'linker '(run (set! *debug-linker?* #t)))
|
||||||
|
(in 'link-config '(open flatloading)) ; A different one.
|
||||||
|
|
||||||
|
; ,open debuginfo packages-internal compiler scan syntactic meta-types
|
||||||
|
|
||||||
|
; (in 'link-config '(dump "l.image"))
|
||||||
|
|
||||||
|
; ,exec (usual-stuff)
|
||||||
|
|
||||||
|
(define (usual-stuff)
|
||||||
|
(in 'link-config)
|
||||||
|
(run '(begin (load-configuration "interfaces.scm")
|
||||||
|
(load-configuration "packages.scm")
|
||||||
|
(flatload initial-structures)))
|
||||||
|
(load "initial.scm"))
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
|
||||||
|
; Script to load the Scheme 48 linker into Common Lisp.
|
||||||
|
; Requires Pseudoscheme 2.11.
|
||||||
|
|
||||||
|
(defvar pseudoscheme-directory "../pseudo/")
|
||||||
|
(load (concatenate 'string pseudoscheme-directory "loadit.lisp"))
|
||||||
|
; or perhaps (load (merge-pathnames "loadit.lisp" pseudoscheme-directory))
|
||||||
|
(load-pseudoscheme pseudoscheme-directory)
|
||||||
|
|
||||||
|
(progn (revised^4-scheme::define-sharp-macro #\.
|
||||||
|
#'(lambda (c port)
|
||||||
|
(read-char port)
|
||||||
|
(eval (let ((*readtable* ps::scheme-readtable))
|
||||||
|
(read port)))))
|
||||||
|
(values))
|
||||||
|
|
||||||
|
(ps:scheme)
|
||||||
|
;--------------------
|
||||||
|
; Scheme forms
|
||||||
|
|
||||||
|
(benchmark-mode)
|
||||||
|
|
||||||
|
(define config-env ; (interaction-environment) would also work here.
|
||||||
|
(#.'scheme-translator:make-program-env
|
||||||
|
'%config
|
||||||
|
(list #.'scheme-translator:revised^4-scheme-structure)))
|
||||||
|
|
||||||
|
(load "bcomp/module-language" config-env)
|
||||||
|
(load "alt/config" config-env)
|
||||||
|
(load "env/flatload" config-env)
|
||||||
|
(eval '(set! *load-file-type* #f) config-env)
|
||||||
|
|
||||||
|
(define load-config
|
||||||
|
(let ((load-config (eval 'load-configuration config-env)))
|
||||||
|
(lambda (filename)
|
||||||
|
(load-config filename config-env))))
|
||||||
|
|
||||||
|
(load-config "packages")
|
||||||
|
|
||||||
|
(define flatload-package (eval 'flatload config-env))
|
||||||
|
|
||||||
|
(flatload-package (eval 'linker-structures config-env) config-env)
|
||||||
|
|
||||||
|
(let ((#.'clever-load:*compile-if-necessary-p* #t))
|
||||||
|
(let ((#.'ps:*scheme-read* #.'#'ps::scheme-read-using-commonlisp-reader))
|
||||||
|
(load "alt/pseudoscheme-record")
|
||||||
|
(load "alt/pseudoscheme-features")))
|
||||||
|
|
||||||
|
(let ((#.'clever-load:*compile-if-necessary-p* #t))
|
||||||
|
(flatload-package (eval 'link-config config-env)))
|
||||||
|
|
||||||
|
(load "alt/init-defpackage.scm")
|
||||||
|
|
||||||
|
(define-syntax struct-list ;not in link.sbin
|
||||||
|
(syntax-rules ()
|
||||||
|
((struct-list ?name ...) (list (cons '?name ?name) ...))))
|
||||||
|
|
||||||
|
;--------------------
|
||||||
|
(quit)
|
||||||
|
|
||||||
|
#+Lucid
|
||||||
|
(defun disksave-restart-function ()
|
||||||
|
(format t "~&Scheme 48 linker.~2%")
|
||||||
|
;; (hax:init-interrupt-delivery) - for threads
|
||||||
|
(ps:scheme)
|
||||||
|
(terpri))
|
||||||
|
#+Lucid
|
||||||
|
(defun dump-linker ()
|
||||||
|
(lcl:disksave "link/linker-in-lucid" :gc t :full-gc t :verbose t
|
||||||
|
:restart-function #'disksave-restart-function))
|
||||||
|
;(dump-linker)
|
||||||
|
;(lcl:quit)
|
||||||
|
|
||||||
|
|
||||||
|
; Debugging hacks
|
||||||
|
;(defun enable-lisp-packages ()
|
||||||
|
; (setq *readtable* ps:scheme-readtable)
|
||||||
|
; (values))
|
||||||
|
;(defun disable-lisp-packages ()
|
||||||
|
; (setq *readtable* ps::roadblock-readtable)
|
||||||
|
; (values))
|
||||||
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
53
|
6.4
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
sysdep.h
|
||||||
|
sysdep.h.in
|
||||||
|
|
@ -1,4 +1,10 @@
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
#define TRUE (0 == 0)
|
#define TRUE (0 == 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
#define FALSE (0 == 1)
|
#define FALSE (0 == 1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define bool char /* boolean type */
|
#define bool char /* boolean type */
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
enum event_enum { KEYBOARD_INTERRUPT_EVENT, IO_COMPLETION_EVENT, ALARM_EVENT,
|
enum event_enum { KEYBOARD_INTERRUPT_EVENT,
|
||||||
OS_SIGNAL_EVENT, ERROR_EVENT, NO_EVENT };
|
IO_READ_COMPLETION_EVENT, IO_WRITE_COMPLETION_EVENT,
|
||||||
|
ALARM_EVENT,
|
||||||
|
OS_SIGNAL_EVENT, ERROR_EVENT, NO_EVENT };
|
||||||
|
|
||||||
extern bool s48_add_pending_fd(int fd, bool is_input);
|
extern bool s48_add_pending_fd(int fd, bool is_input);
|
||||||
extern bool s48_remove_fd(int fd);
|
extern bool s48_remove_fd(int fd);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
/* Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees.
|
||||||
|
See file COPYING. */
|
||||||
|
|
||||||
|
/* Implementation of the vm-extension opcode. This is completely
|
||||||
|
optional; nothing in the standard system uses these features.
|
||||||
|
If you have ANSI C but not POSIX support, try compiling with -DPOSIX=0.
|
||||||
|
|
||||||
|
The vm-extension opcode is being phased out. New code should use the
|
||||||
|
external-call opcode to call C procedures.
|
||||||
|
|
||||||
|
floating point: POSIX.1, ANSI C (should we be linking with -lM or -lm?)
|
||||||
|
sprintf: POSIX.1, ANSI C
|
||||||
|
atof: POSIX.1, ANSI C
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef POSIX
|
||||||
|
# define POSIX 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sysdep.h"
|
||||||
|
#include "scheme48.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <unistd.h> /* setuid & setgid */
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netdb.h> /* gethostbyname */ /* Kali code */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define GREATEST_FIXNUM_VALUE ((1 << 29) - 1)
|
||||||
|
#define LEAST_FIXNUM_VALUE (-1 << 29)
|
||||||
|
#define CHANNEL_INDEX(x) EXTRACT_FIXNUM(STOB_REF(x, 1))
|
||||||
|
#define FOR_INPUT 1
|
||||||
|
#define FOR_OUTPUT 2
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char b[sizeof(double)];
|
||||||
|
} unaligned_double;
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
double f;
|
||||||
|
unaligned_double b;
|
||||||
|
} float_or_bytes;
|
||||||
|
|
||||||
|
extern long s48_Sextension_valueS; /* how values are returned */
|
||||||
|
|
||||||
|
/* return status values */
|
||||||
|
#define EXT_ST_OKAY 0
|
||||||
|
#define EXT_ST_EXCEPTION 1
|
||||||
|
|
||||||
|
#define EXT_RETURN(value) {s48_Sextension_valueS = (value); return EXT_ST_OKAY; }
|
||||||
|
#define EXT_EXCEPTION return EXT_ST_EXCEPTION
|
||||||
|
|
||||||
|
/******************************************/
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_extended_vm (long key, s48_value value)
|
||||||
|
{
|
||||||
|
double x, y;
|
||||||
|
|
||||||
|
switch (key) {
|
||||||
|
|
||||||
|
/* Cases 0 through 19 are reserved for the mobot system. */
|
||||||
|
|
||||||
|
case 0: /* read jumpers on 68000 board */
|
||||||
|
EXT_RETURN(S48_UNSAFE_ENTER_FIXNUM(0));
|
||||||
|
|
||||||
|
/* Floating point */
|
||||||
|
|
||||||
|
#define FLOP 100
|
||||||
|
#define FLOP2(i) case FLOP+(i): \
|
||||||
|
if (!S48_STOB_P(value) || S48_STOB_DESCRIPTOR_LENGTH(value) != 2) \
|
||||||
|
EXT_EXCEPTION;
|
||||||
|
#define FLOP3(i) case FLOP+(i): \
|
||||||
|
if (!S48_STOB_P(value) || S48_STOB_DESCRIPTOR_LENGTH(value) != 3) \
|
||||||
|
EXT_EXCEPTION;
|
||||||
|
|
||||||
|
#define get_arg(args,i) S48_STOB_REF(args,(i))
|
||||||
|
#define get_string_arg(args,i) (S48_UNSAFE_EXTRACT_STRING(get_arg(args,i)))
|
||||||
|
|
||||||
|
#define get_float_arg(args, i, var) EXTRACT_FLOAT(get_arg(args, i), var)
|
||||||
|
#define set_float_arg(args, i, val) SET_FLOAT(get_arg(args, i), val)
|
||||||
|
|
||||||
|
#define EXTRACT_FLOAT(stob, var) \
|
||||||
|
{ s48_value temp_ = (stob); \
|
||||||
|
float_or_bytes loser_; \
|
||||||
|
if (!S48_STOB_P(temp_)) EXT_EXCEPTION; \
|
||||||
|
loser_.b = *(unaligned_double*)(&S48_STOB_REF(temp_, 0)); \
|
||||||
|
(var) = loser_.f; }
|
||||||
|
|
||||||
|
#define SET_FLOAT(stob, val) \
|
||||||
|
{ s48_value temp_ = (stob); \
|
||||||
|
float_or_bytes loser_; \
|
||||||
|
if (!S48_STOB_P(temp_)) EXT_EXCEPTION; \
|
||||||
|
loser_.f = (double)(val); \
|
||||||
|
*(unaligned_double*)(&S48_STOB_REF(temp_, 0)) = loser_.b; }
|
||||||
|
|
||||||
|
FLOP3(0) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
set_float_arg(value, 2, x + y);
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP3(1) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
set_float_arg(value, 2, x - y);
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP3(2) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
set_float_arg(value, 2, x * y);
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP3(3) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
if (y == 0.0) EXT_EXCEPTION;
|
||||||
|
set_float_arg(value, 2, x / y);
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(4) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
EXT_RETURN(S48_ENTER_BOOLEAN(x == y));}
|
||||||
|
FLOP2(5) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
EXT_RETURN(S48_ENTER_BOOLEAN(x < y));}
|
||||||
|
FLOP2(6) { /* fixnum->float */
|
||||||
|
s48_value arg = get_arg(value, 0);
|
||||||
|
if (!S48_FIXNUM_P(arg)) EXT_RETURN(S48_FALSE);
|
||||||
|
set_float_arg(value, 1, S48_UNSAFE_EXTRACT_FIXNUM(arg));
|
||||||
|
EXT_RETURN(S48_TRUE);}
|
||||||
|
FLOP2(7) { /* string->float */
|
||||||
|
char *str = get_string_arg(value, 0);
|
||||||
|
set_float_arg(value, 1, atof(str));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(8) { /* float->string */
|
||||||
|
size_t len;
|
||||||
|
char *str = get_string_arg(value,1);
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
sprintf(str, "%g", x);
|
||||||
|
len = strlen(str);
|
||||||
|
if (len > S48_UNSAFE_STRING_LENGTH(get_arg(value,1)))
|
||||||
|
/* unlikely but catastrophic */
|
||||||
|
fprintf(stderr, "printing float: output too long: %s\n",
|
||||||
|
str);
|
||||||
|
EXT_RETURN(S48_UNSAFE_ENTER_FIXNUM(len));}
|
||||||
|
|
||||||
|
/* exp log sin cos tan asin acos atan sqrt */
|
||||||
|
|
||||||
|
FLOP2(9) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, exp(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(10) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, log(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(11) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, sin(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(12) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, cos(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(13) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, tan(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(14) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, asin(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(15) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, acos(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP3(16) { /* atan */
|
||||||
|
get_float_arg(value, 0, y);
|
||||||
|
get_float_arg(value, 1, x);
|
||||||
|
set_float_arg(value, 2, atan2(y, x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP2(17) {
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, sqrt(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
|
||||||
|
FLOP2(18) { /* floor */
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
set_float_arg(value, 1, floor(x));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
case FLOP+19: { /* integer? */
|
||||||
|
EXTRACT_FLOAT(value, x);
|
||||||
|
EXT_RETURN(S48_ENTER_BOOLEAN(fmod(x, 1.0) == 0.0)); }
|
||||||
|
case FLOP+20: { /* float->fixnum */
|
||||||
|
EXTRACT_FLOAT(value, x);
|
||||||
|
if (x <= (double)GREATEST_FIXNUM_VALUE
|
||||||
|
&& x >= (double)LEAST_FIXNUM_VALUE)
|
||||||
|
{
|
||||||
|
EXT_RETURN(S48_UNSAFE_ENTER_FIXNUM((long)x)); }
|
||||||
|
else
|
||||||
|
EXT_RETURN(S48_FALSE);}
|
||||||
|
FLOP3(21) { /* quotient */
|
||||||
|
double z;
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
if (fmod(x, 1.0) != 0.0 || fmod(y, 1.0) != 0.0) EXT_EXCEPTION;
|
||||||
|
if (y == 0.0) EXT_EXCEPTION;
|
||||||
|
z = x / y;
|
||||||
|
set_float_arg(value, 2, z < 0.0 ? ceil(z) : floor(z));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
FLOP3(22) { /* remainder */
|
||||||
|
get_float_arg(value, 0, x);
|
||||||
|
get_float_arg(value, 1, y);
|
||||||
|
if (fmod(x, 1.0) != 0.0 || fmod(y, 1.0) != 0.0) EXT_EXCEPTION;
|
||||||
|
if (y == 0.0) EXT_EXCEPTION;
|
||||||
|
|
||||||
|
/* "fmod(double x, double y) returns the floating-point remainder
|
||||||
|
(f) of the division of x by y, where f has the same sign as x,
|
||||||
|
such that x=iy+f for some integer i, and |f| < |y|." */
|
||||||
|
|
||||||
|
set_float_arg(value, 2, fmod(x, y));
|
||||||
|
EXT_RETURN(S48_UNSPECIFIC);}
|
||||||
|
|
||||||
|
default:
|
||||||
|
EXT_EXCEPTION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
404
c/external.c
404
c/external.c
|
|
@ -127,6 +127,8 @@ s48_value
|
||||||
s48_external_call(s48_value sch_proc, s48_value proc_name,
|
s48_external_call(s48_value sch_proc, s48_value proc_name,
|
||||||
long nargs, char *char_argv)
|
long nargs, char *char_argv)
|
||||||
{
|
{
|
||||||
|
volatile char *gc_marker; /* volatile to survive longjumps */
|
||||||
|
char *gc_marker_temp; /* C wants it so */
|
||||||
volatile char *gc_roots_marker; /* volatile to survive longjumps */
|
volatile char *gc_roots_marker; /* volatile to survive longjumps */
|
||||||
volatile s48_value name = proc_name; /* volatile to survive longjumps */
|
volatile s48_value name = proc_name; /* volatile to survive longjumps */
|
||||||
|
|
||||||
|
|
@ -144,7 +146,8 @@ s48_external_call(s48_value sch_proc, s48_value proc_name,
|
||||||
S48_CHECK_VALUE(sch_proc);
|
S48_CHECK_VALUE(sch_proc);
|
||||||
S48_CHECK_STRING(name);
|
S48_CHECK_STRING(name);
|
||||||
|
|
||||||
gc_roots_marker = s48_set_gc_roots_baseB();
|
gc_roots_marker = s48_set_gc_roots_baseB(&gc_marker_temp);
|
||||||
|
gc_marker = gc_marker_temp;
|
||||||
|
|
||||||
/* fprintf(stderr, "[external_call at depth %d]\n", depth); */
|
/* fprintf(stderr, "[external_call at depth %d]\n", depth); */
|
||||||
|
|
||||||
|
|
@ -209,7 +212,7 @@ s48_external_call(s48_value sch_proc, s48_value proc_name,
|
||||||
|
|
||||||
/* Raise an exception if the user neglected to pop off some gc roots. */
|
/* Raise an exception if the user neglected to pop off some gc roots. */
|
||||||
|
|
||||||
if (! s48_release_gc_roots_baseB((char *)gc_roots_marker)) {
|
if (! s48_release_gc_roots_baseB((char *)gc_roots_marker, (char *)gc_marker)) {
|
||||||
s48_raise_scheme_exception(S48_EXCEPTION_GC_PROTECTION_MISMATCH, 0);
|
s48_raise_scheme_exception(S48_EXCEPTION_GC_PROTECTION_MISMATCH, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +245,7 @@ s48_external_call(s48_value sch_proc, s48_value proc_name,
|
||||||
depth,
|
depth,
|
||||||
callback_depth());
|
callback_depth());
|
||||||
fprintf(stderr, "[throw unrolling to %ld]\n", gc_roots_marker); */
|
fprintf(stderr, "[throw unrolling to %ld]\n", gc_roots_marker); */
|
||||||
s48_release_gc_roots_baseB((char *)gc_roots_marker);
|
s48_release_gc_roots_baseB((char *)gc_roots_marker, (char *)gc_marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check to see if a thread is waiting to return to the next block down. */
|
/* Check to see if a thread is waiting to return to the next block down. */
|
||||||
|
|
@ -301,7 +304,7 @@ s48_call_scheme(s48_value proc, long nargs, ...)
|
||||||
|
|
||||||
/* It would be nice to push a list of the arguments, but we have no way
|
/* It would be nice to push a list of the arguments, but we have no way
|
||||||
of preserving them across a cons. */
|
of preserving them across a cons. */
|
||||||
if (nargs < 0 || 10 < nargs) { /* DO NOT INCREASE THIS NUMBER */
|
if (nargs < 0 || 12 < nargs) { /* DO NOT INCREASE THIS NUMBER */
|
||||||
s48_value sch_nargs = s48_enter_integer(nargs); /* `proc' is protected */
|
s48_value sch_nargs = s48_enter_integer(nargs); /* `proc' is protected */
|
||||||
s48_raise_scheme_exception(S48_EXCEPTION_TOO_MANY_ARGUMENTS_IN_CALLBACK,
|
s48_raise_scheme_exception(S48_EXCEPTION_TOO_MANY_ARGUMENTS_IN_CALLBACK,
|
||||||
2, proc, sch_nargs);
|
2, proc, sch_nargs);
|
||||||
|
|
@ -473,12 +476,12 @@ s48_raise_scheme_exception(long why, long nargs, ...)
|
||||||
/* Specific exceptions */
|
/* Specific exceptions */
|
||||||
|
|
||||||
void
|
void
|
||||||
s48_raise_argtype_error(s48_value value) {
|
s48_raise_argument_type_error(s48_value value) {
|
||||||
s48_raise_scheme_exception(S48_EXCEPTION_WRONG_TYPE_ARGUMENT, 1, value);
|
s48_raise_scheme_exception(S48_EXCEPTION_WRONG_TYPE_ARGUMENT, 1, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
s48_raise_argnumber_error(s48_value value, s48_value min, s48_value max) {
|
s48_raise_argument_number_error(s48_value value, s48_value min, s48_value max) {
|
||||||
s48_raise_scheme_exception(S48_EXCEPTION_WRONG_NUMBER_OF_ARGUMENTS,
|
s48_raise_scheme_exception(S48_EXCEPTION_WRONG_NUMBER_OF_ARGUMENTS,
|
||||||
3, value, min, max);
|
3, value, min, max);
|
||||||
}
|
}
|
||||||
|
|
@ -501,6 +504,69 @@ s48_raise_os_error(int the_errno) {
|
||||||
s48_enter_string(strerror(the_errno)));
|
s48_enter_string(strerror(the_errno)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_1(int the_errno, s48_value arg1) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 3,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_2(int the_errno, s48_value arg1, s48_value arg2) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 4,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1, arg2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_3(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 5,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_4(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 6,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1, arg2, arg3, arg4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_5(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 7,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1, arg2, arg3, arg4, arg5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_6(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5,
|
||||||
|
s48_value arg6) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 8,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1, arg2, arg3, arg4, arg5, arg6);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
s48_raise_os_error_7(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5,
|
||||||
|
s48_value arg6, s48_value arg7) {
|
||||||
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 9,
|
||||||
|
s48_enter_fixnum(the_errno),
|
||||||
|
s48_enter_string(strerror(the_errno)),
|
||||||
|
arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
s48_raise_string_os_error(char *reason) {
|
s48_raise_string_os_error(char *reason) {
|
||||||
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 1,
|
s48_raise_scheme_exception(S48_EXCEPTION_OS_ERROR, 1,
|
||||||
|
|
@ -529,7 +595,7 @@ long
|
||||||
s48_stob_length(s48_value thing, int type)
|
s48_stob_length(s48_value thing, int type)
|
||||||
{
|
{
|
||||||
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
||||||
s48_raise_argtype_error(thing);
|
s48_raise_argument_type_error(thing);
|
||||||
|
|
||||||
return S48_STOB_DESCRIPTOR_LENGTH(thing);
|
return S48_STOB_DESCRIPTOR_LENGTH(thing);
|
||||||
}
|
}
|
||||||
|
|
@ -538,7 +604,7 @@ long
|
||||||
s48_stob_byte_length(s48_value thing, int type)
|
s48_stob_byte_length(s48_value thing, int type)
|
||||||
{
|
{
|
||||||
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
||||||
s48_raise_argtype_error(thing);
|
s48_raise_argument_type_error(thing);
|
||||||
|
|
||||||
if (type == S48_STOBTYPE_STRING)
|
if (type == S48_STOBTYPE_STRING)
|
||||||
return S48_STOB_BYTE_LENGTH(thing) - 1;
|
return S48_STOB_BYTE_LENGTH(thing) - 1;
|
||||||
|
|
@ -552,7 +618,7 @@ s48_stob_ref(s48_value thing, int type, long offset)
|
||||||
long length;
|
long length;
|
||||||
|
|
||||||
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
||||||
s48_raise_argtype_error(thing);
|
s48_raise_argument_type_error(thing);
|
||||||
|
|
||||||
length = S48_STOB_DESCRIPTOR_LENGTH(thing);
|
length = S48_STOB_DESCRIPTOR_LENGTH(thing);
|
||||||
|
|
||||||
|
|
@ -572,7 +638,7 @@ s48_stob_set(s48_value thing, int type, long offset, s48_value value)
|
||||||
if (!(S48_STOB_P(thing) &&
|
if (!(S48_STOB_P(thing) &&
|
||||||
(S48_STOB_TYPE(thing) == type) &&
|
(S48_STOB_TYPE(thing) == type) &&
|
||||||
!S48_STOB_IMMUTABLEP(thing)))
|
!S48_STOB_IMMUTABLEP(thing)))
|
||||||
s48_raise_argtype_error(thing);
|
s48_raise_argument_type_error(thing);
|
||||||
|
|
||||||
length = S48_STOB_DESCRIPTOR_LENGTH(thing);
|
length = S48_STOB_DESCRIPTOR_LENGTH(thing);
|
||||||
|
|
||||||
|
|
@ -585,12 +651,12 @@ s48_stob_set(s48_value thing, int type, long offset, s48_value value)
|
||||||
}
|
}
|
||||||
|
|
||||||
char
|
char
|
||||||
s48_byte_ref(s48_value thing, int type, long offset)
|
s48_stob_byte_ref(s48_value thing, int type, long offset)
|
||||||
{
|
{
|
||||||
long length;
|
long length;
|
||||||
|
|
||||||
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
||||||
s48_raise_argtype_error(thing);
|
s48_raise_argument_type_error(thing);
|
||||||
|
|
||||||
length = (type == S48_STOBTYPE_STRING) ?
|
length = (type == S48_STOBTYPE_STRING) ?
|
||||||
S48_STOB_BYTE_LENGTH(thing) - 1 :
|
S48_STOB_BYTE_LENGTH(thing) - 1 :
|
||||||
|
|
@ -605,12 +671,12 @@ s48_byte_ref(s48_value thing, int type, long offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
s48_byte_set(s48_value thing, int type, long offset, char value)
|
s48_stob_byte_set(s48_value thing, int type, long offset, char value)
|
||||||
{
|
{
|
||||||
long length;
|
long length;
|
||||||
|
|
||||||
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
if (!(S48_STOB_P(thing) && (S48_STOB_TYPE(thing) == type)))
|
||||||
s48_raise_argtype_error(thing);
|
s48_raise_argument_type_error(thing);
|
||||||
|
|
||||||
length = (type == S48_STOBTYPE_STRING) ?
|
length = (type == S48_STOBTYPE_STRING) ?
|
||||||
S48_STOB_BYTE_LENGTH(thing) - 1 :
|
S48_STOB_BYTE_LENGTH(thing) - 1 :
|
||||||
|
|
@ -645,7 +711,7 @@ s48_value
|
||||||
s48_enter_fixnum(long value)
|
s48_enter_fixnum(long value)
|
||||||
{
|
{
|
||||||
if (value < S48_MIN_FIXNUM_VALUE || S48_MAX_FIXNUM_VALUE < value)
|
if (value < S48_MIN_FIXNUM_VALUE || S48_MAX_FIXNUM_VALUE < value)
|
||||||
s48_raise_argtype_error(s48_enter_integer(value));
|
s48_raise_argument_type_error(s48_enter_integer(value));
|
||||||
|
|
||||||
return S48_UNSAFE_ENTER_FIXNUM(value);
|
return S48_UNSAFE_ENTER_FIXNUM(value);
|
||||||
}
|
}
|
||||||
|
|
@ -654,7 +720,7 @@ long
|
||||||
s48_extract_fixnum(s48_value value)
|
s48_extract_fixnum(s48_value value)
|
||||||
{
|
{
|
||||||
if (! S48_FIXNUM_P(value))
|
if (! S48_FIXNUM_P(value))
|
||||||
s48_raise_argtype_error(value);
|
s48_raise_argument_type_error(value);
|
||||||
|
|
||||||
return S48_UNSAFE_EXTRACT_FIXNUM(value);
|
return S48_UNSAFE_EXTRACT_FIXNUM(value);
|
||||||
}
|
}
|
||||||
|
|
@ -689,6 +755,22 @@ s48_enter_integer(long value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_enter_unsigned_integer(unsigned long value)
|
||||||
|
{
|
||||||
|
if (value <= S48_MAX_FIXNUM_VALUE)
|
||||||
|
return S48_UNSAFE_ENTER_FIXNUM(value);
|
||||||
|
else {
|
||||||
|
S48_SHARED_BINDING_CHECK(long_to_bignum_binding);
|
||||||
|
|
||||||
|
return s48_call_scheme(S48_SHARED_BINDING_REF(long_to_bignum_binding),
|
||||||
|
3,
|
||||||
|
S48_FALSE, /* this is ok */
|
||||||
|
S48_UNSAFE_ENTER_FIXNUM(value >> 16),
|
||||||
|
S48_UNSAFE_ENTER_FIXNUM(value & 0xFFFF));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we have a fixnum we just extract it. Bignums require a call back into
|
* If we have a fixnum we just extract it. Bignums require a call back into
|
||||||
* Scheme 48. (BIGNUM-TO-LONG n) returns a vector containing the sign and the
|
* Scheme 48. (BIGNUM-TO-LONG n) returns a vector containing the sign and the
|
||||||
|
|
@ -717,7 +799,7 @@ s48_extract_integer(s48_value value)
|
||||||
S48_GC_UNPROTECT();
|
S48_GC_UNPROTECT();
|
||||||
|
|
||||||
if (stuff == S48_FALSE)
|
if (stuff == S48_FALSE)
|
||||||
s48_raise_argtype_error(value);
|
s48_raise_argument_type_error(value);
|
||||||
|
|
||||||
/* The first VECTOR_REF does the type checking for the rest. */
|
/* The first VECTOR_REF does the type checking for the rest. */
|
||||||
{
|
{
|
||||||
|
|
@ -728,7 +810,7 @@ s48_extract_integer(s48_value value)
|
||||||
|
|
||||||
if ((! S48_FIXNUM_P(boxed_high)) ||
|
if ((! S48_FIXNUM_P(boxed_high)) ||
|
||||||
high > (pos_p ? 0x7FFF : 0x8000))
|
high > (pos_p ? 0x7FFF : 0x8000))
|
||||||
s48_raise_argtype_error(value);
|
s48_raise_argument_type_error(value);
|
||||||
|
|
||||||
{
|
{
|
||||||
long magnitude = ((- high) << 16) - low;
|
long magnitude = ((- high) << 16) - low;
|
||||||
|
|
@ -738,6 +820,49 @@ s48_extract_integer(s48_value value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
s48_extract_unsigned_integer(s48_value value)
|
||||||
|
{
|
||||||
|
long temp;
|
||||||
|
if (S48_FIXNUM_P(value)){
|
||||||
|
temp = S48_UNSAFE_EXTRACT_FIXNUM(value);
|
||||||
|
if (temp < 0)
|
||||||
|
s48_raise_argument_type_error(value);
|
||||||
|
else return (unsigned long) temp;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s48_value stuff;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(value);
|
||||||
|
|
||||||
|
S48_SHARED_BINDING_CHECK(bignum_to_long_binding);
|
||||||
|
|
||||||
|
stuff = s48_call_scheme(S48_SHARED_BINDING_REF(bignum_to_long_binding),
|
||||||
|
1,
|
||||||
|
value);
|
||||||
|
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
|
||||||
|
if (stuff == S48_FALSE)
|
||||||
|
s48_raise_argument_type_error(value);
|
||||||
|
|
||||||
|
/* The first VECTOR_REF does the type checking for the rest. */
|
||||||
|
{
|
||||||
|
long low = S48_UNSAFE_EXTRACT_FIXNUM(S48_VECTOR_REF(stuff, 2));
|
||||||
|
s48_value boxed_high = S48_UNSAFE_VECTOR_REF(stuff, 1);
|
||||||
|
long high = S48_UNSAFE_EXTRACT_FIXNUM(boxed_high);
|
||||||
|
int pos_p = S48_EXTRACT_BOOLEAN(S48_UNSAFE_VECTOR_REF(stuff, 0));
|
||||||
|
|
||||||
|
if ((!pos_p) ||
|
||||||
|
(! S48_FIXNUM_P(boxed_high)) ||
|
||||||
|
(high > 0xFFFF))
|
||||||
|
s48_raise_argument_type_error(value);
|
||||||
|
else return ((((unsigned long) high) << 16) + low);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Doubles and characters are straightforward.
|
* Doubles and characters are straightforward.
|
||||||
*/
|
*/
|
||||||
|
|
@ -757,7 +882,7 @@ double
|
||||||
s48_extract_double(s48_value s48_double)
|
s48_extract_double(s48_value s48_double)
|
||||||
{
|
{
|
||||||
if (! S48_DOUBLE_P(s48_double))
|
if (! S48_DOUBLE_P(s48_double))
|
||||||
s48_raise_argtype_error(s48_double);
|
s48_raise_argument_type_error(s48_double);
|
||||||
|
|
||||||
return S48_UNSAFE_EXTRACT_DOUBLE(s48_double);
|
return S48_UNSAFE_EXTRACT_DOUBLE(s48_double);
|
||||||
}
|
}
|
||||||
|
|
@ -777,7 +902,7 @@ unsigned char
|
||||||
s48_extract_char(s48_value a_char)
|
s48_extract_char(s48_value a_char)
|
||||||
{
|
{
|
||||||
if (! S48_CHAR_P(a_char))
|
if (! S48_CHAR_P(a_char))
|
||||||
s48_raise_argtype_error(a_char);
|
s48_raise_argument_type_error(a_char);
|
||||||
|
|
||||||
return S48_UNSAFE_EXTRACT_CHAR(a_char);
|
return S48_UNSAFE_EXTRACT_CHAR(a_char);
|
||||||
}
|
}
|
||||||
|
|
@ -812,6 +937,164 @@ s48_cons(s48_value v1, s48_value v2)
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_1(s48_value v1)
|
||||||
|
{
|
||||||
|
return (s48_cons (v1, S48_NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_2(s48_value v1, s48_value v2)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_1 (v2);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_3(s48_value v1, s48_value v2, s48_value v3)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_2 (v2, v3);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_4(s48_value v1, s48_value v2, s48_value v3, s48_value v4)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_3 (v2, v3, v4);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_5(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_4 (v2, v3, v4, v5);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_6(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_5 (v2, v3, v4, v5, v6);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_7(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6, s48_value v7)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_6 (v2, v3, v4, v5, v6, v7);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_8(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6, s48_value v7, s48_value v8)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_7 (v2, v3, v4, v5, v6, v7, v8);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_9(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6, s48_value v7, s48_value v8, s48_value v9)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_8 (v2, v3, v4, v5, v6, v7, v8, v9);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_10(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6, s48_value v7, s48_value v8, s48_value v9, s48_value v10)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_9 (v2, v3, v4, v5, v6, v7, v8, v9, v10);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_11(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6, s48_value v7, s48_value v8, s48_value v9, s48_value v10,
|
||||||
|
s48_value v11)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_10 (v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_list_12(s48_value v1, s48_value v2, s48_value v3, s48_value v4, s48_value v5,
|
||||||
|
s48_value v6, s48_value v7, s48_value v8, s48_value v9, s48_value v10,
|
||||||
|
s48_value v11, s48_value v12)
|
||||||
|
{
|
||||||
|
s48_value list = S48_UNSPECIFIC;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(v1);
|
||||||
|
list = s48_list_11 (v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
|
||||||
|
list = s48_cons (v1, list);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
s48_value
|
s48_value
|
||||||
s48_make_weak_pointer(s48_value value)
|
s48_make_weak_pointer(s48_value value)
|
||||||
{
|
{
|
||||||
|
|
@ -831,7 +1114,7 @@ s48_value
|
||||||
s48_enter_substring(char *str, int length)
|
s48_enter_substring(char *str, int length)
|
||||||
{
|
{
|
||||||
s48_value obj = s48_allocate_stob(S48_STOBTYPE_STRING, length + 1);
|
s48_value obj = s48_allocate_stob(S48_STOBTYPE_STRING, length + 1);
|
||||||
strncpy(S48_UNSAFE_EXTRACT_STRING(obj), str, length);
|
memcpy(S48_UNSAFE_EXTRACT_STRING(obj), str, length);
|
||||||
*(S48_UNSAFE_EXTRACT_STRING(obj) + length) = '\0';
|
*(S48_UNSAFE_EXTRACT_STRING(obj) + length) = '\0';
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
@ -878,9 +1161,31 @@ s48_make_vector(int length, s48_value init)
|
||||||
}
|
}
|
||||||
|
|
||||||
s48_value
|
s48_value
|
||||||
s48_make_byte_vector(int length)
|
s48_enter_byte_vector(char *bvec, int length)
|
||||||
{
|
{
|
||||||
return s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, length);
|
s48_value obj = s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, length);
|
||||||
|
memcpy(S48_UNSAFE_EXTRACT_BYTE_VECTOR(obj), bvec, length);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
s48_extract_byte_vector(s48_value bvec)
|
||||||
|
{
|
||||||
|
S48_CHECK_BYTE_VECTOR(bvec);
|
||||||
|
|
||||||
|
return S48_UNSAFE_EXTRACT_BYTE_VECTOR(bvec);
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_make_byte_vector(int length, int init)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
s48_value obj = s48_allocate_stob(S48_STOBTYPE_BYTE_VECTOR, length);
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
S48_BYTE_VECTOR_SET(obj, i, init);
|
||||||
|
|
||||||
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
s48_value
|
s48_value
|
||||||
|
|
@ -929,7 +1234,7 @@ s48_check_record_type(s48_value record, s48_value type_binding)
|
||||||
if ((! S48_RECORD_P(record)) ||
|
if ((! S48_RECORD_P(record)) ||
|
||||||
(S48_UNSAFE_SHARED_BINDING_REF(type_binding) !=
|
(S48_UNSAFE_SHARED_BINDING_REF(type_binding) !=
|
||||||
S48_UNSAFE_RECORD_REF(record, -1)))
|
S48_UNSAFE_RECORD_REF(record, -1)))
|
||||||
s48_raise_argtype_error(record);
|
s48_raise_argument_type_error(record);
|
||||||
}
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
|
|
@ -945,3 +1250,54 @@ s48_length(s48_value list)
|
||||||
return S48_UNSAFE_ENTER_FIXNUM(i);
|
return S48_UNSAFE_ENTER_FIXNUM(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Support for libscsh.a: add external initializers without the Makefile
|
||||||
|
**
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct simple_list{
|
||||||
|
void (*init)(); /* pointer to init-function */
|
||||||
|
struct simple_list* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct simple_list* additional_inits = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is part of EXTERNAL_INITIALIZERS in the scsh Makefile.
|
||||||
|
* It calls the init-functions in additional_inits.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void s48_init_additional_inits(){
|
||||||
|
|
||||||
|
struct simple_list* ptr = additional_inits;
|
||||||
|
struct simple_list* free_me;
|
||||||
|
|
||||||
|
while (ptr != 0){
|
||||||
|
ptr->init();
|
||||||
|
free_me = ptr;
|
||||||
|
ptr = ptr->next;
|
||||||
|
free (free_me);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Actual API function: argument is an init-function. You have to
|
||||||
|
* ensure, that all s48_add_external_inits are called before you call
|
||||||
|
* s48_main.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int s48_add_external_init(void (*init)()){
|
||||||
|
|
||||||
|
struct simple_list *new_list;
|
||||||
|
|
||||||
|
new_list = (struct simple_list *) malloc(sizeof (struct simple_list));
|
||||||
|
|
||||||
|
if (new_list == 0) return 0;
|
||||||
|
|
||||||
|
new_list->init = init;
|
||||||
|
new_list->next = additional_inits;
|
||||||
|
additional_inits = new_list;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* This include file is for systems which do not have dynamic loading.
|
* This include file is for systems which do not have dynamic loading.
|
||||||
*/
|
*/
|
||||||
#if ! defined(HAVE_DLOPEN)
|
|
||||||
|
|
||||||
extern void *dlopen(char *filename, int flags);
|
extern void *dlopen(char *filename, int flags);
|
||||||
extern char *dlerror(void);
|
extern char *dlerror(void);
|
||||||
extern void *dlsym(void *lib, char *name);
|
extern void *dlsym(void *lib, char *name);
|
||||||
extern int dlclose(void *lib);
|
extern int dlclose(void *lib);
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,18 @@
|
||||||
* (whose name is pointed to by object_file).
|
* (whose name is pointed to by object_file).
|
||||||
*/
|
*/
|
||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
|
#include <stdlib.h>
|
||||||
#include <nlist.h>
|
#include <nlist.h>
|
||||||
|
|
||||||
#ifdef USCORE
|
#ifdef USCORE
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_DLOPEN)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#else
|
||||||
|
#include "../fake/dlfcn.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if ! defined(NLIST_HAS_N_NAME)
|
#if ! defined(NLIST_HAS_N_NAME)
|
||||||
#define n_name n_un.n_name
|
#define n_name n_un.n_name
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -64,7 +70,7 @@ dlsym(void *lib, char *name)
|
||||||
lasterror = "Bad library pointer passed to dlsym()";
|
lasterror = "Bad library pointer passed to dlsym()";
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
if (object_file == NULL) {
|
if (s48_object_file == NULL) {
|
||||||
lasterror = "I don't know the name of my executable";
|
lasterror = "I don't know the name of my executable";
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +93,7 @@ dlsym(void *lib, char *name)
|
||||||
names[0].n_value = 0; /* for Linux */
|
names[0].n_value = 0; /* for Linux */
|
||||||
names[0].n_type = 0; /* for Linux */
|
names[0].n_type = 0; /* for Linux */
|
||||||
names[1].n_name = NULL;
|
names[1].n_name = NULL;
|
||||||
status = nlist(object_file, names);
|
status = nlist(s48_object_file, names);
|
||||||
#ifdef USCORE
|
#ifdef USCORE
|
||||||
if (tmp != buff)
|
if (tmp != buff)
|
||||||
free((void *)tmp);
|
free((void *)tmp);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* This is a fake version of the dynamic loading library for machines
|
||||||
|
* which don't have it, and don't even have an nlist.
|
||||||
|
* We fake it so that everything fails.
|
||||||
|
*/
|
||||||
|
#include "sysdep.h"
|
||||||
|
|
||||||
|
|
||||||
|
static char *lasterror;
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
dlerror(void)
|
||||||
|
{
|
||||||
|
char *res;
|
||||||
|
|
||||||
|
res = lasterror;
|
||||||
|
lasterror = NULL;
|
||||||
|
return (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
dlopen(char *name, int flags)
|
||||||
|
{
|
||||||
|
lasterror = "Dynamic loading not supported on this machine";
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
dlclose(void *lib)
|
||||||
|
{
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *
|
||||||
|
dlsym(void *lib, char *name)
|
||||||
|
{
|
||||||
|
lasterror = "Dynamic loading not supported on this machine";
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
/*
|
||||||
|
* If we don't have sigaction, we fake it using signal.
|
||||||
|
*/
|
||||||
|
#if ! defined(HAVE_SIGACTION)
|
||||||
|
|
||||||
|
struct sigaction {
|
||||||
|
void (*sa_handler)();
|
||||||
|
int sa_mask;
|
||||||
|
int sa_flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define sigaction(sig, act, oact) signal((sig), (act)->sa_handler)
|
||||||
|
#define sigemptyset(ign) 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
/*
|
||||||
|
* If the system doesn't have a strerror procedure, we provide our own.
|
||||||
|
* Note, this depends on sys_nerr and sys_errlist being provided.
|
||||||
|
* If your system doesn't provide that either, you can replace this
|
||||||
|
* procedure with one that always returns "Unknown error".
|
||||||
|
*/
|
||||||
|
#include "sysdep.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern int sys_nerr;
|
||||||
|
extern char *sys_errlist[];
|
||||||
|
|
||||||
|
|
||||||
|
char *
|
||||||
|
strerror(int errnum)
|
||||||
|
{
|
||||||
|
if ((0 <= errnum)
|
||||||
|
&& (errnum < sys_nerr))
|
||||||
|
return (sys_errlist[errnum]);
|
||||||
|
else
|
||||||
|
return ("Unknown error");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* If we don't have strerror(), we fake it using sys_nerr and sys_errlist.
|
||||||
|
*/
|
||||||
|
#if ! defined(HAVE_STRERROR)
|
||||||
|
|
||||||
|
extern char *strerror(int errnum);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*
|
||||||
|
* If we have a sys/select.h, then include it.
|
||||||
|
*/
|
||||||
|
#if defined(HAVE_SYS_SELECT_H)
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -7,6 +7,8 @@ extern int ps_open_fd(char *in_filename, bool is_input, long *status);
|
||||||
|
|
||||||
extern int ps_close_fd(long fd_as_long);
|
extern int ps_close_fd(long fd_as_long);
|
||||||
|
|
||||||
|
extern bool ps_check_fd(long fd_as_long, bool is_read, long *status);
|
||||||
|
|
||||||
extern long ps_read_fd(long fd_as_long, char *buf_as_long, long max, bool waitp,
|
extern long ps_read_fd(long fd_as_long, char *buf_as_long, long max, bool waitp,
|
||||||
bool *eofp, bool *pending, long *status);
|
bool *eofp, bool *pending, long *status);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees.
|
||||||
|
See file COPYING. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "scheme48vm.h"
|
||||||
|
#include "scheme48heap.h"
|
||||||
|
|
||||||
|
extern void s48_sysdep_init(void);
|
||||||
|
extern void s48_initialize_external_modules(void);
|
||||||
|
|
||||||
|
/* JMG: s48_object_file is obsolete according to s48 manual */
|
||||||
|
char *s48_object_file; /* specified via a command line argument */
|
||||||
|
|
||||||
|
char *s48_reloc_file; /* dynamic loading will set this */
|
||||||
|
|
||||||
|
char *prog_name;
|
||||||
|
|
||||||
|
void *heap, *stack;
|
||||||
|
|
||||||
|
int s48_main (long heap_size, long stack_size,
|
||||||
|
char *image_name, int argc, char** argv)
|
||||||
|
{
|
||||||
|
int ret = internal_s48_main(heap_size, stack_size, "libscsh", "libscsh",
|
||||||
|
image_name, argc, argv);
|
||||||
|
free(heap);
|
||||||
|
free(stack);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
internal_s48_main(long heap_size, long stack_size, char * _prog_name,
|
||||||
|
char* object_file, char *image_name, int argc, char** argv)
|
||||||
|
{
|
||||||
|
long return_value;
|
||||||
|
long required_heap_size;
|
||||||
|
int warn_undefined_imported_bindings_p = 1;
|
||||||
|
|
||||||
|
#if defined(STATIC_AREAS)
|
||||||
|
extern long static_entry;
|
||||||
|
extern long static_symbol_table;
|
||||||
|
extern long static_imported_binding_table, static_exported_binding_table;
|
||||||
|
extern long p_count, *p_areas[], p_sizes[];
|
||||||
|
extern long i_count, *i_areas[], i_sizes[];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
prog_name = _prog_name;
|
||||||
|
|
||||||
|
s48_object_file = object_file;
|
||||||
|
s48_reloc_file = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
s48_sysdep_init();
|
||||||
|
s48_heap_init();
|
||||||
|
s48_init();
|
||||||
|
|
||||||
|
if (image_name == NULL)
|
||||||
|
required_heap_size = 0;
|
||||||
|
else {
|
||||||
|
/* check_image_header returns number of bytes; required_heap_size
|
||||||
|
is number of cells. */
|
||||||
|
required_heap_size =
|
||||||
|
s48_check_image_header((unsigned char *)image_name) >> 2;
|
||||||
|
if (-1 == required_heap_size) {
|
||||||
|
fprintf(stderr, "Image file \"%s\" is unusable.\n", image_name);
|
||||||
|
return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* two semi-spaces, plus we want some room to maneuver */
|
||||||
|
if (heap_size < 4 * required_heap_size) {
|
||||||
|
fprintf(stderr, "heap size %ld is too small, using %ld\n",
|
||||||
|
heap_size, 4 * required_heap_size);
|
||||||
|
heap_size = 4 * required_heap_size; }
|
||||||
|
|
||||||
|
heap = (void *) malloc(heap_size * sizeof(long));
|
||||||
|
stack = (void *) malloc(stack_size * sizeof(long));
|
||||||
|
|
||||||
|
if (!heap || !stack) {
|
||||||
|
fprintf(stderr, "system is out of memory\n");
|
||||||
|
return 1; }
|
||||||
|
|
||||||
|
s48_initialize_heap((long)heap, heap_size);
|
||||||
|
|
||||||
|
#if defined(STATIC_AREAS)
|
||||||
|
if (image_name == NULL) {
|
||||||
|
s48_register_static_areas(p_count, p_areas, p_sizes,
|
||||||
|
i_count, i_areas, i_sizes);
|
||||||
|
s48_set_image_valuesB(static_entry,
|
||||||
|
static_symbol_table,
|
||||||
|
static_imported_binding_table,
|
||||||
|
static_exported_binding_table);
|
||||||
|
} else if (s48_read_image() == -1) {
|
||||||
|
fprintf(stderr, "Image file \"%s\" is unusable.\n", image_name);
|
||||||
|
return 1; }
|
||||||
|
#else
|
||||||
|
if (s48_read_image() == -1) {
|
||||||
|
fprintf(stderr, "Image file \"%s\" is unusable.\n", image_name);
|
||||||
|
return 1; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s48_initialize_vm(stack, stack_size);
|
||||||
|
|
||||||
|
s48_initialize_external_modules();
|
||||||
|
|
||||||
|
if (warn_undefined_imported_bindings_p)
|
||||||
|
s48_warn_about_undefined_imported_bindings();
|
||||||
|
|
||||||
|
return_value = s48_call_startup_procedure(argv, argc);
|
||||||
|
|
||||||
|
if (s48_reloc_file != NULL)
|
||||||
|
if (0 != unlink(s48_reloc_file))
|
||||||
|
fprintf(stderr, "unable to delete file %s\n", s48_reloc_file);
|
||||||
|
|
||||||
|
return(return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
extern FILE *ps_open_input_file(char *, long *);
|
||||||
|
extern FILE *ps_open_output_file(char *, long *);
|
||||||
|
extern long ps_close(FILE *);
|
||||||
|
extern char ps_read_char(FILE *, char *, long *, char);
|
||||||
|
extern long ps_read_integer(FILE *, char *, long *);
|
||||||
|
extern long ps_write_char(char, FILE *);
|
||||||
|
extern long ps_write_integer(long, FILE *);
|
||||||
|
extern long ps_write_string(char *, FILE *);
|
||||||
|
extern long ps_read_block(FILE *, char *, long, char *, long *);
|
||||||
|
extern long ps_write_block(FILE *, char *, long);
|
||||||
|
extern char *ps_error_string(long);
|
||||||
|
extern void ps_error(char *, long count, ...);
|
||||||
158
c/main.c
158
c/main.c
|
|
@ -4,12 +4,13 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "scheme48vm.h"
|
|
||||||
#include "scheme48heap.h"
|
|
||||||
|
|
||||||
|
/* I bumped this up from 1.5 Mcell because the debugging info put us over
|
||||||
|
** the top. -Olin
|
||||||
|
*/
|
||||||
#if !defined(DEFAULT_HEAP_SIZE)
|
#if !defined(DEFAULT_HEAP_SIZE)
|
||||||
/* 1.5 megacell = 6 megabytes (3 meg per semispace) */
|
/* 5 megacell = 20 megabytes (10 meg per semispace) */
|
||||||
#define DEFAULT_HEAP_SIZE 1500000L
|
#define DEFAULT_HEAP_SIZE 5000000L
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(DEFAULT_STACK_SIZE)
|
#if !defined(DEFAULT_STACK_SIZE)
|
||||||
|
|
@ -28,24 +29,29 @@
|
||||||
|
|
||||||
#endif /* STATIC_AREAS */
|
#endif /* STATIC_AREAS */
|
||||||
|
|
||||||
extern void s48_sysdep_init(void);
|
|
||||||
extern void s48_initialize_external_modules(void);
|
|
||||||
|
|
||||||
char *s48_object_file; /* specified via a command line argument */
|
|
||||||
char *s48_reloc_file; /* dynamic loading will set this */
|
char ** process_args(char **argv,
|
||||||
|
long *heap_size,
|
||||||
|
long *stack_size,
|
||||||
|
char **object_file,
|
||||||
|
char **image_name);
|
||||||
|
|
||||||
|
extern int
|
||||||
|
internal_s48_main(long heap_size, long stack_size,
|
||||||
|
char* prog_name, char* object_file, char* image_name,
|
||||||
|
int argc, char** argv);
|
||||||
|
|
||||||
int
|
int
|
||||||
main(argc, argv)
|
main(argc, argv)
|
||||||
int argc; char **argv;
|
int argc; char **argv;
|
||||||
{
|
{
|
||||||
|
char **argp; /* JMG */
|
||||||
char *image_name = DEFAULT_IMAGE_NAME;
|
char *image_name = DEFAULT_IMAGE_NAME;
|
||||||
long heap_size = DEFAULT_HEAP_SIZE; /* in numbers of cells */
|
long heap_size = DEFAULT_HEAP_SIZE; /* in numbers of cells */
|
||||||
long stack_size = DEFAULT_STACK_SIZE; /* in numbers of cells */
|
long stack_size = DEFAULT_STACK_SIZE; /* in numbers of cells */
|
||||||
int errors = 0;
|
char *object_file = NULL; /* specified via a command line argument */
|
||||||
long return_value;
|
char *prog_name;
|
||||||
void *heap, *stack;
|
|
||||||
long required_heap_size;
|
|
||||||
int warn_undefined_imported_bindings_p = 1;
|
|
||||||
|
|
||||||
#if defined(STATIC_AREAS)
|
#if defined(STATIC_AREAS)
|
||||||
extern long static_entry;
|
extern long static_entry;
|
||||||
|
|
@ -57,125 +63,11 @@ main(argc, argv)
|
||||||
|
|
||||||
long vm_argc = 0;
|
long vm_argc = 0;
|
||||||
char *me = *argv; /* Save program name. */
|
char *me = *argv; /* Save program name. */
|
||||||
|
prog_name = *argv++;
|
||||||
|
|
||||||
s48_object_file = s48_reloc_file = NULL;
|
argv=process_args(argv,
|
||||||
|
&heap_size, &stack_size,
|
||||||
argv++; argc--; /* Skip program name. */
|
&object_file, &image_name);
|
||||||
|
for(argc=0, argp=argv; *argp; argc++, argp++); /* Recompute argc. */
|
||||||
for (; argc > 0; argc--, argv++)
|
return internal_s48_main(heap_size, stack_size, prog_name, object_file, image_name, argc, argv);
|
||||||
if (argv[0][0] == '-')
|
|
||||||
switch (argv[0][1]) {
|
|
||||||
case 'h':
|
|
||||||
argc--; argv++;
|
|
||||||
if (argc == 0) { errors++; break; }
|
|
||||||
heap_size = atoi(*argv);
|
|
||||||
if (heap_size <= 0) errors++;
|
|
||||||
break;
|
|
||||||
case 's':
|
|
||||||
argc--; argv++;
|
|
||||||
if (argc == 0) { errors++; break; }
|
|
||||||
stack_size = atoi(*argv);
|
|
||||||
if (stack_size <= 0) errors++;
|
|
||||||
break;
|
|
||||||
case 'i':
|
|
||||||
argc--; argv++;
|
|
||||||
if (argc == 0) { errors++; break; }
|
|
||||||
image_name = *argv;
|
|
||||||
break;
|
|
||||||
case 'a':
|
|
||||||
argc--;
|
|
||||||
vm_argc = argc; /* remaining args are passed to the VM */
|
|
||||||
argc = 0;
|
|
||||||
break;
|
|
||||||
case 'o':
|
|
||||||
argc--; argv++;
|
|
||||||
if (argc == 0) { errors++; break; }
|
|
||||||
s48_object_file = *argv;
|
|
||||||
break;
|
|
||||||
case 'u':
|
|
||||||
argc--; argv++;
|
|
||||||
warn_undefined_imported_bindings_p = 0;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
fprintf(stderr, "Invalid argument: %s\n", *argv);
|
|
||||||
errors++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (argv[0][0] != '\0') {
|
|
||||||
fprintf(stderr, "Invalid argument: %s\n", *argv);
|
|
||||||
errors++; }
|
|
||||||
if (errors != 0) {
|
|
||||||
fprintf(stderr,
|
|
||||||
"Usage: %s [options] [-a arguments]\n\
|
|
||||||
Options: -h <total heap size in words>\n\
|
|
||||||
-s <stack buffer size in words>\n\
|
|
||||||
-i <image file name>\n\
|
|
||||||
-o <object file name>\n\
|
|
||||||
-u [don't warn on unbound external identifiers]",
|
|
||||||
me);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
s48_sysdep_init();
|
|
||||||
s48_heap_init();
|
|
||||||
s48_init();
|
|
||||||
|
|
||||||
if (image_name == NULL)
|
|
||||||
required_heap_size = 0;
|
|
||||||
else {
|
|
||||||
/* check_image_header returns number of bytes; required_heap_size
|
|
||||||
is number of cells. */
|
|
||||||
required_heap_size =
|
|
||||||
s48_check_image_header((unsigned char *)image_name) >> 2;
|
|
||||||
if (-1 == required_heap_size) {
|
|
||||||
fprintf(stderr, "Image file \"%s\" is unusable.\n", image_name);
|
|
||||||
return 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* two semi-spaces, plus we want some room to maneuver */
|
|
||||||
if (heap_size < 4 * required_heap_size) {
|
|
||||||
fprintf(stderr, "heap size %ld is too small, using %ld\n",
|
|
||||||
heap_size, 4 * required_heap_size);
|
|
||||||
heap_size = 4 * required_heap_size; }
|
|
||||||
|
|
||||||
heap = (void *) malloc(heap_size * sizeof(long));
|
|
||||||
stack = (void *) malloc(stack_size * sizeof(long));
|
|
||||||
|
|
||||||
if (!heap || !stack) {
|
|
||||||
fprintf(stderr, "system is out of memory\n");
|
|
||||||
return 1; }
|
|
||||||
|
|
||||||
s48_initialize_heap((long)heap, heap_size);
|
|
||||||
|
|
||||||
#if defined(STATIC_AREAS)
|
|
||||||
if (image_name == NULL) {
|
|
||||||
s48_register_static_areas(p_count, p_areas, p_sizes,
|
|
||||||
i_count, i_areas, i_sizes);
|
|
||||||
s48_set_image_valuesB(static_entry,
|
|
||||||
static_symbol_table,
|
|
||||||
static_imported_binding_table,
|
|
||||||
static_exported_binding_table);
|
|
||||||
} else if (s48_read_image() == -1) {
|
|
||||||
fprintf(stderr, "Image file \"%s\" is unusable.\n", image_name);
|
|
||||||
return 1; }
|
|
||||||
#else
|
|
||||||
if (s48_read_image() == -1) {
|
|
||||||
fprintf(stderr, "Image file \"%s\" is unusable.\n", image_name);
|
|
||||||
return 1; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
s48_initialize_vm(stack, stack_size);
|
|
||||||
|
|
||||||
s48_initialize_external_modules();
|
|
||||||
|
|
||||||
if (warn_undefined_imported_bindings_p)
|
|
||||||
s48_warn_about_undefined_imported_bindings();
|
|
||||||
|
|
||||||
return_value = s48_call_startup_procedure(argv, vm_argc);
|
|
||||||
|
|
||||||
if (s48_reloc_file != NULL)
|
|
||||||
if (0 != unlink(s48_reloc_file))
|
|
||||||
fprintf(stderr, "unable to delete file %s\n", s48_reloc_file);
|
|
||||||
|
|
||||||
return(return_value);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
typedef long scheme_value;
|
||||||
|
|
||||||
|
#define FIXNUM_TAG 0
|
||||||
|
#define FIXNUMP(x) (((long)(x) & 3L) == FIXNUM_TAG)
|
||||||
|
#define IMMEDIATE_TAG 1
|
||||||
|
#define IMMEDIATEP(x) (((long)(x) & 3L) == IMMEDIATE_TAG)
|
||||||
|
#define HEADER_TAG 2
|
||||||
|
#define HEADERP(x) (((long)(x) & 3L) == HEADER_TAG)
|
||||||
|
#define STOB_TAG 3
|
||||||
|
#define STOBP(x) (((long)(x) & 3L) == STOB_TAG)
|
||||||
|
|
||||||
|
#define ENTER_FIXNUM(n) ((scheme_value)((n) << 2))
|
||||||
|
#define EXTRACT_FIXNUM(x) ((long)(x) >> 2)
|
||||||
|
|
||||||
|
#define MISC_IMMEDIATE(n) (scheme_value)(IMMEDIATE_TAG | ((n) << 2))
|
||||||
|
#define SCHFALSE MISC_IMMEDIATE(0)
|
||||||
|
#define SCHTRUE MISC_IMMEDIATE(1)
|
||||||
|
#define SCHCHAR MISC_IMMEDIATE(2)
|
||||||
|
#define SCHUNSPECIFIC MISC_IMMEDIATE(3)
|
||||||
|
#define SCHUNDEFINED MISC_IMMEDIATE(4)
|
||||||
|
#define SCHEOF MISC_IMMEDIATE(5)
|
||||||
|
#define SCHNULL MISC_IMMEDIATE(6)
|
||||||
|
#define UNDEFINED SCHUNDEFINED
|
||||||
|
#define UNSPECIFIC SCHUNSPECIFIC
|
||||||
|
|
||||||
|
#define ENTER_BOOLEAN(n) ((n) ? SCHTRUE : SCHFALSE)
|
||||||
|
#define EXTRACT_BOOLEAN(x) ((x) != SCHFALSE)
|
||||||
|
|
||||||
|
#define ENTER_CHAR(c) (SCHCHAR | ((c) << 8))
|
||||||
|
#define EXTRACT_CHAR(x) ((x) >> 8)
|
||||||
|
#define CHARP(x) ((((long) (x)) & 0xff) == SCHCHAR)
|
||||||
|
|
||||||
|
#define ADDRESS_AFTER_HEADER(x, type) ((type *)((x) - STOB_TAG))
|
||||||
|
#define STOB_REF(x, i) ((ADDRESS_AFTER_HEADER(x, long))[i])
|
||||||
|
#define STOB_TYPE(x) ((STOB_HEADER(x)>>2)&31)
|
||||||
|
#define STOB_HEADER(x) (STOB_REF((x),-1))
|
||||||
|
#define STOB_BLENGTH(x) (STOB_HEADER(x) >> 8)
|
||||||
|
#define STOB_LLENGTH(x) (STOB_HEADER(x) >> 10)
|
||||||
|
|
||||||
|
#define STOBTYPE_PAIR 0
|
||||||
|
#define PAIRP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_PAIR))
|
||||||
|
#define STOBTYPE_SYMBOL 1
|
||||||
|
#define SYMBOLP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_SYMBOL))
|
||||||
|
#define STOBTYPE_VECTOR 2
|
||||||
|
#define VECTORP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_VECTOR))
|
||||||
|
#define STOBTYPE_CLOSURE 3
|
||||||
|
#define CLOSUREP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_CLOSURE))
|
||||||
|
#define STOBTYPE_LOCATION 4
|
||||||
|
#define LOCATIONP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_LOCATION))
|
||||||
|
#define STOBTYPE_CHANNEL 5
|
||||||
|
#define CHANNELP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_CHANNEL))
|
||||||
|
#define STOBTYPE_PORT 6
|
||||||
|
#define PORTP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_PORT))
|
||||||
|
#define STOBTYPE_RATNUM 7
|
||||||
|
#define RATNUMP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_RATNUM))
|
||||||
|
#define STOBTYPE_RECORD 8
|
||||||
|
#define RECORDP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_RECORD))
|
||||||
|
#define STOBTYPE_CONTINUATION 9
|
||||||
|
#define CONTINUATIONP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_CONTINUATION))
|
||||||
|
#define STOBTYPE_EXTENDED_NUMBER 10
|
||||||
|
#define EXTENDED_NUMBERP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_EXTENDED_NUMBER))
|
||||||
|
#define STOBTYPE_TEMPLATE 11
|
||||||
|
#define TEMPLATEP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_TEMPLATE))
|
||||||
|
#define STOBTYPE_WEAK_POINTER 12
|
||||||
|
#define WEAK_POINTERP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_WEAK_POINTER))
|
||||||
|
#define STOBTYPE_SHARED_BINDING 13
|
||||||
|
#define SHARED_BINDINGP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_SHARED_BINDING))
|
||||||
|
#define STOBTYPE_UNUSED_D_HEADER1 14
|
||||||
|
#define UNUSED_D_HEADER1P(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_UNUSED_D_HEADER1))
|
||||||
|
#define STOBTYPE_UNUSED_D_HEADER2 15
|
||||||
|
#define UNUSED_D_HEADER2P(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_UNUSED_D_HEADER2))
|
||||||
|
#define STOBTYPE_STRING 16
|
||||||
|
#define STRINGP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_STRING))
|
||||||
|
#define STOBTYPE_CODE_VECTOR 17
|
||||||
|
#define CODE_VECTORP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_CODE_VECTOR))
|
||||||
|
#define STOBTYPE_DOUBLE 18
|
||||||
|
#define DOUBLEP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_DOUBLE))
|
||||||
|
#define STOBTYPE_BIGNUM 19
|
||||||
|
#define BIGNUMP(x) (STOBP(x) && (STOB_TYPE(x) == STOBTYPE_BIGNUM))
|
||||||
|
|
||||||
|
#define CAR(x) STOB_REF(x, 0)
|
||||||
|
#define CDR(x) STOB_REF(x, 1)
|
||||||
|
#define SYMBOL_TO_STRING(x) STOB_REF(x, 0)
|
||||||
|
#define LOCATION_ID(x) STOB_REF(x, 0)
|
||||||
|
#define CONTENTS(x) STOB_REF(x, 1)
|
||||||
|
#define CLOSURE_TEMPLATE(x) STOB_REF(x, 0)
|
||||||
|
#define CLOSURE_ENV(x) STOB_REF(x, 1)
|
||||||
|
#define WEAK_POINTER_REF(x) STOB_REF(x, 0)
|
||||||
|
#define SHARED_BINDING_NAME(x) STOB_REF(x, 0)
|
||||||
|
#define SHARED_BINDING_IS_IMPORTP(x) STOB_REF(x, 1)
|
||||||
|
#define SHARED_BINDING_REF(x) STOB_REF(x, 2)
|
||||||
|
#define PORT_HANDLER(x) STOB_REF(x, 0)
|
||||||
|
#define PORT_STATUS(x) STOB_REF(x, 1)
|
||||||
|
#define PORT_LOCK(x) STOB_REF(x, 2)
|
||||||
|
#define PORT_LOCKEDP(x) STOB_REF(x, 3)
|
||||||
|
#define PORT_DATA(x) STOB_REF(x, 4)
|
||||||
|
#define PORT_BUFFER(x) STOB_REF(x, 5)
|
||||||
|
#define PORT_INDEX(x) STOB_REF(x, 6)
|
||||||
|
#define PORT_LIMIT(x) STOB_REF(x, 7)
|
||||||
|
#define PORT_PENDING_EOFP(x) STOB_REF(x, 8)
|
||||||
|
#define CHANNEL_STATUS(x) STOB_REF(x, 0)
|
||||||
|
#define CHANNEL_ID(x) STOB_REF(x, 1)
|
||||||
|
#define CHANNEL_OS_INDEX(x) STOB_REF(x, 2)
|
||||||
|
|
||||||
|
#define VECTOR_LENGTH(x) STOB_LLENGTH(x)
|
||||||
|
#define VECTOR_REF(x, i) STOB_REF(x, i)
|
||||||
|
#define CODE_VECTOR_LENGTH(x) STOB_BLENGTH(x)
|
||||||
|
#define CODE_VECTOR_REF(x, i) (ADDRESS_AFTER_HEADER(x, unsigned char)[i])
|
||||||
|
#define STRING_LENGTH(x) (STOB_BLENGTH(x)-1)
|
||||||
|
#define STRING_REF(x, i) (ADDRESS_AFTER_HEADER(x, char)[i])
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
#include <errno.h>
|
||||||
|
#include "io.h"
|
||||||
|
|
||||||
|
#define PS_READ_CHAR(PORT,RESULT,EOFP,STATUS) \
|
||||||
|
{ \
|
||||||
|
FILE * TTport = PORT; \
|
||||||
|
int TTchar; \
|
||||||
|
if (EOF == (TTchar = getc(TTport))) \
|
||||||
|
RESULT = ps_read_char(TTport, &EOFP, &STATUS, 0==1);\
|
||||||
|
else { \
|
||||||
|
RESULT = TTchar; \
|
||||||
|
EOFP = 0; \
|
||||||
|
STATUS = 0; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PS_PEEK_CHAR(PORT,RESULT,EOFP,STATUS) \
|
||||||
|
{ \
|
||||||
|
FILE * TTport = PORT; \
|
||||||
|
int TTchar; \
|
||||||
|
if (EOF == (TTchar = getc(TTport))) \
|
||||||
|
RESULT = ps_read_char(TTport, &EOFP, &STATUS, 0==0);\
|
||||||
|
else { \
|
||||||
|
RESULT = TTchar; \
|
||||||
|
ungetc(RESULT, TTport); \
|
||||||
|
EOFP = 0; \
|
||||||
|
STATUS = 0; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PS_READ_INTEGER(PORT,RESULT,EOFP,STATUS) \
|
||||||
|
RESULT = ps_read_integer(PORT,&EOFP,&STATUS);
|
||||||
|
|
||||||
|
#define PS_WRITE_CHAR(CHAR,PORT,STATUS) \
|
||||||
|
{ \
|
||||||
|
FILE * TTport = PORT; \
|
||||||
|
char TTchar = CHAR; \
|
||||||
|
if (EOF == putc(TTchar,TTport)) \
|
||||||
|
STATUS = ps_write_char(TTchar,TTport); \
|
||||||
|
else { \
|
||||||
|
STATUS = 0; } \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* C shifts may not work if the amount is greater than the machine word size */
|
||||||
|
/* Patched by JAR 6/6/93 */
|
||||||
|
|
||||||
|
#define PS_SHIFT_RIGHT(X,Y,RESULT) \
|
||||||
|
{ \
|
||||||
|
long TTx = X, TTy = Y; \
|
||||||
|
RESULT = TTy >= 32 ? (TTx < 0 ? -1 : 0) : TTx >> TTy; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PS_SHIFT_LEFT(X,Y,RESULT) \
|
||||||
|
{ \
|
||||||
|
long TTy = Y; \
|
||||||
|
RESULT = TTy >= 32 ? 0 : X << TTy; \
|
||||||
|
}
|
||||||
|
|
||||||
|
extern long s48_return_value, s48_run_machine();
|
||||||
|
|
||||||
185
c/scheme48.h
185
c/scheme48.h
|
|
@ -13,8 +13,15 @@ typedef long s48_value;
|
||||||
|
|
||||||
#define NO_ERRORS 0 /* errno value */
|
#define NO_ERRORS 0 /* errno value */
|
||||||
|
|
||||||
|
extern int s48_main (long heap_size, long stack_size,
|
||||||
|
char *image_name, int argc, char** argv);
|
||||||
|
|
||||||
|
extern int s48_add_external_init(void (*init)());
|
||||||
|
|
||||||
/* Misc stuff */
|
/* Misc stuff */
|
||||||
|
|
||||||
|
#define S48_EQ_P(v1, v2) ((v1) == (v2))
|
||||||
|
/* Superceded name for the above definition, retained for compatibility. */
|
||||||
#define S48_EQ(v1, v2) ((v1) == (v2))
|
#define S48_EQ(v1, v2) ((v1) == (v2))
|
||||||
|
|
||||||
#define S48_MAX_FIXNUM_VALUE ((1 << 29) - 1)
|
#define S48_MAX_FIXNUM_VALUE ((1 << 29) - 1)
|
||||||
|
|
@ -39,15 +46,43 @@ extern s48_value s48_enter_fixnum(long);
|
||||||
extern long s48_extract_fixnum(s48_value);
|
extern long s48_extract_fixnum(s48_value);
|
||||||
extern s48_value s48_enter_integer(long);
|
extern s48_value s48_enter_integer(long);
|
||||||
extern long s48_extract_integer(s48_value);
|
extern long s48_extract_integer(s48_value);
|
||||||
|
extern s48_value s48_enter_unsigned_integer(unsigned long);
|
||||||
|
extern unsigned long s48_extract_unsigned_integer(s48_value);
|
||||||
extern s48_value s48_enter_double(double);
|
extern s48_value s48_enter_double(double);
|
||||||
extern double s48_extract_double(s48_value);
|
extern double s48_extract_double(s48_value);
|
||||||
extern s48_value s48_cons(s48_value, s48_value);
|
extern s48_value s48_cons(s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_1(s48_value);
|
||||||
|
extern s48_value s48_list_2(s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_3(s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_4(s48_value, s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_5(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value);
|
||||||
|
extern s48_value s48_list_6(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_7(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_8(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_9(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value);
|
||||||
|
extern s48_value s48_list_10(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_11(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_12(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value);
|
||||||
extern s48_value s48_enter_string(char *);
|
extern s48_value s48_enter_string(char *);
|
||||||
extern char * s48_extract_string(s48_value);
|
extern char * s48_extract_string(s48_value);
|
||||||
extern s48_value s48_enter_substring(char *, int);
|
extern s48_value s48_enter_substring(char *, int);
|
||||||
extern s48_value s48_make_string(int, char);
|
extern s48_value s48_make_string(int, char);
|
||||||
extern s48_value s48_make_vector(int, s48_value);
|
extern s48_value s48_make_vector(int, s48_value);
|
||||||
extern s48_value s48_make_byte_vector(int);
|
extern s48_value s48_enter_byte_vector(char *, int);
|
||||||
|
extern char * s48_extract_byte_vector(s48_value);
|
||||||
|
extern s48_value s48_make_byte_vector(int, int);
|
||||||
extern s48_value s48_make_record(s48_value);
|
extern s48_value s48_make_record(s48_value);
|
||||||
extern s48_value s48_make_weak_pointer(s48_value);
|
extern s48_value s48_make_weak_pointer(s48_value);
|
||||||
extern void s48_check_record_type(s48_value, s48_value);
|
extern void s48_check_record_type(s48_value, s48_value);
|
||||||
|
|
@ -64,7 +99,7 @@ extern s48_value s48_call_scheme(s48_value proc, long nargs, ...);
|
||||||
|
|
||||||
#define S48_EXPORT_FUNCTION(p) (s48_define_exported_binding(#p, s48_enter_pointer(p)))
|
#define S48_EXPORT_FUNCTION(p) (s48_define_exported_binding(#p, s48_enter_pointer(p)))
|
||||||
|
|
||||||
#define S48_MAKE_VALUE(type) (s48_make_byte_vector(sizeof(type)))
|
#define S48_MAKE_VALUE(type) (s48_make_byte_vector(sizeof(type),0))
|
||||||
extern void * s48_value_pointer(s48_value);
|
extern void * s48_value_pointer(s48_value);
|
||||||
|
|
||||||
#define S48_EXTRACT_VALUE_POINTER(x, type) ((type *) s48_value_pointer(x))
|
#define S48_EXTRACT_VALUE_POINTER(x, type) ((type *) s48_value_pointer(x))
|
||||||
|
|
@ -177,28 +212,46 @@ extern void * s48_value_pointer(s48_value);
|
||||||
/* Exceptions */
|
/* Exceptions */
|
||||||
|
|
||||||
extern void s48_raise_scheme_exception(long type, long nargs, ...);
|
extern void s48_raise_scheme_exception(long type, long nargs, ...);
|
||||||
extern void s48_raise_argtype_error(s48_value value);
|
extern void s48_raise_argument_type_error(s48_value value);
|
||||||
extern void s48_raise_argnumber_error(s48_value value,
|
extern void s48_raise_argument_number_error(s48_value value,
|
||||||
s48_value min, s48_value max);
|
s48_value min,
|
||||||
|
s48_value max);
|
||||||
extern void s48_raise_range_error(s48_value value,
|
extern void s48_raise_range_error(s48_value value,
|
||||||
s48_value min, s48_value max);
|
s48_value min, s48_value max);
|
||||||
extern void s48_raise_closed_channel_error();
|
extern void s48_raise_closed_channel_error();
|
||||||
extern void s48_raise_os_error(int the_errno);
|
extern void s48_raise_os_error(int the_errno);
|
||||||
|
extern void s48_raise_os_error_1(int the_errno, s48_value arg1);
|
||||||
|
extern void s48_raise_os_error_2(int the_errno, s48_value arg1, s48_value arg2);
|
||||||
|
extern void s48_raise_os_error_3(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3);
|
||||||
|
extern void s48_raise_os_error_4(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4);
|
||||||
|
extern void s48_raise_os_error_5(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5);
|
||||||
|
extern void s48_raise_os_error_6(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5,
|
||||||
|
s48_value arg6);
|
||||||
extern void s48_raise_string_os_error(char *reason);
|
extern void s48_raise_string_os_error(char *reason);
|
||||||
extern void s48_raise_out_of_memory_error();
|
extern void s48_raise_out_of_memory_error();
|
||||||
|
|
||||||
/* Type checking */
|
/* Type checking */
|
||||||
|
|
||||||
#define S48_CHECK_PAIR(v) do { if (!S48_PAIR_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_PAIR(v) do { if (!S48_PAIR_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_FIXNUM(v) do { if (!S48_FIXNUM_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_FIXNUM(v) do { if (!S48_FIXNUM_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_STRING(v) do { if (!S48_STRING_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_STRING(v) do { if (!S48_STRING_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_CHANNEL(v) do { if (!S48_CHANNEL_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_BYTE_VECTOR(v) do { if (!S48_BYTE_VECTOR_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_RECORD(v) do { if (!S48_RECORD_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_CHANNEL(v) do { if (!S48_CHANNEL_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_VALUE(v) do { if (!S48_BYTE_VECTOR_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_RECORD(v) do { if (!S48_RECORD_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_EXPORT_BINDING(v) do { if (!S48_EXPORT_BINDING_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_VALUE(v) do { if (!S48_BYTE_VECTOR_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
|
#define S48_CHECK_EXPORT_BINDING(v) do { if (!S48_EXPORT_BINDING_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
|
|
||||||
#define S48_VALUE_P(v) (S48_BYTE_VECTOR_P(v))
|
#define S48_VALUE_P(v) (S48_BYTE_VECTOR_P(v))
|
||||||
|
|
||||||
|
#define S48_TRUE_P(v) ((v) == S48_TRUE)
|
||||||
|
#define S48_FALSE_P(v) ((v) == S48_FALSE)
|
||||||
|
#define S48_EXTRACT_BOOLEAN(v) ((v) != S48_FALSE)
|
||||||
|
#define S48_ENTER_BOOLEAN(v) ((v) ? S48_TRUE : S48_FALSE)
|
||||||
|
|
||||||
extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
|
|
||||||
#define S48_SHARED_BINDING_CHECK(binding) \
|
#define S48_SHARED_BINDING_CHECK(binding) \
|
||||||
|
|
@ -207,6 +260,7 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
S48_SHARED_BINDING_NAME(binding)); \
|
S48_SHARED_BINDING_NAME(binding)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
||||||
#define S48_FIXNUM_TAG 0
|
#define S48_FIXNUM_TAG 0
|
||||||
#define S48_FIXNUM_P(x) (((long)(x) & 3L) == S48_FIXNUM_TAG)
|
#define S48_FIXNUM_P(x) (((long)(x) & 3L) == S48_FIXNUM_TAG)
|
||||||
#define S48_IMMEDIATE_TAG 1
|
#define S48_IMMEDIATE_TAG 1
|
||||||
|
|
@ -228,9 +282,6 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
#define S48_EOF (S48_MISC_IMMEDIATE(5))
|
#define S48_EOF (S48_MISC_IMMEDIATE(5))
|
||||||
#define S48_NULL (S48_MISC_IMMEDIATE(6))
|
#define S48_NULL (S48_MISC_IMMEDIATE(6))
|
||||||
|
|
||||||
#define S48_ENTER_BOOLEAN(n) ((n) ? S48_TRUE : S48_FALSE)
|
|
||||||
#define S48_EXTRACT_BOOLEAN(x) ((x) != S48_FALSE)
|
|
||||||
|
|
||||||
#define S48_UNSAFE_ENTER_CHAR(c) (S48_CHAR | ((c) << 8))
|
#define S48_UNSAFE_ENTER_CHAR(c) (S48_CHAR | ((c) << 8))
|
||||||
#define S48_UNSAFE_EXTRACT_CHAR(x) ((x) >> 8)
|
#define S48_UNSAFE_EXTRACT_CHAR(x) ((x) >> 8)
|
||||||
#define S48_CHAR_P(x) ((((long) (x)) & 0xff) == S48_CHAR)
|
#define S48_CHAR_P(x) ((((long) (x)) & 0xff) == S48_CHAR)
|
||||||
|
|
@ -238,8 +289,8 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
#define S48_ADDRESS_AFTER_HEADER(x, type) ((type *)((x) - S48_STOB_TAG))
|
#define S48_ADDRESS_AFTER_HEADER(x, type) ((type *)((x) - S48_STOB_TAG))
|
||||||
#define S48_STOB_REF(x, i) (S48_ADDRESS_AFTER_HEADER(x, s48_value)[i])
|
#define S48_STOB_REF(x, i) (S48_ADDRESS_AFTER_HEADER(x, s48_value)[i])
|
||||||
#define S48_STOB_BYTE_REF(x, i) (((char *)S48_ADDRESS_AFTER_HEADER(x, s48_value))[i])
|
#define S48_STOB_BYTE_REF(x, i) (((char *)S48_ADDRESS_AFTER_HEADER(x, s48_value))[i])
|
||||||
#define S48_STOB_SET(x, i, v) do { s48_value __stob_set_x = (x); long __stob_set_i = (i); s48_value __stob_set_v = (v); if (S48_STOB_IMMUTABLEP(__stob_set_x)) s48_raise_argtype_error(__stob_set_x); else { S48_WRITE_BARRIER((__stob_set_x), (char *) (&S48_STOB_REF((__stob_set_x), (__stob_set_i))),(__stob_set_v)); *(&S48_STOB_REF((__stob_set_x), (__stob_set_i))) = (__stob_set_v); } } while (0)
|
#define S48_STOB_SET(x, i, v) do { s48_value __stob_set_x = (x); long __stob_set_i = (i); s48_value __stob_set_v = (v); if (S48_STOB_IMMUTABLEP(__stob_set_x)) s48_raise_argument_type_error(__stob_set_x); else { S48_WRITE_BARRIER((__stob_set_x), (char *) (&S48_STOB_REF((__stob_set_x), (__stob_set_i))),(__stob_set_v)); *(&S48_STOB_REF((__stob_set_x), (__stob_set_i))) = (__stob_set_v); } } while (0)
|
||||||
#define S48_STOB_BYTE_SET(x, i, v) do { char __stob_set_x = (x); long __stob_set_i = (i); s48_value __stob_set_v = (v); if (S48_STOB_IMMUTABLEP(__stob_set_x)) s48_raise_argtype_error(__stob_set_x); else *(&S48_STOB_BYTE_REF((__stob_set_x), (__stob_set_i))) = (__stob_set_v); } while (0)
|
#define S48_STOB_BYTE_SET(x, i, v) do { s48_value __stob_set_x = (x); long __stob_set_i = (i); char __stob_set_v = (v); if (S48_STOB_IMMUTABLEP(__stob_set_x)) s48_raise_argument_type_error(__stob_set_x); else *(&S48_STOB_BYTE_REF((__stob_set_x), (__stob_set_i))) = (__stob_set_v); } while (0)
|
||||||
#define S48_STOB_TYPE(x) ((S48_STOB_HEADER(x)>>2)&31)
|
#define S48_STOB_TYPE(x) ((S48_STOB_HEADER(x)>>2)&31)
|
||||||
#define S48_STOB_HEADER(x) (S48_STOB_REF((x),-1))
|
#define S48_STOB_HEADER(x) (S48_STOB_REF((x),-1))
|
||||||
#define S48_STOB_ADDRESS(x) (&(S48_STOB_HEADER(x)))
|
#define S48_STOB_ADDRESS(x) (&(S48_STOB_HEADER(x)))
|
||||||
|
|
@ -258,46 +309,48 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
#define S48_CLOSURE_P(x) (s48_stob_has_type(x, 3))
|
#define S48_CLOSURE_P(x) (s48_stob_has_type(x, 3))
|
||||||
#define S48_STOBTYPE_LOCATION 4
|
#define S48_STOBTYPE_LOCATION 4
|
||||||
#define S48_LOCATION_P(x) (s48_stob_has_type(x, 4))
|
#define S48_LOCATION_P(x) (s48_stob_has_type(x, 4))
|
||||||
#define S48_STOBTYPE_CHANNEL 5
|
#define S48_STOBTYPE_CELL 5
|
||||||
#define S48_CHANNEL_P(x) (s48_stob_has_type(x, 5))
|
#define S48_CELL_P(x) (s48_stob_has_type(x, 5))
|
||||||
#define S48_STOBTYPE_PORT 6
|
#define S48_STOBTYPE_CHANNEL 6
|
||||||
#define S48_PORT_P(x) (s48_stob_has_type(x, 6))
|
#define S48_CHANNEL_P(x) (s48_stob_has_type(x, 6))
|
||||||
#define S48_STOBTYPE_RATNUM 7
|
#define S48_STOBTYPE_PORT 7
|
||||||
#define S48_RATNUM_P(x) (s48_stob_has_type(x, 7))
|
#define S48_PORT_P(x) (s48_stob_has_type(x, 7))
|
||||||
#define S48_STOBTYPE_RECORD 8
|
#define S48_STOBTYPE_RATNUM 8
|
||||||
#define S48_RECORD_P(x) (s48_stob_has_type(x, 8))
|
#define S48_RATNUM_P(x) (s48_stob_has_type(x, 8))
|
||||||
#define S48_STOBTYPE_CONTINUATION 9
|
#define S48_STOBTYPE_RECORD 9
|
||||||
#define S48_CONTINUATION_P(x) (s48_stob_has_type(x, 9))
|
#define S48_RECORD_P(x) (s48_stob_has_type(x, 9))
|
||||||
#define S48_STOBTYPE_EXTENDED_NUMBER 10
|
#define S48_STOBTYPE_CONTINUATION 10
|
||||||
#define S48_EXTENDED_NUMBER_P(x) (s48_stob_has_type(x, 10))
|
#define S48_CONTINUATION_P(x) (s48_stob_has_type(x, 10))
|
||||||
#define S48_STOBTYPE_TEMPLATE 11
|
#define S48_STOBTYPE_EXTENDED_NUMBER 11
|
||||||
#define S48_TEMPLATE_P(x) (s48_stob_has_type(x, 11))
|
#define S48_EXTENDED_NUMBER_P(x) (s48_stob_has_type(x, 11))
|
||||||
#define S48_STOBTYPE_WEAK_POINTER 12
|
#define S48_STOBTYPE_TEMPLATE 12
|
||||||
#define S48_WEAK_POINTER_P(x) (s48_stob_has_type(x, 12))
|
#define S48_TEMPLATE_P(x) (s48_stob_has_type(x, 12))
|
||||||
#define S48_STOBTYPE_SHARED_BINDING 13
|
#define S48_STOBTYPE_WEAK_POINTER 13
|
||||||
#define S48_SHARED_BINDING_P(x) (s48_stob_has_type(x, 13))
|
#define S48_WEAK_POINTER_P(x) (s48_stob_has_type(x, 13))
|
||||||
#define S48_STOBTYPE_UNUSED_D_HEADER1 14
|
#define S48_STOBTYPE_SHARED_BINDING 14
|
||||||
#define S48_UNUSED_D_HEADER1_P(x) (s48_stob_has_type(x, 14))
|
#define S48_SHARED_BINDING_P(x) (s48_stob_has_type(x, 14))
|
||||||
#define S48_STOBTYPE_UNUSED_D_HEADER2 15
|
#define S48_STOBTYPE_UNUSED_D_HEADER1 15
|
||||||
#define S48_UNUSED_D_HEADER2_P(x) (s48_stob_has_type(x, 15))
|
#define S48_UNUSED_D_HEADER1_P(x) (s48_stob_has_type(x, 15))
|
||||||
#define S48_STOBTYPE_STRING 16
|
#define S48_STOBTYPE_UNUSED_D_HEADER2 16
|
||||||
#define S48_STRING_P(x) (s48_stob_has_type(x, 16))
|
#define S48_UNUSED_D_HEADER2_P(x) (s48_stob_has_type(x, 16))
|
||||||
#define S48_STOBTYPE_BYTE_VECTOR 17
|
#define S48_STOBTYPE_STRING 17
|
||||||
#define S48_BYTE_VECTOR_P(x) (s48_stob_has_type(x, 17))
|
#define S48_STRING_P(x) (s48_stob_has_type(x, 17))
|
||||||
#define S48_STOBTYPE_DOUBLE 18
|
#define S48_STOBTYPE_BYTE_VECTOR 18
|
||||||
#define S48_DOUBLE_P(x) (s48_stob_has_type(x, 18))
|
#define S48_BYTE_VECTOR_P(x) (s48_stob_has_type(x, 18))
|
||||||
#define S48_STOBTYPE_BIGNUM 19
|
#define S48_STOBTYPE_DOUBLE 19
|
||||||
#define S48_BIGNUM_P(x) (s48_stob_has_type(x, 19))
|
#define S48_DOUBLE_P(x) (s48_stob_has_type(x, 19))
|
||||||
|
#define S48_STOBTYPE_BIGNUM 20
|
||||||
|
#define S48_BIGNUM_P(x) (s48_stob_has_type(x, 20))
|
||||||
|
|
||||||
#define S48_CAR_OFFSET 0
|
#define S48_CAR_OFFSET 0
|
||||||
#define S48_CAR(x) (s48_stob_ref((x), S48_STOBTYPE_PAIR, 0))
|
#define S48_CAR(x) (s48_stob_ref((x), S48_STOBTYPE_PAIR, 0))
|
||||||
#define S48_UNSAFE_CAR(x) (S48_STOB_REF((x), 0))
|
#define S48_UNSAFE_CAR(x) (S48_STOB_REF((x), 0))
|
||||||
#define S48_SET_CAR(x, v) (s48_stob_ref((x), S48_STOBTYPE_PAIR, 0, (v)))
|
#define S48_SET_CAR(x, v) (s48_stob_set((x), S48_STOBTYPE_PAIR, 0, (v)))
|
||||||
#define S48_UNSAFE_SET_CAR(x, v) S48_STOB_SET((x), 0, (v))
|
#define S48_UNSAFE_SET_CAR(x, v) S48_STOB_SET((x), 0, (v))
|
||||||
#define S48_CDR_OFFSET 1
|
#define S48_CDR_OFFSET 1
|
||||||
#define S48_CDR(x) (s48_stob_ref((x), S48_STOBTYPE_PAIR, 1))
|
#define S48_CDR(x) (s48_stob_ref((x), S48_STOBTYPE_PAIR, 1))
|
||||||
#define S48_UNSAFE_CDR(x) (S48_STOB_REF((x), 1))
|
#define S48_UNSAFE_CDR(x) (S48_STOB_REF((x), 1))
|
||||||
#define S48_SET_CDR(x, v) (s48_stob_ref((x), S48_STOBTYPE_PAIR, 1, (v)))
|
#define S48_SET_CDR(x, v) (s48_stob_set((x), S48_STOBTYPE_PAIR, 1, (v)))
|
||||||
#define S48_UNSAFE_SET_CDR(x, v) S48_STOB_SET((x), 1, (v))
|
#define S48_UNSAFE_SET_CDR(x, v) S48_STOB_SET((x), 1, (v))
|
||||||
#define S48_SYMBOL_TO_STRING_OFFSET 0
|
#define S48_SYMBOL_TO_STRING_OFFSET 0
|
||||||
#define S48_SYMBOL_TO_STRING(x) (s48_stob_ref((x), S48_STOBTYPE_SYMBOL, 0))
|
#define S48_SYMBOL_TO_STRING(x) (s48_stob_ref((x), S48_STOBTYPE_SYMBOL, 0))
|
||||||
|
|
@ -305,13 +358,18 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
#define S48_LOCATION_ID_OFFSET 0
|
#define S48_LOCATION_ID_OFFSET 0
|
||||||
#define S48_LOCATION_ID(x) (s48_stob_ref((x), S48_STOBTYPE_LOCATION, 0))
|
#define S48_LOCATION_ID(x) (s48_stob_ref((x), S48_STOBTYPE_LOCATION, 0))
|
||||||
#define S48_UNSAFE_LOCATION_ID(x) (S48_STOB_REF((x), 0))
|
#define S48_UNSAFE_LOCATION_ID(x) (S48_STOB_REF((x), 0))
|
||||||
#define S48_SET_LOCATION_ID(x, v) (s48_stob_ref((x), S48_STOBTYPE_LOCATION, 0, (v)))
|
#define S48_SET_LOCATION_ID(x, v) (s48_stob_set((x), S48_STOBTYPE_LOCATION, 0, (v)))
|
||||||
#define S48_UNSAFE_SET_LOCATION_ID(x, v) S48_STOB_SET((x), 0, (v))
|
#define S48_UNSAFE_SET_LOCATION_ID(x, v) S48_STOB_SET((x), 0, (v))
|
||||||
#define S48_CONTENTS_OFFSET 1
|
#define S48_CONTENTS_OFFSET 1
|
||||||
#define S48_CONTENTS(x) (s48_stob_ref((x), S48_STOBTYPE_LOCATION, 1))
|
#define S48_CONTENTS(x) (s48_stob_ref((x), S48_STOBTYPE_LOCATION, 1))
|
||||||
#define S48_UNSAFE_CONTENTS(x) (S48_STOB_REF((x), 1))
|
#define S48_UNSAFE_CONTENTS(x) (S48_STOB_REF((x), 1))
|
||||||
#define S48_SET_CONTENTS(x, v) (s48_stob_ref((x), S48_STOBTYPE_LOCATION, 1, (v)))
|
#define S48_SET_CONTENTS(x, v) (s48_stob_set((x), S48_STOBTYPE_LOCATION, 1, (v)))
|
||||||
#define S48_UNSAFE_SET_CONTENTS(x, v) S48_STOB_SET((x), 1, (v))
|
#define S48_UNSAFE_SET_CONTENTS(x, v) S48_STOB_SET((x), 1, (v))
|
||||||
|
#define S48_CELL_REF_OFFSET 0
|
||||||
|
#define S48_CELL_REF(x) (s48_stob_ref((x), S48_STOBTYPE_CELL, 0))
|
||||||
|
#define S48_UNSAFE_CELL_REF(x) (S48_STOB_REF((x), 0))
|
||||||
|
#define S48_CELL_SET(x, v) (s48_stob_set((x), S48_STOBTYPE_CELL, 0, (v)))
|
||||||
|
#define S48_UNSAFE_CELL_SET(x, v) S48_STOB_SET((x), 0, (v))
|
||||||
#define S48_CLOSURE_TEMPLATE_OFFSET 0
|
#define S48_CLOSURE_TEMPLATE_OFFSET 0
|
||||||
#define S48_CLOSURE_TEMPLATE(x) (s48_stob_ref((x), S48_STOBTYPE_CLOSURE, 0))
|
#define S48_CLOSURE_TEMPLATE(x) (s48_stob_ref((x), S48_STOBTYPE_CLOSURE, 0))
|
||||||
#define S48_UNSAFE_CLOSURE_TEMPLATE(x) (S48_STOB_REF((x), 0))
|
#define S48_UNSAFE_CLOSURE_TEMPLATE(x) (S48_STOB_REF((x), 0))
|
||||||
|
|
@ -330,50 +388,52 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
#define S48_SHARED_BINDING_REF_OFFSET 2
|
#define S48_SHARED_BINDING_REF_OFFSET 2
|
||||||
#define S48_SHARED_BINDING_REF(x) (s48_stob_ref((x), S48_STOBTYPE_SHARED_BINDING, 2))
|
#define S48_SHARED_BINDING_REF(x) (s48_stob_ref((x), S48_STOBTYPE_SHARED_BINDING, 2))
|
||||||
#define S48_UNSAFE_SHARED_BINDING_REF(x) (S48_STOB_REF((x), 2))
|
#define S48_UNSAFE_SHARED_BINDING_REF(x) (S48_STOB_REF((x), 2))
|
||||||
#define S48_SHARED_BINDING_SET(x, v) (s48_stob_ref((x), S48_STOBTYPE_SHARED_BINDING, 2, (v)))
|
#define S48_SHARED_BINDING_SET(x, v) (s48_stob_set((x), S48_STOBTYPE_SHARED_BINDING, 2, (v)))
|
||||||
#define S48_UNSAFE_SHARED_BINDING_SET(x, v) S48_STOB_SET((x), 2, (v))
|
#define S48_UNSAFE_SHARED_BINDING_SET(x, v) S48_STOB_SET((x), 2, (v))
|
||||||
#define S48_PORT_HANDLER_OFFSET 0
|
#define S48_PORT_HANDLER_OFFSET 0
|
||||||
#define S48_PORT_HANDLER(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 0))
|
#define S48_PORT_HANDLER(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 0))
|
||||||
#define S48_UNSAFE_PORT_HANDLER(x) (S48_STOB_REF((x), 0))
|
#define S48_UNSAFE_PORT_HANDLER(x) (S48_STOB_REF((x), 0))
|
||||||
|
#define S48_SET_PORT_HANDLER(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 0, (v)))
|
||||||
|
#define S48_UNSAFE_SET_PORT_HANDLER(x, v) S48_STOB_SET((x), 0, (v))
|
||||||
#define S48_PORT_STATUS_OFFSET 1
|
#define S48_PORT_STATUS_OFFSET 1
|
||||||
#define S48_PORT_STATUS(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 1))
|
#define S48_PORT_STATUS(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 1))
|
||||||
#define S48_UNSAFE_PORT_STATUS(x) (S48_STOB_REF((x), 1))
|
#define S48_UNSAFE_PORT_STATUS(x) (S48_STOB_REF((x), 1))
|
||||||
#define S48_SET_PORT_STATUS(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 1, (v)))
|
#define S48_SET_PORT_STATUS(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 1, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_STATUS(x, v) S48_STOB_SET((x), 1, (v))
|
#define S48_UNSAFE_SET_PORT_STATUS(x, v) S48_STOB_SET((x), 1, (v))
|
||||||
#define S48_PORT_LOCK_OFFSET 2
|
#define S48_PORT_LOCK_OFFSET 2
|
||||||
#define S48_PORT_LOCK(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 2))
|
#define S48_PORT_LOCK(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 2))
|
||||||
#define S48_UNSAFE_PORT_LOCK(x) (S48_STOB_REF((x), 2))
|
#define S48_UNSAFE_PORT_LOCK(x) (S48_STOB_REF((x), 2))
|
||||||
#define S48_SET_PORT_LOCK(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 2, (v)))
|
#define S48_SET_PORT_LOCK(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 2, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_LOCK(x, v) S48_STOB_SET((x), 2, (v))
|
#define S48_UNSAFE_SET_PORT_LOCK(x, v) S48_STOB_SET((x), 2, (v))
|
||||||
#define S48_PORT_LOCKEDP_OFFSET 3
|
#define S48_PORT_LOCKEDP_OFFSET 3
|
||||||
#define S48_PORT_LOCKEDP(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 3))
|
#define S48_PORT_LOCKEDP(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 3))
|
||||||
#define S48_UNSAFE_PORT_LOCKEDP(x) (S48_STOB_REF((x), 3))
|
#define S48_UNSAFE_PORT_LOCKEDP(x) (S48_STOB_REF((x), 3))
|
||||||
#define S48_SET_PORT_LOCKEDP(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 3, (v)))
|
#define S48_SET_PORT_LOCKEDP(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 3, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_LOCKEDP(x, v) S48_STOB_SET((x), 3, (v))
|
#define S48_UNSAFE_SET_PORT_LOCKEDP(x, v) S48_STOB_SET((x), 3, (v))
|
||||||
#define S48_PORT_DATA_OFFSET 4
|
#define S48_PORT_DATA_OFFSET 4
|
||||||
#define S48_PORT_DATA(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 4))
|
#define S48_PORT_DATA(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 4))
|
||||||
#define S48_UNSAFE_PORT_DATA(x) (S48_STOB_REF((x), 4))
|
#define S48_UNSAFE_PORT_DATA(x) (S48_STOB_REF((x), 4))
|
||||||
#define S48_SET_PORT_DATA(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 4, (v)))
|
#define S48_SET_PORT_DATA(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 4, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_DATA(x, v) S48_STOB_SET((x), 4, (v))
|
#define S48_UNSAFE_SET_PORT_DATA(x, v) S48_STOB_SET((x), 4, (v))
|
||||||
#define S48_PORT_BUFFER_OFFSET 5
|
#define S48_PORT_BUFFER_OFFSET 5
|
||||||
#define S48_PORT_BUFFER(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 5))
|
#define S48_PORT_BUFFER(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 5))
|
||||||
#define S48_UNSAFE_PORT_BUFFER(x) (S48_STOB_REF((x), 5))
|
#define S48_UNSAFE_PORT_BUFFER(x) (S48_STOB_REF((x), 5))
|
||||||
#define S48_SET_PORT_BUFFER(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 5, (v)))
|
#define S48_SET_PORT_BUFFER(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 5, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_BUFFER(x, v) S48_STOB_SET((x), 5, (v))
|
#define S48_UNSAFE_SET_PORT_BUFFER(x, v) S48_STOB_SET((x), 5, (v))
|
||||||
#define S48_PORT_INDEX_OFFSET 6
|
#define S48_PORT_INDEX_OFFSET 6
|
||||||
#define S48_PORT_INDEX(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 6))
|
#define S48_PORT_INDEX(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 6))
|
||||||
#define S48_UNSAFE_PORT_INDEX(x) (S48_STOB_REF((x), 6))
|
#define S48_UNSAFE_PORT_INDEX(x) (S48_STOB_REF((x), 6))
|
||||||
#define S48_SET_PORT_INDEX(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 6, (v)))
|
#define S48_SET_PORT_INDEX(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 6, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_INDEX(x, v) S48_STOB_SET((x), 6, (v))
|
#define S48_UNSAFE_SET_PORT_INDEX(x, v) S48_STOB_SET((x), 6, (v))
|
||||||
#define S48_PORT_LIMIT_OFFSET 7
|
#define S48_PORT_LIMIT_OFFSET 7
|
||||||
#define S48_PORT_LIMIT(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 7))
|
#define S48_PORT_LIMIT(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 7))
|
||||||
#define S48_UNSAFE_PORT_LIMIT(x) (S48_STOB_REF((x), 7))
|
#define S48_UNSAFE_PORT_LIMIT(x) (S48_STOB_REF((x), 7))
|
||||||
#define S48_SET_PORT_LIMIT(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 7, (v)))
|
#define S48_SET_PORT_LIMIT(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 7, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_LIMIT(x, v) S48_STOB_SET((x), 7, (v))
|
#define S48_UNSAFE_SET_PORT_LIMIT(x, v) S48_STOB_SET((x), 7, (v))
|
||||||
#define S48_PORT_PENDING_EOFP_OFFSET 8
|
#define S48_PORT_PENDING_EOFP_OFFSET 8
|
||||||
#define S48_PORT_PENDING_EOFP(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 8))
|
#define S48_PORT_PENDING_EOFP(x) (s48_stob_ref((x), S48_STOBTYPE_PORT, 8))
|
||||||
#define S48_UNSAFE_PORT_PENDING_EOFP(x) (S48_STOB_REF((x), 8))
|
#define S48_UNSAFE_PORT_PENDING_EOFP(x) (S48_STOB_REF((x), 8))
|
||||||
#define S48_SET_PORT_PENDING_EOFP(x, v) (s48_stob_ref((x), S48_STOBTYPE_PORT, 8, (v)))
|
#define S48_SET_PORT_PENDING_EOFP(x, v) (s48_stob_set((x), S48_STOBTYPE_PORT, 8, (v)))
|
||||||
#define S48_UNSAFE_SET_PORT_PENDING_EOFP(x, v) S48_STOB_SET((x), 8, (v))
|
#define S48_UNSAFE_SET_PORT_PENDING_EOFP(x, v) S48_STOB_SET((x), 8, (v))
|
||||||
#define S48_CHANNEL_STATUS_OFFSET 0
|
#define S48_CHANNEL_STATUS_OFFSET 0
|
||||||
#define S48_CHANNEL_STATUS(x) (s48_stob_ref((x), S48_STOBTYPE_CHANNEL, 0))
|
#define S48_CHANNEL_STATUS(x) (s48_stob_ref((x), S48_STOBTYPE_CHANNEL, 0))
|
||||||
|
|
@ -403,15 +463,16 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
#define S48_BYTE_VECTOR_REF(x, i) (s48_stob_byte_ref((x), S48_STOBTYPE_BYTE_VECTOR, (i)))
|
#define S48_BYTE_VECTOR_REF(x, i) (s48_stob_byte_ref((x), S48_STOBTYPE_BYTE_VECTOR, (i)))
|
||||||
#define S48_BYTE_VECTOR_SET(x, i, v) (s48_stob_byte_set((x), S48_STOBTYPE_BYTE_VECTOR, (i), (v)))
|
#define S48_BYTE_VECTOR_SET(x, i, v) (s48_stob_byte_set((x), S48_STOBTYPE_BYTE_VECTOR, (i), (v)))
|
||||||
#define S48_UNSAFE_BYTE_VECTOR_REF(x, i) (S48_STOB_BYTE_REF((x), (i)))
|
#define S48_UNSAFE_BYTE_VECTOR_REF(x, i) (S48_STOB_BYTE_REF((x), (i)))
|
||||||
#define S48_UNSAFE_BYTE_VECTOR_SET(x, i, v) S48_BYTE_STOB_SET((x), (i), (v))
|
#define S48_UNSAFE_BYTE_VECTOR_SET(x, i, v) S48_STOB_BYTE_SET((x), (i), (v))
|
||||||
#define S48_STRING_LENGTH(x) (s48_stob_byte_length((x), S48_STOBTYPE_STRING))
|
#define S48_STRING_LENGTH(x) (s48_stob_byte_length((x), S48_STOBTYPE_STRING))
|
||||||
#define S48_STRING_REF(x, i) (s48_stob_byte_ref((x), S48_STOBTYPE_STRING, (i)))
|
#define S48_STRING_REF(x, i) (s48_stob_byte_ref((x), S48_STOBTYPE_STRING, (i)))
|
||||||
#define S48_STRING_SET(x, i, v) (s48_stob_byte_set((x), S48_STOBTYPE_STRING, (i), (v)))
|
#define S48_STRING_SET(x, i, v) (s48_stob_byte_set((x), S48_STOBTYPE_STRING, (i), (v)))
|
||||||
#define S48_UNSAFE_STRING_REF(x, i) (S48_STOB_BYTE_REF((x), (i)))
|
#define S48_UNSAFE_STRING_REF(x, i) (S48_STOB_BYTE_REF((x), (i)))
|
||||||
#define S48_UNSAFE_STRING_SET(x, i, v) S48_BYTE_STOB_SET((x), (i), (v))
|
#define S48_UNSAFE_STRING_SET(x, i, v) S48_STOB_BYTE_SET((x), (i), (v))
|
||||||
#define S48_UNSAFE_BYTE_VECTOR_LENGTH(x) (S48_STOB_BYTE_LENGTH(x))
|
#define S48_UNSAFE_BYTE_VECTOR_LENGTH(x) (S48_STOB_BYTE_LENGTH(x))
|
||||||
#define S48_UNSAFE_STRING_LENGTH(x) (S48_STOB_BYTE_LENGTH(x) - 1)
|
#define S48_UNSAFE_STRING_LENGTH(x) (S48_STOB_BYTE_LENGTH(x) - 1)
|
||||||
#define S48_UNSAFE_EXTRACT_STRING(x) (S48_ADDRESS_AFTER_HEADER((x), char))
|
#define S48_UNSAFE_EXTRACT_STRING(x) (S48_ADDRESS_AFTER_HEADER((x), char))
|
||||||
|
#define S48_UNSAFE_EXTRACT_BYTE_VECTOR(x) (S48_ADDRESS_AFTER_HEADER((x), char))
|
||||||
#define S48_EXTRACT_EXTERNAL_OBJECT(x, type) ((type *)(S48_ADDRESS_AFTER_HEADER(x, long)+1))
|
#define S48_EXTRACT_EXTERNAL_OBJECT(x, type) ((type *)(S48_ADDRESS_AFTER_HEADER(x, long)+1))
|
||||||
|
|
||||||
#define S48_RECORD_TYPE_RESUMER(x) S48_RECORD_REF((x), 0)
|
#define S48_RECORD_TYPE_RESUMER(x) S48_RECORD_REF((x), 0)
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,15 @@ typedef long s48_value;
|
||||||
|
|
||||||
#define NO_ERRORS 0 /* errno value */
|
#define NO_ERRORS 0 /* errno value */
|
||||||
|
|
||||||
|
extern int s48_main (long heap_size, long stack_size,
|
||||||
|
char *image_name, int argc, char** argv);
|
||||||
|
|
||||||
|
extern int s48_add_external_init(void (*init)());
|
||||||
|
|
||||||
/* Misc stuff */
|
/* Misc stuff */
|
||||||
|
|
||||||
|
#define S48_EQ_P(v1, v2) ((v1) == (v2))
|
||||||
|
/* Superceded name for the above definition, retained for compatibility. */
|
||||||
#define S48_EQ(v1, v2) ((v1) == (v2))
|
#define S48_EQ(v1, v2) ((v1) == (v2))
|
||||||
|
|
||||||
#define S48_MAX_FIXNUM_VALUE ((1 << 29) - 1)
|
#define S48_MAX_FIXNUM_VALUE ((1 << 29) - 1)
|
||||||
|
|
@ -33,15 +40,43 @@ extern s48_value s48_enter_fixnum(long);
|
||||||
extern long s48_extract_fixnum(s48_value);
|
extern long s48_extract_fixnum(s48_value);
|
||||||
extern s48_value s48_enter_integer(long);
|
extern s48_value s48_enter_integer(long);
|
||||||
extern long s48_extract_integer(s48_value);
|
extern long s48_extract_integer(s48_value);
|
||||||
|
extern s48_value s48_enter_unsigned_integer(unsigned long);
|
||||||
|
extern unsigned long s48_extract_unsigned_integer(s48_value);
|
||||||
extern s48_value s48_enter_double(double);
|
extern s48_value s48_enter_double(double);
|
||||||
extern double s48_extract_double(s48_value);
|
extern double s48_extract_double(s48_value);
|
||||||
extern s48_value s48_cons(s48_value, s48_value);
|
extern s48_value s48_cons(s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_1(s48_value);
|
||||||
|
extern s48_value s48_list_2(s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_3(s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_4(s48_value, s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_5(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value);
|
||||||
|
extern s48_value s48_list_6(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_7(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_8(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_9(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value);
|
||||||
|
extern s48_value s48_list_10(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_11(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value);
|
||||||
|
extern s48_value s48_list_12(s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value,
|
||||||
|
s48_value, s48_value, s48_value, s48_value);
|
||||||
extern s48_value s48_enter_string(char *);
|
extern s48_value s48_enter_string(char *);
|
||||||
extern char * s48_extract_string(s48_value);
|
extern char * s48_extract_string(s48_value);
|
||||||
extern s48_value s48_enter_substring(char *, int);
|
extern s48_value s48_enter_substring(char *, int);
|
||||||
extern s48_value s48_make_string(int, char);
|
extern s48_value s48_make_string(int, char);
|
||||||
extern s48_value s48_make_vector(int, s48_value);
|
extern s48_value s48_make_vector(int, s48_value);
|
||||||
extern s48_value s48_make_byte_vector(int);
|
extern s48_value s48_enter_byte_vector(char *, int);
|
||||||
|
extern char * s48_extract_byte_vector(s48_value);
|
||||||
|
extern s48_value s48_make_byte_vector(int, int);
|
||||||
extern s48_value s48_make_record(s48_value);
|
extern s48_value s48_make_record(s48_value);
|
||||||
extern s48_value s48_make_weak_pointer(s48_value);
|
extern s48_value s48_make_weak_pointer(s48_value);
|
||||||
extern void s48_check_record_type(s48_value, s48_value);
|
extern void s48_check_record_type(s48_value, s48_value);
|
||||||
|
|
@ -58,7 +93,7 @@ extern s48_value s48_call_scheme(s48_value proc, long nargs, ...);
|
||||||
|
|
||||||
#define S48_EXPORT_FUNCTION(p) (s48_define_exported_binding(#p, s48_enter_pointer(p)))
|
#define S48_EXPORT_FUNCTION(p) (s48_define_exported_binding(#p, s48_enter_pointer(p)))
|
||||||
|
|
||||||
#define S48_MAKE_VALUE(type) (s48_make_byte_vector(sizeof(type)))
|
#define S48_MAKE_VALUE(type) (s48_make_byte_vector(sizeof(type),0))
|
||||||
extern void * s48_value_pointer(s48_value);
|
extern void * s48_value_pointer(s48_value);
|
||||||
|
|
||||||
#define S48_EXTRACT_VALUE_POINTER(x, type) ((type *) s48_value_pointer(x))
|
#define S48_EXTRACT_VALUE_POINTER(x, type) ((type *) s48_value_pointer(x))
|
||||||
|
|
@ -171,28 +206,46 @@ extern void * s48_value_pointer(s48_value);
|
||||||
/* Exceptions */
|
/* Exceptions */
|
||||||
|
|
||||||
extern void s48_raise_scheme_exception(long type, long nargs, ...);
|
extern void s48_raise_scheme_exception(long type, long nargs, ...);
|
||||||
extern void s48_raise_argtype_error(s48_value value);
|
extern void s48_raise_argument_type_error(s48_value value);
|
||||||
extern void s48_raise_argnumber_error(s48_value value,
|
extern void s48_raise_argument_number_error(s48_value value,
|
||||||
s48_value min, s48_value max);
|
s48_value min,
|
||||||
|
s48_value max);
|
||||||
extern void s48_raise_range_error(s48_value value,
|
extern void s48_raise_range_error(s48_value value,
|
||||||
s48_value min, s48_value max);
|
s48_value min, s48_value max);
|
||||||
extern void s48_raise_closed_channel_error();
|
extern void s48_raise_closed_channel_error();
|
||||||
extern void s48_raise_os_error(int the_errno);
|
extern void s48_raise_os_error(int the_errno);
|
||||||
|
extern void s48_raise_os_error_1(int the_errno, s48_value arg1);
|
||||||
|
extern void s48_raise_os_error_2(int the_errno, s48_value arg1, s48_value arg2);
|
||||||
|
extern void s48_raise_os_error_3(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3);
|
||||||
|
extern void s48_raise_os_error_4(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4);
|
||||||
|
extern void s48_raise_os_error_5(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5);
|
||||||
|
extern void s48_raise_os_error_6(int the_errno, s48_value arg1, s48_value arg2,
|
||||||
|
s48_value arg3, s48_value arg4, s48_value arg5,
|
||||||
|
s48_value arg6);
|
||||||
extern void s48_raise_string_os_error(char *reason);
|
extern void s48_raise_string_os_error(char *reason);
|
||||||
extern void s48_raise_out_of_memory_error();
|
extern void s48_raise_out_of_memory_error();
|
||||||
|
|
||||||
/* Type checking */
|
/* Type checking */
|
||||||
|
|
||||||
#define S48_CHECK_PAIR(v) do { if (!S48_PAIR_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_PAIR(v) do { if (!S48_PAIR_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_FIXNUM(v) do { if (!S48_FIXNUM_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_FIXNUM(v) do { if (!S48_FIXNUM_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_STRING(v) do { if (!S48_STRING_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_STRING(v) do { if (!S48_STRING_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_CHANNEL(v) do { if (!S48_CHANNEL_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_BYTE_VECTOR(v) do { if (!S48_BYTE_VECTOR_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_RECORD(v) do { if (!S48_RECORD_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_CHANNEL(v) do { if (!S48_CHANNEL_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_VALUE(v) do { if (!S48_BYTE_VECTOR_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_RECORD(v) do { if (!S48_RECORD_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
#define S48_CHECK_EXPORT_BINDING(v) do { if (!S48_EXPORT_BINDING_P(v)) s48_raise_argtype_error(v); } while (0)
|
#define S48_CHECK_VALUE(v) do { if (!S48_BYTE_VECTOR_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
|
#define S48_CHECK_EXPORT_BINDING(v) do { if (!S48_EXPORT_BINDING_P(v)) s48_raise_argument_type_error(v); } while (0)
|
||||||
|
|
||||||
#define S48_VALUE_P(v) (S48_BYTE_VECTOR_P(v))
|
#define S48_VALUE_P(v) (S48_BYTE_VECTOR_P(v))
|
||||||
|
|
||||||
|
#define S48_TRUE_P(v) ((v) == S48_TRUE)
|
||||||
|
#define S48_FALSE_P(v) ((v) == S48_FALSE)
|
||||||
|
#define S48_EXTRACT_BOOLEAN(v) ((v) != S48_FALSE)
|
||||||
|
#define S48_ENTER_BOOLEAN(v) ((v) ? S48_TRUE : S48_FALSE)
|
||||||
|
|
||||||
extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
|
|
||||||
#define S48_SHARED_BINDING_CHECK(binding) \
|
#define S48_SHARED_BINDING_CHECK(binding) \
|
||||||
|
|
@ -200,3 +253,4 @@ extern void s48_check_record_type(s48_value record, s48_value type_binding);
|
||||||
s48_raise_scheme_exception(S48_EXCEPTION_UNBOUND_EXTERNAL_NAME, 1, \
|
s48_raise_scheme_exception(S48_EXCEPTION_UNBOUND_EXTERNAL_NAME, 1, \
|
||||||
S48_SHARED_BINDING_NAME(binding)); \
|
S48_SHARED_BINDING_NAME(binding)); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
|
|
|
||||||
1056
c/scheme48heap.c
1056
c/scheme48heap.c
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Externally visible objects defined in scheme48heap.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* initialize top-level variables */
|
||||||
|
extern void s48_heap_init(void);
|
||||||
|
|
||||||
|
/* heap-init interface */
|
||||||
|
extern void s48_initialize_heap(long, long);
|
||||||
|
extern void s48_register_static_areas(unsigned char, long *, long *,
|
||||||
|
unsigned char, long *, long *);
|
||||||
|
|
||||||
|
/* heap interface */
|
||||||
|
extern long s48_available(void);
|
||||||
|
extern long s48_heap_size(void);
|
||||||
|
extern long s48_find_all(long);
|
||||||
|
extern long s48_find_all_records(long);
|
||||||
|
extern char *s48_ShpS;
|
||||||
|
extern char *s48_SlimitS;
|
||||||
|
|
||||||
|
/* gc interface */
|
||||||
|
extern void s48_begin_collection(void);
|
||||||
|
extern long s48_trace_value(long);
|
||||||
|
extern long s48_trace_locationsB(char *, char *);
|
||||||
|
extern long s48_trace_stob_contentsB(long);
|
||||||
|
extern void s48_do_gc(void);
|
||||||
|
extern void s48_end_collection(void);
|
||||||
|
extern char s48_extantP(long);
|
||||||
|
extern long s48_gc_count(void);
|
||||||
|
|
||||||
|
/* allocation interface */
|
||||||
|
extern char s48_availableP(long);
|
||||||
|
extern long s48_preallocate_space(long);
|
||||||
|
extern char *s48_allocate_space(long, long, long);
|
||||||
|
extern void s48_write_barrier(long, char *, long);
|
||||||
|
|
||||||
|
/* images interface */
|
||||||
|
extern char s48_image_writing_okayP(void);
|
||||||
|
extern long s48_write_image(long, FILE *);
|
||||||
|
extern long s48_check_image_header(unsigned char *);
|
||||||
|
extern long s48_read_image();
|
||||||
|
|
||||||
|
extern long s48_startup_procedure(void);
|
||||||
|
extern long s48_initial_symbols(void);
|
||||||
|
extern long s48_initial_imported_bindings(void);
|
||||||
|
extern long s48_initial_exported_bindings(void);
|
||||||
|
extern long s48_resumer_records(void);
|
||||||
|
extern long s48_undumpable_records(long *);
|
||||||
|
|
||||||
|
extern void s48_initialization_completeB(void);
|
||||||
|
extern void s48_initializing_gc_root(void);
|
||||||
|
|
||||||
|
extern void s48_set_image_valuesB(long, long, long, long);
|
||||||
14374
c/scheme48vm.c
14374
c/scheme48vm.c
File diff suppressed because it is too large
Load Diff
|
|
@ -23,7 +23,7 @@ extern char s48_Spending_eventsPS;
|
||||||
extern char s48_Spending_interruptPS;
|
extern char s48_Spending_interruptPS;
|
||||||
extern void s48_disable_interruptsB(void);
|
extern void s48_disable_interruptsB(void);
|
||||||
extern void s48_enable_interruptsB(void);
|
extern void s48_enable_interruptsB(void);
|
||||||
extern void s48_set_os_signal(s48_value type, s48_value argument);
|
extern void s48_set_os_signals(s48_value list);
|
||||||
|
|
||||||
/* imported and exported bindings */
|
/* imported and exported bindings */
|
||||||
extern void s48_define_exported_binding(char *, s48_value);
|
extern void s48_define_exported_binding(char *, s48_value);
|
||||||
|
|
@ -56,6 +56,6 @@ extern s48_value s48_add_channel(s48_value, s48_value, long);
|
||||||
extern s48_value s48_allocate_stob(long type, long size);
|
extern s48_value s48_allocate_stob(long type, long size);
|
||||||
extern void s48_push_gc_rootsB(char *, long);
|
extern void s48_push_gc_rootsB(char *, long);
|
||||||
extern char s48_pop_gc_rootsB(void);
|
extern char s48_pop_gc_rootsB(void);
|
||||||
extern char * s48_set_gc_roots_baseB(void);
|
extern char * s48_set_gc_roots_baseB(char **);
|
||||||
extern char s48_release_gc_roots_baseB(char *);
|
extern char s48_release_gc_roots_baseB(char *, char*);
|
||||||
extern void s48_register_gc_rootB(char *marker);
|
extern void s48_register_gc_rootB(char *marker);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,243 @@
|
||||||
|
/* 54-BIT (double) IMPLEMENTATION IN C OF THE "MRG32K3A" GENERATOR
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
Sebastian.Egner@philips.com, Mar-2002, in ANSI-C and Scheme 48 0.57
|
||||||
|
|
||||||
|
This code is a C-implementation of Pierre L'Ecuyer's MRG32k3a generator.
|
||||||
|
The code uses (double)-arithmetics, assuming that it covers the range
|
||||||
|
{-2^53..2^53-1} exactly (!). The code of the generator is based on the
|
||||||
|
L'Ecuyer's own implementation of the generator. Please refer to the
|
||||||
|
file 'mrg32k3a.scm' for more information about the method.
|
||||||
|
|
||||||
|
The method provides the following functions via the C/Scheme
|
||||||
|
interface of Scheme 48 0.57 to 'mrg32k3a-b.scm':
|
||||||
|
|
||||||
|
s48_value mrg32k3a_pack_state1(s48_value state);
|
||||||
|
s48_value mrg32k3a_unpack_state1(s48_value state);
|
||||||
|
s48_value mrg32k3a_random_range();
|
||||||
|
s48_value mrg32k3a_random_integer(s48_value state, s48_value range);
|
||||||
|
s48_value mrg32k3a_random_real(s48_value state);
|
||||||
|
|
||||||
|
As Scheme48 FIXNUMs cannot cover the range {0..m1-1}, we break up
|
||||||
|
all values x in the state into x0+x1*w, where w = 2^16 = 65536.
|
||||||
|
The procedures in Scheme correct for that.
|
||||||
|
|
||||||
|
compile this file with:
|
||||||
|
gcc -c -I $SCHEME48 mrg32k3a-b.c
|
||||||
|
|
||||||
|
history of this file:
|
||||||
|
SE, 18-Mar-2002: initial version
|
||||||
|
SE, 22-Mar-2002: interface changed
|
||||||
|
SE, 25-Mar-2002: tested with Scheme 48 0.57 in c/srfi-27
|
||||||
|
SE, 27-Mar-2002: cleaned
|
||||||
|
SE, 13-May-2002: bug found by Shiro Kawai removed
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "scheme48.h" /* $SCHEME48/c/scheme48.h */
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#ifndef NULL
|
||||||
|
#define NULL 0
|
||||||
|
#endif
|
||||||
|
/* maximum value for random_integer: min(S48_MAX_FIXNUM_VALUE, m1) */
|
||||||
|
#define m_max (((long)1 << 29) - 1)
|
||||||
|
|
||||||
|
/* The Generator
|
||||||
|
=============
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* moduli of the components */
|
||||||
|
#define m1 4294967087.0
|
||||||
|
#define m2 4294944443.0
|
||||||
|
|
||||||
|
/* representation of the state in C */
|
||||||
|
typedef struct {
|
||||||
|
double
|
||||||
|
x10, x11, x12,
|
||||||
|
x20, x21, x22;
|
||||||
|
} state_t;
|
||||||
|
|
||||||
|
/* recursion coefficients of the components */
|
||||||
|
#define a12 1403580.0
|
||||||
|
#define a13n 810728.0
|
||||||
|
#define a21 527612.0
|
||||||
|
#define a23n 1370589.0
|
||||||
|
|
||||||
|
/* normalization factor 1/(m1 + 1) */
|
||||||
|
#define norm 2.328306549295728e-10
|
||||||
|
|
||||||
|
|
||||||
|
/* the actual generator */
|
||||||
|
|
||||||
|
static double mrg32k3a(state_t *s) { /* (double), in {0..m1-1} */
|
||||||
|
double x10, x20, y;
|
||||||
|
long k10, k20;
|
||||||
|
|
||||||
|
/* #define debug 1 */
|
||||||
|
|
||||||
|
#if defined(debug)
|
||||||
|
printf(
|
||||||
|
"state = {%g %g %g %g %g %g};\n",
|
||||||
|
s->x10, s->x11, s->x12,
|
||||||
|
s->x20, s->x21, s->x22
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* component 1 */
|
||||||
|
x10 = a12*(s->x11) - a13n*(s->x12);
|
||||||
|
k10 = x10 / m1;
|
||||||
|
x10 -= k10 * m1;
|
||||||
|
if (x10 < 0.0)
|
||||||
|
x10 += m1;
|
||||||
|
s->x12 = s->x11;
|
||||||
|
s->x11 = s->x10;
|
||||||
|
s->x10 = x10;
|
||||||
|
|
||||||
|
/* component 2 */
|
||||||
|
x20 = a21*(s->x20) - a23n*(s->x22);
|
||||||
|
k20 = x20 / m2;
|
||||||
|
x20 -= k20 * m2;
|
||||||
|
if (x20 < 0.0)
|
||||||
|
x20 += m2;
|
||||||
|
s->x22 = s->x21;
|
||||||
|
s->x21 = s->x20;
|
||||||
|
s->x20 = x20;
|
||||||
|
|
||||||
|
/* combination of component */
|
||||||
|
y = x10 - x20;
|
||||||
|
if (y < 0.0)
|
||||||
|
y += m1;
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exported Interface
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
|
||||||
|
s48_value mrg32k3a_pack_state1(s48_value state) {
|
||||||
|
s48_value result;
|
||||||
|
state_t s;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(state); /* s48_extract_integer may GC */
|
||||||
|
|
||||||
|
result = S48_MAKE_VALUE(state_t);
|
||||||
|
|
||||||
|
|
||||||
|
#define REF(i) (double)s48_extract_integer(S48_VECTOR_REF(state, (long)(i)))
|
||||||
|
|
||||||
|
/* copy the numbers from state into s */
|
||||||
|
s.x10 = REF( 0) + 65536.0 * REF( 1);
|
||||||
|
s.x11 = REF( 2) + 65536.0 * REF( 3);
|
||||||
|
s.x12 = REF( 4) + 65536.0 * REF( 5);
|
||||||
|
s.x20 = REF( 6) + 65536.0 * REF( 7);
|
||||||
|
s.x21 = REF( 8) + 65536.0 * REF( 9);
|
||||||
|
s.x22 = REF(10) + 65536.0 * REF(11);
|
||||||
|
|
||||||
|
#undef REF
|
||||||
|
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
|
||||||
|
/* box s into a Scheme object */
|
||||||
|
result = S48_MAKE_VALUE(state_t);
|
||||||
|
S48_SET_VALUE(result, state_t, s);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value mrg32k3a_unpack_state1(s48_value state) {
|
||||||
|
s48_value result = S48_UNSPECIFIC;
|
||||||
|
state_t s;
|
||||||
|
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
S48_GC_PROTECT_1(result);
|
||||||
|
|
||||||
|
/* unbox s from the Scheme object */
|
||||||
|
s = S48_EXTRACT_VALUE(state, state_t);
|
||||||
|
|
||||||
|
/* make and fill a Scheme vector with the numbers */
|
||||||
|
result = s48_make_vector((long)12, S48_FALSE);
|
||||||
|
|
||||||
|
#define SET(i, x) { \
|
||||||
|
long x1 = (long)((x) / 65536.0); \
|
||||||
|
long x0 = (long)((x) - 65536.0 * (double)x1); \
|
||||||
|
S48_VECTOR_SET(result, (long)(i+0), s48_enter_integer(x0)); \
|
||||||
|
S48_VECTOR_SET(result, (long)(i+1), s48_enter_integer(x1)); }
|
||||||
|
|
||||||
|
SET( 0, s.x10);
|
||||||
|
SET( 2, s.x11);
|
||||||
|
SET( 4, s.x12);
|
||||||
|
SET( 6, s.x20);
|
||||||
|
SET( 8, s.x21);
|
||||||
|
SET(10, s.x22);
|
||||||
|
|
||||||
|
#undef SET
|
||||||
|
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value mrg32k3a_random_range(void) {
|
||||||
|
return s48_enter_fixnum(m_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value mrg32k3a_random_integer(s48_value state, s48_value range) {
|
||||||
|
long result;
|
||||||
|
state_t s;
|
||||||
|
long n;
|
||||||
|
double x, q, qn, xq;
|
||||||
|
|
||||||
|
s = S48_EXTRACT_VALUE(state, state_t);
|
||||||
|
n = s48_extract_integer(range);
|
||||||
|
if (!( ((long)1 <= n) && (n <= m_max) ))
|
||||||
|
s48_raise_range_error(n, (long)1, m_max);
|
||||||
|
|
||||||
|
/* generate result in {0..n-1} using the rejection method */
|
||||||
|
q = (double)( (unsigned long)(m1 / (double)n) );
|
||||||
|
qn = q * n;
|
||||||
|
do {
|
||||||
|
x = mrg32k3a(&s);
|
||||||
|
} while (x >= qn);
|
||||||
|
xq = x / q;
|
||||||
|
|
||||||
|
/* check the range */
|
||||||
|
if (!( (0.0 <= xq) && (xq < (double)m_max) ))
|
||||||
|
s48_raise_range_error((long)xq, (long)0, m_max);
|
||||||
|
|
||||||
|
/* return result */
|
||||||
|
result = (long)xq;
|
||||||
|
S48_SET_VALUE(state, state_t, s);
|
||||||
|
return s48_enter_fixnum(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value mrg32k3a_random_real(s48_value state) {
|
||||||
|
state_t s;
|
||||||
|
double x;
|
||||||
|
|
||||||
|
s = S48_EXTRACT_VALUE(state, state_t);
|
||||||
|
x = (mrg32k3a(&s) + 1.0) * norm;
|
||||||
|
S48_SET_VALUE(state, state_t, s);
|
||||||
|
return s48_enter_double(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Kludge for scsh */
|
||||||
|
static s48_value current_time(void){
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return s48_enter_integer(tv.tv_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Exporting the C values to Scheme
|
||||||
|
================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
void s48_init_srfi_27(void) {
|
||||||
|
S48_EXPORT_FUNCTION(mrg32k3a_pack_state1);
|
||||||
|
S48_EXPORT_FUNCTION(mrg32k3a_unpack_state1);
|
||||||
|
S48_EXPORT_FUNCTION(mrg32k3a_random_range);
|
||||||
|
S48_EXPORT_FUNCTION(mrg32k3a_random_integer);
|
||||||
|
S48_EXPORT_FUNCTION(mrg32k3a_random_real);
|
||||||
|
S48_EXPORT_FUNCTION(current_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,99 +0,0 @@
|
||||||
/* c/sysdep.h.in. Generated automatically from configure.in by autoheader. */
|
|
||||||
|
|
||||||
/* Define to empty if the keyword does not work. */
|
|
||||||
#undef const
|
|
||||||
|
|
||||||
/* Define if you need to in order for stat and other things to work. */
|
|
||||||
#undef _POSIX_SOURCE
|
|
||||||
|
|
||||||
/* Define as the return type of signal handlers (int or void). */
|
|
||||||
#undef RETSIGTYPE
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HAVE_SIGACTION is defined iff sigaction() is available.
|
|
||||||
*/
|
|
||||||
#undef HAVE_SIGACTION
|
|
||||||
|
|
||||||
/*
|
|
||||||
* HAVE_STRERROR is defined iff the standard libraries provide strerror().
|
|
||||||
*/
|
|
||||||
#undef HAVE_STRERROR
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NLIST_HAS_N_NAME is defined iff a struct nlist has an n_name member.
|
|
||||||
* If it doesn't then we assume it has an n_un member which, in turn,
|
|
||||||
* has an n_name member.
|
|
||||||
*/
|
|
||||||
#undef NLIST_HAS_N_NAME
|
|
||||||
|
|
||||||
/*
|
|
||||||
* USCORE is defined iff C externals are prepended with an underscore.
|
|
||||||
*/
|
|
||||||
#undef USCORE
|
|
||||||
|
|
||||||
/* Define if you have the chroot function. */
|
|
||||||
#undef HAVE_CHROOT
|
|
||||||
|
|
||||||
/* Define if you have the dlopen function. */
|
|
||||||
#undef HAVE_DLOPEN
|
|
||||||
|
|
||||||
/* Define if you have the ftime function. */
|
|
||||||
#undef HAVE_FTIME
|
|
||||||
|
|
||||||
/* Define if you have the gettimeofday function. */
|
|
||||||
#undef HAVE_GETTIMEOFDAY
|
|
||||||
|
|
||||||
/* Define if you have the nlist function. */
|
|
||||||
#undef HAVE_NLIST
|
|
||||||
|
|
||||||
/* Define if you have the select function. */
|
|
||||||
#undef HAVE_SELECT
|
|
||||||
|
|
||||||
/* Define if you have the setitimer function. */
|
|
||||||
#undef HAVE_SETITIMER
|
|
||||||
|
|
||||||
/* Define if you have the sigaction function. */
|
|
||||||
#undef HAVE_SIGACTION
|
|
||||||
|
|
||||||
/* Define if you have the socket function. */
|
|
||||||
#undef HAVE_SOCKET
|
|
||||||
|
|
||||||
/* Define if you have the <libgen.h> header file. */
|
|
||||||
#undef HAVE_LIBGEN_H
|
|
||||||
|
|
||||||
/* Define if you have the <posix/time.h> header file. */
|
|
||||||
#undef HAVE_POSIX_TIME_H
|
|
||||||
|
|
||||||
/* Define if you have the <sys/select.h> header file. */
|
|
||||||
#undef HAVE_SYS_SELECT_H
|
|
||||||
|
|
||||||
/* Define if you have the <sys/timeb.h> header file. */
|
|
||||||
#undef HAVE_SYS_TIMEB_H
|
|
||||||
|
|
||||||
/* Define if you have the dl library (-ldl). */
|
|
||||||
#undef HAVE_LIBDL
|
|
||||||
|
|
||||||
/* Define if you have the elf library (-lelf). */
|
|
||||||
#undef HAVE_LIBELF
|
|
||||||
|
|
||||||
/* Define if you have the gen library (-lgen). */
|
|
||||||
#undef HAVE_LIBGEN
|
|
||||||
|
|
||||||
/* Define if you have the m library (-lm). */
|
|
||||||
#undef HAVE_LIBM
|
|
||||||
|
|
||||||
/* Define if you have the mld library (-lmld). */
|
|
||||||
#undef HAVE_LIBMLD
|
|
||||||
|
|
||||||
/* Define if you have the nsl library (-lnsl). */
|
|
||||||
#undef HAVE_LIBNSL
|
|
||||||
|
|
||||||
/* Define if you have the socket library (-lsocket). */
|
|
||||||
#undef HAVE_LIBSOCKET
|
|
||||||
|
|
||||||
/* Define if you have the sun library (-lsun). */
|
|
||||||
#undef HAVE_LIBSUN
|
|
||||||
|
|
||||||
#include "fake/sigact.h"
|
|
||||||
#include "fake/strerror.h"
|
|
||||||
#include "fake/sys-select.h"
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A simple test file for dynamic loading, dynamic name lookup, and
|
||||||
|
* old-style external calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "scheme48.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These should only be called on characters or other immediates.
|
||||||
|
*/
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_dynamo_test(s48_value arg0, s48_value arg1, s48_value arg2)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s48_value vector = s48_make_vector(3, S48_FALSE);
|
||||||
|
|
||||||
|
S48_VECTOR_SET(vector, 0, arg0);
|
||||||
|
S48_VECTOR_SET(vector, 1, arg1);
|
||||||
|
S48_VECTOR_SET(vector, 2, arg2);
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value
|
||||||
|
s48_old_dynamo_test(long nargs, s48_value args[])
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s48_value vector = s48_make_vector(nargs, S48_FALSE);
|
||||||
|
|
||||||
|
for (i = 0; i < nargs; i++)
|
||||||
|
S48_VECTOR_SET(vector, i, args[i]);
|
||||||
|
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -7,8 +7,12 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
#include "scheme48.h"
|
#include "scheme48.h"
|
||||||
#include <dlfcn.h>
|
|
||||||
|
|
||||||
|
#if defined(HAVE_DLOPEN)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#else
|
||||||
|
#include "../fake/dlfcn.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(RTLD_NOW)
|
#if defined(RTLD_NOW)
|
||||||
#define DLOPEN_MODE RTLD_NOW
|
#define DLOPEN_MODE RTLD_NOW
|
||||||
|
|
|
||||||
218
c/unix/event.c
218
c/unix/event.c
|
|
@ -13,16 +13,31 @@
|
||||||
#include "c-mods.h"
|
#include "c-mods.h"
|
||||||
#include "scheme48vm.h"
|
#include "scheme48vm.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "../scsh/scsh_aux.h"
|
||||||
|
#include "../scsh/signals1.h"
|
||||||
|
|
||||||
/* turning interrupts and I/O readiness into events */
|
/* turning interrupts and I/O readiness into events */
|
||||||
|
sigset_t full_sigset;
|
||||||
|
|
||||||
#define block_interrupts()
|
#define block_interrupts(){sigprocmask (SIG_BLOCK, &full_sigset, 0);}
|
||||||
#define allow_interrupts()
|
#define allow_interrupts(){sigprocmask (SIG_UNBLOCK, &full_sigset, 0);}
|
||||||
|
|
||||||
|
|
||||||
static void when_keyboard_interrupt();
|
static void when_keyboard_interrupt();
|
||||||
static void when_alarm_interrupt();
|
static void when_alarm_interrupt();
|
||||||
static void when_sigpipe_interrupt();
|
static void when_sigpipe_interrupt();
|
||||||
|
|
||||||
|
/* JMG:*/
|
||||||
|
static void when_scsh_interrupt();
|
||||||
|
/* JMG: for scsh */
|
||||||
|
#define INTERRUPT_QUEUE_LENGTH 32
|
||||||
|
|
||||||
|
static int interrupt_queue [INTERRUPT_QUEUE_LENGTH];
|
||||||
|
static int next_interrupt = 0;
|
||||||
|
static int s48_os_signal_pending(void);
|
||||||
|
static bool s48_os_signal_happend(void);
|
||||||
|
|
||||||
|
|
||||||
bool s48_setcatcher(int signum, void (*catcher)(int));
|
bool s48_setcatcher(int signum, void (*catcher)(int));
|
||||||
void s48_start_alarm_interrupts(void);
|
void s48_start_alarm_interrupts(void);
|
||||||
|
|
||||||
|
|
@ -38,6 +53,47 @@ s48_sysdep_init(void)
|
||||||
errno);
|
errno);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sigfillset (&full_sigset);
|
||||||
|
|
||||||
|
/* JMG: for scsh */
|
||||||
|
s48_setcatcher(SIGCHLD, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGCONT, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGHUP, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGQUIT, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGTERM, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGTSTP, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGUSR1, when_scsh_interrupt);
|
||||||
|
s48_setcatcher(SIGUSR2, when_scsh_interrupt);
|
||||||
|
#ifdef SIGINFO
|
||||||
|
s48_setcatcher(SIGINFO, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGIO
|
||||||
|
s48_setcatcher(SIGIO, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#if defined SIGPOLL && ((defined SIGIO && SIGPOLL != SIGIO) || \
|
||||||
|
!defined SIGIO)
|
||||||
|
s48_setcatcher(SIGPOLL, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPROF
|
||||||
|
s48_setcatcher(SIGPROF, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPWR
|
||||||
|
s48_setcatcher(SIGPWR, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGVTALRM
|
||||||
|
s48_setcatcher(SIGVTALRM, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGWINCH
|
||||||
|
s48_setcatcher(SIGWINCH, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGXCPU
|
||||||
|
s48_setcatcher(SIGXCPU, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGXFSZ
|
||||||
|
s48_setcatcher(SIGXFSZ, when_scsh_interrupt);
|
||||||
|
#endif
|
||||||
|
|
||||||
s48_start_alarm_interrupts();
|
s48_start_alarm_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -51,15 +107,21 @@ s48_setcatcher(int signum, void (*catcher)(int))
|
||||||
{
|
{
|
||||||
struct sigaction sa;
|
struct sigaction sa;
|
||||||
|
|
||||||
if (sigaction(signum, (struct sigaction *)NULL, &sa) != 0)
|
if (sigaction(signum, (struct sigaction *)NULL, &sa) != 0){
|
||||||
return (FALSE);
|
fprintf(stderr, "Failed to get sigaction for signal %d\n", signum);
|
||||||
if (sa.sa_handler == SIG_IGN)
|
exit(1);
|
||||||
return (TRUE);
|
}
|
||||||
|
/* JMG: what's the point of not setting the handler in this case?
|
||||||
|
if (sa.sa_handler == SIG_IGN)
|
||||||
|
return (TRUE);*/
|
||||||
sa.sa_handler = catcher;
|
sa.sa_handler = catcher;
|
||||||
sigemptyset(&sa.sa_mask);
|
sigemptyset(&sa.sa_mask);
|
||||||
sa.sa_flags = 0;
|
sa.sa_flags = 0;
|
||||||
if (sigaction(signum, &sa, (struct sigaction *)NULL) != 0)
|
if (sigaction(signum, &sa, (struct sigaction *)NULL) != 0){
|
||||||
return (FALSE);
|
fprintf(stderr, "Failed to define handler for signal %d\n", signum);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
return (TRUE);
|
return (TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -106,6 +168,8 @@ when_alarm_interrupt(int ign)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define USEC_PER_POLL (1000000 / POLLS_PER_SECOND)
|
#define USEC_PER_POLL (1000000 / POLLS_PER_SECOND)
|
||||||
|
|
||||||
/* delta is in ticks, 0 cancels current alarm */
|
/* delta is in ticks, 0 cancels current alarm */
|
||||||
|
|
@ -222,7 +286,7 @@ s48_stop_alarm_interrupts(void)
|
||||||
* (queue-ready-ports)
|
* (queue-ready-ports)
|
||||||
* (set! *poll-time* (+ *time* *poll-interval*))))
|
* (set! *poll-time* (+ *time* *poll-interval*))))
|
||||||
* (cond ((not (queue-empty? ready-ports))
|
* (cond ((not (queue-empty? ready-ports))
|
||||||
* (values (enum event-type i/o-completion)
|
* (values (enum event-type i/o-{read/write}-completion)
|
||||||
* (dequeue! ready-ports)))
|
* (dequeue! ready-ports)))
|
||||||
* ((>= *current_time* *alarm-time*)
|
* ((>= *current_time* *alarm-time*)
|
||||||
* (set! *alarm-time* max-integer)
|
* (set! *alarm-time* max-integer)
|
||||||
|
|
@ -237,9 +301,20 @@ s48_stop_alarm_interrupts(void)
|
||||||
* (values (enum event-type no-event) #f))))))
|
* (values (enum event-type no-event) #f))))))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool there_are_ready_ports(void);
|
#define FD_QUIESCENT 0 /* idle */
|
||||||
static int next_ready_port(void);
|
#define FD_READY 1 /* I/O ready to be performed */
|
||||||
static int queue_ready_ports(bool wait, long seconds, long ticks);
|
#define FD_PENDING 2 /* waiting */
|
||||||
|
|
||||||
|
typedef struct fd_struct {
|
||||||
|
int fd, /* file descriptor */
|
||||||
|
status; /* one of the FD_* constants */
|
||||||
|
bool is_input; /* iff input */
|
||||||
|
struct fd_struct *next; /* next on same queue */
|
||||||
|
} fd_struct;
|
||||||
|
|
||||||
|
static bool there_are_ready_ports(void);
|
||||||
|
static fd_struct *next_ready_fd_struct(void);
|
||||||
|
static int queue_ready_ports(bool wait, long seconds, long ticks);
|
||||||
|
|
||||||
int
|
int
|
||||||
s48_get_next_event(long *ready_fd, long *status)
|
s48_get_next_event(long *ready_fd, long *status)
|
||||||
|
|
@ -249,6 +324,8 @@ s48_get_next_event(long *ready_fd, long *status)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int io_poll_status;
|
int io_poll_status;
|
||||||
|
fd_struct *f;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
fprintf(stderr, "[poll at %d (waiting for %d)]\n", s48_current_time, alarm_time);
|
fprintf(stderr, "[poll at %d (waiting for %d)]\n", s48_current_time, alarm_time);
|
||||||
*/
|
*/
|
||||||
|
|
@ -269,21 +346,25 @@ s48_get_next_event(long *ready_fd, long *status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (there_are_ready_ports()) {
|
if (there_are_ready_ports()) {
|
||||||
*ready_fd = next_ready_port();
|
f = next_ready_fd_struct();
|
||||||
|
*ready_fd = f->fd;
|
||||||
*status = 0; /* chars read or written */
|
*status = 0; /* chars read or written */
|
||||||
/* fprintf(stderr, "[i/o completion]\n"); */
|
/* fprintf(stderr, "[i/o completion]\n"); */
|
||||||
return (IO_COMPLETION_EVENT);
|
if (f->is_input)
|
||||||
|
return (IO_READ_COMPLETION_EVENT);
|
||||||
|
else
|
||||||
|
return (IO_WRITE_COMPLETION_EVENT);
|
||||||
}
|
}
|
||||||
if (alarm_time != -1 && s48_current_time >= alarm_time) {
|
if (alarm_time != -1 && s48_current_time >= alarm_time) {
|
||||||
alarm_time = -1;
|
alarm_time = -1;
|
||||||
/* fprintf(stderr, "[alarm]\n"); */
|
/* fprintf(stderr, "[alarm]\n"); */
|
||||||
return (ALARM_EVENT);
|
return (ALARM_EVENT);
|
||||||
}
|
}
|
||||||
/*
|
block_interrupts();
|
||||||
|
/* JMG: scsh should handle this */
|
||||||
if (s48_os_signal_pending())
|
if (s48_os_signal_pending())
|
||||||
return (OS_SIGNAL_EVENT);
|
return (OS_SIGNAL_EVENT);
|
||||||
*/
|
|
||||||
block_interrupts();
|
|
||||||
if ((keyboard_interrupt_count == 0)
|
if ((keyboard_interrupt_count == 0)
|
||||||
&& (alarm_time == -1 || s48_current_time < alarm_time)
|
&& (alarm_time == -1 || s48_current_time < alarm_time)
|
||||||
&& (poll_time == -1 || s48_current_time < poll_time))
|
&& (poll_time == -1 || s48_current_time < poll_time))
|
||||||
|
|
@ -299,17 +380,6 @@ s48_get_next_event(long *ready_fd, long *status)
|
||||||
* the pending ports and move any that are ready onto the other queue and
|
* the pending ports and move any that are ready onto the other queue and
|
||||||
* signal an event.
|
* signal an event.
|
||||||
*/
|
*/
|
||||||
#define FD_QUIESCENT 0 /* idle */
|
|
||||||
#define FD_READY 1 /* I/O ready to be performed */
|
|
||||||
#define FD_PENDING 2 /* waiting */
|
|
||||||
|
|
||||||
typedef struct fd_struct {
|
|
||||||
int fd, /* file descriptor */
|
|
||||||
status; /* one of the FD_* constants */
|
|
||||||
bool is_input; /* iff input */
|
|
||||||
struct fd_struct *next; /* next on same queue */
|
|
||||||
} fd_struct;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A queue of fd_structs is empty iff the first field is NULL. In
|
* A queue of fd_structs is empty iff the first field is NULL. In
|
||||||
|
|
@ -394,14 +464,14 @@ there_are_ready_ports(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static fd_struct *
|
||||||
next_ready_port(void)
|
next_ready_fd_struct(void)
|
||||||
{
|
{
|
||||||
fd_struct *p;
|
fd_struct *p;
|
||||||
|
|
||||||
p = rmque(&ready.first, &ready);
|
p = rmque(&ready.first, &ready);
|
||||||
p->status = FD_QUIESCENT;
|
p->status = FD_QUIESCENT;
|
||||||
return (p->fd);
|
return (p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -508,6 +578,8 @@ s48_wait_for_event(long max_wait, bool is_minutes)
|
||||||
}
|
}
|
||||||
if (keyboard_interrupt_count > 0)
|
if (keyboard_interrupt_count > 0)
|
||||||
status = NO_ERRORS;
|
status = NO_ERRORS;
|
||||||
|
else if (s48_os_signal_happend ())
|
||||||
|
status = NO_ERRORS;
|
||||||
else {
|
else {
|
||||||
status = queue_ready_ports(TRUE, seconds, ticks);
|
status = queue_ready_ports(TRUE, seconds, ticks);
|
||||||
if (there_are_ready_ports())
|
if (there_are_ready_ports())
|
||||||
|
|
@ -552,8 +624,9 @@ queue_ready_ports(bool wait, long seconds, long ticks)
|
||||||
}
|
}
|
||||||
tvp = &tv;
|
tvp = &tv;
|
||||||
if (wait)
|
if (wait)
|
||||||
if (seconds == -1)
|
if (seconds == -1){
|
||||||
tvp = NULL;
|
tvp = NULL;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
tv.tv_sec = seconds;
|
tv.tv_sec = seconds;
|
||||||
tv.tv_usec = ticks * (1000000 / TICKS_PER_SECOND);
|
tv.tv_usec = ticks * (1000000 / TICKS_PER_SECOND);
|
||||||
|
|
@ -561,6 +634,9 @@ queue_ready_ports(bool wait, long seconds, long ticks)
|
||||||
else
|
else
|
||||||
timerclear(&tv);
|
timerclear(&tv);
|
||||||
while(TRUE) {
|
while(TRUE) {
|
||||||
|
if ((keyboard_interrupt_count > 0) || s48_os_signal_happend ())
|
||||||
|
return NO_ERRORS;
|
||||||
|
/* time gap */
|
||||||
left = select(limfd, &reads, &writes, &alls, tvp);
|
left = select(limfd, &reads, &writes, &alls, tvp);
|
||||||
if (left > 0) {
|
if (left > 0) {
|
||||||
fdpp = &pending.first;
|
fdpp = &pending.first;
|
||||||
|
|
@ -587,3 +663,81 @@ queue_ready_ports(bool wait, long seconds, long ticks)
|
||||||
return errno;
|
return errno;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Adds `signum' to the queue of received signals.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
queue_interrupt(int signum)
|
||||||
|
{
|
||||||
|
if (next_interrupt == INTERRUPT_QUEUE_LENGTH){
|
||||||
|
perror("Interrupt queue overflow -- report to Scheme 48 maintainers.");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
interrupt_queue[next_interrupt] = signum;
|
||||||
|
next_interrupt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* JMG: for scsh */
|
||||||
|
static void when_scsh_interrupt(int signo)
|
||||||
|
{
|
||||||
|
queue_interrupt(sig2int[signo]);
|
||||||
|
NOTE_EVENT;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This procedure is called periodically by the VM .
|
||||||
|
*
|
||||||
|
* s48_set_os_signal() is a VM procedure. The two arguments are the type
|
||||||
|
* of interrupt and one other value which can be used to return whatever
|
||||||
|
* associated information is desired. The two values, along with the
|
||||||
|
* current enabled-interrupts mask, are passed to the handler for os-signal
|
||||||
|
* interrupts.
|
||||||
|
*
|
||||||
|
* A handler can be installed by doing
|
||||||
|
(set-interrupt-handler! (enum interrupt os-signal)
|
||||||
|
(lambda (type arg enabled-interrupts)
|
||||||
|
(display type)
|
||||||
|
(newline)
|
||||||
|
(display arg)
|
||||||
|
(newline)
|
||||||
|
(display enabled-interrupts)
|
||||||
|
(newline)))
|
||||||
|
* The handler is called with all interrupts disabled. They are
|
||||||
|
* reenabled when the handler returns (or if done by hand).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns TRUE if there is a signal to be delivered up to Scheme.
|
||||||
|
* Needs no be called with interrupts blocked.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
s48_os_signal_pending(void) {
|
||||||
|
int i;
|
||||||
|
s48_value interrupt_list = S48_NULL;
|
||||||
|
block_interrupts();
|
||||||
|
|
||||||
|
if (next_interrupt == 0) {
|
||||||
|
allow_interrupts();
|
||||||
|
return FALSE; }
|
||||||
|
else {
|
||||||
|
/* turn the queue into a scheme list and preserve the order */
|
||||||
|
for (i = next_interrupt; i > 0 ; i--)
|
||||||
|
interrupt_list = s48_cons (s48_enter_fixnum (interrupt_queue [i - 1]),
|
||||||
|
interrupt_list);
|
||||||
|
s48_set_os_signals(interrupt_list);
|
||||||
|
|
||||||
|
next_interrupt = 0;
|
||||||
|
allow_interrupts();
|
||||||
|
return TRUE; }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
s48_os_signal_happend(void) {
|
||||||
|
return (next_interrupt != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,45 @@ ps_close_fd(long fd_as_long)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ps_check_fd(long fd_as_long, bool is_read, long *status)
|
||||||
|
{
|
||||||
|
int fd = (int)fd_as_long;
|
||||||
|
int ready;
|
||||||
|
|
||||||
|
struct timeval timeout;
|
||||||
|
fd_set fds;
|
||||||
|
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(fd, &fds);
|
||||||
|
timerclear(&timeout);
|
||||||
|
|
||||||
|
*status = NO_ERRORS;
|
||||||
|
|
||||||
|
while(TRUE) {
|
||||||
|
ready = select(fd + 1,
|
||||||
|
is_read ? &fds : NULL,
|
||||||
|
is_read ? NULL : &fds,
|
||||||
|
&fds,
|
||||||
|
&timeout);
|
||||||
|
if (ready == 0)
|
||||||
|
return FALSE;
|
||||||
|
else if (ready == 1)
|
||||||
|
return TRUE;
|
||||||
|
else if (errno != EINTR) {
|
||||||
|
*status = errno;
|
||||||
|
return FALSE; } }
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if successful, and FALSE otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
ps_add_pending_fd(long fd_as_long, bool is_input)
|
||||||
|
{
|
||||||
|
return s48_add_pending_fd((int) fd_as_long, is_input);
|
||||||
|
}
|
||||||
|
|
||||||
long
|
long
|
||||||
ps_read_fd(long fd_as_long, char *buffer, long max, bool waitp,
|
ps_read_fd(long fd_as_long, char *buffer, long max, bool waitp,
|
||||||
bool *eofp, bool *pending, long *status)
|
bool *eofp, bool *pending, long *status)
|
||||||
|
|
@ -172,7 +211,7 @@ long
|
||||||
ps_abort_fd_op(long fd_as_long)
|
ps_abort_fd_op(long fd_as_long)
|
||||||
{
|
{
|
||||||
int fd = (int)fd_as_long;
|
int fd = (int)fd_as_long;
|
||||||
|
fprintf(stderr, "aborting %d\n", fd);
|
||||||
if (!s48_remove_fd(fd))
|
if (!s48_remove_fd(fd))
|
||||||
fprintf(stderr, "Error: ps_abort_fd_op, no pending operation on fd %d\n",
|
fprintf(stderr, "Error: ps_abort_fd_op, no pending operation on fd %d\n",
|
||||||
fd);
|
fd);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
/* Copyright (c) 1993-1999 by Richard Kelsey and Jonathan Rees.
|
||||||
|
See file COPYING. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> /* for getenv(), etc. (POSIX?/ANSI) */
|
||||||
|
#include <string.h> /* for strncpy(), etc. (POSIX/ANSI) */
|
||||||
|
#include <pwd.h> /* for getpwnam() (POSIX.1) */
|
||||||
|
#include <unistd.h> /* for sysconf(), etc. (POSIX.1/.2)*/
|
||||||
|
#include <errno.h>
|
||||||
|
#include "sysdep.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define TRUE (0 == 0)
|
||||||
|
#define FALSE (0 == 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Expanding Unix filenames
|
||||||
|
Unix Sucks
|
||||||
|
Richard Kelsey Wed Jan 17 21:40:26 EST 1990
|
||||||
|
Later modified by others who wish to remain anonymous
|
||||||
|
|
||||||
|
Expands initial ~ and ~/ in string `name', leaving the result in `buffer'.
|
||||||
|
`buffer_len' is the length of `buffer'.
|
||||||
|
|
||||||
|
Note: strncpy(x, y, n) copies from y to x.
|
||||||
|
*/
|
||||||
|
|
||||||
|
char *s48_expand_file_name (name, buffer, buffer_len)
|
||||||
|
char *name, *buffer;
|
||||||
|
int buffer_len;
|
||||||
|
{
|
||||||
|
#define USER_NAME_SIZE 256
|
||||||
|
char *dir, *p, user_name[USER_NAME_SIZE];
|
||||||
|
struct passwd *user_data;
|
||||||
|
int dir_len, i;
|
||||||
|
extern char *getenv();
|
||||||
|
int name_len = strlen(name);
|
||||||
|
|
||||||
|
dir = 0;
|
||||||
|
|
||||||
|
if (name[0] == '~') {
|
||||||
|
name++; name_len--;
|
||||||
|
|
||||||
|
if (name[0] == '/' || name[0] == 0) {
|
||||||
|
dir = getenv("HOME"); }
|
||||||
|
|
||||||
|
else {
|
||||||
|
for (i = 0, p = name; i < name_len && *p != '/'; i++, p++)
|
||||||
|
if (i > (USER_NAME_SIZE - 2)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ns48_expand_file_name: user name longer than %d characters\n",
|
||||||
|
USER_NAME_SIZE - 3);
|
||||||
|
return(NULL); };
|
||||||
|
strncpy(user_name, name, i);
|
||||||
|
user_name[i] = 0;
|
||||||
|
user_data = getpwnam(user_name);
|
||||||
|
if (!user_data) {
|
||||||
|
fprintf(stderr, "\ns48_expand_file_name: unknown user \"%s\"\n",
|
||||||
|
user_name);
|
||||||
|
return(NULL); };
|
||||||
|
name_len -= i;
|
||||||
|
name = p;
|
||||||
|
dir = user_data->pw_dir; } }
|
||||||
|
|
||||||
|
else if (name[0] == '$') {
|
||||||
|
name++; name_len--;
|
||||||
|
|
||||||
|
for (i = 0, p = name; i < name_len && *p != '/'; i++, p++)
|
||||||
|
if (i > (USER_NAME_SIZE - 2)) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\ns48_expand_file_name: environment variable longer than %d characters\n",
|
||||||
|
USER_NAME_SIZE - 3);
|
||||||
|
return(NULL); };
|
||||||
|
strncpy(user_name, name, i);
|
||||||
|
user_name[i] = 0;
|
||||||
|
|
||||||
|
name_len -= i;
|
||||||
|
name = p;
|
||||||
|
dir = getenv(user_name); }
|
||||||
|
|
||||||
|
if (dir) {
|
||||||
|
dir_len = strlen(dir);
|
||||||
|
if ((name_len + dir_len + 1) > buffer_len) {
|
||||||
|
fprintf(stderr, "\ns48_expand_file_name: supplied buffer is too small\n");
|
||||||
|
return(NULL); };
|
||||||
|
strncpy(buffer, dir, dir_len);
|
||||||
|
strncpy(buffer + dir_len, name, name_len);
|
||||||
|
buffer[name_len + dir_len] = 0; }
|
||||||
|
|
||||||
|
else {
|
||||||
|
if ((name_len + 1) > buffer_len) {
|
||||||
|
fprintf(stderr, "\ns48_expand_file_name: supplied buffer is too small\n");
|
||||||
|
return(NULL); };
|
||||||
|
strncpy(buffer, name, name_len);
|
||||||
|
buffer[name_len] = 0; }
|
||||||
|
|
||||||
|
return(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test routine
|
||||||
|
main(argc, argv)
|
||||||
|
int argc;
|
||||||
|
char *argv[];
|
||||||
|
{
|
||||||
|
char buffer[32];
|
||||||
|
s48_expand_file_name(argv[1], buffer, 32);
|
||||||
|
printf("%s\n", buffer);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* Driver loop for tail-recursive calls */
|
||||||
|
|
||||||
|
long s48_return_value;
|
||||||
|
|
||||||
|
long
|
||||||
|
s48_run_machine(long (*proc) (void))
|
||||||
|
{
|
||||||
|
while (proc != 0)
|
||||||
|
proc = (long (*) (void)) (*proc)();
|
||||||
|
return s48_return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char *
|
||||||
|
ps_error_string(long the_errno)
|
||||||
|
{
|
||||||
|
return((unsigned char *)strerror(the_errno));
|
||||||
|
}
|
||||||
|
|
@ -36,9 +36,23 @@ static s48_value s48_socket(s48_value server_p),
|
||||||
s48_value input_p),
|
s48_value input_p),
|
||||||
s48_get_host_name(void);
|
s48_get_host_name(void);
|
||||||
|
|
||||||
|
s48_value s48_add_pending_channel (s48_value channel)
|
||||||
|
{
|
||||||
|
int socket_fd;
|
||||||
|
|
||||||
|
S48_CHECK_CHANNEL(channel);
|
||||||
|
socket_fd = S48_UNSAFE_EXTRACT_FIXNUM(S48_UNSAFE_CHANNEL_OS_INDEX(channel));
|
||||||
|
|
||||||
|
if (! s48_add_pending_fd(socket_fd, 1)) /* 1 for: yes, is input */
|
||||||
|
s48_raise_out_of_memory_error();
|
||||||
|
|
||||||
|
return S48_UNSPECIFIC;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install all exported functions in Scheme48.
|
* Install all exported functions in Scheme48.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
s48_init_socket(void)
|
s48_init_socket(void)
|
||||||
{
|
{
|
||||||
|
|
@ -50,6 +64,7 @@ s48_init_socket(void)
|
||||||
S48_EXPORT_FUNCTION(s48_connect);
|
S48_EXPORT_FUNCTION(s48_connect);
|
||||||
S48_EXPORT_FUNCTION(s48_close_socket_half);
|
S48_EXPORT_FUNCTION(s48_close_socket_half);
|
||||||
S48_EXPORT_FUNCTION(s48_get_host_name);
|
S48_EXPORT_FUNCTION(s48_get_host_name);
|
||||||
|
S48_EXPORT_FUNCTION(s48_add_pending_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -235,7 +250,7 @@ s48_accept(s48_value channel)
|
||||||
* and return #F to tell the Scheme procedure to wait.
|
* and return #F to tell the Scheme procedure to wait.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((errno != EWOULDBLOCK) && (errno != EINTR) && (errno == EAGAIN))
|
if ((errno != EWOULDBLOCK) && (errno != EINTR) && (errno != EAGAIN))
|
||||||
s48_raise_os_error(errno);
|
s48_raise_os_error(errno);
|
||||||
|
|
||||||
if (! s48_add_pending_fd(socket_fd, TRUE))
|
if (! s48_add_pending_fd(socket_fd, TRUE))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#include "c/scheme48.h"
|
||||||
|
|
||||||
|
long
|
||||||
|
frog(long arg_count, long *args)
|
||||||
|
{
|
||||||
|
long i, res;
|
||||||
|
|
||||||
|
for (i = 0, res = s48_enter_integer(-100); i < arg_count; res += args[i], i++);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
|
||||||
|
#define S48_WRITE_BARRIER(stob, address, value) ((void)0)
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
cig
|
||||||
|
cig.image
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,48 @@
|
||||||
|
#!/bin/sh -
|
||||||
|
|
||||||
|
binary=$1
|
||||||
|
shift
|
||||||
|
|
||||||
|
if [ `echo $binary | wc -c` -gt 28 ] ; then
|
||||||
|
echo "#!/bin/sh -"
|
||||||
|
echo exec $binary $* -i '"$0"' '"$@"'
|
||||||
|
|
||||||
|
elif [ $# -gt 0 ] ; then
|
||||||
|
echo '#!'$binary \\
|
||||||
|
echo $* -i
|
||||||
|
|
||||||
|
else echo '#!'$binary -i
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec cat
|
||||||
|
|
||||||
|
|
||||||
|
# This program reads an S48 image from stdin and turns it into
|
||||||
|
# an executable by prepending a #! prefix. The vm and its
|
||||||
|
# args are passed to this program on the command line.
|
||||||
|
#
|
||||||
|
# If the vm binary is 27 chars or less, then we can directly
|
||||||
|
# execute the vm with one of these scripts:
|
||||||
|
# No args:
|
||||||
|
# image2script /usr/local/bin/svm <image
|
||||||
|
# outputs this script:
|
||||||
|
# #!/usr/local/bin/svm -i
|
||||||
|
# ...image bits follow...
|
||||||
|
#
|
||||||
|
# Args:
|
||||||
|
# image2script /usr/bin/svm -h 4000000 -o /usr/bin/svm <image
|
||||||
|
# outputs this script:
|
||||||
|
# #!/usr/bin/svm \
|
||||||
|
# -h 4000000 -o /usr/bin/svm -i
|
||||||
|
# ...image bits follow...
|
||||||
|
#
|
||||||
|
# The exec system call won't handle the #! line if it contains more than
|
||||||
|
# 32 chars, so if the vm binary is over 28 chars, we have to use a /bin/sh
|
||||||
|
# trampoline.
|
||||||
|
# image2script /user1/lecturer/shivers/vc/scsh/s48/lib/svm -h 4000000 < ...
|
||||||
|
# outputs this script:
|
||||||
|
# #!/bin/sh -
|
||||||
|
# exec /user1/lecturer/shivers/vc/scsh/s48/lib/svm -h 4000000 -i $0 $*
|
||||||
|
# ...image bits follow...
|
||||||
|
#
|
||||||
|
# -Olin
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
/* This is an Scheme48/C interface file,
|
||||||
|
** automatically generated by a hacked version of cig 3.0.
|
||||||
|
step 4
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h> /* For malloc. */
|
||||||
|
#include "libcig.h"
|
||||||
|
|
||||||
|
s48_value df_strlen_or_false(s48_value g1)
|
||||||
|
{
|
||||||
|
extern s48_value strlen_or_false(const char * );
|
||||||
|
s48_value ret1 = S48_FALSE;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
s48_value r1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(ret1);
|
||||||
|
r1 = strlen_or_false((const char * )AlienVal(g1));
|
||||||
|
ret1 = r1;
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return ret1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value df_cstring_nullp(s48_value g1)
|
||||||
|
{
|
||||||
|
extern int cstring_nullp(const char * );
|
||||||
|
s48_value ret1 = S48_FALSE;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
int r1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(ret1);
|
||||||
|
r1 = cstring_nullp((const char * )AlienVal(g1));
|
||||||
|
ret1 = ENTER_BOOLEAN(r1);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return ret1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value df_c2scheme_strcpy_free(s48_value g1, s48_value g2)
|
||||||
|
{
|
||||||
|
extern int c2scheme_strcpy_free(s48_value , char* );
|
||||||
|
s48_value ret1 = S48_FALSE;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
int r1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(ret1);
|
||||||
|
r1 = c2scheme_strcpy_free(g1, (char* )AlienVal(g2));
|
||||||
|
ret1 = ENTER_BOOLEAN(r1);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return ret1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value df_c2scheme_strcpy(s48_value g1, s48_value g2)
|
||||||
|
{
|
||||||
|
extern int c2scheme_strcpy(s48_value , char* );
|
||||||
|
s48_value ret1 = S48_FALSE;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
int r1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(ret1);
|
||||||
|
r1 = c2scheme_strcpy(g1, (char* )AlienVal(g2));
|
||||||
|
ret1 = ENTER_BOOLEAN(r1);
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return ret1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value df_c_veclen(s48_value g1)
|
||||||
|
{
|
||||||
|
extern s48_value c_veclen(long* );
|
||||||
|
s48_value ret1 = S48_FALSE;
|
||||||
|
S48_DECLARE_GC_PROTECT(1);
|
||||||
|
s48_value r1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
S48_GC_PROTECT_1(ret1);
|
||||||
|
r1 = c_veclen((long* )AlienVal(g1));
|
||||||
|
ret1 = r1;
|
||||||
|
S48_GC_UNPROTECT();
|
||||||
|
return ret1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value df_free(s48_value g1)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
free((void* )AlienVal(g1));
|
||||||
|
return S48_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
s48_value df_set_strvec_carriers(s48_value g1, s48_value g2)
|
||||||
|
{
|
||||||
|
extern void set_strvec_carriers(s48_value , char** );
|
||||||
|
|
||||||
|
|
||||||
|
set_strvec_carriers(g1, (char** )AlienVal(g2));
|
||||||
|
return S48_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void s48_init_cig(void)
|
||||||
|
{
|
||||||
|
S48_EXPORT_FUNCTION(df_strlen_or_false);
|
||||||
|
S48_EXPORT_FUNCTION(df_cstring_nullp);
|
||||||
|
S48_EXPORT_FUNCTION(df_c2scheme_strcpy_free);
|
||||||
|
S48_EXPORT_FUNCTION(df_c2scheme_strcpy);
|
||||||
|
S48_EXPORT_FUNCTION(df_c_veclen);
|
||||||
|
S48_EXPORT_FUNCTION(df_free);
|
||||||
|
S48_EXPORT_FUNCTION(df_set_strvec_carriers);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "scheme48.h"
|
||||||
|
|
||||||
|
/* StobData is used by fdports.c. It should be changed over to STOB_REF
|
||||||
|
** by removing the extra indirection. */
|
||||||
|
#define StobData(x) (S48_ADDRESS_AFTER_HEADER(x, s48_value))
|
||||||
|
|
||||||
|
#define IsChar(x) ((((long) x) & 0xff) == S48_CHAR)
|
||||||
|
/* JMG: untested !! */
|
||||||
|
|
||||||
|
#define StrByte(x, i) ((i) + S48_ADDRESS_AFTER_HEADER((x), char))
|
||||||
|
#define cig_string_body(x) (S48_ADDRESS_AFTER_HEADER((x), char))
|
||||||
|
|
||||||
|
#define AlienVal(x) (S48_STOB_REF((x),0))
|
||||||
|
/* JMG: no () around this, because it's a do..while(0) */
|
||||||
|
#define SetAlienVal(x, v) S48_STOB_SET((x), 0, (v))
|
||||||
|
|
||||||
|
/* JMG: some hacks to leave to old sources untouched */
|
||||||
|
#define ENTER_BOOLEAN(x) (x ? S48_TRUE : S48_FALSE)
|
||||||
|
#define EXTRACT_BOOLEAN(x) ((x==S48_TRUE) ? 1 : 0)
|
||||||
|
/* #define ENTER_FIXNUM(x) (s48_enter_fixnum(x)) */
|
||||||
|
/* #define SCHFALSE S48_FALSE */
|
||||||
|
|
||||||
|
extern char *scheme2c_strcpy(s48_value sstr);
|
||||||
|
|
||||||
|
extern s48_value strlen_or_false(const char *s);
|
||||||
|
|
||||||
|
extern char *copystring_or_die(const char *);
|
||||||
|
extern char *copystring(char *, const char *);
|
||||||
|
|
||||||
|
extern s48_value strlen_or_false(const char *);
|
||||||
|
|
||||||
|
extern void cig_check_nargs(int arity, int nargs, const char *fn);
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
;;; (DEFINE-FOREIGN ...) forms are expanded by Cig into Scheme stubs.
|
||||||
|
;;; These stubs reference some support procedures to rep-convert the
|
||||||
|
;;; standard reps (e.g., string). This structure provides these support
|
||||||
|
;;; procedures.
|
||||||
|
;;;
|
||||||
|
;;; We export three kinds of things:
|
||||||
|
;;; - Type predicates that aren't in the R4RS env (e.g., FIXNUM?).
|
||||||
|
;;; - Carrier makers for making boxes to return things in.
|
||||||
|
;;; - Scheme-side rep-converters for return values.
|
||||||
|
|
||||||
|
(define-structure cig-aux
|
||||||
|
(export cstring-null?
|
||||||
|
C->scheme-string
|
||||||
|
C->scheme-string-w/len
|
||||||
|
C->scheme-string-w/len-no-free
|
||||||
|
C-string-vec->Scheme&free
|
||||||
|
C-string-vec->Scheme ; Bogus, because clients not reentrant.
|
||||||
|
string-carrier->string
|
||||||
|
string-carrier->string-no-free
|
||||||
|
fixnum?
|
||||||
|
make-string-carrier
|
||||||
|
make-alien
|
||||||
|
alien?
|
||||||
|
)
|
||||||
|
(open scheme code-vectors define-foreign-syntax)
|
||||||
|
|
||||||
|
(begin
|
||||||
|
(define min-fixnum (- (expt 2 29)))
|
||||||
|
(define max-fixnum (- (expt 2 29) 1))
|
||||||
|
(define (fixnum? x) (and (integer? x) (<= min-fixnum x max-fixnum)))
|
||||||
|
|
||||||
|
;; Internal utility.
|
||||||
|
(define (mapv! f v)
|
||||||
|
(let ((len (vector-length v)))
|
||||||
|
(do ((i 0 (+ i 1)))
|
||||||
|
((= i len) v)
|
||||||
|
(vector-set! v i (f (vector-ref v i))))))
|
||||||
|
|
||||||
|
;; Make a carrier for returning strings.
|
||||||
|
;; It holds a raw C string and a fixnum giving the length of the string.
|
||||||
|
(define (make-string-carrier) (cons (make-alien) 0))
|
||||||
|
|
||||||
|
(define (make-alien) (make-code-vector 4 0))
|
||||||
|
(define (alien? x) (and (code-vector? x) (= 4 (code-vector-length x)))) ; BOGUS
|
||||||
|
|
||||||
|
|
||||||
|
;;; C/Scheme string and vector conversion
|
||||||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
|
;;; Generally speaking, in the following routines,
|
||||||
|
;;; a NULL C string param causes a function to return #f.
|
||||||
|
(foreign-init-name "cig")
|
||||||
|
|
||||||
|
(define-foreign %cstring-length-or-false
|
||||||
|
(strlen_or_false ((C "const char * ~a") cstr))
|
||||||
|
desc)
|
||||||
|
|
||||||
|
(define-foreign cstring-null?
|
||||||
|
(cstring_nullp ((C "const char * ~a") cstr))
|
||||||
|
bool)
|
||||||
|
|
||||||
|
(define-foreign %copy-c-string&free
|
||||||
|
(c2scheme_strcpy_free (string-desc sstr) ((C char*) cstr))
|
||||||
|
bool)
|
||||||
|
|
||||||
|
(define-foreign %copy-c-string
|
||||||
|
(c2scheme_strcpy (string-desc sstr) ((C char*) cstr))
|
||||||
|
bool)
|
||||||
|
|
||||||
|
(define (C->scheme-string cstr)
|
||||||
|
(cond ((%cstring-length-or-false cstr)
|
||||||
|
=> (lambda (strlen)
|
||||||
|
(let ((str (make-string strlen)))
|
||||||
|
(%copy-c-string&free str cstr)
|
||||||
|
str)))
|
||||||
|
(else #f)))
|
||||||
|
|
||||||
|
(define (C->scheme-string-w/len cstr len)
|
||||||
|
(and (integer? len)
|
||||||
|
(let ((str (make-string len)))
|
||||||
|
(%copy-c-string&free str cstr)
|
||||||
|
str)))
|
||||||
|
|
||||||
|
(define (C->scheme-string-w/len-no-free cstr len)
|
||||||
|
(and (integer? len)
|
||||||
|
(let ((str (make-string len)))
|
||||||
|
(%copy-c-string str cstr)
|
||||||
|
str)))
|
||||||
|
|
||||||
|
(define (string-carrier->string carrier)
|
||||||
|
(C->scheme-string-w/len (car carrier) (cdr carrier)))
|
||||||
|
|
||||||
|
(define (string-carrier->string-no-free carrier)
|
||||||
|
(C->scheme-string-w/len-no-free (car carrier) (cdr carrier)))
|
||||||
|
|
||||||
|
;;; Return the length of a null-terminated C word vector.
|
||||||
|
;;; Does not count the null word as part of the length.
|
||||||
|
;;; If vector is NULL, returns #f.
|
||||||
|
|
||||||
|
(define-foreign %c-veclen-or-false
|
||||||
|
(c_veclen ((C long*) c-vec))
|
||||||
|
desc) ; integer or #f if arg is NULL.
|
||||||
|
|
||||||
|
;;; CVEC is a C vector of char* strings, length VECLEN.
|
||||||
|
;;; This procedure converts a C vector of strings into a Scheme vector of
|
||||||
|
;;; strings. The C vector and its strings are all assumed to come from
|
||||||
|
;;; the malloc heap; they are returned to the heap when the rep-conversion
|
||||||
|
;;; is done.
|
||||||
|
;;;
|
||||||
|
;;; Hack: if VECLEN is #f, CVEC is assumed to be NULL terminated, and
|
||||||
|
;;; its length is calculated thusly.
|
||||||
|
|
||||||
|
(define (C-string-vec->Scheme&free cvec veclen)
|
||||||
|
(let ((vec (make-vector (or veclen (%c-veclen-or-false cvec) 0))))
|
||||||
|
(mapv! (lambda (ignore) (make-string-carrier)) vec)
|
||||||
|
(%set-string-vector-carriers! vec cvec)
|
||||||
|
(C-free cvec)
|
||||||
|
(mapv! string-carrier->string vec)))
|
||||||
|
|
||||||
|
(define (C-string-vec->Scheme cvec veclen) ; No free.
|
||||||
|
(let ((vec (make-vector (or veclen (%c-veclen-or-false cvec) 0))))
|
||||||
|
(mapv! (lambda (ignore) (make-string-carrier)) vec)
|
||||||
|
(%set-string-vector-carriers! vec cvec)
|
||||||
|
(mapv! string-carrier->string-no-free vec)))
|
||||||
|
|
||||||
|
|
||||||
|
(define-foreign C-free (free ((C void*) ptr)) no-declare ; for SunOS 4.x
|
||||||
|
ignore)
|
||||||
|
|
||||||
|
(define-foreign %set-string-vector-carriers!
|
||||||
|
(set_strvec_carriers (vector-desc svec) ((C char**) cvec))
|
||||||
|
ignore)
|
||||||
|
|
||||||
|
)) ; egakcap
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,163 @@
|
||||||
|
/* Generic routines for Scheme48/C interfacing -- mostly for converting
|
||||||
|
** strings and null-terminated vectors back and forth.
|
||||||
|
** Copyright (c) 1993 by Olin Shivers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "libcig.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#define Malloc(type,n) ((type *) malloc(sizeof(type)*(n)))
|
||||||
|
#define Free(p) (free((char *)(p)))
|
||||||
|
|
||||||
|
/* (c2scheme_strcpy dest_scheme_string source_C_string)
|
||||||
|
** Copies C string's chars into Scheme string. Return #t.
|
||||||
|
** If C string is NULL, do nothing and return #f.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int c2scheme_strcpy(s48_value sstr, const char *cstr)
|
||||||
|
{
|
||||||
|
if( cstr ) {
|
||||||
|
strncpy( (char*) StobData(sstr), cstr, S48_STRING_LENGTH(sstr) );
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Same as above, but free the C string when we are done. */
|
||||||
|
int c2scheme_strcpy_free(s48_value sstr, const char *cstr)
|
||||||
|
{
|
||||||
|
if( cstr ) {
|
||||||
|
strncpy( (char*) StobData(sstr), cstr, S48_STRING_LENGTH(sstr) );
|
||||||
|
Free(cstr);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *scheme2c_strcpy(s48_value sstr)
|
||||||
|
{
|
||||||
|
char *result;
|
||||||
|
int slen;
|
||||||
|
|
||||||
|
slen = S48_STRING_LENGTH(sstr);
|
||||||
|
result = Malloc(char, slen+1);
|
||||||
|
|
||||||
|
if( result == NULL ) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Fatal error: C stub tried to copy Scheme string,\n"
|
||||||
|
"but malloc failed on arg 0x%x, errno %d.\n",
|
||||||
|
sstr, errno);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(result, cig_string_body(sstr), slen);
|
||||||
|
result[slen] = '\000';
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* One arg, a zero-terminated C word vec. Returns length.
|
||||||
|
** The terminating null is not counted. Returns #f on NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
s48_value c_veclen(const long *vec)
|
||||||
|
{
|
||||||
|
const long *vptr = vec;
|
||||||
|
if( !vptr ) return S48_FALSE;
|
||||||
|
while( *vptr ) vptr++;
|
||||||
|
return s48_enter_fixnum(vptr - vec);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Copy string from into string to. If to is NULL, malloc a fresh string
|
||||||
|
** (if the malloc loses, return NULL).
|
||||||
|
** If from is NULL, then
|
||||||
|
** - if to is NULL, do nothing and return NULL.
|
||||||
|
** - Otherwise, deposit a single nul byte.
|
||||||
|
** Under normal conditions, this routine returns the destination string.
|
||||||
|
**
|
||||||
|
** The little boundary cases of this procedure are a study in obfuscation
|
||||||
|
** because C doesn't have a reasonable string data type. Give me a break.
|
||||||
|
*/
|
||||||
|
char *copystring(char *to, const char *from)
|
||||||
|
{
|
||||||
|
if( from ) {
|
||||||
|
int slen = strlen(from)+1;
|
||||||
|
if( !to && !(to = Malloc(char, slen)) ) return NULL;
|
||||||
|
else return memcpy(to, from, slen);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
return to ? *to = '\000', to : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* As in copystring, but if malloc loses, print out an error msg and croak. */
|
||||||
|
char *copystring_or_die(const char *str ) /* Note: NULL -> NULL. */
|
||||||
|
{
|
||||||
|
if( str ) {
|
||||||
|
int len = strlen(str)+1;
|
||||||
|
char *new_str = Malloc(char, len);
|
||||||
|
if( ! new_str ) {
|
||||||
|
fprintf(stderr, "copystring: Malloc failed.\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return memcpy(new_str, str, len);
|
||||||
|
}
|
||||||
|
else return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cstring_nullp( const char *s ) { return ! s; }
|
||||||
|
|
||||||
|
s48_value strlen_or_false(const char *s)
|
||||||
|
{ return s ? s48_enter_fixnum(strlen(s)) : S48_FALSE; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* svec is a Scheme vector of C string carriers. Scan over the C strings
|
||||||
|
** in cvec, and initialise the corresponding string carriers in svec.
|
||||||
|
*/
|
||||||
|
void set_strvec_carriers(s48_value svec, char const * const * cvec)
|
||||||
|
{
|
||||||
|
int svec_len = S48_VECTOR_LENGTH(svec);
|
||||||
|
char const * const * cv = cvec;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
/* JMG: now using normal array access, instead of pointer++ on a s48_value */
|
||||||
|
for(; svec_len > 0; i++, cv++, svec_len-- ) {
|
||||||
|
s48_value carrier, alien;
|
||||||
|
int strl;
|
||||||
|
|
||||||
|
/* *sv is a (cons (make-alien <c-string>) <string-length>). */
|
||||||
|
carrier = S48_VECTOR_REF(svec,i);
|
||||||
|
alien = S48_CAR(carrier);
|
||||||
|
strl = strlen(*cv);
|
||||||
|
S48_SET_CDR(carrier, s48_enter_fixnum(strl));
|
||||||
|
SetAlienVal(alien, (long) *cv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helper function for arg checking. Why bother, actually? */
|
||||||
|
void cig_check_nargs(int arity, int nargs, const char *fn)
|
||||||
|
{
|
||||||
|
if( arity != nargs ) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Cig fatal error (%s) -- C stub expected %d arg%s, "
|
||||||
|
"but got %d.\n",
|
||||||
|
fn, arity, (arity == 1) ? "" : "s", nargs);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* void ciginit(){ */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_strlen_or_false); */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_c_veclen); */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_set_strvec_carriers); */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_c2scheme_strcpy_free); */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_cstring_nullp); */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_free); */
|
||||||
|
/* S48_EXPORT_FUNCTION (df_c2scheme_strcpy); */
|
||||||
|
/* } */
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
330
configure.in
330
configure.in
|
|
@ -3,26 +3,7 @@ dnl
|
||||||
dnl We might want AC_WORDS_BIGENDIAN in the future.
|
dnl We might want AC_WORDS_BIGENDIAN in the future.
|
||||||
dnl We might want AC_CHAR_UNSIGNED in the future.
|
dnl We might want AC_CHAR_UNSIGNED in the future.
|
||||||
dnl
|
dnl
|
||||||
dnl The -cckr (K&R) flag is for the IRIX C compiler. If this is left
|
|
||||||
dnl out, scheme48vm.c breaks because the rather pedantic SGI compiler
|
|
||||||
dnl decides that a char is not the same thing as an unsigned char.
|
|
||||||
dnl - Bryan O'Sullivan 3/94
|
|
||||||
dnl Note, this test didn't work correctly on Sun's which take -cckr as a
|
|
||||||
dnl synonym for -c. (HCC)
|
|
||||||
define(S48_CFLAG_CKR, [dnl
|
|
||||||
if test "z$GCC" = z; then
|
|
||||||
AC_MSG_CHECKING([-cckr])
|
|
||||||
oldCFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS -cckr"
|
|
||||||
AC_TRY_RUN([int main() { return 0;}],
|
|
||||||
[AC_MSG_RESULT(yes)],
|
|
||||||
[AC_MSG_RESULT(no)
|
|
||||||
CFLAGS="$oldCFLAGS"],
|
|
||||||
[AC_MSG_RESULT(no)
|
|
||||||
CFLAGS="$oldCFLAGS"])
|
|
||||||
fi
|
|
||||||
])dnl
|
|
||||||
dnl
|
|
||||||
define(S48_POSIX_LIBC, [dnl
|
define(S48_POSIX_LIBC, [dnl
|
||||||
echo checking for RISC/OS POSIX library lossage
|
echo checking for RISC/OS POSIX library lossage
|
||||||
if test -f /usr/posix/usr/lib/libc.a; then
|
if test -f /usr/posix/usr/lib/libc.a; then
|
||||||
|
|
@ -64,24 +45,254 @@ dnl
|
||||||
define(S48_USCORE, [dnl
|
define(S48_USCORE, [dnl
|
||||||
AC_MSG_CHECKING([underscore before symbols])
|
AC_MSG_CHECKING([underscore before symbols])
|
||||||
echo 'main() { return 0; } fnord() {}' >conftest.c
|
echo 'main() { return 0; } fnord() {}' >conftest.c
|
||||||
if ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} conftest.c ${LIBS} &&
|
if ${CC} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o a.out conftest.c ${LIBS} &&
|
||||||
nm a.out | grep _fnord >/dev/null; then
|
nm a.out | grep _fnord >/dev/null; then
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
AC_DEFINE(USCORE)
|
AC_DEFINE(USCORE, 1, [Define to 1 if symbols start with _])
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT([no])
|
AC_MSG_RESULT([no])
|
||||||
fi
|
fi
|
||||||
rm -f conftest.c a.out
|
rm -f conftest.c a.out
|
||||||
])dnl
|
])dnl
|
||||||
dnl
|
dnl
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
AC_DEFUN(SCSH_TZNAME,[
|
||||||
|
AC_MSG_CHECKING(for tzname)
|
||||||
|
AC_CACHE_VAL(scsh_cv_tzname,[
|
||||||
|
AC_TRY_COMPILE([#include <time.h>],
|
||||||
|
[return (int) tzname;],
|
||||||
|
scsh_cv_tzname=yes,
|
||||||
|
scsh_cv_tzname=no)])
|
||||||
|
AC_MSG_RESULT($scsh_cv_tzname)
|
||||||
|
if test $scsh_cv_tzname = yes; then
|
||||||
|
AC_DEFINE(HAVE_TZNAME)
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
AC_DEFUN(SCSH_ELF, [
|
||||||
|
AC_MSG_CHECKING(for ELF)
|
||||||
|
AC_CACHE_VAL(scsh_cv_elf,[
|
||||||
|
touch conftest.c
|
||||||
|
if ${CC} -v -o a.out conftest.c 2>&1 | grep -q __ELF__ ; then
|
||||||
|
scsh_cv_elf=yes
|
||||||
|
else
|
||||||
|
scsh_cv_elf=no
|
||||||
|
fi])
|
||||||
|
AC_MSG_RESULT($scsh_cv_elf)
|
||||||
|
if test $scsh_cv_elf = yes; then
|
||||||
|
LDFLAGS=-rdynamic
|
||||||
|
fi
|
||||||
|
rm -f conftest.c a.out
|
||||||
|
])
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
AC_DEFUN(SCSH_SIG_NRS, [
|
||||||
|
AC_MSG_RESULT([defining signal constants])
|
||||||
|
${CC} -o scsh_aux scsh/scsh_aux.c
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_1, `./scsh_aux 1`, [scsh interrupt for signal 1])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_2, `./scsh_aux 2`, [scsh interrupt for signal 2])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_3, `./scsh_aux 3`, [scsh interrupt for signal 3])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_4, `./scsh_aux 4`, [scsh interrupt for signal 4])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_5, `./scsh_aux 5`, [scsh interrupt for signal 5])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_6, `./scsh_aux 6`, [scsh interrupt for signal 6])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_7, `./scsh_aux 7`, [scsh interrupt for signal 7])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_8, `./scsh_aux 8`, [scsh interrupt for signal 8])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_9, `./scsh_aux 9`, [scsh interrupt for signal 9])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_10, `./scsh_aux 10`, [scsh interrupt for signal 10])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_11, `./scsh_aux 11`, [scsh interrupt for signal 11])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_12, `./scsh_aux 12`, [scsh interrupt for signal 12])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_13, `./scsh_aux 13`, [scsh interrupt for signal 13])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_14, `./scsh_aux 14`, [scsh interrupt for signal 14])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_15, `./scsh_aux 15`, [scsh interrupt for signal 15])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_16, `./scsh_aux 16`, [scsh interrupt for signal 16])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_17, `./scsh_aux 17`, [scsh interrupt for signal 17])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_18, `./scsh_aux 18`, [scsh interrupt for signal 18])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_19, `./scsh_aux 19`, [scsh interrupt for signal 19])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_20, `./scsh_aux 20`, [scsh interrupt for signal 20])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_21, `./scsh_aux 21`, [scsh interrupt for signal 21])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_22, `./scsh_aux 22`, [scsh interrupt for signal 22])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_23, `./scsh_aux 23`, [scsh interrupt for signal 23])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_24, `./scsh_aux 24`, [scsh interrupt for signal 24])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_25, `./scsh_aux 25`, [scsh interrupt for signal 25])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_26, `./scsh_aux 26`, [scsh interrupt for signal 26])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_27, `./scsh_aux 27`, [scsh interrupt for signal 27])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_28, `./scsh_aux 28`, [scsh interrupt for signal 28])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_29, `./scsh_aux 29`, [scsh interrupt for signal 29])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_30, `./scsh_aux 30`, [scsh interrupt for signal 30])
|
||||||
|
AC_DEFINE_UNQUOTED(SIGNR_31, `./scsh_aux 31`, [scsh interrupt for signal 31])
|
||||||
|
rm -f scsh_aux scsh_aux.exe
|
||||||
|
])
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
AC_DEFUN(SCSH_LINUX_STATIC_DEBUG, [
|
||||||
|
case "$host" in
|
||||||
|
*-*-linux* )
|
||||||
|
AC_MSG_CHECKING(for broken Linux that needs -static with -g)
|
||||||
|
AC_CACHE_VAL(scsh_cv_linux_static_debug,[
|
||||||
|
AC_TRY_LINK([],
|
||||||
|
[],
|
||||||
|
scsh_cv_linux_static_debug=no,
|
||||||
|
scsh_cv_linux_static_debug=yes)])
|
||||||
|
AC_MSG_RESULT($scsh_cv_linux_static_debug)
|
||||||
|
if test $scsh_cv_linux_static_debug = yes; then
|
||||||
|
LDFLAGS="-static ${LDFLAGS}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
AC_DEFUN(SCSH_CONST_SYS_ERRLIST,[
|
||||||
|
AC_MSG_CHECKING(for const sys_errlist)
|
||||||
|
AC_CACHE_VAL(scsh_cv_const_sys_errlist,[
|
||||||
|
AC_TRY_COMPILE([#include <errno.h>
|
||||||
|
#include <unistd.h>],
|
||||||
|
[const extern char *sys_errlist[];],
|
||||||
|
scsh_cv_const_sys_errlist=yes,
|
||||||
|
scsh_cv_const_sys_errlist=no)])
|
||||||
|
AC_MSG_RESULT($scsh_cv_const_sys_errlist)
|
||||||
|
if test $scsh_cv_const_sys_errlist = yes; then
|
||||||
|
AC_DEFINE(HAVE_CONST_SYS_ERRLIST, 1, [const char* sys_errlist])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
|
AC_DEFUN(SCSH_SOCKLEN_T,[
|
||||||
|
AC_MSG_CHECKING(for socklen_t)
|
||||||
|
AC_TRY_COMPILE([#include <sys/socket.h>
|
||||||
|
socklen_t x;
|
||||||
|
],[],[AC_MSG_RESULT(yes)],[
|
||||||
|
AC_TRY_COMPILE([#include <sys/socket.h>
|
||||||
|
int accept (int, struct sockaddr *, size_t *);
|
||||||
|
],[],[
|
||||||
|
AC_MSG_RESULT(size_t)
|
||||||
|
AC_DEFINE(socklen_t,
|
||||||
|
size_t, [Define to type of socklen_t])], [
|
||||||
|
AC_MSG_RESULT(int)
|
||||||
|
AC_DEFINE(socklen_t,int)])])
|
||||||
|
])
|
||||||
|
dnl -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||||
AC_INIT(c/scheme48vm.c)
|
AC_INIT(c/scheme48vm.c)
|
||||||
AC_CONFIG_HEADER(c/sysdep.h)
|
AC_CONFIG_HEADER(c/sysdep.h)
|
||||||
|
AC_CANONICAL_HOST
|
||||||
S48_PROG_CC
|
S48_PROG_CC
|
||||||
|
SCSH_SIG_NRS
|
||||||
AC_ISC_POSIX
|
AC_ISC_POSIX
|
||||||
|
SCSH_LINUX_STATIC_DEBUG
|
||||||
dnl set the cross-compile flag before we try anything.
|
dnl set the cross-compile flag before we try anything.
|
||||||
AC_TRY_RUN([int main() { return 0;}], [], [], [true])
|
AC_TRY_RUN([int main() { return 0;}], [], [], [true])
|
||||||
S48_CFLAG_CKR
|
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
AC_PROG_RANLIB
|
||||||
|
AC_C_CONST
|
||||||
|
|
||||||
|
AC_C_BIGENDIAN
|
||||||
|
if test $ac_cv_c_bigendian = no ; then
|
||||||
|
ENDIAN=little
|
||||||
|
else
|
||||||
|
ENDIAN=big
|
||||||
|
fi
|
||||||
|
|
||||||
|
AR=${AR-"ar cq"}
|
||||||
|
TMPDIR=${TMPDIR-"/var/tmp"}
|
||||||
|
case "$host" in
|
||||||
|
## CX/UX
|
||||||
|
m88k-harris-cxux* )
|
||||||
|
dir=cxux
|
||||||
|
CC="cc -Xa"
|
||||||
|
CFLAGS="-O"
|
||||||
|
LDFLAGS="-O -Wl,-Bexport"
|
||||||
|
AC_DEFINE(HAVE_HARRIS, 1, [Define to 1 on m88k-harris-cxux])
|
||||||
|
;;
|
||||||
|
|
||||||
|
## DEC Ultrix
|
||||||
|
mips-dec-ultrix* )
|
||||||
|
dir=ultrix
|
||||||
|
if test ${CC} = cc; then
|
||||||
|
LDFLAGS=-N
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
## HP 9000 series 700 and 800, running HP/UX
|
||||||
|
hppa*-hp-hpux* )
|
||||||
|
dir=hpux
|
||||||
|
LDFLAGS="-Wl,-E"
|
||||||
|
if test ${CC} = cc; then
|
||||||
|
CFLAGS="-Ae -O +Obb1800"
|
||||||
|
fi
|
||||||
|
AC_DEFINE(_HPUX_SOURCE, 1, [Define to 1 to compile on HP/UX])
|
||||||
|
AC_DEFINE(hpux, 1, [Define to 1 on HP/UX])
|
||||||
|
AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Define to 1 to compile on HP/UX])
|
||||||
|
;;
|
||||||
|
|
||||||
|
## IBM AIX
|
||||||
|
rs6000-ibm-aix*|powerpc-ibm-aix* )
|
||||||
|
dir=aix
|
||||||
|
LDFLAGS="-O"
|
||||||
|
if test ${CC} = gcc; then
|
||||||
|
LDFLAGS_AIX="-Xlinker -bexport:exportlist.aix"
|
||||||
|
else
|
||||||
|
LDFLAGS_AIX="-bexport:exportlist.aix"
|
||||||
|
fi
|
||||||
|
CFLAGS="-O"
|
||||||
|
AIX_P="exportlist.aix"
|
||||||
|
;;
|
||||||
|
|
||||||
|
## Linux
|
||||||
|
*-*-linux* )
|
||||||
|
dir=linux
|
||||||
|
# gross, but needed for some older a.out systems for 0.4.x
|
||||||
|
LIBS=-lc
|
||||||
|
SCSH_ELF
|
||||||
|
;;
|
||||||
|
|
||||||
|
## NetBSD and FreeBSD ( and maybe 386BSD also)
|
||||||
|
*-*-*bsd*|*-*-darwin* )
|
||||||
|
dir=bsd
|
||||||
|
SCSH_ELF
|
||||||
|
;;
|
||||||
|
|
||||||
|
## NeXT
|
||||||
|
*-next-* )
|
||||||
|
dir=next
|
||||||
|
CC="$CC -posix"
|
||||||
|
AC_DEFINE(HAVE_SIGACTION)
|
||||||
|
;;
|
||||||
|
|
||||||
|
## SGI IRIX
|
||||||
|
mips-sgi-irix* )
|
||||||
|
dir=irix
|
||||||
|
S48_CFLAG_CKR
|
||||||
|
INSTALL='$(srcdir)/install-sh'
|
||||||
|
;;
|
||||||
|
|
||||||
|
## SunOS
|
||||||
|
sparc*-sun-sunos* )
|
||||||
|
dir=sunos
|
||||||
|
;;
|
||||||
|
|
||||||
|
## Solaris - Sparc and i386
|
||||||
|
*-*-solaris* )
|
||||||
|
dir=solaris
|
||||||
|
AC_DEFINE(HAVE_NLIST)
|
||||||
|
;;
|
||||||
|
|
||||||
|
## NT - cygwin32
|
||||||
|
*-*-cygwin* )
|
||||||
|
AC_DEFINE(CYGWIN, 1, [Define to 1 on cygwin])
|
||||||
|
dir=cygwin32
|
||||||
|
EXEEXT=".exe"
|
||||||
|
;;
|
||||||
|
|
||||||
|
## Generic Configuration
|
||||||
|
* )
|
||||||
|
dir=generic
|
||||||
|
echo "WARNING: "
|
||||||
|
echo "WARNING: Using generic configuration."
|
||||||
|
echo "WARNING: See doc/porting.txt for more information."
|
||||||
|
echo "WARNING: "
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
(cd $srcdir/scsh && rm -rf machine && ln -s $dir machine)
|
||||||
|
|
||||||
AC_CHECK_LIB(m, main)
|
AC_CHECK_LIB(m, main)
|
||||||
AC_CHECK_LIB(dl, main)
|
AC_CHECK_LIB(dl, main)
|
||||||
AC_CHECK_LIB(mld, main)
|
AC_CHECK_LIB(mld, main)
|
||||||
|
|
@ -89,27 +300,42 @@ AC_INIT(c/scheme48vm.c)
|
||||||
AC_CHECK_LIB(gen, main)
|
AC_CHECK_LIB(gen, main)
|
||||||
AC_CHECK_LIB(socket, main)
|
AC_CHECK_LIB(socket, main)
|
||||||
AC_CHECK_LIB(sun, getpwnam)
|
AC_CHECK_LIB(sun, getpwnam)
|
||||||
|
AC_CHECK_LIB(c, crypt, [true], AC_CHECK_LIB(crypt, crypt))
|
||||||
dnl Solaris 2.3 seems to need -lelf for nlist(). (tnx Bryan O'Sullivan)
|
dnl Solaris 2.3 seems to need -lelf for nlist(). (tnx Bryan O'Sullivan)
|
||||||
AC_CHECK_LIB(elf, main)
|
AC_CHECK_LIB(elf, main)
|
||||||
S48_POSIX_LIBC
|
S48_POSIX_LIBC
|
||||||
AC_CONST
|
AC_CONST
|
||||||
AC_RETSIGTYPE
|
AC_RETSIGTYPE
|
||||||
AC_CHECK_HEADERS(libgen.h sys/timeb.h posix/time.h)
|
AC_CHECK_HEADERS(libgen.h sys/timeb.h posix/time.h sys/select.h nlist.h)
|
||||||
AC_CHECK_HEADERS(sys/select.h)
|
AC_CHECK_HEADERS(sys/un.h)
|
||||||
AC_CHECK_FUNCS(gettimeofday ftime nlist select setitimer sigaction)
|
AC_CHECK_HEADERS(crypt.h)
|
||||||
AC_CHECK_FUNC(dlopen, AC_DEFINE(HAVE_DLOPEN),
|
AC_CHECK_FUNCS(gettimeofday ftime nlist select setitimer sigaction vasprintf)
|
||||||
AC_CHECK_FUNC(nlist, [LIBOBJS="$LIBOBJS c/fake/libdl1.c],
|
SCSH_SOCKLEN_T
|
||||||
[LIBOBJS="$LIBOBJS c/fake/libdl2.c]))
|
AC_CHECK_FUNC(dlopen, [AC_DEFINE(HAVE_DLOPEN,
|
||||||
|
1, [Define to 1 if the interface to the dynamic linker exists])],
|
||||||
|
[AC_CHECK_FUNC(nlist, [AC_LIBOBJ([c/fake/libdl1])],
|
||||||
|
[AC_LIBOBJ([c/fake/libdl2])])])
|
||||||
AC_CHECK_FUNCS(socket chroot)
|
AC_CHECK_FUNCS(socket chroot)
|
||||||
AC_CHECK_FUNC(strerror, AC_DEFINE(HAVE_STRERROR),
|
AC_CHECK_FUNC(strerror, AC_DEFINE(HAVE_STRERROR,
|
||||||
[LIBOBJS="$LIBOBJS c/fake/strerror.o"])
|
1, [Define to 1 if you have the strerror function]),
|
||||||
AC_MSG_CHECKING([n_name])
|
[AC_LIBOBJ([c/fake/strerror])])
|
||||||
AC_TRY_LINK([#include <nlist.h>],
|
|
||||||
[struct nlist name_list;
|
AC_CHECK_FUNC(seteuid, [AC_DEFINE(HAVE_SETEUID,
|
||||||
name_list.n_name = "foo";],
|
1, [Define to 1 if you have the seteuid function])],
|
||||||
AC_DEFINE(NLIST_HAS_N_NAME)
|
[AC_CHECK_FUNC(setreuid, [AC_DEFINE(HAVE_SETREUID,
|
||||||
AC_MSG_RESULT([yes]),
|
1, [Define to 1 if you have the setreuid function])],
|
||||||
AC_MSG_RESULT([no]))
|
[AC_MSG_ERROR("Neither setegid nor setregid defined. Cannot continue.")])])
|
||||||
|
|
||||||
|
AC_CHECK_FUNC(setegid, [AC_DEFINE(HAVE_SETEGID,
|
||||||
|
1, [Define to 1 if you have the setegid function])],
|
||||||
|
[AC_CHECK_FUNC(setregid, [AC_DEFINE(HAVE_SETREGID,
|
||||||
|
1, [Define to 1 if you have the setregid function])],
|
||||||
|
[AC_MSG_ERROR("Neither setegid nor setregid defined. Cannot continue.")])])
|
||||||
|
|
||||||
|
|
||||||
|
AC_CHECK_MEMBER(struct nlist.n_name,
|
||||||
|
[AC_DEFINE(NLIST_HAS_N_NAME, 1, [Define to 1 if struct nlist.n_name exists])],,
|
||||||
|
[#include <nlist.h>])
|
||||||
AC_MSG_CHECKING([__NEXT__])
|
AC_MSG_CHECKING([__NEXT__])
|
||||||
AC_TRY_LINK(,[
|
AC_TRY_LINK(,[
|
||||||
#ifdef __NeXT__
|
#ifdef __NeXT__
|
||||||
|
|
@ -124,7 +350,31 @@ fail
|
||||||
AC_MSG_RESULT([no]))
|
AC_MSG_RESULT([no]))
|
||||||
S48_USCORE
|
S48_USCORE
|
||||||
S48_RDYNAMIC
|
S48_RDYNAMIC
|
||||||
|
AC_STRUCT_TIMEZONE
|
||||||
|
AC_CHECK_MEMBER(struct tm.tm_gmtoff,
|
||||||
|
AC_DEFINE(HAVE_GMTOFF, 1, [Define to 1 if struct tm has member tm_gmtoff]))
|
||||||
|
|
||||||
|
SCSH_CONST_SYS_ERRLIST
|
||||||
|
CFLAGS1=${CFLAGS}
|
||||||
|
|
||||||
AC_SUBST(CFLAGS)
|
AC_SUBST(CFLAGS)
|
||||||
AC_SUBST(LIBOBJS)
|
|
||||||
AC_SUBST(LDFLAGS)
|
AC_SUBST(LDFLAGS)
|
||||||
AC_OUTPUT(Makefile)
|
|
||||||
|
|
||||||
|
AC_SUBST(AIX_P)
|
||||||
|
AC_SUBST(AR)
|
||||||
|
AC_SUBST(CC)
|
||||||
|
AC_SUBST(CFLAGS)
|
||||||
|
AC_SUBST(CFLAGS1)
|
||||||
|
AC_SUBST(EXEEXT)
|
||||||
|
AC_SUBST(ENDIAN)
|
||||||
|
AC_SUBST(LDFLAGS)
|
||||||
|
AC_SUBST(LDFLAGS_AIX)
|
||||||
|
AC_SUBST(LIBS)
|
||||||
|
AC_SUBST(TMPDIR)
|
||||||
|
|
||||||
|
|
||||||
|
AC_CONFIG_FILES(Makefile scsh/endian.scm scsh-config)
|
||||||
|
AC_CONFIG_COMMANDS([scsh-config+x],[chmod +x scsh-config])
|
||||||
|
AC_OUTPUT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,309 +0,0 @@
|
||||||
|
|
||||||
Documentation for Big Scheme
|
|
||||||
|
|
||||||
|
|
||||||
Big Scheme is a set of generally useful facilities.
|
|
||||||
|
|
||||||
Easiest way to access these things:
|
|
||||||
|
|
||||||
> ,open big-scheme
|
|
||||||
Load structure big-scheme (y/n)? y
|
|
||||||
...
|
|
||||||
|
|
||||||
A better way is to use the module system.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Ascii conversions
|
|
||||||
|
|
||||||
(CHAR->ASCII <char>) => <integer>
|
|
||||||
(ASCII->CHAR <integer>) => <char>
|
|
||||||
These are identical to CHAR->INTEGER and INTEGER->CHAR except that
|
|
||||||
they use the ASCII encoding.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Bitwise operations
|
|
||||||
|
|
||||||
(BITWISE-NOT <integer>) => <integer>
|
|
||||||
(BITWISE-AND <integer> <integer>) => <integer>
|
|
||||||
(BITWISE-IOR <integer> <integer>) => <integer>
|
|
||||||
(BITWISE-XOR <integer> <integer>) => <integer>
|
|
||||||
These perform various logical operations on integers on a bit-by-bit
|
|
||||||
basis, using a two's-complement representation.
|
|
||||||
|
|
||||||
(ARITHMETIC-SHIFT <integer> <bit-count>) => <integer>
|
|
||||||
Shift the integer by the given bit count, shifting left for positive
|
|
||||||
counts and right for negative ones. A two's complement
|
|
||||||
representation is used.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Hash tables
|
|
||||||
|
|
||||||
(MAKE-TABLE) => <table>
|
|
||||||
(MAKE-STRING-TABLE) => <string-table>
|
|
||||||
Make a new, empty table. MAKE-TABLE returns a table that uses EQ?
|
|
||||||
for comparing keys and an ad-hoc hash function. String tables uses
|
|
||||||
strings for keys.
|
|
||||||
|
|
||||||
(MAKE-TABLE-MAKER <comparison-procedure> <hash-procedure>) => <procedure>
|
|
||||||
Returns a procedure of no arguments that makes tables that use the
|
|
||||||
given comparison and hash procedures.
|
|
||||||
(<comparison-procedure> <key1> <key2>) => <boolean>
|
|
||||||
(<hash-procedure> <key>) => <non-negative-integer>
|
|
||||||
|
|
||||||
(TABLE? <x>) => <boolean>
|
|
||||||
True if <x> is a table.
|
|
||||||
|
|
||||||
(TABLE-REF <table> <key>) => <x>
|
|
||||||
Return the value for <key> in <table>, or #F if there is none.
|
|
||||||
<key> should be of a type appropriate for <table>.
|
|
||||||
|
|
||||||
(TABLE-SET! <table> <key> <value>) => <undefined>
|
|
||||||
Make <value> be the value of <key> in <table>. <key> should be of a
|
|
||||||
type appropriate for <table>.
|
|
||||||
|
|
||||||
(TABLE-WALK <procedure> <table>) => <undefined>
|
|
||||||
Apply <procedure>, which must accept two arguments, to every
|
|
||||||
associated key and value in <table>.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Enumerations
|
|
||||||
|
|
||||||
(DEFINE-ENUMERATION <type-name> (<name0> <name1> ...)) *SYNTAX*
|
|
||||||
Defines <type-name> to be an enumeration with components <name0>
|
|
||||||
<name1> .... Also defines <type-name>-COUNT to be the number of
|
|
||||||
components.
|
|
||||||
|
|
||||||
(ENUM <type-name> <component-name>) => <integer> *SYNTAX*
|
|
||||||
Evaluates to the value of <component-name> within the enumeration
|
|
||||||
<type-name>. For example, if (DEFINE-ENUMERATION COLOR (GREEN
|
|
||||||
RED)), then (ENUM COLOR GREEN) is zero and (ENUM COLOR RED) is one.
|
|
||||||
The mapping from name to integer is done at macro-expansion time, so
|
|
||||||
there is no run-time overhead.
|
|
||||||
|
|
||||||
(ENUMERAND->NAME <integer> <enumeration>) => <symbol>
|
|
||||||
Returns the name associated with <integer> within <enumeration>.
|
|
||||||
E.g. (ENUMERAND->NAME 1 COLOR) => 'RED.
|
|
||||||
|
|
||||||
(NAME->ENUMERAND <symbol> <enumeration>) => <integer>
|
|
||||||
Returns the integer associated with <symbol> within <enumeration>.
|
|
||||||
E.g. (ENUMERAND->NAME 'GREEN COLOR) => 0.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Port extensions
|
|
||||||
|
|
||||||
(MAKE-TRACKING-INPUT-PORT <input-port>) => <input-port>
|
|
||||||
(MAKE-TRACKING-OUTPUT-PORT <output-port>) => <output-port>
|
|
||||||
These return ports that keep track of the current row and column and
|
|
||||||
are otherwise identical to their arguments.
|
|
||||||
|
|
||||||
(MAKE-STRING-INPUT-PORT <string>) => <input-port>
|
|
||||||
Returns a port that reads characters from the supplied string.
|
|
||||||
|
|
||||||
(CALL-WITH-STRING-OUTPUT-PORT <procedure>) => <string>
|
|
||||||
The procedure is called on a port. When it returns, CALL-WITH-STRING-
|
|
||||||
OUTPUT-PORT returns a string containing the characters written to the port.
|
|
||||||
|
|
||||||
(WRITE-ONE-LINE <output-port> <character-count> <procedure>) => <unspecified>
|
|
||||||
The procedure is called on an output port. Output written to that
|
|
||||||
port is copied to <output-port> until <character-count> characters
|
|
||||||
have been written, at which point WRITE-ONE-LINE returns.
|
|
||||||
|
|
||||||
(CURRENT-ROW <port>) => <integer> or #f
|
|
||||||
(CURRENT-COLUMN <port>) => <integer> or #f
|
|
||||||
These return the current read or write location of the port. #F is
|
|
||||||
returned if the port does not keep track of its location.
|
|
||||||
|
|
||||||
(FRESH-LINE <output-port>) => <undefined>
|
|
||||||
Write a newline character to <output-port> if its current column is not 0.
|
|
||||||
|
|
||||||
(INPUT-PORT? <any>) => <boolean>
|
|
||||||
(OUTPUT-PORT? <any>) => <boolean>
|
|
||||||
These are versions of the standard Scheme predicates that answer true for
|
|
||||||
extended ports.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Queues
|
|
||||||
|
|
||||||
(MAKE-QUEUE) => <queue>
|
|
||||||
Returns a new, empty queue.
|
|
||||||
|
|
||||||
(ENQUEUE! <queue> <x>) => <undefined>
|
|
||||||
Puts <x> on the queue.
|
|
||||||
|
|
||||||
(DEQUEUE! <queue>) => <x>
|
|
||||||
Removes and returns the first element of the queue.
|
|
||||||
|
|
||||||
(QUEUE-EMPTY? <queue>) => <boolean>
|
|
||||||
True if the queue is empty.
|
|
||||||
|
|
||||||
(QUEUE? <x>) => <boolean>
|
|
||||||
True if <x> is a queue.
|
|
||||||
|
|
||||||
(QUEUE->LIST <queue>) => <list>
|
|
||||||
Returns a list of the elements of the queue, in order.
|
|
||||||
|
|
||||||
(QUEUE-LENGTH <queue>) => <integer>
|
|
||||||
The number of elements currently on the queue.
|
|
||||||
|
|
||||||
(DELETE-FROM-QUEUE! <queue> <x>) => <boolean>
|
|
||||||
Removes the first occurance of <x> from the queue, returning true if
|
|
||||||
it was found and false otherwise.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Little utility procedures
|
|
||||||
|
|
||||||
(ATOM? <any>) => <boolean>
|
|
||||||
(ATOM? x) == (NOT (PAIR? x))
|
|
||||||
|
|
||||||
(NULL-LIST? <list>) => <boolean>
|
|
||||||
Returns #t for the empty list, #f for a pair, and signals an error
|
|
||||||
otherwise.
|
|
||||||
|
|
||||||
(NEQ? <any> <any>) => <boolean>
|
|
||||||
(NEQ? x y) is the same as (NOT (EQ? x y)).
|
|
||||||
|
|
||||||
(N= <number> <number>) => <boolean>
|
|
||||||
(N= x y) is the same as (NOT (= x y)).
|
|
||||||
|
|
||||||
(IDENTITY <any>) => <any>
|
|
||||||
(NO-OP <any>) => <any>
|
|
||||||
These both just return their argument. NO-OP is guaranteed not to
|
|
||||||
be compiled in-line, IDENTITY may be.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
List utilities
|
|
||||||
|
|
||||||
(MEMQ? <element> <list>) => <boolean>
|
|
||||||
Returns true if <element> is in <list>, false otherwise.
|
|
||||||
|
|
||||||
(ANY? <predicate> <list>) => <boolean>
|
|
||||||
Returns true if <predicate> is true for any element of <list>.
|
|
||||||
|
|
||||||
(EVERY? <predicate> <list>) => <boolean>
|
|
||||||
Returns true if <predicate> is true for every element of <list>.
|
|
||||||
|
|
||||||
(ANY <predicate> <list>)
|
|
||||||
(FIRST <predicate> <list>)
|
|
||||||
ANY returns some element of <list> for which <predicate> is true, or
|
|
||||||
#F if there are none. FIRST does the same except that it returns
|
|
||||||
the first element for which <predicate> is true.
|
|
||||||
|
|
||||||
(FILTER <predicate> <list>)
|
|
||||||
(FILTER! <predicate> <list>)
|
|
||||||
Returns a list containing all of the elements of <list> for which
|
|
||||||
<predicate> is true. The order of the elements is preserved.
|
|
||||||
FILTER! may reuse the storage of <list>.
|
|
||||||
|
|
||||||
(FILTER-MAP <procedure> <list>)
|
|
||||||
The same as FILTER except the returned list contains the results of
|
|
||||||
applying <procedure> instead of elements of <list>. (FILTER-MAP p
|
|
||||||
l) is the same as (FILTER IDENTITY (MAP p l)).
|
|
||||||
|
|
||||||
(PARTITION-LIST <predicate> <list>) => <list> <list>
|
|
||||||
(PARTITION-LIST! <predicate> <list>) => <list> <list>
|
|
||||||
The first return value contains those elements <list> for which
|
|
||||||
<predicate> is true, the second contains the remaining elements.
|
|
||||||
The order of the elements is preserved. PARTITION-LIST! may resuse
|
|
||||||
the storage of the <list>.
|
|
||||||
|
|
||||||
(REMOVE-DUPLICATES <list>) => <list>
|
|
||||||
Returns its argument with all duplicate elements removed. The first
|
|
||||||
instance of each element is preserved.
|
|
||||||
|
|
||||||
(DELQ <element> <list>) => <list>
|
|
||||||
(DELQ! <element> <list>) => <list>
|
|
||||||
(DELETE <predicate> <list>) => <list>
|
|
||||||
All three of these return <list> with some elements removed. DELQ
|
|
||||||
removes all elements EQ? to <element>. DELQ! does the same and may
|
|
||||||
modify the list argument. DELETE removes all elements for which
|
|
||||||
<predicate> is true. Both DELQ and DELETE may reuse some of the
|
|
||||||
storage in the list argument, but won't modify it.
|
|
||||||
|
|
||||||
(REVERSE! <list>) => <list>
|
|
||||||
Destructively reverses <list>.
|
|
||||||
|
|
||||||
(SORT-LIST <list> <a<b-procedure>) => <list>
|
|
||||||
(SORT-LIST! <list> <a<b-procedure>) => <list>
|
|
||||||
Returns a sorted copy of <list>. The sorting algorithm is stable.
|
|
||||||
(SORT-LIST '(6 5 1 3 2 4) <) => '(1 2 3 4 5 6)
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Additional syntax
|
|
||||||
|
|
||||||
(DESTRUCTURE ((<pattern> <init>) ...) <body> ...) *SYNTAX*
|
|
||||||
The <init>s are evaluated and their values are dissasembled
|
|
||||||
according to the corresponding patterns, with identifiers in the
|
|
||||||
patterns being bound to fresh locations holding the corresponding
|
|
||||||
part, and the body is evaluated in the extended environment.
|
|
||||||
Patterns may be any of the following:
|
|
||||||
|
|
||||||
#f Discard the corresponding part.
|
|
||||||
<identifier> Bind the <indentifier> to the part.
|
|
||||||
(<pattern> ...) The part must be a list at least as long as the
|
|
||||||
pattern.
|
|
||||||
(<pattern1> ... . <patternN>)
|
|
||||||
The same thing, except that the final CDR of the
|
|
||||||
part is dissasembled according to <patternN>.
|
|
||||||
#(<pattern> ...) The part must be a vector at least as long as the
|
|
||||||
pattern.
|
|
||||||
|
|
||||||
(RECEIVE <identifiers> <exp> <body> ...) *SYNTAX*
|
|
||||||
=> (CALL-WITH-VALUES (LAMBDA () <exp>) (LAMBDA <identifiers> <body> ...))
|
|
||||||
Bind <identifiers> to the values returned by <exp>, and evaluate the
|
|
||||||
body in the resulting environment.
|
|
||||||
|
|
||||||
-----
|
|
||||||
|
|
||||||
Printing and related procedures
|
|
||||||
|
|
||||||
(CONCATENATE-SYMBOL . <components>)
|
|
||||||
Returns the symbol whose name is produced by concatenating the DISPLAYed
|
|
||||||
representations of <components>.
|
|
||||||
(CONCATENATE-SYMBOL 'abc "-" 4) => 'abc-4
|
|
||||||
|
|
||||||
(FORMAT <port-spec> <format-string> . <arguments>) => <string> or <undefined>
|
|
||||||
Prints the arguments to the port as directed by the string. <port-spec>
|
|
||||||
should be either:
|
|
||||||
An output port. The output is written directly to the port. The result
|
|
||||||
of the call to FORMAT is undefined.
|
|
||||||
#T. The output is written to the current output port. The result of the
|
|
||||||
call to FORMAT is undefined.
|
|
||||||
#F. The output is written to a string, which is then the value returned
|
|
||||||
from the call to FORMAT.
|
|
||||||
Characters in <format-string> which are not preceded by a ~ are written
|
|
||||||
directly to the output. Characters preceded by a ~ have the following
|
|
||||||
meaning (case is irrelevant; ~a and ~A have the same meaning):
|
|
||||||
~~ prints a single ~
|
|
||||||
~A prints the next argument using DISPLAY
|
|
||||||
~D prints the next argument as a decimal number
|
|
||||||
~S prints the next argument using WRITE
|
|
||||||
~% prints a newline character
|
|
||||||
~& prints a NEWLINE character if the previous printed character was not one
|
|
||||||
(this is implemented using FRESH-LINE)
|
|
||||||
~? performs a recursive call to FORMAT using the next two arguments as the
|
|
||||||
string and the list of arguments
|
|
||||||
|
|
||||||
(ERROR <format-string> . <format-arguments>)
|
|
||||||
(BREAKPOINT <format-string> . <format-arguments>)
|
|
||||||
Signals an error or breakpoint condition, passing it the result of
|
|
||||||
applying FORMAT to the arguments.
|
|
||||||
|
|
||||||
(P <thing>)
|
|
||||||
(P <thing> <output-port>)
|
|
||||||
(PRETTY-PRINT <thing> <output-port> <position>)
|
|
||||||
Pretty-print <thing>. The current output port is used if no port is
|
|
||||||
specified. <position> is the starting offset. <thing> will be
|
|
||||||
pretty-printed to the right of this column.
|
|
||||||
|
|
||||||
|
|
||||||
Original by RK, 26 Jan 1993.
|
|
||||||
Minor changes by JAR, 5 Dec 1993.
|
|
||||||
|
|
@ -0,0 +1,740 @@
|
||||||
|
Scsh cheat sheet
|
||||||
|
Olin Shivers
|
||||||
|
November 1996
|
||||||
|
|
||||||
|
This cheat sheet is intentionally kept brief and minimalist.
|
||||||
|
It is intended to function as an ASCII-format reminder for the
|
||||||
|
full manual, not as the definition. It can be read using GNU Emacs's
|
||||||
|
outline mode.
|
||||||
|
|
||||||
|
It is also not entirely up-to-date. I'd appreciate getting updates from users.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
* High-level forms
|
||||||
|
|
||||||
|
Extended process form:
|
||||||
|
(PF [REDIR1 ...])
|
||||||
|
|
||||||
|
Redirection:
|
||||||
|
(< [FDES] FILE-NAME)
|
||||||
|
(> [FDES] FILE-NAME)
|
||||||
|
(<< [FDES] OBJECT)
|
||||||
|
(= FDES FDES/PORT)
|
||||||
|
(- FDES/PORT)
|
||||||
|
stdports
|
||||||
|
Subforms are implicitly backquoted.
|
||||||
|
|
||||||
|
Process form:
|
||||||
|
(| PF1 ...) ; pipeline
|
||||||
|
(|+ CONNECT-LIST PF1 ...) ; complex pipeline
|
||||||
|
(begin . BODY) ; Scheme form
|
||||||
|
(epf . EPF) ; Embedded extended process form
|
||||||
|
(PROG ARG1 ... ARGn) ; Exec a program
|
||||||
|
Subforms are implicitly backquoted.
|
||||||
|
|
||||||
|
Using process forms in Scheme:
|
||||||
|
(exec-epf . EPF) ; Nuke the current process.
|
||||||
|
(& . EPF) ; Fork process in background. Return proc object.
|
||||||
|
(run . EPF) ; Run process. Return exit code.
|
||||||
|
|
||||||
|
(& . EPF) = (fork (lambda () (exec-epf . EPF)))
|
||||||
|
(run . EPF) = (wait (& . EPF))
|
||||||
|
|
||||||
|
Interfacing to subprocess I/O:
|
||||||
|
(run/port . EPF) -> port
|
||||||
|
(run/file . EPF) -> string
|
||||||
|
(run/string . EPF) -> string
|
||||||
|
(run/strings . EPF) -> string list
|
||||||
|
(run/sexp . EPF) -> object
|
||||||
|
(run/sexps . EPF) -> list
|
||||||
|
|
||||||
|
There are procedural equivalents for each of these, e.g., run/port* and
|
||||||
|
run/file*, that take thunk arguments for the subprocess.
|
||||||
|
|
||||||
|
(port->string PORT) -> string
|
||||||
|
Read until EOF on PORT, return data as a string.
|
||||||
|
|
||||||
|
(port->string-list PORT) -> string list
|
||||||
|
Repeatedly apply READ-LINE to PORT until EOF. Return list of lines read.
|
||||||
|
|
||||||
|
(port->sexp-list PORT) -> list
|
||||||
|
Repeatedly apply READ to PORT until EOF. Return list of items read.
|
||||||
|
|
||||||
|
(port->list READER PORT)
|
||||||
|
Repeatedly apply READER to PORT until EOF. Return list of items read.
|
||||||
|
|
||||||
|
(reduce-port PORT READER OP . SEEDS)
|
||||||
|
Evaluate (OP (READER PORT) . SEEDS) to get a new set of seeds
|
||||||
|
(OP must return as many values as there are SEEDS). When
|
||||||
|
a port read returns EOF, the current set of seed values are
|
||||||
|
returned as multiple values.
|
||||||
|
|
||||||
|
(run/port+proc . EPF) -> [port proc]
|
||||||
|
(run/port+proc* THUNK) -> [port proc]
|
||||||
|
|
||||||
|
(run/collecting FDS . EPF) -> [port ...]
|
||||||
|
(run/collecting* FDS THUNK) -> [port ...]
|
||||||
|
RUN/COLLECTING implicitly backquotes FDS.
|
||||||
|
|
||||||
|
(|| PF1 ... PFn)
|
||||||
|
(&& PF1 ... PFn)
|
||||||
|
Conditionally execute processes.
|
||||||
|
|
||||||
|
(char-filter filter) -> procedure
|
||||||
|
(string-filter filter [buflen]) -> procedure
|
||||||
|
|
||||||
|
* System calls
|
||||||
|
|
||||||
|
** Errors
|
||||||
|
|
||||||
|
(errno-error errno SYSCALL . DATA)
|
||||||
|
(with-errno-handler* HANDLER THUNK) -> value of thunk
|
||||||
|
HANDLER is called on two arguments: (HANDLER ERRNO PACKET)
|
||||||
|
where PACKET is a list of the form (ERRNO-MSG SYSCALL . DATA)
|
||||||
|
If HANDLER returns at all, the handler search continues upwards.
|
||||||
|
|
||||||
|
(with-errno-handler HANDLER-SPEC . BODY)
|
||||||
|
HANDLER-SPEC is of the form
|
||||||
|
((ERRNO PACKET) CLAUSE ...)
|
||||||
|
ERRNO and PACKET are variables bound to the errno error being raised.
|
||||||
|
There are two forms for handler clauses:
|
||||||
|
((ERRNO ...) . BODY)
|
||||||
|
(else . BODY)
|
||||||
|
ERRNO are expressions evaluating to errno integers.
|
||||||
|
|
||||||
|
** I/O
|
||||||
|
*** Port Manipulation
|
||||||
|
(close-after PORT CONSUMER) -> value(s) of consumer
|
||||||
|
(error-output-port) -> port
|
||||||
|
|
||||||
|
(with-current-input-port port . body) -> value(s) of body
|
||||||
|
(with-current-output-port port . body) -> value(s) of body
|
||||||
|
(with-error-output-port port . body) -> value(s) of body
|
||||||
|
|
||||||
|
(with-current-input-port* port thunk) -> value(s) of thunk
|
||||||
|
(with-current-output-port* port thunk) -> value(s) of thunk
|
||||||
|
(with-error-output-port* port thunk) -> value(s) of thunk
|
||||||
|
|
||||||
|
(close fd/port)
|
||||||
|
|
||||||
|
(stdports->stdio)
|
||||||
|
(stdio->stdports)
|
||||||
|
|
||||||
|
(with-stdio-ports* thunk) -> value(s) of thunk
|
||||||
|
(with-stdio-ports . body) -> value(s) of body
|
||||||
|
|
||||||
|
(make-string-input-port) -> port
|
||||||
|
(string-output-port-output port) -> port
|
||||||
|
(call-with-string-output-port proc) -> str
|
||||||
|
|
||||||
|
** Port and file descriptors
|
||||||
|
(fdes->inport fd) -> port
|
||||||
|
(fdes->outport fd) -> port
|
||||||
|
(port->fdes port) -> fixnum
|
||||||
|
Increment port's revealed count.
|
||||||
|
|
||||||
|
(port-revealed port) -> integer or #f
|
||||||
|
(release-port-handle port)
|
||||||
|
(call/fdes fd/port consumer) -> value(s) of consumer
|
||||||
|
|
||||||
|
(move->fdes fd/port target-fd) -> port or fdes
|
||||||
|
|
||||||
|
** Unix I/O
|
||||||
|
|
||||||
|
(dup fd/port [newfd]) -> fd/port
|
||||||
|
(dup->inport fd/port [newfd]) -> port
|
||||||
|
(dup->outport fd/port [newfd]) -> port
|
||||||
|
(dup->fdes fd/port [newfd]) -> fd
|
||||||
|
|
||||||
|
(file-seek fd/port offset whence)
|
||||||
|
|
||||||
|
(open-file fname flags [perms]) -> port
|
||||||
|
(open-input-file fname [flags]) -> port
|
||||||
|
(open-output-file fname [flags perms]) -> port
|
||||||
|
(open-fdes fname flags [perms]) -> integer
|
||||||
|
|
||||||
|
(fdes-flags fd/port)
|
||||||
|
(set-fdes-flags fd/port flags)
|
||||||
|
Only Posix flag defined is FDFLAGS/CLOSE-ON-EXEC, which you should
|
||||||
|
not ever have to use -- scsh manages this automatically.
|
||||||
|
|
||||||
|
(fdes-status fd/port)
|
||||||
|
(set-fdes-flags fd/port flags)
|
||||||
|
|
||||||
|
Operations allowed Flags
|
||||||
|
------------------ -----
|
||||||
|
Open+get+set open/append, open/non-blocking
|
||||||
|
open/async, open/fsync (non-Posix)
|
||||||
|
|
||||||
|
Open+get open/read, open/write, open/read+write
|
||||||
|
open/access-mask
|
||||||
|
|
||||||
|
Open only open/create, open/exclusive,
|
||||||
|
open/no-control-tty, open/truncate
|
||||||
|
|
||||||
|
(pipe) -> [rport wport]
|
||||||
|
(read-line [fd/port retain-newline?]) -> string or eof-object
|
||||||
|
|
||||||
|
(read-string nbytes [fd/port]) -> string or #f
|
||||||
|
(read-string! str [fd/port start end]) -> [nread or #f]
|
||||||
|
(read-string/partial nbytes [fd/port]) -> string or #f
|
||||||
|
(read-string!/partial str [fd/port start end]) -> [nread or #f]
|
||||||
|
|
||||||
|
(write-string string [fd/port start end])
|
||||||
|
(write-string/partial string [fd/port start end]) -> nwritten
|
||||||
|
(force-output [fd/port])
|
||||||
|
|
||||||
|
** File locking
|
||||||
|
(define-record lock-region
|
||||||
|
exclusive? ; write or read lock?
|
||||||
|
start ; integer: start, end & whence
|
||||||
|
end ; integer: define the region being locked.
|
||||||
|
whence ; The value of SEEK/SET, SEEK/DELTA, or SEEK/END.
|
||||||
|
proc) ; A proc object for the process locking the region.
|
||||||
|
|
||||||
|
(make-lock-region exclusive? start len [whence]) -> lock-region
|
||||||
|
WHENCE defaults to the value of SEEK/SET.
|
||||||
|
|
||||||
|
(lock-region fdes lock)
|
||||||
|
(lock-region/no-block fdes lock)
|
||||||
|
|
||||||
|
(get-lock-region fdes lock) -> lock-region or #f
|
||||||
|
|
||||||
|
(unlock-region fdes lock)
|
||||||
|
|
||||||
|
(with-region-lock* fdes lock thunk)
|
||||||
|
(with-region-lock fdes lock body ...) Syntax
|
||||||
|
|
||||||
|
** File system
|
||||||
|
(create-directory fname [perms override?])
|
||||||
|
(create-fifo fname [perms override?])
|
||||||
|
(create-hard-link oldname newname [override?])
|
||||||
|
OVERRIDE? one of {#f, QUERY, other true value}
|
||||||
|
|
||||||
|
(delete-directory fname)
|
||||||
|
(delete-file fname)
|
||||||
|
(delete-filesys-object fname)
|
||||||
|
|
||||||
|
(read-symlink fname) -> string
|
||||||
|
|
||||||
|
(rename-file old-fname new-fname [override?])
|
||||||
|
|
||||||
|
(set-file-mode fname/fd/port mode)
|
||||||
|
(set-file-owner fname/fd/port uid)
|
||||||
|
(set-file-group fname/fd/port gid)
|
||||||
|
|
||||||
|
(sync-file fd/port)
|
||||||
|
(sync-file-system)
|
||||||
|
|
||||||
|
(truncate-file fname/fd/port len)
|
||||||
|
|
||||||
|
(file-attributes fname/fd/port [chase?]) -> file-info
|
||||||
|
|
||||||
|
(define-record file-info
|
||||||
|
type ; {block-special, char-special, directory,
|
||||||
|
; fifo, regular, socket, symlink}
|
||||||
|
device ; Device file resides on.
|
||||||
|
inode ; File's inode.
|
||||||
|
mode ; File's permission bits.
|
||||||
|
nlinks ; Number of hard links to this file.
|
||||||
|
uid ; Owner of file.
|
||||||
|
gid ; File's group id.
|
||||||
|
size ; Size of file, in bytes.
|
||||||
|
atime ; Last access time.
|
||||||
|
mtime ; Last status-change time.
|
||||||
|
ctime) ; Creation time.
|
||||||
|
|
||||||
|
Derived procedures:
|
||||||
|
file-type type
|
||||||
|
file-inode inode
|
||||||
|
file-mode mode
|
||||||
|
file-nlinks nlinks
|
||||||
|
file-owner uid
|
||||||
|
file-group gid
|
||||||
|
file-size size
|
||||||
|
file-last-access atime
|
||||||
|
file-last-mod mtime
|
||||||
|
file-last-status-change ctime
|
||||||
|
|
||||||
|
(file-not-readable? fname) -> boolean
|
||||||
|
(file-not-writable? fname) -> boolean
|
||||||
|
(file-not-executable? fname) -> boolean
|
||||||
|
|
||||||
|
Returns one of
|
||||||
|
#f Access permitted
|
||||||
|
SEARCH-DENIED Can't stat---a protected directory
|
||||||
|
is blocking access.
|
||||||
|
PERMISSION Permission denied.
|
||||||
|
NO-DIRECTORY Some directory doesn't exist.
|
||||||
|
NONEXISTENT File doesn't exist.
|
||||||
|
|
||||||
|
(file-readable? fname) -> boolean
|
||||||
|
(file-writable? fname) -> boolean
|
||||||
|
(file-executable? fname) -> boolean
|
||||||
|
|
||||||
|
(file-not-exists? fname [chase?]) -> boolean
|
||||||
|
#f Exists.
|
||||||
|
SEARCH-DENIED Some protected directory
|
||||||
|
is blocking the search.
|
||||||
|
#t Doesn't exist.
|
||||||
|
|
||||||
|
(file-exists? fname [chase?]) -> boolean
|
||||||
|
|
||||||
|
(directory-files [dir dotfiles?]) -> string list
|
||||||
|
(glob pat1 ...) -> string list
|
||||||
|
(glob-quote string) -> string
|
||||||
|
(file-match root dot-files? pat1 ...) -> string list
|
||||||
|
|
||||||
|
(create-temp-file [prefix]) -> string
|
||||||
|
(temp-file-iterate maker [template]) -> [object ...]
|
||||||
|
TEMPLATE defaults to the value of *TEMP-FILE-TEMPLATE*.
|
||||||
|
|
||||||
|
(temp-file-channel) -> [inport outport]
|
||||||
|
|
||||||
|
** Processes
|
||||||
|
(exec prog arg1 ...)
|
||||||
|
(exec-path prog arg1 ...)
|
||||||
|
(exec/env prog env arg1 ...)
|
||||||
|
(exec-path/env prog env arg1 ...)
|
||||||
|
|
||||||
|
(%exec prog arglist env)
|
||||||
|
(exec-path-search fname pathlist) -> string
|
||||||
|
|
||||||
|
(exit [status])
|
||||||
|
(%exit [status])
|
||||||
|
|
||||||
|
(suspend)
|
||||||
|
|
||||||
|
(fork [thunk]) -> proc or #d
|
||||||
|
(%fork [thunk]) -> proc or #f
|
||||||
|
|
||||||
|
(fork/pipe [thunk]) -> proc or #f
|
||||||
|
(%fork/pipe [thunk]) -> proc or #f
|
||||||
|
|
||||||
|
(fork/pipe+ conns [thunk]) proc or #f
|
||||||
|
(%fork/pipe+ conns [thunk]) proc or #f
|
||||||
|
|
||||||
|
(wait proc/pid [flags]) -> status [proc]
|
||||||
|
|
||||||
|
(call-terminally thunk)
|
||||||
|
|
||||||
|
** Process state
|
||||||
|
|
||||||
|
(umask) -> fixnum
|
||||||
|
(set-umask perms)
|
||||||
|
(with-umask* perms thunk) -> values of thunk
|
||||||
|
(with-umask perms . body) -> values of body
|
||||||
|
|
||||||
|
(chdir [fname])
|
||||||
|
(cwd) -> string
|
||||||
|
(with-cwd* fname thunk) -> value(s) of thunk
|
||||||
|
(with-cwd fname . body) -> value(s) of body
|
||||||
|
|
||||||
|
(pid) -> fixnum
|
||||||
|
(parent-pid) -> fixnum
|
||||||
|
(process-group) -> fixnum
|
||||||
|
(set-process-group [proc/pid] pgrp)
|
||||||
|
|
||||||
|
(user-login-name) -> string
|
||||||
|
(user-uid) -> fixnum
|
||||||
|
(user-effective-uid) -> fixnum
|
||||||
|
(user-gid) -> fixnum
|
||||||
|
(user-effective-gid) -> fixnum
|
||||||
|
(user-supplementary-gids) -> fixnum list
|
||||||
|
(set-uid uid)
|
||||||
|
(set-gid gid)
|
||||||
|
|
||||||
|
(process-times) -> [ucpu scpu uchildren schildren]
|
||||||
|
|
||||||
|
** User and group db access
|
||||||
|
|
||||||
|
(user-info uid-or-name) -> user-info
|
||||||
|
|
||||||
|
(define-record user-info
|
||||||
|
name
|
||||||
|
uid
|
||||||
|
gid
|
||||||
|
home-dir
|
||||||
|
shell)
|
||||||
|
|
||||||
|
(->uid uid/name) -> fixnum
|
||||||
|
(->username uid/name) -> string
|
||||||
|
|
||||||
|
(group-info gid-or-name) -> record
|
||||||
|
|
||||||
|
(define-record group-info
|
||||||
|
name
|
||||||
|
gid
|
||||||
|
members) ; List of uids
|
||||||
|
|
||||||
|
(->gid gid/name) -> fixnum
|
||||||
|
(->group gid/name) -> string
|
||||||
|
|
||||||
|
** Accessing command-line arguments
|
||||||
|
|
||||||
|
command-line-arguments
|
||||||
|
Does not include program name
|
||||||
|
|
||||||
|
(command-line) -> string list
|
||||||
|
Includes program name in list.
|
||||||
|
|
||||||
|
(arg arglist n [default]) -> string
|
||||||
|
(arg* arglist n [default-thunk]) -> string
|
||||||
|
(argv n [default]) -> string
|
||||||
|
ARG is 1-based access to ARGLIST
|
||||||
|
ARGV is 0-based access to prog + args
|
||||||
|
|
||||||
|
** System parameters
|
||||||
|
|
||||||
|
(system-name) -> string
|
||||||
|
|
||||||
|
** Signal system
|
||||||
|
|
||||||
|
(signal-process proc/pid sig)
|
||||||
|
(signal-procgroup prgrp sig)
|
||||||
|
(pause-until-interrupt)
|
||||||
|
(sleep secs)
|
||||||
|
|
||||||
|
Non-signal S48 interrupts
|
||||||
|
-------------------------
|
||||||
|
interrupt/memory-shortage
|
||||||
|
|
||||||
|
Posix signals with S48 interrupts
|
||||||
|
------------------------------
|
||||||
|
signal/alrm interrupt/alrm (aka interrupt/alarm)
|
||||||
|
signal/int interrupt/int (aka interrupt/int)
|
||||||
|
signal/chld interrupt/chld
|
||||||
|
signal/cont interrupt/cont
|
||||||
|
signal/hup interrupt/hup
|
||||||
|
signal/quit interrupt/quit
|
||||||
|
signal/term interrupt/term
|
||||||
|
signal/tstp interrupt/tstp
|
||||||
|
signal/usr1 interrupt/usr1
|
||||||
|
signal/usr2 interrupt/usr2
|
||||||
|
|
||||||
|
signal/info interrupt/info Non-Posix
|
||||||
|
signal/io interrupt/io Non-Posix
|
||||||
|
signal/poll interrupt/poll Non-Posix
|
||||||
|
signal/prof interrupt/prof Non-Posix
|
||||||
|
signal/pwr interrupt/pwr Non-Posix
|
||||||
|
signal/urg interrupt/urg Non-Posix
|
||||||
|
signal/vtalrm interrupt/vtalrm Non-Posix
|
||||||
|
signal/winch interrupt/winch Non-Posix
|
||||||
|
signal/xcpu interrupt/xcpu Non-Posix
|
||||||
|
signal/xfsz interrupt/xfsz Non-Posix
|
||||||
|
|
||||||
|
Synchronous and uncatchable signals
|
||||||
|
-----------------------------------
|
||||||
|
signal/stop Uncatchable Posix
|
||||||
|
signal/kill Uncatchable Posix
|
||||||
|
|
||||||
|
signal/abrt Synchronous Posix
|
||||||
|
signal/fpe Synchronous Posix
|
||||||
|
signal/ill Synchronous Posix
|
||||||
|
signal/pipe Synchronous Posix
|
||||||
|
signal/segv Synchronous Posix
|
||||||
|
signal/ttin Synchronous Posix
|
||||||
|
signal/ttou Synchronous Posix
|
||||||
|
|
||||||
|
signal/bus Synchronous BSD + SVR4
|
||||||
|
signal/emt Synchronous BSD + SVR4
|
||||||
|
signal/iot Synchronous BSD + SVR4
|
||||||
|
signal/sys Synchronous BSD + SVR4
|
||||||
|
signal/trap Synchronous BSD + SVR4
|
||||||
|
|
||||||
|
** Interrupt handlers
|
||||||
|
(signal->interrupt sig) -> interrupt
|
||||||
|
(interrupt-set integer1 ...) -> integer
|
||||||
|
|
||||||
|
(enabled-interrupts) -> integer
|
||||||
|
(set-enabled-interrupts! integer) -> integer
|
||||||
|
|
||||||
|
(with-enabled-interrupts interrupt-set body ...) Syntax
|
||||||
|
(with-enabled-interrupts* interrupt-set thunk)
|
||||||
|
|
||||||
|
(set-interrupt-handler! interrupt handler) -> old-handler
|
||||||
|
(interrupt-handler interrupt) -> handler
|
||||||
|
HANDLER is #f (ignored), #t (default), or (lambda (enabled-ints) ...) proc.
|
||||||
|
|
||||||
|
** Time
|
||||||
|
|
||||||
|
(define-record date
|
||||||
|
seconds minute hour month-day month year
|
||||||
|
tz-name tz-secs summer?
|
||||||
|
week-day year-day)
|
||||||
|
|
||||||
|
(make-date sec min hour mday month year [tz-name tz-secs summer? wday yday])
|
||||||
|
|
||||||
|
(time+ticks)
|
||||||
|
(ticks/sec)
|
||||||
|
|
||||||
|
(date [time tz])
|
||||||
|
(time [date])
|
||||||
|
|
||||||
|
(date->string date)
|
||||||
|
(format-date fmt date)
|
||||||
|
|
||||||
|
** Environment variables
|
||||||
|
|
||||||
|
(setenv var val)
|
||||||
|
(getenv var) -> string
|
||||||
|
|
||||||
|
(env->alist) -> string->string alist
|
||||||
|
(alist->env alist)
|
||||||
|
|
||||||
|
(alist-delete key alist) -> alist
|
||||||
|
(alist-update key val alist) -> alist
|
||||||
|
(alist-compress alist) -> alist
|
||||||
|
|
||||||
|
(with-env* env-alist-delta thunk) -> value(s) of thunk
|
||||||
|
(with-total-env* env-alist thunk) -> value(s) of thunk
|
||||||
|
|
||||||
|
(with-env env-alist-delta . body) -> value(s) of body
|
||||||
|
(with-total-env env-alist . body) -> value(s) of body
|
||||||
|
|
||||||
|
(add-before elt before list) -> list
|
||||||
|
(add-after elt after list) -> list
|
||||||
|
|
||||||
|
** $USER $HOME, and $PATH
|
||||||
|
|
||||||
|
home-directory
|
||||||
|
exec-path-list
|
||||||
|
|
||||||
|
* Networking
|
||||||
|
|
||||||
|
** High Level Socket Routines
|
||||||
|
|
||||||
|
*** clients
|
||||||
|
(socket-connect protocol-family/internet socket-type name port) -> socket
|
||||||
|
(socket-connect protocol-family/unix socket-type pathname) -> socket
|
||||||
|
|
||||||
|
*** server
|
||||||
|
(bind-listen-accept-loop protocol-family/internet proc port) -> does-not-return
|
||||||
|
(bind-listen-accept-loop protocol-family/unix proc pathname) -> does-not-return
|
||||||
|
|
||||||
|
proc is a procedure of two arguments: a socket and a socket-address
|
||||||
|
|
||||||
|
** Sockets
|
||||||
|
(create-socket protocol-family type [protocol]) -> socket
|
||||||
|
(create-socket-pair type) -> [socket1 socket2]
|
||||||
|
(close-socket socket) -> undefined
|
||||||
|
|
||||||
|
protocol-family/unix
|
||||||
|
protocol-family/internet
|
||||||
|
|
||||||
|
socket-type/stream
|
||||||
|
socket-type/datagram
|
||||||
|
|
||||||
|
for protocol see protocol-info
|
||||||
|
|
||||||
|
(define-record socket family inport outport)
|
||||||
|
|
||||||
|
** Socket Addresses
|
||||||
|
(define-record socket-address family)
|
||||||
|
|
||||||
|
(unix-address->socket-address pathname) -> socket-address
|
||||||
|
(internet-address->socket-address host-address service-port)-> socket-address
|
||||||
|
|
||||||
|
internet-address/any
|
||||||
|
internet-address/loopback
|
||||||
|
internet-address/broadcast
|
||||||
|
|
||||||
|
(socket-address->unix-address socket-address) -> pathname
|
||||||
|
(socket-address->internet-address socket-address) ->
|
||||||
|
[host-address service-port]
|
||||||
|
|
||||||
|
** Low Level Socket Routines
|
||||||
|
|
||||||
|
(connect-socket socket socket-address) -> undefined
|
||||||
|
(bind-socket socket socket-address) -> undefined
|
||||||
|
(listen-socket socket backlog) -> undefined
|
||||||
|
(accept-connection socket) -> [new-socket socket-address]
|
||||||
|
|
||||||
|
(socket-local-address socket) -> socket-address
|
||||||
|
(socket-remote-address socket) -> socket-address
|
||||||
|
|
||||||
|
(shutdown-socket socket how-to) -> undefined
|
||||||
|
how-to:
|
||||||
|
shutdown/receives
|
||||||
|
shutdown/sends
|
||||||
|
shutdown/sends+receives
|
||||||
|
|
||||||
|
** Socket Specific I/O
|
||||||
|
see read-string/write-string for info on arguments
|
||||||
|
|
||||||
|
(receive-message socket length [flags]) ->
|
||||||
|
[string-or-#f socket-address]
|
||||||
|
(receive-message! socket string [start] [end] [flags]) ->
|
||||||
|
[count-or-#f socket-address]
|
||||||
|
(receive-message/partial socket length [flags]) ->
|
||||||
|
[string-or-#f socket-address]
|
||||||
|
(receive-message!/partial socket string [start] [end] [flags]) ->
|
||||||
|
[count-or-#f socket-address]
|
||||||
|
|
||||||
|
(send-message socket string [start] [end] [flags] [socket-address] ->
|
||||||
|
undefined
|
||||||
|
(send-message/partial socket string [start] [end] [flags] [socket-address]) ->
|
||||||
|
count
|
||||||
|
|
||||||
|
** Socket Options
|
||||||
|
(socket-option socket level option) -> value
|
||||||
|
(set-socket-option socket level option value) -> undefined
|
||||||
|
|
||||||
|
boolean:
|
||||||
|
socket/debug
|
||||||
|
socket/accept-connect
|
||||||
|
socket/reuse-address
|
||||||
|
socket/keep-alive
|
||||||
|
socket/dont-route
|
||||||
|
socket/broadcast
|
||||||
|
socket/use-loop-back
|
||||||
|
socket/oob-inline
|
||||||
|
socket/use-privileged
|
||||||
|
socket/cant-signal
|
||||||
|
tcp/no-delay
|
||||||
|
|
||||||
|
value:
|
||||||
|
socket/send-buffer
|
||||||
|
socket/receive-buffer
|
||||||
|
socket/send-low-water
|
||||||
|
socket/receive-low-water
|
||||||
|
socket/error
|
||||||
|
socket/type
|
||||||
|
ip/time-to-live
|
||||||
|
tcp/max-segment
|
||||||
|
|
||||||
|
socket/linger is #f or integer seconds
|
||||||
|
|
||||||
|
real number with microsecond resolution:
|
||||||
|
socket/send-timeout
|
||||||
|
socket/receive-timeout
|
||||||
|
|
||||||
|
|
||||||
|
** Database-information entries
|
||||||
|
|
||||||
|
(host-info name-or-socket-address) -> host-info
|
||||||
|
(network-info name-or-socket-address) -> network-info
|
||||||
|
(service-info name-or-number [protocol-name]) -> service-info
|
||||||
|
(protocol-info name-or-number) -> protocol-info
|
||||||
|
|
||||||
|
(define-record host-info name aliases addresses)
|
||||||
|
(define-record network-info name aliases net)
|
||||||
|
(define-record service-info name aliases port protocol)
|
||||||
|
(define-record protocol-info name aliases number)
|
||||||
|
|
||||||
|
* String manipulation
|
||||||
|
|
||||||
|
** Regular expressions
|
||||||
|
|
||||||
|
(string-match regexp string [start]) -> match or false
|
||||||
|
(regexp-match? obj) -> boolean
|
||||||
|
(match:start match [match-number]) -> fixnum
|
||||||
|
(match:end match [match-number]) -> fixnum
|
||||||
|
(match:substring match [match-number]) -> string
|
||||||
|
(make-regexp str) -> re
|
||||||
|
(regexp? obj) -> boolean
|
||||||
|
(regexp-exec regexp str [start]) -> match or false
|
||||||
|
(regexp-quote str) -> string
|
||||||
|
|
||||||
|
** Other string manipulation facilities
|
||||||
|
|
||||||
|
(index string char [start]) -> fixnum or false
|
||||||
|
(rindex string char [start]) -> fixnum or false
|
||||||
|
|
||||||
|
(substitute-env-vars fname) -> string
|
||||||
|
|
||||||
|
** Manipulating file-names
|
||||||
|
|
||||||
|
** Record I/O and field parsing
|
||||||
|
|
||||||
|
(read-delimited char-set [port]) -> string or eof
|
||||||
|
(read-delimited! char-set buf [port start end]) -> nchars or #f or eof
|
||||||
|
|
||||||
|
((record-reader [delims elide-delims? handle-delim]) [port]) -> string or eof
|
||||||
|
HANDLE-DELIM one of {trim, split, concat}
|
||||||
|
|
||||||
|
(read-paragraph [port delimiter?])
|
||||||
|
|
||||||
|
** Parsing fields
|
||||||
|
|
||||||
|
(field-splitter [regexp num-fields]) -> parser
|
||||||
|
(infix-splitter [delim num-fields handle-delim]) -> parser
|
||||||
|
(suffix-splitter [delim num-fields handle-delim]) -> parser
|
||||||
|
(sloppy-suffix-splitter [delim num-fields handle-delim]) -> parser
|
||||||
|
Where (parser string [start])
|
||||||
|
HANDLE-DELIM one of {trim, concat, split}
|
||||||
|
|
||||||
|
(join-strings strings [delimiter grammar])
|
||||||
|
GRAMMAR one of {infix, suffix}
|
||||||
|
|
||||||
|
** Field readers
|
||||||
|
|
||||||
|
(field-reader [field-parser record-reader])
|
||||||
|
|
||||||
|
* Awk
|
||||||
|
|
||||||
|
(awk <reader-exp> <rec&field-vars> [<rec-counter>] <state-var-inits>
|
||||||
|
<clause>
|
||||||
|
.
|
||||||
|
.
|
||||||
|
)
|
||||||
|
|
||||||
|
* Miscellaneous routines
|
||||||
|
|
||||||
|
** Integer bitwise ops
|
||||||
|
|
||||||
|
(arithmetic-shift i j) -> integer
|
||||||
|
(bitwise-and i j) -> integer
|
||||||
|
(bitwise-ior i j) -> integer
|
||||||
|
(bitwise-not i) -> integer
|
||||||
|
(bitwise-xor i j) -> integer
|
||||||
|
|
||||||
|
** ASCII encoding
|
||||||
|
|
||||||
|
(char->ascii \character) -> integer
|
||||||
|
(ascii->char \integer) -> character
|
||||||
|
|
||||||
|
** Top level
|
||||||
|
|
||||||
|
(repl)
|
||||||
|
|
||||||
|
* Running scsh
|
||||||
|
|
||||||
|
scsh [meta-arg] [switch1 ...] [end-option arg1 ...]
|
||||||
|
meta-arg: \ <script-file-name>
|
||||||
|
|
||||||
|
switch: -e <entry-point> Top-level entry point
|
||||||
|
-o <structure> Open structure in current package.
|
||||||
|
-m <structure> Switch to package.
|
||||||
|
-n <new-package> Switch to new package.
|
||||||
|
|
||||||
|
-lm <module> <file-name> Load module into config package.
|
||||||
|
-l <file-name> Load file into current package.
|
||||||
|
-dm Do script module.
|
||||||
|
-ds Do script.
|
||||||
|
|
||||||
|
end-option: -s <script> Specifies script to load.
|
||||||
|
-sfd <num> Script from file descriptor <num>.
|
||||||
|
-c <expression> Eval <expression> and exit.
|
||||||
|
--
|
||||||
|
|
||||||
|
scshvm [meta-arg] [vm-options] [end-option arg1 ...]
|
||||||
|
meta-arg: \ <fname>
|
||||||
|
|
||||||
|
vm-options: -h heap-size
|
||||||
|
-s stack-size
|
||||||
|
-o object-file
|
||||||
|
|
||||||
|
end-option: -i image-file
|
||||||
|
--
|
||||||
|
(dump-scsh-program main fname)
|
||||||
|
|
||||||
|
** File locations
|
||||||
|
/usr/local/bin/scsh
|
||||||
|
|
||||||
|
/usr/local/lib/scsh/
|
||||||
|
scshvm
|
||||||
|
scsh
|
||||||
|
scsh.image
|
||||||
|
doc/
|
||||||
|
|
||||||
4430
doc/external.ps
4430
doc/external.ps
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,290 @@
|
||||||
|
|
||||||
|
,bench
|
||||||
|
,load-package linker
|
||||||
|
,new-package =link= linker debuginfo defpackage
|
||||||
|
,load scripts.scm
|
||||||
|
(link-initial-system)
|
||||||
|
|
||||||
|
|
||||||
|
To change between initial image starting in mini-command (MINI) and
|
||||||
|
command (MAXI):
|
||||||
|
|
||||||
|
1. Definition of initial system's command module in comp-packages.scm:
|
||||||
|
MINI: (make-mini-command scheme)
|
||||||
|
MAXI: (make-command scheme)
|
||||||
|
2. Location of (define-module (make-command ...)...):
|
||||||
|
MINI: more-packages.scm
|
||||||
|
MAXI: comp-packages.scm
|
||||||
|
3. Location of (define-interface command-interface ...):
|
||||||
|
MINI: more-interfaces.scm
|
||||||
|
MAXI: interfaces.scm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> ,new-package z architecture primitives packages table enumerated debug-data
|
||||||
|
z> (let ((i 0))
|
||||||
|
(table-walk (lambda (x y) (set! i (+ i 1)))
|
||||||
|
location-name-table)
|
||||||
|
i)
|
||||||
|
1385
|
||||||
|
z> (vector-length (find-all-xs (name->enumerand 'location stob)))
|
||||||
|
1259
|
||||||
|
(vector-length (find-all-xs (name->enumerand 'record stob)))
|
||||||
|
2150
|
||||||
|
|
||||||
|
(find-all-xs (name->enumerand 'record stob))
|
||||||
|
z> (do ((i 0 (+ i 1))
|
||||||
|
(j 0 (if (package? (vector-ref rs i)) (+ j 1) j))) ((= i (vector-length rs)) j))
|
||||||
|
72
|
||||||
|
z>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> ,new-package z architecture primitives compiler table
|
||||||
|
z> (vector-ref stob 10)
|
||||||
|
'template
|
||||||
|
z> stob
|
||||||
|
'#(pair symbol vector closure location port ratio record continuation extended-number template weak-pointer external unused-d-header1 unused-d-header2 string code-vector double bignum)
|
||||||
|
z> (vector-ref stob 7)
|
||||||
|
'record
|
||||||
|
z> (define rs (find-all-xs 7))
|
||||||
|
z> (vector-length rs)
|
||||||
|
2178
|
||||||
|
z> (define ls (find-all-xs 4))
|
||||||
|
z> (vector-length ls)
|
||||||
|
1266
|
||||||
|
z>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
To get a fresh config package:
|
||||||
|
|
||||||
|
,in config (define-structures ((config1 (export)))
|
||||||
|
(open defpackage built-in-structures more-structures))
|
||||||
|
,config-package-is config1
|
||||||
|
|
||||||
|
|
||||||
|
To load a linker with a fresh new compiler:
|
||||||
|
x48 -i new-scheme48.image -h 10000000 <l.s48
|
||||||
|
|
||||||
|
Then ,load scripts.scm or whatever.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
These are all files not belonging to any package description:
|
||||||
|
|
||||||
|
boot-packages.scm
|
||||||
|
comp-packages.scm
|
||||||
|
flatload.scm
|
||||||
|
more-packages.scm
|
||||||
|
more-interfaces.scm
|
||||||
|
rts-packages.scm
|
||||||
|
scripts.scm
|
||||||
|
interfaces.scm
|
||||||
|
|
||||||
|
infix/
|
||||||
|
debug/
|
||||||
|
alt/
|
||||||
|
|
||||||
|
link/p-features.scm
|
||||||
|
link/p-record.scm
|
||||||
|
link/t-features.scm
|
||||||
|
link/t-record.scm
|
||||||
|
|
||||||
|
misc/icon.scm
|
||||||
|
misc/mail.scm -- related to more-thread.scm
|
||||||
|
misc/more-thread.scm -- needs work
|
||||||
|
misc/sicp.scm -- add to more-packages
|
||||||
|
|
||||||
|
|
||||||
|
,load-package rk-extensions
|
||||||
|
,new-package rk-user rk-extensions
|
||||||
|
,user-package-is rk-user
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# If initial images starts in mini-command instead of command, the
|
||||||
|
# rule for $(IMAGE) becomes something like this:
|
||||||
|
# (echo ,load more-interfaces.scm $(S48ROOT)/more-packages.scm; \
|
||||||
|
# echo "(ensure-loaded command)"; \
|
||||||
|
# echo ",go ((structure-ref command 'command-processor) batch)"; \
|
||||||
|
|
||||||
|
|
||||||
|
,in config (define-structures ((reification (export reify-structures)))
|
||||||
|
(open scheme-level-2 table
|
||||||
|
signals ;error
|
||||||
|
packages
|
||||||
|
features ;location-id location?
|
||||||
|
scan) ;find-free-names-in-syntax-rules
|
||||||
|
(files (link reify)))
|
||||||
|
|
||||||
|
,load-package reification
|
||||||
|
|
||||||
|
debug-config> ,in reification reify-structures
|
||||||
|
'#{Procedure 8447 reify-structures}
|
||||||
|
debug-config> (define reify-structures ##)
|
||||||
|
debug-config> make-simple-package
|
||||||
|
|
||||||
|
Error: undefined variable
|
||||||
|
make-simple-package
|
||||||
|
(package debug-config)
|
||||||
|
1 debug-config>
|
||||||
|
debug-config> (define-structures ((p (export start))) (open initial-system scheme-level-2 packages))
|
||||||
|
debug-config> (define go (in p `(start ,(reify-structures (desirable-packages) (lambda (loc) `',loc)))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Small images for exercising the linker and/or runtime system
|
||||||
|
|
||||||
|
debug/tiny.image: debug/tiny.scm $(LINKER_IMAGE)
|
||||||
|
($(START_LINKER_RUNNABLE) \
|
||||||
|
echo "(load \"debug/tiny-packages.scm\")"; \
|
||||||
|
echo "(link-simple-system '(debug tiny) 'start tiny-system)") \
|
||||||
|
| $(LINKER_RUNNABLE) -i $(LINKER_IMAGE)
|
||||||
|
|
||||||
|
debug/little.image: $(LINKER_IMAGE) $(CONFIG_FILES) $(little-files)
|
||||||
|
($(START_LINKER_RUNNABLE) \
|
||||||
|
echo "(load \"scripts.scm\")"; \
|
||||||
|
echo "(link-little-system)") \
|
||||||
|
| $(LINKER_RUNNABLE) -i $(LINKER_IMAGE) $(BIG_HEAP)
|
||||||
|
|
||||||
|
debug/medium.image: $(LINKER_IMAGE) $(CONFIG_FILES) $(medium-files)
|
||||||
|
($(START_LINKER_RUNNABLE) \
|
||||||
|
echo "(load \"scripts.scm\")"; \
|
||||||
|
echo "(link-medium-system)") \
|
||||||
|
| $(LINKER_RUNNABLE) -i $(LINKER_IMAGE) $(BIG_HEAP)
|
||||||
|
|
||||||
|
|
||||||
|
echo "(define l-f (package-all-filenames little-system))"; \
|
||||||
|
echo "(define m-f (package-all-filenames medium-system))"; \
|
||||||
|
|
||||||
|
'little-files l-f 'medium-files m-f \
|
||||||
|
|
||||||
|
|
||||||
|
[The following is from June 1992, and probably not quite compatible
|
||||||
|
with the current compiler internals.]
|
||||||
|
|
||||||
|
To eliminate use of the stack GC to implement tail recursion, change
|
||||||
|
comp.scm as follows:
|
||||||
|
|
||||||
|
(define (compile-unknown-call exp cenv depth cont)
|
||||||
|
(note-source-code
|
||||||
|
exp
|
||||||
|
(maybe-push-continuation (sequentially
|
||||||
|
(push-all (cdr exp) cenv 0)
|
||||||
|
(compile (car exp)
|
||||||
|
cenv
|
||||||
|
(length (cdr exp))
|
||||||
|
(fall-through-cont))
|
||||||
|
(instruction (if (return-cont? cont)
|
||||||
|
op/move-args-and-call
|
||||||
|
op/call)
|
||||||
|
(length (cdr exp))))
|
||||||
|
depth
|
||||||
|
cont)))
|
||||||
|
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Here's another cool thing. 6/28/93
|
||||||
|
|
||||||
|
(define-interface evaluation-interface
|
||||||
|
(export eval load eval-from-file))
|
||||||
|
|
||||||
|
(define-structure run evaluation-interface
|
||||||
|
(open scheme-level-2 syntactic packages scan
|
||||||
|
environments
|
||||||
|
signals
|
||||||
|
locations
|
||||||
|
features ;force-output
|
||||||
|
table
|
||||||
|
fluids)
|
||||||
|
(files (debug run)))
|
||||||
|
|
||||||
|
,load-package run
|
||||||
|
,in run
|
||||||
|
,in package-commands (environment-for-syntax-promise)
|
||||||
|
(define cool (make-simple-package (list scheme) eval ## 'cool))
|
||||||
|
,in command set-environment-for-commands!
|
||||||
|
(## cool)
|
||||||
|
|
||||||
|
cool> ,inspect (lambda (x) x)
|
||||||
|
'#{Procedure 6394}
|
||||||
|
|
||||||
|
[0: exp] '(lambda (x) x)
|
||||||
|
[1: env] '#{Package 286 cool}
|
||||||
|
inspect:
|
||||||
|
inspect: q
|
||||||
|
cool>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(define (z s)
|
||||||
|
(define (show-type name static)
|
||||||
|
(write name)
|
||||||
|
(display " : ")
|
||||||
|
(write (static-type static))
|
||||||
|
(newline))
|
||||||
|
(if (package? s)
|
||||||
|
(for-each-definition (lambda (name static loc)
|
||||||
|
(show-type name static))
|
||||||
|
s)
|
||||||
|
(interface-walk (lambda (name type)
|
||||||
|
(show-type name
|
||||||
|
(car (structure-lookup
|
||||||
|
s name #t))))
|
||||||
|
(structure-interface s))))
|
||||||
|
|
||||||
|
; ,open expander syntactic packages reconstruction
|
||||||
|
|
||||||
|
(define (e x)
|
||||||
|
(let ((p (interaction-environment)))
|
||||||
|
(let ((node (expand-form x p)))
|
||||||
|
(write (node-type node (package->environment p)))
|
||||||
|
(newline)
|
||||||
|
(eval node p))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
> (define hunk3 (lap hunk3
|
||||||
|
0 (check-nargs= 3)
|
||||||
|
2 (pop)
|
||||||
|
3 (make-stored-object 3 0)
|
||||||
|
6 (return)))
|
||||||
|
> (hunk3 1 2 3)
|
||||||
|
'(1 . 2)
|
||||||
|
> (define cxr (lap cxr
|
||||||
|
0 (check-nargs= 2)
|
||||||
|
2 (pop)
|
||||||
|
3 (stored-object-indexed-ref 0)
|
||||||
|
5 (return)))
|
||||||
|
> (cxr (hunk3 1 2 3) 2)
|
||||||
|
3
|
||||||
|
>
|
||||||
|
|
||||||
|
|
||||||
|
(define-syntax %cons
|
||||||
|
(lambda (e r c)
|
||||||
|
(let ((n (cadr e))
|
||||||
|
(kind (caddr e)))
|
||||||
|
`(,(r 'lap) (%cons ,n ,kind)
|
||||||
|
(check-nargs= ,n)
|
||||||
|
(pop)
|
||||||
|
(make-stored-object ,n ,kind)
|
||||||
|
(return)))))
|
||||||
|
|
||||||
|
|
||||||
|
(define (& x)
|
||||||
|
(or (node-ref x 'uid)
|
||||||
|
(begin (set! *n* (+ *n* 1))
|
||||||
|
(node-set! x 'uid *n*)
|
||||||
|
*n*))
|
||||||
|
x)
|
||||||
|
|
||||||
|
(define (uid n) (node-ref (& n) 'uid))
|
||||||
|
|
||||||
|
(define *n* 0)
|
||||||
|
|
@ -1,690 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<HTML>
|
|
||||||
<!-- HTML file produced from file: external.tex --
|
|
||||||
-- using Hyperlatex v 2.3.1 (c) Otfried Cheong--
|
|
||||||
-- on Emacs 19.34.1, Tue Feb 23 18:21:44 1999 -->
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>Mixing Scheme 48 and C</TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1 ALIGN=CENTER>Using C code with Scheme 48</H1>
|
|
||||||
<H2 ALIGN=CENTER>Mike Sperber<BR><TT><FONT SIZE=-1>sperber@informatik.uni-tuebingen.de</FONT></TT><BR>Richard Kelsey<BR><TT><FONT SIZE=-1>kelsey@research.nj.nec.com</FONT></TT>
|
|
||||||
</H2>
|
|
||||||
<H3 ALIGN=CENTER>February 23, 1999</H3>
|
|
||||||
<H3 ALIGN=CENTER>Abstract</H3>
|
|
||||||
<BLOCKQUOTE>
|
|
||||||
This document describes an interface for calling C functions
|
|
||||||
from Scheme, calling Scheme functions from C, and allocating
|
|
||||||
storage in the Scheme heap.
|
|
||||||
These facilities are designed to link
|
|
||||||
existing C libraries into Scheme 48 in order to use them from Scheme.
|
|
||||||
To this end, Scheme 48 manages stub functions in C that
|
|
||||||
negotiate between the calling conventions of Scheme and C and the
|
|
||||||
memory allocation policies of both worlds.
|
|
||||||
No stub generator is available yet, but writing them is a straightforward task.
|
|
||||||
</BLOCKQUOTE>
|
|
||||||
<H1><A NAME="1">Available Facilities</A></H1>
|
|
||||||
|
|
||||||
<P>The following facilities are available for interfacing between
|
|
||||||
Scheme 48 and C:
|
|
||||||
<UL><LI>Scheme code can call C functions.
|
|
||||||
<LI>The external interface provides full introspection for all
|
|
||||||
Scheme objects. External code may inspect, modify, and allocate
|
|
||||||
Scheme objects arbitrarily.
|
|
||||||
<LI>External code may raise exceptions back to Scheme 48 to
|
|
||||||
signal errors.
|
|
||||||
<LI>External code may call back into Scheme. Scheme 48
|
|
||||||
correctly unrolls the process stack on non-local exits.
|
|
||||||
<LI>External modules may register bindings of names to values with a
|
|
||||||
central registry accessible from
|
|
||||||
Scheme. Conversely, Scheme code can register shared
|
|
||||||
bindings for access by C code.
|
|
||||||
</UL>
|
|
||||||
This document has three parts: the first describes how bindings are
|
|
||||||
moved from Scheme to C and vice versa, the second tells how to call
|
|
||||||
C functions from Scheme, and the third covers the C interface
|
|
||||||
to Scheme objects, including calling Scheme procedures, using the
|
|
||||||
Scheme heap, and so forth.
|
|
||||||
<H2><A NAME="2">Scheme structures</A></H2>
|
|
||||||
<P>The structure <CODE>external-calls</CODE> has
|
|
||||||
most of the Scheme functions described here.
|
|
||||||
The others are in
|
|
||||||
<CODE>dynamic-externals</CODE>, which has the functions for dynamic loading and
|
|
||||||
name lookup from
|
|
||||||
|
|
||||||
the section on <A HREF="#dynamic-externals">Dynamic Loading</A>,
|
|
||||||
and <CODE>shared-bindings</CODE>, which has the additional shared-binding functions
|
|
||||||
described in
|
|
||||||
|
|
||||||
the section on the <A HREF="#more-shared-bindings">complete shared-binding interface</A>.
|
|
||||||
<H2><A NAME="3">C naming conventions</A></H2>
|
|
||||||
<P>The names of all of Scheme 48's visible C bindings begin
|
|
||||||
with `<CODE>s48_</CODE>' (for procedures and variables) or
|
|
||||||
`<CODE>S48_</CODE>' (for macros).
|
|
||||||
Whenever a C name is derived from a Scheme identifier, we
|
|
||||||
replace `<CODE>-</CODE>' with `<CODE>_</CODE>' and convert letters to lowercase
|
|
||||||
for procedures and uppercase for macros.
|
|
||||||
A final `<CODE>?</CODE>' converted to `<CODE>_p</CODE>' (`<CODE>_P</CODE>' in C macro names).
|
|
||||||
A final `<CODE>!</CODE>' is dropped.
|
|
||||||
Thus the C macro for Scheme's <CODE>pair?</CODE> is <CODE>S48_PAIR_P</CODE> and
|
|
||||||
the one for <CODE>set-car!</CODE> is <CODE>S48_SET_CAR</CODE>.
|
|
||||||
Procedures and macros that do not check the types of their arguments
|
|
||||||
have `<CODE>unsafe</CODE>' in their names.
|
|
||||||
<P>All of the C functions and macros described have prototypes or definitions
|
|
||||||
in the file <CODE>c/scheme48.h</CODE>.
|
|
||||||
The C type for Scheme values is defined there to be <CODE>s48_value</CODE>.
|
|
||||||
<H1><A NAME="4">Shared bindings</A></H1>
|
|
||||||
|
|
||||||
<P>Shared bindings are the means by which named values are shared between Scheme
|
|
||||||
code and C code.
|
|
||||||
There are two separate tables of shared bindings, one for values defined in
|
|
||||||
Scheme and accessed from C and the other for values going the other way.
|
|
||||||
Shared bindings actually bind names to cells, to allow a name to be looked
|
|
||||||
up before it has been assigned.
|
|
||||||
This is necessary because C initialization code may be run before or after
|
|
||||||
the corresponding Scheme code, depending on whether the Scheme code is in
|
|
||||||
the resumed image or is run in the current session.
|
|
||||||
<H2><A NAME="5">Exporting Scheme values to C</A></H2>
|
|
||||||
<UL><LI><CODE>(define-exported-binding<I> name value</I>) -> <I>shared-binding</I></CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>s48_value s48_get_imported_binding(char *name)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_SHARED_BINDING_REF(s48_value shared_binding)</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>Define-exported-binding</CODE> makes <CODE><I>value</I></CODE> available to C code
|
|
||||||
under as <CODE><I>name</I></CODE> which must be a <CODE><I>string</I></CODE>, creating a new shared
|
|
||||||
binding if necessary.
|
|
||||||
The C function <CODE>s48_get_imported_binding</CODE> returns the shared binding
|
|
||||||
defined for <CODE>name</CODE>, again creating it if necessary.
|
|
||||||
The C macro <CODE>S48_SHARED_BINDING_REF</CODE> dereferences a shared binding,
|
|
||||||
returning its current value.
|
|
||||||
<H2><A NAME="6">Exporting C values to Scheme</A></H2>
|
|
||||||
<UL><LI><CODE>void s48_define_exported_binding(char *name, s48_value value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>(lookup-imported-binding<I> string</I>) -> <I>shared-binding</I></CODE>
|
|
||||||
<LI><CODE>(shared-binding-ref<I> shared-binding</I>) -> <I>value</I></CODE>
|
|
||||||
</UL>
|
|
||||||
<P>These are used to define shared bindings from C and to access them
|
|
||||||
from Scheme.
|
|
||||||
Again, if a name is looked up before it has been defined, a new binding is
|
|
||||||
created for it.
|
|
||||||
<P>The common case of exporting a C function to Scheme can be done using
|
|
||||||
the macro <CODE>S48_EXPORT_FUNCTION(<EM>name</EM>)</CODE>.
|
|
||||||
This expands into
|
|
||||||
<P><CODE>s48_define_exported_binding("<CODE><I>name</I></CODE>", s48_enter_pointer(<CODE><I>name</I></CODE>))</CODE>
|
|
||||||
<P>which boxes the function into a Scheme byte vector and then
|
|
||||||
exports it.
|
|
||||||
Note that <CODE>s48_enter_pointer</CODE> allocates space in the Scheme heap
|
|
||||||
and might trigger a
|
|
||||||
<A HREF="#gc">garbage collection</A>.
|
|
||||||
<UL><LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>(import-definition <CODE><I>name</I></CODE>)</CODE></td> <td align=right>syntax</td></tr></table>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>(import-definition <CODE><I>name c-name</I></CODE>)</CODE></td> <td align=right>syntax</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
These macros simplify importing definitions from C to Scheme.
|
|
||||||
They expand into
|
|
||||||
<P><CODE>(define <CODE><I>name</I></CODE> (lookup-imported-binding <CODE><I>c-name</I></CODE>))</CODE>
|
|
||||||
<P>where <CODE><I>c-name</I></CODE> is as supplied for the second form.
|
|
||||||
For the first form <CODE><I>c-name</I></CODE> is derived from <CODE><I>name</I></CODE> by
|
|
||||||
replacing `<CODE>-</CODE>' with `<CODE>_</CODE>' and converting letters to lowercase.
|
|
||||||
For example, <CODE>(import-definition my-foo)</CODE> expands into
|
|
||||||
<P><CODE>(define my-foo (lookup-imported-binding "my_foo"))</CODE>
|
|
||||||
<H2><A NAME="more-shared-bindings">Complete shared binding interface</A></H2>
|
|
||||||
|
|
||||||
<P>There are a number of other Scheme functions related to shared bindings;
|
|
||||||
these are in the structure <CODE>shared-bindings</CODE>.
|
|
||||||
<UL><LI><CODE>(shared-binding?<I> x</I>) -> <I>boolean</I></CODE>
|
|
||||||
<LI><CODE>(shared-binding-name<I> shared-binding</I>) -> <I>string</I></CODE>
|
|
||||||
<LI><CODE>(shared-binding-is-import?<I> shared-binding</I>) -> <I>boolean</I></CODE>
|
|
||||||
<LI><CODE>(shared-binding-set!<I> shared-binding value</I>)</CODE>
|
|
||||||
<LI><CODE>(define-imported-binding<I> string value</I>)</CODE>
|
|
||||||
<LI><CODE>(lookup-exported-binding<I> string</I>)</CODE>
|
|
||||||
<LI><CODE>(undefine-imported-binding<I> string</I>)</CODE>
|
|
||||||
<LI><CODE>(undefine-exported-binding<I> string</I>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>Shared-binding?</CODE> is the predicate for shared-bindings.
|
|
||||||
<CODE>Shared-binding-name</CODE> returns the name of a binding.
|
|
||||||
<CODE>Shared-binding-is-import?</CODE> is true if the binding was defined from C.
|
|
||||||
<CODE>Shared-binding-set!</CODE> changes the value of a binding.
|
|
||||||
<CODE>Define-imported-binding</CODE> and <CODE>lookup-exported-binding</CODE> are
|
|
||||||
Scheme versions of <CODE>s48_define_exported_binding</CODE>
|
|
||||||
and <CODE>s48_lookup_imported_binding</CODE>.
|
|
||||||
The two <CODE>undefine-</CODE> procedures remove bindings from the two tables.
|
|
||||||
They do nothing if the name is not found in the table.
|
|
||||||
<P>The following C macros correspond to the Scheme functions above.
|
|
||||||
<UL><LI><CODE>int S48_SHARED_BINDING_P(x)</CODE>
|
|
||||||
<LI><CODE>int S48_SHARED_BINDING_IS_IMPORT_P(s48_value s_b)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_SHARED_BINDING_NAME(s48_value s_b)</CODE>
|
|
||||||
<LI><CODE>void S48_SHARED_BINDING_SET(s48_value s_b, s48_value value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<H1><A NAME="8">Calling C Functions from Scheme</A></H1>
|
|
||||||
|
|
||||||
<P>There are three different ways to call C functions from Scheme, depending on
|
|
||||||
how the C function was obtained.
|
|
||||||
<UL><LI><CODE>(call-imported-binding<I> binding arg<I><sub>0</sub></I> ...</I>) -> <I>value</I></CODE>
|
|
||||||
<LI><CODE>(call-external<I> external arg<I><sub>0</sub></I> ...</I>) -> <I>value</I></CODE>
|
|
||||||
<LI><CODE>(call-external-value<I> value name arg<I><sub>0</sub></I> ...</I>) -> <I>value</I></CODE>
|
|
||||||
</UL>
|
|
||||||
Each of these applies its first argument, a C function, to the rest of
|
|
||||||
the arguments.
|
|
||||||
For <CODE>call-imported-binding</CODE> the function argument must be an
|
|
||||||
imported binding.
|
|
||||||
For <CODE>call-external</CODE> the function argument must be an external
|
|
||||||
bound in the current process
|
|
||||||
(see
|
|
||||||
|
|
||||||
the section on <A HREF="#dynamic-externals">Dynamic Loading</A>).
|
|
||||||
For <CODE>call-external-value</CODE> <CODE><I>value</I></CODE> must be a byte vector
|
|
||||||
whose contents is a pointer to a C function and <CODE><I>name</I></CODE> should be
|
|
||||||
a string naming the function.
|
|
||||||
The <CODE><I>name</I></CODE> argument is used only for printing error messages.
|
|
||||||
<P>For all of these, the C function is passed the <CODE><I>arg<I><sub>i</sub></I></I></CODE> values
|
|
||||||
and the value returned is that returned by C procedure.
|
|
||||||
Up to twelve arguments may be passed.
|
|
||||||
There is no method supplied for returning multiple values to
|
|
||||||
Scheme from C (or vice versa) (mainly because C does not have multiple return
|
|
||||||
values).
|
|
||||||
<P>Keyboard interrupts that occur during a call to a C function are ignored
|
|
||||||
until the function returns to Scheme (this is clearly a
|
|
||||||
problem; we are working on a solution).
|
|
||||||
<UL><LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>(import-lambda-definition <CODE><I>name</I></CODE> (<CODE><I>formal</I></CODE> ...))</CODE></td> <td align=right>syntax</td></tr></table>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>(import-lambda-definition <CODE><I>name</I></CODE> (<CODE><I>formal</I></CODE> ...) <CODE><I>c-name</I></CODE>)</CODE></td> <td align=right>syntax</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
These macros simplify importing functions from C.
|
|
||||||
They define <CODE><I>name</I></CODE> to be a function with the given formals that
|
|
||||||
applies those formals to the corresponding C binding.
|
|
||||||
<CODE><I>C-name</I></CODE>, if supplied, should be a string.
|
|
||||||
These expand into
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define temp (lookup-imported-binding <CODE><I>c-name</I></CODE>))
|
|
||||||
(define <CODE><I>name</I></CODE>
|
|
||||||
(lambda (<CODE><I>formal</I></CODE> ...)
|
|
||||||
(external-apply temp <CODE><I>formal</I></CODE> ...)))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<P>
|
|
||||||
If <CODE><I>c-name</I></CODE> is not supplied, it is derived from <CODE><I>name</I></CODE> by converting
|
|
||||||
all letters to lowercase and replacing `<CODE>-</CODE>' with `<CODE>_</CODE>'.
|
|
||||||
<H1><A NAME="9">Adding external modules to the <CODE>Makefile</CODE></A></H1>
|
|
||||||
|
|
||||||
<P>Getting access to C bindings from Scheme requires that the C code be
|
|
||||||
compiled an linked in with the Scheme 48 virtual machine and that the
|
|
||||||
relevent shared-bindings be created.
|
|
||||||
The Scheme 48 makefile has rules for compiling and linking external code
|
|
||||||
and for specifying initialization functions that should be called on
|
|
||||||
startup.
|
|
||||||
There are three Makefile variables that control which external modules are
|
|
||||||
included in the executable for the virutal machine (<CODE>scheme48vm</CODE>).
|
|
||||||
<CODE>EXTERNAL_OBJECTS</CODE> lists the object files to be included in
|
|
||||||
<CODE>scheme48vm</CODE>,
|
|
||||||
<CODE>EXTERNAL_FLAGS</CODE> is a list of <CODE>ld</CODE> flags to be used when
|
|
||||||
creating <CODE>scheme48vm</CODE>, and
|
|
||||||
<CODE>EXTERNAL_INITIALIZERS</CODE> is a list of C procedures to be called
|
|
||||||
on startup.
|
|
||||||
The procedures listed in <CODE>EXTERNAL_INITIALIZERS</CODE> should take no
|
|
||||||
arguments and have a return type of <CODE>void</CODE>.
|
|
||||||
After changing the definitions of any of these variables you should
|
|
||||||
do <CODE>make scheme48vm</CODE> to rebuild the virtual machine.
|
|
||||||
<H1><A NAME="dynamic-externals">Dynamic Loading</A></H1>
|
|
||||||
|
|
||||||
<P>External code can be loaded into a running Scheme 48 process
|
|
||||||
and C object-file bindings can be dereferenced at runtime and
|
|
||||||
their values called
|
|
||||||
(although not all versions of Unix support all of this).
|
|
||||||
The required Scheme functions are in the structure <CODE>dynamic-externals</CODE>.
|
|
||||||
<UL><LI><CODE>(dynamic-load<I> string</I>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Dynamic-load</CODE> loads the named file into the current
|
|
||||||
process, raising an exception if the file cannot be found or if dynamic
|
|
||||||
loading is not supported by the operating system.
|
|
||||||
The file must have been compiled and linked appropriately.
|
|
||||||
For Linux, the following commands compile <CODE>foo.c</CODE> into a
|
|
||||||
file <CODE>foo.so</CODE> that can be loaded dynamically.
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
% gcc -c -o foo.o foo.c
|
|
||||||
% ld -shared -o foo.so foo.o
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<UL><LI><CODE>(get-external<I> string</I>) -> <I>external</I></CODE>
|
|
||||||
<LI><CODE>(external?<I> x</I>) -> <I>boolean</I></CODE>
|
|
||||||
<LI><CODE>(external-name<I> external</I>) -> <I>string</I></CODE>
|
|
||||||
<LI><CODE>(external-value<I> external</I>) -> <I>byte-vector</I></CODE>
|
|
||||||
</UL>
|
|
||||||
These functions give access to values bound in the current process, and
|
|
||||||
are used for retrieving values from dynamically-loaded files.
|
|
||||||
<CODE>Get-external</CODE> returns an <I>external</I> object that contains the
|
|
||||||
value of <CODE><I>name</I></CODE>, raising an exception if there is no such
|
|
||||||
value in the current process.
|
|
||||||
<CODE>External?</CODE> is the predicate for externals, and
|
|
||||||
<CODE>external-name</CODE> and <CODE>external-value</CODE> return the name and
|
|
||||||
value of an external.
|
|
||||||
The value is returned as byte vector of length four (on 32-bit
|
|
||||||
architectures).
|
|
||||||
The value is that which was extant when <CODE>get-external</CODE> was
|
|
||||||
called.
|
|
||||||
The following two functions can be used to update the values of
|
|
||||||
externals.
|
|
||||||
<UL><LI><CODE>(lookup-external<I> external</I>) -> <I>boolean</I></CODE>
|
|
||||||
<LI><CODE>(lookup-all-externals<I></I>) -> <I>boolean</I></CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Lookup-external</CODE> updates the value of <CODE><I>external</I></CODE> by looking its
|
|
||||||
name in the current process, returning <CODE>#t</CODE> if it is bound and <CODE>#f</CODE>
|
|
||||||
if it is not.
|
|
||||||
<CODE>Lookup-all-externals</CODE> calls <CODE>lookup-external</CODE> on all extant
|
|
||||||
externals, returning <CODE>#f</CODE> any are unbound.
|
|
||||||
<UL><LI><CODE>(call-external<I> external arg<I><sub>0</sub></I> ...</I>) -> <I>value</I></CODE>
|
|
||||||
</UL>
|
|
||||||
An external whose value is a C procedure can be called using
|
|
||||||
<CODE>call-external</CODE>.
|
|
||||||
See
|
|
||||||
|
|
||||||
the section on <A HREF="#8">calling C functions from Scheme</A>
|
|
||||||
for more information.
|
|
||||||
<P>In some versions of Unix retrieving a value from the current
|
|
||||||
process may require a non-trivial amount of computation.
|
|
||||||
We recommend that a dynamically-loaded file contain a single initialization
|
|
||||||
procedure that creates shared bindings for the values exported by the file.
|
|
||||||
<H1><A NAME="11">Compatibility</A></H1>
|
|
||||||
<P>Scheme 48's old <CODE>external-call</CODE> function is still available in the structure
|
|
||||||
<CODE>externals</CODE>, which now also includes <CODE>external-name</CODE> and
|
|
||||||
<CODE>external-value</CODE>.
|
|
||||||
The old <CODE>scheme48.h</CODE> file has been renamed <CODE>old-scheme48.h</CODE>.
|
|
||||||
<H1><A NAME="12">Accessing Scheme data from C</A></H1>
|
|
||||||
|
|
||||||
<P>The C header file <CODE>scheme48.h</CODE> provides
|
|
||||||
access to Scheme 48 data structures
|
|
||||||
(for compatibility, the old <CODE>scheme48.h</CODE> file is available
|
|
||||||
as <CODE>old-scheme48.h</CODE>).
|
|
||||||
The type <CODE>s48_value</CODE> is used for Scheme values.
|
|
||||||
When the type of a value is known, such as the integer returned
|
|
||||||
by <CODE>vector-length</CODE> or the boolean returned by <CODE>pair?</CODE>,
|
|
||||||
the corresponding C procedure returns a C value of the appropriate
|
|
||||||
type, and not a <CODE>s48_value</CODE>.
|
|
||||||
Predicates return <CODE>1</CODE> for true and <CODE>0</CODE> for false.
|
|
||||||
<H2><A NAME="13">Constants</A></H2>
|
|
||||||
|
|
||||||
<P>The following macros denote Scheme constants:
|
|
||||||
<DL><DT><B><CODE>S48_FALSE</CODE></B><DD> is <CODE>#f</CODE>.
|
|
||||||
<DT><B><CODE>S48_TRUE</CODE></B><DD> is <CODE>#t</CODE>.
|
|
||||||
<DT><B><CODE>S48_NULL</CODE></B><DD> is the empty list.
|
|
||||||
<DT><B><CODE>S48_UNSPECIFIC</CODE></B><DD> is a value used for functions which have no
|
|
||||||
meaningful return value
|
|
||||||
(in Scheme this value returned by the nullary procedure <CODE>unspecific</CODE>
|
|
||||||
in the structure <CODE>util</CODE>).
|
|
||||||
<DT><B><CODE>S48_EOF</CODE></B><DD> is the end-of-file object
|
|
||||||
(in Scheme this value is returned by the nullary procedure <CODE>eof-object</CODE>
|
|
||||||
in the structure <CODE>i/o-internal</CODE>).
|
|
||||||
</DL>
|
|
||||||
<H2><A NAME="14">Converting values</A></H2>
|
|
||||||
<P>The following functions convert values between Scheme and C
|
|
||||||
representations.
|
|
||||||
The `extract' ones convert from Scheme to C and the `enter's go the other
|
|
||||||
way.
|
|
||||||
<UL><LI><CODE>unsigned char s48_extract_char(s48_value)</CODE>
|
|
||||||
<LI><CODE>char * s48_extract_string(s48_value)</CODE>
|
|
||||||
<LI><CODE>long s48_extract_integer(s48_value)</CODE>
|
|
||||||
<LI><CODE>double s48_extract_double(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value s48_enter_char(unsigned char)</CODE>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_enter_string(char *)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_enter_integer(long)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_enter_double(double)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
<P>The value returned by <CODE>s48_extract_string</CODE> points to the actual
|
|
||||||
storage used by the string; it is valid only until the next
|
|
||||||
<A HREF="#gc">garbage collection</A>.
|
|
||||||
<P><CODE>s48_enter_integer()</CODE> needs to allocate storage when
|
|
||||||
its argument is too large to fit in a Scheme 48 fixnum.
|
|
||||||
In cases where the number is known to fit within a fixnum (currently 30 bits
|
|
||||||
including the sign), the following procedures can be used.
|
|
||||||
These have the disadvantage of only having a limited range, but
|
|
||||||
the advantage of never causing a garbage collection.
|
|
||||||
<UL><LI><CODE>long s48_extract_fixnum(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value s48_enter_fixnum(long)</CODE>
|
|
||||||
<LI><CODE>long S48_MAX_FIXNUM_VALUE</CODE>
|
|
||||||
<LI><CODE>long S48_MIN_FIXNUM_VALUE</CODE>
|
|
||||||
</UL>
|
|
||||||
<P>An error is signalled if <CODE>s48_extract_fixnum</CODE>'s argument
|
|
||||||
is not a fixnum or if the argument to <CODE>s48_enter_fixnum</CODE> is less than
|
|
||||||
<CODE>S48_MIN_FIXNUM_VALUE</CODE> or greater than <CODE>S48_MAX_FIXNUM_VALUE</CODE>
|
|
||||||
(<I>-2<sup>29</sup></I> and <I>2<sup>29</sup>-1</I> in the current system).
|
|
||||||
<H2><A NAME="15">C versions of Scheme procedures</A></H2>
|
|
||||||
<P>The following macros and procedures are C versions of Scheme procedures.
|
|
||||||
The names were derived by replacing `<CODE>-</CODE>' with `<CODE>_</CODE>',
|
|
||||||
`<CODE>?</CODE>' with `<CODE>p</CODE>', and dropping `<CODE>!</CODE>.
|
|
||||||
<UL><LI><CODE>int S48_EQ_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>int S48_CHAR_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>int S48_INTEGER_P(s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>int S48_PAIR_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_CAR(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_CDR(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_SET_CAR(s48_value, s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_SET_CDR(s48_value, s48_value)</CODE>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_cons(s48_value, s48_value)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
<LI><CODE>long s48_length(s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>int S48_VECTOR_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>long S48_VECTOR_LENGTH(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_VECTOR_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_VECTOR_SET(s48_value, long, s48_value)</CODE>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_make_vector(long, s48_value)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>int S48_STRING_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>long S48_STRING_LENGTH(s48_value)</CODE>
|
|
||||||
<LI><CODE>char S48_STRING_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_STRING_SET(s48_value, long, char)</CODE>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_make_string(long, char)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>int S48_SYMBOL_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value s48_SYMBOL_TO_STRING(s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>int S48_BYTE_VECTOR_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>long S48_BYTE_VECTOR_LENGTH(s48_value)</CODE>
|
|
||||||
<LI><CODE>char S48_BYTE_VECTOR_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_BYTE_VECTOR_SET(s48_value, long, int)</CODE>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value s48_make_byte_vector(long, int)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
<H1><A NAME="16">Calling Scheme functions from C</A></H1>
|
|
||||||
|
|
||||||
<P>External code that has been called from Scheme can call back to Scheme
|
|
||||||
procedures using the following function.
|
|
||||||
<UL><LI><CODE>scheme_value s48_call_scheme(s48_value proc, long nargs, ...)</CODE>
|
|
||||||
</UL>
|
|
||||||
This calls the Scheme procedure <CODE>proc</CODE> on <CODE>nargs</CODE>
|
|
||||||
arguments, which are passed as additional arguments to <CODE>s48_call_scheme</CODE>.
|
|
||||||
There may be at most ten arguments.
|
|
||||||
The value returned by the Scheme procedure is returned by the C procedure.
|
|
||||||
Invoking any Scheme procedure may potentially cause a garbage collection.
|
|
||||||
<P>There are some complications that occur when mixing calls from C to Scheme
|
|
||||||
with continuations and threads.
|
|
||||||
C only supports downward continuations (via <CODE>longjmp()</CODE>).
|
|
||||||
Scheme continuations that capture a portion of the C stack have to follow the
|
|
||||||
same restriction.
|
|
||||||
For example, suppose Scheme procedure <CODE>s0</CODE> captures continuation <CODE>a</CODE>
|
|
||||||
and then calls C procedure <CODE>c0</CODE>, which in turn calls Scheme procedure
|
|
||||||
<CODE>s1</CODE>.
|
|
||||||
Procedure <CODE>s1</CODE> can safely call the continuation <CODE>a</CODE>, because that
|
|
||||||
is a downward use.
|
|
||||||
When <CODE>a</CODE> is called Scheme 48 will remove the portion of the C stack used
|
|
||||||
by the call to <CODE>c0</CODE>.
|
|
||||||
On the other hand, if <CODE>s1</CODE> captures a continuation, that continuation
|
|
||||||
cannot be used from <CODE>s0</CODE>, because by the time control returns to
|
|
||||||
<CODE>s0</CODE> the C stack used by <CODE>c0</CODE> will no longer be valid.
|
|
||||||
An attempt to invoke an upward continuation that is closed over a portion
|
|
||||||
of the C stack will raise an exception.
|
|
||||||
<P>In Scheme 48 threads are implemented using continuations, so the downward
|
|
||||||
restriction applies to them as well.
|
|
||||||
An attempt to return from Scheme to C at a time when the appropriate
|
|
||||||
C frame is not on top of the C stack will cause the current thread to
|
|
||||||
block until the frame is available.
|
|
||||||
For example, suppose thread <CODE>t0</CODE> calls a C procedure which calls back
|
|
||||||
to Scheme, at which point control switches to thread <CODE>t1</CODE>, which also
|
|
||||||
calls C and then back to Scheme.
|
|
||||||
At this point both <CODE>t0</CODE> and <CODE>t1</CODE> have active calls to C on the
|
|
||||||
C stack, with <CODE>t1</CODE>'s C frame above <CODE>t0</CODE>'s.
|
|
||||||
If thread <CODE>t0</CODE> attempts to return from Scheme to C it will block,
|
|
||||||
as its frame is not accessable.
|
|
||||||
Once <CODE>t1</CODE> has returned to C and from there to Scheme, <CODE>t0</CODE> will
|
|
||||||
be able to resume.
|
|
||||||
The return to Scheme is required because context switches can only occur while
|
|
||||||
C code is running.
|
|
||||||
<CODE>T0</CODE> will also be able to resume if <CODE>t1</CODE> uses a continuation to
|
|
||||||
throw past its call to C.
|
|
||||||
<H1><A NAME="gc">Interacting with the Scheme Heap</A></H1>
|
|
||||||
|
|
||||||
|
|
||||||
<P>Scheme 48 uses a copying, precise garbage collector.
|
|
||||||
Any procedure that allocates objects within the Scheme 48 heap may trigger
|
|
||||||
a garbage collection.
|
|
||||||
Variables bound to values in the Scheme 48 heap need to be registered with
|
|
||||||
the garbage collector so that the value will be retained and so that the
|
|
||||||
variables will be updated if the garbage collector moves the object.
|
|
||||||
The garbage collector has no facility for updating pointers to the interiors
|
|
||||||
of objects, so such pointers, for example the ones returned by
|
|
||||||
<CODE>EXTRACT_STRING</CODE>, will likely become invalid when a garbage collection
|
|
||||||
occurs.
|
|
||||||
<H2><A NAME="18">Registering Objects with the GC</A></H2>
|
|
||||||
|
|
||||||
<P>A set of macros are used to manage the registration of local variables with the
|
|
||||||
garbage collector.
|
|
||||||
<UL><LI><CODE>S48_DECLARE_GC_PROTECT(<I>n</I>)</CODE>
|
|
||||||
<LI><CODE>void S48_GC_PROTECT_<I>n</I>(s48_value<I><sub>1</sub></I>, <I>...</I>, s48_value<I><sub>n</sub></I>)</CODE>
|
|
||||||
<LI><CODE>void S48_GC_UNPROTECT()</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>S48_DECLARE_GC_PROTECT(<I>n</I>)</CODE>, where <I>1 <= n <= 9</I>, allocates
|
|
||||||
storage for registering <I>n</I> variables.
|
|
||||||
At most one use of <CODE>S48_DECLARE_GC_PROTECT</CODE> may occur in a block.
|
|
||||||
<CODE>S48_GC_PROTECT_<I>n</I>(<I>v<sub>1</sub></I>, <I>...</I>, <I>v<sub>n</sub></I>)</CODE> registers the
|
|
||||||
<I>n</I> variables (l-values) with the garbage collector.
|
|
||||||
It must be within scope of a <CODE>S48_DECLARE_GC_PROTECT(<I>n</I>)</CODE>
|
|
||||||
and be before any code which can cause a GC.
|
|
||||||
<CODE>S48_GC_UNPROTECT</CODE> removes the block's protected variables from
|
|
||||||
the garbage collectors list.
|
|
||||||
It must be called at the end of the block after
|
|
||||||
any code which may cause a garbage collection.
|
|
||||||
Omitting any of the three may cause serious and
|
|
||||||
hard-to-debug problems.
|
|
||||||
Notably, the garbage collector may relocate an object and
|
|
||||||
invalidate <CODE>s48_value</CODE> variables which are not protected.
|
|
||||||
<P>A <CODE>gc-protection-mismatch</CODE> exception is raised if, when a C
|
|
||||||
procedure returns to Scheme, the calls
|
|
||||||
to <CODE>S48_GC_PROTECT()</CODE> have not been matched by an equal number of
|
|
||||||
calls to <CODE>S48_GC_UNPROTECT()</CODE>.
|
|
||||||
<P>Global variables may also be registered with the garbage collector.
|
|
||||||
<UL><LI><CODE>void S48_GC_PROTECT_GLOBAL(<CODE><I>value</I></CODE>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>S48_GC_PROTECT_GLOBAL</CODE> permanently registers the
|
|
||||||
variable <CODE><I>value</I></CODE> (an l-value) with the garbage collector.
|
|
||||||
There is no way to unregister the variable.
|
|
||||||
<H2><A NAME="19">Keeping C data structures in the Scheme heap</A></H2>
|
|
||||||
|
|
||||||
<P>C data structures can be kept in the Scheme heap by embedding them
|
|
||||||
inside byte vectors.
|
|
||||||
The following macros can be used to create and access embedded C objects.
|
|
||||||
<UL><LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value S48_MAKE_VALUE(type)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
<LI><CODE>type S48_EXTRACT_VALUE(s48_value, type)</CODE>
|
|
||||||
<LI><CODE>type * S48_EXTRACT_VALUE_POINTER(s48_value, type)</CODE>
|
|
||||||
<LI><CODE>void S48_SET_VALUE(s48_value, type, value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>S48_MAKE_VALUE</CODE> makes a byte vector large enough to hold an object
|
|
||||||
whose type is <CODE><I>type</I></CODE>.
|
|
||||||
<CODE>S48_EXTRACT_VALUE</CODE> returns the contents of a byte vector cast to
|
|
||||||
<CODE><I>type</I></CODE>, and <CODE>S48_EXTRACT_VALUE_POINTER</CODE> returns a pointer
|
|
||||||
to the contents of the byte vector.
|
|
||||||
The value returned by <CODE>S48_EXTRACT_VALUE_POINTER</CODE> is valid only until
|
|
||||||
the next <A HREF="#gc">garbage collection</A>.
|
|
||||||
<P><CODE>S48_SET_VALUE</CODE> stores <CODE>value</CODE> into the byte vector.
|
|
||||||
<H2><A NAME="20">C code and heap images</A></H2>
|
|
||||||
|
|
||||||
<P>Scheme 48 uses dumped heap images to restore a previous system state.
|
|
||||||
The Scheme 48 heap is written into a file in a machine-independent and
|
|
||||||
operating-system-independent format.
|
|
||||||
The procedures described above may be used to create objects in the
|
|
||||||
Scheme heap that contain information specific to the current
|
|
||||||
machine, operating system, or process.
|
|
||||||
A heap image containing such objects may not work correctly on
|
|
||||||
when resumed.
|
|
||||||
<P>To address this problem, a record type may be given a `resumer'
|
|
||||||
procedure.
|
|
||||||
On startup, the resumer procedure for a type is applied to each record of
|
|
||||||
that type in the image being restarted.
|
|
||||||
This procedure can update the record in a manner appropriate to
|
|
||||||
the machine, operating system, or process used to resume the
|
|
||||||
image.
|
|
||||||
<UL><LI><CODE>(define-record-resumer<I> record-type procedure</I>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>Define-record-resumer</CODE> defines <CODE><I>procedure</I></CODE>,
|
|
||||||
which should accept one argument, to be the resumer for
|
|
||||||
<I>record-type</I>.
|
|
||||||
The order in which resumer procedures are called is not specified.
|
|
||||||
<P>The <CODE><I>procedure</I></CODE> argument to <CODE>define-record-resumer</CODE> may
|
|
||||||
be <CODE>#f</CODE>, in which case records of the given type are
|
|
||||||
not written out in heap images.
|
|
||||||
When writing a heap image any reference to such a record is replaced by
|
|
||||||
the value of the record's first field, and an exception is raised
|
|
||||||
after the image is written.
|
|
||||||
<H1><A NAME="21">Using Scheme records in C code</A></H1>
|
|
||||||
<P>External modules can create records and access their slots
|
|
||||||
positionally.
|
|
||||||
<UL><LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>s48_value S48_MAKE_RECORD(s48_value)</CODE></td> <td align=right>(may GC)</td></tr></table>
|
|
||||||
<LI><CODE>int S48_RECORD_P(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_RECORD_TYPE(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_RECORD_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_RECORD_SET(s48_value, long, s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
The argument to <CODE>S48_MAKE_RECORD</CODE> should be a shared binding
|
|
||||||
whose value is a record type.
|
|
||||||
In C the fields of Scheme records are only accessible via offsets,
|
|
||||||
with the first field having offset zero, the second offset one, and
|
|
||||||
so forth.
|
|
||||||
If the order of the fields is changed in the Scheme definition of the
|
|
||||||
record type the C code must be updated as well.
|
|
||||||
<P>For example, given the following record-type definition
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-record-type thing :thing
|
|
||||||
(make-thing a b)
|
|
||||||
thing?
|
|
||||||
(a thing-a)
|
|
||||||
(b thing-b))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
the identifier <CODE>:thing</CODE> is bound to the record type and can
|
|
||||||
be exported to C:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-exported-binding "thing-record-type" :thing)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<CODE>Thing</CODE> records can then be made in C:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
static scheme_value thing_record_type_binding = SCHFALSE;
|
|
||||||
|
|
||||||
void initialize_things(void)
|
|
||||||
{
|
|
||||||
S48_GC_PROTECT_GLOBAL(thing_record_type_binding);
|
|
||||||
thing_record_type_binding =
|
|
||||||
s48_get_imported_binding("thing-record-type");
|
|
||||||
}
|
|
||||||
|
|
||||||
scheme_value make_thing(scheme_value a, scheme_value b)
|
|
||||||
{
|
|
||||||
s48_value thing;
|
|
||||||
s48_DECLARE_GC_PROTECT(2);
|
|
||||||
|
|
||||||
S48_GC_PROTECT_2(a, b);
|
|
||||||
|
|
||||||
thing = s48_make_record(thing_record_type_binding);
|
|
||||||
S48_RECORD_SET(thing, 0, a);
|
|
||||||
S48_RECORD_SET(thing, 1, b);
|
|
||||||
|
|
||||||
S48_GC_UNPROTECT();
|
|
||||||
|
|
||||||
return thing;
|
|
||||||
}
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
Note that the variables <CODE>a</CODE> and <CODE>b</CODE> must be protected
|
|
||||||
against the possibility of a garbage collection occuring during
|
|
||||||
the call to <CODE>s48_make_record()</CODE>.
|
|
||||||
<H1><A NAME="22">Raising exceptions from external code</A></H1>
|
|
||||||
|
|
||||||
<P>The following macros explicitly raise certain errors, immediately
|
|
||||||
returning to Scheme 48.
|
|
||||||
Raising an exception performs all
|
|
||||||
necessary clean-up actions to properly return to Scheme 48, including
|
|
||||||
adjusting the stack of protected variables.
|
|
||||||
<UL><LI><CODE>s48_raise_scheme_exception(int type, int nargs, ...)</CODE>
|
|
||||||
</UL>
|
|
||||||
<P><CODE>s48_raise_scheme_exception</CODE> is the base procedure for
|
|
||||||
raising exceptions.
|
|
||||||
<CODE>type</CODE> is the type of exception, and should be one of the
|
|
||||||
<CODE>S48_EXCEPTION_</CODE>...constants defined in <CODE>scheme48arch.h</CODE>.
|
|
||||||
<CODE>nargs</CODE> is the number of additional values to be included in the
|
|
||||||
exception; these follow the <CODE>nargs</CODE> argument and should all have
|
|
||||||
type <CODE>s48_value</CODE>.
|
|
||||||
<CODE>s48_raise_scheme_exception</CODE> never returns.
|
|
||||||
<P>The following procedures are available for raising particular
|
|
||||||
types of exceptions.
|
|
||||||
Like <CODE>s48_raise_scheme_exception</CODE> these never return.
|
|
||||||
<UL><LI><CODE>s48_raise_argument_type_error(scheme_value)</CODE>
|
|
||||||
<LI><CODE>s48_raise_argument_number_error(int nargs, int min, int max)</CODE>
|
|
||||||
<LI><CODE>s48_raise_index_range_error(long value, long min, long max)</CODE>
|
|
||||||
<LI><CODE>s48_raise_closed_channel_error()</CODE>
|
|
||||||
<LI><CODE>s48_raise_os_error(int errno)</CODE>
|
|
||||||
<LI><CODE>s48_raise_out_of_memory_error()</CODE>
|
|
||||||
</UL>
|
|
||||||
<P>An argument type error indicates that the given value is of the wrong
|
|
||||||
type.
|
|
||||||
An argument number error is raised when the number of arguments, <CODE>nargs</CODE>,
|
|
||||||
should be, but isn't, between <CODE>min</CODE> and <CODE>max</CODE>, inclusive.
|
|
||||||
Similarly, and index range error is raised when <CODE>value</CODE> is not between
|
|
||||||
between <CODE>min</CODE> and <CODE>max</CODE>, inclusive.
|
|
||||||
<P>The following macros raise argument type errors if their argument does not
|
|
||||||
have the required type.
|
|
||||||
<UL><LI><CODE>void S48_CHECK_SYMBOL(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_PAIR(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_STRING(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_INTEGER(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_CHANNEL(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_BYTE_VECTOR(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_RECORD(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_CHECK_SHARED_BINDING(s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<H1><A NAME="23">Unsafe functions and macros</A></H1>
|
|
||||||
<P>All of the C procedures and macros described above check that their
|
|
||||||
arguments have the appropriate types and that indexes are in range.
|
|
||||||
The following procedures and macros are identical to those described
|
|
||||||
above, except that they do not perform type and range checks.
|
|
||||||
They are provided for the purpose of writing more efficient code;
|
|
||||||
their general use is not recommended.
|
|
||||||
<UL><LI><CODE>char S48_UNSAFE_EXTRACT_CHAR(s48_value)</CODE>
|
|
||||||
<LI><CODE>char * S48_UNSAFE_EXTRACT_STRING(s48_value)</CODE>
|
|
||||||
<LI><CODE>long S48_UNSAFE_EXTRACT_INTEGER(s48_value)</CODE>
|
|
||||||
<LI><CODE>long S48_UNSAFE_EXTRACT_DOUBLE(s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>long S48_UNSAFE_EXTRACT_FIXNUM(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_UNSAFE_ENTER_FIXNUM(long)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>s48_value S48_UNSAFE_CAR(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_UNSAFE_CDR(s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_SET_CAR(s48_value, s48_value)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_SET_CDR(s48_value, s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>long S48_UNSAFE_VECTOR_LENGTH(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_UNSAFE_VECTOR_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_VECTOR_SET(s48_value, long, s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>long S48_UNSAFE_STRING_LENGTH(s48_value)</CODE>
|
|
||||||
<LI><CODE>char S48_UNSAFE_STRING_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_STRING_SET(s48_value, long, char)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>s48_value S48_UNSAFE_SYMBOL_TO_STRING(s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>long S48_UNSAFE_BYTE_VECTOR_LENGTH(s48_value)</CODE>
|
|
||||||
<LI><CODE>char S48_UNSAFE_BYTE_VECTOR_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_BYTE_VECTOR_SET(s48_value, long, int)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>s48_value S48_UNSAFE_SHARED_BINDING_REF(s48_value s_b)</CODE>
|
|
||||||
<LI><CODE>int S48_UNSAFE_SHARED_BINDING_P(x)</CODE>
|
|
||||||
<LI><CODE>int S48_UNSAFE_SHARED_BINDING_IS_IMPORT_P(s48_value s_b)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_UNSAFE_SHARED_BINDING_NAME(s48_value s_b)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_SHARED_BINDING_SET(s48_value s_b, s48_value value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>s48_value S48_UNSAFE_RECORD_TYPE(s48_value)</CODE>
|
|
||||||
<LI><CODE>s48_value S48_UNSAFE_RECORD_REF(s48_value, long)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_RECORD_SET(s48_value, long, s48_value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<UL><LI><CODE>type S48_UNSAFE_EXTRACT_VALUE(s48_value, type)</CODE>
|
|
||||||
<LI><CODE>type * S48_UNSAFE_EXTRACT_VALUE_POINTER(s48_value, type)</CODE>
|
|
||||||
<LI><CODE>void S48_UNSAFE_SET_VALUE(s48_value, type, value)</CODE>
|
|
||||||
</UL>
|
|
||||||
<HR ><ADDRESS><a href="http://www-pu.informatik.uni-tuebingen.de/users/sperber/">Mike
|
|
||||||
Sperber</a>, <a href="http://www.neci.nj.nec.com/homepages/kelsey/">Richard Kelsey</a></ADDRESS><BR>
|
|
||||||
</BODY></HTML>
|
|
||||||
|
|
@ -1,315 +0,0 @@
|
||||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
|
|
||||||
<HTML>
|
|
||||||
<!-- HTML file produced from file: utilities.tex --
|
|
||||||
-- using Hyperlatex v 2.3.1 (c) Otfried Cheong--
|
|
||||||
-- on Emacs 19.34.1, Tue Feb 23 18:25:11 1999 -->
|
|
||||||
<HEAD>
|
|
||||||
<TITLE>Untitled</TITLE>
|
|
||||||
|
|
||||||
</HEAD><BODY>
|
|
||||||
|
|
||||||
|
|
||||||
<H1 ALIGN=CENTER>Scheme 48 User's Guide</H1>
|
|
||||||
<H2 ALIGN=CENTER>Richard A. Kelsey</H2>
|
|
||||||
<H3 ALIGN=CENTER>February 23, 1999</H3>
|
|
||||||
<H1><A NAME="1">ASCII character encoding</A></H1>
|
|
||||||
<P>These are in the structure <CODE>ascii</CODE>.
|
|
||||||
<UL><LI><CODE>(char->ascii<VAR> char</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
<LI><CODE>(ascii->char<VAR> integer</VAR>) -> <VAR>char</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
These are identical to <CODE>char->integer</CODE> and <CODE>integer->char</CODE> except that
|
|
||||||
they use the ASCII encoding.
|
|
||||||
<UL><LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>ascii-limit</CODE></td> <td align=right>integer</td></tr></table>
|
|
||||||
<LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE>ascii-whitespaces</CODE></td> <td align=right>list of integers</td></tr></table>
|
|
||||||
</UL>
|
|
||||||
<CODE>Ascii-limit</CODE> is one more than the largest value that <CODE>char->ascii</CODE>
|
|
||||||
may return.
|
|
||||||
<CODE>Ascii-whitespaces</CODE> is a list of the ASCII values of whitespace characters
|
|
||||||
(space, tab, line feed, form feed, and carriage return).
|
|
||||||
<H1><A NAME="2">Bitwise integer operations</A></H1>
|
|
||||||
<P>These functions use the two's-complement representation for integers.
|
|
||||||
There is no limit to the number of bits in an integer.
|
|
||||||
They are in the structures <CODE>bitwise</CODE> and <CODE>big-scheme</CODE>.
|
|
||||||
<UL><LI><CODE>(bitwise-and<VAR> integer integer</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
<LI><CODE>(bitwise-ior<VAR> integer integer</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
<LI><CODE>(bitwise-xor<VAR> integer integer</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
<LI><CODE>(bitwise-not<VAR> integer</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
These perform various logical operations on integers on a bit-by-bit
|
|
||||||
basis. `<CODE>ior</CODE>' is inclusive OR and `<CODE>xor</CODE>' is exclusive OR.
|
|
||||||
<UL><LI><CODE>(arithmetic-shift<VAR> integer bit-count</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
Shifts the integer by the given bit count, which must be an integer,
|
|
||||||
shifting left for positive counts and right for negative ones.
|
|
||||||
Shifting preserves the integer's sign.
|
|
||||||
<H1><A NAME="3">Arrays</A></H1>
|
|
||||||
<P>These are N-dimensional, zero-based arrays and
|
|
||||||
are in the structure <CODE>arrays</CODE>.
|
|
||||||
<P>The array interface is derived from one written by Alan Bawden.
|
|
||||||
<UL><LI><CODE>(make-array<VAR> value dimension<I><sub>0</sub></I> ...</VAR>) -> <VAR>array</VAR></CODE>
|
|
||||||
<LI><CODE>(array<VAR> dimensions element<I><sub>0</sub></I> ...</VAR>) -> <VAR>array</VAR></CODE>
|
|
||||||
<LI><CODE>(copy-array<VAR> array</VAR>) -> <VAR>array</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Make-array</CODE> makes a new array with the given dimensions, each of which
|
|
||||||
must be a non-negative integer.
|
|
||||||
Every element is initially set to <CODE><VAR>value</VAR></CODE>.
|
|
||||||
<CODE>Array</CODE> Returns a new array with the given dimensions and elements.
|
|
||||||
<CODE><VAR>Dimensions</VAR></CODE> must be a list of non-negative integers,
|
|
||||||
The number of elements should be the equal to the product of the
|
|
||||||
dimensions.
|
|
||||||
The elements are stored in row-major order.
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(make-array 'a 2 3) <CODE>-></CODE> {Array 2 3}
|
|
||||||
|
|
||||||
(array '(2 3) 'a 'b 'c 'd 'e 'f)
|
|
||||||
<CODE>-></CODE> {Array 2 3}
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<P><CODE>Copy-array</CODE> returns a copy of <CODE><VAR>array</VAR></CODE>.
|
|
||||||
The copy is identical to the <CODE><VAR>array</VAR></CODE> but does not share storage with it.
|
|
||||||
<UL><LI><CODE>(array?<VAR> value</VAR>) -> <VAR>boolean</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
Returns <CODE>#t</CODE> if <CODE><VAR>value</VAR></CODE> is an array.
|
|
||||||
<UL><LI><CODE>(array-ref<VAR> array index<I><sub>0</sub></I> ...</VAR>) -> <VAR>value</VAR></CODE>
|
|
||||||
<LI><CODE>(array-set!<VAR> array value index<I><sub>0</sub></I> ...</VAR>)</CODE>
|
|
||||||
<LI><CODE>(array->vector<VAR> array</VAR>) -> <VAR>vector</VAR></CODE>
|
|
||||||
<LI><CODE>(array-dimensions<VAR> array</VAR>) -> <VAR>list</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Array-ref</CODE> returns the specified array element and <CODE>array-set!</CODE>
|
|
||||||
replaces the element with <CODE><VAR>value</VAR></CODE>.
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(let ((a (array '(2 3) 'a 'b 'c 'd 'e 'f)))
|
|
||||||
(let ((x (array-ref a 0 1)))
|
|
||||||
(array-set! a 'g 0 1)
|
|
||||||
(list x (array-ref a 0 1))))
|
|
||||||
<CODE>-></CODE> '(b g)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<P><CODE>Array->vector</CODE> returns a vector containing the elements of <CODE><VAR>array</VAR></CODE>
|
|
||||||
in row-major order.
|
|
||||||
<CODE>Array-dimensions</CODE> returns the dimensions of
|
|
||||||
the array as a list.
|
|
||||||
<UL><LI><CODE>(make-shared-array<VAR> array linear-map dimension<I><sub>0</sub></I> ...</VAR>) -> <VAR>array</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Make-shared-array</CODE> makes a new array that shares storage with <CODE><VAR>array</VAR></CODE>
|
|
||||||
and uses <CODE><VAR>linear-map</VAR></CODE> to map indicies to elements.
|
|
||||||
<CODE><VAR>Linear-map</VAR></CODE> must accept as many arguments as the number of
|
|
||||||
<CODE><VAR>dimension</VAR></CODE>s given and must return a list of non-negative integers
|
|
||||||
that are valid indicies into <CODE><VAR>array</VAR></CODE>.
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(array-ref (make-shared-array a f i0 i1 ...)
|
|
||||||
j0 j1 ...)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
is equivalent to
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(apply array-ref a (f j0 j1 ...))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<P>As an example, the following function makes the transpose of a two-dimensional
|
|
||||||
array:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define (transpose array)
|
|
||||||
(let ((dimensions (array-dimensions array)))
|
|
||||||
(make-shared-array array
|
|
||||||
(lambda (x y)
|
|
||||||
(list y x))
|
|
||||||
(cadr dimensions)
|
|
||||||
(car dimensions))))
|
|
||||||
|
|
||||||
(array->vector
|
|
||||||
(transpose
|
|
||||||
(array '(2 3) 'a 'b 'c 'd 'e 'f)))
|
|
||||||
<CODE>-></CODE> '(a d b e c f)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<H1><A NAME="4">Records</A></H1>
|
|
||||||
<P>New types can be constructed using the <CODE>define-record-type</CODE> macro
|
|
||||||
from the <CODE>define-record-types</CODE> structure
|
|
||||||
The general syntax is:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-record-type <CODE><VAR>tag</VAR></CODE> <CODE><VAR>type-name</VAR></CODE>
|
|
||||||
(<CODE><VAR>constructor-name</VAR></CODE> <CODE><VAR>field-tag</VAR></CODE> ...)
|
|
||||||
<CODE><VAR>predicate-name</VAR></CODE>
|
|
||||||
(<CODE><VAR>field-tag</VAR></CODE> <CODE><VAR>accessor-name</VAR></CODE> [<CODE><VAR>modifier-name</VAR></CODE>])
|
|
||||||
...)
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
This makes the following definitions:
|
|
||||||
<UL><LI><table border=0 cellspacing=0 cellpadding=0 width=80%>
|
|
||||||
<tr> <td><CODE><CODE><VAR>type-name</VAR></CODE></CODE></td> <td align=right>type</td></tr></table>
|
|
||||||
<LI><CODE>(<CODE><VAR>constructor-name</VAR></CODE><VAR> field-init ...</VAR>) -> <VAR>type-name</VAR></CODE>
|
|
||||||
<LI><CODE>(<CODE><VAR>predicate-name</VAR></CODE><VAR> value</VAR>) -> <VAR>boolean</VAR></CODE>
|
|
||||||
<LI><CODE>(<CODE><VAR>accessor-name</VAR></CODE><VAR> type-name</VAR>) -> <VAR>value</VAR></CODE>
|
|
||||||
<LI><CODE>(<CODE><VAR>modifier-name</VAR></CODE><VAR> type-name value</VAR>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE><VAR>Type-name</VAR></CODE> is the record type itself, and can be used to
|
|
||||||
specify a print method (see below).
|
|
||||||
<CODE><VAR>Constructor-name</VAR></CODE> is a constructor that accepts values
|
|
||||||
for the fields whose tags are specified.
|
|
||||||
<CODE><VAR>Predicate-name</VAR></CODE> to a predicate that can returns <CODE>#t</CODE> for
|
|
||||||
elements of the type and <CODE>#f</CODE> for everything else.
|
|
||||||
The <CODE><VAR>accessor-name</VAR></CODE>s retrieve the values of fields,
|
|
||||||
and the <CODE><VAR>modifier-name</VAR></CODE>'s update them.
|
|
||||||
The <CODE><VAR>tag</VAR></CODE> is used in printing instances of the record type and
|
|
||||||
the field tags are used in the inspector and to match
|
|
||||||
constructor arguments with fields.
|
|
||||||
<UL><LI><CODE>(define-record-discloser<VAR> type discloser</VAR>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Define-record-discloser</CODE> determines how
|
|
||||||
records of type <CODE><VAR>type</VAR></CODE> are printed.
|
|
||||||
<CODE><VAR>Discloser</VAR></CODE> should be procedure which takes a single
|
|
||||||
record of type <CODE><VAR>type</VAR></CODE> and returns a list whose car is
|
|
||||||
a symbol.
|
|
||||||
The record will be printed as the value returned by <CODE><VAR>discloser</VAR></CODE>
|
|
||||||
with curly braces used instead of the usual parenthesis.
|
|
||||||
<P>For example
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-record-type pare :pare
|
|
||||||
(kons x y)
|
|
||||||
pare?
|
|
||||||
(x kar set-kar!)
|
|
||||||
(y kdr))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
defines <CODE>kons</CODE> to be a constructor, <CODE>kar</CODE> and <CODE>kdr</CODE> to be
|
|
||||||
accessors, <CODE>set-kar!</CODE> to be a modifier, and <CODE>pare?</CODE> to be a predicate
|
|
||||||
for a new type of object.
|
|
||||||
The type itself is named <CODE>:pare</CODE>.
|
|
||||||
<CODE>Pare</CODE> is a tag used in printing the new objects.
|
|
||||||
<P>By default, the new objects print as <CODE>#Pare</CODE>.
|
|
||||||
The print method can be modified using DEFINE-RECORD-DISCLOSER:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-record-discloser :pare
|
|
||||||
(lambda (p) `(pare ,(kar p) ,(kdr p))))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
will cause the result of <CODE>(kons 1 2)</CODE> to print as
|
|
||||||
<CODE>#{pare 1 2}</CODE>.
|
|
||||||
<H1><A NAME="5">Finite record types</A></H1>
|
|
||||||
<P>The structure <CODE>finite-types</CODE> has
|
|
||||||
two macros for defining `finite' record types.
|
|
||||||
These are record types for which there are a fixed number of instances,
|
|
||||||
which are created when the record type is defined.
|
|
||||||
The syntax for the defining a finite type is:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-finite-type <CODE><VAR>tag</VAR></CODE> <CODE><VAR>type-name</VAR></CODE>
|
|
||||||
(<CODE><VAR>field-tag</VAR></CODE> ...)
|
|
||||||
<CODE><VAR>predicate-name</VAR></CODE>
|
|
||||||
<CODE><VAR>vector-of-elements-name</VAR></CODE>
|
|
||||||
<CODE><VAR>name-accessor</VAR></CODE>
|
|
||||||
<CODE><VAR>index-accessor</VAR></CODE>
|
|
||||||
(<CODE><VAR>field-tag</VAR></CODE> <CODE><VAR>accessor-name</VAR></CODE> [<CODE><VAR>modifier-name</VAR></CODE>])
|
|
||||||
...
|
|
||||||
((<CODE><VAR>element-name</VAR></CODE> <CODE><VAR>field-value</VAR></CODE> ...)
|
|
||||||
...))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
This differs from <CODE>define-record-type</CODE> in the following ways:
|
|
||||||
<UL><LI>No name is specified for the constructor, but the field arguments
|
|
||||||
to the constructor are listed.
|
|
||||||
<LI>The <CODE><VAR>vector-of-elements-name</VAR></CODE> is added; it will be bound
|
|
||||||
to a vector containing all of the elements of the type.
|
|
||||||
These are constructed by applying the (unnamed) constructor to the
|
|
||||||
initial field values at the end of the form.
|
|
||||||
<LI>There are names for accessors for two required fields, name
|
|
||||||
and index.
|
|
||||||
These fields are not settable, and are not to be included
|
|
||||||
in the argument list for the constructor.
|
|
||||||
<LI>The form ends with the names and the initial field values for
|
|
||||||
the elements of the type.
|
|
||||||
The name must be first.
|
|
||||||
The remaining values must match the <CODE><VAR>field-tag</VAR></CODE>s in the constructor's
|
|
||||||
argument list.
|
|
||||||
<LI><CODE><VAR>Tag</VAR></CODE> is bound to a macro that maps <CODE><VAR>element-name</VAR></CODE>s to the
|
|
||||||
the corresponding element of the vector.
|
|
||||||
The name lookup is done at macro-expansion time.
|
|
||||||
</UL>
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-finite-type color :color
|
|
||||||
(red green blue)
|
|
||||||
color?
|
|
||||||
colors
|
|
||||||
color-name
|
|
||||||
color-index
|
|
||||||
(red color-red)
|
|
||||||
(green color-green)
|
|
||||||
(blue color-blue)
|
|
||||||
((white 255 255 255)
|
|
||||||
(black 0 0 0)
|
|
||||||
(yellow 255 255 0)
|
|
||||||
(maroon 176 48 96)))
|
|
||||||
|
|
||||||
(color-name (vector-ref colors 0)) <CODE>-></CODE> white
|
|
||||||
(color-name (color black)) <CODE>-></CODE> black
|
|
||||||
(color-index (color yellow)) <CODE>-></CODE> 2
|
|
||||||
(color-red (color maroon)) <CODE>-></CODE> 176
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<P>Enumerated types are finite types whose only fields are the name
|
|
||||||
and the index.
|
|
||||||
The syntax for defining an enumerated type is:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-enumerated-type <CODE><VAR>tag</VAR></CODE> <CODE><VAR>type-name</VAR></CODE>
|
|
||||||
<CODE><VAR>predicate-name</VAR></CODE>
|
|
||||||
<CODE><VAR>vector-of-elements-name</VAR></CODE>
|
|
||||||
<CODE><VAR>name-accessor</VAR></CODE>
|
|
||||||
<CODE><VAR>index-accessor</VAR></CODE>
|
|
||||||
(<CODE><VAR>element-name</VAR></CODE> ...))
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
In the absence of any additional fields, both the constructor argument
|
|
||||||
list and the initial field values are not required.
|
|
||||||
<P>The above example of a finite type can be pared down to the following
|
|
||||||
enumerated type:
|
|
||||||
<BLOCKQUOTE><PRE>
|
|
||||||
(define-enumerated-type color :color
|
|
||||||
color?
|
|
||||||
colors
|
|
||||||
color-name
|
|
||||||
color-index
|
|
||||||
(white black yellow maroon))
|
|
||||||
|
|
||||||
(color-name (vector-ref colors 0)) <CODE>-></CODE> white
|
|
||||||
(color-name (color black)) <CODE>-></CODE> black
|
|
||||||
(color-index (color yellow)) <CODE>-></CODE> 2
|
|
||||||
</PRE></BLOCKQUOTE>
|
|
||||||
<H1><A NAME="6">Hash tables</A></H1>
|
|
||||||
<P>These are generic hash tables, and are in the structure <CODE>tables</CODE>.
|
|
||||||
Strictly speaking they are more maps than tables, as every table has a
|
|
||||||
value for every possible key (for that type of table).
|
|
||||||
All but a finite number of those values are <CODE>#f</CODE>.
|
|
||||||
<UL><LI><CODE>(make-table<VAR></VAR>) -> <VAR>table</VAR></CODE>
|
|
||||||
<LI><CODE>(make-symbol-table<VAR></VAR>) -> <VAR>symbol-table</VAR></CODE>
|
|
||||||
<LI><CODE>(make-string-table<VAR></VAR>) -> <VAR>string-table</VAR></CODE>
|
|
||||||
<LI><CODE>(make-integer-table<VAR></VAR>) -> <VAR>integer-table</VAR></CODE>
|
|
||||||
<LI><CODE>(make-table-maker<VAR> compare-proc hash-proc</VAR>) -> <VAR>procedure</VAR></CODE>
|
|
||||||
<LI><CODE>(make-table-immutable!<VAR> table</VAR>)</CODE>
|
|
||||||
</UL>
|
|
||||||
The first four functions listed make various kinds of tables.
|
|
||||||
<CODE>Make-table</CODE> returns a table whose keys may be symbols, integer,
|
|
||||||
characters, booleans, or the empty list (these are also the values
|
|
||||||
that may be used in <CODE>case</CODE> expressions).
|
|
||||||
As with <CODE>case</CODE>, comparison is done using <CODE>eqv?</CODE>.
|
|
||||||
The comparison procedures used in symbol, string, and integer tables are
|
|
||||||
<CODE>eq?</CODE>, <CODE>string=?</CODE>, and <CODE>=</CODE>.
|
|
||||||
<P><CODE>Make-table-maker</CODE> takes two procedures as arguments and returns
|
|
||||||
a nullary table-making procedure.
|
|
||||||
<CODE><VAR>Compare-proc</VAR></CODE> should be a two-argument equality predicate.
|
|
||||||
<CODE><VAR>Hash-proc</VAR></CODE> should be a one argument procedure that takes a key
|
|
||||||
and returns a non-negative integer hash value.
|
|
||||||
If <CODE>(<CODE><VAR>compare-proc</VAR></CODE> <CODE><VAR>x</VAR></CODE> <CODE><VAR>y</VAR></CODE>)</CODE> returns true,
|
|
||||||
then <CODE>(= (<CODE><VAR>hash-proc</VAR></CODE> <CODE><VAR>x</VAR></CODE>) (<CODE><VAR>hash-proc</VAR></CODE> <CODE><VAR>y</VAR></CODE>))</CODE>
|
|
||||||
must also return true.
|
|
||||||
For example, <CODE>make-integer-table</CODE> could be defined
|
|
||||||
as <CODE>(make-table-maker = abs)</CODE>.
|
|
||||||
<P><CODE>Make-table-immutable!</CODE> prohibits future modification to its argument.
|
|
||||||
<UL><LI><CODE>(table?<VAR> value</VAR>) -> <VAR>boolean</VAR></CODE>
|
|
||||||
<LI><CODE>(table-ref<VAR> table key</VAR>) -> <VAR>value or <CODE>#f</CODE></VAR></CODE>
|
|
||||||
<LI><CODE>(table-set!<VAR> table key value</VAR>)</CODE>
|
|
||||||
<LI><CODE>(table-walk<VAR> procedure table</VAR>)</CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>Table?</CODE> is the predicate for tables.
|
|
||||||
<CODE>Table-ref</CODE> and <CODE>table-set!</CODE> access and modify the value of <CODE><VAR>key</VAR></CODE>
|
|
||||||
in <CODE><VAR>table</VAR></CODE>.
|
|
||||||
<CODE>Table-walk</CODE> applies <CODE><VAR>procedure</VAR></CODE>, which must accept two arguments,
|
|
||||||
to every associated key and non-<CODE>#f</CODE> value in <CODE>table</CODE>.
|
|
||||||
<UL><LI><CODE>(default-hash-function<VAR> value</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
<LI><CODE>(string-hash<VAR> string</VAR>) -> <VAR>integer</VAR></CODE>
|
|
||||||
</UL>
|
|
||||||
<CODE>default-hash-function</CODE> is the hash function used in the tables
|
|
||||||
returned by <CODE>make-table</CODE>, and <CODE>string-hash</CODE> it the one used
|
|
||||||
by <CODE>make-string-table</CODE>.
|
|
||||||
<HR >
|
|
||||||
</BODY></HTML>
|
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
-*- Mode: Indented-text; -*-
|
||||||
|
|
||||||
|
Here are some remarks to complement what's in the INSTALL file.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
When running "make", don't worry if the ".notify" target fails. Its
|
||||||
|
only purpose is to send an email message to
|
||||||
|
scheme-48-notifications@martigny.ai.mit.edu, so that we can get a
|
||||||
|
rough idea of how much Scheme 48 is being used and by whom. We
|
||||||
|
promise not to use your name or email address for any commercial
|
||||||
|
purpose. If you don't want us to know, just do "make -t .notify"
|
||||||
|
first.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Customizing the installation
|
||||||
|
|
||||||
|
1. If you don't believe in configure scripts, or don't have a
|
||||||
|
/bin/sh that can handle the configure script, you can make
|
||||||
|
sysdep.h and Makefile manually from sysdep.h.in and Makefile.in.
|
||||||
|
The technique is fairly obvious. For Makefile, just give
|
||||||
|
reasonable values for all of the variables at the top that are
|
||||||
|
defined as "foo = @foo@", e.g. srcdir=., CC=cc, LIBS=-lm,
|
||||||
|
INSTALL=cp, etc. For sysdep.h, read the comments. If your OS is
|
||||||
|
Posix compliant, you should be able to copy sysdep.h.in to
|
||||||
|
sysdep.h unmodified and everything should work.
|
||||||
|
|
||||||
|
2. If you definitely won't be installing Scheme 48, you should set
|
||||||
|
libdir to the distribution directory (e.g. "make libdir=`pwd`").
|
||||||
|
This will make the ,open and ,load-package commands work for the
|
||||||
|
library packages defined in more-packages.scm.
|
||||||
|
|
||||||
|
3. If desired, customize the contents of the development environment
|
||||||
|
heap image by editing the definitions of USUAL-COMMANDS and/or
|
||||||
|
USUAL-FEATURES in more-packages.scm; see below.
|
||||||
|
|
||||||
|
4. If you're using a DEC MIPS, and want to use the foreign function
|
||||||
|
interface, specify LDFLAGS=-N (with e.g. "make LDFLAGS=-N").
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Customizing scheme48.image
|
||||||
|
|
||||||
|
By default, the image consists of a core Scheme system (Revised^5
|
||||||
|
Scheme plus a very minimal read-eval-print loop) together with a
|
||||||
|
standard set of "options" (command processor, debugging commands,
|
||||||
|
inspector, disassembler, generic arithmetic). The set of options is
|
||||||
|
controlled by the definitions of USUAL-COMMANDS and USUAL-FEATURES in
|
||||||
|
more-packages.scm. If you make the (open ...) clause empty, then
|
||||||
|
"make scheme48.image" will create a Scheme system without any extras
|
||||||
|
(such as error recovery), and the image will be smaller. The files
|
||||||
|
are listed in approximate order of decreasing desirability; you'll
|
||||||
|
probably want at least these:
|
||||||
|
|
||||||
|
package-commands, build
|
||||||
|
- necessary for the scheme48.image script to work
|
||||||
|
debuginfo, disclosers
|
||||||
|
- necessary if you want error messages to be at all helpful
|
||||||
|
debugging
|
||||||
|
- defines important debugging commands such as ,preview and ,trace
|
||||||
|
|
||||||
|
After editing the definition of usual-features, simply
|
||||||
|
|
||||||
|
make scheme48.image
|
||||||
|
|
||||||
|
to rebuild the image.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Deeper changes to the system -- for example, edits to most of the
|
||||||
|
files in the rts/ directory -- will require using the static linker to
|
||||||
|
make a new initial.image. After you have a working scheme48.image
|
||||||
|
(perhaps a previous version of Scheme 48), you can create a linker
|
||||||
|
image with
|
||||||
|
|
||||||
|
make linker
|
||||||
|
|
||||||
|
after which you can say
|
||||||
|
|
||||||
|
make image
|
||||||
|
|
||||||
|
to get the linker to build a new initial.image and initial.debug.
|
||||||
|
scheme48.image will then be built from those.
|
||||||
|
|
||||||
|
You might think that "make scheme48.image" ought to do this, but the
|
||||||
|
circular dependencies
|
||||||
|
|
||||||
|
scheme48.image on initial.image
|
||||||
|
initial.image on link/linker.image
|
||||||
|
link/linker.image on scheme48.image
|
||||||
|
|
||||||
|
needs to be broken somewhere, or else make will (justifiably) barf. I
|
||||||
|
chose to break the cycle by making scheme48.image not depend on
|
||||||
|
initial.image, since this is most robust for installation purposes.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Editor support
|
||||||
|
|
||||||
|
We recommend interacting with the Scheme 48 command processor using the
|
||||||
|
emacs/scheme interface written by Olin Shivers at CMU. Copies of the
|
||||||
|
relevant .el files, together with a "cmuscheme48.el", are in the
|
||||||
|
emacs/ subdirectory of the release. Usage information is in
|
||||||
|
doc/user-guide.txt.
|
||||||
|
|
||||||
|
You will probably want to byte-compile the .el files to get .elc
|
||||||
|
files. Use M-x byte-compile-file to do this.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
Performance
|
||||||
|
|
||||||
|
If you don't have a C compiler that optimizes as well as gcc does,
|
||||||
|
then performance may suffer. Take a look at the automatically
|
||||||
|
generated code in scheme48vm.c to find out why. With a good register
|
||||||
|
allocator, all those variables (including some of the virtual
|
||||||
|
machine's virtual registers) get allocated to hardware registers, and
|
||||||
|
it really flies. Without one, performance can be pretty bad.
|
||||||
|
|
||||||
|
The configure script automatically sets the Makefile variable CFLAGS
|
||||||
|
to -O2 -g if gcc is available, or to -O if it isn't. This can be
|
||||||
|
overriden by specifying a different CFLAGS, e.g. "make CFLAGS=-g" for
|
||||||
|
no optimization.
|
||||||
|
|
||||||
|
Even if you do have a good compiler, you should be able to improve
|
||||||
|
overall performance even more, maybe about 6-10%, by removing the
|
||||||
|
range check from the interpreter's instruction dispatch. To do this,
|
||||||
|
use the -S flag to get assembly code for scheme48vm.c, then find the
|
||||||
|
instructions in scheme48vm.s corresponding to the big dispatch in
|
||||||
|
restart():
|
||||||
|
|
||||||
|
L19173: {
|
||||||
|
code_pointer_83X = arg1K0;
|
||||||
|
switch ((*((unsigned char *) code_pointer_83X))) {
|
||||||
|
... }
|
||||||
|
|
||||||
|
There will be one or two comparison instructions to see whether the
|
||||||
|
opcode is in range; just remove them. For the 68000 I use a "sed"
|
||||||
|
script
|
||||||
|
|
||||||
|
/cmpl #137,d0/ N
|
||||||
|
/cmpl #137,d0\n jhi L/ d
|
||||||
|
|
||||||
|
but of course the constant will probably have to change when a new
|
||||||
|
release comes along.
|
||||||
|
|
||||||
|
See the user's guide for information on the ,bench command, which
|
||||||
|
makes programs run faster.
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
filenames.make is "include"d by the Makefile, but is automatically
|
||||||
|
generated from the module dependencies laid out in the various
|
||||||
|
configuration files (*-packages.scm). If you edit any of these .scm
|
||||||
|
files, you may want to do a "make filenames.make" before you do any
|
||||||
|
further "make"s in order to update the depedencies. This step isn't
|
||||||
|
necessary if you're using Gnu make, because Gnu make will make
|
||||||
|
included files automatically.
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
|
||||||
|
There are two types of I/O objects in Scheme 48, channels and ports.
|
||||||
|
Channels are the raw, unbuffered ports of the operating system. The
|
||||||
|
only I/O operations the VM supports for channels are block reads and
|
||||||
|
writes. Ports are the actual Scheme ports and are implemented in Scheme,
|
||||||
|
with some support from the VM for READ-CHAR, PEEK-CHAR, and WRITE-CHAR
|
||||||
|
for efficiency. The run-time system provides ports that are buffered
|
||||||
|
versions of channels. Other sorts of ports are in big/more-port.scm.
|
||||||
|
|
||||||
|
Source files:
|
||||||
|
|
||||||
|
rts/port.scm port operations and port handlers
|
||||||
|
rts/current-port.scm current-input-port, etc.
|
||||||
|
rts/channel.scm blocking on channels and handling i/o interrupts
|
||||||
|
rts/channel-port.scm ports that read and write to channels
|
||||||
|
rts/low.scm CHANNEL-READ and CHANNEL-WRITE
|
||||||
|
big/more-port.scm additional kinds of ports
|
||||||
|
vm/arch.scm fields of ports and channels
|
||||||
|
vm/prim-io.scm VM i/o opcodes
|
||||||
|
vm/vmio.scm implementation of channels
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
CHANNELS
|
||||||
|
|
||||||
|
The VM instructions that deal with channels are:
|
||||||
|
|
||||||
|
(OPEN-CHANNEL <spec> <mode>) -> channel
|
||||||
|
<mode> is a from the enumeration OPEN-CHANNEL-OPTION in arch.scm.
|
||||||
|
<spec> is either a filename (as a string) or an OS port (as a one-word
|
||||||
|
code-vector), depending on the mode.
|
||||||
|
|
||||||
|
(CLOSE-CHANNEL <channel>) -> unspecific
|
||||||
|
|
||||||
|
(CHANNEL-MAYBE-READ <string-or-code-vector> <start-index> <count> <wait?>
|
||||||
|
<channel>)
|
||||||
|
-> number of bytes read or the eof-object
|
||||||
|
(CHANNEL-MAYBE-WRITE <string-or-code-vector> <start-index> <count> <channel>)
|
||||||
|
-> number of bytes written
|
||||||
|
These read or write up to the specified number of characters or bytes
|
||||||
|
from or to the string or code-vector, with the first character or byte
|
||||||
|
going at <start-index>.
|
||||||
|
|
||||||
|
(CHANNEL-ABORT <channel>) -> number of bytes read or written or
|
||||||
|
the eof-object
|
||||||
|
This aborts any pending read or write operation on the channel. The return
|
||||||
|
value reflects any partial completion.
|
||||||
|
|
||||||
|
CHANNEL-MAYBE-READ and CHANNEL-MAYBE-WRITE do not block. If the read or
|
||||||
|
write cannot be completed immediately a PENDING-CHANNEL-I/O exception is
|
||||||
|
raised. It is then up to the run-time system to either wait or run some
|
||||||
|
other thread. The VM raises an I/O-COMPLETION interrupt whenever an i/o
|
||||||
|
operation completes.
|
||||||
|
|
||||||
|
Because CHANNEL-MAYBE-READ and CHANNEL-MAYBE-WRITE are awkward to use,
|
||||||
|
the RTS defines somewhat simpler versions:
|
||||||
|
|
||||||
|
(CHANNEL-READ <buffer> <start> <needed> <channel>)
|
||||||
|
-> number of bytes read or the eof-object
|
||||||
|
(CHANNEL-WRITE <buffer> <start> <count> <channel>)
|
||||||
|
-> unspecified
|
||||||
|
<Buffer> is either a string or code vector and <start> is the index of the
|
||||||
|
first character read or written. <Needed> is one of:
|
||||||
|
N > 0 : the call returns when this many characters has been read or
|
||||||
|
an EOF is reached.
|
||||||
|
'IMMEDIATE : the call reads as many characters as are available and
|
||||||
|
returns immediately.
|
||||||
|
'ANY : the call returns as soon as at least one character has been read
|
||||||
|
or an EOF is reached.
|
||||||
|
<Count> is the number of characters to be written. CHANNEL-READ will read
|
||||||
|
the requested number of characters unless an EOF is reached. CHANNEL-WRITE
|
||||||
|
will write the requested number of characters.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
PORTS
|
||||||
|
|
||||||
|
Ports are actual Scheme port and are (usually) buffered. They are fully
|
||||||
|
exposed to the run-time system. The VM instructions on ports could be
|
||||||
|
implemented in Scheme; they are in the VM for efficiency. Buffers are
|
||||||
|
code-vectors (this is a micro-hack; strings have a slightly higher overhead
|
||||||
|
because of the null terminating byte for C compatibility) (code-vectors are
|
||||||
|
just vectors of bytes).
|
||||||
|
|
||||||
|
The fields of a port are:
|
||||||
|
|
||||||
|
PORT-STATUS: a bit set represented as a fixnum.
|
||||||
|
Indices into this bit set are from the PORT-STATUS-OPTIONS
|
||||||
|
enumeration in arch.scm. The current bits are: input, output,
|
||||||
|
open-for-input, open-for-output (the last two are for things like
|
||||||
|
sockets, on which you need to block but which do not support
|
||||||
|
normal reading or writing).
|
||||||
|
|
||||||
|
PORT-HANDLER: a record containing three procedures. These handle
|
||||||
|
printing the port, closing the port, and filling (for input ports)
|
||||||
|
or emptying (for output ports) buffers.
|
||||||
|
|
||||||
|
PORT-DATA: ?
|
||||||
|
Whatever stuff the handler needs.
|
||||||
|
|
||||||
|
PORT-LOCKED?, PORT-LOCK: used by the system to guarentee the atomicity
|
||||||
|
of i/o operations.
|
||||||
|
|
||||||
|
PORT-BUFFER: a code-vector. The input or output buffer of the port.
|
||||||
|
|
||||||
|
PORT-INDEX: a fixnum. The index of the next byte to read or written.
|
||||||
|
|
||||||
|
PORT-LIMIT: a fixnum. One past the end of the valid/available buffer space.
|
||||||
|
|
||||||
|
PORT-PENDING-EOF?: true if the next read to this port should return EOF.
|
||||||
|
|
||||||
|
Additional operations on ports:
|
||||||
|
|
||||||
|
(READ-BLOCK string-or-code-vector start count input-port)
|
||||||
|
Read COUNT bytes into STRING-OR-CODE-VECTOR starting at index START.
|
||||||
|
Returns the number of bytes read. Only an end-of-file will prevent
|
||||||
|
the requested number of bytes from being read.
|
||||||
|
|
||||||
|
(WRITE-STRING string output-port)
|
||||||
|
Write the characters in the string to the port.
|
||||||
|
|
||||||
|
(WRITE-BLOCK string-or-code-vector start count output-port)
|
||||||
|
The output counterpart to READ-BLOCK. This always writes out the
|
||||||
|
requested number of bytes. Its return value is unspecified.
|
||||||
|
|
||||||
|
(FORCE_OUTPUT output-port)
|
||||||
|
Causes any buffered characters to be written out.
|
||||||
|
|
||||||
|
(CURRENT-ERROR-PORT)
|
||||||
|
The current error port, analogous to Scheme's CURRENT-INPUT-PORT
|
||||||
|
and CURRENT-OUTPUT-PORT.
|
||||||
|
|
||||||
|
The system maintains a list of output ports whose buffers should be
|
||||||
|
periodically flushed. The default output port and ports made by
|
||||||
|
OPEN-OUTPUT-FILE are on this list. (PERIODICALLY-FORCE-OUTPUT! <output-port>)
|
||||||
|
may be used to add others.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
PORT HANDLERS
|
||||||
|
|
||||||
|
Every port has a handler with three procedures. The first two are used
|
||||||
|
for printing and closing ports and have the same type for all ports:
|
||||||
|
|
||||||
|
(DISCLOSE port-data) -> disclose list
|
||||||
|
(CLOSE port-data) -> unspecific
|
||||||
|
|
||||||
|
For CLOSE, The system takes care of modifying the port's status.
|
||||||
|
|
||||||
|
The third procedure is used to fill and empty buffers. Its arguments
|
||||||
|
and return values depend on the kind of port:
|
||||||
|
|
||||||
|
Buffered output ports:
|
||||||
|
(BUFFER-PROC port-data buffer start-index byte-count) -> unspecific
|
||||||
|
BYTE-COUNT bytes should be copied from the buffer beginning at
|
||||||
|
START-INDEX. The buffer may be either a string or a code-vector.
|
||||||
|
|
||||||
|
Unbuffered output ports:
|
||||||
|
(BUFFER-PROC port-data char) -> unspecific
|
||||||
|
Write out the given character. The system uses this for the default
|
||||||
|
error port.
|
||||||
|
|
||||||
|
Input ports:
|
||||||
|
(BUFFER-PROC data buffer start-index needed-bytes)
|
||||||
|
-> EOF or number of bytes read (before an EOF)
|
||||||
|
Bytes should be copied into the buffer starting at START-INDEX. The
|
||||||
|
buffer may be either a string or a code-vector. NEEDED-BYTES is one of:
|
||||||
|
|
||||||
|
'IMMEDIATE
|
||||||
|
The call should return immediately after transfering whatever number
|
||||||
|
of bytes are currently available, possibly none (this is used for
|
||||||
|
CHAR-READY?). The maximum number of characters is determined by the
|
||||||
|
length of BUFFER.
|
||||||
|
|
||||||
|
'ANY
|
||||||
|
The call should wait until at least one byte is available or an EOF
|
||||||
|
occurs (used for READ-CHAR and PEEK-CHAR). The maximum number of
|
||||||
|
characters is determined by the length of BUFFER.
|
||||||
|
|
||||||
|
N > 0
|
||||||
|
The call should wait until N bytes have been copied into the buffer
|
||||||
|
or an EOF occurs. If the return value is less than NEEDED-BYTES the
|
||||||
|
port code inserts an EOF after the last byte.
|
||||||
|
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
Ports and the Virtual Machine
|
||||||
|
|
||||||
|
Ports could be implemented entirely in Scheme, with no support from
|
||||||
|
the VM. For efficiency reasons VM instructions are supplied for
|
||||||
|
three port operations:
|
||||||
|
|
||||||
|
(READ-CHAR <port>)
|
||||||
|
(PEEK-CHAR <port>)
|
||||||
|
(WRITE-CHAR <char> <port>)
|
||||||
|
|
||||||
|
For each of these, if there is sufficient data or space in the
|
||||||
|
appropriate buffer the VM performs the operation. Otherwise a
|
||||||
|
buffer-full/empty exception is raised and the exception handler
|
||||||
|
uses the buffer procedure from the port's handler to fill or
|
||||||
|
empty the buffer.
|
||||||
File diff suppressed because it is too large
Load Diff
1417
doc/module.ps
1417
doc/module.ps
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,700 @@
|
||||||
|
-*- Mode: Indented-text; -*-
|
||||||
|
|
||||||
|
Recent changes to Scheme 48.
|
||||||
|
|
||||||
|
2/24/99 (version 0.53)
|
||||||
|
Additions:
|
||||||
|
DEFINE-FINITE-TYPE and DEFINE-ENUMERATED-TYPE (in structure
|
||||||
|
FINITE-TYPES; documented in doc/utilities.ps and
|
||||||
|
doc/html/utilities.html.
|
||||||
|
Added CHAR-SOURCE->INPUT-PORT, CHAR-SINK->OUTPUT-PORT,
|
||||||
|
MAKE-STRING-OUTPUT-PORT, STRING-OUTPUT-SOURCE-OUTPUT to
|
||||||
|
the extended-ports structure.
|
||||||
|
The structure BYTE-VECTORS is the same as CODE-VECTORS with `byte'
|
||||||
|
replacing `code' in all the names. The underlying datatype is the
|
||||||
|
same for both, and uses `byte' when printing.
|
||||||
|
There is a new and much improved interface to C code, thanks to
|
||||||
|
Mike Sperber. It is documented in in doc/external.ps and
|
||||||
|
doc/html/external.html.
|
||||||
|
Bug fixes:
|
||||||
|
Session-data and user-context records are no longer in the fluid env.
|
||||||
|
Lexical environments can now be nested up to 65k deep.
|
||||||
|
,expand no longer prints `definition in expression context' warnings.
|
||||||
|
Added ARRAY? and SEARCH-TREE? to the array and search tree structures.
|
||||||
|
Flat environments work again.
|
||||||
|
Templates of the form `var ... ...' now work in syntax rules.
|
||||||
|
Reinstated caching of SCHEMIFY results to greatly reduce the space
|
||||||
|
used by debugging info.
|
||||||
|
Added argument checking to STRING->NUMBER and NUMBER->STRING.
|
||||||
|
Fixed space blow-up in LOAD.
|
||||||
|
Unused ports are closed more reliably.
|
||||||
|
Changes:
|
||||||
|
The heap, gc, and image code is now in three separate modules.
|
||||||
|
The symbol table is now held in a VM register.
|
||||||
|
Inlined SHOWING-FOCUS-VALUES into the main command loop and moved
|
||||||
|
the sentinal call to reduce the noise at the base of ,preview output.
|
||||||
|
The tables returned by MAKE-TABLE now use EQV? for comparison (instead
|
||||||
|
of EQ?). This makes these tables about 50% slower when numbers are
|
||||||
|
used as keys, but significantly more accurate.
|
||||||
|
Floating-point numbers are no longer double boxed.
|
||||||
|
The channels structure has been split into channels and low-channels.
|
||||||
|
|
||||||
|
7/22/98 (version 0.52)
|
||||||
|
Bug fixes:
|
||||||
|
Fixed problems with unbound variables in SET! and the inliner.
|
||||||
|
Made macro expansion a bit less eager; this should reduce the amount
|
||||||
|
of heap space needed for compilation.
|
||||||
|
|
||||||
|
6/29/98 (version 0.51)
|
||||||
|
Incompatible changes:
|
||||||
|
BIG-SCHEME no longer exports its version of DEFINE-RECORD-TYPE (but
|
||||||
|
it is available from the structure DEFRECORD). I am slowly removing
|
||||||
|
all uses of this version of DEFINE-RECORD-TYPE from the sources.
|
||||||
|
The version of DEFINE-RECORD-TYPE exported by DEFINE-RECORD-TYPES
|
||||||
|
checks that every constructor argument corresponds to a field.
|
||||||
|
Uses of LAP must list their free variables (see env/assem.scm).
|
||||||
|
Changes:
|
||||||
|
The functions exported by BIG-SCHEME that were not available elsewhere
|
||||||
|
are now exported by BIG-UTIL as well.
|
||||||
|
MAKE-RANDOM now checks its argument (but is still a fairly poor
|
||||||
|
source of pseudo-randomness).
|
||||||
|
SIGPIPE no longer kills the S48 process (this was done earlier but
|
||||||
|
not listed here).
|
||||||
|
The macro/module/compiler code has been reorganized. Hopefully
|
||||||
|
the only noticable difference is in the babble written when loading
|
||||||
|
files and packages.
|
||||||
|
Added CODE-QUOTE (in its own structure of the same name) for use
|
||||||
|
in writing hygienic macro-generating macros. CODE-QUOTE is the
|
||||||
|
same as QUOTE except that it does not strip off any of the macro
|
||||||
|
system's name annotations.
|
||||||
|
The FLOATNUMS package now exports FLOATNUM?.
|
||||||
|
Bug fixes:
|
||||||
|
Fixed phony stack-overflow bug.
|
||||||
|
Fixed a bug in thread time-debit mechanism.
|
||||||
|
Made floating point numbers always print as inexact.
|
||||||
|
Got rid of bogus type-error warnings when using floatnums.
|
||||||
|
Fixed declaration of call_startup_procedure in c/main.c.
|
||||||
|
|
||||||
|
2/11/98 (version 0.50)
|
||||||
|
Fixed bug in closed-compiled version of READ-CHAR.
|
||||||
|
Fixed negative-key bug in integer tables.
|
||||||
|
|
||||||
|
11/18/97 (version 0.49)
|
||||||
|
Removed some non-portable Kali code that had been accidentally
|
||||||
|
included in c/extension.c.
|
||||||
|
|
||||||
|
10/29/97 (version 0.48)
|
||||||
|
The VM's calling convention now has the caller doing protocol checking,
|
||||||
|
instead of the callee. The *NARGS* register no longer exists.
|
||||||
|
Scheme's variable-arity procedures (APPLY, MAKE-VECTOR, +, -, etc.)
|
||||||
|
are usually handled without raising an exception. Calls with an
|
||||||
|
`atypical' number of arguments are now much faster.
|
||||||
|
Opcodes were added for >, <=, and >=.
|
||||||
|
Procedures can take up to about 8k arguments. The limit is determined
|
||||||
|
by the value of AVAILABLE-STACK-SPACE in scheme/vm/arch.scm.
|
||||||
|
Compiler detects wrong number of arguments in ((lambda ...) ...).
|
||||||
|
Removed the dynamic point from the dynamic environment to make
|
||||||
|
DYNAMIC-WIND behave reasonably with threads.
|
||||||
|
KILL-THREAD! should work more reliably.
|
||||||
|
The I/O primitives now pass OS error messages to the exception handlers.
|
||||||
|
I/O errors when flushing buffers no longer crash the system.
|
||||||
|
The Pre-Scheme compiler's hack for shadowing global variables with
|
||||||
|
local copies is no longer used.
|
||||||
|
Incompatible changes:
|
||||||
|
The internal thread interface was simplified.
|
||||||
|
There are some architecture changes; .image files will have to
|
||||||
|
be rebuilt.
|
||||||
|
ACCESS-SCHEME-48 and scheme/misc/slib-init.scm have been removed
|
||||||
|
(thanks to Mike Sperber's updating of slib).
|
||||||
|
|
||||||
|
1/27/97 (version 0.47)
|
||||||
|
Fixed ,exit and added ,exit-when-done.
|
||||||
|
CASE now uses EQV? exclusively.
|
||||||
|
|
||||||
|
11/5/96 (version 0.46)
|
||||||
|
Fixed a few minor thread problems.
|
||||||
|
opt/analyze.scm now writes to current-noise-port.
|
||||||
|
DELQ and DELETE now delete every instance, as the documentation claims.
|
||||||
|
There should be no more spurious heap-overflow interrupts.
|
||||||
|
Fixed bugs that caused the system to die if stdout blocked.
|
||||||
|
Template offsets have been increased to two bytes.
|
||||||
|
Disassembly of flat-lambda now works (fix from Michael Sperber).
|
||||||
|
|
||||||
|
8/23/96 (version 0.45)
|
||||||
|
Fixed various problems with thread termination and nested schedulers.
|
||||||
|
Changed thread-internal interface to make schedulers easier to write.
|
||||||
|
BITWISE-{AND,IOR,XOR} now take an arbitrary number of arguments.
|
||||||
|
Output ports have their buffers flushed when Scheme 48 terminates.
|
||||||
|
In keeping with RnRS, CLOSE-{IN,OUT}PUT-PORT are now idempotent.
|
||||||
|
MODULO now handles negative arguments properly.
|
||||||
|
|
||||||
|
6/20/96 (version 0.44)
|
||||||
|
The VM's byte-code interpreter and storage management code are
|
||||||
|
now compiled to separate C files.
|
||||||
|
The socket code works again.
|
||||||
|
|
||||||
|
5/10/96 (version 0.42-0.43)
|
||||||
|
Various fixes to the thread and I/O systems.
|
||||||
|
The Unix interface code is more portable.
|
||||||
|
EOF (control-D) now resumes running all non-broken threads on
|
||||||
|
resumed command level. Thus EOF after a keyboard interrupt
|
||||||
|
(control-C) resumes running the interrupted thread.
|
||||||
|
|
||||||
|
11/30/95 (version 0.41)
|
||||||
|
The distribution has been reorganized to reduce the number of files
|
||||||
|
in the top-level directory.
|
||||||
|
The threads implementation has been replaced with one based on engines
|
||||||
|
to allow for nested schedulers.
|
||||||
|
Threads are now included in the initial image.
|
||||||
|
The I/O system has been fixed and automatic periodic output buffer
|
||||||
|
flushing has been reinstalled.
|
||||||
|
Command levels have been integrated with the threads system to ensure
|
||||||
|
that at most one REPL is active at any time.
|
||||||
|
CONDVAR has been changed to PLACEHOLDER (condition variables being
|
||||||
|
something quite different).
|
||||||
|
,profile no longer works, it will be fixed in a later version.
|
||||||
|
MIN and MAX now do inexact contagion.
|
||||||
|
|
||||||
|
4/13/95 (version 0.40)
|
||||||
|
Renamed error-output-port to current-error-port.
|
||||||
|
Reinstated ".gdbinit"...
|
||||||
|
segment->template now takes parent templates debug data as an
|
||||||
|
argument.
|
||||||
|
Automatic periodic output buffer flushing has been
|
||||||
|
temporarily disabled. A future version of the I/O system
|
||||||
|
will fix it.
|
||||||
|
Fixed expansion of named LET.
|
||||||
|
The bummed-define-record-types structure is now gone; use
|
||||||
|
define-record-types instead.
|
||||||
|
There is somewhat better syntax checking now.
|
||||||
|
|
||||||
|
8/12/94 (versions 0.38-0.39)
|
||||||
|
,profile <command> prints out profiling information
|
||||||
|
An interrupt is raised after ever GC; the default handler checks
|
||||||
|
to see if some reasonable amount of storage was reclaimed.
|
||||||
|
Some of the standard Scheme procedures, including LENGTH, FOR-EACH,
|
||||||
|
VECTOR, and ASSQ, are now significantly faster.
|
||||||
|
Making, accessing, and setting records is faster.
|
||||||
|
tar file now includes the top-level directory
|
||||||
|
The "scheme-level-2-internal" structure has been renamed to
|
||||||
|
"usual-resumer".
|
||||||
|
` ( . ' is now illegal (as required by the R4RS grammar).
|
||||||
|
Made DELAY and FORCE comply with R4RS.
|
||||||
|
The EXPAND optimizer does a topological sort on definitions.
|
||||||
|
(optimize flat-environments) causes the compiler to produce
|
||||||
|
flat (instead of nested) lexical environments.
|
||||||
|
The I/O system has been rewritten to do its own buffering. There
|
||||||
|
are significant changes to unix.c to support this. See doc/io.txt.
|
||||||
|
(ERROR-OUTPUT) is now available from the structure i/o.
|
||||||
|
jar-defrecord has been replaced with a modified bummed-jar-defrecord
|
||||||
|
Files load about 25% faster, for a number of reasons.
|
||||||
|
Removed the copy of vm/arch.scm from the rts directory.
|
||||||
|
Threads and sockets work together; SOCKET-ACCEPT no longer blocks.
|
||||||
|
The compiler no longer prints out .'s as it compiles definitions.
|
||||||
|
|
||||||
|
7/5/94 (version 0.37)
|
||||||
|
I/O opcodes now raise an interrupt instead of blocking (they still
|
||||||
|
block if no corresponding interrupt handler has been installed).
|
||||||
|
The threads code has been rewritten; threads that block on I/O
|
||||||
|
do not busy wait and THREAD-READ-CHAR and THREAD-PEEK-CHAR have
|
||||||
|
been removed.
|
||||||
|
Attempting to obtain a lock twice or to release an unowned lock
|
||||||
|
now signal errors.
|
||||||
|
READ-CHAR-WITH-TIMEOUT returns #F if the timeout occurs.
|
||||||
|
The socket structure is back in more-packages.scm.
|
||||||
|
Renamed .gdbinit to gdbinit
|
||||||
|
tar file now contains a top-level directory
|
||||||
|
|
||||||
|
3/22/94 (version 0.36)
|
||||||
|
Removed doc/lsc.ps for copyright reasons.
|
||||||
|
Fixed (* 47123 46039) multiply bug.
|
||||||
|
Modified vm/README to make it easier to run the VM.
|
||||||
|
|
||||||
|
3/16/94 (version 0.35)
|
||||||
|
Fixed (exact->inexact 0.1) -> 0..1. bug.
|
||||||
|
Fixed VM bug that permitted the creation of stored objects with
|
||||||
|
negative sizes.
|
||||||
|
|
||||||
|
3/8/94 (version 0.34)
|
||||||
|
"make check" target tests out various features.
|
||||||
|
Fixes for SGI IRIX 4.0.5 and MIPS RISC/OS 4.51, courtesy
|
||||||
|
Bryan O'Sullivan.
|
||||||
|
debug/run.scm and the "medium system" work again now.
|
||||||
|
misc/static.scm should work on the 68000.
|
||||||
|
Command processor no longer fluid-binds (interaction-environment)
|
||||||
|
on recursive entry.
|
||||||
|
|
||||||
|
2/24/94 (version 0.33)
|
||||||
|
Fixed bug in VM's interrupt system.
|
||||||
|
Made non-local srcdir work in Makefile.
|
||||||
|
Added (load-package 'bigbit) to vm/README.
|
||||||
|
|
||||||
|
2/23/94 (version 0.32)
|
||||||
|
Some incompatible changes to the VM; .image files will have
|
||||||
|
to be rebuilt.
|
||||||
|
Improvements to configuration script and to unix.c to support
|
||||||
|
a wider variety of Unixes. The system should now work
|
||||||
|
under any Posix-compliant Unix (except maybe for
|
||||||
|
char-ready?; see comments in unix.c).
|
||||||
|
Upped the default heap size from 4 meg (2 per semispace) to 6
|
||||||
|
meg (3 per semispace).
|
||||||
|
New command line argument -s <size> for specifying size of
|
||||||
|
stack buffer. Default is 2500 (words).
|
||||||
|
$@ -> "$@" in script (thanks to Paul Stodghill for this fix).
|
||||||
|
Obscure interrupt/exception VM bug fixed.
|
||||||
|
It is now possible to put an initial heap image into static
|
||||||
|
memory (effectively allocated by OS process creation).
|
||||||
|
Immutable initial objects go into static read-only memory,
|
||||||
|
and mutable initial objects go into static read-write
|
||||||
|
memory. Initial objects not copied by the GC. There is no
|
||||||
|
documentation yet, but look at the rules for little and
|
||||||
|
debug/little.o in the Makefile if you're interested.
|
||||||
|
|
||||||
|
2/13/94 (version 0.31)
|
||||||
|
Incompatible changes:
|
||||||
|
In interfaces, all exported syntactic keywords must be
|
||||||
|
given type :syntax. For example,
|
||||||
|
(define-interface my-macros
|
||||||
|
(export (my-macro :syntax) ...))
|
||||||
|
Image entry procedures for the ,build command are now
|
||||||
|
passed a list of strings, not just a single string, for
|
||||||
|
the command line arguments following -a.
|
||||||
|
The names of the macros defined in scheme48.h
|
||||||
|
(pairp, car, string_length, etc.) are now all upper case.
|
||||||
|
New "configure" script generates Makefile from Makefile.in
|
||||||
|
and sysdep.h from sysdep.h.in (thanks to Gnu autoconf).
|
||||||
|
See INSTALL and doc/install.txt.
|
||||||
|
Bug fixes:
|
||||||
|
Can now make vectors (strings, etc.) as big as the amount
|
||||||
|
of heap space available (but you're still screwed if you
|
||||||
|
try to make one bigger than 2^23-1 bytes - don't do it).
|
||||||
|
Non-ANSI-ness fixed in scheme48vm.c (jump out of, then
|
||||||
|
back into, a block expected block-local variables to be
|
||||||
|
unchanged).
|
||||||
|
Fixed big/external.scm (had VECTOR-POSQ instead of ENUM).
|
||||||
|
In (define-syntax foo bar) you got an error if bar was a
|
||||||
|
variable reference.
|
||||||
|
Plugged a storage leak (file-environments table in
|
||||||
|
env/debug.scm). Images made with ,build were too large.
|
||||||
|
Flushed extraneous delay from make-reflective-tower.
|
||||||
|
Renamed variables in Makefile to resemble Gnu standards.
|
||||||
|
Fixed definition of LINKER_RUNNABLE in Makefile.
|
||||||
|
Added doc/call-back.txt.
|
||||||
|
Fixed define-enumerated documentation (doc/big-scheme.txt).
|
||||||
|
Environment maps no longer retained for things in initial.image
|
||||||
|
and scheme48.image. This makes scheme48.image about 170K
|
||||||
|
smaller.
|
||||||
|
|
||||||
|
2/3/94 (version 0.30)
|
||||||
|
Faster EXPT.
|
||||||
|
FLOATNUMS improvement: (inexact->exact <float>) should now
|
||||||
|
work, e.g.
|
||||||
|
(inexact->exact (/ 1. 3.)) => 6004799503160661/18014398509481984
|
||||||
|
Reinstated ACCESS-SCHEME-48 for the benefit of PSD (portable
|
||||||
|
scheme debugger) and a certain other software package that
|
||||||
|
shall remain nameless. It only knows about a small number of
|
||||||
|
procedures, including things like ERROR and FORCE-OUTPUT.
|
||||||
|
Various changes to support the Pre-Scheme compiler, notably
|
||||||
|
SET-REFLECTIVE-TOWER-MAKER!.
|
||||||
|
Incompatible change to the ENUMERATED structure: the names
|
||||||
|
foo/bar no longer become defined. Write (enum foo bar)
|
||||||
|
instead. This will macro expand into the correct small
|
||||||
|
integer.
|
||||||
|
|
||||||
|
1/30/94 (version 0.29)
|
||||||
|
Fixed ps_run_time() to call sysconf() to find out how many
|
||||||
|
ticks there are per second. It used to assume 60. This
|
||||||
|
affects the output of the ,time command, so don't try
|
||||||
|
comparing numbers from this version with numbers from older
|
||||||
|
versions.
|
||||||
|
,time command will now accept a command, e.g.
|
||||||
|
,time ,load foo.scm.
|
||||||
|
It appears that if multiple arguments follow -a on the
|
||||||
|
argument line, they are concatenated together with spaces
|
||||||
|
separating them and passed to the startup procedure. I
|
||||||
|
don't know how long this has worked. This will change in
|
||||||
|
the future so that the startup procedure gets a list of
|
||||||
|
strings.
|
||||||
|
Installed what used to be called the GENERAL-TABLES structure
|
||||||
|
as the TABLES structure used by the system. This allows
|
||||||
|
the use of other comparison predicates besides EQ?, and
|
||||||
|
eliminates some code that had a restrictive copyright
|
||||||
|
notice.
|
||||||
|
ENUM, NAME->ENUMERAND, and ENUMERAND->NAME are all macros.
|
||||||
|
Enumerated types themselves are now macros as well.
|
||||||
|
|
||||||
|
1/23/94 Fixed bad multiplication bug in VM: (* 214760876 10) was
|
||||||
|
returning 125112.
|
||||||
|
Moved RECORD-TYPE? and RECORD-TYPE-FIELD-NAMES from the
|
||||||
|
RECORDS-INTERNAL interface to the RECORDS interface, for
|
||||||
|
a somewhat closer approximation to MIT Scheme.
|
||||||
|
Various type system improvements.
|
||||||
|
Still no documentation for the ,exec package, but see
|
||||||
|
link/load-linker.exec for an example.
|
||||||
|
New generic function feature, exported by the METHODS
|
||||||
|
interface (see interfaces.scm), almost like in a certain
|
||||||
|
dynamic object-oriented language.
|
||||||
|
|
||||||
|
1/11/94 (version 0.27)
|
||||||
|
Change:
|
||||||
|
The isomorphism used by CHAR->INTEGER and INTEGER->CHAR is
|
||||||
|
no longer ASCII. This change was introduced in order to
|
||||||
|
assist the development of portable programs. If you need
|
||||||
|
ASCII encoding, you should open the ASCII structure and
|
||||||
|
use the procedures CHAR->ASCII and ASCII->CHAR.
|
||||||
|
Features:
|
||||||
|
The help system is somewhat improved.
|
||||||
|
New form DEFINE-STRUCTURE defines a single structure.
|
||||||
|
Incompatible changes to package system:
|
||||||
|
Renamed DEFINE-PACKAGE to DEFINE-STRUCTURES
|
||||||
|
Renamed DEFINE-STRUCTURE to DEFINE
|
||||||
|
Renamed all the base types from FOO to :FOO. E.g.
|
||||||
|
:SYNTAX, :VALUE, :PAIR, etc.
|
||||||
|
Other:
|
||||||
|
Removed socket support due to restrictive copyright on some
|
||||||
|
of the C code that was in extension.c.
|
||||||
|
|
||||||
|
12/21/93 ,take has been flushed in favor of ,exec ,load. Commands are
|
||||||
|
now accessed via a distinguished package instead of a table.
|
||||||
|
Documentation pending.
|
||||||
|
Postscript (.ps) files now included in doc/ subdirectory. (I
|
||||||
|
thought they had been there all along, but apparently I was
|
||||||
|
wrong.)
|
||||||
|
Enhanced, but still kludgey, floating point support. Use
|
||||||
|
,open floatnum.
|
||||||
|
|
||||||
|
12/12/93 (version 0.26)
|
||||||
|
NetBSD port.
|
||||||
|
Hacked write-level and write-depth for inspecting circular
|
||||||
|
structure.
|
||||||
|
Recursive FORCEs signal errors, e.g.
|
||||||
|
(force (letrec ((loser (delay (force loser)))) loser))
|
||||||
|
|
||||||
|
12/7/93 (version 0.25)
|
||||||
|
Bug fix:
|
||||||
|
filenames.make can now be remade using initial.image. This
|
||||||
|
means that you can snarf a distribution and then edit
|
||||||
|
USUAL-FEATURES before making scheme48.image.
|
||||||
|
|
||||||
|
|
||||||
|
12/6/93 Incompatible changes:
|
||||||
|
Change of terminology: "signature" --> "interface".
|
||||||
|
This means that DEFINE-SIGNATURE is now called
|
||||||
|
DEFINE-INTERFACE, etc.
|
||||||
|
Some structures have been renamed:
|
||||||
|
condition -> conditions
|
||||||
|
continuation -> continuations
|
||||||
|
exception -> exceptions
|
||||||
|
queue -> queues
|
||||||
|
port -> ports
|
||||||
|
record -> records, record-internal -> records-internal
|
||||||
|
table -> tables
|
||||||
|
template -> templates
|
||||||
|
The ,load-into command has been removed. Use ,in ... ,load
|
||||||
|
instead (see below), e.g.
|
||||||
|
,in mumble ,load myfile.scm
|
||||||
|
The heap size for -h is specified in words, not bytes. As
|
||||||
|
before, the size must account for both semispaces; -h 2n
|
||||||
|
means n words per semispace. This change was actually
|
||||||
|
made a while ago, but I was confused as to what it meant.
|
||||||
|
Bug fixes:
|
||||||
|
#e1.7 reads as 17/10, (exact? 1+1.0i) => #f, and 1.0+i prints.
|
||||||
|
Features:
|
||||||
|
Things like ((structure-ref scheme if) 1 2 3) work.
|
||||||
|
The following commands now take arbitrary commands to execute
|
||||||
|
in the specified package, not just forms:
|
||||||
|
,config ,user ,for-syntax ,in <package>
|
||||||
|
For example, you can say
|
||||||
|
,in mumble ,trace foo
|
||||||
|
This subsumes the functionality of the ,load-into and
|
||||||
|
,load-config commands.
|
||||||
|
Dynamic loading of shared libraries for System V systems
|
||||||
|
(untested).
|
||||||
|
Documentation:
|
||||||
|
Somewhat improved. user-guide.txt now lists most of the
|
||||||
|
interesting built-in packages. lsc.ps is a draft of "A
|
||||||
|
Tractable Scheme Implementation," a paper submitted to Lisp
|
||||||
|
and Symbolic Computation. See also doc/big-scheme.txt,
|
||||||
|
doc/thread.txt, and doc/external.txt.
|
||||||
|
|
||||||
|
|
||||||
|
10/30/93 LET-SYNTAX and LETREC-SYNTAX.
|
||||||
|
Arrays (see big/array.scm).
|
||||||
|
Lots of internal changes.
|
||||||
|
|
||||||
|
7/20/93 Features:
|
||||||
|
Type system. See doc/types.txt.
|
||||||
|
|
||||||
|
7/4/93 Features:
|
||||||
|
New define-package clause (for-syntax <clause>*).
|
||||||
|
E.g. (define-package ((my-package ...))
|
||||||
|
(open ...)
|
||||||
|
(for-syntax (open scheme my-utilities)
|
||||||
|
(files more-crud-for-syntax))
|
||||||
|
...)
|
||||||
|
A file name to package map is now used by the emacs
|
||||||
|
interface. Whenever you load a file, or zap from a file that
|
||||||
|
hasn't been previously loaded or zapped, the package in
|
||||||
|
which forms are being evaluated is remembered in a table.
|
||||||
|
The next time you zap some forms from the same file, they
|
||||||
|
will be evaluated in that package.
|
||||||
|
Sometimes you may get an association you don't want. In that
|
||||||
|
situation, you can use the ,forget command to delete an
|
||||||
|
entry in the table.
|
||||||
|
A new ,push command goes to a deeper command level.
|
||||||
|
Experimental "command preferred" command processor mode: if
|
||||||
|
you give the command ",form-preferred off", commands will
|
||||||
|
be "preferred" to forms, meaning that you don't need to
|
||||||
|
type a comma before giving a command. To see the value
|
||||||
|
of a variable FOO you have to say (begin foo).
|
||||||
|
Experimental "no levels" command processor mode: if you
|
||||||
|
give the command ",levels off", then an error will not
|
||||||
|
push a new command level. If you want to ignore an
|
||||||
|
error, you don't need to take any action - further
|
||||||
|
evaluations will happen at top level. If you want to
|
||||||
|
enter the inspector or get a preview, you can issue these
|
||||||
|
commands or a ,push command immediately after the error
|
||||||
|
occurs (more precisely, any time until the focus object
|
||||||
|
is set by some other command).
|
||||||
|
All of the mode-control commands (batch, bench,
|
||||||
|
break-on-warnings, form-preferred, and levels) take
|
||||||
|
an optional argument. When no argument is given, they
|
||||||
|
will toggle the corresponding mode. With an argument of
|
||||||
|
ON or OFF, they turn the mode on or off.
|
||||||
|
The ,flush and ,keep commands have been made more flexible
|
||||||
|
and verbose.
|
||||||
|
|
||||||
|
|
||||||
|
6/18/93 Incompatible changes:
|
||||||
|
The access-scheme48 procedure has gone away. Use ,open
|
||||||
|
or the module system instead.
|
||||||
|
The user, configuration, and for-syntax packages no longer
|
||||||
|
have variables bound to them in the configuration package.
|
||||||
|
Where previously you said: Now you should say:
|
||||||
|
,in user <form> ,user <form>
|
||||||
|
,in config <form> ,config <form>
|
||||||
|
,in for-syntax <form> ,for-syntax <form>
|
||||||
|
,load-into config <file> ,load-config <file>
|
||||||
|
,load-into for-syntax <file> ,for-syntax (load "file")
|
||||||
|
|
||||||
|
Features:
|
||||||
|
There is an ,expand <form> command for debugging macros.
|
||||||
|
The ,open command takes any number of structure names, and opens
|
||||||
|
them all (like ,new-package).
|
||||||
|
New procedure DEFINE-INDENTATION exported by the PP structure.
|
||||||
|
E.g. (define-indentation 'let-fluid 1) is like Gnu emacs's
|
||||||
|
(put 'let-fluid 'scheme-indent-hook 1).
|
||||||
|
The inspector simplifies generated names in continuation
|
||||||
|
source code display. E.g. when formerly it said
|
||||||
|
"Waiting for (#{Generated lambda} () (x->node (car exps)))"
|
||||||
|
now it says
|
||||||
|
"Waiting for (lambda () (x->node (car exps)))"
|
||||||
|
Macros can signal syntax errors by returning input expression
|
||||||
|
unchanged. (Comparison uses EQ?.)
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
The doc/ directory contains a draft of a "Scheme 48
|
||||||
|
Progress Report."
|
||||||
|
|
||||||
|
Cleanup:
|
||||||
|
Procedure NULL-TERMINATE added to structure EXTERNALS's
|
||||||
|
signature.
|
||||||
|
"Vulgar Scheme" renamed to "Big Scheme".
|
||||||
|
Two new subdirectories, env/ (for programming environment)
|
||||||
|
and big/ (for Big Scheme), now contain most of what was
|
||||||
|
in the misc/ directory.
|
||||||
|
Several source files that were in the top level and link/
|
||||||
|
directories have moved to the env/ and alt/ directories.
|
||||||
|
|
||||||
|
|
||||||
|
5/6/93 Bug fixes:
|
||||||
|
Fixed -h command line switch. The size was being improperly
|
||||||
|
divided by 4, so if you asked for an N megabyte heap, you'd
|
||||||
|
actually only get an N/4 megabyte heap.
|
||||||
|
Nested backquotes were broken for a while; should be fixed
|
||||||
|
now.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
Quoted structure is read-only: e.g. (set-car! '(a b) 3) will
|
||||||
|
produce an exception.
|
||||||
|
,config [<form>] and ,user [<form>] are like ,in <struct> <form>.
|
||||||
|
Unix socket support; see misc/socket.scm.
|
||||||
|
Now using gzip instead of compress for distributions.
|
||||||
|
,open command offers to load packages.
|
||||||
|
A .gdbinit file sets a breakpoint at CM's exception raising
|
||||||
|
code, and defines a handy "preview" command.
|
||||||
|
|
||||||
|
1/18/93 Feature:
|
||||||
|
Scheme 48 distributions now have version numbers. The
|
||||||
|
version number is printed in the image startup message.
|
||||||
|
Please include it in bug reports.
|
||||||
|
The module system is now documented. See doc/module.tex.
|
||||||
|
|
||||||
|
12/17/92 Bug fixes:
|
||||||
|
Macro templates of the form (x ... y) are supported.
|
||||||
|
Macro templates are now less fussy about meta-variable
|
||||||
|
rank: you can do "(x y) ..." even when the rank of either
|
||||||
|
x or y (but not both) is too low; the low-ranking text
|
||||||
|
will be copied as many times as necessary. (A
|
||||||
|
meta-variable's "rank" is the number of ...'s it sits
|
||||||
|
under in the left-hand side of the rewrite rule.)
|
||||||
|
SYNTAX-RULES is now itself hygienic. This means you can
|
||||||
|
have a meta-variable named CAR, for instance.
|
||||||
|
|
||||||
|
New development environment features:
|
||||||
|
Commands now start with comma (",") instead of colon
|
||||||
|
(":"). (Easier to type since it's not shifted.)
|
||||||
|
values, call-with-values, dynamic-wind, eval,
|
||||||
|
interaction-environment, and scheme-report-environment
|
||||||
|
added per upcoming Revised^5 Scheme report. See
|
||||||
|
doc/meeting.tex.
|
||||||
|
Modifications to quoted structure will now be detected and
|
||||||
|
reported as errors.
|
||||||
|
An interrupt will occur if an insufficient amount of memory
|
||||||
|
is reclaimed by a garbage collection.
|
||||||
|
Inspector now accepts arbitrary command processor commands
|
||||||
|
(with or without leading comma)
|
||||||
|
,keep command controls retention of debugging information.
|
||||||
|
|
||||||
|
Features removed:
|
||||||
|
#\page and #\tab. These aren't in the Scheme report.
|
||||||
|
Their absence in Scheme 48 will encourage portability.
|
||||||
|
access-scheme48 works with fewer names than before. Use the
|
||||||
|
package system instead.
|
||||||
|
Complex numbers not in the system, by default. Get them
|
||||||
|
back by changing usual-features in more-packages.scm.
|
||||||
|
|
||||||
|
Features changed:
|
||||||
|
Many changes to package system. See doc/module.tex.
|
||||||
|
The :identify-image command is gone. Instead, supply a
|
||||||
|
second argument (optional) to the ,dump command.
|
||||||
|
The inspector's TEM command has been shortened to T.
|
||||||
|
|
||||||
|
Internal changes and features:
|
||||||
|
Stored objects types are now part of the virtual machine
|
||||||
|
architecture, i.e. known to the byte-code compiler.
|
||||||
|
Run-time system is split up into many little modules.
|
||||||
|
File names are retained in debug database. (But not used for
|
||||||
|
anything yet...)
|
||||||
|
Tweaks to table package reduce standard image size by 50K
|
||||||
|
and increase compiler speed by 7%.
|
||||||
|
Immutability bit in object headers.
|
||||||
|
Weak pointers.
|
||||||
|
|
||||||
|
7/18/92 Features removed:
|
||||||
|
Table package's default hash function no longer supports
|
||||||
|
string, pairs, or vectors.
|
||||||
|
|
||||||
|
7/9/92 Bug fixes:
|
||||||
|
(- 0 -536870912)
|
||||||
|
Inspector now uses command i/o ports instead of current ones
|
||||||
|
Inexact integers print as N. instead of #iN
|
||||||
|
Throwing back into a call-with-....put-port now produces a
|
||||||
|
warning instead of an error
|
||||||
|
|
||||||
|
Feature fixes:
|
||||||
|
In DEFINE-PACKAGE, OPEN no longer implies ACCESS.
|
||||||
|
misc/receive.scm renamed to rts/values.scm, made to conform
|
||||||
|
with Revised^5 Report, and installed internally.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
New :load-package command. Uses file names in (file ...) clause
|
||||||
|
of a define-package. These are interpreted relative to the
|
||||||
|
directory in which the file containing the define-package
|
||||||
|
was found.
|
||||||
|
#\tab and #\page now print this way.
|
||||||
|
|
||||||
|
|
||||||
|
6/17/92 Bug fixes:
|
||||||
|
Fixed bug in modulo.
|
||||||
|
Flushed LAST-PAIR (which disappeared between R^3 and R^4).
|
||||||
|
DEFINE-SYNTAX and SYNTAX-RULES now exist.
|
||||||
|
CEILING, FLOOR, and ROUND now exist.
|
||||||
|
GCD and LCM are now n-ary.
|
||||||
|
STRING-CI=? and STRING-COPY fixed.
|
||||||
|
STRING->SYMBOL now copies its argument before handing it to
|
||||||
|
INTERN.
|
||||||
|
=, <, etc. now work with more than two arguments.
|
||||||
|
CHAR-READY? exists.
|
||||||
|
Calls via APPLY are now tail-recursive.
|
||||||
|
DISPLAY of vectors and lists works (ugh).
|
||||||
|
|
||||||
|
Development environment improvements:
|
||||||
|
Type ? at inspector to get list of inspector commands.
|
||||||
|
Inspector D command goes to next continuation.
|
||||||
|
Inspector M command shows more of a long menu.
|
||||||
|
Inspector TEM command goes to a continuation's or closure's
|
||||||
|
template.
|
||||||
|
For closures and continuations, inspector displays local
|
||||||
|
variables with their names.
|
||||||
|
For continuations, inspector displays source code for
|
||||||
|
expression into which control will return.
|
||||||
|
Multiple command loop levels. EOF (control-D) now only pops
|
||||||
|
out a single level. :reset pops all the way out. :level n
|
||||||
|
goes out to level n.
|
||||||
|
Can disable benchmark mode.
|
||||||
|
Procedures made with (let ((f (lambda ...))) ...) now print
|
||||||
|
with names.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
Package system: special forms define-package and package-ref;
|
||||||
|
command processor commands :set-package, :load-into,
|
||||||
|
:clear-package, :new-package, :export, :open-package, etc.
|
||||||
|
In misc directory: threads, queues, extended ports, format, etc.
|
||||||
|
|
||||||
|
Changes to system environment:
|
||||||
|
user-initial-environment -> user-package
|
||||||
|
record-updator -> record-modifier
|
||||||
|
primitive-throw superseded by with-continuation
|
||||||
|
ash -> arithmetic-shift
|
||||||
|
New bootstrap regime.
|
||||||
|
Support for threads: alarm clock interrupt, etc.
|
||||||
|
|
||||||
|
Etc.:
|
||||||
|
Liberal COPYRIGHT file, and a little notice in each source file.
|
||||||
|
INSTALL and NEWS split off from README.
|
||||||
|
doc.txt renamed to user-guide.txt.
|
||||||
|
The Makefile now provides two ways to make "s48" for
|
||||||
|
installation. One depends on the exec #! script execution
|
||||||
|
feature and the other doesn't.
|
||||||
|
"make" targets for testsys.image and little.image.
|
||||||
|
Runs Jaffer's test suite and library.
|
||||||
|
Flushed s48.el. Use cmuscheme instead.
|
||||||
|
|
||||||
|
|
||||||
|
9/5/90 Command processor argument parser revamped.
|
||||||
|
:load, :trace, and :untrace commands take arbitrary number
|
||||||
|
of arguments. Argument to :proceed is optional.
|
||||||
|
New (but undocumented) :identify-image command.
|
||||||
|
Better error messages: wrong number of arguments, undefined
|
||||||
|
variable.
|
||||||
|
+, *, min, max, apply are now n-ary; -, /, make-string,
|
||||||
|
make-vector, read-char, peek-char, write-char have
|
||||||
|
appropriate argument optionality.
|
||||||
|
Better internal support for macros; not yet ready for release.
|
||||||
|
Added STRING as per R^3.99RS.
|
||||||
|
More testing of Scheme version of bytecode interpreter.
|
||||||
|
Better scoping of ##; files can't see command processor context.
|
||||||
|
OR and CASE don't cons closures.
|
||||||
|
VM checks for non-existent heap image file, gives error
|
||||||
|
message instead of "bus error".
|
||||||
|
Numerous internal changes in compiler and exception system.
|
||||||
|
Fixed char<?.
|
||||||
|
Fixed -.5 bug in string->number.
|
||||||
|
|
||||||
|
8/26/90 Tested (link-system) inside of T; seems to work.
|
||||||
|
Benchmark mode available via :BENCH command.
|
||||||
|
System is 15K bigger due to new fatter global environment
|
||||||
|
representations.
|
||||||
|
Inspector abbreviation improved.
|
||||||
|
Disassembler now works on continuations, sort of.
|
||||||
|
|
||||||
|
7/26/90 ((lambda ...) ...) no longer makes a closure
|
||||||
|
Features now in default system:
|
||||||
|
:inspect
|
||||||
|
:dis[assemble]
|
||||||
|
Generic arithmetic: bignums, rationals, complexes
|
||||||
|
rationalize
|
||||||
|
:time command is more verbose
|
||||||
|
MOREFILES variable in Makefile for loading extra stuff
|
||||||
|
Default heap size increased to 2 megabytes per semispace
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
Return-Path: <kelsey@ccs.neu.edu>
|
||||||
|
Date: Mon, 14 Jun 93 14:34:40 -0400
|
||||||
|
To: jar@cs.cornell.edu
|
||||||
|
Subject: environments for leaf procedures
|
||||||
|
From: kelsey@flora.ccs.neu.edu
|
||||||
|
Sender: kelsey@ccs.neu.edu
|
||||||
|
|
||||||
|
|
||||||
|
I merged the no-leaf-environments code back into the system, and this
|
||||||
|
time it may be worth it. Loading pp.scm sped up by 2%, even though
|
||||||
|
the compiler is doing more work. Benchmark times (in seconds):
|
||||||
|
|
||||||
|
old new speedup
|
||||||
|
quicksort 1.48 1.39 6%
|
||||||
|
towers 1.05 1.05 0%
|
||||||
|
matrix-multiply 3.32 3.10 7%
|
||||||
|
matrix-multiply2 1.94 1.80 7%
|
||||||
|
|
||||||
|
Local variable names are screwed up:
|
||||||
|
|
||||||
|
> (define (f x) (let ((y 4)) (+ x y)))
|
||||||
|
> (f 'a)
|
||||||
|
|
||||||
|
Error: exception
|
||||||
|
(+ 'a 4)
|
||||||
|
1> ,debug
|
||||||
|
'#{Continuation (pc 13) f}
|
||||||
|
|
||||||
|
[0] 4
|
||||||
|
[1: y] 'a
|
||||||
|
inspect:
|
||||||
|
|
||||||
|
There is probably a simple fix for this.
|
||||||
|
|
||||||
|
Here is the diff:
|
||||||
|
|
||||||
|
% diff comp.scm comp.scm.save
|
||||||
|
26d25
|
||||||
|
< (define $compiling-leaf (make-fluid 'no))
|
||||||
|
28,33d26
|
||||||
|
< (define (note-not-leaf!)
|
||||||
|
< (set-fluid! $compiling-leaf 'no))
|
||||||
|
<
|
||||||
|
< (define (compiling-leaf?)
|
||||||
|
< (eq? 'yes (fluid $compiling-leaf)))
|
||||||
|
<
|
||||||
|
63,82c56,66
|
||||||
|
< (deliver-value (if (env-ref? den)
|
||||||
|
< (local-variable den cenv depth #f)
|
||||||
|
< (instruction-with-variable op/global exp den #f))
|
||||||
|
< cont)))
|
||||||
|
<
|
||||||
|
< (define (local-variable den cenv depth set?)
|
||||||
|
< (let ((back (env-ref-back den cenv))
|
||||||
|
< (over (env-ref-over den)))
|
||||||
|
< (if (and (compiling-leaf?)
|
||||||
|
< (= back 0))
|
||||||
|
< (instruction (if set? op/stack-set! op/stack-ref)
|
||||||
|
< (+ (- over 1) depth))
|
||||||
|
< (let ((back (if (compiling-leaf?) (- back 1) back)))
|
||||||
|
< (if set?
|
||||||
|
< (instruction op/set-local! back over)
|
||||||
|
< (case back
|
||||||
|
< ((0) (instruction op/local0 over)) ;+++
|
||||||
|
< ((1) (instruction op/local1 over)) ;+++
|
||||||
|
< ((2) (instruction op/local2 over)) ;+++
|
||||||
|
< (else (instruction op/local back over))))))))
|
||||||
|
---
|
||||||
|
> (if (env-ref? den)
|
||||||
|
> (let ((back (env-ref-back den cenv))
|
||||||
|
> (over (env-ref-over den)))
|
||||||
|
> (deliver-value (case back
|
||||||
|
> ((0) (instruction op/local0 over)) ;+++
|
||||||
|
> ((1) (instruction op/local1 over)) ;+++
|
||||||
|
> ((2) (instruction op/local2 over)) ;+++
|
||||||
|
> (else (instruction op/local back over)))
|
||||||
|
> cont))
|
||||||
|
> (deliver-value (instruction-with-variable op/global exp den #f)
|
||||||
|
> cont))))
|
||||||
|
143,145c127,132
|
||||||
|
< (if (env-ref? den)
|
||||||
|
< (local-variable den cenv depth #t)
|
||||||
|
< (instruction-with-variable op/set-global! name den #t)))
|
||||||
|
---
|
||||||
|
> (cond ((env-ref? den)
|
||||||
|
> (instruction op/set-local!
|
||||||
|
> (env-ref-back den cenv)
|
||||||
|
> (env-ref-over den)))
|
||||||
|
> (else
|
||||||
|
> (instruction-with-variable op/set-global! name den #t))))
|
||||||
|
203d189
|
||||||
|
< (note-not-leaf!) ; this isn't strictly necessary, but it keeps things simpler
|
||||||
|
222,231c208,215
|
||||||
|
< (cond ((return-cont? cont)
|
||||||
|
< code)
|
||||||
|
< (else
|
||||||
|
< (note-not-leaf!) ; this isn't strictly necessary, but it keeps things simpler
|
||||||
|
< (sequentially (instruction-with-offset&byte op/make-cont
|
||||||
|
< (segment-size code)
|
||||||
|
< depth)
|
||||||
|
< (note-source-code (cont-source-info cont)
|
||||||
|
< code)
|
||||||
|
< (cont-segment cont)))))
|
||||||
|
---
|
||||||
|
> (if (return-cont? cont)
|
||||||
|
> code
|
||||||
|
> (sequentially (instruction-with-offset&byte op/make-cont
|
||||||
|
> (segment-size code)
|
||||||
|
> depth)
|
||||||
|
> (note-source-code (cont-source-info cont)
|
||||||
|
> code)
|
||||||
|
> (cont-segment cont))))
|
||||||
|
264d247
|
||||||
|
< (note-not-leaf!)
|
||||||
|
280,315c263,284
|
||||||
|
< (let-fluids $compiling-leaf 'maybe
|
||||||
|
< (lambda ()
|
||||||
|
< (let ((code (really-compile-lambda-code formals body cenv name)))
|
||||||
|
< (if (eq? (fluid $compiling-leaf) 'maybe)
|
||||||
|
< (let-fluids $compiling-leaf 'yes
|
||||||
|
< (lambda ()
|
||||||
|
< (really-compile-lambda-code formals body cenv name)))
|
||||||
|
< code)))))
|
||||||
|
<
|
||||||
|
< (define (really-compile-lambda-code formals body cenv name)
|
||||||
|
< (let* ((nargs (number-of-required-args formals))
|
||||||
|
< (vars (normalize-formals formals))
|
||||||
|
< (cenv (if (null? formals)
|
||||||
|
< cenv ;+++
|
||||||
|
< (bind-vars vars cenv))))
|
||||||
|
< (sequentially
|
||||||
|
< (cond ((n-ary? formals)
|
||||||
|
< (sequentially
|
||||||
|
< (instruction op/make-rest-list nargs)
|
||||||
|
< (instruction op/push)
|
||||||
|
< (if (compiling-leaf?)
|
||||||
|
< empty-segment
|
||||||
|
< (instruction op/make-env (+ nargs 1)))))
|
||||||
|
< ((null? formals)
|
||||||
|
< (note-not-leaf!) ; no point if no variables
|
||||||
|
< empty-segment)
|
||||||
|
< ((compiling-leaf?)
|
||||||
|
< empty-segment)
|
||||||
|
< (else
|
||||||
|
< (instruction op/make-env nargs)))
|
||||||
|
< (note-environment
|
||||||
|
< vars
|
||||||
|
< (compile-body body
|
||||||
|
< cenv
|
||||||
|
< 0
|
||||||
|
< (return-cont name))))))
|
||||||
|
---
|
||||||
|
> (if (null? formals)
|
||||||
|
> (compile-body body ;+++ Don't make null environment
|
||||||
|
> cenv
|
||||||
|
> 0
|
||||||
|
> (return-cont name))
|
||||||
|
> (sequentially
|
||||||
|
> (let ((nargs (number-of-required-args formals)))
|
||||||
|
> (if (n-ary? formals)
|
||||||
|
> (sequentially
|
||||||
|
> (instruction op/make-rest-list nargs)
|
||||||
|
> (instruction op/push)
|
||||||
|
> (instruction op/make-env (+ nargs 1)))
|
||||||
|
> (instruction op/make-env nargs)))
|
||||||
|
> (let* ((vars (normalize-formals formals))
|
||||||
|
> (cenv (bind-vars vars cenv)))
|
||||||
|
> (note-environment
|
||||||
|
> vars
|
||||||
|
> (compile-body body
|
||||||
|
> cenv
|
||||||
|
> 0
|
||||||
|
> (return-cont name)))))))
|
||||||
|
>
|
||||||
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
-- this file is probably obsolete --
|
|
||||||
|
|
||||||
The package system interface. Much too complicated.
|
|
||||||
|
|
||||||
Signatures
|
|
||||||
|
|
||||||
make-simple-signature
|
|
||||||
make-compound-signature
|
|
||||||
signature?
|
|
||||||
signature-ref
|
|
||||||
signature-walk
|
|
||||||
|
|
||||||
Structures
|
|
||||||
|
|
||||||
make-structure
|
|
||||||
structure?
|
|
||||||
structure-signature
|
|
||||||
structure-package
|
|
||||||
structure-name
|
|
||||||
|
|
||||||
Packages
|
|
||||||
|
|
||||||
make-package
|
|
||||||
make-simple-package ;start.scm
|
|
||||||
|
|
||||||
Lookup and definition operations
|
|
||||||
|
|
||||||
package-lookup
|
|
||||||
package-lookup-type ;comp.scm
|
|
||||||
package-find-location ;rts/env.scm
|
|
||||||
package-lookup-location ;segment.scm
|
|
||||||
probe-package
|
|
||||||
package-check-assigned
|
|
||||||
package-check-variable
|
|
||||||
|
|
||||||
package-define!
|
|
||||||
package-define-type! ;hmm.
|
|
||||||
package-ensure-defined!
|
|
||||||
|
|
||||||
Things needed by the form/file/package scanner
|
|
||||||
|
|
||||||
for-each-definition ;for integrate-all-primitives!
|
|
||||||
package-accesses ;for scan-package
|
|
||||||
package-clauses ;for scan-package
|
|
||||||
package-file-name ;for scan-package
|
|
||||||
package-opens ;for scan-package
|
|
||||||
package-evaluator ;for define-syntax
|
|
||||||
package-for-syntax ;for define-syntax
|
|
||||||
|
|
||||||
Miscellaneous
|
|
||||||
|
|
||||||
$note-undefined ;eval.scm
|
|
||||||
noting-undefined-variables ;eval.scm, etc.
|
|
||||||
package-uid ;eval.scm
|
|
||||||
set-shadow-action! ;eval.scm
|
|
||||||
verify-later! ;for the define-structures macro
|
|
||||||
reset-packages-state! ;Makefile - for linker
|
|
||||||
initialize-reified-package! ;for reification
|
|
||||||
transform-for-structure-ref ;for reification ?
|
|
||||||
|
|
||||||
Inessential (for package mutation, programming environment)
|
|
||||||
|
|
||||||
check-structure
|
|
||||||
package-integrate? ;env/debug.scm
|
|
||||||
set-package-integrate?! ;env/debug.scm
|
|
||||||
package-loaded? ;env/load-package.scm
|
|
||||||
set-package-loaded?! ;env/load-package.scm
|
|
||||||
package-name ;env/command.scm
|
|
||||||
package-name-table ;env/debuginfo.scm
|
|
||||||
package-open! ;env/debug.scm
|
|
||||||
package-system-sentinel ;env/command.scm
|
|
||||||
package-unstable? ;env/pacman.scm
|
|
||||||
package? ;env/command.scm
|
|
||||||
undefined-variables ;env/debug.scm
|
|
||||||
|
|
||||||
Location names (also inessential)
|
|
||||||
|
|
||||||
flush-location-names
|
|
||||||
location-name
|
|
||||||
location-name-table
|
|
||||||
location-package-name
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
What to do when your system isn't supported
|
||||||
|
|
||||||
|
First of all: DON'T PANIC. It's easy to get scsh to work on a new
|
||||||
|
system. Besides, you'll be a hero to the masses waiting for the Scheme
|
||||||
|
Shell on your platform. There is a sample "generic" system in
|
||||||
|
scsh/generic which you can copy as a base to modify. The modifications
|
||||||
|
mainly involve pulling some constants in from C header files and hacking
|
||||||
|
a few lines of C based on your standard I/O internals. I know, its C and
|
||||||
|
all, together we can survive. If you need some hand holding, feel free
|
||||||
|
to write to the scsh mailing list at scsh@zurich.ai.mit.edu.
|
||||||
|
|
||||||
|
stdio_dep.c:
|
||||||
|
This is the one C file you have to actually deal with. The code in here
|
||||||
|
defines two or three simple operations on stdio FILE*'s that are not
|
||||||
|
part of the stdio.h interface. The main things it needs to be able
|
||||||
|
to do is see if there is input ready, how much is ready, and to change
|
||||||
|
the file descriptor associated with a FILE*. Usually how to do this
|
||||||
|
is fairly obvious from <stdio.h>. Check out the other platforms for ideas.
|
||||||
|
|
||||||
|
errno.scm:
|
||||||
|
Scheme defines for C header values found in <errno.h>.
|
||||||
|
|
||||||
|
fdflags.scm:
|
||||||
|
Scheme defines for C header values found in <fcntl.h>.
|
||||||
|
|
||||||
|
netconst.scm:
|
||||||
|
Scheme defines for C header values found in socket and network includes.
|
||||||
|
|
||||||
|
signals.scm:
|
||||||
|
Scheme defines for C header values found in <sys/signal.h>.
|
||||||
|
|
||||||
|
waitcodes.scm:
|
||||||
|
Scheme defines for C header values and macros found in <sys/wait.h>.
|
||||||
|
|
||||||
|
packages.scm:
|
||||||
|
Scheme48 module definitions for the values in the above scheme files.
|
||||||
|
|
||||||
|
load-scsh.scm:
|
||||||
|
The script of commands and expressions used to build scsh.
|
||||||
|
|
||||||
|
After you've hacked these files together, it'd be nice to also hack
|
||||||
|
config.scsh to support your new machine. Run config.guess to see what it
|
||||||
|
thinks your machine is. Then, send us the info, and we'll make sure it
|
||||||
|
gets in a future release. (That means you, Jonathan.)
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
.TH LS48 1
|
||||||
|
.\" File scheme48.man: Manual page template for Scheme 48.
|
||||||
|
.\" Replace LS48 with the name of your default image and LLIB with the
|
||||||
|
.\" directory containing scheme48vm and default image.
|
||||||
|
.SH NAME
|
||||||
|
LS48 \- a Scheme interpreter
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B LS48
|
||||||
|
[-i image] [-h heapsize] [-a argument]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B LS48
|
||||||
|
is an implementation of the Scheme programming language as described in
|
||||||
|
the
|
||||||
|
.I "Revised^4 Report on the Algorithmic Language Scheme."
|
||||||
|
A runnable system requires two parts, an executable program that implements
|
||||||
|
the Scheme 48 virtual machine, and an image that is used to initialize
|
||||||
|
the store of the virtual machine.
|
||||||
|
.B LS48
|
||||||
|
is a shell script that starts the virtual machine with an image that runs
|
||||||
|
in a Scheme command loop.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B LS48
|
||||||
|
command loop reads Scheme expressions,
|
||||||
|
evaluates them, and prints their results.
|
||||||
|
It also executes commands, which are identified by an initial comma character.
|
||||||
|
Type the command
|
||||||
|
.I ,help
|
||||||
|
to receive a list of available commands.
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.B \-h
|
||||||
|
option causes
|
||||||
|
.IR heapsize
|
||||||
|
words to be allocated for both semispaces of the copying garbage
|
||||||
|
collector. One word is four bytes. Cons cells are currently 3 words,
|
||||||
|
so if you want to make sure you can allocate, say, a million cons
|
||||||
|
cells, you should specify
|
||||||
|
.B \-h
|
||||||
|
6000000 (actually a little more, to account for the initial heap
|
||||||
|
image and breathing room).
|
||||||
|
.PP
|
||||||
|
The
|
||||||
|
.I ,dump
|
||||||
|
and
|
||||||
|
.I ,build
|
||||||
|
commands put heap images in files.
|
||||||
|
The
|
||||||
|
.B \-i
|
||||||
|
option causes the initial heap image to be taken from file
|
||||||
|
.IR image .
|
||||||
|
The
|
||||||
|
.B \-a
|
||||||
|
option causes a list of strings to be passed as the argument
|
||||||
|
to an image generated using the
|
||||||
|
.I ,build
|
||||||
|
command. The first argument to
|
||||||
|
.I ,build
|
||||||
|
is a procedure that is passed
|
||||||
|
the arguments following
|
||||||
|
.B \-a
|
||||||
|
and which should return an integer (which is the
|
||||||
|
return value of the Scheme 48 process).
|
||||||
|
.PP
|
||||||
|
.nf
|
||||||
|
> ,build (lambda (a) (display a) (newline) 0) foo.image
|
||||||
|
> ,exit
|
||||||
|
$ LS48 -i foo.image -a mumble
|
||||||
|
mumble
|
||||||
|
$
|
||||||
|
.PP
|
||||||
|
.fi
|
||||||
|
.SH FILES
|
||||||
|
.TP 40
|
||||||
|
.B LLIB/scheme48vm
|
||||||
|
the virtual machine.
|
||||||
|
.TP
|
||||||
|
.B LLIB/LS48.image
|
||||||
|
the default image.
|
||||||
|
.SH BUGS
|
||||||
|
Procedure calls with more than 63 explicit arguments might not work.
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
*.aux *.log *.out
|
||||||
|
*.idx *.ilg *.ind *.dvi
|
||||||
|
.,*
|
||||||
|
*.toc
|
||||||
|
thumb*.png
|
||||||
|
man.ps man.pdf
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
html
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
.SUFFIXES: .tex .dvi .ps .pdf $(.SUFFIXES)
|
||||||
|
|
||||||
|
TEX= front.tex intro.tex procnotation.tex syscalls.tex network.tex \
|
||||||
|
strings.tex awk.tex miscprocs.tex running.tex
|
||||||
|
|
||||||
|
TEX2PAGE=tex2page
|
||||||
|
|
||||||
|
man.dvi: $(TEX)
|
||||||
|
man.pdf: $(TEX)
|
||||||
|
|
||||||
|
.dvi.ps:
|
||||||
|
dvips -j0 -o $@ $<
|
||||||
|
|
||||||
|
.tex.dvi:
|
||||||
|
latex $< && latex $<
|
||||||
|
makeindex $(<:.tex=.idx)
|
||||||
|
rm $*.log
|
||||||
|
|
||||||
|
.tex.pdf:
|
||||||
|
pdflatex $< && thumbpdf $@ && pdflatex $<
|
||||||
|
makeindex $(<:.tex=.idx)
|
||||||
|
rm $*.log
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -f *.log *.png man.out man.dvi man.ps man.pdf thumb*.png
|
||||||
|
rm -rf html
|
||||||
|
|
||||||
|
INSTALL_DATA= install -c -m 644
|
||||||
|
|
||||||
|
tar:
|
||||||
|
tar cf - *.tex sty | gzip > man.tar.gz
|
||||||
|
|
||||||
|
html: $(TEX)
|
||||||
|
$(TEX2PAGE) man && $(TEX2PAGE) man
|
||||||
|
|
||||||
|
install: man.ps
|
||||||
|
@echo WARNING:
|
||||||
|
@echo WARNING: this depends on /u/su/scsh/scsh
|
||||||
|
@echo WARNING: pointing to the current release
|
||||||
|
@echo WARNING:
|
||||||
|
$(INSTALL_DATA) cheat.txt /u/su/scsh/scsh/doc/
|
||||||
|
$(INSTALL_DATA) man.ps /u/su/scsh/scsh/doc/scsh-manual.ps
|
||||||
|
$(INSTALL_DATA) $(TEX) /u/su/scsh/scsh/doc/scsh-manual/
|
||||||
|
$(INSTALL_DATA) sty/* /u/su/scsh/scsh/doc/scsh-manual/sty/
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
Michel.Schinz@studi.epfl.ch
|
||||||
|
Documentation error in STRING-OUTPUT-PORT-OUTPUT.
|
||||||
|
Reported 12/19.
|
||||||
|
|
||||||
|
Victor Zandy
|
||||||
|
character-gobbling in (record-reader) caused by 'trim / 'peek
|
||||||
|
default misunderstanding in delimited readers. Fixed 4/5/96
|
||||||
|
|
||||||
|
Michael Becker
|
||||||
|
reap-policy = early can still lose if you loop and fork.
|
||||||
|
fork now reaps & retries if it loses and the policy is early reap.
|
||||||
|
This is a kludge until I have sigchld handlers.
|
||||||
|
Fixed 4/5/96
|
||||||
|
|
||||||
|
Tod Olson
|
||||||
|
Reported painfully slow delimited-reader I/O in November.
|
||||||
|
|
||||||
|
Michel.Schinz@studi.epfl.ch
|
||||||
|
Reported some picky little typos in the manual.
|
||||||
|
|
||||||
|
Shriram
|
||||||
|
Doc bugs in defrec.scm
|
||||||
|
|
||||||
|
euler@lavielle.COM (Lutz Euler) 2/24/97
|
||||||
|
Manual bugs and a bug in stdio->stdports.
|
||||||
|
|
||||||
|
Alan Bawden 4/97
|
||||||
|
Lots of good bug reports and fixes.
|
||||||
|
|
||||||
|
Jim Blandy 4/97
|
||||||
|
Fixes for meta.scm
|
||||||
|
|
||||||
|
Kevin Esler 4/97
|
||||||
|
Updated Irix port
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
Acknowledgements
|
||||||
|
|
||||||
|
Who should I thank? My so-called "colleagues," who laugh at me behind my
|
||||||
|
back, all the while becoming famous on *my* work? My worthless graduate
|
||||||
|
students, whose computer skills appear to be limited to downloading bitmaps
|
||||||
|
off of netnews? My parents, who are still waiting for me to quit "fooling
|
||||||
|
around with computers," go to med school, and become a radiologist? My
|
||||||
|
department chairman, a manager who gives one new insight into and sympathy for
|
||||||
|
disgruntled postal workers?
|
||||||
|
|
||||||
|
My God, no one could blame me--no one!--if I went off the edge and just lost
|
||||||
|
it completely one day. I couldn't get through the day as it is without the
|
||||||
|
Prozac and Jack Daniels I keep on the shelf, behind my Tops-20 JSYS manuals.
|
||||||
|
I start getting the shakes real bad around 10am, right before my advisor
|
||||||
|
meetings. A 10 oz. Jack 'n Zac helps me get through the meetings without one
|
||||||
|
of my students winding up with his severed head in a bowling-ball bag. They
|
||||||
|
look at me funny; they think I twitch a lot. I'm not twitching. I'm
|
||||||
|
controlling my impulse to snag my 9mm Sig-Sauer out from my day-pack and make
|
||||||
|
a few strong points about the quality of undergraduate education in Amerika.
|
||||||
|
|
||||||
|
If I thought anyone cared, if I thought anyone would even be reading this, I'd
|
||||||
|
probably make an effort to keep up appearances until the last possible
|
||||||
|
moment. But no one does, and no one will. So I can pretty much say exactly
|
||||||
|
what I think.
|
||||||
|
|
||||||
|
Oh, yes, the *acknowledgements.* I think not. I did it. I did it all,
|
||||||
|
by myself.
|
||||||
|
|
||||||
|
Olin Shivers
|
||||||
|
Cambridge
|
||||||
|
September 4, 1994
|
||||||
|
|
||||||
|
|
@ -0,0 +1,252 @@
|
||||||
|
%%
|
||||||
|
%% This is file `/usr2/distrib/latex209/nfss/array.sty' generated
|
||||||
|
%% on <1991/11/22> with the docstrip utility (v1.1k).
|
||||||
|
%%
|
||||||
|
%% The original source files were:
|
||||||
|
%%
|
||||||
|
%% /usr2/users/latex3/source/array/array.doc
|
||||||
|
|
||||||
|
%%
|
||||||
|
%% Copyright (C) 1989,1990,1991 by Frank Mittelbach, Rainer Schoepf.
|
||||||
|
%% All rights reserved.
|
||||||
|
%%
|
||||||
|
%% This file is part of the NFSS (New Font Selection Scheme) package.
|
||||||
|
%%
|
||||||
|
%% IMPORTANT NOTICE:
|
||||||
|
%%
|
||||||
|
%% You are not allowed to change this file. You may however copy this file
|
||||||
|
%% to a file with a different name and then change the copy if you obey
|
||||||
|
%% the restrictions on file changes described in readme.mz.
|
||||||
|
%%
|
||||||
|
%% You are allowed to distribute this file under the condition that it is
|
||||||
|
%% distributed together with all files mentioned in readme.mz3. If you
|
||||||
|
%% receive only some of these files from someone, complain!
|
||||||
|
%%
|
||||||
|
%% You are NOT ALLOWED to distribute this file alone. You are NOT ALLOWED
|
||||||
|
%% to take money for the distribution or use of either this file or a
|
||||||
|
%% changed version, except for a nominal charge for copying etc.
|
||||||
|
%%
|
||||||
|
%% For error reports in case of UNCHANGED versions see readme files.
|
||||||
|
%%
|
||||||
|
%% Please do not request updates from us directly. Distribution is done
|
||||||
|
%% through Mail-Servers and TeX organizations.
|
||||||
|
%%
|
||||||
|
|
||||||
|
\def\fileversion{v2.0e}
|
||||||
|
\def\filedate{91/02/07}
|
||||||
|
\def\docdate {90/08/20}
|
||||||
|
|
||||||
|
%% \CheckSum{681}
|
||||||
|
%% \CharacterTable
|
||||||
|
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||||
|
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||||
|
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||||
|
%% Exclamation \! Double quote \" Hash (number) \#
|
||||||
|
%% Dollar \$ Percent \% Ampersand \&
|
||||||
|
%% Acute accent \' Left paren \( Right paren \)
|
||||||
|
%% Asterisk \* Plus \+ Comma \,
|
||||||
|
%% Minus \- Point \. Solidus \/
|
||||||
|
%% Colon \: Semicolon \; Less than \<
|
||||||
|
%% Equals \= Greater than \> Question mark \?
|
||||||
|
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||||
|
%% Right bracket \] Circumflex \^ Underscore \_
|
||||||
|
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||||
|
%% Right brace \} Tilde \~}
|
||||||
|
%%
|
||||||
|
\@ifundefined{d@llar}{}{\endinput}
|
||||||
|
\typeout{Style-Option: `array' \fileversion
|
||||||
|
\space\space <\filedate> (F.M.)}
|
||||||
|
\typeout{English documentation dated \space <\docdate> (F.M.)}
|
||||||
|
\def\@addtopreamble#1{\xdef\@preamble{\@preamble #1}}
|
||||||
|
\def\@testpach#1{\@chclass
|
||||||
|
\ifnum \@lastchclass=6 \@ne \@chnum \@ne \else
|
||||||
|
\ifnum \@lastchclass=7 5 \else
|
||||||
|
\ifnum \@lastchclass=8 \tw@ \else
|
||||||
|
\ifnum \@lastchclass=9 \thr@@
|
||||||
|
\else \z@
|
||||||
|
\ifnum \@lastchclass = 10 \else
|
||||||
|
\@chnum
|
||||||
|
\if #1c\z@ \else
|
||||||
|
\if #1l\@ne \else
|
||||||
|
\if #1r\tw@ \else
|
||||||
|
\z@ \@chclass
|
||||||
|
\if#1|\@ne \else
|
||||||
|
\if #1!6 \else
|
||||||
|
\if #1@7 \else
|
||||||
|
\if #1<8 \else
|
||||||
|
\if #1>9 \else
|
||||||
|
10
|
||||||
|
\@chnum
|
||||||
|
\if #1m\thr@@\else
|
||||||
|
\if #1p4 \else
|
||||||
|
\if #1b5 \else
|
||||||
|
\z@ \@chclass \z@ \@preamerr \z@ \fi \fi \fi \fi
|
||||||
|
\fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi \fi}
|
||||||
|
\def\@xexpast#1*#2#3#4\@@{%
|
||||||
|
\@tempcnta #2
|
||||||
|
\toks@={#1}\@temptokena={#3}%
|
||||||
|
\let\the@toksz\relax \let\the@toks\relax
|
||||||
|
\def\@tempa{\the@toksz}%
|
||||||
|
\ifnum\@tempcnta >0 \@whilenum\@tempcnta >0\do
|
||||||
|
{\edef\@tempa{\@tempa\the@toks}\advance \@tempcnta \m@ne}%
|
||||||
|
\let \@tempb \@xexpast \else
|
||||||
|
\let \@tempb \@xexnoop \fi
|
||||||
|
\def\the@toksz{\the\toks@}\def\the@toks{\the\@temptokena}%
|
||||||
|
\edef\@tempa{\@tempa}%
|
||||||
|
\expandafter \@tempb \@tempa #4\@@}
|
||||||
|
\def\prepnext@tok{\advance \count@ \@ne
|
||||||
|
\toks\count@={}}
|
||||||
|
\def\save@decl{\toks\count@ \expandafter{\@nextchar}}
|
||||||
|
\def\insert@column{%
|
||||||
|
\the@toks \the \@tempcnta
|
||||||
|
{\ignorespaces \@sharp \unskip}%
|
||||||
|
\the@toks \the \count@ \relax}
|
||||||
|
\newdimen\col@sep
|
||||||
|
\def\@acol{\@addtopreamble{\hskip\col@sep}}
|
||||||
|
\def\@mkpream#1{\gdef\@preamble{}\@lastchclass 4 \@firstamptrue
|
||||||
|
\let\@sharp\relax \let\@startpbox\relax \let\@endpbox\relax
|
||||||
|
\@xexpast #1*0x\@@
|
||||||
|
\count@\m@ne
|
||||||
|
\let\the@toks\relax
|
||||||
|
\prepnext@tok
|
||||||
|
\expandafter \@tfor \expandafter \@nextchar
|
||||||
|
\expandafter :\expandafter =\@tempa \do
|
||||||
|
{\@testpach\@nextchar
|
||||||
|
\ifcase \@chclass \@classz \or \@classi \or \@classii
|
||||||
|
\or \save@decl \or \or \@classv \or \@classvi
|
||||||
|
\or \@classvii \or \@classviii \or \@classix
|
||||||
|
\or \@classx \fi
|
||||||
|
\@lastchclass\@chclass}%
|
||||||
|
\ifcase\@lastchclass
|
||||||
|
\@acol \or
|
||||||
|
\or
|
||||||
|
\@acol \or
|
||||||
|
\@preamerr \thr@@ \or
|
||||||
|
\@preamerr \tw@ \@addtopreamble\@sharp \or
|
||||||
|
\or
|
||||||
|
\else \@preamerr \@ne \fi
|
||||||
|
\def\the@toks{\the\toks}}
|
||||||
|
\def\@classx{%
|
||||||
|
\ifcase \@lastchclass
|
||||||
|
\@acolampacol \or
|
||||||
|
\@addamp \@acol \or
|
||||||
|
\@acolampacol \or
|
||||||
|
\or
|
||||||
|
\@acol \@firstampfalse \or
|
||||||
|
\@addamp
|
||||||
|
\fi}
|
||||||
|
\def\@classz{\@classx
|
||||||
|
\@tempcnta \count@
|
||||||
|
\prepnext@tok
|
||||||
|
\@addtopreamble{\ifcase \@chnum
|
||||||
|
\hfil
|
||||||
|
\d@llar
|
||||||
|
\insert@column
|
||||||
|
\d@llar \hfil \or
|
||||||
|
\d@llar \insert@column \d@llar \hfil \or
|
||||||
|
\hfil\kern\z@ \d@llar \insert@column \d@llar \or
|
||||||
|
$\vcenter
|
||||||
|
\@startpbox{\@nextchar}\insert@column \@endpbox $\or
|
||||||
|
\vtop \@startpbox{\@nextchar}\insert@column \@endpbox \or
|
||||||
|
\vbox \@startpbox{\@nextchar}\insert@column \@endpbox
|
||||||
|
\fi}\prepnext@tok}
|
||||||
|
\def\@classix{\ifnum \@lastchclass = \thr@@
|
||||||
|
\@preamerr \thr@@ \fi
|
||||||
|
\@classx}
|
||||||
|
\def\@classviii{\ifnum \@lastchclass >\z@
|
||||||
|
\@preamerr 4\@chclass 6 \@classvi \fi}
|
||||||
|
\def\@arrayrule{\@addtopreamble \vline}
|
||||||
|
\def\@classvii{\ifnum \@lastchclass = \thr@@
|
||||||
|
\@preamerr \thr@@ \fi}
|
||||||
|
\def\@classvi{\ifcase \@lastchclass
|
||||||
|
\@acol \or
|
||||||
|
\@addtopreamble{\hskip \doublerulesep}\or
|
||||||
|
\@acol \or
|
||||||
|
\@classvii
|
||||||
|
\fi}
|
||||||
|
\def\@classii{\advance \count@ \m@ne
|
||||||
|
\save@decl\prepnext@tok}
|
||||||
|
\def\@classv{\save@decl
|
||||||
|
\@addtopreamble{\d@llar\the@toks\the\count@\relax\d@llar}%
|
||||||
|
\prepnext@tok}
|
||||||
|
\def\@classi{\@classvi
|
||||||
|
\ifcase \@chnum \@arrayrule \or
|
||||||
|
\@classv \fi}
|
||||||
|
\def\@startpbox#1{\bgroup
|
||||||
|
\hsize #1 \@arrayparboxrestore
|
||||||
|
\vrule \@height \ht\@arstrutbox \@width \z@}
|
||||||
|
\def\@endpbox{\vrule \@width \z@ \@depth \dp \@arstrutbox \egroup}
|
||||||
|
\def\@array[#1]#2{%
|
||||||
|
\@tempdima \ht \strutbox
|
||||||
|
\advance \@tempdima by\extrarowheight
|
||||||
|
\setbox \@arstrutbox \hbox{\vrule
|
||||||
|
\@height \arraystretch \@tempdima
|
||||||
|
\@depth \arraystretch \dp \strutbox
|
||||||
|
\@width \z@}%
|
||||||
|
\begingroup
|
||||||
|
\@mkpream{#2}%
|
||||||
|
\xdef\@preamble{\ialign \@halignto
|
||||||
|
\bgroup \@arstrut \@preamble
|
||||||
|
\tabskip \z@ \cr}%
|
||||||
|
\endgroup
|
||||||
|
\if #1t\vtop \else \if#1b\vbox \else \vcenter \fi \fi
|
||||||
|
\bgroup
|
||||||
|
\let \@sharp ##\let \protect \relax
|
||||||
|
\lineskip \z@
|
||||||
|
\baselineskip \z@
|
||||||
|
\m@th
|
||||||
|
\let\\ \@arraycr \let\par\@empty \@preamble}
|
||||||
|
\newdimen \extrarowheight
|
||||||
|
\extrarowheight=0pt
|
||||||
|
\def\@arstrut{\unhcopy\@arstrutbox}
|
||||||
|
\def\@arraycr{{\ifnum 0=`}\fi
|
||||||
|
\@ifstar \@xarraycr \@xarraycr}
|
||||||
|
\def\@xarraycr{\@ifnextchar [%
|
||||||
|
\@argarraycr {\ifnum 0=`{\fi}\cr}}
|
||||||
|
\def\@argarraycr[#1]{\ifnum0=`{\fi}\ifdim #1>\z@
|
||||||
|
\@xargarraycr{#1}\else \@yargarraycr{#1}\fi}
|
||||||
|
\def\@xargarraycr#1{\unskip
|
||||||
|
\@tempdima #1\advance\@tempdima \dp\@arstrutbox
|
||||||
|
\vrule \@depth\@tempdima \@width\z@ \cr}
|
||||||
|
\def\@yargarraycr#1{\cr\noalign{\vskip #1}}
|
||||||
|
\def\multicolumn#1#2#3{%
|
||||||
|
\multispan{#1}\begingroup
|
||||||
|
\def\@addamp{\if@firstamp \@firstampfalse \else
|
||||||
|
\@preamerr 5\fi}%
|
||||||
|
\@mkpream{#2}\@addtopreamble\@empty
|
||||||
|
\endgroup
|
||||||
|
\def\@sharp{#3}%
|
||||||
|
\@arstrut \@preamble \ignorespaces}
|
||||||
|
\def\array{\col@sep\arraycolsep
|
||||||
|
\def\d@llar{$}\gdef\@halignto{}%
|
||||||
|
\@tabarray}
|
||||||
|
\def\@tabarray{\@ifnextchar[{\@array}{\@array[c]}}
|
||||||
|
\def\tabular{\gdef\@halignto{}\@tabular}
|
||||||
|
\expandafter\def\csname tabular*\endcsname#1{%
|
||||||
|
\gdef\@halignto{to#1}\@tabular}
|
||||||
|
\def\@tabular{%
|
||||||
|
\leavevmode
|
||||||
|
\hbox \bgroup $\col@sep\tabcolsep \let\d@llar\@empty
|
||||||
|
\@tabarray}
|
||||||
|
\def\endarray{\crcr \egroup \egroup \gdef\@preamble{}}
|
||||||
|
\def\endtabular{\endarray $\egroup}
|
||||||
|
\expandafter\let\csname endtabular*\endcsname=\endtabular
|
||||||
|
\let\@ampacol=\relax \let\@expast=\relax
|
||||||
|
\let\@arrayclassiv=\relax \let\@arrayclassz=\relax
|
||||||
|
\let\@tabclassiv=\relax \let\@tabclassz=\relax
|
||||||
|
\let\@arrayacol=\relax \let\@tabacol=\relax
|
||||||
|
\let\@tabularcr=\relax \let\@@endpbox=\relax
|
||||||
|
\let\@argtabularcr=\relax \let\@xtabularcr=\relax
|
||||||
|
\def\@preamerr#1{\def\@tempd{{..} at wrong position: }%
|
||||||
|
\@latexerr{%
|
||||||
|
\ifcase #1 Illegal pream-token (\@nextchar): `c' used\or %0
|
||||||
|
Missing arg: token ignored\or %1
|
||||||
|
Empty preamble: `l' used\or %2
|
||||||
|
>\@tempd token ignored\or %3
|
||||||
|
<\@tempd changed to !{..}\or %4
|
||||||
|
Only one colum-spec. allowed.\fi}\@ehc} %5
|
||||||
|
\def\@tfor#1:=#2\do#3{\def\@fortmp{#2}\ifx\@fortmp\@empty
|
||||||
|
\else\@tforloop#2\@nil\@nil\@@#1{#3}\fi}
|
||||||
|
\endinput
|
||||||
|
%%
|
||||||
|
%% End of file `/usr2/distrib/latex209/nfss/array.sty'.
|
||||||
|
|
@ -0,0 +1,672 @@
|
||||||
|
%&latex -*- latex -*-
|
||||||
|
|
||||||
|
\chapter{Awk, record I/O, and field parsing}
|
||||||
|
\label{chapt:fr-awk}
|
||||||
|
|
||||||
|
{\Unix} programs frequently process streams of records,
|
||||||
|
where each record is delimited by a newline,
|
||||||
|
and records are broken into fields with other delimiters
|
||||||
|
(for example, the colon character in \ex{/etc/passwd}).
|
||||||
|
Scsh has procedures that allow the programmer to easily
|
||||||
|
do this kind of processing.
|
||||||
|
Scsh's field parsers can also be used to parse other kinds
|
||||||
|
of delimited strings, such as colon-separated \verb|$PATH| lists.
|
||||||
|
These routines can be used with scsh's \ex{awk} loop construct
|
||||||
|
to conveniently perform pattern-directed computation over streams
|
||||||
|
of records.
|
||||||
|
|
||||||
|
|
||||||
|
\section{Record I/O and field parsing}
|
||||||
|
\label{sec:field-reader}
|
||||||
|
|
||||||
|
The procedures in this section are used to read records from
|
||||||
|
I/O streams and parse them into fields.
|
||||||
|
A record is defined as text terminated by some delimiter (usually a newline).
|
||||||
|
A record can be split into fields by using regular expressions in
|
||||||
|
one of several ways: to \emph{match} fields, to \emph{separate} fields,
|
||||||
|
or to \emph{terminate} fields.
|
||||||
|
The field parsers can be applied to arbitrary strings (one common use is
|
||||||
|
splitting environment variables such as \ex{\$PATH} at colons into its
|
||||||
|
component elements).
|
||||||
|
|
||||||
|
The general delimited-input procedures described in
|
||||||
|
chapter~\ref{chapt:rdelim} are also useful for reading simple records,
|
||||||
|
such as single lines, paragraphs of text, or strings terminated by specific
|
||||||
|
characters.
|
||||||
|
|
||||||
|
\subsection{Reading records}
|
||||||
|
|
||||||
|
\defun{record-reader} {[delims elide-delims? handle-delim]} {\proc}
|
||||||
|
\begin{desc}
|
||||||
|
Returns a procedure that reads records from a port. The
|
||||||
|
procedure is invoked as follows:
|
||||||
|
%
|
||||||
|
\codex{(\var{reader} \var{[port]}) $\longrightarrow$
|
||||||
|
\textrm{\textit{{\str} or eof}}}
|
||||||
|
%
|
||||||
|
A record is a sequence of characters terminated by one of the characters
|
||||||
|
in \var{delims} or eof. If \var{elide-delims?} is true, then a contiguous
|
||||||
|
sequence of delimiter chars are taken as a single record delimiter. If
|
||||||
|
\var{elide-delims?} is false, then a delimiter char coming immediately
|
||||||
|
after a delimiter char produces an empty-string record. The reader
|
||||||
|
consumes the delimiting char(s) before returning from a read.
|
||||||
|
|
||||||
|
The \var{delims} set defaults to the set $\{\mbox{newline}\}$.
|
||||||
|
It may be a charset, string, character, or character predicate,
|
||||||
|
and is coerced to a charset.
|
||||||
|
The \var{elide-delims?} flag defaults to \ex{\#f}.
|
||||||
|
|
||||||
|
The \var{handle-delim} argument controls what is done with the record's
|
||||||
|
terminating delimiter.
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{lp{0.6\linewidth}}
|
||||||
|
\ex{'trim} & Delimiters are trimmed. (The default)\\
|
||||||
|
\ex{'split}& Reader returns delimiter string as a second argument.
|
||||||
|
If record is terminated by EOF, then the eof object is
|
||||||
|
returned as this second argument. \\
|
||||||
|
\ex{'concat} & The record and its delimiter are returned as
|
||||||
|
a single string.
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
The reader procedure returned takes one optional argument, the port
|
||||||
|
from which to read, which defaults to the current input port. It returns
|
||||||
|
a string or eof.
|
||||||
|
\end{desc}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Parsing fields}
|
||||||
|
\label{sec:field-splitter}
|
||||||
|
|
||||||
|
\defun {field-splitter} {[field num-fields]} \proc
|
||||||
|
\defunx {infix-splitter} {[delim num-fields handle-delim]} \proc
|
||||||
|
\defunx {suffix-splitter} {[delim num-fields handle-delim]} \proc
|
||||||
|
\defunx {sloppy-suffix-splitter} {[delim num-fields handle-delim]} \proc
|
||||||
|
\begin{desc}
|
||||||
|
These functions return a parser function that can be used as follows:
|
||||||
|
\codex{(\var{parser} \var{string} \var{[start]}) $\longrightarrow$
|
||||||
|
\var{string-list}}
|
||||||
|
|
||||||
|
The returned parsers split strings into fields defined
|
||||||
|
by regular expressions. You can parse by specifying a pattern that
|
||||||
|
\emph{separates} fields, a pattern that \emph{terminates} fields, or
|
||||||
|
a pattern that \emph{matches} fields:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{l@{\qquad}l}
|
||||||
|
Procedure & Pattern \\ \hline
|
||||||
|
\ex{field-splitter} & matches fields \\
|
||||||
|
\ex{infix-splitter} & separates fields \\
|
||||||
|
\ex{suffix-splitter}& terminates fields \\
|
||||||
|
\ex{sloppy-suffix-splitter} & terminates fields
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
These parser generators are controlled by a range of options, so that you
|
||||||
|
can precisely specify what kind of parsing you want. However, these
|
||||||
|
options default to reasonable values for general use.
|
||||||
|
|
||||||
|
Defaults:
|
||||||
|
\begin{tightinset}
|
||||||
|
\begin{tabular}{l@{\quad=\quad }ll}
|
||||||
|
\var{delim} & \ex{(rx (| (+ white) eos))} & (suffix delimiter: white space or eos) \\
|
||||||
|
\multicolumn{1}{l}{} & \ex{(rx (+ white))} & (infix delimiter: white space) \\
|
||||||
|
|
||||||
|
\var{field} & \verb|(rx (+ (~ white)))| & (non-white-space) \\
|
||||||
|
|
||||||
|
\var{num-fields} & \verb|#f| & (as many fields as possible) \\
|
||||||
|
|
||||||
|
\var{handle-delim} & \verb|'trim| & (discard delimiter chars)
|
||||||
|
\end{tabular}
|
||||||
|
\end{tightinset}
|
||||||
|
{\ldots}which means: break the string at white space, discarding the
|
||||||
|
white space, and parse as many fields as possible.
|
||||||
|
|
||||||
|
The \var{delim} parameter is a regular expression matching the text
|
||||||
|
that occurs between fields.
|
||||||
|
See chapter~\ref{chapt:sre} for information on regular expressions,
|
||||||
|
and the \ex{rx} form used to specify them.
|
||||||
|
In the separator case,
|
||||||
|
it defaults to a pattern matching white space;
|
||||||
|
in the terminator case,
|
||||||
|
it defaults to white space or end-of-string.
|
||||||
|
|
||||||
|
The \var{field} parameter is a regular expression used
|
||||||
|
to match fields. It defaults to non-white-space.
|
||||||
|
|
||||||
|
The \var{delim} patterns may also be given as a string,
|
||||||
|
character, or char-set, which are coerced to regular expressions.
|
||||||
|
So the following expressions are all equivalent,
|
||||||
|
each producing a function that splits strings apart at colons:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{verbatim}
|
||||||
|
(infix-splitter (rx ":"))
|
||||||
|
(infix-splitter ":")
|
||||||
|
(infix-splitter #\:)
|
||||||
|
(infix-splitter (char-set #\:))\end{verbatim}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
The boolean \var{handle-delim} determines what to do with delimiters.
|
||||||
|
\begin{tightinset}\begin{tabular}{ll}
|
||||||
|
\ex{'trim} & Delimiters are thrown away after parsing. (default) \\
|
||||||
|
\ex{'concat} & Delimiters are appended to the field preceding them. \\
|
||||||
|
\ex{'split} & Delimiters are returned as separate elements in
|
||||||
|
the field list.
|
||||||
|
\end{tabular}
|
||||||
|
\end{tightinset}
|
||||||
|
|
||||||
|
The \var{num-fields} argument used to create the parser specifies how many
|
||||||
|
fields to parse. If \ex{\#f} (the default), the procedure parses them all.
|
||||||
|
If a positive integer $n$, exactly that many fields are parsed; it is an
|
||||||
|
error if there are more or fewer than $n$ fields in the record. If
|
||||||
|
\var{num-fields} is a negative integer or zero, then $|n|$ fields
|
||||||
|
are parsed, and the remainder of the string is returned in the last
|
||||||
|
element of the field list; it is an error if fewer than $|n|$ fields
|
||||||
|
can be parsed.
|
||||||
|
|
||||||
|
The field parser produced is a procedure that can be employed as
|
||||||
|
follows:
|
||||||
|
\codex{(\var{parse} \var{string} \var{[start]}) \evalto \var{string-list}}
|
||||||
|
The optional \var{start} argument (default 0) specifies where in the string
|
||||||
|
to begin the parse. It is an error if
|
||||||
|
$\var{start} > \ex{(string-length \var{string})}$.
|
||||||
|
|
||||||
|
The parsers returned by the four parser generators implement different
|
||||||
|
kinds of field parsing:
|
||||||
|
\begin{description}
|
||||||
|
\item[\ex{field-splitter}]
|
||||||
|
The regular expression specifies the actual field.
|
||||||
|
|
||||||
|
|
||||||
|
\item[\ex{suffix-splitter}]
|
||||||
|
Delimiters are interpreted as element \emph{terminators}.
|
||||||
|
If vertical-bar is the the delimiter, then the string \ex{""}
|
||||||
|
is the empty record \ex{()}, \ex{"foo|"} produces a one-field record
|
||||||
|
\ex{("foo")}, and \ex{"foo"} is an error.
|
||||||
|
|
||||||
|
The syntax of suffix-delimited records is:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{lcll}
|
||||||
|
\synvar{record} & ::= & \ex{""} \qquad (Empty record) \\
|
||||||
|
& $|$ & \synvar{element} \synvar{delim}
|
||||||
|
\synvar{record}
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
It is an error if a non-empty record does not end with a delimiter.
|
||||||
|
To make the last delimiter optional, make sure the delimiter regexp
|
||||||
|
matches the end-of-string (sre \ex{eos}).
|
||||||
|
|
||||||
|
\item [\ex{infix-splitter}]
|
||||||
|
Delimiters are interpreted as element \emph{separators}. If comma is the
|
||||||
|
delimiter, then the string \ex{"foo,"} produces a two-field
|
||||||
|
record \ex{("foo" "")}.
|
||||||
|
|
||||||
|
The syntax of infix-delimited records is:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{lcll}
|
||||||
|
\synvar{record} & ::= & \ex{""} \qquad (Forced to be empty record) \\
|
||||||
|
& $|$ & \synvar{real-infix-record} \\
|
||||||
|
\\
|
||||||
|
\synvar{real-infix-record} & ::= & \synvar{element} \synvar{delim}
|
||||||
|
\synvar{real-infix-record} \\
|
||||||
|
& $|$ & \synvar{element}
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
Note that separator semantics doesn't really allow for empty
|
||||||
|
records---the straightforward grammar (\ie, \synvar{real-infix-record})
|
||||||
|
parses an empty string as a singleton list whose one field is the empty
|
||||||
|
string, \ex{("")}, not as the empty record \ex{()}. This is unfortunate,
|
||||||
|
since it means that infix string parsing doesn't make \ex{string-append}
|
||||||
|
and \ex{append} isomorphic. For example,
|
||||||
|
\codex{((infix-splitter ":") (string-append \var{x} ":" \var{y}))}
|
||||||
|
doesn't always equal
|
||||||
|
\begin{code}
|
||||||
|
(append ((infix-splitter ":") \var{x})
|
||||||
|
((infix-splitter ":") \var{y}))\end{code}
|
||||||
|
It fails when \var{x} or \var{y} are the empty string.
|
||||||
|
Terminator semantics \emph{does} preserve a similar isomorphism.
|
||||||
|
|
||||||
|
However, separator semantics is frequently what other Unix software
|
||||||
|
uses, so to parse their strings, we need to use it. For example,
|
||||||
|
Unix \verb|$PATH| lists have separator semantics. The path list
|
||||||
|
\ex{"/bin:"} is broken up into \ex{("/bin" "")}, not \ex{("/bin")}.
|
||||||
|
Comma-separated lists should also be parsed this way.
|
||||||
|
|
||||||
|
\item[\ex{sloppy-suffix}]
|
||||||
|
The same as the \ex{suffix} case, except that the parser will skip an
|
||||||
|
initial delimiter string if the string begins with one instead of parsing
|
||||||
|
an initial empty field. This can be used, for example, to field-split a
|
||||||
|
sequence of English text at white-space boundaries, where the string may
|
||||||
|
begin or end with white space, by using regex
|
||||||
|
\begin{code}{(rx (| (+ white) eos))}\end{code}
|
||||||
|
(But you would be better off using \ex{field-splitter} in this case.)
|
||||||
|
\end{description}
|
||||||
|
\end{desc}
|
||||||
|
|
||||||
|
Figure~\ref{fig:splitters} shows how the different parser grammars
|
||||||
|
split apart the same strings.
|
||||||
|
%
|
||||||
|
\begin{boxedfigure}{tbp}
|
||||||
|
\begin{center}\small
|
||||||
|
\begin{tabular}{lllll}
|
||||||
|
Record & : suffix & \verb!:|$! suffix & : infix & non-: field \\
|
||||||
|
\hline
|
||||||
|
\ex{""} & \ex{()} & \ex{()} & \ex{()} & \ex{()} \\
|
||||||
|
\ex{":"} & \ex{("")} & \ex{("")} & \ex{("" "")} & \ex{()} \\
|
||||||
|
\ex{"foo:"} & \ex{("foo")} & \ex{("foo")} & \ex{("foo" "")} & \ex{("foo")} \\
|
||||||
|
\ex{":foo"}& \emph{error} & \ex{("" "foo")}& \ex{("" "foo")}& \ex{("foo")} \\
|
||||||
|
\ex{"foo:bar"} & \emph{error} & \ex{("foo" "bar")} & \ex{("foo" "bar")} & \ex{("foo" "bar")}
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
\caption{Using different grammars to split records into fields.}
|
||||||
|
\label{fig:splitters}
|
||||||
|
\end{boxedfigure}
|
||||||
|
%
|
||||||
|
Having to choose between the different grammars requires you to decide
|
||||||
|
what you want, but at least you can be precise about what you are parsing.
|
||||||
|
Take fifteen seconds and think it out. Say what you mean; mean what you
|
||||||
|
say.
|
||||||
|
|
||||||
|
|
||||||
|
\defun{join-strings} {string-list [delimiter grammar]} \str
|
||||||
|
\begin{desc}
|
||||||
|
This procedure is a simple unparser---it pastes strings together using
|
||||||
|
the delimiter string.
|
||||||
|
|
||||||
|
The \var{grammar} argument is one of the symbols \ex{infix} (the default)
|
||||||
|
or \ex{suffix}; it determines whether the
|
||||||
|
delimiter string is used as a separator or as a terminator.
|
||||||
|
|
||||||
|
The delimiter is the string used to delimit elements; it defaults to
|
||||||
|
a single space \ex{" "}.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
\begin{code}
|
||||||
|
(join-strings '("foo" "bar" "baz") ":")
|
||||||
|
\qquad{\evalto} "foo:bar:baz"\end{code}
|
||||||
|
\end{desc}
|
||||||
|
|
||||||
|
\subsection{Field readers}
|
||||||
|
|
||||||
|
\defun{field-reader} {[field-parser rec-reader]} \proc
|
||||||
|
\begin{desc}
|
||||||
|
This utility returns a procedure that reads records with field structure
|
||||||
|
from a port.
|
||||||
|
The reader's interface is designed to make it useful in the \ex{awk}
|
||||||
|
loop macro (section~\ref{sec:awk}).
|
||||||
|
The reader is used as follows:
|
||||||
|
\codex{(\var{reader} \var{[port]}) {\evalto} \var{[raw-record parsed-record]} or \var{[eof ()]}}
|
||||||
|
|
||||||
|
When the reader is applied to an input port (default: the current
|
||||||
|
input port), it reads a record using \var{rec-reader}. If this record isn't
|
||||||
|
the eof object, it is parsed with \var{field-parser}. These two
|
||||||
|
values---the record, and its parsed representation---are returned
|
||||||
|
as multiple values from the reader.
|
||||||
|
|
||||||
|
When called at eof, the reader returns [eof-object \ex{()}].
|
||||||
|
|
||||||
|
Although the record reader typically returns a string, and
|
||||||
|
the field-parser typically takes a string argument, this is not
|
||||||
|
required. The record reader can produce, and the field-parser consume,
|
||||||
|
values of any type. However, the empty list returned as the
|
||||||
|
parsed value on eof is hardwired into the field reader.
|
||||||
|
|
||||||
|
For example, if port \ex{p} is open on \ex{/etc/passwd}, then
|
||||||
|
\codex{((field-reader (infix-splitter ":" 7)) p)}
|
||||||
|
returns two values:
|
||||||
|
{\small
|
||||||
|
\begin{widecode}
|
||||||
|
"dalbertz:mx3Uaqq0:107:22:David Albertz:/users/dalbertz:/bin/csh"
|
||||||
|
("dalbertz" "mx3Uaqq0" "107" "22" "David Albertz" "/users/dalbertz"
|
||||||
|
"/bin/csh")\end{widecode}}
|
||||||
|
The \var{field-parser} defaults to the value of \ex{(field-splitter)},
|
||||||
|
a parser that picks out sequences of non-white-space strings.
|
||||||
|
|
||||||
|
The \var{rec-reader} defaults to \ex{read-line}.
|
||||||
|
|
||||||
|
Figure~\ref{fig:field-readers} shows \ex{field-reader} being
|
||||||
|
used to read different kinds of Unix records.
|
||||||
|
|
||||||
|
\begin{boxedfigure}{tbhp}
|
||||||
|
\begin{centercode}
|
||||||
|
;;; /etc/passwd reader
|
||||||
|
(field-reader (infix-splitter ":" 7))
|
||||||
|
; wandy:3xuncWdpKhR.:73:22:Wandy Saetan:/usr/wandy:/bin/csh
|
||||||
|
|
||||||
|
;;; Two ls -l output readers
|
||||||
|
(field-reader (infix-splitter (rx (+ white)) 8))
|
||||||
|
(field-reader (infix-splitter (rx (+ white)) -7))
|
||||||
|
; -rw-r--r-- 1 shivers 22880 Sep 24 12:45 scsh.scm
|
||||||
|
|
||||||
|
;;; Internet hostname reader
|
||||||
|
(field-reader (field-splitter (rx (+ (~ ".")))))
|
||||||
|
; stat.sinica.edu.tw
|
||||||
|
|
||||||
|
;;; Internet IP address reader
|
||||||
|
(field-reader (field-splitter (rx (+ (~ "."))) 4))
|
||||||
|
; 18.24.0.241
|
||||||
|
|
||||||
|
;;; Line of integers
|
||||||
|
(let ((parser (field-splitter (rx (? ("+-")) (+ digit)))))
|
||||||
|
(field-reader (\l{s} (map string->number (parser s))))
|
||||||
|
; 18 24 0 241
|
||||||
|
|
||||||
|
;;; Same as above.
|
||||||
|
(let ((reader (field-reader (field-splitter (rx (? ("+-"))
|
||||||
|
(+ digit))))))
|
||||||
|
(\lx{maybe-port} (map string->number (apply reader maybe-port))))
|
||||||
|
; Yale beat harvard 26 to 7.\end{centercode}
|
||||||
|
\caption{Some examples of \protect\ex{field-reader}}
|
||||||
|
\label{fig:field-readers}
|
||||||
|
\end{boxedfigure}
|
||||||
|
|
||||||
|
\end{desc}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Forward-progress guarantees and empty-string matches}
|
||||||
|
A loop that pulls text off a string by repeatedly matching a regexp
|
||||||
|
against that string can conceivably get stuck in an infinite loop if
|
||||||
|
the regexp matches the empty string. For example, the SREs
|
||||||
|
\ex{bos}, \ex{eos}, \ex{(* any)}, and \ex{(| "foo" (* (~ "f")))}
|
||||||
|
can all match the empty string.
|
||||||
|
|
||||||
|
The routines in this package that iterate through strings with regular
|
||||||
|
expressions are careful to handle this empty-string case.
|
||||||
|
If a regexp matches the empty string, the next search starts, not from
|
||||||
|
the end of the match (which in the empty string case is also the
|
||||||
|
beginning---that's the problem), but from the next character over.
|
||||||
|
This is the correct behaviour. Regexps match the longest possible
|
||||||
|
string at a given location, so if the regexp matched the empty string
|
||||||
|
at location $i$, then it is guaranteed it could not have matched
|
||||||
|
a longer pattern starting with character $i$. So we can safely begin
|
||||||
|
our search for the next match at char $i+1$.
|
||||||
|
|
||||||
|
With this provision, every iteration through the loop makes some forward
|
||||||
|
progress, and the loop is guaranteed to terminate.
|
||||||
|
|
||||||
|
This has the effect you want with field parsing. For example, if you split
|
||||||
|
a string with the empty pattern, you will explode the string into its
|
||||||
|
individual characters:
|
||||||
|
\codex{((suffix-splitter (rx)) "foo") {\evalto} ("" "f" "o" "o")}
|
||||||
|
However, even though this boundary case is handled correctly, we don't
|
||||||
|
recommend using it. Say what you mean---just use a field splitter:
|
||||||
|
\codex{((field-splitter (rx any)) "foo") {\evalto} ("f" "o" "o")}
|
||||||
|
Or, more efficiently,
|
||||||
|
\codex{((\l{s} (map string (string->list s))) "foo")}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection{Reader limitations}
|
||||||
|
Since all of the readers in this package require the ability to peek
|
||||||
|
ahead one char in the input stream, they cannot be applied to raw
|
||||||
|
integer file descriptors, only Scheme input ports. This is because
|
||||||
|
Unix doesn't support peeking ahead into input streams.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Awk}
|
||||||
|
\label{sec:awk}
|
||||||
|
|
||||||
|
Scsh provides a loop macro and a set of field parsers that can
|
||||||
|
be used to perform text processing very similar to the Awk programming
|
||||||
|
language.
|
||||||
|
The basic functionality of Awk is factored in scsh into its component
|
||||||
|
parts.
|
||||||
|
The control structure is provided by the \ex{awk} loop macro;
|
||||||
|
the text I/O and parsers are provided by the field-reader subroutine library
|
||||||
|
(section~\ref{sec:field-reader}).
|
||||||
|
This factoring allows the programmer to compose the basic loop structure
|
||||||
|
with any parser or input mechanism at all.
|
||||||
|
If the parsers provided by the field-reader package are insufficient,
|
||||||
|
the programmer can write a custom parser in Scheme and use it with
|
||||||
|
equal ease in the awk framework.
|
||||||
|
|
||||||
|
Awk-in-scheme is given by a loop macro called \ex{awk}. It looks like
|
||||||
|
this:
|
||||||
|
\begin{code}\cdmath
|
||||||
|
(awk \synvar{next-record} \synvar{record\&field-vars}
|
||||||
|
{\rm[\synvar{counter}]} \synvar{state-var-decls}
|
||||||
|
\synvar{clause$_1$} \ldots)\index{awk}\end{code}
|
||||||
|
|
||||||
|
The body of the loop is a series of clauses, each one representing
|
||||||
|
a kind of condition/action pair. The loop repeatedly reads a record,
|
||||||
|
and then executes each clause whose condition is satisfied by the record.
|
||||||
|
|
||||||
|
Here's an example that reads lines from port \ex{p}
|
||||||
|
and prints the line number and line of every line containing the
|
||||||
|
string ``\ex{Church-Rosser}'':
|
||||||
|
\begin{code}
|
||||||
|
(awk (read-line) (ln) lineno ()
|
||||||
|
("Church-Rosser" (format #t "~d: ~s~%" lineno ln)))\end{code}
|
||||||
|
This example has just one clause in the loop body, the one that
|
||||||
|
tests for matches against the regular expression ``\ex{Church-Rosser}''.
|
||||||
|
|
||||||
|
The \synvar{next-record} form is an expression that is evaluated each time
|
||||||
|
through the loop to produce a record to process.
|
||||||
|
This expression can return multiple values;
|
||||||
|
these values are bound to the variables given in the
|
||||||
|
\synvar{record\&field-vars} list of variables.
|
||||||
|
The first value returned is assumed to be the record;
|
||||||
|
when it is the end-of-file object, the loop terminates.
|
||||||
|
|
||||||
|
For example, let's suppose we want to read items from \ex{/etc/password},
|
||||||
|
and we use the \ex{field-reader} procedure to define a record parser for
|
||||||
|
\ex{/etc/passwd} entries:
|
||||||
|
\codex{(define read-passwd (field-reader (infix-splitter ":" 7)))}
|
||||||
|
binds \ex{read-passwd} to a procedure that reads in a line of text when
|
||||||
|
it is called, and splits the text at colons. It returns two values:
|
||||||
|
the entire line read, and a seven-element list of the split-out fields.
|
||||||
|
(See section~\ref{sec:field-reader} for more on \ex{field-reader} and
|
||||||
|
\ex{infix-splitter}.)
|
||||||
|
|
||||||
|
So if the \synvar{next-record} form in an \ex{awk} expression is
|
||||||
|
\ex{(read-passwd)}, then \synvar{record\&field-vars} must be a list of
|
||||||
|
two variables, \eg,
|
||||||
|
\codex{(record field-vec)}
|
||||||
|
since \ex{read-passwd} returns two values.
|
||||||
|
|
||||||
|
Note that \ex{awk} allows us to use \emph{any} record reader we want in the
|
||||||
|
loop, returning whatever number of values we like. These values
|
||||||
|
don't have to be strings or string lists. The only requirement
|
||||||
|
is that the record reader return the eof object as its first value
|
||||||
|
when the loop should terminate.
|
||||||
|
|
||||||
|
The \ex{awk} loop allows the programmer to have loop variables. These are
|
||||||
|
declared and initialised by the \synvar{state-var-decls} form, a
|
||||||
|
\codex{((\var{var} \var{init-exp}) (\var{var} \var{init-exp}) \ldots)}
|
||||||
|
list rather like the \ex{let} form. Whenever a clause in the loop body
|
||||||
|
executes, it evaluates to as many values as there are state variables,
|
||||||
|
updating them.
|
||||||
|
|
||||||
|
The optional \synvar{counter} variable is an iteration counter.
|
||||||
|
It is bound to 0 when the loop starts.
|
||||||
|
The counter is incremented each time a non-eof record is read.
|
||||||
|
|
||||||
|
There are several kinds of loop clause. When evaluating the body of the
|
||||||
|
loop, \ex{awk} evaluates \emph{all} the clauses sequentially.
|
||||||
|
Unlike \ex{cond}, it does not stop after the first clause is satisfied;
|
||||||
|
it checks them all.
|
||||||
|
|
||||||
|
\begin{itemize}
|
||||||
|
|
||||||
|
\itum{\ex{(\var{test} \vari{body}1 \vari{body}2 \ldots)}}
|
||||||
|
If \var{test} is true, execute the body forms. The last body form
|
||||||
|
is the value of the clause. The test and body forms are evaluated
|
||||||
|
in the scope of the record and state variables.
|
||||||
|
|
||||||
|
The \var{test} form can be one of:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{lp{0.6\linewidth}}
|
||||||
|
\var{integer}: & The test is true for that iteration of the loop.
|
||||||
|
The first iteration is \#1. \\
|
||||||
|
|
||||||
|
\var{sre}: & A regular expression, in SRE notation
|
||||||
|
(see chapter~\ref{chapt:sre}) can be used as
|
||||||
|
a test. The test is successful if the pattern
|
||||||
|
matches the record.
|
||||||
|
In particular, note that any string is an SRE. \\
|
||||||
|
|
||||||
|
\ex{(when \var{expr})}: &
|
||||||
|
The body of a \ex{when} test is evaluated as a
|
||||||
|
Scheme boolean expression in the inner scope of the
|
||||||
|
\ex{awk} form. \\
|
||||||
|
|
||||||
|
\var{expr}: & If the form is none of the above, it is treated as
|
||||||
|
a Scheme expression---in practice, the \ex{when}
|
||||||
|
keyword is only needed in cases where SRE/Scheme
|
||||||
|
expression ambiguity might occur.
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
|
||||||
|
\itum{\begin{tabular}[t]{l}
|
||||||
|
\ex{(range\ \ \ \var{start-test} \var{stop-test} \vari{body}1 \ldots)} \\
|
||||||
|
\ex{(:range\ \ \var{start-test} \var{stop-test} \vari{body}1 \ldots)} \\
|
||||||
|
\ex{(range:\ \ \var{start-test} \var{stop-test} \vari{body}1 \ldots)} \\
|
||||||
|
\ex{(:range:\ \var{start-test} \var{stop-test} \vari{body}1 \ldots)}
|
||||||
|
\end{tabular}}
|
||||||
|
%
|
||||||
|
These clauses become activated when \var{start-test} is true;
|
||||||
|
they stay active on all further iterations until \var{stop-test}
|
||||||
|
is true.
|
||||||
|
|
||||||
|
So, to print out the first ten lines of a file, we use the clause:
|
||||||
|
\codex{(:range: 1 10 (display record))}
|
||||||
|
|
||||||
|
The colons control whether or not the start and stop lines
|
||||||
|
are processed by the clause. For example:
|
||||||
|
\begin{inset}\begin{tabular}{l@{\qquad}l}
|
||||||
|
\ex{(range\ \ \ 1 5\ \ \ldots)} & Lines \phantom{1} 2 3 4 \\
|
||||||
|
\ex{(:range\ \ 1 5\ \ \ldots)} & Lines 1 2 3 4 \\
|
||||||
|
\ex{(range:\ \ 1 5\ \ \ldots)} & Lines \phantom{1} 2 3 4 5 \\
|
||||||
|
\ex{(:range: 1 5\ \ \ldots)} & Lines 1 2 3 4 5
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
|
||||||
|
A line can trigger both tests, either simultaneously starting and
|
||||||
|
stopping an active region, or simultaneously stopping one and starting
|
||||||
|
a new one, so ranges can abut seamlessly.
|
||||||
|
|
||||||
|
\itum{\ex{(else \vari{body}1 \vari{body}2 \ldots)}}
|
||||||
|
If no other clause has executed since the top of the loop, or
|
||||||
|
since the last \ex{else} clause, this clause executes.
|
||||||
|
|
||||||
|
\itum{\ex{(\var{test} => \var{exp})}}
|
||||||
|
If evaluating \ex{test} produces a true value,
|
||||||
|
apply \var{exp} to that value.
|
||||||
|
If \var{test} is a regular expression, then \var{exp} is applied
|
||||||
|
to the match data structure returned by the regexp match routine.
|
||||||
|
|
||||||
|
\itum{\ex{(after \vari{body}1 \ldots)}}
|
||||||
|
This clause executes when the loop encounters EOF. The body forms
|
||||||
|
execute in the scope of the state vars and the record-count var,
|
||||||
|
if there are any. The value of the last body form is the value
|
||||||
|
of the entire awk form.
|
||||||
|
|
||||||
|
If there is no \ex{after} clause, \ex{awk} returns the loop's state
|
||||||
|
variables as multiple values.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{Examples}
|
||||||
|
Here are some examples of \ex{awk} being used to process various types
|
||||||
|
of input stream.
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
(define $ nth) ; Saves typing.
|
||||||
|
|
||||||
|
;;; Print out the name and home-directory of everyone in /etc/passwd:
|
||||||
|
(let ((read-passwd (field-reader (infix-splitter ":" 7))))
|
||||||
|
(call-with-input-file "/etc/passwd"
|
||||||
|
(lambda (port)
|
||||||
|
(awk (read-passwd port) (record fields) ()
|
||||||
|
(#t (format #t "~a's home directory is ~a~%"
|
||||||
|
($ fields 0)
|
||||||
|
($ fields 5)))))))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Print out the user-name and home-directory of everyone whose
|
||||||
|
;;; name begins with "S"
|
||||||
|
(let ((read-passwd (field-reader (infix-splitter ":" 7))))
|
||||||
|
(call-with-input-file "/etc/passwd"
|
||||||
|
(lambda (port)
|
||||||
|
(awk (read-passwd port) (record fields) ()
|
||||||
|
((: bos "S")
|
||||||
|
(format #t "~a's home directory is ~a~%"
|
||||||
|
($ fields 0)
|
||||||
|
($ fields 5)))))))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Read a series of integers from stdin. This expression evaluates
|
||||||
|
;;; to the number of positive numbers that were read. Note our
|
||||||
|
;;; "record-reader" is the standard Scheme READ procedure.
|
||||||
|
(awk (read) (i) ((npos 0))
|
||||||
|
((> i 0) (+ npos 1)))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Filter -- pass only lines containing my name.
|
||||||
|
(awk (read-line) (line) ()
|
||||||
|
("Olin" (display line) (newline)))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Count the number of non-comment lines of code in my Scheme source.
|
||||||
|
(awk (read-line) (line) ((nlines 0))
|
||||||
|
((: bos (* white) ";") nlines) ; A comment line.
|
||||||
|
(else (+ nlines 1))) ; Not a comment line.\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Read numbers, counting the evens and odds.
|
||||||
|
(awk (read) (val) ((evens 0) (odds 0))
|
||||||
|
((> val 0) (display "pos ") (values evens odds)) ; Tell me about
|
||||||
|
((< val 0) (display "neg ") (values evens odds)) ; sign, too.
|
||||||
|
(else (display "zero ") (values evens odds))
|
||||||
|
|
||||||
|
((even? val) (values (+ evens 1) odds))
|
||||||
|
(else (values evens (+ odds 1))))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Determine the max length of all the lines in the file.
|
||||||
|
(awk (read-line) (line) ((max-len 0))
|
||||||
|
(#t (max max-len (string-length line))))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; (This could also be done with PORT-FOLD:)
|
||||||
|
(port-fold (current-input-port) read-line
|
||||||
|
(lambda (line maxlen) (max (string-length line) maxlen))
|
||||||
|
0)\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Print every line longer than 80 chars.
|
||||||
|
;;; Prefix each line with its line #.
|
||||||
|
(awk (read-line) (line) lineno ()
|
||||||
|
((> (string-length line) 80)
|
||||||
|
(format #t "~d: ~s~%" lineno line)))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Strip blank lines from input.
|
||||||
|
(awk (read-line) (line) ()
|
||||||
|
((~ white) (display line) (newline)))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Sort the entries in /etc/passwd by login name.
|
||||||
|
(for-each (lambda (entry) (display (cdr entry)) (newline)) ; Out
|
||||||
|
(sort (lambda (x y) (string<? (car x) (car y))) ; Sort
|
||||||
|
(let ((read (field-reader (infix-splitter ":" 7)))) ; In
|
||||||
|
(awk (read) (line fields) ((ans '()))
|
||||||
|
(#t (cons (cons ($ fields 0) line) ans))))))\end{code}
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
;;; Prefix line numbers to the input stream.
|
||||||
|
(awk (read-line) (line) lineno ()
|
||||||
|
(#t (format #t "~d:\\t~a~%" lineno line)))\end{code}
|
||||||
|
|
||||||
|
|
||||||
|
\section{Backwards compatibility}
|
||||||
|
|
||||||
|
Previous scsh releases provided an \ex{awk} form with a different syntax,
|
||||||
|
designed around regular expressions written in Posix notation as strings,
|
||||||
|
rather than SREs.
|
||||||
|
|
||||||
|
This form is still available in a separate module for old code.
|
||||||
|
It'll be documented in the next release of this manual. Dig around
|
||||||
|
in the sources for it.
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
% boxedminipage.sty
|
||||||
|
%
|
||||||
|
% adds the boxedminipage environment---just like minipage, but has a
|
||||||
|
% box round it!
|
||||||
|
%
|
||||||
|
% The thickneess of the rules around the box is controlled by
|
||||||
|
% \fboxrule, and the distance between the rules and the edges of the
|
||||||
|
% inner box is governed by \fboxsep.
|
||||||
|
%
|
||||||
|
% This code is based on Lamport's minipage code.
|
||||||
|
|
||||||
|
\def\boxedminipage{\@ifnextchar [{\@iboxedminipage}{\@iboxedminipage[c]}}
|
||||||
|
|
||||||
|
\def\@iboxedminipage[#1]#2{\leavevmode \@pboxswfalse
|
||||||
|
\if #1b\vbox
|
||||||
|
\else \if #1t\vtop
|
||||||
|
\else \ifmmode \vcenter
|
||||||
|
\else \@pboxswtrue $\vcenter
|
||||||
|
\fi
|
||||||
|
\fi
|
||||||
|
\fi\bgroup % start of outermost vbox/vtop/vcenter
|
||||||
|
\hsize #2
|
||||||
|
\hrule\@height\fboxrule
|
||||||
|
\hbox\bgroup % inner hbox
|
||||||
|
\vrule\@width\fboxrule \hskip\fboxsep \vbox\bgroup % innermost vbox
|
||||||
|
\advance\hsize -2\fboxrule \advance\hsize-2\fboxsep
|
||||||
|
\textwidth\hsize \columnwidth\hsize
|
||||||
|
\@parboxrestore
|
||||||
|
\def\@mpfn{mpfootnote}\def\thempfn{\thempfootnote}\c@mpfootnote\z@
|
||||||
|
\let\@footnotetext\@mpfootnotetext
|
||||||
|
\let\@listdepth\@mplistdepth \@mplistdepth\z@
|
||||||
|
\@minipagerestore\@minipagetrue
|
||||||
|
\everypar{\global\@minipagefalse\everypar{}}}
|
||||||
|
|
||||||
|
\def\endboxedminipage{%
|
||||||
|
\par\vskip-\lastskip
|
||||||
|
\ifvoid\@mpfootins\else
|
||||||
|
\vskip\skip\@mpfootins\footnoterule\unvbox\@mpfootins\fi
|
||||||
|
\egroup % ends the innermost \vbox
|
||||||
|
\hskip\fboxsep \vrule\@width\fboxrule
|
||||||
|
\egroup % ends the \hbox
|
||||||
|
\hrule\@height\fboxrule
|
||||||
|
\egroup% ends the vbox/vtop/vcenter
|
||||||
|
\if@pboxsw $\fi}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,296 @@
|
||||||
|
% code.sty: -*- latex -*-
|
||||||
|
% Latex macros for a "weak" verbatim mode.
|
||||||
|
% -- like verbatim, except \, {, and } have their usual meanings.
|
||||||
|
|
||||||
|
% Environments: code, tightcode, codeaux, codebox, centercode
|
||||||
|
% Commands: \dcd, \cddollar, \cdmath, \cd, \codeallowbreaks, \codeskip, \^
|
||||||
|
% Already defined in LaTeX, but of some relevance: \#, \$, \%, \&, \_, \{, \}
|
||||||
|
|
||||||
|
% Changelog at the end of the file.
|
||||||
|
|
||||||
|
% These commands give you an environment, code, that is like verbatim
|
||||||
|
% except that you can still insert commands in the middle of the environment:
|
||||||
|
% \begin{code}
|
||||||
|
% for(x=1; x<loop_bound; x++)
|
||||||
|
% y += x^3; /* {\em Add in {\tt x} cubed} */
|
||||||
|
% \end{code}
|
||||||
|
%
|
||||||
|
% All characters are ordinary except \{}. To get \{} in your text,
|
||||||
|
% you use the commands \\, \{, and \}.
|
||||||
|
|
||||||
|
% These macros mess with the definition of the special chars (e.g., ^_~%).
|
||||||
|
% The characters \{} are left alone, so you can still have embedded commands:
|
||||||
|
% \begin{code} f(a,b,\ldots,y,z) \end{code}
|
||||||
|
% However, if your embedded commands use the formerly-special chars, as in
|
||||||
|
% \begin{code} x := x+1 /* \mbox{\em This is $y^3$} */ \end{code}
|
||||||
|
% then you lose. The $ and ^ chars are scanned in as non-specials,
|
||||||
|
% so they don't work. If the chars are scanned *outside* the code env,
|
||||||
|
% then you have no problem:
|
||||||
|
% \def\ycube{$y^3$}
|
||||||
|
% \begin{code} x := x+1 /* {\em This is \ycube} */ \end{code}
|
||||||
|
% If you must put special chars inside the code env, you do it by
|
||||||
|
% prefixing them with the special \dcd ("decode") command, that
|
||||||
|
% reverts the chars to back to special status:
|
||||||
|
% \begin{code} x := x+1 /* {\dcd\em This is $y^3$} */ \end{code}
|
||||||
|
% \dcd's scope is bounded by its enclosing braces. It is only defined within
|
||||||
|
% the code env. You can also turn on just $ with the \cddollar command;
|
||||||
|
% you can turn on just $^_ with the \cdmath command. See below.
|
||||||
|
%
|
||||||
|
% Alternatively, just use \(...\) for $...$, \sp for ^, and \sb for _.
|
||||||
|
|
||||||
|
% WARNING:
|
||||||
|
% Like \verb, you cannot put a \cd{...} inside an argument to a macro
|
||||||
|
% or a command. If you try, for example,
|
||||||
|
% \mbox{\cd{$x^y$}}
|
||||||
|
% you will lose. That is because the text "\cd{$x^y$}" gets read in
|
||||||
|
% as \mbox's argument before the \cd executes. But the \cd has to
|
||||||
|
% have a chance to run before LaTeX ever reads the $x^y$ so it can
|
||||||
|
% turn off the specialness of $ and ^. So, \cd has to appear at
|
||||||
|
% top level, not inside an argument. Similarly, you can't have
|
||||||
|
% a \cd or a \code inside a macro (Although you could use \gdef to
|
||||||
|
% define a macro *inside* a \cd, which you could then use outside.
|
||||||
|
% Don't worry about this if you don't understand it.)
|
||||||
|
|
||||||
|
% BUG: In the codebox env, the effect of a \dcd, \cddollar, or \cdmath
|
||||||
|
% command is reset at the end of each line. This can be hacked by
|
||||||
|
% messing with the \halign's preamble, if you feel up to it.
|
||||||
|
|
||||||
|
% Useage note: the initial newline after the \begin{code} or
|
||||||
|
% \begin{codebox} is eaten, but the last newline is not.
|
||||||
|
% So,
|
||||||
|
% \begin{code}
|
||||||
|
% foo
|
||||||
|
% bar
|
||||||
|
% \end{code}
|
||||||
|
% leaves one more blank line after bar than does
|
||||||
|
% \begin{code}
|
||||||
|
% foo
|
||||||
|
% bar\end{code}
|
||||||
|
% Moral: get in the habit of terminating code envs without a newline
|
||||||
|
% (as in the second example).
|
||||||
|
%
|
||||||
|
|
||||||
|
% All this stuff tweaks the meaning of space, tab, and newline.
|
||||||
|
%===============================================================================
|
||||||
|
% \cd@obeyspaces
|
||||||
|
% Turns all spaces into non-breakable spaces.
|
||||||
|
% Note: this is like \@vobeyspaces except without spurious space in defn.
|
||||||
|
% @xobeysp is basically a space; it's defined in latex.tex.
|
||||||
|
%
|
||||||
|
{\catcode`\ =\active\gdef\cd@obeyspaces{\catcode`\ =\active\let =\@xobeysp}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% \cd@obeytabs
|
||||||
|
% Turns all tabs into 8 non-breakable spaces (which is bogus).
|
||||||
|
%
|
||||||
|
{\catcode`\^^I=\active %
|
||||||
|
\gdef\cd@obeytabs{\catcode`\^^I=\active\let^^I=\cd@tab}}
|
||||||
|
|
||||||
|
\def\cd@tab{\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp\@xobeysp}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% \cd@obeylines
|
||||||
|
% Turns all cr's into linebreaks. Pagebreaks are not permitted between lines.
|
||||||
|
% This is copied from lplain.tex's \obeylines, with the cr def'n changed.
|
||||||
|
%
|
||||||
|
{\catcode`\^^M=\active % these lines must end with %
|
||||||
|
\gdef\cd@obeylines{\catcode`\^^M=\active\let^^M=\cd@cr}}
|
||||||
|
|
||||||
|
% What ^M turns into. This def'n keeps blank lines from being compressed out.
|
||||||
|
\def\cd@cr{\par\penalty10000\leavevmode} % TeX magicness
|
||||||
|
%\def\cd@cr{\par\penalty10000\mbox{}} % LaTeX
|
||||||
|
|
||||||
|
|
||||||
|
% \codeallowbreaks
|
||||||
|
% Same as \cd@obeylines, except pagebreaks are allowed.
|
||||||
|
% Put this command inside a code env to allow pagebreaks.
|
||||||
|
|
||||||
|
{\catcode`\^^M=\active % these lines must end with %
|
||||||
|
\gdef\codeallowbreaks{\catcode`\^^M\active\let^^M\cd@crbr}}
|
||||||
|
|
||||||
|
%\def\cd@crbr{\leavevmode\endgraf} % What ^M turns into.
|
||||||
|
\def\cd@crbr{\par\leavevmode} % What ^M turns into.
|
||||||
|
|
||||||
|
|
||||||
|
% \cd@obeycrsp
|
||||||
|
% Turns cr's into non-breakable spaces. Used by \cd.
|
||||||
|
|
||||||
|
{\catcode`\^^M=\active % these lines must end with %
|
||||||
|
\gdef\cd@obeycrsp{\catcode`\^^M=\active\let^^M=\@xobeysp}}
|
||||||
|
|
||||||
|
% =============================================================================
|
||||||
|
|
||||||
|
% Set up code environment, in which most of the common special characters
|
||||||
|
% appearing in code are treated verbatim, namely: $&#^_~%
|
||||||
|
% \ { } are still enabled so that macros can be called in this
|
||||||
|
% environment. Use \\, \{, and \} to use these characters verbatim
|
||||||
|
% in this environment.
|
||||||
|
%
|
||||||
|
% Inside a group, you can make
|
||||||
|
% all the hacked chars special with the \dcd command
|
||||||
|
% $ special with the \cddollar command
|
||||||
|
% $^_ special with the \cdmath command.
|
||||||
|
% If you have a bunch of math $..$'s in your code env, then a global \cddollar
|
||||||
|
% or \cdmath at the beginning of the env can save a lot of trouble.
|
||||||
|
% When chars are special (e.g., after a \dcd), you can still get #$%&_{} with
|
||||||
|
% \#, \$, \%, \&, \_, \{, and \} -- this is standard LaTeX.
|
||||||
|
% Additionally, \\ gives \ inside the code env, and when \cdmath
|
||||||
|
% makes ^ special, it also defines \^ to give ^.
|
||||||
|
|
||||||
|
%The hacked characters can be made special again
|
||||||
|
% within a group by using the \dcd command.
|
||||||
|
|
||||||
|
% Note: this environment allows no breaking of lines whatsoever; not
|
||||||
|
% at spaces or hypens. To arrange for a break use the standard \- command,
|
||||||
|
% or a \discretionary{}{}{} which breaks, but inserts nothing. This is useful,
|
||||||
|
% for example for allowing hypenated identifiers to be broken, e.g.
|
||||||
|
% \def\={\discretionary{}{}{}} %optional break
|
||||||
|
% FOO-\=BAR.
|
||||||
|
|
||||||
|
\def\setupcode{\parsep=0pt\parindent=0pt%
|
||||||
|
\normalfont\ttfamily\frenchspacing\catcode``=13\@noligs%
|
||||||
|
\def\\{\char`\\}%
|
||||||
|
\let\dcd=\cd@dcd\let\cddollar=\cd@dollarspecial\let\cdmath=\cd@mathspecial%
|
||||||
|
\@makeother\$\@makeother\&\@makeother\#%
|
||||||
|
\@makeother\^\@makeother\_\@makeother\~%
|
||||||
|
\@makeother\%\cd@obeytabs\cd@obeyspaces}
|
||||||
|
% other: $&#^_~%
|
||||||
|
% left special: \{}
|
||||||
|
% unnecessary: @`'"
|
||||||
|
|
||||||
|
|
||||||
|
%% codebox, centercode
|
||||||
|
%%=============================================================================
|
||||||
|
%% The codebox env makes a box exactly as wide as it needs to be
|
||||||
|
%% (i.e., as wide as the longest line of code is). This is useful
|
||||||
|
%% if you want to center a chunk of code, or flush it right, or
|
||||||
|
%% something like that. The optional argument to the environment,
|
||||||
|
%% [t], [c], or [b], specifies how to vertically align the codebox,
|
||||||
|
%% just as with arrays or other boxes. Default is [c].
|
||||||
|
|
||||||
|
%% Must be a newline immediately after "\begin{codebox}[t]"!
|
||||||
|
|
||||||
|
{\catcode`\^^M=\active % these lines must end with %
|
||||||
|
\gdef\cd@obeycr{\catcode`\^^M=\active\let^^M=\cr}}
|
||||||
|
|
||||||
|
% If there is a [<letter>] option, then the following newline will
|
||||||
|
% be read *after* ^M is bound to \cr, so we're cool. If there isn't
|
||||||
|
% an option given (i.e., default to [c]), then the @\ifnextchar will
|
||||||
|
% gobble up the newline as it gobbles whitespace. So we insert the
|
||||||
|
% \cr explicitly. Isn't TeX fun?
|
||||||
|
\def\codebox{\leavevmode\@ifnextchar[{\@codebox}{\@codebox[c]\cr}} %]
|
||||||
|
|
||||||
|
\def\@codebox[#1]%
|
||||||
|
{\hbox\bgroup$\if #1t\vtop \else \if#1b\vbox \else \vcenter \fi\fi\bgroup%
|
||||||
|
\tabskip\z@\setupcode\cd@obeycr% just before cd@obey
|
||||||
|
\halign\bgroup##\hfil\span}
|
||||||
|
|
||||||
|
\def\endcodebox{\crcr\egroup\egroup\m@th$\egroup}
|
||||||
|
|
||||||
|
% Center the box on the page:
|
||||||
|
\newenvironment{centercode}%
|
||||||
|
{\begin{center}\begin{codebox}[c]}%
|
||||||
|
{\end{codebox}\end{center}}
|
||||||
|
|
||||||
|
|
||||||
|
%% code, codeaux, tightcode
|
||||||
|
%%=============================================================================
|
||||||
|
%% Code environment as described above. Lines are kept on one page.
|
||||||
|
%% This actually works by setting a huge penalty for breaking
|
||||||
|
%% between lines of code. Code is indented same as other displayed paras.
|
||||||
|
%% Note: to increase left margin, use \begin{codeaux}{\leftmargin=1in}.
|
||||||
|
|
||||||
|
% To allow pagebreaks, say \codeallowbreaks immediately inside the env.
|
||||||
|
% You can allow breaks at specific lines with a \pagebreak form.
|
||||||
|
|
||||||
|
%% N.B.: The \global\@ignoretrue command must be performed just inside
|
||||||
|
%% the *last* \end{...} before the following text. If not, you will
|
||||||
|
%% get an extra space on the following line. Blech.
|
||||||
|
|
||||||
|
%% This environment takes two arguments.
|
||||||
|
%% The second, required argument is the \list parameters to override the
|
||||||
|
%% \@listi... defaults.
|
||||||
|
%% - Usefully set by clients: \topsep \leftmargin
|
||||||
|
%% - Possible, but less useful: \partopsep
|
||||||
|
%% The first, optional argument is the extra \parskip glue that you get around
|
||||||
|
%% \list environments. It defaults to the value of \parskip.
|
||||||
|
\def\codeaux{\@ifnextchar[{\@codeaux}{\@codeaux[\parskip]}} %]
|
||||||
|
\def\@codeaux[#1]#2{%
|
||||||
|
\bgroup\parskip#1%
|
||||||
|
\begin{list}{}%
|
||||||
|
{\parsep\z@\rightskip\z@\listparindent\z@\itemindent\z@#2}%
|
||||||
|
\item[]\setupcode\cd@obeylines}%
|
||||||
|
\def\endcodeaux{\end{list}\leavevmode\egroup\ignorespaces\global\@ignoretrue}
|
||||||
|
|
||||||
|
%% Code env is codeaux with the default margin and spacing \list params:
|
||||||
|
\def\code{\codeaux{}} \let\endcode=\endcodeaux
|
||||||
|
|
||||||
|
%% Like code, but with no extra vertical space above and below.
|
||||||
|
\def\tightcode{\codeaux[=0pt]{\topsep\z@}}%
|
||||||
|
\let\endtightcode\endcodeaux
|
||||||
|
% {\vspace{-1\parskip}\begin{codeaux}{\partopsep\z@\topsep\z@}}%
|
||||||
|
% {\end{codeaux}\vspace{-1\parskip}}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
% Reasonable separation between lines of code
|
||||||
|
\newcommand{\codeskip}{\penalty0\vspace{2ex}}
|
||||||
|
|
||||||
|
|
||||||
|
% \cd is used to build a code environment in the middle of text.
|
||||||
|
% Note: only difference from display code is that cr's are taken
|
||||||
|
% as unbreakable spaces instead of linebreaks.
|
||||||
|
|
||||||
|
\def\cd{\leavevmode\begingroup\ifmmode\let\startcode=\startmcode\else%
|
||||||
|
\let\startcode\starttcode\fi%
|
||||||
|
\setupcode\cd@obeycrsp\startcode}
|
||||||
|
|
||||||
|
\def\starttcode#1{#1\endgroup}
|
||||||
|
\def\startmcode#1{\hbox{#1}\endgroup}
|
||||||
|
|
||||||
|
|
||||||
|
% Restore $&#^_~% to their normal catcodes
|
||||||
|
% Define \^ to give the ^ char.
|
||||||
|
% \dcd points to this guy inside a code env.
|
||||||
|
\def\cd@dcd{\catcode`\$=3\catcode`\&=4\catcode`\#=6\catcode`\^=7%
|
||||||
|
\catcode`\_=8\catcode`\~=13\catcode`\%=14\def\^{\char`\^}}
|
||||||
|
|
||||||
|
% Selectively enable $, and $^_ as special.
|
||||||
|
% \cd@mathspecial also defines \^ give the ^ char.
|
||||||
|
% \cddollar and \cdmath point to these guys inside a code env.
|
||||||
|
\def\cd@dollarspecial{\catcode`\$=3}
|
||||||
|
\def\cd@mathspecial{\catcode`\$=3\catcode`\^=7\catcode`\_=8%
|
||||||
|
\def\^{\char`\^}}
|
||||||
|
|
||||||
|
|
||||||
|
% Change log:
|
||||||
|
% Started off as some macros found in C. Rich's library.
|
||||||
|
% Olin 1/90:
|
||||||
|
% Removed \makeatletter, \makeatother's -- they shouldn't be there,
|
||||||
|
% because style option files are read with makeatletter. The terminal
|
||||||
|
% makeatother screwed things up for the following style options.
|
||||||
|
% Olin 3/91:
|
||||||
|
% Rewritten.
|
||||||
|
% - Changed things so blank lines don't get compressed out (the \leavevmove
|
||||||
|
% in \cd@cr and \cd@crwb).
|
||||||
|
% - Changed names to somewhat less horrible choices.
|
||||||
|
% - Added lots of doc, so casual hackers can more easily mess with all this.
|
||||||
|
% - Removed `'"@ from the set of hacked chars, since they are already
|
||||||
|
% non-special.
|
||||||
|
% - Removed the bigcode env, which effect can be had with the \codeallowbreaks
|
||||||
|
% command.
|
||||||
|
% - Removed the \@noligs command, since it's already defined in latex.tex.
|
||||||
|
% - Win big with the new \dcd, \cddollar, and \cdmath commands.
|
||||||
|
% - Now, *only* the chars \{} are special inside the code env. If you need
|
||||||
|
% more, use the \dcd command inside a group.
|
||||||
|
% - \cd now works inside math mode. (But if you use it in a superscript,
|
||||||
|
% it still comes out full size. You must explicitly put a \scriptsize\tt
|
||||||
|
% inside the \cd: $x^{\cd{\scriptsize\tt...}}$. A \leavevmode was added
|
||||||
|
% so that if you begin a paragraph with a \cd{...}, TeX realises you
|
||||||
|
% are starting a paragraph.
|
||||||
|
% - Added the codebox env. Tricky bit involving the first line hacked
|
||||||
|
% with help from David Long.
|
||||||
|
% Olin 8/94
|
||||||
|
% Changed the font commands for LaTeX2e.
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
% css.t2p
|
||||||
|
% Dorai Sitaram
|
||||||
|
% 19 Jan 2001
|
||||||
|
% A basic style for HTML documents generated
|
||||||
|
% with tex2page.
|
||||||
|
|
||||||
|
\ifx\shipout\UNDEFINED
|
||||||
|
\cssblock
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: black;
|
||||||
|
/* background-color: #e5e5e5;*/
|
||||||
|
background-color: #ffffff;
|
||||||
|
/*background-color: beige;*/
|
||||||
|
margin-top: 2em;
|
||||||
|
margin-left: 8%;
|
||||||
|
margin-right: 8%;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1,h2,h3,h4,h5,h6 {
|
||||||
|
margin-top: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partheading {
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chapterheading {
|
||||||
|
font-size: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
margin-left: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol {
|
||||||
|
list-style-type: decimal;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol {
|
||||||
|
list-style-type: lower-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol ol {
|
||||||
|
list-style-type: lower-roman;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol ol ol ol {
|
||||||
|
list-style-type: upper-alpha;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme {
|
||||||
|
color: brown;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme .keyword {
|
||||||
|
color: #990000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme .builtin {
|
||||||
|
color: #990000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme .variable {
|
||||||
|
color: navy;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme .global {
|
||||||
|
color: purple;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme .selfeval {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheme .comment {
|
||||||
|
color: teal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.schemeresponse {
|
||||||
|
color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation {
|
||||||
|
color: red;
|
||||||
|
text-align: right;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disable {
|
||||||
|
/* color: #e5e5e5; */
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallcaps {
|
||||||
|
font-size: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallprint {
|
||||||
|
color: gray;
|
||||||
|
font-size: 75%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallprint hr {
|
||||||
|
text-align: left;
|
||||||
|
width: 40%;
|
||||||
|
}
|
||||||
|
|
||||||
|
\endcssblock
|
||||||
|
\fi
|
||||||
|
|
||||||
|
% ex:ft=css
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
% Loads cmtt fonts in on \tt. -*- latex -*-
|
||||||
|
% I prefer these to the Courier fonts that latex gives you w/postscript styles.
|
||||||
|
% Courier is too spidery and too wide -- it's hard to get 80 chars on a line.
|
||||||
|
% -Olin
|
||||||
|
|
||||||
|
\renewcommand{\ttdefault}{cmtt}
|
||||||
|
|
@ -0,0 +1,278 @@
|
||||||
|
\makeatletter
|
||||||
|
\def\ie{\mbox{\emph{i.e.}}} % \mbox keeps the last period from
|
||||||
|
\def\Ie{\mbox{\emph{I.e.}}} % looking like an end-of-sentence.
|
||||||
|
\def\eg{\mbox{\emph{e.g.}}}
|
||||||
|
\def\Eg{\mbox{\emph{E.g.}}}
|
||||||
|
\def\etc{{\em etc.}}
|
||||||
|
|
||||||
|
\def\Lisp{\textsc{Lisp}}
|
||||||
|
\def\CommonLisp{\textsc{Common Lisp}}
|
||||||
|
\def\Ascii{\textsc{Ascii}}
|
||||||
|
\def\Ansi{\textsc{Ansi}}
|
||||||
|
\def\Unix{{Unix}} % Not smallcaps, according to Bart.
|
||||||
|
\def\Scheme{{Scheme}}
|
||||||
|
\def\scm{{Scheme 48}}
|
||||||
|
\def\RnRS{R5RS}
|
||||||
|
\def\Posix{\textsc{Posix}}
|
||||||
|
|
||||||
|
\def\sharpf{\textnormal{\texttt{\#f}}}
|
||||||
|
\def\sharpt{\textnormal{\texttt{\#t}}}
|
||||||
|
\newcommand{\synteq}{\textnormal{::=}}
|
||||||
|
|
||||||
|
\def\maketildeother{\catcode`\~=12}
|
||||||
|
\def\maketildeactive{\catcode`\~=13}
|
||||||
|
\def\~{\char`\~}
|
||||||
|
|
||||||
|
\newcommand{\evalsto}{\ensuremath{\Rightarrow}}
|
||||||
|
|
||||||
|
% One-line code examples
|
||||||
|
%\newcommand{\codex}[1]% One line, centred. Tight spacing.
|
||||||
|
% {$$\abovedisplayskip=.75ex plus 1ex minus .5ex%
|
||||||
|
% \belowdisplayskip=\abovedisplayskip%
|
||||||
|
% \abovedisplayshortskip=0ex plus .5ex%
|
||||||
|
% \belowdisplayshortskip=\abovedisplayshortskip%
|
||||||
|
% \hbox{\ttt #1}$$}
|
||||||
|
%\newcommand{\codex}[1]{\begin{tightinset}\ex{#1}\end{tightinset}\ignorespaces}
|
||||||
|
\newcommand{\codex}[1]{\begin{leftinset}\ex{#1}\end{leftinset}\ignorespaces}
|
||||||
|
|
||||||
|
\def\widecode{\codeaux{\leftmargin=0pt\topsep=0pt}}
|
||||||
|
\def\endwidecode{\endcodeaux}
|
||||||
|
|
||||||
|
% For multiletter vars in math mode:
|
||||||
|
\newcommand{\var}[1]{\mbox{\frenchspacing\it{#1}}}
|
||||||
|
\newcommand{\vari}[2]{\ensuremath{\mbox{\it{#1}}_{#2}}}
|
||||||
|
|
||||||
|
%% What you frequently want when you say \tt:
|
||||||
|
\def\ttchars{\catcode``=13\@noligs\frenchspacing}
|
||||||
|
\def\ttt{\normalfont\ttfamily\ttchars}
|
||||||
|
|
||||||
|
% Works in math mode; all special chars remain special; cheaper than \cd.
|
||||||
|
% Will not be correct size in super and subscripts, though.
|
||||||
|
\newcommand{\ex}[1]{{\normalfont\texttt{\ttchars #1}}}
|
||||||
|
|
||||||
|
\newenvironment{inset}
|
||||||
|
{\bgroup\parskip=1ex plus 1ex\begin{list}{}%
|
||||||
|
{\topsep=0pt\rightmargin\leftmargin}%
|
||||||
|
\item[]}%
|
||||||
|
{\end{list}\leavevmode\egroup\global\@ignoretrue}
|
||||||
|
|
||||||
|
\newenvironment{leftinset}
|
||||||
|
{\bgroup\parskip=1ex plus 1ex\begin{list}{}%
|
||||||
|
{\topsep=0pt}%
|
||||||
|
\item[]}%
|
||||||
|
{\end{list}\leavevmode\egroup\global\@ignoretrue}
|
||||||
|
|
||||||
|
\newenvironment{tightinset}
|
||||||
|
{\bgroup\parskip=0pt\begin{list}{}%
|
||||||
|
{\topsep=0pt\rightmargin\leftmargin}%
|
||||||
|
\item[]}%
|
||||||
|
{\end{list}\leavevmode\egroup\global\@ignoretrue}
|
||||||
|
|
||||||
|
\newenvironment{tightleftinset}
|
||||||
|
{\bgroup\parskip=0pt\begin{list}{}%
|
||||||
|
{\topsep=0pt}%
|
||||||
|
\item[]}%
|
||||||
|
{\end{list}\leavevmode\egroup\global\@ignoretrue}
|
||||||
|
|
||||||
|
\long\def\remark#1{\bgroup\small\begin{quote}\textsl{Remark: } #1\end{quote}\egroup}
|
||||||
|
\newenvironment{remarkenv}{\bgroup\small\begin{quote}\textsl{Remark: }}%
|
||||||
|
{\end{quote}\egroup}
|
||||||
|
\newcommand{\oops}[1]{\bgroup\small\begin{quote}\textsl{Oops: } #1\end{quote}\egroup}
|
||||||
|
|
||||||
|
\newcommand{\note}[1]{\{Note #1\}}
|
||||||
|
|
||||||
|
\newcommand{\itum}[1]{\item{\bf #1}\\*}
|
||||||
|
|
||||||
|
% For use in code. The \llap magicness makes the lambda exactly as wide as
|
||||||
|
% the other chars in \tt; the \hskip shifts it right a bit so it doesn't
|
||||||
|
% crowd the left paren -- which is necessary if \tt is cmtt.
|
||||||
|
% Note that (\l{x y} (+ x y)) uses the same number of columns in TeX form
|
||||||
|
% as it produces when typeset. This makes it easy to line up the columns
|
||||||
|
% in your input. \l is bound to some useless command in LaTeX, so we have to
|
||||||
|
% define it w/renewcommand.
|
||||||
|
\let\oldl\l %Save the old \l on \oldl
|
||||||
|
\renewcommand{\l}[1]{\ \llap{$\lambda$\hskip-.05em}\ (#1)}
|
||||||
|
|
||||||
|
% This one is for the rare (lambda x ...) case -- it doesn't have the
|
||||||
|
% column-invariant property. Oh, well.
|
||||||
|
\newcommand{\lx}[1]{\ \llap{$\lambda$\hskip-.05em}\ {#1}}
|
||||||
|
|
||||||
|
% For subcaptions
|
||||||
|
\newcommand{\subcaption}[1]
|
||||||
|
{\unskip\vspace{-2mm}\begin{center}\unskip\em#1\end{center}}
|
||||||
|
|
||||||
|
%%% T release notes stuff
|
||||||
|
\newlength{\notewidth}
|
||||||
|
\setlength{\notewidth}{\textwidth}
|
||||||
|
\addtolength{\notewidth}{-1.25in}
|
||||||
|
|
||||||
|
%\newcommand{\remark} [1]
|
||||||
|
% {\par\vspace{\parskip}
|
||||||
|
% \parbox[t]{.75in}{\sc Remark:}
|
||||||
|
% \parbox[t]{\notewidth}{\em #1}
|
||||||
|
% \vspace{\parskip}
|
||||||
|
% }
|
||||||
|
|
||||||
|
\newenvironment{optiontable}%
|
||||||
|
{\begin{tightinset}\renewcommand{\arraystretch}{1.5}%
|
||||||
|
\begin{tabular}{@{}>{\ttt}ll@{}}}%
|
||||||
|
{\end{tabular}\end{tightinset}}%
|
||||||
|
|
||||||
|
\newenvironment{desctable}[1]%
|
||||||
|
{\begin{inset}\renewcommand{\arraystretch}{1.5}%
|
||||||
|
\begin{tabular}{lp{#1}}}%
|
||||||
|
{\end{tabular}\end{inset}}
|
||||||
|
|
||||||
|
\def\*{{\ttt *}}
|
||||||
|
|
||||||
|
% Names of things
|
||||||
|
|
||||||
|
\newcommand{\keyword} [1]{\index{#1}{\normalfont\textsf{#1}}}
|
||||||
|
|
||||||
|
% \ex{#1} and also generates an index entry.
|
||||||
|
\newcommand{\exi}[1]{\index{#1@\texttt{#1}}\ex{#1}}
|
||||||
|
\newcommand{\indextt}[1]{\index{#1@\texttt{#1}}}
|
||||||
|
|
||||||
|
|
||||||
|
\newcommand{\evalto}{$\Longrightarrow$\ }
|
||||||
|
\renewcommand{\star}{$^*$\/}
|
||||||
|
\newcommand{\+}{$^+$}
|
||||||
|
|
||||||
|
% Semantic domains, used to indicate the type of a value
|
||||||
|
|
||||||
|
\newcommand{\sem}{\normalfont\itshape} %semantic font
|
||||||
|
\newcommand{\semvar}[1]{\textit{#1}} %semantic font
|
||||||
|
\newcommand{\synvar}[1]{\textrm{\textit{$\left<\right.$#1$\left.\right>$}}} %syntactic font
|
||||||
|
\newcommand{\type}{\sem}
|
||||||
|
\newcommand{\zeroormore}[1]{{\sem #1$_1$ \ldots #1$_n$}}
|
||||||
|
\newcommand{\oneormore}[1]{{\sem #1$_1$ #1$_2$ \ldots #1$_n$}}
|
||||||
|
|
||||||
|
\newcommand{\proc} {{\sem procedure}}
|
||||||
|
\newcommand{\boolean} {{\sem boolean}}
|
||||||
|
\newcommand{\true} {{\sem true}}
|
||||||
|
\newcommand{\false} {{\sem false}}
|
||||||
|
|
||||||
|
\newcommand{\num} {{\sem number}}
|
||||||
|
\newcommand{\fixnum} {{\sem fixnum}}
|
||||||
|
\newcommand{\integer} {{\sem integer}}
|
||||||
|
\newcommand{\real} {{\sem real}}
|
||||||
|
|
||||||
|
\newcommand{\character} {{\sem character}}
|
||||||
|
\newcommand{\str} {{\sem string}}
|
||||||
|
\newcommand{\sym} {{\sem symbol}}
|
||||||
|
|
||||||
|
\newcommand{\location} {{\sem location}}
|
||||||
|
\newcommand{\object} {{\sem object}}
|
||||||
|
|
||||||
|
\newcommand{\error} {{\sem error}}
|
||||||
|
\newcommand{\syntaxerror} {{\sem syntax error}}
|
||||||
|
\newcommand{\readerror} {{\sem read error}}
|
||||||
|
\newcommand{\undefined} {{\sem undefined}}
|
||||||
|
\newcommand{\noreturn} {{\sem no return value}}
|
||||||
|
|
||||||
|
\newcommand{\port} {{\sem port}}
|
||||||
|
|
||||||
|
% semantic variables
|
||||||
|
|
||||||
|
\newcommand{\identifier} {{\sem identifier}}
|
||||||
|
\newcommand{\identifiers} {\zeroormore{\<ident>}}
|
||||||
|
\newcommand{\expr} {{\sem expression}}
|
||||||
|
\newcommand{\body} {{\sem body}}
|
||||||
|
\newcommand{\valueofbody} {{\sem value~of~body}}
|
||||||
|
\newcommand{\emptylist} {{\sem empty~list}}
|
||||||
|
\newcommand{\car} {\keyword{car}}
|
||||||
|
\newcommand{\cdr} {\keyword{cdr}}
|
||||||
|
\newcommand{\TMPDIR}{\texttt{\$TMPDIR}}
|
||||||
|
|
||||||
|
% generally useful things
|
||||||
|
|
||||||
|
% For line-breaking \tt stuff.
|
||||||
|
\renewcommand{\=}{\discretionary{-}{}{-}}
|
||||||
|
\newcommand{\ob}{\discretionary{}{}{}} % Optional break.
|
||||||
|
|
||||||
|
\newcommand{\indx}[1]{#1 \index{ #1 }}
|
||||||
|
%\newcommand{\gloss}[1]{#1 \glossary{ #1 }}
|
||||||
|
|
||||||
|
% This lossage produces #2 if #1 is zero length, otw #3.
|
||||||
|
% We use it to conditionally add a space between the procedure and
|
||||||
|
% the args in procedure prototypes, but only if there are any args--
|
||||||
|
% we want to produce "(read)", not "(read )".
|
||||||
|
\newlength{\voidlen}
|
||||||
|
\newcommand{\testvoid}[3]{\settowidth\voidlen{#1}\ifdim\voidlen>0in{#3}\else{#2}\fi}
|
||||||
|
|
||||||
|
|
||||||
|
% Typeset a definition prototype line, e.g.:
|
||||||
|
% (cons <arg1> <arg2>) -> pair procedure
|
||||||
|
%
|
||||||
|
% Five args are: proc-name args ret-value(s) type index-entry
|
||||||
|
\newcommand{\dfnix}[5]
|
||||||
|
{\hbox to \linewidth{\ttchars%
|
||||||
|
{\ttt(#1\testvoid{#2}{}{\ }{\sem{#2}}\testvoid{#2}{}{\/})\hskip 1em minus
|
||||||
|
0.5em$\longrightarrow$\hskip 1em minus 0.5em{\sem{#3}}\hfill\quad\textnormal{#4}}}\index{#5}}
|
||||||
|
|
||||||
|
\newcommand{\dfnx}[4] {\dfnix{#1}{#2}{#3}{#4}{#1@\texttt{#1}}}
|
||||||
|
|
||||||
|
\newcommand{\dfn} {\par\medskip\dfnx} % Takes 4 args, actually.
|
||||||
|
\newcommand{\dfni} {\par\medskip\dfnix} % Takes 5 args, actually.
|
||||||
|
|
||||||
|
\newcommand{\defvar} {\par\medskip\defvarx} % Takes 4 args, actually.
|
||||||
|
\newcommand{\defvarx}[2]%
|
||||||
|
{\index{#1}
|
||||||
|
\hbox to \linewidth{\ttchars{{\ttt{#1}} \hfill #2}}}%
|
||||||
|
|
||||||
|
% Typeset the protocol line, then do the following descriptive text indented.
|
||||||
|
% If you want to group two procs together, do the first one with a \dfn,
|
||||||
|
% then the second one, and the documentation, with a \defndescx.
|
||||||
|
|
||||||
|
% This one doesn't put whitespace above. Use it immediately after a \dfn
|
||||||
|
% to group two prototype lines together.
|
||||||
|
\newenvironment{dfndescx}[4]%
|
||||||
|
{\dfnx{#1}{#2}{#3}{#4}\begin{desc}}{\end{desc}}
|
||||||
|
|
||||||
|
\newenvironment{dfndesc}[4] % This one puts whitespace above.
|
||||||
|
{\par\medskip\begin{dfndescx}{#1}{#2}{#3}{#4}}
|
||||||
|
{\end{dfndescx}}
|
||||||
|
|
||||||
|
\newenvironment{desc}%
|
||||||
|
{\nopagebreak[2]%
|
||||||
|
\smallskip
|
||||||
|
\bgroup\begin{list}{}{\topsep=0pt\parskip=0pt}\item[]}
|
||||||
|
{\end{list}\leavevmode\egroup\global\@ignoretrue}
|
||||||
|
|
||||||
|
\def\defun#1#2#3{\dfn{#1}{#2}{#3}{procedure}} % preskip
|
||||||
|
\newcommand{\defunx}[3]{\dfnx{#1}{#2}{#3}{procedure}} % no skip
|
||||||
|
|
||||||
|
\newenvironment{defundescx}[3]%
|
||||||
|
{\begin{dfndescx}{#1}{#2}{#3}{procedure}}
|
||||||
|
{\end{dfndescx}}
|
||||||
|
|
||||||
|
\newenvironment{defundesc}[3]%
|
||||||
|
{\begin{dfndesc}{#1}{#2}{#3}{procedure}}
|
||||||
|
{\end{dfndesc}}
|
||||||
|
|
||||||
|
|
||||||
|
\newenvironment{column}{\begin{tabular}[t]{@{}l@{}}}{\end{tabular}}
|
||||||
|
|
||||||
|
\newenvironment{exampletable}%
|
||||||
|
{\begin{leftinset}%
|
||||||
|
\newcommand{\header}[1]{\multicolumn{2}{@{}l@{}}{##1}\\}%
|
||||||
|
\newcommand{\splitline}[2]%
|
||||||
|
{\multicolumn{2}{@{}l@{}}{##1}\\\multicolumn{2}{@{}l@{}}{\qquad\evalto\quad{##2}}}
|
||||||
|
\begin{tabular}{@{}l@{\quad\evalto\quad}l@{}}}%
|
||||||
|
{\end{tabular}\end{leftinset}}
|
||||||
|
|
||||||
|
% Put on blank lines in a code env to allow a pagebreak.
|
||||||
|
\newcommand{\cb}{\pagebreak[0]}
|
||||||
|
|
||||||
|
\newenvironment{boxedcode}
|
||||||
|
{\begin{inset}\tabular{|l|}\hline}
|
||||||
|
{\\ \hline \end{tabular}\end{inset}}
|
||||||
|
|
||||||
|
% A ragged-right decl that doesn't redefine \\ -- for use in tables.
|
||||||
|
\newcommand{\raggedrightparbox}{\let\temp=\\\raggedright\let\\=\temp}
|
||||||
|
|
||||||
|
\newenvironment{boxedfigure}[1]%
|
||||||
|
{\begin{figure}[#1]\begin{boxedminipage}{\linewidth}\vskip 1.5ex}
|
||||||
|
{\end{boxedminipage}\end{figure}}
|
||||||
|
|
||||||
|
\makeatother
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
% Document style option "draftfooter"
|
||||||
|
% -- usage: \documentstyle[...,draftfooter,...]{...}
|
||||||
|
% -- puts "DRAFT" with date and time in page footer
|
||||||
|
%
|
||||||
|
% Olin Shivers 1/17/94
|
||||||
|
% - Hacked from code I used in my dissertation and from code in a
|
||||||
|
% drafthead.sty package written by Stephen Page sdpage@uk.ac.oxford.prg.
|
||||||
|
%----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
%
|
||||||
|
% compute the time in hours and minutes; make new variables \timehh and \timemm
|
||||||
|
%
|
||||||
|
\newcount\timehh\newcount\timemm
|
||||||
|
\timehh=\time
|
||||||
|
\divide\timehh by 60 \timemm=\time
|
||||||
|
\count255=\timehh\multiply\count255 by -60 \advance\timemm by \count255
|
||||||
|
%
|
||||||
|
|
||||||
|
\def\draftbox{{\protect\small\bf \fbox{DRAFT}}}
|
||||||
|
\def\drafttime{%
|
||||||
|
{\protect\small\sl\today\ -- \ifnum\timehh<10 0\fi%
|
||||||
|
\number\timehh\,:\,\ifnum\timemm<10 0\fi\number\timemm}}
|
||||||
|
\def\drafttimer{\protect\makebox[0pt][r]{\drafttime}}
|
||||||
|
\def\drafttimel{\protect\makebox[0pt][l]{\drafttime}}
|
||||||
|
|
||||||
|
\def\thepagel{\protect\makebox[0pt][l]{\rm\thepage}}
|
||||||
|
\def\thepager{\protect\makebox[0pt][r]{\rm\thepage}}
|
||||||
|
|
||||||
|
% Header is empty.
|
||||||
|
% Footer is "date DRAFT pageno"
|
||||||
|
\def\ps@plain{
|
||||||
|
\let\@mkboth\@gobbletwo
|
||||||
|
\let\@oddhead\@empty \let\@evenhead\@empty
|
||||||
|
|
||||||
|
\def\@oddfoot{\reset@font\rm\drafttimel\hfil\draftbox\hfil\thepager}
|
||||||
|
\if@twoside
|
||||||
|
\def\@evenfoot{\reset@font\rm\thepagel\hfil\draftbox\hfil\drafttimer}
|
||||||
|
\else \let\@evenfoot\@oddfoot
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
% Aux macro -- sets footer to be "date DRAFT".
|
||||||
|
\def\@draftfooters{
|
||||||
|
\def\@oddfoot{\reset@font\rm\drafttimel\hfil\draftbox}
|
||||||
|
\if@twoside
|
||||||
|
\def\@evenfoot{\reset@font\rm\draftbox\hfil\drafttimer}
|
||||||
|
\else \let\@evenfoot\@oddfoot
|
||||||
|
\fi
|
||||||
|
}
|
||||||
|
|
||||||
|
% Header is empty.
|
||||||
|
% Footer is "date DRAFT".
|
||||||
|
\def\ps@empty{
|
||||||
|
\let\@mkboth\@gobbletwo
|
||||||
|
\let\@oddhead\@empty \let\@evenhead\@empty
|
||||||
|
\@draftfooters
|
||||||
|
}
|
||||||
|
|
||||||
|
% Header is defined by the document style (article, book, etc.).
|
||||||
|
% Footer is "date DRAFT".
|
||||||
|
\let\@draftoldhead\ps@headings
|
||||||
|
\def\ps@headings{
|
||||||
|
\@draftoldhead % Do the default \pagestyle{headings} stuff.
|
||||||
|
\@draftfooters % Then define the draft footers:
|
||||||
|
}
|
||||||
|
|
||||||
|
% Header is defined by the document style (article, book, etc.),
|
||||||
|
% and filled in by user's \markboth and \markright commands.
|
||||||
|
% Footer is "date DRAFT".
|
||||||
|
\let\@draftoldmyhead\ps@myheadings
|
||||||
|
\def\ps@myheadings{
|
||||||
|
\@draftoldmyhead % Do the default \pagestyle{myheadings} stuff.
|
||||||
|
\@draftfooters % Then define the draft footers:
|
||||||
|
}
|
||||||
|
|
||||||
|
\ps@plain
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
%&latex -*- latex -*-
|
||||||
|
|
||||||
|
\title{Scsh Reference Manual}
|
||||||
|
\subtitle{For scsh release 0.6.4}
|
||||||
|
\author{Olin Shivers, Brian D.~Carlstrom, Martin Gasbichler, and Mike Sperber}
|
||||||
|
\date{April 2003}
|
||||||
|
|
||||||
|
\maketitle
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
% Some code-changes for tex2page and latex output. NF
|
||||||
|
\texonly
|
||||||
|
\chapter*{Acknowledgements}
|
||||||
|
\endtexonly
|
||||||
|
\htmlonly
|
||||||
|
\\ \ex{Acknowledgements} \\ \\
|
||||||
|
\endhtmlonly
|
||||||
|
|
||||||
|
Who should I thank?
|
||||||
|
My so-called ``colleagues,'' who laugh at me behind my back,
|
||||||
|
all the while becoming famous on {\em my\/} work?
|
||||||
|
My worthless graduate students, whose computer skills appear to
|
||||||
|
be limited to downloading bitmaps off of netnews?
|
||||||
|
My parents, who are still waiting for me to quit ``fooling around with
|
||||||
|
computers,'' go to med school, and become a radiologist?
|
||||||
|
My department chairman, a manager who gives one new insight into
|
||||||
|
and sympathy for disgruntled postal workers?
|
||||||
|
|
||||||
|
My God, no one could blame me---no one!---if I went off the edge and just
|
||||||
|
lost it completely one day.
|
||||||
|
I couldn't get through the day as it is without the Prozac and Jack Daniels
|
||||||
|
I keep on the shelf, behind my Tops-20 JSYS manuals.
|
||||||
|
I start getting the shakes real bad around 10am, right before my
|
||||||
|
advisor meetings. A 10 oz.\ Jack 'n Zac helps me get through the
|
||||||
|
meetings without one of my students winding up with his severed head
|
||||||
|
in a bowling-ball bag. They look at me funny; they think I twitch a
|
||||||
|
lot. I'm not twitching. I'm controlling my impulse to snag my 9mm
|
||||||
|
Sig-Sauer out from my day-pack and make a few strong points about
|
||||||
|
the quality of undergraduate education in Amerika.
|
||||||
|
|
||||||
|
If I thought anyone cared, if I thought anyone would even be reading this,
|
||||||
|
I'd probably make an effort to keep up appearances until the last possible
|
||||||
|
moment. But no one does, and no one will. So I can pretty much say exactly
|
||||||
|
what I think.
|
||||||
|
|
||||||
|
Oh, yes, the {\em acknowledgements.}
|
||||||
|
I think not. I did it. I did it all, by myself.
|
||||||
|
\begin{flushright}
|
||||||
|
\begin{tabular}{l}
|
||||||
|
Olin Shivers \\
|
||||||
|
Cambridge \\
|
||||||
|
September 4, 1994
|
||||||
|
\end{tabular}
|
||||||
|
\end{flushright}
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\tableofcontents
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
% headings.tex -*- latex -*-
|
||||||
|
% Quieter headings that the ones used in article.sty.
|
||||||
|
% This is not a style option. Don't say [headings].
|
||||||
|
% Instead, say \input{headings} after the \documentstyle.
|
||||||
|
% -Olin 7/91
|
||||||
|
|
||||||
|
\makeatletter
|
||||||
|
|
||||||
|
\def\section{\@startsection {section}{1}{\z@}{-3.5ex plus -1ex minus
|
||||||
|
-.2ex}{2.3ex plus .2ex}{\large\normalfont\bfseries}}
|
||||||
|
\def\subsection{\@startsection{subsection}{2}{\z@}{-3.25ex plus -1ex minus
|
||||||
|
-.2ex}{1.5ex plus .2ex}{\normalsize\normalfont\bfseries}}
|
||||||
|
\def\subsubsection{\@startsection{subsubsection}{3}{\z@}{-3.25ex plus
|
||||||
|
-1ex minus -.2ex}{1.5ex plus .2ex}{\normalsize\normalfont\bfseries}}
|
||||||
|
|
||||||
|
\makeatother
|
||||||
|
|
@ -0,0 +1,435 @@
|
||||||
|
%&latex -*- latex -*-
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\chapter{Introduction}
|
||||||
|
|
||||||
|
This is the reference manual for scsh,
|
||||||
|
a {\Unix} shell that is embedded within {\Scheme}.
|
||||||
|
Scsh is a Scheme system designed for writing useful standalone Unix
|
||||||
|
programs and shell scripts---it spans a wide range of application,
|
||||||
|
from ``script'' applications usually handled with perl or sh,
|
||||||
|
to more standard systems applications usually written in C.
|
||||||
|
|
||||||
|
Scsh comes built on top of {\scm}, and has two components:
|
||||||
|
a process notation for running programs and setting up pipelines
|
||||||
|
and redirections,
|
||||||
|
and a complete syscall library for low-level access to the operating system.
|
||||||
|
This manual gives a complete description of scsh.
|
||||||
|
A general discussion of the design principles behind scsh can be found
|
||||||
|
in a companion paper, ``A Scheme Shell.''
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Copyright \& source-code license}
|
||||||
|
Scsh is open source. The complete sources come with the standard
|
||||||
|
distribution, which can be downloaded off the net.
|
||||||
|
Scsh has an ideologically hip, BSD-style license.
|
||||||
|
|
||||||
|
We note that the code is a rich source for other Scheme implementations
|
||||||
|
to mine. Not only the \emph{code}, but the \emph{APIs} are available
|
||||||
|
for implementors working on Scheme environments for systems programming.
|
||||||
|
These APIs represent years of work, and should provide a big head-start
|
||||||
|
on any related effort. (Just don't call it ``scsh,'' unless it's
|
||||||
|
\emph{exactly} compliant with the scsh interfaces.)
|
||||||
|
|
||||||
|
Take all the code you like; we'll just write more.
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Obtaining scsh}
|
||||||
|
Scsh is distributed via net publication.
|
||||||
|
We place new releases at well-known network sites,
|
||||||
|
and allow them to propagate from there.
|
||||||
|
We currently release scsh to the following Internet sites:
|
||||||
|
\begin{inset}\begin{flushleft}
|
||||||
|
\ex{\urlh{ftp://ftp.scsh.net/pub/scsh}{ftp://ftp.scsh.net/pub/scsh}} \\
|
||||||
|
\ex{\urlh{http://prdownloads.sourceforge.net/scsh/}{http://prdownloads.sourceforge.net/scsh/}} \\
|
||||||
|
\end{flushleft}
|
||||||
|
\end{inset}
|
||||||
|
%
|
||||||
|
Each should have a compressed tar file of the entire scsh release,
|
||||||
|
which includes all the source code and the manual,
|
||||||
|
and a separate file containing just this manual in Postscript form,
|
||||||
|
for those who simply wish to read about the system.
|
||||||
|
|
||||||
|
However, nothing is certain for long on the Net.
|
||||||
|
Probably the best way to get a copy of scsh is to use a network
|
||||||
|
resource-discovery tool, such as archie,
|
||||||
|
to find ftp servers storing scsh tar files.
|
||||||
|
Take the set of sites storing the most recent release of scsh,
|
||||||
|
choose one close to your site, and download the tar file.
|
||||||
|
|
||||||
|
\section{Building scsh}
|
||||||
|
Scsh currently runs on a fairly large set of Unix systems, including
|
||||||
|
Linux, FreeBSD, OpenBSD, NetBSD, MacOS X, SunOS, Solaris, AIX, NeXTSTEP, Irix, and HP-UX.
|
||||||
|
We use the Gnu project's autoconfig tool to generate self-configuring
|
||||||
|
shell scripts that customise the scsh Makefile for different OS variants.
|
||||||
|
This means that if you use one of the common Unix implementations,
|
||||||
|
building scsh should require exactly the following steps:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{l@{\qquad}l}
|
||||||
|
\ex{gunzip scsh.tar.gz} & \emph{Uncompress the release tar file.} \\
|
||||||
|
\ex{untar xfv scsh.tar} & \emph{Unpack the source code.} \\
|
||||||
|
\ex{cd scsh-0.6.x} & \emph{Move to the source directory.} \\
|
||||||
|
\ex{./configure} & \emph{Examine host; build Makefile.} \\
|
||||||
|
\ex{make} & \emph{Build system.}
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
When you are done, you should have a virtual machine compiled in
|
||||||
|
file \ex{scshvm}, and a heap image in file \ex{scsh/scsh.image}.
|
||||||
|
Typing
|
||||||
|
\begin{code}
|
||||||
|
make install
|
||||||
|
\end{code}
|
||||||
|
will install these programs in your installation directory
|
||||||
|
(by default, \ex{/usr/local}), along with a small stub startup
|
||||||
|
binary, \ex{scsh}.
|
||||||
|
|
||||||
|
If you don't have the patience to do this, you can start up
|
||||||
|
a Scheme shell immediately after the initial make by simply
|
||||||
|
saying
|
||||||
|
\codex{./scshvm -o ./scshvm -i scsh/scsh.image}
|
||||||
|
See chapter~\ref{chapt:running} for full details on installation
|
||||||
|
locations and startup options.
|
||||||
|
|
||||||
|
It is not too difficult to port scsh to another Unix platform if your
|
||||||
|
OS is not supported by the current release.
|
||||||
|
See the release notes for more details on how to do this.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Caveats}
|
||||||
|
|
||||||
|
It is important to note what scsh is \emph{not}, as well as what it is.
|
||||||
|
Scsh, in the current release, is primarily designed for the writing of
|
||||||
|
shell scripts---programming.
|
||||||
|
It is not a very comfortable system for interactive command use:
|
||||||
|
the current release lacks job control, command-line editing, a terse,
|
||||||
|
convenient command syntax, and it does not read in an initialisation
|
||||||
|
file analogous to \ex{.login} or \ex{.profile}.
|
||||||
|
We hope to address all of these issues in future releases;
|
||||||
|
we even have designs for several of these features;
|
||||||
|
but the system as-released does not currently provide these features.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Naming conventions}
|
||||||
|
Scsh follows a general naming scheme that consistently employs a set of
|
||||||
|
abbreviations.
|
||||||
|
This is intended to make it easier to remember the names of things.
|
||||||
|
Some of the common ones are:
|
||||||
|
\begin{description}
|
||||||
|
\item [\ex{fdes}]
|
||||||
|
Means ``file descriptor,'' a small integer used in {\Unix}
|
||||||
|
to represent I/O channels.
|
||||||
|
|
||||||
|
\item [\ex{\ldots*}]
|
||||||
|
A given bit of functionality sometimes comes in two related forms,
|
||||||
|
the first being a \emph{special form} that contains a body of
|
||||||
|
{\Scheme} code to be executed in some context,
|
||||||
|
and the other being a \emph{procedure} that takes a procedural
|
||||||
|
argument (a ``thunk'') to be called in the same context.
|
||||||
|
The procedure variant is named by taking the name of the special form,
|
||||||
|
and appending an asterisk. For example:
|
||||||
|
\begin{code}
|
||||||
|
;;; Special form:
|
||||||
|
(with-cwd "/etc"
|
||||||
|
(for-each print-file (directory-files))
|
||||||
|
(display "All done"))
|
||||||
|
|
||||||
|
;;; Procedure:
|
||||||
|
(with-cwd* "/etc"
|
||||||
|
(lambda ()
|
||||||
|
(for-each print-file (directory-files))
|
||||||
|
(display "All done")))\end{code}
|
||||||
|
|
||||||
|
\item [\ex{\var{action}/\var{modifier}}]
|
||||||
|
The infix ``\ex{/}'' is pronounced ``with,'' as in
|
||||||
|
\ex{exec/env}---``exec with environment.''
|
||||||
|
|
||||||
|
\item [\ex{call/\ldots}]
|
||||||
|
Procedures that call their argument on some computed value
|
||||||
|
are usually named ``\ex{call/\ldots},'' \eg,
|
||||||
|
\ex{(call/fdes \var{port} \var{proc})}, which calls \var{proc}
|
||||||
|
on \var{port}'s file descriptor, returning whatever \var{proc}
|
||||||
|
returns. The abbreviated name means ``call with file descriptor.''
|
||||||
|
|
||||||
|
\item [\ex{with-\ldots}]
|
||||||
|
Procedures that call their argument, and special forms that execute
|
||||||
|
their bodies in some special dynamic context frequently have
|
||||||
|
names of the form \ex{with-\ldots}. For example,
|
||||||
|
\ex{(with-env \var{env} \vari{body}1 \ldots)} and
|
||||||
|
\ex{(with-env* \var{env} \var{thunk})}. These forms set
|
||||||
|
the process environment body, execute their body or thunk,
|
||||||
|
and then return after resetting the environment to its original
|
||||||
|
state.
|
||||||
|
|
||||||
|
\item[\ex{create-}]
|
||||||
|
Procedures that create objects in the file system (files, directories,
|
||||||
|
temp files, fifos, \etc), begin with \ex{create-\ldots}.
|
||||||
|
|
||||||
|
\item [\ex{delete-}]
|
||||||
|
Procedures that delete objects from the file system (files,
|
||||||
|
directories, temp files, fifos, \etc), begin with \ex{delete-\ldots}.
|
||||||
|
|
||||||
|
\item[ \ex{\var{record}:\var{field}} ]
|
||||||
|
Procedures that access fields of a record are usually written
|
||||||
|
with a colon between the name of the record and the name of the
|
||||||
|
field, as in \ex{user-info:home-dir}.
|
||||||
|
|
||||||
|
\item[\ex{\%\ldots}]
|
||||||
|
A percent sign is used to prefix lower-level scsh primitives
|
||||||
|
that are not commonly used.
|
||||||
|
|
||||||
|
\item[\ex{-info}]
|
||||||
|
Data structures packaging up information about various OS
|
||||||
|
entities frequently end in \ldots\ex{-info}. Examples:
|
||||||
|
\ex{user-info}, \ex{file-info}, \ex{group-info}, and \ex{host-info}.
|
||||||
|
|
||||||
|
\end{description}
|
||||||
|
%
|
||||||
|
Enumerated constants from some set \var{s} are usually named
|
||||||
|
\ex{\var{s}/\vari{const}1}, \ex{\var{s}/\vari{const}2}, \ldots.
|
||||||
|
For example, the various {\Unix} signal integers have the names
|
||||||
|
\ex{signal/cont}, \ex{signal/kill}, \ex{signal/int}, \ex{signal/hup},
|
||||||
|
and so forth.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Lexical issues}
|
||||||
|
Scsh's lexical syntax is just {\RnRS} {\Scheme}, with the following
|
||||||
|
exceptions.
|
||||||
|
|
||||||
|
\subsection{Extended symbol syntax}
|
||||||
|
Scsh's symbol syntax differs from {\RnRS} {\Scheme} in the following ways:
|
||||||
|
\begin{itemize}
|
||||||
|
\item In scsh, symbol case is preserved by \ex{read} and is significant on
|
||||||
|
symbol comparison. This means
|
||||||
|
\codex{(run (less Readme))}
|
||||||
|
displays the right file.
|
||||||
|
|
||||||
|
\item ``\ex{-}'' and ``\ex{+}'' are allowed to begin symbols.
|
||||||
|
So the following are legitimate symbols:
|
||||||
|
\codex{-O2 -geometry +Wn}
|
||||||
|
|
||||||
|
\item ``\ex{|}'' and ``\ex{.}'' are symbol constituents.
|
||||||
|
This allows \ex{|} for the pipe symbol, and \ex{..} for the parent-directory
|
||||||
|
symbol. (Of course, ``\ex{.}'' alone is not a symbol, but a
|
||||||
|
dotted-pair marker.)
|
||||||
|
|
||||||
|
\item A symbol may begin with a digit.
|
||||||
|
So the following are legitimate symbols:
|
||||||
|
\codex{9x15 80x36-3+440}
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\subsection{Extended string syntax}
|
||||||
|
Scsh strings are allowed to contain the {\Ansi} C escape sequences
|
||||||
|
such as \verb|\n| and \verb|\161|.
|
||||||
|
|
||||||
|
\subsection{Block comments and executable interpreter-triggers}
|
||||||
|
Scsh allows source files to begin with a header of the form
|
||||||
|
\codex{\#!/usr/local/bin/scsh -s}
|
||||||
|
The Unix operating system treats source files beginning with the headers
|
||||||
|
of this form specially;
|
||||||
|
they can be directly executed by the operating system
|
||||||
|
(see chapter~\ref{chapt:running} for information on how to use this feature).
|
||||||
|
The scsh interpreter ignores this special header by treating \ex{\#!} as a
|
||||||
|
comment marker similar to \ex{;}.
|
||||||
|
When the scsh reader encounters \ex{\#!}, it skips characters until it finds
|
||||||
|
the closing sequence
|
||||||
|
new\-line/{\ob}ex\-cla\-ma\-tion-{\ob}point/{\ob}sharp-{\ob}sign/{\ob}new\-line.
|
||||||
|
|
||||||
|
Although the form of the \ex{\#!} read-macro was chosen to support
|
||||||
|
interpreter-triggers for executable Unix scripts,
|
||||||
|
it is a general block-comment sequence and can be used as such
|
||||||
|
anywhere in a scsh program.
|
||||||
|
|
||||||
|
\subsection{Here-strings}
|
||||||
|
The read macro \ex{\#<} is used to introduce ``here-strings''
|
||||||
|
in programs, similar to the \ex{<<} ``here document'' redirections
|
||||||
|
provided by sh and csh.
|
||||||
|
There are two kinds of here-string, character-delimited and line-delimited;
|
||||||
|
they are both introduced by the \ex{\#<} sequence.
|
||||||
|
|
||||||
|
\subsubsection{Character-delimited here-strings}
|
||||||
|
A \emph{character-delimited} here-string has the form
|
||||||
|
\codex{\#<\emph{x}...stuff...\emph{x}}
|
||||||
|
where \emph{x} is any single character
|
||||||
|
(except \ex{<}, see below),
|
||||||
|
which is used to delimit the string bounds.
|
||||||
|
Some examples:
|
||||||
|
\begin{inset}
|
||||||
|
\begin{tabular}{ll}
|
||||||
|
Here-string syntax & Ordinary string syntax \\ \hline
|
||||||
|
\verb:#<|Hello, world.|: & \verb:"Hello, world.": \\
|
||||||
|
\verb:#<!"Ouch," he said.!: & \verb:"\"Ouch,\" he said.":
|
||||||
|
\end{tabular}
|
||||||
|
\end{inset}
|
||||||
|
%
|
||||||
|
There is no interpretation of characters within the here-string;
|
||||||
|
the characters are all copied verbatim.
|
||||||
|
|
||||||
|
\subsubsection{Line-delimited here-strings}
|
||||||
|
If the sequence begins "\ex{\#<<}" then it introduces a \emph{line-delimited}
|
||||||
|
here-string.
|
||||||
|
These are similar to the ``here documents'' of sh and csh.
|
||||||
|
Line-delimited here-strings are delimited by the rest of the text line that
|
||||||
|
follows the "\ex{\#<<}" sequence.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
\begin{code}
|
||||||
|
#<<FOO
|
||||||
|
Hello, there.
|
||||||
|
This is read by Scheme as a string,
|
||||||
|
terminated by the first occurrence
|
||||||
|
of newline-F-O-O-newline or newline-F-O-O-eof.
|
||||||
|
FOO\end{code}
|
||||||
|
%
|
||||||
|
Thus,
|
||||||
|
\begin{code}
|
||||||
|
#<<foo
|
||||||
|
Hello, world.
|
||||||
|
foo\end{code}
|
||||||
|
%
|
||||||
|
is the same thing as
|
||||||
|
\codex{"Hello, world."}
|
||||||
|
|
||||||
|
Line-delimited here-strings are useful for writing down long, constant
|
||||||
|
strings---such as long, multi-line \ex{format} strings,
|
||||||
|
or arguments to Unix programs, \eg,
|
||||||
|
\begin{code}
|
||||||
|
;; Free up some disk space for my netnews files.
|
||||||
|
(run (csh -c #<<EOF
|
||||||
|
cd /urops
|
||||||
|
rm -rf *
|
||||||
|
echo All done.
|
||||||
|
|
||||||
|
EOF
|
||||||
|
))\end{code}
|
||||||
|
|
||||||
|
The advantage they have over the double-quote syntax
|
||||||
|
(\eg, \ex{"Hello, world."})
|
||||||
|
is that there is no need to backslash-quote special characters internal
|
||||||
|
to the string, such as the double-quote or backslash characters.
|
||||||
|
|
||||||
|
The detailed syntax of line-delimited here-strings is as follows.
|
||||||
|
The characters "\ex{\#<<}" begin the here-string.
|
||||||
|
The characters between the "\ex{\#<<}" and the next newline are the
|
||||||
|
\emph{delimiter line}.
|
||||||
|
All characters between the "\ex{\#<<}" and the next newline comprise the
|
||||||
|
delimiter line---including any white space.
|
||||||
|
The body of the string begins on the following line,
|
||||||
|
and is terminated by a line of text which exactly matches the
|
||||||
|
delimiter line.
|
||||||
|
This terminating line can be ended by either a newline or end-of-file.
|
||||||
|
Absolutely no interpretation is done on the input string.
|
||||||
|
Control characters, white space, quotes, backslash---everything
|
||||||
|
is copied as-is.
|
||||||
|
The newline immediately preceding the terminating delimiter line is
|
||||||
|
not included in the result string
|
||||||
|
(leave an extra blank line if you need to put a final
|
||||||
|
newline in the here-string---see the example above).
|
||||||
|
If EOF is encountered before reading the end of the here-string,
|
||||||
|
an error is signalled.
|
||||||
|
|
||||||
|
\subsection{Dot}
|
||||||
|
It is unfortunate that the single-dot token, ``\ex{.}'', is both
|
||||||
|
a fundamental {\Unix} file name and a deep, primitive syntactic token
|
||||||
|
in {\Scheme}---it means the following will not parse correctly in scsh:
|
||||||
|
\codex{(run/strings (find . -name *.c -print))}
|
||||||
|
You must instead quote the dot:
|
||||||
|
\codex{(run/strings (find "." -name *.c -print))}
|
||||||
|
|
||||||
|
When you write shell scripts that manipulate the file system,
|
||||||
|
keep in mind the special status of the dot token.
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{Record types and the \texttt{define-record} form}
|
||||||
|
\label{sec:defrec}
|
||||||
|
\index{define-record@\texttt{define-record}}
|
||||||
|
|
||||||
|
Scsh's interfaces occasionally provide data in structured record types;
|
||||||
|
an example is the \ex{file-info} record whose various fields describe the size,
|
||||||
|
protection, last date of modification, and other pertinent data for a
|
||||||
|
particular file.
|
||||||
|
These record types are described in this manual using the \ex{define-record}
|
||||||
|
notation, which looks like the following:
|
||||||
|
%
|
||||||
|
\begin{code}
|
||||||
|
(define-record ship
|
||||||
|
x
|
||||||
|
y
|
||||||
|
(size 100))\end{code}
|
||||||
|
%
|
||||||
|
This form defines a \var{ship} record, with three fields:
|
||||||
|
its x and y coordinates, and its size.
|
||||||
|
The values of the \var{x} and \var{y} fields are specified as parameters
|
||||||
|
to the ship-building procedure, \ex{(make-ship \var{x} \var{y})},
|
||||||
|
and the \var{size} field is initialised to 100.
|
||||||
|
All told, the \ex{define-record} form above defines the following procedures:
|
||||||
|
%
|
||||||
|
\begin{center}
|
||||||
|
\begin{tabular}{|ll|}
|
||||||
|
\multicolumn{1}{l}{Procedure} & \multicolumn{1}{l}{Definition} \\
|
||||||
|
\hline
|
||||||
|
(make-ship \var{x} \var{y}) & Create a new \var{ship} record. \\
|
||||||
|
\hline
|
||||||
|
(ship:x \var{ship}) & Retrieve the \var{x} field. \\
|
||||||
|
(ship:y \var{ship}) & Retrieve the \var{y} field. \\
|
||||||
|
(ship:size \var{ship}) & Retrieve the \var{size} field. \\
|
||||||
|
\hline
|
||||||
|
(set-ship:x \var{ship} \var{new-x}) & Assign the \var{x} field. \\
|
||||||
|
(set-ship:y \var{ship} \var{new-y}) & Assign the \var{y} field. \\
|
||||||
|
(set-ship:size \var{ship} \var{new-size}) & Assign the \var{size} field. \\
|
||||||
|
\hline
|
||||||
|
(modify-ship:x \var{ship} \var{xfun}) & Modify \var{x} field with \var{xfun}. \\
|
||||||
|
(modify-ship:y \var{ship} \var{yfun}) & Modify \var{y} field with \var{yfun}. \\
|
||||||
|
(modify-ship:size \var{ship} \var{sizefun}) & Modify \var{size} field with \var{sizefun}. \\
|
||||||
|
\hline
|
||||||
|
(ship? \var{object}) & Type predicate. \\
|
||||||
|
\hline
|
||||||
|
(copy-ship \var{ship}) & Shallow-copy of the record. \\
|
||||||
|
\hline
|
||||||
|
\end{tabular}
|
||||||
|
\end{center}
|
||||||
|
%
|
||||||
|
|
||||||
|
An implementation of \ex{define-record} is available as a macro for Scheme
|
||||||
|
programmers to define their own record types;
|
||||||
|
the syntax is accessed by opening the package \ex{defrec-package}, which
|
||||||
|
exports the single syntax form \ex{define-record}.
|
||||||
|
See the source code for the \ex{defrec-package} module
|
||||||
|
for further details of the macro.
|
||||||
|
|
||||||
|
You must open this package to access the form.
|
||||||
|
Scsh does not export a record-definition package by default as there are
|
||||||
|
several from which to choose.
|
||||||
|
Besides the \ex{define-record} macro, which Shivers prefers\footnote{He wrote
|
||||||
|
it.}, you might instead wish to employ the notationally-distinct
|
||||||
|
\ex{define-record-type} macro that Jonathan Rees
|
||||||
|
prefers\footnote{He wrote it.}.
|
||||||
|
It can be found in the
|
||||||
|
\ex{define-record-types} structure.
|
||||||
|
|
||||||
|
Alternatively, you may define your own, of course.
|
||||||
|
|
||||||
|
|
||||||
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
\section{A word about {\Unix} standards}
|
||||||
|
``The wonderful thing about {\Unix} standards is that there are so many
|
||||||
|
to choose from.''
|
||||||
|
You may be totally bewildered about the multitude of various standards that
|
||||||
|
exist.
|
||||||
|
Rest assured that nowhere in this manual will you encounter an attempt
|
||||||
|
to spell it all out for you;
|
||||||
|
you could not read and internalise such a twisted account without
|
||||||
|
bleeding from the nose and ears.
|
||||||
|
|
||||||
|
However, you might keep in mind the following simple fact: of all the
|
||||||
|
standards, {\Posix} is the least common denominator.
|
||||||
|
So when this manual repeatedly refers to {\Posix}, the point is ``the
|
||||||
|
thing we are describing should be portable just about anywhere.''
|
||||||
|
Scsh sticks to {\Posix} when at all possible; its major departure is
|
||||||
|
symbolic links, which aren't in {\Posix} (see---it
|
||||||
|
really \emph{is} a least common denominator).
|
||||||
|
|
||||||
|
%%% Local Variables:
|
||||||
|
%%% mode: latex
|
||||||
|
%%% TeX-master: "man"
|
||||||
|
%%% End:
|
||||||
|
|
@ -0,0 +1,133 @@
|
||||||
|
% man.t2p
|
||||||
|
% Dorai Sitaram
|
||||||
|
% Feb 6, 2000
|
||||||
|
|
||||||
|
% This file contains the tex2page macros needed to process
|
||||||
|
% the scsh LaTeX document scsh-n.n.n/doc/scsh-manual/man.tex.
|
||||||
|
% Copy (or link) this file alongside man.tex and run
|
||||||
|
%
|
||||||
|
% tex2page man
|
||||||
|
|
||||||
|
\input css.t2p
|
||||||
|
\htmlmathstyle{no-image}
|
||||||
|
|
||||||
|
\let\pagebreak\relax
|
||||||
|
|
||||||
|
\let\small\relax
|
||||||
|
|
||||||
|
%\let\PRIMtableofcontents\tableofcontents
|
||||||
|
%\def\tableofcontents{\chapter*{Contents}\PRIMtableofcontents}
|
||||||
|
|
||||||
|
\def\subtitle#1{\def\savesubtitle{#1}}
|
||||||
|
|
||||||
|
\def\maketitle{
|
||||||
|
\subject{\TIIPtitle}
|
||||||
|
{\bf \hr}
|
||||||
|
\rightline{\savesubtitle}
|
||||||
|
\bigskip\bigskip
|
||||||
|
\bigskip\bigskip
|
||||||
|
{\bf\TIIPauthor}
|
||||||
|
{\bf\hr}
|
||||||
|
}
|
||||||
|
|
||||||
|
\let\PRIMdocument\document
|
||||||
|
|
||||||
|
\def\document{\PRIMdocument
|
||||||
|
|
||||||
|
\let\ttchars\relax
|
||||||
|
\let\ttt\tt
|
||||||
|
|
||||||
|
%\def\~{\rawhtml~\endrawhtml}
|
||||||
|
\def\~{\char`\~}
|
||||||
|
\def\cd#1{{\tt\def\\{\char`\\}\defcsactive\${\char`\$}\defcsactive\~{\char`\~}\defcsactive\&{\char`\&}#1}}
|
||||||
|
\def\cddollar{\undefcsactive\$}
|
||||||
|
\def\cdmath{\undefcsactive\$}
|
||||||
|
\def\codeallowbreaks{\relax}
|
||||||
|
\def\defvarx#1#2{\index{#1}\leftline{{\tt #1} \qquad #2}}
|
||||||
|
|
||||||
|
\let\PRIMflushright\flushright
|
||||||
|
|
||||||
|
\def\flushright{\PRIMflushright\TIIPtabularborder=0 }
|
||||||
|
|
||||||
|
\let\PRIMfigure\figure
|
||||||
|
\let\PRIMendfigure\endfigure
|
||||||
|
|
||||||
|
\def\figure{\par\hrule\PRIMfigure}
|
||||||
|
\def\endfigure{\PRIMendfigure\hrule\par}
|
||||||
|
|
||||||
|
\let\PRIMtable\table
|
||||||
|
\let\PRIMendtable\endtable
|
||||||
|
|
||||||
|
\def\table{\par\hrule\PRIMtable}
|
||||||
|
\def\endtable{\PRIMendtable\hrule\par}
|
||||||
|
|
||||||
|
\imgdef\vdots{\bf.\par.\par.}
|
||||||
|
|
||||||
|
%\evalh{
|
||||||
|
%
|
||||||
|
%(define all-blanks?
|
||||||
|
% (lambda (s)
|
||||||
|
% (andmap
|
||||||
|
% char-whitespace?
|
||||||
|
% (string->list s))))
|
||||||
|
%
|
||||||
|
%}
|
||||||
|
%
|
||||||
|
%
|
||||||
|
%\def\spaceifnotempty{\evalh{
|
||||||
|
%
|
||||||
|
%(let ((x (ungroup (get-token))))
|
||||||
|
% (unless (all-blanks? x)
|
||||||
|
% (emit #\space)))
|
||||||
|
%
|
||||||
|
%}}
|
||||||
|
|
||||||
|
\def\spaceifnotempty#1{%
|
||||||
|
\def\TEMP{#1}%
|
||||||
|
\ifx\TEMP\empty\else\ \fi}
|
||||||
|
|
||||||
|
\def\dfnix#1#2#3#4#5{\index{#5}\leftline{{\tt(#1\spaceifnotempty{#2}{\it#2})} \quad $\longrightarrow$ \quad {\it #3} \qquad (#4)}}
|
||||||
|
|
||||||
|
%\def\ex#1{{\tt #1}}
|
||||||
|
%\let\ex\texttt
|
||||||
|
\def\l#1{lambda (#1)}
|
||||||
|
\def\lx#1{lambda {#1}}
|
||||||
|
%\def\notenum#1{}
|
||||||
|
%\def\project#1{}
|
||||||
|
%\def\var#1{{\it #1\/}}
|
||||||
|
%\let\var\textit
|
||||||
|
%\def\vari#1#2{\mbox{{\it #1\/}\undefcsactive\$$_{#2}$}}
|
||||||
|
%\def\vari#1#2{\textit{#1}$_{#2}$}
|
||||||
|
|
||||||
|
\renewenvironment{boxedfigure}{\def\srecomment#1{\\#1\\}%
|
||||||
|
\begin{figure}\pagestyle}{\end{figure}}
|
||||||
|
|
||||||
|
\newenvironment{centercode}{\begin{code}}{\end{code}}
|
||||||
|
|
||||||
|
\def\setupcode{\tt%
|
||||||
|
\def\\{\char`\\}%
|
||||||
|
\defcsactive\${\$}%
|
||||||
|
\def\evalto{==> }%
|
||||||
|
\defcsactive\%{\%}\obeywhitespace}
|
||||||
|
|
||||||
|
\newenvironment{code}{\begin{quote}\setupcode\GOBBLEOPTARG}
|
||||||
|
{\end{quote}}
|
||||||
|
|
||||||
|
\newenvironment{codebox}{\begin{tableplain}\bgroup\setupcode\GOBBLEOPTARG}
|
||||||
|
{\egroup\end{tableplain}}
|
||||||
|
|
||||||
|
\renewenvironment{desc}{\begin{quote}}{\end{quote}}
|
||||||
|
|
||||||
|
\renewenvironment{exampletable}{%
|
||||||
|
\def\header#1{\\\leftline{#1}\\}%
|
||||||
|
\def\splitline#1#2{\\\leftline{#1}\\\leftline{#2}}%
|
||||||
|
\begin{tabular}{}}{\end{tabular}}
|
||||||
|
|
||||||
|
\newenvironment{tightcode}{\begin{code}}{\end{code}}
|
||||||
|
\renewenvironment{widecode}{\begin{code}}{\end{code}}
|
||||||
|
|
||||||
|
\renewenvironment{inset}{\begin{quote}}{\end{quote}}
|
||||||
|
\renewenvironment{leftinset}{\begin{quote}}{\end{quote}}
|
||||||
|
\renewenvironment{tightinset}{\begin{quote}}{\end{quote}}
|
||||||
|
\renewenvironment{tightleftinset}{\begin{quote}}{\end{quote}}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
% -*- latex -*-
|
||||||
|
|
||||||
|
% This is the reference manual for the Scheme Shell.
|
||||||
|
|
||||||
|
\documentclass[twoside]{report}
|
||||||
|
\usepackage{code,boxedminipage,makeidx,palatino,ct,
|
||||||
|
headings,mantitle,array,matter,mysize10,tex2page}
|
||||||
|
|
||||||
|
\texonly
|
||||||
|
% tex2page defines \url and hyperref loads the package url
|
||||||
|
% but setting \url to \relax satisfies \newcommand
|
||||||
|
\let\url\relax
|
||||||
|
\input{pdfcond}
|
||||||
|
\ifpdf
|
||||||
|
\usepackage[pdftex,hyperindex,
|
||||||
|
pdftitle={scsh manual, release 0.6.4},
|
||||||
|
pdfauthor={Olin Shivers, Brian D.~Carlstrom, Martin Gasbichler,
|
||||||
|
and Mike Sperber}
|
||||||
|
colorlinks=true,linkcolor=blue,pagecolor=blue,urlcolor=blue,
|
||||||
|
pdfstartview=FitH,pdfview=FitH]{hyperref}
|
||||||
|
\usepackage{thumbpdf}
|
||||||
|
\usepackage{tocbibind}
|
||||||
|
\else
|
||||||
|
\usepackage[dvipdfm,hyperindex,hypertex,
|
||||||
|
pdftitle={scsh manual, release 0.6.4},
|
||||||
|
pdfauthor={Olin Shivers, Brian D.~Carlstrom, Martin Gasbichler,
|
||||||
|
and Mike Sperber}
|
||||||
|
colorlinks=true,linkcolor=blue,pagecolor=blue,urlcolor=blue,
|
||||||
|
pdfstartview=FitH,pdfview=FitH]{hyperref}
|
||||||
|
\fi
|
||||||
|
\endtexonly
|
||||||
|
|
||||||
|
% These fonts are good choices for screen-readable pdf, but the man needs
|
||||||
|
% a pass over the layout, since the this tt font will blow out the width
|
||||||
|
% of some examples, making them wrap and generally screwing them up. Maybe this
|
||||||
|
% should also be a LaTeX option, so we can get palatino on the hardcopy
|
||||||
|
% runs and these fonts on pdf runs...
|
||||||
|
%\renewcommand{\rmdefault}{phv}
|
||||||
|
%\renewcommand{\sfdefault}{phv}
|
||||||
|
%\renewcommand{\ttdefault}{pcr}
|
||||||
|
|
||||||
|
% Style issues
|
||||||
|
\parskip = 3pt plus 3pt
|
||||||
|
\sloppy
|
||||||
|
|
||||||
|
%\includeonly{miscprocs}
|
||||||
|
|
||||||
|
\input{decls}
|
||||||
|
\makeindex
|
||||||
|
%%% End preamble
|
||||||
|
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
|
||||||
|
\frontmatter
|
||||||
|
\include{front}
|
||||||
|
|
||||||
|
\mainmatter
|
||||||
|
\include{intro}
|
||||||
|
\include{procnotation}
|
||||||
|
\include{syscalls}
|
||||||
|
\include{network}
|
||||||
|
\include{strings}
|
||||||
|
\include{sre}
|
||||||
|
\include{rdelim}
|
||||||
|
\include{awk}
|
||||||
|
\include{threads}
|
||||||
|
\include{miscprocs}
|
||||||
|
\include{running}
|
||||||
|
|
||||||
|
\backmatter
|
||||||
|
\printindex
|
||||||
|
|
||||||
|
\end{document}
|
||||||
|
|
||||||
|
% General things to do when converting ASCII text to LaTeX:
|
||||||
|
% Build a set of \breakondash, \breakondot, \breakonslash commands
|
||||||
|
% that will enable breaking in \tt. This is better than \=, etc.
|
||||||
|
%
|
||||||
|
% Check for ..., quote char, double-dashes --
|
||||||
|
% Double-word check
|
||||||
|
% lambda -> \l
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue