fix: README -> README.md
This commit is contained in:
parent
43e68af625
commit
99b0a6292c
756 changed files with 323753 additions and 71 deletions
13
README
13
README
|
@ -1,13 +0,0 @@
|
|||
chez-openbsd - mirror of ChezScheme with OpenBSD boot files
|
||||
=============================================================
|
||||
|
||||
THIS REPO IS A MIRROR OF https://github.com/cisco/ChezScheme CONTAINING OPENBSD BOOT FILES.
|
||||
I am not the owner of ChezScheme nor a developer of ChezScheme.
|
||||
Please send issues related to ChezScheme directly to their Github repo.
|
||||
You'll find a copy of the original README in README.md.
|
||||
|
||||
To build on OpenBSD, simply do `./configure --threads` and `gmake -jN`,
|
||||
`--threads` enabling posix thread support and N in `-jN` being the number of cores in your system.
|
||||
|
||||
See https://git.heimdall.pm/chez-openbsd/releases for releases.
|
||||
See https://heimdall.pm/blog/2022/07/28/how-to-build-chezscheme-on-openbsd.html for more information.
|
71
README.md
71
README.md
|
@ -1,60 +1,17 @@
|
|||
[](https://github.com/cisco/ChezScheme/actions/workflows/test.yml)
|
||||
# chez-openbsd - mirror of ChezScheme with OpenBSD boot files
|
||||
## ChezScheme v9.5.9
|
||||
|
||||
Chez Scheme is both a programming language and an implementation
|
||||
of that language, with supporting tools and documentation.
|
||||
**THIS REPO IS A MIRROR OF [CHEZSCHEME](https://github.com/cisco/ChezScheme) CONTAINING OPENBSD BOOT FILES.**
|
||||
I am not the owner of ChezScheme nor a developer of ChezScheme.
|
||||
Please send issues related to ChezScheme directly to their [Github repo](https://github.com/cisco/ChezScheme).
|
||||
You'll find a copy of the original README in `README.original.md`.
|
||||
|
||||
As a superset of the language described in the
|
||||
[Revised<sup>6</sup> Report on the Algorithmic Language Scheme](http://www.r6rs.org)
|
||||
(R6RS), Chez Scheme supports all standard features of Scheme,
|
||||
including first-class procedures, proper treatment of tail calls,
|
||||
continuations, user-defined records, libraries, exceptions, and
|
||||
hygienic macro expansion.
|
||||
To build on OpenBSD, simply do:
|
||||
```bash
|
||||
$ ./configure --threads
|
||||
$ gmake -jN
|
||||
```
|
||||
`--threads` enables (posix) thread support and the `N` in `-jN` being the number of cores in your system.
|
||||
|
||||
Chez Scheme also includes extensive support for interfacing with C
|
||||
and other languages, support for multiple threads possibly running
|
||||
on multiple cores, non-blocking I/O, and many other features.
|
||||
|
||||
The Chez Scheme implementation consists of a compiler, run-time
|
||||
system, and programming environment.
|
||||
Although an interpreter is available, all code is compiled by
|
||||
default.
|
||||
Source code is compiled on-the-fly when loaded from a source file
|
||||
or entered via the shell.
|
||||
A source file can also be precompiled into a stored binary form and
|
||||
automatically recompiled when its dependencies change.
|
||||
Whether compiling on the fly or precompiling, the compiler produces
|
||||
optimized machine code, with some optimization across separately
|
||||
compiled library boundaries.
|
||||
The compiler can also be directed to perform whole-program compilation,
|
||||
which does full cross-library optimization and also reduces a
|
||||
program and the libraries upon which it depends to a single binary.
|
||||
|
||||
The run-time system interfaces with the operating system and supports,
|
||||
among other things, binary and textual (Unicode) I/O, automatic
|
||||
storage management (dynamic memory allocation and generational
|
||||
garbage collection), library management, and exception handling.
|
||||
By default, the compiler is included in the run-time system, allowing
|
||||
programs to be generated and compiled at run time, and storage for
|
||||
dynamically compiled code, just like any other dynamically allocated
|
||||
storage, is automatically reclaimed by the garbage collector.
|
||||
|
||||
The programming environment includes a source-level debugger, a
|
||||
mechanism for producing HTML displays of profile counts and program
|
||||
"hot spots" when profiling is enabled during compilation, tools for
|
||||
inspecting memory usage, and an interactive shell interface (the
|
||||
expression editor, or "expeditor" for short) that supports multi-line
|
||||
expression editing.
|
||||
|
||||
The R6RS core of the Chez Scheme language is described in
|
||||
[The Scheme Programming Language](http://www.scheme.com/tspl4/),
|
||||
which also includes an introduction to Scheme and a set of example programs.
|
||||
Chez Scheme's additional language, run-time system, and
|
||||
programming environment features are described in the
|
||||
[Chez Scheme User's Guide](http://cisco.github.io/ChezScheme/csug9.5/csug.html).
|
||||
The latter includes a shared index and a shared summary of forms,
|
||||
with links where appropriate to the former, so it is often the best
|
||||
starting point.
|
||||
|
||||
Get started with Chez Scheme by [Building Chez Scheme](BUILDING).
|
||||
|
||||
For more information see the [Chez Scheme Project Page](https://cisco.github.io/ChezScheme/).
|
||||
See [releases](https://basedwa.re/tmtt/chez-openbsd/releases).
|
||||
See [the original blogpost](https://heimdall.pm/blog/2022/07/28/how-to-build-chezscheme-on-openbsd.html) for more information.
|
||||
|
|
60
README.original.md
Normal file
60
README.original.md
Normal file
|
@ -0,0 +1,60 @@
|
|||
[](https://github.com/cisco/ChezScheme/actions/workflows/test.yml)
|
||||
|
||||
Chez Scheme is both a programming language and an implementation
|
||||
of that language, with supporting tools and documentation.
|
||||
|
||||
As a superset of the language described in the
|
||||
[Revised<sup>6</sup> Report on the Algorithmic Language Scheme](http://www.r6rs.org)
|
||||
(R6RS), Chez Scheme supports all standard features of Scheme,
|
||||
including first-class procedures, proper treatment of tail calls,
|
||||
continuations, user-defined records, libraries, exceptions, and
|
||||
hygienic macro expansion.
|
||||
|
||||
Chez Scheme also includes extensive support for interfacing with C
|
||||
and other languages, support for multiple threads possibly running
|
||||
on multiple cores, non-blocking I/O, and many other features.
|
||||
|
||||
The Chez Scheme implementation consists of a compiler, run-time
|
||||
system, and programming environment.
|
||||
Although an interpreter is available, all code is compiled by
|
||||
default.
|
||||
Source code is compiled on-the-fly when loaded from a source file
|
||||
or entered via the shell.
|
||||
A source file can also be precompiled into a stored binary form and
|
||||
automatically recompiled when its dependencies change.
|
||||
Whether compiling on the fly or precompiling, the compiler produces
|
||||
optimized machine code, with some optimization across separately
|
||||
compiled library boundaries.
|
||||
The compiler can also be directed to perform whole-program compilation,
|
||||
which does full cross-library optimization and also reduces a
|
||||
program and the libraries upon which it depends to a single binary.
|
||||
|
||||
The run-time system interfaces with the operating system and supports,
|
||||
among other things, binary and textual (Unicode) I/O, automatic
|
||||
storage management (dynamic memory allocation and generational
|
||||
garbage collection), library management, and exception handling.
|
||||
By default, the compiler is included in the run-time system, allowing
|
||||
programs to be generated and compiled at run time, and storage for
|
||||
dynamically compiled code, just like any other dynamically allocated
|
||||
storage, is automatically reclaimed by the garbage collector.
|
||||
|
||||
The programming environment includes a source-level debugger, a
|
||||
mechanism for producing HTML displays of profile counts and program
|
||||
"hot spots" when profiling is enabled during compilation, tools for
|
||||
inspecting memory usage, and an interactive shell interface (the
|
||||
expression editor, or "expeditor" for short) that supports multi-line
|
||||
expression editing.
|
||||
|
||||
The R6RS core of the Chez Scheme language is described in
|
||||
[The Scheme Programming Language](http://www.scheme.com/tspl4/),
|
||||
which also includes an introduction to Scheme and a set of example programs.
|
||||
Chez Scheme's additional language, run-time system, and
|
||||
programming environment features are described in the
|
||||
[Chez Scheme User's Guide](http://cisco.github.io/ChezScheme/csug9.5/csug.html).
|
||||
The latter includes a shared index and a shared summary of forms,
|
||||
with links where appropriate to the former, so it is often the best
|
||||
starting point.
|
||||
|
||||
Get started with Chez Scheme by [Building Chez Scheme](BUILDING).
|
||||
|
||||
For more information see the [Chez Scheme Project Page](https://cisco.github.io/ChezScheme/).
|
|
@ -1 +0,0 @@
|
|||
../csug.css
|
35
csug/canned/csug.css
Normal file
35
csug/canned/csug.css
Normal file
|
@ -0,0 +1,35 @@
|
|||
BODY {background-color: #FFFFFF}
|
||||
|
||||
a:link, a:active, a:visited { color:#005568; text-decoration:underline }
|
||||
a:hover { color:white; text-decoration:underline; background:#005568 }
|
||||
|
||||
a.plain:link, a.plain:active, a.plain:visited { color:#005568; text-decoration:none }
|
||||
a.plain:hover { color:white; text-decoration:none; background:#005568 }
|
||||
|
||||
a.toc:link, a.toc:active, a.toc:visited {font-family: sans-serif; color:#005568; text-decoration:none}
|
||||
a.toc:hover {font-family: sans-serif; color:white; text-decoration:none; background:#005568}
|
||||
|
||||
a.image:link, a.image:active, a.image:visited, a.image:hover {
|
||||
color: #005568;
|
||||
background: #FFFFFF;
|
||||
}
|
||||
|
||||
ul.tocchapter { list-style: none; }
|
||||
ul.tocsection { list-style: circle; color: #C41230 }
|
||||
|
||||
hr.copyright { width: 50% }
|
||||
|
||||
input.default { background: #ffffff; color: #000000; vertical-align: middle}
|
||||
|
||||
h1, h2, h3, h4 {font-family: sans-serif; color: #005568}
|
||||
h1 {font-size: 2em}
|
||||
h2 {margin-top: 30px; font-size: 1.5em}
|
||||
h3 {margin-top: 30px; font-size: 1.17em}
|
||||
h1, h2, h3, h4 {font-weight: bold}
|
||||
|
||||
.title { font-family: sans-serif; font-weight: bold; font-size: 2.5em; color: #005568; white-space: nowrap}
|
||||
|
||||
.formdef { color: #005568 }
|
||||
|
||||
table.indent {margin-left: 20px}
|
||||
|
70
ta6ob/Makefile
Normal file
70
ta6ob/Makefile
Normal file
|
@ -0,0 +1,70 @@
|
|||
# Makefile-workarea.in
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
PREFIX=
|
||||
|
||||
.PHONY: build
|
||||
build:
|
||||
(cd c && $(MAKE))
|
||||
(cd s && $(MAKE) bootstrap)
|
||||
|
||||
.PHONY: install
|
||||
install: build
|
||||
$(MAKE) -f Mf-install
|
||||
|
||||
.PHONY: uninstall
|
||||
uninstall:
|
||||
$(MAKE) -f Mf-install uninstall
|
||||
|
||||
.PHONY: test
|
||||
test: build
|
||||
(cd mats && $(MAKE) allx)
|
||||
@echo "test run complete. check $(PREFIX)mats/summary for errors."
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
rm -f s/bootstrap
|
||||
(cd c && $(MAKE))
|
||||
(cd s && $(MAKE) bootstrap p=t c=t)
|
||||
(cd mats && $(MAKE) allx c=t)
|
||||
|
||||
.PHONY: bootfiles
|
||||
bootfiles: build
|
||||
$(MAKE) -f Mf-boot
|
||||
|
||||
.PHONY: bintar
|
||||
bintar: build
|
||||
(cd bintar && $(MAKE))
|
||||
|
||||
.PHONY: rpm
|
||||
rpm: bintar
|
||||
(cd rpm && $(MAKE))
|
||||
|
||||
.PHONY: pkg
|
||||
pkg: bintar
|
||||
(cd pkg && $(MAKE))
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f petite.1 scheme.1
|
||||
(cd s && $(MAKE) clean)
|
||||
(cd c && $(MAKE) clean)
|
||||
(cd mats && $(MAKE) clean)
|
||||
(cd examples && $(MAKE) clean)
|
||||
(cd bintar && $(MAKE) clean)
|
||||
(cd rpm && $(MAKE) clean)
|
||||
(cd pkg && $(MAKE) clean)
|
||||
rm -f Make.out
|
28
ta6ob/Mf-boot
Normal file
28
ta6ob/Mf-boot
Normal file
|
@ -0,0 +1,28 @@
|
|||
# Mf-boot.in
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
bootfiles=$(addsuffix .boot, $(shell cd ../boot ; echo *))
|
||||
|
||||
doit: $(bootfiles)
|
||||
|
||||
%.boot:
|
||||
( cd .. ; ./workarea $* xc-$* )
|
||||
( cd ../xc-$*/s ; make -f Mf-cross base=../../ta6ob --jobs=2 m=ta6ob xm=$* )
|
||||
for x in `echo scheme.boot petite.boot scheme.h equates.h` ; do\
|
||||
if [ ! -h ../xc-$*/boot/$*/$$x ] ; then \
|
||||
mv -f ../xc-$*/boot/$*/$$x ../boot/$*/$$x ;\
|
||||
fi ;\
|
||||
done
|
||||
rm -rf ../xc-$*
|
164
ta6ob/Mf-install
Normal file
164
ta6ob/Mf-install
Normal file
|
@ -0,0 +1,164 @@
|
|||
# Mf-install.in
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
###############################################################################
|
||||
# the following variables are set up by configure #
|
||||
###############################################################################
|
||||
|
||||
m=ta6ob
|
||||
|
||||
# The following variables determine where the executables, boot files,
|
||||
# example programs, and manual pages are installed.
|
||||
|
||||
# executable directory
|
||||
InstallBin=/usr/local/bin
|
||||
|
||||
# library directory
|
||||
InstallLib=/usr/local/lib
|
||||
|
||||
# man page directory
|
||||
InstallMan=/usr/local/man/man1
|
||||
|
||||
# installation owner
|
||||
InstallOwner=
|
||||
|
||||
# installation group
|
||||
InstallGroup=
|
||||
|
||||
# Files are actually installed at ${TempRoot}${InstallBin},
|
||||
# ${TempRoot}${InstallLib}, and ${TempRoot}${InstallMan}.
|
||||
# This useful for testing the install process and for building
|
||||
# installation scripts
|
||||
TempRoot=
|
||||
|
||||
# compress man pages?
|
||||
GzipManPages=yes
|
||||
|
||||
# executable names
|
||||
InstallSchemeName=scheme
|
||||
InstallPetiteName=petite
|
||||
InstallScriptName=scheme-script
|
||||
|
||||
# Whether to install "kernel.o" or "libkernel.a"
|
||||
InstallKernelTarget=installkernelobj
|
||||
|
||||
# Maybe install libz.a and liblz4.a by setting to "installzlib" and "installliz4"
|
||||
InstallZlibTarget=
|
||||
InstallLZ4Target=
|
||||
|
||||
###############################################################################
|
||||
# no changes should be needed below this point #
|
||||
###############################################################################
|
||||
|
||||
Version=csv9.5.9
|
||||
Include=boot/$m
|
||||
PetiteBoot=boot/$m/petite.boot
|
||||
SchemeBoot=boot/$m/scheme.boot
|
||||
Revision=boot/$m/revision
|
||||
Scheme=bin/$m/scheme
|
||||
Petite=bin/$m/petite
|
||||
InstallLibExamples=${InstallLib}/${Version}/examples
|
||||
InstallLibBin=${InstallLib}/${Version}/$m
|
||||
|
||||
Bin=${TempRoot}${InstallBin}
|
||||
Lib=${TempRoot}${InstallLib}/${Version}
|
||||
LibExamples=${TempRoot}${InstallLibExamples}
|
||||
LibBin=${TempRoot}${InstallLibBin}
|
||||
Man=${TempRoot}${InstallMan}
|
||||
PetitePath=${Bin}/${InstallPetiteName}
|
||||
SchemePath=${Bin}/${InstallSchemeName}
|
||||
SchemeScriptPath=${Bin}/${InstallScriptName}
|
||||
|
||||
install: bininstall libbininstall maninstall liblibinstall ${InstallKernelTarget}
|
||||
|
||||
uninstall:
|
||||
rm -rf ${Lib}
|
||||
rm -f ${PetitePath}
|
||||
rm -f ${SchemePath}
|
||||
rm -f ${SchemeScriptPath}
|
||||
rm -f ${Man}/${InstallPetiteName}.1{,.gz}
|
||||
rm -f ${Man}/${InstallSchemeName}.1{,.gz}
|
||||
|
||||
scheme.1 petite.1: scheme.1.in
|
||||
sed -e "s;{InstallBin};${InstallBin};g" \
|
||||
-e "s;{InstallLibExamples};${InstallLibExamples};g" \
|
||||
-e "s;{InstallLibBin};${InstallLibBin};g" \
|
||||
-e "s;{InstallPetiteName};${InstallPetiteName};g" \
|
||||
-e "s;{InstallSchemeName};${InstallSchemeName};g" \
|
||||
-e "s;{InstallScriptName};${InstallScriptName};g" \
|
||||
scheme.1.in > $@
|
||||
|
||||
###############################################################################
|
||||
# no useful external targets below this line #
|
||||
###############################################################################
|
||||
|
||||
I=./installsh -o "${InstallOwner}" -g "${InstallGroup}"
|
||||
|
||||
bininstall: ${Bin}
|
||||
$I -m 555 ${Scheme} ${SchemePath}
|
||||
ln -f ${SchemePath} ${PetitePath}
|
||||
ln -f ${SchemePath} ${SchemeScriptPath}
|
||||
|
||||
libbininstall: ${LibBin}
|
||||
$I -m 444 ${PetiteBoot} ${LibBin}/petite.boot
|
||||
if [ "${InstallPetiteName}" != "petite" ]; then\
|
||||
rm -f ${LibBin}/${InstallPetiteName}.boot;\
|
||||
ln -f ${LibBin}/petite.boot ${LibBin}/${InstallPetiteName}.boot;\
|
||||
fi
|
||||
$I -m 444 ${SchemeBoot} ${LibBin}/scheme.boot;\
|
||||
if [ "${InstallSchemeName}" != "scheme" ]; then\
|
||||
rm -f ${LibBin}/${InstallSchemeName}.boot;\
|
||||
ln -f ${LibBin}/scheme.boot ${LibBin}/${InstallSchemeName}.boot;\
|
||||
fi
|
||||
ln -f ${LibBin}/scheme.boot ${LibBin}/${InstallScriptName}.boot;
|
||||
$I -m 444 ${Include}/main.o ${LibBin}
|
||||
$I -m 444 ${Include}/scheme.h ${LibBin}
|
||||
$I -m 444 ${Revision} ${LibBin}/revision
|
||||
|
||||
installkernelobj: ${LibBin}
|
||||
$I -m 444 ${Include}/kernel.o ${LibBin}
|
||||
|
||||
installkernellib: ${LibBin} ${InstallZlibTarget} ${InstallLZ4Target}
|
||||
$I -m 444 ${Include}/libkernel.a ${LibBin}
|
||||
|
||||
installzlib: ${LibBin}
|
||||
$I -m 444 zlib/libz.a ${LibBin}
|
||||
|
||||
installlz4: ${LibBin}
|
||||
$I -m 444 lz4/lib/liblz4.a ${LibBin}
|
||||
|
||||
maninstall: scheme.1 petite.1 ${Man}
|
||||
$I -m 444 scheme.1 ${Man}/${InstallSchemeName}.1
|
||||
if [ ${GzipManPages} = yes ] ; then gzip -f ${Man}/${InstallSchemeName}.1 ; fi
|
||||
$I -m 444 petite.1 ${Man}/${InstallPetiteName}.1
|
||||
if [ ${GzipManPages} = yes ] ; then gzip -f ${Man}/${InstallPetiteName}.1 ; fi
|
||||
|
||||
liblibinstall: ${LibExamples}
|
||||
$I -m 444 examples/* ${LibExamples}
|
||||
|
||||
${Lib}:
|
||||
$I -d -m 755 ${Lib}
|
||||
|
||||
${LibBin}: ${Lib}
|
||||
$I -d -m 755 ${LibBin}
|
||||
|
||||
${LibExamples}: ${Lib}
|
||||
$I -d -m 755 ${LibExamples}
|
||||
|
||||
${Bin}:
|
||||
$I -d -m 755 ${Bin}
|
||||
|
||||
${Man}:
|
||||
$I -d -m 755 ${Man}
|
BIN
ta6ob/bin/petite
Executable file
BIN
ta6ob/bin/petite
Executable file
Binary file not shown.
BIN
ta6ob/bin/scheme
Executable file
BIN
ta6ob/bin/scheme
Executable file
Binary file not shown.
BIN
ta6ob/bin/ta6ob/petite
Executable file
BIN
ta6ob/bin/ta6ob/petite
Executable file
Binary file not shown.
BIN
ta6ob/bin/ta6ob/scheme
Executable file
BIN
ta6ob/bin/ta6ob/scheme
Executable file
Binary file not shown.
86
ta6ob/bintar/Makefile
Normal file
86
ta6ob/bintar/Makefile
Normal file
|
@ -0,0 +1,86 @@
|
|||
# Makefile
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
version = 9.5.9
|
||||
m := $(shell find ../bin/* -type d | xargs basename)
|
||||
|
||||
R = csv$(version)
|
||||
TARBALL = $(R)-$(m).tar.gz
|
||||
|
||||
CONTENTS=\
|
||||
$(R)/LICENSE\
|
||||
$(R)/NOTICE\
|
||||
$(R)/scheme.1.in\
|
||||
$(R)/installsh\
|
||||
$(R)/Makefile\
|
||||
$(R)/examples\
|
||||
$(R)/boot\
|
||||
$(R)/bin
|
||||
|
||||
$(TARBALL): $(CONTENTS)
|
||||
( BROKEN=`find -L $R -type l` ; \
|
||||
if test -n "$$BROKEN" ; then \
|
||||
echo "Error: missing $(BROKEN)" ; \
|
||||
exit 1 ; \
|
||||
fi )
|
||||
tar -czhf $(TARBALL) $R
|
||||
rm -rf $(R)
|
||||
|
||||
$(R)/LICENSE: $(R)
|
||||
( cd $(R) ; ln -s ../../../LICENSE . )
|
||||
|
||||
$(R)/NOTICE: $(R)
|
||||
( cd $(R) ; ln -s ../../../NOTICE . )
|
||||
|
||||
$(R)/scheme.1.in: $(R)
|
||||
( cd $(R) ; ln -s ../../scheme.1.in . )
|
||||
|
||||
$(R)/installsh: $(R)
|
||||
( cd $(R) ; ln -s ../../installsh . )
|
||||
|
||||
$(R)/Makefile: $(R)
|
||||
( cd $(R) ; ln -s ../../Mf-install Makefile )
|
||||
|
||||
$(R)/examples: $(R)
|
||||
( cd $(R) ; ln -s ../../examples . )
|
||||
|
||||
$(R)/boot: $(R)
|
||||
mkdir -p $(R)/boot/$(m)
|
||||
( cd $(R)/boot/$(m) ; ln -s ../../../../boot/$(m)/{scheme.h,petite.boot,scheme.boot,revision} . )
|
||||
case $(m) in \
|
||||
*nt) \
|
||||
( cd $R/boot/$(m) ; ln -s ../../../../boot/$(m)/{csv959md.lib,csv959mt.lib,mainmd.obj,mainmt.obj,scheme.res} . ) \
|
||||
;; \
|
||||
*) \
|
||||
( cd $R/boot/$(m) ; ln -s ../../../../boot/$(m)/{main.o,kernel.o} . ) \
|
||||
;; \
|
||||
esac
|
||||
|
||||
$(R)/bin: $(R)
|
||||
mkdir -p $(R)/bin/$(m)
|
||||
case $(m) in \
|
||||
*nt) \
|
||||
( cd $R/bin/$(m) ; ln -s ../../../../bin/$(m)/{scheme.exe,csv959.dll,csv959.lib,vcruntime140.lib} . ) \
|
||||
;; \
|
||||
*) \
|
||||
( cd $R/bin/$(m) ; ln -s ../../../../bin/$(m)/scheme . ) \
|
||||
;; \
|
||||
esac
|
||||
|
||||
$(R):
|
||||
mkdir $(R)
|
||||
|
||||
clean:
|
||||
rm -rf $(R) $(TARBALL)
|
993
ta6ob/boot/ta6ob/equates.h
Normal file
993
ta6ob/boot/ta6ob/equates.h
Normal file
|
@ -0,0 +1,993 @@
|
|||
/* equates.h for Chez Scheme Version 9.5.9 */
|
||||
|
||||
/* Do not edit this file. It is automatically generated and */
|
||||
/* specifically tailored to the version of Chez Scheme named */
|
||||
/* above. Always be certain that you have the correct version */
|
||||
/* of this file for the version of Chez Scheme you are using. */
|
||||
|
||||
/* Warning: Some macros may evaluate arguments more than once. */
|
||||
|
||||
/* Integer typedefs */
|
||||
typedef char I8;
|
||||
typedef unsigned char U8;
|
||||
typedef short I16;
|
||||
typedef unsigned short U16;
|
||||
typedef int I32;
|
||||
typedef unsigned int U32;
|
||||
typedef long I64;
|
||||
typedef unsigned long U64;
|
||||
|
||||
/* constants from cmacros.ss */
|
||||
#define $c_func_closure_index 0x4
|
||||
#define $c_func_closure_record_index 0x3
|
||||
#define $c_func_code_object_index 0x2
|
||||
#define $c_func_code_record_index 0x1
|
||||
#define COMPRESS_FORMAT_BITS 0x3
|
||||
#define COMPRESS_GZIP 0x0
|
||||
#define COMPRESS_HIGH 0x3
|
||||
#define COMPRESS_LOW 0x1
|
||||
#define COMPRESS_LZ4 0x1
|
||||
#define COMPRESS_MAX 0x4
|
||||
#define COMPRESS_MEDIUM 0x2
|
||||
#define COMPRESS_MIN 0x0
|
||||
#define ERROR_CALL_ARGUMENT_COUNT 0x4
|
||||
#define ERROR_CALL_NONPROCEDURE 0x3
|
||||
#define ERROR_CALL_NONPROCEDURE_SYMBOL 0x2
|
||||
#define ERROR_CALL_UNBOUND 0x1
|
||||
#define ERROR_MVLET 0x8
|
||||
#define ERROR_NONCONTINUABLE_INTERRUPT 0x6
|
||||
#define ERROR_OTHER 0x0
|
||||
#define ERROR_RESET 0x5
|
||||
#define ERROR_VALUES 0x7
|
||||
#define OPEN_ERROR_EXISTS 0x2
|
||||
#define OPEN_ERROR_EXISTSNOT 0x3
|
||||
#define OPEN_ERROR_OTHER 0x0
|
||||
#define OPEN_ERROR_PROTECTION 0x1
|
||||
#define PORT_FLAG_BINARY 0x400
|
||||
#define PORT_FLAG_BLOCK_BUFFERED 0x20000
|
||||
#define PORT_FLAG_BOL 0x8000
|
||||
#define PORT_FLAG_CHAR_POSITIONS 0x100000
|
||||
#define PORT_FLAG_CLOSED 0x800
|
||||
#define PORT_FLAG_COMPRESSED 0x2000
|
||||
#define PORT_FLAG_EOF 0x10000
|
||||
#define PORT_FLAG_EXCLUSIVE 0x4000
|
||||
#define PORT_FLAG_FILE 0x1000
|
||||
#define PORT_FLAG_FOLD_CASE 0x400000
|
||||
#define PORT_FLAG_INPUT 0x100
|
||||
#define PORT_FLAG_INPUT_MODE 0x80000
|
||||
#define PORT_FLAG_LINE_BUFFERED 0x40000
|
||||
#define PORT_FLAG_NO_FOLD_CASE 0x800000
|
||||
#define PORT_FLAG_OUTPUT 0x200
|
||||
#define PORT_FLAG_R6RS 0x200000
|
||||
#define SAPPEND 0x3
|
||||
#define SDEFAULT 0x4
|
||||
#define SEOF -0x1
|
||||
#define SERROR 0x0
|
||||
#define SICONV_DUNNO 0x0
|
||||
#define SICONV_INCOMPLETE 0x2
|
||||
#define SICONV_INVALID 0x1
|
||||
#define SICONV_NOROOM 0x3
|
||||
#define SREPLACE 0x2
|
||||
#define STRVNCATE 0x1
|
||||
#define address_bits 0x40
|
||||
#define alloc_waste_maximum 0x800
|
||||
#define annotation_all 0x3
|
||||
#define annotation_debug 0x1
|
||||
#define annotation_profile 0x2
|
||||
#define architecture x86_64
|
||||
#define asm_arg_reg_cnt 0x3
|
||||
#define asm_arg_reg_max 0x5
|
||||
#define bigit_bits 0x20
|
||||
#define bigit_bytes 0x4
|
||||
#define bignum_data_disp 0x9
|
||||
#define bignum_length_factor 0x40
|
||||
#define bignum_length_offset 0x6
|
||||
#define bignum_sign_offset 0x5
|
||||
#define bignum_type_disp 0x1
|
||||
#define black_hole (ptr)0x46
|
||||
#define box_ref_disp 0x9
|
||||
#define box_type_disp 0x1
|
||||
#define byte_alignment 0x10
|
||||
#define byte_constant_mask 0xFFFFFFFFFFFFFFFF
|
||||
#define bytes_per_card 0x200
|
||||
#define bytes_per_segment 0x4000
|
||||
#define bytevector_data_disp 0x9
|
||||
#define bytevector_immutable_flag 0x4
|
||||
#define bytevector_length_factor 0x8
|
||||
#define bytevector_length_offset 0x3
|
||||
#define bytevector_type_disp 0x1
|
||||
#define c_entry_name_vector #(thread-context get-thread-context handle-apply-overflood handle-docall-error handle-overflow handle-overflood handle-nonprocedure-symbol thread-list split-and-resize raw-collect-cond raw-tc-mutex activate-thread deactivate-thread unactivate-thread handle-values-error handle-mvlet-error handle-arg-error foreign-entry install-library-entry get-more-room scan-remembered-set instantiate-code-object Sreturn Scall-one-result Scall-any-results)
|
||||
#define c_entry_vector_size 0x19
|
||||
#define cached_stack_link_disp 0x8
|
||||
#define cached_stack_size_disp 0x0
|
||||
#define card_offset_bits 0x9
|
||||
#define cards_per_segment 0x20
|
||||
#define char_data_offset 0x8
|
||||
#define char_factor 0x100
|
||||
#define closure_code_disp 0x3
|
||||
#define closure_data_disp 0xB
|
||||
#define code_arity_mask_disp 0x21
|
||||
#define code_closure_length_disp 0x29
|
||||
#define code_data_disp 0x41
|
||||
#define code_flag_continuation 0x2
|
||||
#define code_flag_guardian 0x8
|
||||
#define code_flag_system 0x1
|
||||
#define code_flag_template 0x4
|
||||
#define code_flags_offset 0x8
|
||||
#define code_info_disp 0x31
|
||||
#define code_length_disp 0x9
|
||||
#define code_name_disp 0x19
|
||||
#define code_pinfos_disp 0x39
|
||||
#define code_reloc_disp 0x11
|
||||
#define code_type_disp 0x1
|
||||
#define collect_interrupt_index 0x1
|
||||
#define continuation_code_disp 0x3
|
||||
#define continuation_link_disp 0x23
|
||||
#define continuation_return_address_disp 0x2B
|
||||
#define continuation_stack_clength_disp 0x1B
|
||||
#define continuation_stack_disp 0xB
|
||||
#define continuation_stack_length_disp 0x13
|
||||
#define continuation_winders_disp 0x33
|
||||
#define countof_bignum 0x5
|
||||
#define countof_box 0x9
|
||||
#define countof_bytevector 0x15
|
||||
#define countof_closure 0x3
|
||||
#define countof_code 0xB
|
||||
#define countof_continuation 0x4
|
||||
#define countof_ephemeron 0x19
|
||||
#define countof_exactnum 0x8
|
||||
#define countof_flonum 0x2
|
||||
#define countof_fxvector 0x14
|
||||
#define countof_guardian 0x17
|
||||
#define countof_inexactnum 0x7
|
||||
#define countof_locked 0x16
|
||||
#define countof_oblist 0x18
|
||||
#define countof_pair 0x0
|
||||
#define countof_port 0xA
|
||||
#define countof_ratnum 0x6
|
||||
#define countof_relocation_table 0x10
|
||||
#define countof_rtd_counts 0xE
|
||||
#define countof_stack 0xF
|
||||
#define countof_string 0x13
|
||||
#define countof_symbol 0x1
|
||||
#define countof_thread 0xC
|
||||
#define countof_tlc 0xD
|
||||
#define countof_types 0x1A
|
||||
#define countof_vector 0x12
|
||||
#define countof_weakpair 0x11
|
||||
#define default_collect_trip_bytes 0x800000
|
||||
#define default_heap_reserve_ratio 1.0
|
||||
#define default_max_nonstatic_generation 0x4
|
||||
#define default_stack_size 0xFFF0
|
||||
#define default_timer_ticks 0x3E8
|
||||
#define dtvec_hour 0x3
|
||||
#define dtvec_isdst 0x9
|
||||
#define dtvec_mday 0x4
|
||||
#define dtvec_min 0x2
|
||||
#define dtvec_mon 0x5
|
||||
#define dtvec_nsec 0x0
|
||||
#define dtvec_sec 0x1
|
||||
#define dtvec_size 0xC
|
||||
#define dtvec_tzname 0xB
|
||||
#define dtvec_tzoff 0xA
|
||||
#define dtvec_wday 0x7
|
||||
#define dtvec_yday 0x8
|
||||
#define dtvec_year 0x6
|
||||
#define ephemeron_car_disp 0x7
|
||||
#define ephemeron_cdr_disp 0xF
|
||||
#define ephemeron_next_disp 0x17
|
||||
#define ephemeron_trigger_next_disp 0x1F
|
||||
#define eq_hashtable_subtype_ephemeron 0x2
|
||||
#define eq_hashtable_subtype_normal 0x0
|
||||
#define eq_hashtable_subtype_weak 0x1
|
||||
#define exactnum_imag_disp 0x11
|
||||
#define exactnum_real_disp 0x9
|
||||
#define exactnum_type_disp 0x1
|
||||
#define fasl_fld_double 0xA
|
||||
#define fasl_fld_i16 0x2
|
||||
#define fasl_fld_i24 0x3
|
||||
#define fasl_fld_i32 0x4
|
||||
#define fasl_fld_i40 0x5
|
||||
#define fasl_fld_i48 0x6
|
||||
#define fasl_fld_i56 0x7
|
||||
#define fasl_fld_i64 0x8
|
||||
#define fasl_fld_ptr 0x0
|
||||
#define fasl_fld_single 0x9
|
||||
#define fasl_fld_u8 0x1
|
||||
#define fasl_header #vu8(0 0 0 0 99 104 101 122)
|
||||
#define fasl_type_base_rtd 0x1A
|
||||
#define fasl_type_box 0x1
|
||||
#define fasl_type_bytevector 0x1D
|
||||
#define fasl_type_closure 0x6
|
||||
#define fasl_type_code 0xB
|
||||
#define fasl_type_entry 0xD
|
||||
#define fasl_type_ephemeron 0x1C
|
||||
#define fasl_type_eq_hashtable 0x1F
|
||||
#define fasl_type_exactnum 0x14
|
||||
#define fasl_type_flonum 0x8
|
||||
#define fasl_type_fxvector 0x1B
|
||||
#define fasl_type_gensym 0x13
|
||||
#define fasl_type_graph 0x10
|
||||
#define fasl_type_graph_def 0x11
|
||||
#define fasl_type_graph_ref 0x12
|
||||
#define fasl_type_gzip 0x2B
|
||||
#define fasl_type_header 0x0
|
||||
#define fasl_type_immediate 0xC
|
||||
#define fasl_type_immutable_box 0x29
|
||||
#define fasl_type_immutable_bytevector 0x28
|
||||
#define fasl_type_immutable_fxvector 0x27
|
||||
#define fasl_type_immutable_string 0x26
|
||||
#define fasl_type_immutable_vector 0x25
|
||||
#define fasl_type_inexactnum 0x5
|
||||
#define fasl_type_large_integer 0xA
|
||||
#define fasl_type_library 0xE
|
||||
#define fasl_type_library_code 0xF
|
||||
#define fasl_type_lz4 0x2C
|
||||
#define fasl_type_pair 0x7
|
||||
#define fasl_type_ratnum 0x3
|
||||
#define fasl_type_record 0x17
|
||||
#define fasl_type_revisit 0x23
|
||||
#define fasl_type_rtd 0x18
|
||||
#define fasl_type_small_integer 0x19
|
||||
#define fasl_type_string 0x9
|
||||
#define fasl_type_symbol 0x2
|
||||
#define fasl_type_symbol_hashtable 0x20
|
||||
#define fasl_type_uncompressed 0x2A
|
||||
#define fasl_type_vector 0x4
|
||||
#define fasl_type_visit 0x22
|
||||
#define fasl_type_visit_revisit 0x24
|
||||
#define fasl_type_weak_pair 0x1E
|
||||
#define fixnum_bits 0x3D
|
||||
#define fixnum_factor 0x8
|
||||
#define fixnum_offset 0x3
|
||||
#define fld_byte_index 0x4
|
||||
#define fld_mutablep_index 0x2
|
||||
#define fld_name_index 0x1
|
||||
#define fld_type_index 0x3
|
||||
#define flonum_data_disp 0x6
|
||||
#define forward_address_disp 0x8
|
||||
#define forward_marker (ptr)0x2E
|
||||
#define forward_marker_disp 0x0
|
||||
#define ftype_guardian_rep (ptr)0x56
|
||||
#define fxvector_data_disp 0x9
|
||||
#define fxvector_immutable_flag 0x8
|
||||
#define fxvector_length_factor 0x10
|
||||
#define fxvector_length_offset 0x4
|
||||
#define fxvector_type_disp 0x1
|
||||
#define guardian_entry_next_disp 0x18
|
||||
#define guardian_entry_obj_disp 0x0
|
||||
#define guardian_entry_rep_disp 0x8
|
||||
#define guardian_entry_tconc_disp 0x10
|
||||
#define hashtable_default_size 0x8
|
||||
#define header_size_bignum 0x8
|
||||
#define header_size_bytevector 0x8
|
||||
#define header_size_closure 0x8
|
||||
#define header_size_code 0x40
|
||||
#define header_size_fxvector 0x8
|
||||
#define header_size_record 0x8
|
||||
#define header_size_reloc_table 0x10
|
||||
#define header_size_string 0x8
|
||||
#define header_size_vector 0x8
|
||||
#define ignore_event_flag 0x0
|
||||
#define inexactnum_imag_disp 0x19
|
||||
#define inexactnum_pad_disp 0x9
|
||||
#define inexactnum_real_disp 0x11
|
||||
#define inexactnum_type_disp 0x1
|
||||
#define int_bits 0x20
|
||||
#define integer_divide_instruction 1
|
||||
#define keyboard_interrupt_index 0x3
|
||||
#define library_entry_vector_size 0x210
|
||||
#define libspec_closure_index 0xD
|
||||
#define libspec_does_not_expect_headroom_index 0x0
|
||||
#define libspec_error_index 0xE
|
||||
#define libspec_fake_index 0x10
|
||||
#define libspec_flags_index 0x2
|
||||
#define libspec_has_does_not_expect_headroom_version_index 0xF
|
||||
#define libspec_index_base_offset 0x1
|
||||
#define libspec_index_base_size 0x9
|
||||
#define libspec_index_offset 0x0
|
||||
#define libspec_index_size 0xA
|
||||
#define libspec_interface_offset 0xA
|
||||
#define libspec_interface_size 0x3
|
||||
#define libspec_name_index 0x1
|
||||
#define log2_ptr_bytes 0x3
|
||||
#define long_bits 0x40
|
||||
#define long_long_bits 0x40
|
||||
#define machine_type 0x10
|
||||
#define machine_type_a6fb 0x15
|
||||
#define machine_type_a6le 0xB
|
||||
#define machine_type_a6nb 0x19
|
||||
#define machine_type_a6nt 0x1B
|
||||
#define machine_type_a6ob 0xF
|
||||
#define machine_type_a6osx 0xD
|
||||
#define machine_type_a6s2 0x11
|
||||
#define machine_type_alist ((0 . any) (1 . i3le) (2 . ti3le) (3 . i3nt) (4 . ti3nt) (5 . i3fb) (6 . ti3fb) (7 . i3ob) (8 . ti3ob) (9 . i3osx) (10 . ti3osx) (11 . a6le) (12 . ta6le) (13 . a6osx) (14 . ta6osx) (15 . a6ob) (16 . ta6ob) (17 . a6s2) (18 . ta6s2) (19 . i3s2) (20 . ti3s2) (21 . a6fb) (22 . ta6fb) (23 . i3nb) (24 . ti3nb) (25 . a6nb) (26 . ta6nb) (27 . a6nt) (28 . ta6nt) (29 . i3qnx) (30 . ti3qnx) (31 . arm32le) (32 . tarm32le) (33 . ppc32le) (34 . tppc32le))
|
||||
#define machine_type_any 0x0
|
||||
#define machine_type_arm32le 0x1F
|
||||
#define machine_type_i3fb 0x5
|
||||
#define machine_type_i3le 0x1
|
||||
#define machine_type_i3nb 0x17
|
||||
#define machine_type_i3nt 0x3
|
||||
#define machine_type_i3ob 0x7
|
||||
#define machine_type_i3osx 0x9
|
||||
#define machine_type_i3qnx 0x1D
|
||||
#define machine_type_i3s2 0x13
|
||||
#define machine_type_limit 0x23
|
||||
#define machine_type_name ta6ob
|
||||
#define machine_type_ppc32le 0x21
|
||||
#define machine_type_ta6fb 0x16
|
||||
#define machine_type_ta6le 0xC
|
||||
#define machine_type_ta6nb 0x1A
|
||||
#define machine_type_ta6nt 0x1C
|
||||
#define machine_type_ta6ob 0x10
|
||||
#define machine_type_ta6osx 0xE
|
||||
#define machine_type_ta6s2 0x12
|
||||
#define machine_type_tarm32le 0x20
|
||||
#define machine_type_ti3fb 0x6
|
||||
#define machine_type_ti3le 0x2
|
||||
#define machine_type_ti3nb 0x18
|
||||
#define machine_type_ti3nt 0x4
|
||||
#define machine_type_ti3ob 0x8
|
||||
#define machine_type_ti3osx 0xA
|
||||
#define machine_type_ti3qnx 0x1E
|
||||
#define machine_type_ti3s2 0x14
|
||||
#define machine_type_tppc32le 0x22
|
||||
#define mask_bignum 0x1F
|
||||
#define mask_bignum_sign 0x20
|
||||
#define mask_binary_input_port 0x5FF
|
||||
#define mask_binary_output_port 0x6FF
|
||||
#define mask_binary_port 0x4FF
|
||||
#define mask_boolean 0xF7
|
||||
#define mask_box 0x7F
|
||||
#define mask_bwp 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_bytevector 0x3
|
||||
#define mask_char 0xFF
|
||||
#define mask_closure 0x7
|
||||
#define mask_code 0xFF
|
||||
#define mask_continuation_code 0x2FF
|
||||
#define mask_eof 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_exactnum 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_false 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_fixnum 0x7
|
||||
#define mask_flonum 0x7
|
||||
#define mask_fxvector 0x7
|
||||
#define mask_guardian_code 0x8FF
|
||||
#define mask_immediate 0x7
|
||||
#define mask_inexactnum 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_input_port 0x1FF
|
||||
#define mask_mutable_box 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_mutable_bytevector 0x7
|
||||
#define mask_mutable_fxvector 0xF
|
||||
#define mask_mutable_string 0xF
|
||||
#define mask_mutable_vector 0xF
|
||||
#define mask_nil 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_octet -0x7F9
|
||||
#define mask_other_number 0xF
|
||||
#define mask_output_port 0x2FF
|
||||
#define mask_pair 0x7
|
||||
#define mask_port 0xFF
|
||||
#define mask_ratnum 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_record 0x7
|
||||
#define mask_rtd_counts 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_signed_bignum 0x3F
|
||||
#define mask_string 0x7
|
||||
#define mask_symbol 0x7
|
||||
#define mask_system_code 0x1FF
|
||||
#define mask_textual_input_port 0x5FF
|
||||
#define mask_textual_output_port 0x6FF
|
||||
#define mask_textual_port 0x4FF
|
||||
#define mask_thread 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_tlc 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_typed_object 0x7
|
||||
#define mask_unbound 0xFFFFFFFFFFFFFFFF
|
||||
#define mask_vector 0x7
|
||||
#define max_float_alignment 0x8
|
||||
#define max_integer_alignment 0x8
|
||||
#define max_real_space 0xB
|
||||
#define max_space 0xC
|
||||
#define max_sweep_space 0xA
|
||||
#define maximum_bignum_length (iptr)0x3FFFFFFFFFFFFFF
|
||||
#define maximum_bytevector_length (iptr)0xFFFFFFFFFFFFFFF
|
||||
#define maximum_fxvector_length (iptr)0xFFFFFFFFFFFFFFF
|
||||
#define maximum_interrupt_index 0x4
|
||||
#define maximum_string_length (iptr)0xFFFFFFFFFFFFFFF
|
||||
#define maximum_vector_length (iptr)0xFFFFFFFFFFFFFFF
|
||||
#define minimum_segment_request 0x80
|
||||
#define most_negative_fixnum (iptr)-0x1000000000000000
|
||||
#define most_positive_fixnum (iptr)0xFFFFFFFFFFFFFFF
|
||||
#define native_endianness little
|
||||
#define one_shot_headroom 0xC00
|
||||
#define ordinary_type_bits 0x8
|
||||
#define pair_car_disp 0x7
|
||||
#define pair_cdr_disp 0xF
|
||||
#define pair_shift 0x4
|
||||
#define port_flag_binary 0x4
|
||||
#define port_flag_block_buffered 0x200
|
||||
#define port_flag_bol 0x80
|
||||
#define port_flag_char_positions 0x1000
|
||||
#define port_flag_closed 0x8
|
||||
#define port_flag_compressed 0x20
|
||||
#define port_flag_eof 0x100
|
||||
#define port_flag_exclusive 0x40
|
||||
#define port_flag_file 0x10
|
||||
#define port_flag_fold_case 0x4000
|
||||
#define port_flag_input 0x1
|
||||
#define port_flag_input_mode 0x800
|
||||
#define port_flag_line_buffered 0x400
|
||||
#define port_flag_no_fold_case 0x8000
|
||||
#define port_flag_output 0x2
|
||||
#define port_flag_r6rs 0x2000
|
||||
#define port_flags_offset 0x8
|
||||
#define port_handler_disp 0x9
|
||||
#define port_ibuffer_disp 0x39
|
||||
#define port_icount_disp 0x19
|
||||
#define port_ilast_disp 0x31
|
||||
#define port_info_disp 0x41
|
||||
#define port_name_disp 0x49
|
||||
#define port_obuffer_disp 0x29
|
||||
#define port_ocount_disp 0x11
|
||||
#define port_olast_disp 0x21
|
||||
#define port_type_disp 0x1
|
||||
#define prelex_is_flags_offset 0x8
|
||||
#define prelex_is_mask 0xFF00
|
||||
#define prelex_sticky_mask 0xFF
|
||||
#define prelex_was_flags_offset 0x10
|
||||
#define primary_type_bits 0x3
|
||||
#define ptr_bits 0x40
|
||||
#define ptr_bytes 0x8
|
||||
#define ptrdiff_t_bits 0x40
|
||||
#define ratnum_denominator_disp 0x11
|
||||
#define ratnum_numerator_disp 0x9
|
||||
#define ratnum_type_disp 0x1
|
||||
#define real_space_alist ((new . 0) (impure . 1) (symbol . 2) (port . 3) (weakpair . 4) (ephemeron . 5) (pure . 6) (continuation . 7) (code . 8) (pure-typed-object . 9) (impure-record . 10) (data . 11))
|
||||
#define record_data_disp 0x9
|
||||
#define record_type_counts_disp 0x49
|
||||
#define record_type_disp 0x1
|
||||
#define record_type_flags_disp 0x39
|
||||
#define record_type_flds_disp 0x31
|
||||
#define record_type_mpm_disp 0x21
|
||||
#define record_type_name_disp 0x29
|
||||
#define record_type_parent_disp 0x9
|
||||
#define record_type_pm_disp 0x19
|
||||
#define record_type_size_disp 0x11
|
||||
#define record_type_type_disp 0x1
|
||||
#define record_type_uid_disp 0x41
|
||||
#define reloc_abs 0x0
|
||||
#define reloc_code_offset_index 0x3
|
||||
#define reloc_code_offset_mask 0x3FFFFFF
|
||||
#define reloc_code_offset_offset 0x4
|
||||
#define reloc_extended_format 0x1
|
||||
#define reloc_item_offset_index 0x2
|
||||
#define reloc_item_offset_mask 0x3FFFFFF
|
||||
#define reloc_item_offset_offset 0x1E
|
||||
#define reloc_longp_index 0x4
|
||||
#define reloc_table_code_disp 0x8
|
||||
#define reloc_table_data_disp 0x10
|
||||
#define reloc_table_size_disp 0x0
|
||||
#define reloc_type_index 0x1
|
||||
#define reloc_type_mask 0x7
|
||||
#define reloc_type_offset 0x1
|
||||
#define reloc_x86_64_call 0x1
|
||||
#define reloc_x86_64_jump 0x2
|
||||
#define return_address_frame_size_disp -0x10
|
||||
#define return_address_livemask_disp -0x20
|
||||
#define return_address_mv_return_address_disp -0x8
|
||||
#define return_address_toplink_disp -0x18
|
||||
#define rp_header_frame_size_disp 0x10
|
||||
#define rp_header_livemask_disp 0x0
|
||||
#define rp_header_mv_return_address_disp 0x18
|
||||
#define rp_header_toplink_disp 0x8
|
||||
#define rtd_counts_data_disp 0x11
|
||||
#define rtd_counts_timestamp_disp 0x9
|
||||
#define rtd_counts_type_disp 0x1
|
||||
#define rtd_generative 0x1
|
||||
#define rtd_opaque 0x2
|
||||
#define rtd_sealed 0x4
|
||||
#define sbwp (ptr)0x4E
|
||||
#define scaled_shot_1_shot_flag -0x8
|
||||
#define scheme_version 0x90509
|
||||
#define segment_card_offset_bits 0x5
|
||||
#define segment_offset_bits 0xE
|
||||
#define segment_t1_bits 0x10
|
||||
#define segment_t2_bits 0x11
|
||||
#define segment_t3_bits 0x11
|
||||
#define segment_table_levels 0x3
|
||||
#define seof (ptr)0x36
|
||||
#define sfalse (ptr)0x6
|
||||
#define short_bits 0x10
|
||||
#define signal_interrupt_index 0x4
|
||||
#define size_box 0x10
|
||||
#define size_cached_stack 0x10
|
||||
#define size_continuation 0x40
|
||||
#define size_ephemeron 0x20
|
||||
#define size_exactnum 0x20
|
||||
#define size_flonum 0x10
|
||||
#define size_forward 0x10
|
||||
#define size_guardian_entry 0x20
|
||||
#define size_inexactnum 0x20
|
||||
#define size_pair 0x10
|
||||
#define size_port 0x50
|
||||
#define size_ratnum 0x20
|
||||
#define size_record_type 0x50
|
||||
#define size_rp_header 0x20
|
||||
#define size_rtd_counts 0x810
|
||||
#define size_symbol 0x30
|
||||
#define size_tc 0x2C0
|
||||
#define size_thread 0x10
|
||||
#define size_tlc 0x20
|
||||
#define size_typed_object 0x10
|
||||
#define size_t_bits 0x40
|
||||
#define snil (ptr)0x26
|
||||
#define space_char_list (#\n #\i #\x #\q #\w #\e #\p #\k #\c #\r #\s #\d #\e)
|
||||
#define space_cname_list ("new" "impure" "symbol" "port" "weakpr" "emph" "pure" "cont" "code" "p-tobj" "ip-rec" "data" "empty")
|
||||
#define space_code 0x8
|
||||
#define space_continuation 0x7
|
||||
#define space_data 0xB
|
||||
#define space_empty 0xC
|
||||
#define space_ephemeron 0x5
|
||||
#define space_impure 0x1
|
||||
#define space_impure_record 0xA
|
||||
#define space_locked 0x20
|
||||
#define space_new 0x0
|
||||
#define space_old 0x40
|
||||
#define space_port 0x3
|
||||
#define space_pure 0x6
|
||||
#define space_pure_typed_object 0x9
|
||||
#define space_symbol 0x2
|
||||
#define space_weakpair 0x4
|
||||
#define stack_frame_limit 0x200
|
||||
#define stack_slop 0x400
|
||||
#define static_generation 0xFF
|
||||
#define string_char_bits 0x20
|
||||
#define string_char_bytes 0x4
|
||||
#define string_char_offset 0x2
|
||||
#define string_data_disp 0x9
|
||||
#define string_immutable_flag 0x8
|
||||
#define string_length_factor 0x10
|
||||
#define string_length_offset 0x4
|
||||
#define string_type_disp 0x1
|
||||
#define strue (ptr)0xE
|
||||
#define sunbound (ptr)0x1E
|
||||
#define svoid (ptr)0x3E
|
||||
#define symbol_hash_disp 0x2D
|
||||
#define symbol_name_disp 0x1D
|
||||
#define symbol_plist_disp 0x15
|
||||
#define symbol_pvalue_disp 0xD
|
||||
#define symbol_splist_disp 0x25
|
||||
#define symbol_value_disp 0x5
|
||||
#define tc_DSTBV_disp 0x2A8
|
||||
#define tc_SRCBV_disp 0x2B0
|
||||
#define tc_U_disp 0x160
|
||||
#define tc_V_disp 0x168
|
||||
#define tc_W_disp 0x170
|
||||
#define tc_X_disp 0x178
|
||||
#define tc_Y_disp 0x180
|
||||
#define tc_ac0_disp 0x28
|
||||
#define tc_ac1_disp 0x30
|
||||
#define tc_active_disp 0x134
|
||||
#define tc_alloc_counter_disp 0x298
|
||||
#define tc_ap_disp 0x50
|
||||
#define tc_arg_regs_disp 0x0
|
||||
#define tc_block_counter_disp 0x1D8
|
||||
#define tc_cchain_disp 0x120
|
||||
#define tc_code_ranges_to_flush_disp 0x128
|
||||
#define tc_compile_profile_disp 0x230
|
||||
#define tc_compress_format_disp 0x278
|
||||
#define tc_compress_level_disp 0x280
|
||||
#define tc_cp_disp 0x40
|
||||
#define tc_current_error_disp 0x1D0
|
||||
#define tc_current_input_disp 0x1C0
|
||||
#define tc_current_mso_disp 0x1E8
|
||||
#define tc_current_output_disp 0x1C8
|
||||
#define tc_default_record_equal_procedure_disp 0x268
|
||||
#define tc_default_record_hash_procedure_disp 0x270
|
||||
#define tc_disable_count_disp 0x198
|
||||
#define tc_eap_disp 0x58
|
||||
#define tc_esp_disp 0x48
|
||||
#define tc_fxfirst_bit_set_bv_disp 0x200
|
||||
#define tc_fxlength_bv_disp 0x1F8
|
||||
#define tc_generate_inspector_information_disp 0x238
|
||||
#define tc_generate_procedure_source_information_disp 0x240
|
||||
#define tc_generate_profile_forms_disp 0x248
|
||||
#define tc_guardian_entries_disp 0x118
|
||||
#define tc_instr_counter_disp 0x290
|
||||
#define tc_keyboard_interrupt_pending_disp 0x1B0
|
||||
#define tc_lz4_out_buffer_disp 0x288
|
||||
#define tc_meta_level_disp 0x228
|
||||
#define tc_null_immutable_bytevector_disp 0x218
|
||||
#define tc_null_immutable_fxvector_disp 0x210
|
||||
#define tc_null_immutable_string_disp 0x220
|
||||
#define tc_null_immutable_vector_disp 0x208
|
||||
#define tc_optimize_level_disp 0x250
|
||||
#define tc_parameters_disp 0x2A0
|
||||
#define tc_random_seed_disp 0x130
|
||||
#define tc_real_eap_disp 0x90
|
||||
#define tc_ret_disp 0x60
|
||||
#define tc_scheme_stack_disp 0x138
|
||||
#define tc_scheme_stack_size_disp 0x150
|
||||
#define tc_sfd_disp 0x1E0
|
||||
#define tc_sfp_disp 0x38
|
||||
#define tc_signal_interrupt_pending_disp 0x1A0
|
||||
#define tc_signal_interrupt_queue_disp 0x1A8
|
||||
#define tc_something_pending_disp 0x188
|
||||
#define tc_stack_cache_disp 0x140
|
||||
#define tc_stack_link_disp 0x148
|
||||
#define tc_subset_mode_disp 0x258
|
||||
#define tc_suppress_primitive_inlining_disp 0x260
|
||||
#define tc_target_machine_disp 0x1F0
|
||||
#define tc_td_disp 0x88
|
||||
#define tc_threadno_disp 0x1B8
|
||||
#define tc_timer_ticks_disp 0x190
|
||||
#define tc_trap_disp 0x68
|
||||
#define tc_ts_disp 0x80
|
||||
#define tc_virtual_registers_disp 0x98
|
||||
#define tc_winders_disp 0x158
|
||||
#define tc_xp_disp 0x70
|
||||
#define tc_yp_disp 0x78
|
||||
#define thread_tc_disp 0x9
|
||||
#define thread_type_disp 0x1
|
||||
#define time_collector_cpu 0x5
|
||||
#define time_collector_real 0x6
|
||||
#define time_duration 0x2
|
||||
#define time_monotonic 0x3
|
||||
#define time_process 0x0
|
||||
#define time_t_bits 0x40
|
||||
#define time_thread 0x1
|
||||
#define time_utc 0x4
|
||||
#define timer_interrupt_index 0x2
|
||||
#define tlc_ht_disp 0x11
|
||||
#define tlc_keyval_disp 0x9
|
||||
#define tlc_next_disp 0x19
|
||||
#define tlc_type_disp 0x1
|
||||
#define type_bignum 0x6
|
||||
#define type_binary_input_port 0x51E
|
||||
#define type_binary_output_port 0x61E
|
||||
#define type_binary_port 0x41E
|
||||
#define type_boolean 0x6
|
||||
#define type_box 0xE
|
||||
#define type_bytevector 0x1
|
||||
#define type_char 0x16
|
||||
#define type_closure 0x5
|
||||
#define type_code 0x3E
|
||||
#define type_continuation_code 0x23E
|
||||
#define type_exactnum 0x56
|
||||
#define type_fixnum 0x0
|
||||
#define type_flonum 0x2
|
||||
#define type_fxvector 0x3
|
||||
#define type_guardian_code 0x83E
|
||||
#define type_immediate 0x6
|
||||
#define type_immutable_box 0x8E
|
||||
#define type_immutable_bytevector 0x5
|
||||
#define type_immutable_fxvector 0xB
|
||||
#define type_immutable_string 0xA
|
||||
#define type_immutable_vector 0x8
|
||||
#define type_inexactnum 0x36
|
||||
#define type_input_port 0x11E
|
||||
#define type_io_port 0x31E
|
||||
#define type_mutable_box 0xE
|
||||
#define type_mutable_bytevector 0x1
|
||||
#define type_mutable_fxvector 0x3
|
||||
#define type_mutable_string 0x2
|
||||
#define type_mutable_vector 0x0
|
||||
#define type_negative_bignum 0x26
|
||||
#define type_octet 0x0
|
||||
#define type_other_number 0x6
|
||||
#define type_output_port 0x21E
|
||||
#define type_pair 0x1
|
||||
#define type_port 0x1E
|
||||
#define type_positive_bignum 0x6
|
||||
#define type_ratnum 0x16
|
||||
#define type_record 0x7
|
||||
#define type_rtd_counts 0x6E
|
||||
#define type_string 0x2
|
||||
#define type_symbol 0x3
|
||||
#define type_system_code 0x13E
|
||||
#define type_textual_input_port 0x11E
|
||||
#define type_textual_output_port 0x21E
|
||||
#define type_textual_port 0x1E
|
||||
#define type_thread 0x4E
|
||||
#define type_tlc 0x5E
|
||||
#define type_typed_object 0x7
|
||||
#define type_vector 0x0
|
||||
#define typed_object_type_disp 0x1
|
||||
#define typedef_i16 "short"
|
||||
#define typedef_i32 "int"
|
||||
#define typedef_i64 "long"
|
||||
#define typedef_i8 "char"
|
||||
#define typedef_iptr "long int"
|
||||
#define typedef_ptr "void *"
|
||||
#define typedef_string_char "unsigned int"
|
||||
#define typedef_u16 "unsigned short"
|
||||
#define typedef_u32 "unsigned int"
|
||||
#define typedef_u64 "unsigned long"
|
||||
#define typedef_u8 "unsigned char"
|
||||
#define typedef_uptr "unsigned long int"
|
||||
#define typemod 0x8
|
||||
#define unactivate_mode_deactivate 0x1
|
||||
#define unactivate_mode_destroy 0x2
|
||||
#define unactivate_mode_noop 0x0
|
||||
#define unaligned_floats 1
|
||||
#define unaligned_integers 1
|
||||
#define underflow_limit 0x80
|
||||
#define unscaled_shot_1_shot_flag -0x1
|
||||
#define vector_data_disp 0x9
|
||||
#define vector_immutable_flag 0x8
|
||||
#define vector_length_factor 0x10
|
||||
#define vector_length_offset 0x4
|
||||
#define vector_type_disp 0x1
|
||||
#define virtual_register_count 0x10
|
||||
#define wchar_bits 0x20
|
||||
|
||||
/* constants from declare-c-entries */
|
||||
#define CENTRY_Scall_any_results 24
|
||||
#define CENTRY_Scall_one_result 23
|
||||
#define CENTRY_Sreturn 22
|
||||
#define CENTRY_activate_thread 11
|
||||
#define CENTRY_deactivate_thread 12
|
||||
#define CENTRY_foreign_entry 17
|
||||
#define CENTRY_get_more_room 19
|
||||
#define CENTRY_get_thread_context 1
|
||||
#define CENTRY_handle_apply_overflood 2
|
||||
#define CENTRY_handle_arg_error 16
|
||||
#define CENTRY_handle_docall_error 3
|
||||
#define CENTRY_handle_mvlet_error 15
|
||||
#define CENTRY_handle_nonprocedure_symbol 6
|
||||
#define CENTRY_handle_overflood 5
|
||||
#define CENTRY_handle_overflow 4
|
||||
#define CENTRY_handle_values_error 14
|
||||
#define CENTRY_install_library_entry 18
|
||||
#define CENTRY_instantiate_code_object 21
|
||||
#define CENTRY_raw_collect_cond 9
|
||||
#define CENTRY_raw_tc_mutex 10
|
||||
#define CENTRY_scan_remembered_set 20
|
||||
#define CENTRY_split_and_resize 8
|
||||
#define CENTRY_thread_context 0
|
||||
#define CENTRY_thread_list 7
|
||||
#define CENTRY_unactivate_thread 13
|
||||
|
||||
/* displacements for records */
|
||||
#define eq_hashtable_rtd_disp 1
|
||||
#define eq_hashtable_type_disp 9
|
||||
#define eq_hashtable_mutablep_disp 17
|
||||
#define eq_hashtable_vec_disp 25
|
||||
#define eq_hashtable_minlen_disp 33
|
||||
#define eq_hashtable_size_disp 41
|
||||
#define eq_hashtable_subtype_disp 49
|
||||
#define symbol_hashtable_rtd_disp 1
|
||||
#define symbol_hashtable_type_disp 9
|
||||
#define symbol_hashtable_mutablep_disp 17
|
||||
#define symbol_hashtable_vec_disp 25
|
||||
#define symbol_hashtable_minlen_disp 33
|
||||
#define symbol_hashtable_size_disp 41
|
||||
#define symbol_hashtable_equivp_disp 49
|
||||
#define code_info_rtd_disp 1
|
||||
#define code_info_src_disp 9
|
||||
#define code_info_sexpr_disp 17
|
||||
#define code_info_free_disp 25
|
||||
#define code_info_live_disp 33
|
||||
#define code_info_rpis_disp 41
|
||||
|
||||
/* predicates */
|
||||
#define Simmediatep(x) (((uptr)(x)&0x7)==0x6)
|
||||
#define Sportp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0xFF)==0x1E))
|
||||
#define Scodep(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0xFF)==0x3E))
|
||||
|
||||
/* structure accessors */
|
||||
#define INITCAR(x) (*((ptr *)((uptr)(x)+7)))
|
||||
#define INITCDR(x) (*((ptr *)((uptr)(x)+15)))
|
||||
#define SETCAR(x,y) DIRTYSET(((ptr *)((uptr)(x)+7)),(y))
|
||||
#define SETCDR(x,y) DIRTYSET(((ptr *)((uptr)(x)+15)),(y))
|
||||
#define BOXTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define INITBOXREF(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define SETBOXREF(x,y) DIRTYSET(((ptr *)((uptr)(x)+9)),(y))
|
||||
#define EPHEMERONNEXT(x) (*((ptr *)((uptr)(x)+23)))
|
||||
#define INITEPHEMERONNEXT(x) (*((ptr *)((uptr)(x)+23)))
|
||||
#define EPHEMERONTRIGGERNEXT(x) (*((ptr *)((uptr)(x)+31)))
|
||||
#define INITEPHEMERONTRIGGERNEXT(x) (*((ptr *)((uptr)(x)+31)))
|
||||
#define TLCTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define TLCKEYVAL(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define TLCHT(x) (*((ptr *)((uptr)(x)+17)))
|
||||
#define TLCNEXT(x) (*((ptr *)((uptr)(x)+25)))
|
||||
#define INITTLCKEYVAL(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define INITTLCHT(x) (*((ptr *)((uptr)(x)+17)))
|
||||
#define INITTLCNEXT(x) (*((ptr *)((uptr)(x)+25)))
|
||||
#define SETTLCNEXT(x,y) DIRTYSET(((ptr *)((uptr)(x)+25)),(y))
|
||||
#define SYMVAL(x) (*((ptr *)((uptr)(x)+5)))
|
||||
#define SYMPVAL(x) (*((ptr *)((uptr)(x)+13)))
|
||||
#define SYMPLIST(x) (*((ptr *)((uptr)(x)+21)))
|
||||
#define SYMNAME(x) (*((ptr *)((uptr)(x)+29)))
|
||||
#define SYMSPLIST(x) (*((ptr *)((uptr)(x)+37)))
|
||||
#define SYMHASH(x) (*((ptr *)((uptr)(x)+45)))
|
||||
#define INITSYMVAL(x) (*((ptr *)((uptr)(x)+5)))
|
||||
#define INITSYMPVAL(x) (*((ptr *)((uptr)(x)+13)))
|
||||
#define INITSYMPLIST(x) (*((ptr *)((uptr)(x)+21)))
|
||||
#define INITSYMNAME(x) (*((ptr *)((uptr)(x)+29)))
|
||||
#define INITSYMSPLIST(x) (*((ptr *)((uptr)(x)+37)))
|
||||
#define INITSYMHASH(x) (*((ptr *)((uptr)(x)+45)))
|
||||
#define SETSYMVAL(x,y) DIRTYSET(((ptr *)((uptr)(x)+5)),(y))
|
||||
#define SETSYMPVAL(x,y) DIRTYSET(((ptr *)((uptr)(x)+13)),(y))
|
||||
#define SETSYMPLIST(x,y) DIRTYSET(((ptr *)((uptr)(x)+21)),(y))
|
||||
#define SETSYMNAME(x,y) DIRTYSET(((ptr *)((uptr)(x)+29)),(y))
|
||||
#define SETSYMSPLIST(x,y) DIRTYSET(((ptr *)((uptr)(x)+37)),(y))
|
||||
#define SETSYMHASH(x,y) DIRTYSET(((ptr *)((uptr)(x)+45)),(y))
|
||||
#define VECTTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define INITVECTIT(x,i) (((ptr *)((uptr)(x)+9))[i])
|
||||
#define SETVECTIT(x,i,y) DIRTYSET((((ptr *)((uptr)(x)+9))+i),(y))
|
||||
#define FXVECTOR_TYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define FXVECTIT(x,i) (((ptr *)((uptr)(x)+9))[i])
|
||||
#define BYTEVECTOR_TYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define BVIT(x,i) (((octet *)((uptr)(x)+9))[i])
|
||||
#define INEXACTNUM_TYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define INEXACTNUM_REAL_PART(x) (*((double *)((uptr)(x)+17)))
|
||||
#define INEXACTNUM_IMAG_PART(x) (*((double *)((uptr)(x)+25)))
|
||||
#define EXACTNUM_TYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define EXACTNUM_REAL_PART(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define EXACTNUM_IMAG_PART(x) (*((ptr *)((uptr)(x)+17)))
|
||||
#define RATTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define RATNUM(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define RATDEN(x) (*((ptr *)((uptr)(x)+17)))
|
||||
#define CLOSENTRY(x) (*((ptr *)((uptr)(x)+3)))
|
||||
#define CLOSIT(x,i) (((ptr *)((uptr)(x)+11))[i])
|
||||
#define FLODAT(x) (*((double *)((uptr)(x)+6)))
|
||||
#define PORTTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define PORTNAME(x) (*((ptr *)((uptr)(x)+73)))
|
||||
#define PORTHANDLER(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define PORTINFO(x) (*((ptr *)((uptr)(x)+65)))
|
||||
#define PORTOCNT(x) (*((iptr *)((uptr)(x)+17)))
|
||||
#define PORTOLAST(x) (*((ptr *)((uptr)(x)+33)))
|
||||
#define PORTOBUF(x) (*((ptr *)((uptr)(x)+41)))
|
||||
#define PORTICNT(x) (*((iptr *)((uptr)(x)+25)))
|
||||
#define PORTILAST(x) (*((ptr *)((uptr)(x)+49)))
|
||||
#define PORTIBUF(x) (*((ptr *)((uptr)(x)+57)))
|
||||
#define STRTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define STRIT(x,i) (((string_char *)((uptr)(x)+9))[i])
|
||||
#define BIGTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define BIGIT(x,i) (((bigit *)((uptr)(x)+9))[i])
|
||||
#define CODETYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define CODELEN(x) (*((iptr *)((uptr)(x)+9)))
|
||||
#define CODERELOC(x) (*((ptr *)((uptr)(x)+17)))
|
||||
#define CODENAME(x) (*((ptr *)((uptr)(x)+25)))
|
||||
#define CODEARITYMASK(x) (*((ptr *)((uptr)(x)+33)))
|
||||
#define CODEFREE(x) (*((iptr *)((uptr)(x)+41)))
|
||||
#define CODEINFO(x) (*((ptr *)((uptr)(x)+49)))
|
||||
#define CODEPINFOS(x) (*((ptr *)((uptr)(x)+57)))
|
||||
#define CODEIT(x,i) (((octet *)((uptr)(x)+65))[i])
|
||||
#define RELOCSIZE(x) (*((iptr *)((uptr)(x)+0)))
|
||||
#define RELOCCODE(x) (*((ptr *)((uptr)(x)+8)))
|
||||
#define RELOCIT(x,i) (((uptr *)((uptr)(x)+16))[i])
|
||||
#define CONTSTACK(x) (*((ptr *)((uptr)(x)+11)))
|
||||
#define CONTLENGTH(x) (*((iptr *)((uptr)(x)+19)))
|
||||
#define CONTCLENGTH(x) (*((iptr *)((uptr)(x)+27)))
|
||||
#define CONTLINK(x) (*((ptr *)((uptr)(x)+35)))
|
||||
#define CONTRET(x) (*((ptr *)((uptr)(x)+43)))
|
||||
#define CONTWINDERS(x) (*((ptr *)((uptr)(x)+51)))
|
||||
#define RTDCOUNTSTYPE(x) (*((iptr *)((uptr)(x)+1)))
|
||||
#define RTDCOUNTSTIMESTAMP(x) (*((U64 *)((uptr)(x)+9)))
|
||||
#define RTDCOUNTSIT(x,i) (((uptr *)((uptr)(x)+17))[i])
|
||||
#define RECORDDESCPARENT(x) (*((ptr *)((uptr)(x)+9)))
|
||||
#define RECORDDESCSIZE(x) (*((ptr *)((uptr)(x)+17)))
|
||||
#define RECORDDESCPM(x) (*((ptr *)((uptr)(x)+25)))
|
||||
#define RECORDDESCMPM(x) (*((ptr *)((uptr)(x)+33)))
|
||||
#define RECORDDESCNAME(x) (*((ptr *)((uptr)(x)+41)))
|
||||
#define RECORDDESCFLDS(x) (*((ptr *)((uptr)(x)+49)))
|
||||
#define RECORDDESCFLAGS(x) (*((ptr *)((uptr)(x)+57)))
|
||||
#define RECORDDESCUID(x) (*((ptr *)((uptr)(x)+65)))
|
||||
#define RECORDDESCCOUNTS(x) (*((ptr *)((uptr)(x)+73)))
|
||||
#define RECORDINSTTYPE(x) (*((ptr *)((uptr)(x)+1)))
|
||||
#define RECORDINSTIT(x,i) (((ptr *)((uptr)(x)+9))[i])
|
||||
#define CLOSCODE(p) ((ptr)((uptr)CLOSENTRY(p)-code_data_disp))
|
||||
#define CODEENTRYPOINT(x) ((ptr)((uptr)(x)+code_data_disp))
|
||||
#define SETCLOSCODE(p,x) (CLOSENTRY(p) = CODEENTRYPOINT(x))
|
||||
#define SYMCODE(p) ((ptr)((uptr)SYMPVAL(p)-code_data_disp))
|
||||
#define INITSYMCODE(p,x) (INITSYMPVAL(p) = CODEENTRYPOINT(x))
|
||||
#define SETSYMCODE(p,x) SETSYMPVAL(p,CODEENTRYPOINT(x))
|
||||
#define BIGLEN(x) ((iptr)((uptr)BIGTYPE(x) >> bignum_length_offset))
|
||||
#define BIGSIGN(x) ((BIGTYPE(x) & mask_bignum_sign) >> bignum_sign_offset)
|
||||
#define SETBIGLENANDSIGN(x,xl,xs) BIGTYPE(x) = (uptr)(xl) << bignum_length_offset | (xs) << bignum_sign_offset | type_bignum
|
||||
#define CLOSLEN(p) CODEFREE(CLOSCODE(p))
|
||||
#define GUARDIANOBJ(x) (*((ptr *)((uptr)(x)+0)))
|
||||
#define GUARDIANREP(x) (*((ptr *)((uptr)(x)+8)))
|
||||
#define GUARDIANTCONC(x) (*((ptr *)((uptr)(x)+16)))
|
||||
#define GUARDIANNEXT(x) (*((ptr *)((uptr)(x)+24)))
|
||||
#define INITGUARDIANOBJ(x) (*((ptr *)((uptr)(x)+0)))
|
||||
#define INITGUARDIANREP(x) (*((ptr *)((uptr)(x)+8)))
|
||||
#define INITGUARDIANTCONC(x) (*((ptr *)((uptr)(x)+16)))
|
||||
#define INITGUARDIANNEXT(x) (*((ptr *)((uptr)(x)+24)))
|
||||
#define FORWARDMARKER(x) (*((ptr *)((uptr)(x)+0)))
|
||||
#define FORWARDADDRESS(x) (*((ptr *)((uptr)(x)+8)))
|
||||
#define CACHEDSTACKSIZE(x) (*((iptr *)((uptr)(x)+0)))
|
||||
#define CACHEDSTACKLINK(x) (*((ptr *)((uptr)(x)+8)))
|
||||
#define RPHEADERFRAMESIZE(x) (*((iptr *)((uptr)(x)+16)))
|
||||
#define RPHEADERLIVEMASK(x) (*((ptr *)((uptr)(x)+0)))
|
||||
#define RPHEADERTOPLINK(x) (*((uptr *)((uptr)(x)+8)))
|
||||
|
||||
/* machine types */
|
||||
#define machine_type_names {"any", "i3le", "ti3le", "i3nt", "ti3nt", "i3fb", "ti3fb", "i3ob", "ti3ob", "i3osx", "ti3osx", "a6le", "ta6le", "a6osx", "ta6osx", "a6ob", "ta6ob", "a6s2", "ta6s2", "i3s2", "ti3s2", "a6fb", "ta6fb", "i3nb", "ti3nb", "a6nb", "ta6nb", "a6nt", "ta6nt", "i3qnx", "ti3qnx", "arm32le", "tarm32le", "ppc32le", "tppc32le"}
|
||||
|
||||
/* allocation-space names */
|
||||
#define alloc_space_names "new", "impure", "symbol", "port", "weakpr", "emph", "pure", "cont", "code", "p-tobj", "ip-rec", "data", "empty"
|
||||
|
||||
/* allocation-space characters */
|
||||
#define alloc_space_chars 'n', 'i', 'x', 'q', 'w', 'e', 'p', 'k', 'c', 'r', 's', 'd', 'e'
|
||||
|
||||
/* threads */
|
||||
#define THREADTC(x) (*((uptr *)((uptr)(x)+9)))
|
||||
|
||||
/* thread-context data */
|
||||
#define DSTBV(x) (*((ptr *)((uptr)(x)+680)))
|
||||
#define SRCBV(x) (*((ptr *)((uptr)(x)+688)))
|
||||
#define U(x) (*((ptr *)((uptr)(x)+352)))
|
||||
#define V(x) (*((ptr *)((uptr)(x)+360)))
|
||||
#define W(x) (*((ptr *)((uptr)(x)+368)))
|
||||
#define X(x) (*((ptr *)((uptr)(x)+376)))
|
||||
#define Y(x) (*((ptr *)((uptr)(x)+384)))
|
||||
#define AC0(x) (*((void* *)((uptr)(x)+40)))
|
||||
#define AC1(x) (*((void* *)((uptr)(x)+48)))
|
||||
#define ACTIVE(x) (*((I32 *)((uptr)(x)+308)))
|
||||
#define ALLOCCOUNTER(x) (*((U64 *)((uptr)(x)+664)))
|
||||
#define AP(x) (*((void* *)((uptr)(x)+80)))
|
||||
#define ARGREGS(x,i) (((void* *)((uptr)(x)+0))[i])
|
||||
#define BLOCKCOUNTER(x) (*((ptr *)((uptr)(x)+472)))
|
||||
#define CCHAIN(x) (*((ptr *)((uptr)(x)+288)))
|
||||
#define CODERANGESTOFLUSH(x) (*((ptr *)((uptr)(x)+296)))
|
||||
#define COMPILEPROFILE(x) (*((ptr *)((uptr)(x)+560)))
|
||||
#define COMPRESSFORMAT(x) (*((ptr *)((uptr)(x)+632)))
|
||||
#define COMPRESSLEVEL(x) (*((ptr *)((uptr)(x)+640)))
|
||||
#define CP(x) (*((void* *)((uptr)(x)+64)))
|
||||
#define CURRENTERROR(x) (*((ptr *)((uptr)(x)+464)))
|
||||
#define CURRENTINPUT(x) (*((ptr *)((uptr)(x)+448)))
|
||||
#define CURRENTMSO(x) (*((ptr *)((uptr)(x)+488)))
|
||||
#define CURRENTOUTPUT(x) (*((ptr *)((uptr)(x)+456)))
|
||||
#define DEFAULTRECORDEQUALPROCEDURE(x) (*((ptr *)((uptr)(x)+616)))
|
||||
#define DEFAULTRECORDHASHPROCEDURE(x) (*((ptr *)((uptr)(x)+624)))
|
||||
#define DISABLECOUNT(x) (*((ptr *)((uptr)(x)+408)))
|
||||
#define EAP(x) (*((void* *)((uptr)(x)+88)))
|
||||
#define ESP(x) (*((void* *)((uptr)(x)+72)))
|
||||
#define FXFIRSTBITSETBV(x) (*((ptr *)((uptr)(x)+512)))
|
||||
#define FXLENGTHBV(x) (*((ptr *)((uptr)(x)+504)))
|
||||
#define GENERATEINSPECTORINFORMATION(x) (*((ptr *)((uptr)(x)+568)))
|
||||
#define GENERATEPROCEDURESOURCEINFORMATION(x) (*((ptr *)((uptr)(x)+576)))
|
||||
#define GENERATEPROFILEFORMS(x) (*((ptr *)((uptr)(x)+584)))
|
||||
#define GUARDIANENTRIES(x) (*((ptr *)((uptr)(x)+280)))
|
||||
#define INSTRCOUNTER(x) (*((U64 *)((uptr)(x)+656)))
|
||||
#define KEYBOARDINTERRUPTPENDING(x) (*((ptr *)((uptr)(x)+432)))
|
||||
#define LZ4OUTBUFFER(x) (*((void* *)((uptr)(x)+648)))
|
||||
#define METALEVEL(x) (*((ptr *)((uptr)(x)+552)))
|
||||
#define NULLIMMUTABLEBYTEVECTOR(x) (*((ptr *)((uptr)(x)+536)))
|
||||
#define NULLIMMUTABLEFXVECTOR(x) (*((ptr *)((uptr)(x)+528)))
|
||||
#define NULLIMMUTABLESTRING(x) (*((ptr *)((uptr)(x)+544)))
|
||||
#define NULLIMMUTABLEVECTOR(x) (*((ptr *)((uptr)(x)+520)))
|
||||
#define OPTIMIZELEVEL(x) (*((ptr *)((uptr)(x)+592)))
|
||||
#define PARAMETERS(x) (*((ptr *)((uptr)(x)+672)))
|
||||
#define RANDOMSEED(x) (*((U32 *)((uptr)(x)+304)))
|
||||
#define REAL_EAP(x) (*((void* *)((uptr)(x)+144)))
|
||||
#define RET(x) (*((void* *)((uptr)(x)+96)))
|
||||
#define SCHEMESTACK(x) (*((void* *)((uptr)(x)+312)))
|
||||
#define SCHEMESTACKSIZE(x) (*((iptr *)((uptr)(x)+336)))
|
||||
#define SFD(x) (*((ptr *)((uptr)(x)+480)))
|
||||
#define SFP(x) (*((void* *)((uptr)(x)+56)))
|
||||
#define SIGNALINTERRUPTPENDING(x) (*((ptr *)((uptr)(x)+416)))
|
||||
#define SIGNALINTERRUPTQUEUE(x) (*((ptr *)((uptr)(x)+424)))
|
||||
#define SOMETHINGPENDING(x) (*((ptr *)((uptr)(x)+392)))
|
||||
#define STACKCACHE(x) (*((ptr *)((uptr)(x)+320)))
|
||||
#define STACKLINK(x) (*((ptr *)((uptr)(x)+328)))
|
||||
#define SUBSETMODE(x) (*((ptr *)((uptr)(x)+600)))
|
||||
#define SUPPRESSPRIMITIVEINLINING(x) (*((ptr *)((uptr)(x)+608)))
|
||||
#define TARGETMACHINE(x) (*((ptr *)((uptr)(x)+496)))
|
||||
#define TD(x) (*((void* *)((uptr)(x)+136)))
|
||||
#define THREADNO(x) (*((ptr *)((uptr)(x)+440)))
|
||||
#define TIMERTICKS(x) (*((ptr *)((uptr)(x)+400)))
|
||||
#define TRAP(x) (*((void* *)((uptr)(x)+104)))
|
||||
#define TS(x) (*((void* *)((uptr)(x)+128)))
|
||||
#define VIRTUALREGISTERS(x,i) (((ptr *)((uptr)(x)+152))[i])
|
||||
#define WINDERS(x) (*((ptr *)((uptr)(x)+344)))
|
||||
#define XP(x) (*((void* *)((uptr)(x)+112)))
|
||||
#define YP(x) (*((void* *)((uptr)(x)+120)))
|
||||
#define ARGREG(x,i) (((void* *)((uptr)(x)+0))[i])
|
||||
#define VIRTREG(x,i) (((ptr *)((uptr)(x)+152))[i])
|
||||
|
||||
/* library entries we access from C code */
|
||||
#define library_nonprocedure_code 152
|
||||
#define library_dounderflow 154
|
BIN
ta6ob/boot/ta6ob/kernel.o
Normal file
BIN
ta6ob/boot/ta6ob/kernel.o
Normal file
Binary file not shown.
BIN
ta6ob/boot/ta6ob/main.o
Normal file
BIN
ta6ob/boot/ta6ob/main.o
Normal file
Binary file not shown.
BIN
ta6ob/boot/ta6ob/petite.boot
Normal file
BIN
ta6ob/boot/ta6ob/petite.boot
Normal file
Binary file not shown.
2
ta6ob/boot/ta6ob/revision
Normal file
2
ta6ob/boot/ta6ob/revision
Normal file
|
@ -0,0 +1,2 @@
|
|||
43e68af625b650124dc0a2c2f22fac26a3449c24
|
||||
git
|
BIN
ta6ob/boot/ta6ob/scheme.boot
Normal file
BIN
ta6ob/boot/ta6ob/scheme.boot
Normal file
Binary file not shown.
245
ta6ob/boot/ta6ob/scheme.h
Normal file
245
ta6ob/boot/ta6ob/scheme.h
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* scheme.h for Chez Scheme Version 9.5.9 (ta6ob) */
|
||||
|
||||
/* Do not edit this file. It is automatically generated and */
|
||||
/* specifically tailored to the version of Chez Scheme named */
|
||||
/* above. Always be certain that you have the correct scheme.h */
|
||||
/* for the version of Chez Scheme you are using. */
|
||||
|
||||
/* Warning: Some macros may evaluate arguments more than once. */
|
||||
|
||||
/* Specify declaration of exports. */
|
||||
#ifdef _WIN32
|
||||
# if __cplusplus
|
||||
# ifdef SCHEME_IMPORT
|
||||
# define EXPORT extern "C" __declspec (dllimport)
|
||||
# elif SCHEME_STATIC
|
||||
# define EXPORT extern "C"
|
||||
# else
|
||||
# define EXPORT extern "C" __declspec (dllexport)
|
||||
# endif
|
||||
# else
|
||||
# ifdef SCHEME_IMPORT
|
||||
# define EXPORT extern __declspec (dllimport)
|
||||
# elif SCHEME_STATIC
|
||||
# define EXPORT extern
|
||||
# else
|
||||
# define EXPORT extern __declspec (dllexport)
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# if __cplusplus
|
||||
# define EXPORT extern "C"
|
||||
# else
|
||||
# define EXPORT extern
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Chez Scheme Version and machine type */
|
||||
#define VERSION "9.5.9"
|
||||
#define MACHINE_TYPE "ta6ob"
|
||||
|
||||
/* All Scheme objects are of type ptr. Type iptr and */
|
||||
/* uptr are signed and unsigned ints of the same size */
|
||||
/* as a ptr */
|
||||
typedef void * ptr;
|
||||
typedef long int iptr;
|
||||
typedef unsigned long int uptr;
|
||||
|
||||
/* String elements are 32-bit tagged char objects */
|
||||
typedef unsigned int string_char;
|
||||
|
||||
/* Bytevector elements are 8-bit unsigned "octets" */
|
||||
typedef unsigned char octet;
|
||||
|
||||
/* Type predicates */
|
||||
#define Sfixnump(x) (((uptr)(x)&0x7)==0x0)
|
||||
#define Scharp(x) (((uptr)(x)&0xFF)==0x16)
|
||||
#define Snullp(x) ((uptr)(x)==0x26)
|
||||
#define Seof_objectp(x) ((uptr)(x)==0x36)
|
||||
#define Sbwp_objectp(x) ((uptr)(x)==0x4E)
|
||||
#define Sbooleanp(x) (((uptr)(x)&0xF7)==0x6)
|
||||
#define Spairp(x) (((uptr)(x)&0x7)==0x1)
|
||||
#define Ssymbolp(x) (((uptr)(x)&0x7)==0x3)
|
||||
#define Sprocedurep(x) (((uptr)(x)&0x7)==0x5)
|
||||
#define Sflonump(x) (((uptr)(x)&0x7)==0x2)
|
||||
#define Svectorp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x0))
|
||||
#define Sfxvectorp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x3))
|
||||
#define Sbytevectorp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x3)==0x1))
|
||||
#define Sstringp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x2))
|
||||
#define Sbignump(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x1F)==0x6))
|
||||
#define Sboxp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x7F)==0xE))
|
||||
#define Sinexactnump(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
((uptr)((*((ptr *)((uptr)(x)+1))))==0x36))
|
||||
#define Sexactnump(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
((uptr)((*((ptr *)((uptr)(x)+1))))==0x56))
|
||||
#define Sratnump(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
((uptr)((*((ptr *)((uptr)(x)+1))))==0x16))
|
||||
#define Sinputportp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x1FF)==0x11E))
|
||||
#define Soutputportp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x2FF)==0x21E))
|
||||
#define Srecordp(x) ((((uptr)(x)&0x7)==0x7) &&\
|
||||
(((uptr)((*((ptr *)((uptr)(x)+1))))&0x7)==0x7))
|
||||
|
||||
/* Accessors */
|
||||
#define Sfixnum_value(x) ((iptr)(x)/8)
|
||||
#define Schar_value(x) ((string_char)((uptr)(x)>>8))
|
||||
#define Sboolean_value(x) ((x) != Sfalse)
|
||||
#define Scar(x) (*((ptr *)((uptr)(x)+7)))
|
||||
#define Scdr(x) (*((ptr *)((uptr)(x)+15)))
|
||||
#define Sflonum_value(x) (*((double *)((uptr)(x)+6)))
|
||||
#define Svector_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>4))
|
||||
#define Svector_ref(x,i) (((ptr *)((uptr)(x)+9))[i])
|
||||
#define Sfxvector_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>4))
|
||||
#define Sfxvector_ref(x,i) (((ptr *)((uptr)(x)+9))[i])
|
||||
#define Sbytevector_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>3))
|
||||
#define Sbytevector_u8_ref(x,i) (((octet *)((uptr)(x)+9))[i])
|
||||
/* Warning: Sbytevector_data(x) returns a pointer into x. */
|
||||
#define Sbytevector_data(x) &Sbytevector_u8_ref(x,0)
|
||||
#define Sstring_length(x) ((iptr)((uptr)(*((iptr *)((uptr)(x)+1)))>>4))
|
||||
#define Sstring_ref(x,i) Schar_value(((string_char *)((uptr)(x)+9))[i])
|
||||
#define Sunbox(x) (*((ptr *)((uptr)(x)+9)))
|
||||
EXPORT iptr Sinteger_value(ptr);
|
||||
#define Sunsigned_value(x) (uptr)Sinteger_value(x)
|
||||
EXPORT int Sinteger32_value(ptr);
|
||||
#define Sunsigned32_value(x) (unsigned int)Sinteger32_value(x)
|
||||
EXPORT long Sinteger64_value(ptr);
|
||||
#define Sunsigned64_value(x) (unsigned long)Sinteger64_value(x)
|
||||
|
||||
/* Mutators */
|
||||
EXPORT void Sset_box(ptr, ptr);
|
||||
EXPORT void Sset_car(ptr, ptr);
|
||||
EXPORT void Sset_cdr(ptr, ptr);
|
||||
#define Sstring_set(x,i,c) ((void)((((string_char *)((uptr)(x)+9))[i]) = (string_char)(uptr)Schar(c)))
|
||||
#define Sfxvector_set(x,i,n) ((void)(Sfxvector_ref(x,i) = (n)))
|
||||
#define Sbytevector_u8_set(x,i,n) ((void)(Sbytevector_u8_ref(x,i) = (n)))
|
||||
EXPORT void Svector_set(ptr, iptr, ptr);
|
||||
|
||||
/* Constructors */
|
||||
#define Sfixnum(x) ((ptr)(uptr)((x)*8))
|
||||
#define Schar(x) ((ptr)(uptr)((x)<<8|0x16))
|
||||
#define Snil ((ptr)0x26)
|
||||
#define Strue ((ptr)0xE)
|
||||
#define Sfalse ((ptr)0x6)
|
||||
#define Sboolean(x) ((x)?Strue:Sfalse)
|
||||
#define Sbwp_object ((ptr)0x4E)
|
||||
#define Seof_object ((ptr)0x36)
|
||||
#define Svoid ((ptr)0x3E)
|
||||
EXPORT ptr Scons(ptr, ptr);
|
||||
EXPORT ptr Sstring_to_symbol(const char *);
|
||||
EXPORT ptr Ssymbol_to_string(ptr);
|
||||
EXPORT ptr Sflonum(double);
|
||||
EXPORT ptr Smake_vector(iptr, ptr);
|
||||
EXPORT ptr Smake_fxvector(iptr, ptr);
|
||||
EXPORT ptr Smake_bytevector(iptr, int);
|
||||
EXPORT ptr Smake_string(iptr, int);
|
||||
EXPORT ptr Smake_uninitialized_string(iptr);
|
||||
EXPORT ptr Sstring(const char *);
|
||||
EXPORT ptr Sstring_of_length(const char *, iptr);
|
||||
EXPORT ptr Sstring_utf8(const char*, iptr);
|
||||
EXPORT ptr Sbox(ptr);
|
||||
EXPORT ptr Sinteger(iptr);
|
||||
EXPORT ptr Sunsigned(uptr);
|
||||
EXPORT ptr Sinteger32(int);
|
||||
EXPORT ptr Sunsigned32(unsigned int);
|
||||
EXPORT ptr Sinteger64(long);
|
||||
EXPORT ptr Sunsigned64(unsigned long);
|
||||
|
||||
/* Miscellaneous */
|
||||
EXPORT ptr Stop_level_value(ptr);
|
||||
EXPORT void Sset_top_level_value(ptr, ptr);
|
||||
EXPORT void Slock_object(ptr);
|
||||
EXPORT void Sunlock_object(ptr);
|
||||
EXPORT int Slocked_objectp(ptr);
|
||||
EXPORT void Sforeign_symbol(const char *, void *);
|
||||
EXPORT void Sregister_symbol(const char *, void *);
|
||||
|
||||
/* Support for calls into Scheme */
|
||||
EXPORT ptr Scall0(ptr);
|
||||
EXPORT ptr Scall1(ptr, ptr);
|
||||
EXPORT ptr Scall2(ptr, ptr, ptr);
|
||||
EXPORT ptr Scall3(ptr, ptr, ptr, ptr);
|
||||
EXPORT void Sinitframe(iptr);
|
||||
EXPORT void Sput_arg(iptr, ptr);
|
||||
EXPORT ptr Scall(ptr, iptr);
|
||||
/* Warning: Sforeign_callable_entry_point(x) returns a pointer into x. */
|
||||
#define Sforeign_callable_entry_point(x) ((void (*)(void))((uptr)(x)+65))
|
||||
#define Sforeign_callable_code_object(x) ((ptr)((uptr)(x)-65))
|
||||
|
||||
/* Customization support. */
|
||||
EXPORT const char * Skernel_version(void);
|
||||
EXPORT void Sretain_static_relocation(void);
|
||||
EXPORT void Sset_verbose(int);
|
||||
EXPORT void Sscheme_init(void (*)(void));
|
||||
EXPORT void Sregister_boot_file(const char *);
|
||||
EXPORT void Sregister_boot_file_fd(const char *, int fd);
|
||||
EXPORT void Sregister_heap_file(const char *);
|
||||
EXPORT void Scompact_heap(void);
|
||||
EXPORT void Ssave_heap(const char *, int);
|
||||
EXPORT void Sbuild_heap(const char *, void (*)(void));
|
||||
EXPORT void Senable_expeditor(const char *);
|
||||
EXPORT int Sscheme_start(int, const char *[]);
|
||||
EXPORT int Sscheme_script(const char *, int, const char *[]);
|
||||
EXPORT int Sscheme_program(const char *, int, const char *[]);
|
||||
EXPORT void Sscheme_deinit(void);
|
||||
|
||||
/* Thread support. */
|
||||
EXPORT int Sactivate_thread(void);
|
||||
EXPORT void Sdeactivate_thread(void);
|
||||
EXPORT int Sdestroy_thread(void);
|
||||
|
||||
/* Features. */
|
||||
#define FEATURE_ICONV
|
||||
#define FEATURE_EXPEDITOR
|
||||
#define FEATURE_PTHREADS
|
||||
|
||||
/* Locking macros. */
|
||||
#define INITLOCK(addr) \
|
||||
__asm__ __volatile__ ("movq $0, (%0)"\
|
||||
: \
|
||||
: "r" (addr) \
|
||||
: "memory")
|
||||
|
||||
#define SPINLOCK(addr) \
|
||||
__asm__ __volatile__ ("0:\n\t"\
|
||||
"movq $1, %%rax\n\t"\
|
||||
"xchgq (%0), %%rax\n\t"\
|
||||
"cmpq $0, %%rax\n\t"\
|
||||
"je 2f\n\t"\
|
||||
"1:\n\t"\
|
||||
"pause\n\t"\
|
||||
"cmpq $0, (%0)\n\t"\
|
||||
"je 0b\n\t"\
|
||||
"jmp 1b\n\t"\
|
||||
"2:"\
|
||||
: \
|
||||
: "r" (addr) \
|
||||
: "rax", "flags", "memory")
|
||||
|
||||
#define UNLOCK(addr) \
|
||||
__asm__ __volatile__ ("movq $0, (%0)"\
|
||||
: \
|
||||
: "r" (addr) \
|
||||
:"memory")
|
||||
|
||||
#define LOCKED_INCR(addr, ret) \
|
||||
__asm__ __volatile__ ("lock; incq (%1)\n\t"\
|
||||
"sete %b0\n\t"\
|
||||
"movzx %b0, %0\n\t"\
|
||||
: "=q" (ret) \
|
||||
: "r" (addr) \
|
||||
: "flags", "memory")
|
||||
|
||||
#define LOCKED_DECR(addr, ret) \
|
||||
__asm__ __volatile__ ("lock; decq (%1)\n\t"\
|
||||
"sete %b0\n\t"\
|
||||
"movzx %b0, %0\n\t"\
|
||||
: "=q" (ret) \
|
||||
: "r" (addr) \
|
||||
: "flags", "memory")
|
47
ta6ob/c/Makefile
Normal file
47
ta6ob/c/Makefile
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Mf-ta6ob
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
m = ta6ob
|
||||
Cpu = X86_64
|
||||
|
||||
mdinclude = -I/usr/local/include -I/usr/X11R6/include
|
||||
mdclib = -L/usr/local/lib -liconv -lm ${ncursesLib} -lpthread -lossp-uuid
|
||||
C = ${CC} ${CPPFLAGS} -Wpointer-arith -Werror -O2 -D_REENTRANT -pthread ${CFLAGS}
|
||||
o = o
|
||||
mdsrc = i3le.c
|
||||
mdobj = i3le.o
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
.c.o:
|
||||
$C -c -D${Cpu} -I${Include} ${zlibInc} ${LZ4Inc} ${mdinclude} $*.c
|
||||
|
||||
include Mf-base
|
||||
|
||||
${KernelO}: ${kernelobj} ${zlibDep} ${LZ4Dep}
|
||||
${LD} -r -X -o ${KernelO} ${kernelobj} ${zlibLib} ${LZ4Lib}
|
||||
|
||||
${KernelLib}: ${kernelobj}
|
||||
${AR} ${ARFLAGS} ${KernelLib} ${kernelobj}
|
||||
|
||||
${Scheme}: ${Kernel} ${KernelLinkDeps} ${Main}
|
||||
$C -rdynamic -Wl,--export-dynamic -Wl,-zwxneeded -o ${Scheme} ${Main} ${Kernel} ${mdclib} ${KernelLinkLibs} ${LDFLAGS}
|
||||
|
||||
../zlib/configure.log:
|
||||
(cd ../zlib; CFLAGS="${CFLAGS} -m64" ./configure --64)
|
||||
|
||||
../lz4/lib/liblz4.a: ${LZ4Sources}
|
||||
(cd ../lz4/lib; CFLAGS="${CFLAGS} -m64" ${MAKE} liblz4.a)
|
82
ta6ob/c/Mf-base
Normal file
82
ta6ob/c/Mf-base
Normal file
|
@ -0,0 +1,82 @@
|
|||
# Mf-base
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
include Mf-config
|
||||
export CC CFLAGS LD LDFLAGS
|
||||
|
||||
Include=../boot/$m
|
||||
PetiteBoot=../boot/$m/petite.boot
|
||||
SchemeBoot=../boot/$m/scheme.boot
|
||||
Main=../boot/$m/main.$o
|
||||
Scheme=../bin/$m/scheme
|
||||
|
||||
# One of these sets is referenced in Mf-config to select between
|
||||
# linking with kernel.o or libkernel.a
|
||||
|
||||
KernelO=../boot/$m/kernel.$o
|
||||
KernelOLinkDeps=
|
||||
KernelOLinkLibs=
|
||||
|
||||
KernelLib=../boot/$m/libkernel.a
|
||||
KernelLibLinkDeps=${zlibDep} ${LZ4Dep}
|
||||
KernelLibLinkLibs=${zlibLib} ${LZ4Lib}
|
||||
|
||||
kernelsrc=statics.c segment.c alloc.c symbol.c intern.c gcwrapper.c gc-011.c gc-ocd.c gc-oce.c\
|
||||
number.c schsig.c io.c new-io.c print.c fasl.c stats.c foreign.c prim.c prim5.c flushcache.c\
|
||||
schlib.c thread.c expeditor.c scheme.c compress-io.c
|
||||
|
||||
kernelobj=${kernelsrc:%.c=%.$o} ${mdobj}
|
||||
|
||||
kernelhdr=system.h types.h version.h globals.h externs.h segment.h gc.c sort.h thread.h config.h compress-io.h itest.c nocurses.h
|
||||
|
||||
mainsrc=main.c
|
||||
|
||||
mainobj:=${mainsrc:%.c=%.$o}
|
||||
|
||||
doit: ${Scheme}
|
||||
|
||||
source: ${kernelsrc} ${kernelhdr} ${mdsrc} ${mainsrc}
|
||||
|
||||
${Main}: ${mainobj}
|
||||
cp -p ${mainobj} ${Main}
|
||||
|
||||
rootsrc=$(shell cd ../../c; echo *)
|
||||
${rootsrc}:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
cp -p ../../c/$@ $@
|
||||
else
|
||||
ln -s ../../c/$@ $@
|
||||
endif
|
||||
|
||||
scheme.o: itest.c
|
||||
scheme.o main.o: config.h
|
||||
${kernelobj}: system.h types.h version.h externs.h globals.h segment.h thread.h sort.h compress-io.h nocurses.h
|
||||
${kernelobj}: ${Include}/equates.h ${Include}/scheme.h
|
||||
${mainobj}: ${Include}/scheme.h
|
||||
${kernelobj}: ${zlibHeaderDep} ${LZ4HeaderDep}
|
||||
gc-011.o gc-ocd.o gc-oce.o: gc.c
|
||||
|
||||
../zlib/zlib.h ../zlib/zconf.h: ../zlib/configure.log
|
||||
|
||||
../zlib/libz.a: ../zlib/configure.log
|
||||
(cd ../zlib; ${MAKE})
|
||||
|
||||
LZ4Sources=../lz4/lib/lz4.h ../lz4/lib/lz4frame.h \
|
||||
../lz4/lib/lz4.c ../lz4/lib/lz4frame.c \
|
||||
../lz4/lib/lz4hc.c ../lz4/lib/xxhash.c
|
||||
|
||||
clean:
|
||||
rm -f *.$o ${mdclean}
|
||||
rm -f Make.out
|
22
ta6ob/c/Mf-config
Normal file
22
ta6ob/c/Mf-config
Normal file
|
@ -0,0 +1,22 @@
|
|||
CC=gcc
|
||||
CPPFLAGS=
|
||||
CFLAGS=
|
||||
LD=ld
|
||||
LDFLAGS=
|
||||
AR=ar
|
||||
ARFLAGS=rc
|
||||
RANLIB=ranlib
|
||||
WINDRES=windres
|
||||
cursesLib=-lcurses
|
||||
ncursesLib=-lncurses
|
||||
zlibInc=-I../zlib
|
||||
LZ4Inc=-I../lz4/lib
|
||||
zlibDep=../zlib/libz.a
|
||||
LZ4Dep=../lz4/lib/liblz4.a
|
||||
zlibLib=../zlib/libz.a
|
||||
LZ4Lib=../lz4/lib/liblz4.a
|
||||
zlibHeaderDep=../zlib/zconf.h ../zlib/zlib.h
|
||||
LZ4HeaderDep=../lz4/lib/lz4.h ../lz4/lib/lz4frame.h
|
||||
Kernel=${KernelO}
|
||||
KernelLinkDeps=${KernelOLinkDeps}
|
||||
KernelLinkLibs=${KernelOLinkLibs}
|
47
ta6ob/c/Mf-ta6ob
Normal file
47
ta6ob/c/Mf-ta6ob
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Mf-ta6ob
|
||||
# Copyright 1984-2017 Cisco Systems, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
m = ta6ob
|
||||
Cpu = X86_64
|
||||
|
||||
mdinclude = -I/usr/local/include -I/usr/X11R6/include
|
||||
mdclib = -L/usr/local/lib -liconv -lm ${ncursesLib} -lpthread -lossp-uuid
|
||||
C = ${CC} ${CPPFLAGS} -Wpointer-arith -Werror -O2 -D_REENTRANT -pthread ${CFLAGS}
|
||||
o = o
|
||||
mdsrc = i3le.c
|
||||
mdobj = i3le.o
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .c .o
|
||||
|
||||
.c.o:
|
||||
$C -c -D${Cpu} -I${Include} ${zlibInc} ${LZ4Inc} ${mdinclude} $*.c
|
||||
|
||||
include Mf-base
|
||||
|
||||
${KernelO}: ${kernelobj} ${zlibDep} ${LZ4Dep}
|
||||
${LD} -r -X -o ${KernelO} ${kernelobj} ${zlibLib} ${LZ4Lib}
|
||||
|
||||
${KernelLib}: ${kernelobj}
|
||||
${AR} ${ARFLAGS} ${KernelLib} ${kernelobj}
|
||||
|
||||
${Scheme}: ${Kernel} ${KernelLinkDeps} ${Main}
|
||||
$C -rdynamic -Wl,--export-dynamic -Wl,-zwxneeded -o ${Scheme} ${Main} ${Kernel} ${mdclib} ${KernelLinkLibs} ${LDFLAGS}
|
||||
|
||||
../zlib/configure.log:
|
||||
(cd ../zlib; CFLAGS="${CFLAGS} -m64" ./configure --64)
|
||||
|
||||
../lz4/lib/liblz4.a: ${LZ4Sources}
|
||||
(cd ../lz4/lib; CFLAGS="${CFLAGS} -m64" ${MAKE} liblz4.a)
|
862
ta6ob/c/alloc.c
Normal file
862
ta6ob/c/alloc.c
Normal file
|
@ -0,0 +1,862 @@
|
|||
/* alloc.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* locally defined functions */
|
||||
static void maybe_fire_collector(void);
|
||||
|
||||
void S_alloc_init(void) {
|
||||
ISPC s; IGEN g; UINT i;
|
||||
|
||||
if (S_boot_time) {
|
||||
/* reset the allocation tables */
|
||||
for (g = 0; g <= static_generation; g++) {
|
||||
S_G.bytes_of_generation[g] = 0;
|
||||
for (s = 0; s <= max_real_space; s++) {
|
||||
S_G.base_loc[g][s] = FIX(0);
|
||||
S_G.first_loc[g][s] = FIX(0);
|
||||
S_G.next_loc[g][s] = FIX(0);
|
||||
S_G.bytes_left[g][s] = 0;
|
||||
S_G.bytes_of_space[g][s] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the dirty-segment lists. */
|
||||
for (i = 0; i < DIRTY_SEGMENT_LISTS; i += 1) {
|
||||
S_G.dirty_segments[i] = NULL;
|
||||
}
|
||||
|
||||
S_G.collect_trip_bytes = default_collect_trip_bytes;
|
||||
S_G.g0_bytes_after_last_gc = 0;
|
||||
|
||||
/* set to final value in prim.c when known */
|
||||
S_protect(&S_G.nonprocedure_code);
|
||||
S_G.nonprocedure_code = FIX(0);
|
||||
|
||||
S_protect(&S_G.null_vector);
|
||||
find_room(space_new, 0, type_typed_object, size_vector(0), S_G.null_vector);
|
||||
VECTTYPE(S_G.null_vector) = (0 << vector_length_offset) | type_vector;
|
||||
|
||||
S_protect(&S_G.null_fxvector);
|
||||
find_room(space_new, 0, type_typed_object, size_fxvector(0), S_G.null_fxvector);
|
||||
FXVECTOR_TYPE(S_G.null_fxvector) = (0 << fxvector_length_offset) | type_fxvector;
|
||||
|
||||
S_protect(&S_G.null_bytevector);
|
||||
find_room(space_new, 0, type_typed_object, size_bytevector(0), S_G.null_bytevector);
|
||||
BYTEVECTOR_TYPE(S_G.null_bytevector) = (0 << bytevector_length_offset) | type_bytevector;
|
||||
|
||||
S_protect(&S_G.null_string);
|
||||
find_room(space_new, 0, type_typed_object, size_string(0), S_G.null_string);
|
||||
STRTYPE(S_G.null_string) = (0 << string_length_offset) | type_string;
|
||||
}
|
||||
}
|
||||
|
||||
void S_protect(ptr *p) {
|
||||
if (S_G.protect_next > max_protected)
|
||||
S_error_abort("max_protected constant too small");
|
||||
*p = snil;
|
||||
S_G.protected[S_G.protect_next++] = p;
|
||||
}
|
||||
|
||||
/* S_reset_scheme_stack is always called with mutex */
|
||||
void S_reset_scheme_stack(ptr tc, iptr n) {
|
||||
ptr *x; iptr m;
|
||||
|
||||
/* we allow less than one_shot_headroom here for no truly justifiable
|
||||
reason */
|
||||
n = ptr_align(n + (one_shot_headroom >> 1));
|
||||
|
||||
x = &STACKCACHE(tc);
|
||||
for (;;) {
|
||||
if (*x == snil) {
|
||||
if (n < default_stack_size) n = default_stack_size;
|
||||
/* stacks are untyped objects */
|
||||
find_room(space_new, 0, typemod, n, SCHEMESTACK(tc));
|
||||
break;
|
||||
}
|
||||
if ((m = CACHEDSTACKSIZE(*x)) >= n) {
|
||||
n = m;
|
||||
SCHEMESTACK(tc) = *x;
|
||||
/* if we decide to leave KEEPSMALLPUPPIES undefined permanently, we should
|
||||
rewrite this code to remove the indirect on x */
|
||||
/* #define KEEPSMALLPUPPIES */
|
||||
#ifdef KEEPSMALLPUPPIES
|
||||
*x = CACHEDSTACKLINK(*x);
|
||||
#else
|
||||
STACKCACHE(tc) = CACHEDSTACKLINK(*x);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
x = &CACHEDSTACKLINK(*x);
|
||||
}
|
||||
SCHEMESTACKSIZE(tc) = n;
|
||||
ESP(tc) = (ptr)((uptr)SCHEMESTACK(tc) + n - stack_slop);
|
||||
SFP(tc) = (ptr)SCHEMESTACK(tc);
|
||||
}
|
||||
|
||||
ptr S_compute_bytes_allocated(ptr xg, ptr xs) {
|
||||
ptr tc = get_thread_context();
|
||||
ISPC s, smax, smin; IGEN g, gmax, gmin;
|
||||
uptr n;
|
||||
|
||||
gmin = (IGEN)UNFIX(xg);
|
||||
if (gmin < 0) {
|
||||
gmin = 0;
|
||||
gmax = static_generation;
|
||||
} else if (gmin == S_G.new_max_nonstatic_generation) {
|
||||
/* include virtual inhabitents too */
|
||||
gmax = S_G.max_nonstatic_generation;
|
||||
} else {
|
||||
gmax = gmin;
|
||||
}
|
||||
|
||||
smin = (ISPC)(UNFIX(xs));
|
||||
smax = smin < 0 ? max_real_space : smin;
|
||||
smin = smin < 0 ? 0 : smin;
|
||||
|
||||
n = 0;
|
||||
|
||||
g = gmin;
|
||||
while (g <= gmax) {
|
||||
for (s = smin; s <= smax; s++) {
|
||||
ptr next_loc = S_G.next_loc[g][s];
|
||||
/* add in bytes previously recorded */
|
||||
n += S_G.bytes_of_space[g][s];
|
||||
/* add in bytes in active segments */
|
||||
if (next_loc != FIX(0))
|
||||
n += (char *)next_loc - (char *)S_G.base_loc[g][s];
|
||||
}
|
||||
if (g == S_G.max_nonstatic_generation)
|
||||
g = static_generation;
|
||||
else
|
||||
g += 1;
|
||||
}
|
||||
|
||||
/* subtract off bytes not allocated */
|
||||
if (gmin == 0 && smin <= space_new && space_new <= smax)
|
||||
n -= (uptr)REAL_EAP(tc) - (uptr)AP(tc);
|
||||
|
||||
return Sunsigned(n);
|
||||
}
|
||||
|
||||
static void maybe_fire_collector(void) {
|
||||
if (S_G.bytes_of_generation[0] - S_G.g0_bytes_after_last_gc >= S_G.collect_trip_bytes)
|
||||
S_fire_collector();
|
||||
}
|
||||
|
||||
/* find_more_room
|
||||
* S_find_more_room is called from the macro find_room when
|
||||
* the current segment is too full to fit the allocation.
|
||||
*
|
||||
* A forward_marker followed by a pointer to
|
||||
* the newly obtained segment is placed at next_loc to show
|
||||
* gc where the end of this segment is and where the next
|
||||
* segment of this type resides. Allocation occurs from the
|
||||
* beginning of the newly obtained segment. The need for the
|
||||
* eos marker explains the (2 * ptr_bytes) byte factor in
|
||||
* S_find_more_room.
|
||||
*/
|
||||
/* S_find_more_room is always called with mutex */
|
||||
ptr S_find_more_room(ISPC s, IGEN g, iptr n, ptr old) {
|
||||
iptr nsegs, seg;
|
||||
ptr new;
|
||||
|
||||
S_pants_down += 1;
|
||||
|
||||
nsegs = (uptr)(n + 2 * ptr_bytes + bytes_per_segment - 1) >> segment_offset_bits;
|
||||
|
||||
/* block requests to minimize fragmentation and improve cache locality */
|
||||
if (s == space_code && nsegs < 16) nsegs = 16;
|
||||
|
||||
seg = S_find_segments(s, g, nsegs);
|
||||
new = build_ptr(seg, 0);
|
||||
|
||||
if (old == FIX(0)) {
|
||||
/* first object of this space */
|
||||
S_G.first_loc[g][s] = new;
|
||||
} else {
|
||||
uptr bytes = (char *)old - (char *)S_G.base_loc[g][s];
|
||||
/* increment bytes_allocated by the closed-off partial segment */
|
||||
S_G.bytes_of_space[g][s] += bytes;
|
||||
S_G.bytes_of_generation[g] += bytes;
|
||||
/* lay down an end-of-segment marker */
|
||||
*(ptr*)old = forward_marker;
|
||||
*((ptr*)old + 1) = new;
|
||||
}
|
||||
|
||||
/* base address of current block of segments to track amount of allocation */
|
||||
S_G.base_loc[g][s] = new;
|
||||
|
||||
S_G.next_loc[g][s] = (ptr)((uptr)new + n);
|
||||
S_G.bytes_left[g][s] = (nsegs * bytes_per_segment - n) - 2 * ptr_bytes;
|
||||
|
||||
if (g == 0 && S_pants_down == 1) maybe_fire_collector();
|
||||
|
||||
S_pants_down -= 1;
|
||||
return new;
|
||||
}
|
||||
|
||||
/* S_reset_allocation_pointer is always called with mutex */
|
||||
/* We always allocate exactly one segment for the allocation area, since
|
||||
we can get into hot water with formerly locked objects, specifically
|
||||
symbols and impure records, that cross segment boundaries. This allows
|
||||
us to maintain the invariant that no object crosses a segment boundary
|
||||
unless it starts on a segment boundary (and is thus at least one
|
||||
segment long). NB. This invariant does not apply to code objects
|
||||
since we grab large blocks of segments for them.
|
||||
*/
|
||||
|
||||
void S_reset_allocation_pointer(ptr tc) {
|
||||
iptr seg;
|
||||
|
||||
S_pants_down += 1;
|
||||
|
||||
seg = S_find_segments(space_new, 0, 1);
|
||||
|
||||
/* NB: if allocate_segments didn't already ensure we don't use the last segment
|
||||
of memory, we'd have to reject it here so cp2-alloc can avoid a carry check for
|
||||
small allocation requests, using something like this:
|
||||
|
||||
if (seg == (((uptr)1 << (ptr_bits - segment_offset_bits)) - 1))
|
||||
seg = S_find_segments(space_new, 0, 1);
|
||||
*/
|
||||
|
||||
S_G.bytes_of_space[0][space_new] += bytes_per_segment;
|
||||
S_G.bytes_of_generation[0] += bytes_per_segment;
|
||||
|
||||
if (S_pants_down == 1) maybe_fire_collector();
|
||||
|
||||
AP(tc) = build_ptr(seg, 0);
|
||||
REAL_EAP(tc) = EAP(tc) = (ptr)((uptr)AP(tc) + bytes_per_segment);
|
||||
|
||||
S_pants_down -= 1;
|
||||
}
|
||||
|
||||
|
||||
FORCEINLINE void mark_segment_dirty(seginfo *si, IGEN from_g, IGEN to_g) {
|
||||
IGEN old_to_g = si->min_dirty_byte;
|
||||
if (to_g < old_to_g) {
|
||||
seginfo **pointer_to_first, *oldfirst;
|
||||
if (old_to_g != 0xff) {
|
||||
seginfo *next = si->dirty_next, **prev = si->dirty_prev;
|
||||
/* presently on some other list, so remove */
|
||||
*prev = next;
|
||||
if (next != NULL) next->dirty_prev = prev;
|
||||
}
|
||||
oldfirst = *(pointer_to_first = &DirtySegments(from_g, to_g));
|
||||
*pointer_to_first = si;
|
||||
si->dirty_prev = pointer_to_first;
|
||||
si->dirty_next = oldfirst;
|
||||
if (oldfirst != NULL) oldfirst->dirty_prev = &si->dirty_next;
|
||||
si->min_dirty_byte = to_g;
|
||||
}
|
||||
}
|
||||
|
||||
void S_dirty_set(ptr *loc, ptr x) {
|
||||
*loc = x;
|
||||
if (!Sfixnump(x)) {
|
||||
seginfo *si = SegInfo(addr_get_segment(loc));
|
||||
IGEN from_g = si->generation;
|
||||
if (from_g != 0) {
|
||||
si->dirty_bytes[((uptr)loc >> card_offset_bits) & ((1 << segment_card_offset_bits) - 1)] = 0;
|
||||
mark_segment_dirty(si, from_g, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void S_mark_card_dirty(uptr card, IGEN to_g) {
|
||||
uptr loc = card << card_offset_bits;
|
||||
uptr seg = addr_get_segment(loc);
|
||||
seginfo *si = SegInfo(seg);
|
||||
uptr cardno = card & ((1 << segment_card_offset_bits) - 1);
|
||||
if (to_g < si->dirty_bytes[cardno]) {
|
||||
si->dirty_bytes[cardno] = to_g;
|
||||
mark_segment_dirty(si, si->generation, to_g);
|
||||
}
|
||||
}
|
||||
|
||||
/* scan remembered set from P to ENDP, transferring to dirty vector */
|
||||
void S_scan_dirty(ptr **p, ptr **endp) {
|
||||
uptr this, last;
|
||||
|
||||
last = 0;
|
||||
|
||||
while (p < endp) {
|
||||
ptr *loc = *p;
|
||||
/* whether building s directory or running UXLB code, the most
|
||||
common situations are that *loc is a fixnum, this == last, or loc
|
||||
is in generation 0. the generated code no longer adds elements
|
||||
to the remembered set if the RHS val is a fixnum. the other
|
||||
checks we do here. we don't bother looking for *loc being an
|
||||
immediate or outside the heap, nor for the generation of *loc
|
||||
being the same or older than the generation of loc, since these
|
||||
don't seem to weed out many dirty writes, and we don't want to
|
||||
waste time here on fruitless memory reads and comparisions */
|
||||
if ((this = (uptr)loc >> card_offset_bits) != last) {
|
||||
seginfo *si = SegInfo(addr_get_segment(loc));
|
||||
IGEN from_g = si->generation;
|
||||
if (from_g != 0) {
|
||||
si->dirty_bytes[((uptr)loc >> card_offset_bits) & ((1 << segment_card_offset_bits) - 1)] = 0;
|
||||
if (this >> segment_card_offset_bits != last >> segment_card_offset_bits) mark_segment_dirty(si, from_g, 0);
|
||||
}
|
||||
last = this;
|
||||
}
|
||||
p += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* S_scan_remembered_set is called from generated machine code when there
|
||||
* is insufficient room for a remembered set addition.
|
||||
*/
|
||||
|
||||
void S_scan_remembered_set(void) {
|
||||
ptr tc = get_thread_context();
|
||||
uptr ap, eap, real_eap;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
ap = (uptr)AP(tc);
|
||||
eap = (uptr)EAP(tc);
|
||||
real_eap = (uptr)REAL_EAP(tc);
|
||||
|
||||
S_scan_dirty((ptr **)eap, (ptr **)real_eap);
|
||||
eap = real_eap;
|
||||
|
||||
if (eap - ap > alloc_waste_maximum) {
|
||||
AP(tc) = (ptr)ap;
|
||||
EAP(tc) = (ptr)eap;
|
||||
} else {
|
||||
uptr bytes = eap - ap;
|
||||
S_G.bytes_of_space[0][space_new] -= bytes;
|
||||
S_G.bytes_of_generation[0] -= bytes;
|
||||
S_reset_allocation_pointer(tc);
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
}
|
||||
|
||||
/* S_get_more_room is called from generated machine code when there is
|
||||
* insufficient room for an allocation. ap has already been incremented
|
||||
* by the size of the object and xp is a (typed) pointer to the value of
|
||||
* ap before the allocation attempt. xp must be set to a new object of
|
||||
* the appropriate type and size.
|
||||
*/
|
||||
|
||||
void S_get_more_room(void) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr xp; uptr ap, type, size;
|
||||
|
||||
xp = XP(tc);
|
||||
if ((type = TYPEBITS(xp)) == 0) type = typemod;
|
||||
ap = (uptr)UNTYPE(xp, type);
|
||||
size = (uptr)((iptr)AP(tc) - (iptr)ap);
|
||||
|
||||
XP(tc) = S_get_more_room_help(tc, ap, type, size);
|
||||
}
|
||||
|
||||
ptr S_get_more_room_help(ptr tc, uptr ap, uptr type, uptr size) {
|
||||
ptr x; uptr eap, real_eap;
|
||||
|
||||
eap = (uptr)EAP(tc);
|
||||
real_eap = (uptr)REAL_EAP(tc);
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
S_scan_dirty((ptr **)eap, (ptr **)real_eap);
|
||||
eap = real_eap;
|
||||
|
||||
if (eap - ap >= size) {
|
||||
x = TYPE(ap, type);
|
||||
ap += size;
|
||||
if (eap - ap > alloc_waste_maximum) {
|
||||
AP(tc) = (ptr)ap;
|
||||
EAP(tc) = (ptr)eap;
|
||||
} else {
|
||||
uptr bytes = eap - ap;
|
||||
S_G.bytes_of_space[0][space_new] -= bytes;
|
||||
S_G.bytes_of_generation[0] -= bytes;
|
||||
S_reset_allocation_pointer(tc);
|
||||
}
|
||||
} else if (eap - ap > alloc_waste_maximum) {
|
||||
AP(tc) = (ptr)ap;
|
||||
EAP(tc) = (ptr)eap;
|
||||
find_room(space_new, 0, type, size, x);
|
||||
} else {
|
||||
uptr bytes = eap - ap;
|
||||
S_G.bytes_of_space[0][space_new] -= bytes;
|
||||
S_G.bytes_of_generation[0] -= bytes;
|
||||
S_reset_allocation_pointer(tc);
|
||||
ap = (uptr)AP(tc);
|
||||
if (size + alloc_waste_maximum <= (uptr)EAP(tc) - ap) {
|
||||
x = TYPE(ap, type);
|
||||
AP(tc) = (ptr)(ap + size);
|
||||
} else {
|
||||
find_room(space_new, 0, type, size, x);
|
||||
}
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* S_cons_in is always called with mutex */
|
||||
ptr S_cons_in(ISPC s, IGEN g, ptr car, ptr cdr) {
|
||||
ptr p;
|
||||
|
||||
find_room(s, g, type_pair, size_pair, p);
|
||||
INITCAR(p) = car;
|
||||
INITCDR(p) = cdr;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr Scons(ptr car, ptr cdr) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_pair, size_pair, p);
|
||||
INITCAR(p) = car;
|
||||
INITCDR(p) = cdr;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr Sbox(ptr ref) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_typed_object, size_box, p);
|
||||
BOXTYPE(p) = type_box;
|
||||
INITBOXREF(p) = ref;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_symbol(ptr name) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_symbol, size_symbol, p);
|
||||
/* changes here should be reflected in the oblist collection code in gc.c */
|
||||
INITSYMVAL(p) = sunbound;
|
||||
INITSYMCODE(p,S_G.nonprocedure_code);
|
||||
INITSYMPLIST(p) = snil;
|
||||
INITSYMSPLIST(p) = snil;
|
||||
INITSYMNAME(p) = name;
|
||||
INITSYMHASH(p) = Sfalse;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_rational(ptr n, ptr d) {
|
||||
if (d == FIX(1)) return n;
|
||||
else {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_typed_object, size_ratnum, p);
|
||||
RATTYPE(p) = type_ratnum;
|
||||
RATNUM(p) = n;
|
||||
RATDEN(p) = d;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
ptr S_tlc(ptr keyval, ptr ht, ptr next) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_typed_object, size_tlc, p);
|
||||
TLCTYPE(p) = type_tlc;
|
||||
INITTLCKEYVAL(p) = keyval;
|
||||
INITTLCHT(p) = ht;
|
||||
INITTLCNEXT(p) = next;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* S_vector_in is always called with mutex */
|
||||
ptr S_vector_in(ISPC s, IGEN g, iptr n) {
|
||||
ptr p; iptr d;
|
||||
|
||||
if (n == 0) return S_G.null_vector;
|
||||
|
||||
if ((uptr)n >= maximum_vector_length)
|
||||
S_error("", "invalid vector size request");
|
||||
|
||||
d = size_vector(n);
|
||||
/* S_vector_in always called with mutex */
|
||||
find_room(s, g, type_typed_object, d, p);
|
||||
VECTTYPE(p) = (n << vector_length_offset) | type_vector;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_vector(iptr n) {
|
||||
ptr tc;
|
||||
ptr p; iptr d;
|
||||
|
||||
if (n == 0) return S_G.null_vector;
|
||||
|
||||
if ((uptr)n >= maximum_vector_length)
|
||||
S_error("", "invalid vector size request");
|
||||
|
||||
tc = get_thread_context();
|
||||
|
||||
d = size_vector(n);
|
||||
thread_find_room(tc, type_typed_object, d, p);
|
||||
VECTTYPE(p) = (n << vector_length_offset) | type_vector;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_fxvector(iptr n) {
|
||||
ptr tc;
|
||||
ptr p; iptr d;
|
||||
|
||||
if (n == 0) return S_G.null_fxvector;
|
||||
|
||||
if ((uptr)n > (uptr)maximum_fxvector_length)
|
||||
S_error("", "invalid fxvector size request");
|
||||
|
||||
tc = get_thread_context();
|
||||
|
||||
d = size_fxvector(n);
|
||||
thread_find_room(tc, type_typed_object, d, p);
|
||||
FXVECTOR_TYPE(p) = (n << fxvector_length_offset) | type_fxvector;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_bytevector(iptr n) {
|
||||
ptr tc;
|
||||
ptr p; iptr d;
|
||||
|
||||
if (n == 0) return S_G.null_bytevector;
|
||||
|
||||
if ((uptr)n > (uptr)maximum_bytevector_length)
|
||||
S_error("", "invalid bytevector size request");
|
||||
|
||||
tc = get_thread_context();
|
||||
|
||||
d = size_bytevector(n);
|
||||
thread_find_room(tc, type_typed_object, d, p);
|
||||
BYTEVECTOR_TYPE(p) = (n << bytevector_length_offset) | type_bytevector;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_null_immutable_vector(void) {
|
||||
ptr v;
|
||||
find_room(space_new, 0, type_typed_object, size_vector(0), v);
|
||||
VECTTYPE(v) = (0 << vector_length_offset) | type_vector | vector_immutable_flag;
|
||||
return v;
|
||||
}
|
||||
|
||||
ptr S_null_immutable_fxvector(void) {
|
||||
ptr v;
|
||||
find_room(space_new, 0, type_typed_object, size_fxvector(0), v);
|
||||
VECTTYPE(v) = (0 << fxvector_length_offset) | type_fxvector | fxvector_immutable_flag;
|
||||
return v;
|
||||
}
|
||||
|
||||
ptr S_null_immutable_bytevector(void) {
|
||||
ptr v;
|
||||
find_room(space_new, 0, type_typed_object, size_bytevector(0), v);
|
||||
VECTTYPE(v) = (0 << bytevector_length_offset) | type_bytevector | bytevector_immutable_flag;
|
||||
return v;
|
||||
}
|
||||
|
||||
ptr S_null_immutable_string(void) {
|
||||
ptr v;
|
||||
find_room(space_new, 0, type_typed_object, size_string(0), v);
|
||||
VECTTYPE(v) = (0 << string_length_offset) | type_string | string_immutable_flag;
|
||||
return v;
|
||||
}
|
||||
|
||||
ptr S_record(iptr n) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_typed_object, n, p);
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_closure(ptr cod, iptr n) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p; iptr d;
|
||||
|
||||
d = size_closure(n);
|
||||
thread_find_room(tc, type_closure, d, p);
|
||||
CLOSENTRY(p) = cod;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* S_mkcontinuation is always called with mutex */
|
||||
ptr S_mkcontinuation(ISPC s, IGEN g, ptr nuate, ptr stack, iptr length, iptr clength,
|
||||
ptr link, ptr ret, ptr winders) {
|
||||
ptr p;
|
||||
|
||||
find_room(s, g, type_closure, size_continuation, p);
|
||||
CLOSENTRY(p) = nuate;
|
||||
CONTSTACK(p) = stack;
|
||||
CONTLENGTH(p) = length;
|
||||
CONTCLENGTH(p) = clength;
|
||||
CONTLINK(p) = link;
|
||||
CONTRET(p) = ret;
|
||||
CONTWINDERS(p) = winders;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr Sflonum(double x) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_flonum, size_flonum, p);
|
||||
FLODAT(p) = x;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_inexactnum(double rp, double ip) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_typed_object, size_inexactnum, p);
|
||||
INEXACTNUM_TYPE(p) = type_inexactnum;
|
||||
INEXACTNUM_REAL_PART(p) = rp;
|
||||
INEXACTNUM_IMAG_PART(p) = ip;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* S_thread is always called with mutex */
|
||||
ptr S_thread(ptr xtc) {
|
||||
ptr p;
|
||||
|
||||
/* don't use thread_find_room since we may be building the current thread */
|
||||
find_room(space_new, 0, type_typed_object, size_thread, p);
|
||||
TYPEFIELD(p) = (ptr)type_thread;
|
||||
THREADTC(p) = (uptr)xtc;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_exactnum(ptr a, ptr b) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p;
|
||||
|
||||
thread_find_room(tc, type_typed_object, size_exactnum, p);
|
||||
EXACTNUM_TYPE(p) = type_exactnum;
|
||||
EXACTNUM_REAL_PART(p) = a;
|
||||
EXACTNUM_IMAG_PART(p) = b;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* S_string returns a new string of length n. If s is not NULL, it is
|
||||
* copied into the new string. If n < 0, then s must be non-NULL,
|
||||
* and the length of s (by strlen) determines the length of the string */
|
||||
ptr S_string(const char *s, iptr n) {
|
||||
ptr tc;
|
||||
ptr p; iptr d;
|
||||
iptr i;
|
||||
|
||||
if (n < 0) n = strlen(s);
|
||||
|
||||
if (n == 0) return S_G.null_string;
|
||||
|
||||
if ((uptr)n > (uptr)maximum_string_length)
|
||||
S_error("", "invalid string size request");
|
||||
|
||||
tc = get_thread_context();
|
||||
|
||||
d = size_string(n);
|
||||
thread_find_room(tc, type_typed_object, d, p);
|
||||
STRTYPE(p) = (n << string_length_offset) | type_string;
|
||||
|
||||
/* fill the string with valid characters */
|
||||
i = 0;
|
||||
|
||||
/* first copy input string, if any */
|
||||
if (s != (char *)NULL) {
|
||||
while (i != n && *s != 0) {
|
||||
Sstring_set(p, i, *s++);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* fill remaining slots with nul */
|
||||
while (i != n) {
|
||||
Sstring_set(p, i, 0);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr Sstring_utf8(const char *s, iptr n) {
|
||||
const char* u8;
|
||||
iptr cc, d, i, n8;
|
||||
ptr p, tc;
|
||||
|
||||
if (n < 0) n = strlen(s);
|
||||
|
||||
if (n == 0) return S_G.null_string;
|
||||
|
||||
/* determine code point count cc */
|
||||
u8 = s;
|
||||
n8 = n;
|
||||
cc = 0;
|
||||
while (n8 > 0) {
|
||||
unsigned char b1 = *(const unsigned char*)u8++;
|
||||
n8--;
|
||||
cc++;
|
||||
if ((b1 & 0x80) == 0)
|
||||
;
|
||||
else if ((b1 & 0x40) == 0)
|
||||
;
|
||||
else if ((b1 & 0x20) == 0) {
|
||||
if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) {
|
||||
u8++;
|
||||
n8--;
|
||||
}
|
||||
} else if ((b1 & 0x10) == 0) {
|
||||
if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) {
|
||||
u8++;
|
||||
n8--;
|
||||
if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) {
|
||||
u8++;
|
||||
n8--;
|
||||
}
|
||||
}
|
||||
} else if ((b1 & 0x08) == 0) {
|
||||
if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) {
|
||||
u8++;
|
||||
n8--;
|
||||
if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) {
|
||||
u8++;
|
||||
n8--;
|
||||
if ((n8 >= 1) && ((*u8 & 0xc0) == 0x80)) {
|
||||
u8++;
|
||||
n8--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((uptr)cc > (uptr)maximum_string_length)
|
||||
S_error("", "invalid string size request");
|
||||
|
||||
tc = get_thread_context();
|
||||
d = size_string(cc);
|
||||
thread_find_room(tc, type_typed_object, d, p);
|
||||
STRTYPE(p) = (cc << string_length_offset) | type_string;
|
||||
|
||||
/* fill the string */
|
||||
u8 = s;
|
||||
n8 = n;
|
||||
i = 0;
|
||||
while (n8 > 0) {
|
||||
unsigned char b1 = *u8++;
|
||||
int c = 0xfffd;
|
||||
n8--;
|
||||
if ((b1 & 0x80) == 0)
|
||||
c = b1;
|
||||
else if ((b1 & 0x40) == 0)
|
||||
;
|
||||
else if ((b1 & 0x20) == 0) {
|
||||
unsigned char b2;
|
||||
if ((n8 >= 1) && (((b2 = *u8) & 0xc0) == 0x80)) {
|
||||
int x = ((b1 & 0x1f) << 6) | (b2 & 0x3f);
|
||||
u8++;
|
||||
n8--;
|
||||
if (x >= 0x80)
|
||||
c = x;
|
||||
}
|
||||
} else if ((b1 & 0x10) == 0) {
|
||||
unsigned char b2;
|
||||
if ((n8 >= 1) && (((b2 = *u8) & 0xc0) == 0x80)) {
|
||||
unsigned char b3;
|
||||
u8++;
|
||||
n8--;
|
||||
if ((n8 >= 1) && (((b3 = *u8) & 0xc0) == 0x80)) {
|
||||
int x = ((b1 & 0x0f) << 12) | ((b2 & 0x3f) << 6) | (b3 & 0x3f);
|
||||
u8++;
|
||||
n8--;
|
||||
if ((x >= 0x800) && ((x < 0xd800) || (x > 0xdfff)))
|
||||
c = x;
|
||||
}
|
||||
}
|
||||
} else if ((b1 & 0x08) == 0) {
|
||||
unsigned char b2;
|
||||
if ((n8 >= 1) && (((b2 = *u8) & 0xc0) == 0x80)) {
|
||||
unsigned char b3;
|
||||
u8++;
|
||||
n8--;
|
||||
if ((n8 >= 1) && (((b3 = *u8) & 0xc0) == 0x80)) {
|
||||
unsigned char b4;
|
||||
u8++;
|
||||
n8--;
|
||||
if ((n8 >= 1) && (((b4 = *u8) & 0xc0) == 0x80)) {
|
||||
int x = ((b1 & 0x07) << 18) | ((b2 & 0x3f) << 12) | ((b3 & 0x3f) << 6) | (b4 & 0x3f);
|
||||
u8++;
|
||||
n8--;
|
||||
if ((x >= 0x10000) && (x <= 0x10ffff))
|
||||
c = x;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Sstring_set(p, i++, c);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_bignum(ptr tc, iptr n, IBOOL sign) {
|
||||
ptr p; iptr d;
|
||||
|
||||
if ((uptr)n > (uptr)maximum_bignum_length)
|
||||
S_error("", "invalid bignum size request");
|
||||
|
||||
d = size_bignum(n);
|
||||
thread_find_room(tc, type_typed_object, d, p);
|
||||
BIGTYPE(p) = (uptr)n << bignum_length_offset | sign << bignum_sign_offset | type_bignum;
|
||||
return p;
|
||||
}
|
||||
|
||||
/* S_code is always called with mutex */
|
||||
ptr S_code(ptr tc, iptr type, iptr n) {
|
||||
ptr p; iptr d;
|
||||
|
||||
d = size_code(n);
|
||||
find_room(space_code, 0, type_typed_object, d, p);
|
||||
CODETYPE(p) = type;
|
||||
CODELEN(p) = n;
|
||||
/* we record the code modification here, even though we haven't
|
||||
even started modifying the code yet, since we always create
|
||||
and fill the code object within a critical section. */
|
||||
S_record_code_mod(tc, (uptr)&CODEIT(p,0), (uptr)n);
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_relocation_table(iptr n) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr p; iptr d;
|
||||
|
||||
d = size_reloc_table(n);
|
||||
thread_find_room(tc, typemod, d, p);
|
||||
RELOCSIZE(p) = n;
|
||||
return p;
|
||||
}
|
||||
|
||||
ptr S_weak_cons(ptr car, ptr cdr) {
|
||||
ptr p;
|
||||
tc_mutex_acquire();
|
||||
p = S_cons_in(space_weakpair, 0, car, cdr);
|
||||
tc_mutex_release();
|
||||
return p;
|
||||
}
|
BIN
ta6ob/c/alloc.o
Normal file
BIN
ta6ob/c/alloc.o
Normal file
Binary file not shown.
672
ta6ob/c/compress-io.c
Normal file
672
ta6ob/c/compress-io.c
Normal file
|
@ -0,0 +1,672 @@
|
|||
/* compress-io.c
|
||||
* Copyright 1984-2019 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Dispatch to zlib or LZ4 */
|
||||
|
||||
#include "system.h"
|
||||
#include "zlib.h"
|
||||
#include "lz4.h"
|
||||
#include "lz4frame.h"
|
||||
#include "lz4hc.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
# define WIN32_IZE(id) _ ## id
|
||||
# define GLZ_O_BINARY O_BINARY
|
||||
#else
|
||||
# define WIN32_IZE(id) id
|
||||
# define GLZ_O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* the value of LZ4_OUTPUT_PORT_IN_BUFFER_SIZE was determined
|
||||
through experimentation on an intel linux server and an intel
|
||||
osx laptop. smaller sizes result in significantly worse compression
|
||||
of object files, and larger sizes don't have much beneficial effect.
|
||||
don't increase the output-port in-buffer size unless you're sure
|
||||
it reduces object-file size or reduces compression time
|
||||
significantly. don't decrease it unless you're sure it doesn't
|
||||
increase object-file size significantly. one buffer of size
|
||||
LZ4_OUTPUT_PORT_IN_BUFFER_SIZE is allocated per lz4-compressed
|
||||
output port. another buffer of a closely related size is allocated
|
||||
per thread. */
|
||||
#define LZ4_OUTPUT_PORT_IN_BUFFER_SIZE (1 << 18)
|
||||
|
||||
/* the values we choose for LZ4_INPUT_PORT_IN_BUFFER_SIZE and
|
||||
LZ4_INPUT_PORT_OUT_BUFFER_SIZE don't seem to make much difference
|
||||
in decompression speed, so we keep them fairly small. one buffer
|
||||
of size LZ4_INPUT_PORT_IN_BUFFER_SIZE and one buffer of size
|
||||
LZ4_INPUT_PORT_OUT_BUFFER_SIZE are allocated per lz4-compressed
|
||||
input port. */
|
||||
#define LZ4_INPUT_PORT_IN_BUFFER_SIZE (1 << 12)
|
||||
#define LZ4_INPUT_PORT_OUT_BUFFER_SIZE (1 << 14)
|
||||
|
||||
typedef struct lz4File_out_r {
|
||||
LZ4F_preferences_t preferences;
|
||||
INT fd;
|
||||
INT out_buffer_size;
|
||||
INT in_pos;
|
||||
INT err;
|
||||
size_t stream_pos;
|
||||
char in_buffer[LZ4_OUTPUT_PORT_IN_BUFFER_SIZE];
|
||||
} lz4File_out;
|
||||
|
||||
typedef struct lz4File_in_r {
|
||||
INT fd;
|
||||
LZ4F_dctx *dctx;
|
||||
INT in_pos, in_len, out_pos, out_len;
|
||||
INT frame_ended;
|
||||
INT err;
|
||||
size_t stream_pos;
|
||||
off_t init_pos;
|
||||
char in_buffer[LZ4_INPUT_PORT_IN_BUFFER_SIZE];
|
||||
char out_buffer[LZ4_INPUT_PORT_OUT_BUFFER_SIZE];
|
||||
} lz4File_in;
|
||||
|
||||
typedef struct sized_buffer_r {
|
||||
INT size;
|
||||
char buffer[0];
|
||||
} sized_buffer;
|
||||
|
||||
/* local functions */
|
||||
static glzFile glzdopen_output_gz(INT fd, INT compress_level);
|
||||
static glzFile glzdopen_output_lz4(INT fd, INT compress_level);
|
||||
static glzFile glzdopen_input_gz(INT fd);
|
||||
static glzFile glzdopen_input_lz4(INT fd, off_t init_pos);
|
||||
static INT glzread_lz4(lz4File_in *lz4, void *buffer, UINT count);
|
||||
static INT glzemit_lz4(lz4File_out *lz4, void *buffer, UINT count);
|
||||
static INT glzwrite_lz4(lz4File_out *lz4, void *buffer, UINT count);
|
||||
|
||||
INT S_zlib_compress_level(INT compress_level) {
|
||||
switch (compress_level) {
|
||||
case COMPRESS_MIN:
|
||||
case COMPRESS_LOW:
|
||||
return Z_BEST_SPEED;
|
||||
case COMPRESS_MEDIUM:
|
||||
return (Z_BEST_SPEED + Z_BEST_COMPRESSION) / 2;
|
||||
case COMPRESS_HIGH:
|
||||
return (Z_BEST_SPEED + (3 * Z_BEST_COMPRESSION)) / 4;
|
||||
case COMPRESS_MAX:
|
||||
return Z_BEST_COMPRESSION;
|
||||
default:
|
||||
S_error1("S_zlib_compress_level", "unexpected compress level ~s", Sinteger(compress_level));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static glzFile glzdopen_output_gz(INT fd, INT compress_level) {
|
||||
gzFile gz;
|
||||
glzFile glz;
|
||||
INT as_append;
|
||||
INT level;
|
||||
|
||||
#ifdef WIN32
|
||||
as_append = 0;
|
||||
#else
|
||||
as_append = fcntl(fd, F_GETFL) & O_APPEND;
|
||||
#endif
|
||||
|
||||
if ((gz = gzdopen(fd, as_append ? "ab" : "wb")) == Z_NULL) return Z_NULL;
|
||||
|
||||
level = S_zlib_compress_level(compress_level);
|
||||
|
||||
gzsetparams(gz, level, Z_DEFAULT_STRATEGY);
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
(void)gzclose(gz);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 0;
|
||||
glz->format = COMPRESS_GZIP;
|
||||
glz->gz = gz;
|
||||
return glz;
|
||||
}
|
||||
|
||||
INT S_lz4_compress_level(INT compress_level) {
|
||||
switch (compress_level) {
|
||||
case COMPRESS_MIN:
|
||||
case COMPRESS_LOW:
|
||||
return 1;
|
||||
case COMPRESS_MEDIUM:
|
||||
return LZ4HC_CLEVEL_MIN;
|
||||
case COMPRESS_HIGH:
|
||||
return (LZ4HC_CLEVEL_MIN + LZ4HC_CLEVEL_MAX) / 2;
|
||||
case COMPRESS_MAX:
|
||||
return LZ4HC_CLEVEL_MAX;
|
||||
default:
|
||||
S_error1("S_lz4_compress_level", "unexpected compress level ~s", Sinteger(compress_level));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static glzFile glzdopen_output_lz4(INT fd, INT compress_level) {
|
||||
glzFile glz;
|
||||
lz4File_out *lz4;
|
||||
INT level;
|
||||
|
||||
level = S_lz4_compress_level(compress_level);
|
||||
|
||||
if ((lz4 = malloc(sizeof(lz4File_out))) == NULL) return Z_NULL;
|
||||
memset(&lz4->preferences, 0, sizeof(LZ4F_preferences_t));
|
||||
lz4->preferences.compressionLevel = level;
|
||||
lz4->fd = fd;
|
||||
lz4->out_buffer_size = (INT)LZ4F_compressFrameBound(LZ4_OUTPUT_PORT_IN_BUFFER_SIZE, &lz4->preferences);
|
||||
lz4->in_pos = 0;
|
||||
lz4->err = 0;
|
||||
lz4->stream_pos = 0;
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
free(lz4);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 0;
|
||||
glz->format = COMPRESS_LZ4;
|
||||
glz->lz4_out = lz4;
|
||||
return glz;
|
||||
}
|
||||
|
||||
glzFile S_glzdopen_output(INT fd, INT compress_format, INT compress_level) {
|
||||
switch (compress_format) {
|
||||
case COMPRESS_GZIP:
|
||||
return glzdopen_output_gz(fd, compress_level);
|
||||
case COMPRESS_LZ4:
|
||||
return glzdopen_output_lz4(fd, compress_level);
|
||||
default:
|
||||
S_error1("glzdopen_output", "unexpected compress format ~s", Sinteger(compress_format));
|
||||
return Z_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static glzFile glzdopen_input_gz(INT fd) {
|
||||
gzFile gz;
|
||||
glzFile glz;
|
||||
|
||||
if ((gz = gzdopen(fd, "rb")) == Z_NULL) return Z_NULL;
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
(void)gzclose(gz);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 1;
|
||||
glz->format = COMPRESS_GZIP;
|
||||
glz->gz = gz;
|
||||
return glz;
|
||||
}
|
||||
|
||||
static glzFile glzdopen_input_lz4(INT fd, off_t init_pos) {
|
||||
glzFile glz;
|
||||
LZ4F_dctx *dctx;
|
||||
LZ4F_errorCode_t r;
|
||||
lz4File_in *lz4;
|
||||
|
||||
r = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
|
||||
if (LZ4F_isError(r))
|
||||
return Z_NULL;
|
||||
|
||||
if ((lz4 = malloc(sizeof(lz4File_in))) == NULL) {
|
||||
(void)LZ4F_freeDecompressionContext(dctx);
|
||||
return Z_NULL;
|
||||
}
|
||||
lz4->fd = fd;
|
||||
lz4->dctx = dctx;
|
||||
lz4->in_pos = 0;
|
||||
lz4->in_len = 0;
|
||||
lz4->out_len = 0;
|
||||
lz4->out_pos = 0;
|
||||
lz4->frame_ended = 0;
|
||||
lz4->err = 0;
|
||||
lz4->stream_pos = 0;
|
||||
lz4->init_pos = init_pos;
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
(void)LZ4F_freeDecompressionContext(lz4->dctx);
|
||||
free(lz4);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 1;
|
||||
glz->format = COMPRESS_LZ4;
|
||||
glz->lz4_in = lz4;
|
||||
return glz;
|
||||
}
|
||||
|
||||
glzFile S_glzdopen_input(INT fd) {
|
||||
INT r, pos = 0;
|
||||
unsigned char buffer[4];
|
||||
off_t init_pos;
|
||||
|
||||
/* check for LZ4 magic number, otherwise defer to gzdopen */
|
||||
|
||||
if ((init_pos = WIN32_IZE(lseek)(fd, 0, SEEK_CUR)) == -1) return Z_NULL;
|
||||
|
||||
while (pos < 4) {
|
||||
r = WIN32_IZE(read)(fd, (char*)buffer + pos, 4 - pos);
|
||||
if (r == 0)
|
||||
break;
|
||||
else if (r > 0)
|
||||
pos += r;
|
||||
#ifdef EINTR
|
||||
else if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
else
|
||||
break; /* error reading */
|
||||
}
|
||||
|
||||
if (pos > 0) {
|
||||
if (WIN32_IZE(lseek)(fd, init_pos, SEEK_SET) == -1) return Z_NULL;
|
||||
}
|
||||
|
||||
if ((pos == 4)
|
||||
&& (buffer[0] == 0x04)
|
||||
&& (buffer[1] == 0x22)
|
||||
&& (buffer[2] == 0x4d)
|
||||
&& (buffer[3] == 0x18))
|
||||
return glzdopen_input_lz4(fd, init_pos);
|
||||
|
||||
return glzdopen_input_gz(fd);
|
||||
}
|
||||
|
||||
glzFile S_glzopen_input(const char *path) {
|
||||
INT fd;
|
||||
|
||||
fd = WIN32_IZE(open)(path, O_RDONLY | GLZ_O_BINARY);
|
||||
|
||||
if (fd == -1)
|
||||
return Z_NULL;
|
||||
else
|
||||
return S_glzdopen_input(fd);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
glzFile S_glzopen_input_w(const wchar_t *path) {
|
||||
INT fd;
|
||||
|
||||
fd = _wopen(path, O_RDONLY | GLZ_O_BINARY);
|
||||
|
||||
if (fd == -1)
|
||||
return Z_NULL;
|
||||
else
|
||||
return S_glzdopen_input(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
IBOOL S_glzdirect(glzFile glz) {
|
||||
if (glz->format == COMPRESS_GZIP)
|
||||
return gzdirect(glz->gz);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT S_glzclose(glzFile glz) {
|
||||
INT r = Z_OK, saved_errno = 0;
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
r = gzclose(glz->gz);
|
||||
break;
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp) {
|
||||
lz4File_in *lz4 = glz->lz4_in;
|
||||
while (1) {
|
||||
INT r = WIN32_IZE(close)(lz4->fd);
|
||||
#ifdef EINTR
|
||||
if (r < 0 && errno == EINTR) continue;
|
||||
#endif
|
||||
if (r == 0) { saved_errno = errno; }
|
||||
break;
|
||||
}
|
||||
(void)LZ4F_freeDecompressionContext(lz4->dctx);
|
||||
free(lz4);
|
||||
} else {
|
||||
lz4File_out *lz4 = glz->lz4_out;
|
||||
if (lz4->in_pos != 0) {
|
||||
r = glzemit_lz4(lz4, lz4->in_buffer, lz4->in_pos);
|
||||
if (r >= 0) r = Z_OK; else { r = Z_ERRNO; saved_errno = errno; }
|
||||
}
|
||||
while (1) {
|
||||
int r1 = WIN32_IZE(close)(lz4->fd);
|
||||
#ifdef EINTR
|
||||
if (r1 < 0 && errno == EINTR) continue;
|
||||
#endif
|
||||
if (r == Z_OK && r1 < 0) { r = Z_ERRNO; saved_errno = errno; }
|
||||
break;
|
||||
}
|
||||
free(lz4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
S_error1("S_glzclose", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
}
|
||||
free(glz);
|
||||
if (saved_errno) errno = saved_errno;
|
||||
return r;
|
||||
}
|
||||
|
||||
static INT glzread_lz4(lz4File_in *lz4, void *buffer, UINT count) {
|
||||
while (lz4->out_pos == lz4->out_len) {
|
||||
INT in_avail;
|
||||
|
||||
in_avail = lz4->in_len - lz4->in_pos;
|
||||
if (!in_avail) {
|
||||
while (1) {
|
||||
in_avail = WIN32_IZE(read)(lz4->fd, lz4->in_buffer, LZ4_INPUT_PORT_IN_BUFFER_SIZE);
|
||||
if (in_avail >= 0) {
|
||||
lz4->in_len = in_avail;
|
||||
lz4->in_pos = 0;
|
||||
break;
|
||||
#ifdef EINTR
|
||||
} else if (errno == EINTR) {
|
||||
/* try again */
|
||||
#endif
|
||||
} else {
|
||||
lz4->err = Z_ERRNO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_avail > 0) {
|
||||
size_t amt, out_len = LZ4_INPUT_PORT_OUT_BUFFER_SIZE, in_len = in_avail;
|
||||
|
||||
/* For a large enough result buffer, try to decompress directly
|
||||
to that buffer: */
|
||||
if (count >= (out_len >> 1)) {
|
||||
size_t direct_out_len = count;
|
||||
|
||||
if (lz4->frame_ended && lz4->in_buffer[lz4->in_pos] == 0)
|
||||
return 0; /* count 0 after frame as stream terminator */
|
||||
|
||||
amt = LZ4F_decompress(lz4->dctx,
|
||||
buffer, &direct_out_len,
|
||||
lz4->in_buffer + lz4->in_pos, &in_len,
|
||||
NULL);
|
||||
lz4->frame_ended = (amt == 0);
|
||||
|
||||
if (LZ4F_isError(amt)) {
|
||||
lz4->err = Z_STREAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lz4->in_pos += (INT)in_len;
|
||||
|
||||
if (direct_out_len) {
|
||||
lz4->stream_pos += direct_out_len;
|
||||
return (INT)direct_out_len;
|
||||
}
|
||||
|
||||
in_len = in_avail - in_len;
|
||||
}
|
||||
|
||||
if (in_len > 0) {
|
||||
if (lz4->frame_ended && lz4->in_buffer[lz4->in_pos] == 0)
|
||||
return 0; /* count 0 after frame as stream terminator */
|
||||
|
||||
amt = LZ4F_decompress(lz4->dctx,
|
||||
lz4->out_buffer, &out_len,
|
||||
lz4->in_buffer + lz4->in_pos, &in_len,
|
||||
NULL);
|
||||
lz4->frame_ended = (amt == 0);
|
||||
|
||||
if (LZ4F_isError(amt)) {
|
||||
lz4->err = Z_STREAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lz4->in_pos += (INT)in_len;
|
||||
lz4->out_len = (INT)out_len;
|
||||
lz4->out_pos = 0;
|
||||
}
|
||||
} else {
|
||||
/* EOF on read */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lz4->out_pos < lz4->out_len) {
|
||||
UINT amt = lz4->out_len - lz4->out_pos;
|
||||
if (amt > count) amt = count;
|
||||
memcpy(buffer, lz4->out_buffer + lz4->out_pos, amt);
|
||||
lz4->out_pos += amt;
|
||||
lz4->stream_pos += amt;
|
||||
return amt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT S_glzread(glzFile glz, void *buffer, UINT count) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzread(glz->gz, buffer, count);
|
||||
case COMPRESS_LZ4:
|
||||
return glzread_lz4(glz->lz4_in, buffer, count);
|
||||
default:
|
||||
S_error1("S_glzread", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static INT glzemit_lz4(lz4File_out *lz4, void *buffer, UINT count) {
|
||||
ptr tc = get_thread_context();
|
||||
sized_buffer *cached_out_buffer;
|
||||
char *out_buffer;
|
||||
INT out_len, out_pos;
|
||||
INT r = 0;
|
||||
|
||||
/* allocate one out_buffer (per thread) since we don't need one for each file.
|
||||
the buffer is freed by destroy_thread. */
|
||||
if ((cached_out_buffer = LZ4OUTBUFFER(tc)) == NULL || cached_out_buffer->size < lz4->out_buffer_size) {
|
||||
if (cached_out_buffer != NULL) free(cached_out_buffer);
|
||||
if ((LZ4OUTBUFFER(tc) = cached_out_buffer = malloc(sizeof(sized_buffer) + lz4->out_buffer_size)) == NULL) return -1;
|
||||
cached_out_buffer->size = lz4->out_buffer_size;
|
||||
}
|
||||
out_buffer = cached_out_buffer->buffer;
|
||||
|
||||
out_len = (INT)LZ4F_compressFrame(out_buffer, lz4->out_buffer_size,
|
||||
buffer, count,
|
||||
&lz4->preferences);
|
||||
if (LZ4F_isError(out_len)) {
|
||||
lz4->err = Z_STREAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_pos = 0;
|
||||
while (out_pos < out_len) {
|
||||
r = WIN32_IZE(write)(lz4->fd, out_buffer + out_pos, out_len - out_pos);
|
||||
if (r >= 0)
|
||||
out_pos += r;
|
||||
#ifdef EINTR
|
||||
else if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static INT glzwrite_lz4(lz4File_out *lz4, void *buffer, UINT count) {
|
||||
UINT amt; INT r;
|
||||
|
||||
if ((amt = LZ4_OUTPUT_PORT_IN_BUFFER_SIZE - lz4->in_pos) > count) amt = count;
|
||||
|
||||
if (amt == LZ4_OUTPUT_PORT_IN_BUFFER_SIZE) {
|
||||
/* full buffer coming from input...skip the memcpy */
|
||||
if ((r = glzemit_lz4(lz4, buffer, LZ4_OUTPUT_PORT_IN_BUFFER_SIZE)) < 0) return 0;
|
||||
} else {
|
||||
memcpy(lz4->in_buffer + lz4->in_pos, buffer, amt);
|
||||
if ((lz4->in_pos += amt) == LZ4_OUTPUT_PORT_IN_BUFFER_SIZE) {
|
||||
lz4->in_pos = 0;
|
||||
if ((r = glzemit_lz4(lz4, lz4->in_buffer, LZ4_OUTPUT_PORT_IN_BUFFER_SIZE)) < 0) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lz4->stream_pos += amt;
|
||||
return amt;
|
||||
}
|
||||
|
||||
INT S_glzwrite(glzFile glz, void *buffer, UINT count) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzwrite(glz->gz, buffer, count);
|
||||
case COMPRESS_LZ4:
|
||||
return glzwrite_lz4(glz->lz4_out, buffer, count);
|
||||
default:
|
||||
S_error1("S_glzwrite", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long S_glzseek(glzFile glz, long offset, INT whence) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzseek(glz->gz, offset, whence);
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp) {
|
||||
lz4File_in *lz4 = glz->lz4_in;
|
||||
if (whence == SEEK_CUR)
|
||||
offset += (long)lz4->stream_pos;
|
||||
if (offset < 0)
|
||||
offset = 0;
|
||||
if ((size_t)offset < lz4->stream_pos) {
|
||||
/* rewind and read from start */
|
||||
if (WIN32_IZE(lseek)(lz4->fd, lz4->init_pos, SEEK_SET) < 0) {
|
||||
lz4->err = Z_ERRNO;
|
||||
return -1;
|
||||
}
|
||||
LZ4F_resetDecompressionContext(lz4->dctx);
|
||||
lz4->in_pos = 0;
|
||||
lz4->in_len = 0;
|
||||
lz4->out_len = 0;
|
||||
lz4->out_pos = 0;
|
||||
lz4->err = 0;
|
||||
lz4->stream_pos = 0;
|
||||
}
|
||||
while ((size_t)offset > lz4->stream_pos) {
|
||||
static char buffer[1024];
|
||||
size_t amt = (size_t)offset - lz4->stream_pos;
|
||||
if (amt > sizeof(buffer)) amt = sizeof(buffer);
|
||||
if (glzread_lz4(lz4, buffer, (UINT)amt) < 0)
|
||||
return -1;
|
||||
}
|
||||
return (long)lz4->stream_pos;
|
||||
} else {
|
||||
lz4File_out *lz4 = glz->lz4_out;
|
||||
if (whence == SEEK_CUR)
|
||||
offset += (long)lz4->stream_pos;
|
||||
if (offset >= 0) {
|
||||
while ((size_t)offset > lz4->stream_pos) {
|
||||
size_t amt = (size_t)offset - lz4->stream_pos;
|
||||
if (amt > 8) amt = 8;
|
||||
if (glzwrite_lz4(lz4, "\0\0\0\0\0\0\0\0", (UINT)amt) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (long)lz4->stream_pos;
|
||||
}
|
||||
default:
|
||||
S_error1("S_glzseek", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INT S_glzgetc(glzFile glz) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzgetc(glz->gz);
|
||||
case COMPRESS_LZ4:
|
||||
{
|
||||
unsigned char buffer[1];
|
||||
INT r;
|
||||
r = S_glzread(glz, buffer, 1);
|
||||
if (r == 1)
|
||||
return buffer[0];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
S_error1("S_glzgetc", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INT S_glzungetc(INT c, glzFile glz) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzungetc(c, glz->gz);
|
||||
case COMPRESS_LZ4:
|
||||
{
|
||||
lz4File_in *lz4 = glz->lz4_in;
|
||||
if (lz4->out_len == 0)
|
||||
lz4->out_len = lz4->out_pos = 1;
|
||||
if (lz4->out_pos) {
|
||||
lz4->out_pos--;
|
||||
lz4->out_buffer[lz4->out_pos] = c;
|
||||
lz4->stream_pos--;
|
||||
return c;
|
||||
} else {
|
||||
/* support ungetc only just after a getc, in which case there
|
||||
should have been room */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
default:
|
||||
S_error1("S_glzungetc", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INT S_glzrewind(glzFile glz) {
|
||||
return S_glzseek(glz, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
void S_glzerror(glzFile glz, INT *errnum) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
(void)gzerror(glz->gz, errnum);
|
||||
break;
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp)
|
||||
*errnum = glz->lz4_in->err;
|
||||
else
|
||||
*errnum = glz->lz4_out->err;
|
||||
break;
|
||||
default:
|
||||
S_error1("S_glzerror", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
*errnum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void S_glzclearerr(glzFile glz) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
gzclearerr(glz->gz);
|
||||
break;
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp)
|
||||
glz->lz4_in->err = 0;
|
||||
else
|
||||
glz->lz4_out->err = 0;
|
||||
break;
|
||||
default:
|
||||
S_error1("S_glzerror", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
}
|
||||
}
|
26
ta6ob/c/compress-io.h
Normal file
26
ta6ob/c/compress-io.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* compress-io.h
|
||||
* Copyright 1984-2019 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
typedef struct glzFile_r {
|
||||
INT fd;
|
||||
IBOOL inputp;
|
||||
INT format;
|
||||
union {
|
||||
struct gzFile_s *gz;
|
||||
struct lz4File_in_r *lz4_in;
|
||||
struct lz4File_out_r *lz4_out;
|
||||
};
|
||||
} *glzFile;
|
BIN
ta6ob/c/compress-io.o
Normal file
BIN
ta6ob/c/compress-io.o
Normal file
Binary file not shown.
4
ta6ob/c/config.h
Normal file
4
ta6ob/c/config.h
Normal file
|
@ -0,0 +1,4 @@
|
|||
#define SCHEME_SCRIPT "scheme-script"
|
||||
#ifndef WIN32
|
||||
#define DEFAULT_HEAP_PATH "/usr/local/lib/csv%v/%m"
|
||||
#endif
|
1087
ta6ob/c/expeditor.c
Normal file
1087
ta6ob/c/expeditor.c
Normal file
File diff suppressed because it is too large
Load diff
BIN
ta6ob/c/expeditor.o
Normal file
BIN
ta6ob/c/expeditor.o
Normal file
Binary file not shown.
415
ta6ob/c/externs.h
Normal file
415
ta6ob/c/externs.h
Normal file
|
@ -0,0 +1,415 @@
|
|||
/* externs.h
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* This file sets up platform-dependent includes and extern declarations
|
||||
* for Scheme globals not intended for use outside of the system (prefixed
|
||||
* with S_). Scheme globals intended for use outside of the system
|
||||
* (prefixed with S) are declared in scheme.h
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef WIN32
|
||||
#include <unistd.h>
|
||||
|
||||
#if (machine_type == machine_type_i3qnx || machine_type == machine_type_ti3qnx)
|
||||
off64_t lseek64(int,off64_t,int);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef SOLARIS
|
||||
#include <fcntl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#include <fcntl.h>
|
||||
#include <direct.h> /* for _getcwd */
|
||||
#include <setjmp.h>
|
||||
#endif
|
||||
|
||||
#if !defined(NORETURN)
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
# define NORETURN __attribute__((noreturn))
|
||||
# elif defined(_MSC_VER)
|
||||
# define NORETURN __declspec(noreturn)
|
||||
# else
|
||||
# define NORETURN
|
||||
# endif /* defined(__GNUC__) || defined(__clang__) */
|
||||
#endif /* !defined(NORETURN) */
|
||||
|
||||
/* external procedure declarations */
|
||||
/* prototypes gen. by ProtoGen Version 0.31 (Haydn Huntley) 1/18/93 */
|
||||
|
||||
/* alloc.c */
|
||||
extern void S_alloc_init(void);
|
||||
extern void S_protect(ptr *p);
|
||||
extern void S_reset_scheme_stack(ptr tc, iptr n);
|
||||
extern void S_reset_allocation_pointer(ptr tc);
|
||||
extern ptr S_compute_bytes_allocated(ptr xg, ptr xs);
|
||||
extern ptr S_find_more_room(ISPC s, IGEN g, iptr n, ptr old);
|
||||
extern void S_dirty_set(ptr *loc, ptr x);
|
||||
extern void S_mark_card_dirty(uptr card, IGEN to_g);
|
||||
extern void S_scan_dirty(ptr **p, ptr **endp);
|
||||
extern void S_scan_remembered_set(void);
|
||||
extern void S_get_more_room(void);
|
||||
extern ptr S_get_more_room_help(ptr tc, uptr ap, uptr type, uptr size);
|
||||
extern ptr S_cons_in(ISPC s, IGEN g, ptr car, ptr cdr);
|
||||
extern ptr S_symbol(ptr name);
|
||||
extern ptr S_rational(ptr n, ptr d);
|
||||
extern ptr S_tlc(ptr keyval, ptr tconc, ptr next);
|
||||
extern ptr S_vector_in(ISPC s, IGEN g, iptr n);
|
||||
extern ptr S_vector(iptr n);
|
||||
extern ptr S_fxvector(iptr n);
|
||||
extern ptr S_bytevector(iptr n);
|
||||
extern ptr S_null_immutable_vector(void);
|
||||
extern ptr S_null_immutable_fxvector(void);
|
||||
extern ptr S_null_immutable_bytevector(void);
|
||||
extern ptr S_null_immutable_string(void);
|
||||
extern ptr S_record(iptr n);
|
||||
extern ptr S_closure(ptr cod, iptr n);
|
||||
extern ptr S_mkcontinuation(ISPC s, IGEN g, ptr nuate, ptr stack,
|
||||
iptr length, iptr clength, ptr link, ptr ret, ptr winders);
|
||||
extern ptr S_inexactnum(double rp, double ip);
|
||||
extern ptr S_exactnum(ptr a, ptr b);
|
||||
extern ptr S_thread(ptr tc);
|
||||
extern ptr S_string(const char *s, iptr n);
|
||||
extern ptr S_bignum(ptr tc, iptr n, IBOOL sign);
|
||||
extern ptr S_code(ptr tc, iptr type, iptr n);
|
||||
extern ptr S_relocation_table(iptr n);
|
||||
extern ptr S_weak_cons(ptr car, ptr cdr);
|
||||
|
||||
/* fasl.c */
|
||||
extern void S_fasl_init(void);
|
||||
ptr S_fasl_read(INT fd, IFASLCODE situation, ptr path);
|
||||
ptr S_bv_fasl_read(ptr bv, ptr path);
|
||||
ptr S_boot_read(INT fd, const char *path);
|
||||
char *S_format_scheme_version(uptr n);
|
||||
char *S_lookup_machine_type(uptr n);
|
||||
extern void S_set_code_obj(char *who, IFASLCODE typ, ptr p, iptr n,
|
||||
ptr x, iptr o);
|
||||
extern ptr S_get_code_obj(IFASLCODE typ, ptr p, iptr n, iptr o);
|
||||
|
||||
/* flushcache.c */
|
||||
extern void S_record_code_mod(ptr tc, uptr addr, uptr bytes);
|
||||
extern void S_flush_instruction_cache(ptr tc);
|
||||
extern void S_flushcache_init(void);
|
||||
|
||||
/* foreign.c */
|
||||
extern void S_foreign_init(void);
|
||||
extern void S_foreign_entry(void);
|
||||
|
||||
/* gcwrapper.c */
|
||||
extern void S_ptr_tell(ptr p);
|
||||
extern void S_addr_tell(ptr p);
|
||||
extern void S_gc_init(void);
|
||||
#ifndef WIN32
|
||||
extern void S_register_child_process(INT child);
|
||||
#endif /* WIN32 */
|
||||
extern void S_fixup_counts(ptr counts);
|
||||
extern void S_do_gc(IGEN max_cg, IGEN min_tg, IGEN max_tg);
|
||||
extern void S_gc(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg);
|
||||
extern void S_gc_init(void);
|
||||
extern void S_set_maxgen(IGEN g);
|
||||
extern IGEN S_maxgen(void);
|
||||
extern void S_set_minfreegen(IGEN g);
|
||||
extern IGEN S_minfreegen(void);
|
||||
#ifndef WIN32
|
||||
extern void S_register_child_process(INT child);
|
||||
#endif /* WIN32 */
|
||||
extern IBOOL S_enable_object_counts(void);
|
||||
extern void S_set_enable_object_counts(IBOOL eoc);
|
||||
extern ptr S_object_counts(void);
|
||||
extern ptr S_locked_objects(void);
|
||||
extern ptr S_unregister_guardian(ptr tconc);
|
||||
extern void S_compact_heap(void);
|
||||
extern void S_check_heap(IBOOL aftergc);
|
||||
|
||||
/* gc-011.c */
|
||||
extern void S_gc_011(ptr tc);
|
||||
|
||||
/* gc-ocd.c */
|
||||
extern void S_gc_ocd(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg);
|
||||
|
||||
/* gc-oce.c */
|
||||
extern void S_gc_oce(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg);
|
||||
|
||||
/* intern.c */
|
||||
extern void S_intern_init(void);
|
||||
extern void S_resize_oblist(void);
|
||||
extern ptr S_intern(const unsigned char *s);
|
||||
extern ptr S_intern_sc(const string_char *s, iptr n, ptr name_str);
|
||||
extern ptr S_intern3(const string_char *pname, iptr plen, const string_char *uname, iptr ulen, ptr pname_str, ptr uame_str);
|
||||
extern void S_intern_gensym(ptr g);
|
||||
extern void S_retrofit_nonprocedure_code(void);
|
||||
|
||||
/* io.c */
|
||||
extern IBOOL S_file_existsp(const char *inpath, IBOOL followp);
|
||||
extern IBOOL S_file_regularp(const char *inpath, IBOOL followp);
|
||||
extern IBOOL S_file_directoryp(const char *inpath, IBOOL followp);
|
||||
extern IBOOL S_file_symbolic_linkp(const char *inpath);
|
||||
#ifdef WIN32
|
||||
extern ptr S_find_files(const char *wildpath);
|
||||
#else
|
||||
extern ptr S_directory_list(const char *inpath);
|
||||
#endif
|
||||
extern char *S_malloc_pathname(const char *inpath);
|
||||
#ifdef WIN32
|
||||
extern wchar_t *S_malloc_wide_pathname(const char *inpath);
|
||||
#endif
|
||||
extern IBOOL S_fixedpathp(const char *inpath);
|
||||
|
||||
/* compress-io.c */
|
||||
extern INT S_zlib_compress_level(INT compress_level);
|
||||
extern INT S_lz4_compress_level(INT compress_level);
|
||||
extern glzFile S_glzdopen_output(INT fd, INT compress_format, INT compress_level);
|
||||
extern glzFile S_glzdopen_input(INT fd);
|
||||
extern glzFile S_glzopen_input(const char *path);
|
||||
#ifdef WIN32
|
||||
extern glzFile S_glzopen_input_w(const wchar_t *path);
|
||||
#endif
|
||||
extern IBOOL S_glzdirect(glzFile file);
|
||||
extern INT S_glzclose(glzFile file);
|
||||
|
||||
extern INT S_glzread(glzFile file, void *buffer, UINT count);
|
||||
extern INT S_glzwrite(glzFile file, void *buffer, UINT count);
|
||||
extern long S_glzseek(glzFile file, long offset, INT whence);
|
||||
extern INT S_glzgetc(glzFile file);
|
||||
extern INT S_glzungetc(INT c, glzFile file);
|
||||
extern INT S_glzrewind(glzFile file);
|
||||
|
||||
extern void S_glzerror(glzFile file, INT *errnum);
|
||||
extern void S_glzclearerr(glzFile fdfile);
|
||||
|
||||
|
||||
/* new-io.c */
|
||||
extern INT S_gzxfile_fd(ptr x);
|
||||
extern glzFile S_gzxfile_gzfile(ptr x);
|
||||
extern ptr S_new_open_input_fd(const char *filename, IBOOL compressed);
|
||||
extern ptr S_new_open_output_fd(
|
||||
const char *filename, INT mode,
|
||||
IBOOL no_create, IBOOL no_fail, IBOOL no_truncate,
|
||||
IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed);
|
||||
extern ptr S_new_open_input_output_fd(
|
||||
const char *filename, INT mode,
|
||||
IBOOL no_create, IBOOL no_fail, IBOOL no_truncate,
|
||||
IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed);
|
||||
extern ptr S_close_fd(ptr file, IBOOL gzflag);
|
||||
extern ptr S_compress_input_fd(INT fd, I64 fp);
|
||||
extern ptr S_compress_output_fd(INT fd);
|
||||
|
||||
extern ptr S_bytevector_read(ptr file, ptr buffer, iptr start, iptr count, IBOOL gzflag);
|
||||
extern ptr S_bytevector_read_nb(ptr file, ptr buffer, iptr start, iptr count, IBOOL gzflag);
|
||||
extern ptr S_bytevector_write(ptr file, ptr buffer, iptr start, iptr count, IBOOL gzflag);
|
||||
extern ptr S_put_byte(ptr file, INT byte, IBOOL gzflag);
|
||||
|
||||
extern ptr S_get_fd_pos(ptr file, IBOOL gzflag);
|
||||
extern ptr S_set_fd_pos(ptr file, ptr pos, IBOOL gzflag);
|
||||
extern ptr S_get_fd_non_blocking(ptr file, IBOOL gzflag);
|
||||
extern ptr S_set_fd_non_blocking(ptr file, IBOOL x, IBOOL gzflag);
|
||||
extern ptr S_get_fd_length(ptr file, IBOOL gzflag);
|
||||
extern ptr S_set_fd_length(ptr file, ptr length, IBOOL gzflag);
|
||||
extern void S_new_io_init(void);
|
||||
|
||||
extern uptr S_bytevector_compress_size(iptr s_count, INT compress_format);
|
||||
extern ptr S_bytevector_compress(ptr dest_bv, iptr d_start, iptr d_count,
|
||||
ptr src_bv, iptr s_start, iptr s_count,
|
||||
INT compress_format);
|
||||
extern ptr S_bytevector_uncompress(ptr dest_bv, iptr d_start, iptr d_count,
|
||||
ptr src_bv, iptr s_start, iptr s_count,
|
||||
INT compress_format);
|
||||
|
||||
/* thread.c */
|
||||
extern void S_thread_init(void);
|
||||
extern ptr S_create_thread_object(const char *who, ptr p_tc);
|
||||
#ifdef PTHREADS
|
||||
extern ptr S_fork_thread(ptr thunk);
|
||||
extern scheme_mutex_t *S_make_mutex(void);
|
||||
extern void S_mutex_free(scheme_mutex_t *m);
|
||||
extern void S_mutex_acquire(scheme_mutex_t *m);
|
||||
extern INT S_mutex_tryacquire(scheme_mutex_t *m);
|
||||
extern void S_mutex_release(scheme_mutex_t *m);
|
||||
extern s_thread_cond_t *S_make_condition(void);
|
||||
extern void S_condition_free(s_thread_cond_t *c);
|
||||
extern IBOOL S_condition_wait(s_thread_cond_t *c, scheme_mutex_t *m, ptr t);
|
||||
extern INT S_activate_thread(void);
|
||||
extern void S_unactivate_thread(int mode);
|
||||
#endif
|
||||
|
||||
/* scheme.c */
|
||||
extern void S_generic_invoke(ptr tc, ptr code);
|
||||
|
||||
/* number.c */
|
||||
extern void S_number_init(void);
|
||||
extern ptr S_normalize_bignum(ptr x);
|
||||
extern IBOOL S_integer_valuep(ptr x);
|
||||
extern iptr S_integer_value(const char *who, ptr x);
|
||||
extern I64 S_int64_value(char *who, ptr x);
|
||||
extern IBOOL S_big_eq(ptr x, ptr y);
|
||||
extern IBOOL S_big_lt(ptr x, ptr y);
|
||||
extern ptr S_big_negate(ptr x);
|
||||
extern ptr S_add(ptr x, ptr y);
|
||||
extern ptr S_sub(ptr x, ptr y);
|
||||
extern ptr S_mul(ptr x, ptr y);
|
||||
extern ptr S_div(ptr x, ptr y);
|
||||
extern ptr S_rem(ptr x, ptr y);
|
||||
extern ptr S_trunc(ptr x, ptr y);
|
||||
extern void S_trunc_rem(ptr tc, ptr x, ptr y, ptr *q, ptr *r);
|
||||
extern ptr S_gcd(ptr x, ptr y);
|
||||
extern ptr S_ash(ptr x, ptr n);
|
||||
extern ptr S_big_positive_bit_field(ptr x, ptr fxstart, ptr fxend);
|
||||
extern ptr S_integer_length(ptr x);
|
||||
extern ptr S_big_first_bit_set(ptr x);
|
||||
extern double S_random_double(U32 m1, U32 m2,
|
||||
U32 m3, U32 m4, double scale);
|
||||
extern double S_floatify(ptr x);
|
||||
extern ptr S_decode_float(double d);
|
||||
extern ptr S_logand(ptr x, ptr y);
|
||||
extern ptr S_logbitp(ptr k, ptr x);
|
||||
extern ptr S_logbit0(ptr k, ptr x);
|
||||
extern ptr S_logbit1(ptr k, ptr x);
|
||||
extern ptr S_logtest(ptr x, ptr y);
|
||||
extern ptr S_logor(ptr x, ptr y);
|
||||
extern ptr S_logxor(ptr x, ptr y);
|
||||
extern ptr S_lognot(ptr x);
|
||||
|
||||
/* prim.c */
|
||||
extern ptr S_lookup_library_entry(iptr n, IBOOL errorp);
|
||||
extern ptr S_lookup_c_entry(iptr i);
|
||||
extern void S_prim_init(void);
|
||||
|
||||
/* prim5.c */
|
||||
extern ptr S_strerror(INT errnum);
|
||||
extern void S_prim5_init(void);
|
||||
extern void S_dump_tc(ptr tc);
|
||||
|
||||
/* print.c */
|
||||
extern void S_print_init(void);
|
||||
extern void S_prin1(ptr x);
|
||||
|
||||
/* schsig.c */
|
||||
extern ptr S_get_scheme_arg(ptr tc, iptr n);
|
||||
extern void S_put_scheme_arg(ptr tc, iptr n, ptr x);
|
||||
extern iptr S_continuation_depth(ptr k);
|
||||
extern ptr S_single_continuation(ptr k, iptr n);
|
||||
extern void S_split_and_resize(void);
|
||||
extern void S_handle_overflow(void);
|
||||
extern void S_handle_overflood(void);
|
||||
extern void S_handle_apply_overflood(void);
|
||||
extern void S_overflow(ptr tc, iptr frame_request);
|
||||
extern NORETURN void S_error_reset(const char *s);
|
||||
extern NORETURN void S_error_abort(const char *s);
|
||||
extern NORETURN void S_abnormal_exit(void);
|
||||
extern NORETURN void S_error(const char *who, const char *s);
|
||||
extern NORETURN void S_error1(const char *who, const char *s, ptr x);
|
||||
extern NORETURN void S_error2(const char *who, const char *s, ptr x, ptr y);
|
||||
extern NORETURN void S_error3(const char *who, const char *s, ptr x, ptr y, ptr z);
|
||||
extern NORETURN void S_boot_error(const ptr who, ptr s, ptr args);
|
||||
extern void S_handle_docall_error(void);
|
||||
extern void S_handle_arg_error(void);
|
||||
extern void S_handle_nonprocedure_symbol(void);
|
||||
extern void S_handle_values_error(void);
|
||||
extern void S_handle_mvlet_error(void);
|
||||
extern ptr S_allocate_scheme_signal_queue(void);
|
||||
extern ptr S_dequeue_scheme_signals(ptr tc);
|
||||
extern void S_register_scheme_signal(iptr sig);
|
||||
extern void S_fire_collector(void);
|
||||
extern NORETURN void S_noncontinuable_interrupt(void);
|
||||
extern void S_schsig_init(void);
|
||||
#ifdef DEFINE_MATHERR
|
||||
#include <math.h>
|
||||
extern INT matherr(struct exception *x);
|
||||
#endif /* DEFINE_MATHERR */
|
||||
|
||||
/* segment.c */
|
||||
extern void S_segment_init(void);
|
||||
extern void *S_getmem(iptr bytes, IBOOL zerofill);
|
||||
extern void S_freemem(void *addr, iptr bytes);
|
||||
extern iptr S_find_segments(ISPC s, IGEN g, iptr n);
|
||||
extern void S_free_chunk(chunkinfo *chunk);
|
||||
extern void S_free_chunks(void);
|
||||
extern uptr S_curmembytes(void);
|
||||
extern uptr S_maxmembytes(void);
|
||||
extern void S_resetmaxmembytes(void);
|
||||
extern void S_move_to_chunk_list(chunkinfo *chunk, chunkinfo **pchunk_list);
|
||||
|
||||
/* stats.c */
|
||||
extern void S_stats_init(void);
|
||||
extern ptr S_cputime(void);
|
||||
extern ptr S_realtime(void);
|
||||
extern ptr S_clock_gettime(I32 typeno);
|
||||
extern ptr S_gmtime(ptr tzoff, ptr tspair);
|
||||
extern ptr S_asctime(ptr dtvec);
|
||||
extern ptr S_mktime(ptr dtvec);
|
||||
extern ptr S_unique_id(void);
|
||||
extern void S_gettime(INT typeno, struct timespec *tp);
|
||||
|
||||
/* symbol.c */
|
||||
extern ptr S_symbol_value(ptr sym);
|
||||
extern void S_set_symbol_value(ptr sym, ptr val);
|
||||
|
||||
/* machine-dependent .c files, e.g., x88k.c */
|
||||
#ifdef FLUSHCACHE
|
||||
extern INT S_flushcache_max_gap(void);
|
||||
extern void S_doflush(uptr start, uptr end);
|
||||
#endif
|
||||
extern void S_machine_init(void);
|
||||
|
||||
/* schlib.c */
|
||||
extern void S_initframe(ptr tc, iptr n);
|
||||
extern void S_put_arg(ptr tc, iptr i, ptr x);
|
||||
extern void S_return(void);
|
||||
extern void S_call_help(ptr tc, IBOOL singlep, IBOOL lock_ts);
|
||||
extern void S_call_one_result(void);
|
||||
extern void S_call_any_results(void);
|
||||
|
||||
#ifdef WIN32
|
||||
/* windows.c */
|
||||
extern INT S_getpagesize(void);
|
||||
extern ptr S_LastErrorString(void);
|
||||
extern void *S_ntdlopen(const char *path);
|
||||
extern void *S_ntdlsym(void *h, const char *s);
|
||||
extern ptr S_ntdlerror(void);
|
||||
extern int S_windows_flock(int fd, int operation);
|
||||
extern int S_windows_chdir(const char *pathname);
|
||||
extern int S_windows_chmod(const char *pathname, int mode);
|
||||
extern int S_windows_mkdir(const char *pathname);
|
||||
extern int S_windows_open(const char *pathname, int flags, int mode);
|
||||
extern int S_windows_rename(const char *oldpathname, const char *newpathname);
|
||||
extern int S_windows_rmdir(const char *pathname);
|
||||
extern int S_windows_stat64(const char *pathname, struct STATBUF *buffer);
|
||||
extern int S_windows_system(const char *command);
|
||||
extern int S_windows_unlink(const char *pathname);
|
||||
extern char *S_windows_getcwd(char *buffer, int maxlen);
|
||||
#endif /* WIN32 */
|
||||
|
||||
#ifdef _WIN64
|
||||
extern int S_setjmp(void* jb);
|
||||
extern void S_longjmp(void* jb, int value);
|
||||
#endif /* _WIN64 */
|
||||
|
||||
#ifdef FEATURE_EXPEDITOR
|
||||
/* expeditor.c */
|
||||
extern void S_expeditor_init(void);
|
||||
#endif /* FEATURE_EXPEDITOR */
|
||||
|
||||
/* statics.c */
|
||||
extern void scheme_statics(void);
|
1662
ta6ob/c/fasl.c
Normal file
1662
ta6ob/c/fasl.c
Normal file
File diff suppressed because it is too large
Load diff
BIN
ta6ob/c/fasl.o
Normal file
BIN
ta6ob/c/fasl.o
Normal file
Binary file not shown.
87
ta6ob/c/flushcache.c
Normal file
87
ta6ob/c/flushcache.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/* flushcache.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#ifdef FLUSHCACHE
|
||||
typedef struct {
|
||||
uptr start;
|
||||
uptr end;
|
||||
} mod_range;
|
||||
|
||||
#define mod_range_start(x) (((mod_range *)&BVIT(x,0))->start)
|
||||
#define mod_range_end(x) (((mod_range *)&BVIT(x,0))->end)
|
||||
|
||||
static uptr max_gap;
|
||||
|
||||
static ptr make_mod_range(uptr start, uptr end) {
|
||||
ptr bv = S_bytevector(sizeof(mod_range));
|
||||
mod_range_start(bv) = start;
|
||||
mod_range_end(bv) = end;
|
||||
return bv;
|
||||
}
|
||||
|
||||
/* we record info per thread so flush in one prematurely for another doesn't prevent
|
||||
the other from doing its own flush...and also since it's not clear that flushing in one
|
||||
actually syncs caches across cores & processors */
|
||||
|
||||
void S_record_code_mod(ptr tc, uptr addr, uptr bytes) {
|
||||
uptr end = addr + bytes;
|
||||
ptr ls = CODERANGESTOFLUSH(tc);
|
||||
|
||||
if (ls != Snil) {
|
||||
ptr last_mod = Scar(ls);
|
||||
uptr last_end = mod_range_end(last_mod);
|
||||
if (addr > last_end && addr - last_end < max_gap) {
|
||||
#ifdef DEBUG
|
||||
printf(" record_code_mod merging %x %x and %x %x\n", mod_range_start(last_mod), last_end, addr, end); fflush(stdout);
|
||||
#endif
|
||||
mod_range_end(last_mod) = end;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf(" record_code_mod new range %x to %x\n", addr, end); fflush(stdout);
|
||||
#endif
|
||||
CODERANGESTOFLUSH(tc) = S_cons_in(space_new, 0, make_mod_range(addr, end), ls);
|
||||
return;
|
||||
}
|
||||
|
||||
extern void S_flush_instruction_cache(ptr tc) {
|
||||
ptr ls;
|
||||
|
||||
for (ls = CODERANGESTOFLUSH(tc); ls != Snil; ls = Scdr(ls)) {
|
||||
S_doflush(mod_range_start(Scar(ls)), mod_range_end(Scar(ls)));
|
||||
}
|
||||
CODERANGESTOFLUSH(tc) = Snil;
|
||||
}
|
||||
|
||||
extern void S_flushcache_init(void) {
|
||||
if (S_boot_time) {
|
||||
max_gap = S_flushcache_max_gap();
|
||||
if (max_gap < (uptr)(code_data_disp + byte_alignment)) {
|
||||
max_gap = (uptr)(code_data_disp + byte_alignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* FLUSHCACHE */
|
||||
|
||||
extern void S_record_code_mod(UNUSED ptr tc, UNUSED uptr addr, UNUSED uptr bytes) {}
|
||||
extern void S_flush_instruction_cache(UNUSED ptr tc) {}
|
||||
extern void S_flushcache_init(void) { return; }
|
||||
|
||||
#endif /* FLUSHCACHE */
|
BIN
ta6ob/c/flushcache.o
Normal file
BIN
ta6ob/c/flushcache.o
Normal file
Binary file not shown.
334
ta6ob/c/foreign.c
Normal file
334
ta6ob/c/foreign.c
Normal file
|
@ -0,0 +1,334 @@
|
|||
/* foreign.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define debug(y) /* (void)printf(y) *//* uncomment printf for debug */
|
||||
/* #define UNLINK(x) 0 *//* uncomment #define to preserve temp files */
|
||||
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* we can now return arbitrary values (aligned or not)
|
||||
* since the garbage collector ignores addresses outside of the heap
|
||||
* or within foreign segments */
|
||||
#define ptr_to_addr(p) ((void *)p)
|
||||
#define addr_to_ptr(a) ((ptr)a)
|
||||
|
||||
/* buckets should be prime */
|
||||
#define buckets 457
|
||||
#define multiplier 3
|
||||
|
||||
#define ptrhash(x) ((uptr)x % buckets)
|
||||
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
#if defined(HPUX)
|
||||
#include <dl.h>
|
||||
#define dlopen(path,flags) (void *)shl_load(path, BIND_IMMEDIATE, 0L)
|
||||
#define s_dlerror() Sstring_utf8(strerror(errno), -1)
|
||||
#elif defined(WIN32)
|
||||
#define dlopen(path,flags) S_ntdlopen(path)
|
||||
#define dlsym(h,s) S_ntdlsym(h,s)
|
||||
#define s_dlerror() S_ntdlerror()
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#define s_dlerror() Sstring_utf8(dlerror(), -1)
|
||||
#ifndef RTLD_NOW
|
||||
#define RTLD_NOW 2
|
||||
#endif /* RTLD_NOW */
|
||||
#endif /* machine types */
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
|
||||
/* locally defined functions */
|
||||
static uptr symhash(const char *s);
|
||||
static ptr lookup_static(const char *s);
|
||||
static ptr lookup_dynamic(const char *s, ptr tbl);
|
||||
static ptr lookup(const char *s);
|
||||
static ptr remove_foreign_entry(const char *s);
|
||||
static void *lookup_foreign_entry(const char *s);
|
||||
static ptr foreign_entries(void);
|
||||
static ptr foreign_static_table(void);
|
||||
static ptr foreign_dynamic_table(void);
|
||||
static ptr bvstring(const char *s);
|
||||
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
static void load_shared_object(const char *path);
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
|
||||
#ifdef HPUX
|
||||
void *proc2entry(void *f, ptr name) {
|
||||
if (((uptr)f & 2) == 0)
|
||||
if (name == NULL)
|
||||
S_error("Sforeign_symbol", "invalid entry");
|
||||
else
|
||||
S_error1("Sforeign_symbol", "invalid entry for ~s", name);
|
||||
return (void *)((uptr)f & ~0x3);
|
||||
}
|
||||
#endif /* HPUX */
|
||||
|
||||
static ptr bvstring(const char *s) {
|
||||
iptr n = strlen(s) + 1;
|
||||
ptr x = S_bytevector(n);
|
||||
memcpy(&BVIT(x, 0), s, n);
|
||||
return x;
|
||||
}
|
||||
|
||||
/* multiplier weights each character, h = n factors in the length */
|
||||
static uptr symhash(const char *s) {
|
||||
uptr n, h;
|
||||
|
||||
h = n = strlen(s);
|
||||
while (n--) h = h * multiplier + (unsigned char)*s++;
|
||||
return h % buckets;
|
||||
}
|
||||
|
||||
static ptr lookup_static(const char *s) {
|
||||
uptr b; ptr p;
|
||||
|
||||
b = symhash(s);
|
||||
for (p = Svector_ref(S_G.foreign_static, b); p != Snil; p = Scdr(p))
|
||||
if (strcmp(s, (char *)&BVIT(Scar(Scar(p)),0)) == 0)
|
||||
return Scdr(Scar(p));
|
||||
|
||||
return addr_to_ptr(0);
|
||||
}
|
||||
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
#define LOOKUP_DYNAMIC
|
||||
static ptr lookup_dynamic(const char *s, ptr tbl) {
|
||||
ptr p;
|
||||
|
||||
for (p = tbl; p != Snil; p = Scdr(p)) {
|
||||
#ifdef HPUX
|
||||
(void *)value = (void *)0; /* assignment to prevent compiler warning */
|
||||
shl_t handle = (shl_t)ptr_to_addr(Scar(p));
|
||||
|
||||
if (shl_findsym(&handle, s, TYPE_PROCEDURE, (void *)&value) == 0)
|
||||
return addr_to_ptr(proc2entry(value, NULL));
|
||||
#else /* HPUX */
|
||||
void *value;
|
||||
|
||||
value = dlsym(ptr_to_addr(Scar(p)), s);
|
||||
if (value != (void *)0) return addr_to_ptr(value);
|
||||
#endif /* HPUX */
|
||||
}
|
||||
|
||||
return addr_to_ptr(0);
|
||||
}
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
|
||||
static ptr lookup(const char *s) {
|
||||
iptr b; ptr p;
|
||||
|
||||
#ifdef LOOKUP_DYNAMIC
|
||||
ptr x;
|
||||
|
||||
x = lookup_dynamic(s, S_foreign_dynamic);
|
||||
if (x == addr_to_ptr(0))
|
||||
#endif /* LOOKUP_DYNAMIC */
|
||||
|
||||
x = lookup_static(s);
|
||||
if (x == addr_to_ptr(0)) return x;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = ptrhash(x);
|
||||
for (p = Svector_ref(S_G.foreign_names, b); p != Snil; p = Scdr(p)) {
|
||||
if (Scar(Scar(p)) == x) {
|
||||
SETCDR(Scar(p),bvstring(s));
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
SETVECTIT(S_G.foreign_names, b, Scons(Scons(addr_to_ptr(x),bvstring(s)),
|
||||
Svector_ref(S_G.foreign_names, b)));
|
||||
|
||||
quit:
|
||||
tc_mutex_release()
|
||||
return x;
|
||||
}
|
||||
|
||||
void Sforeign_symbol(const char *s, void *v) {
|
||||
iptr b; ptr x;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
#ifdef HPUX
|
||||
v = proc2entry(v,name);
|
||||
#endif
|
||||
|
||||
if ((x = lookup(s)) == addr_to_ptr(0)) {
|
||||
b = symhash(s);
|
||||
SETVECTIT(S_G.foreign_static, b, Scons(Scons(bvstring(s), addr_to_ptr(v)),
|
||||
Svector_ref(S_G.foreign_static, b)));
|
||||
} else if (ptr_to_addr(x) != v)
|
||||
S_error1("Sforeign_symbol", "duplicate symbol entry for ~s", Sstring_utf8(s, -1));
|
||||
|
||||
tc_mutex_release()
|
||||
}
|
||||
|
||||
/* like Sforeign_symbol except it silently redefines the symbol
|
||||
if it's already in S_G.foreign_static */
|
||||
void Sregister_symbol(const char *s, void *v) {
|
||||
uptr b; ptr p;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = symhash(s);
|
||||
for (p = Svector_ref(S_G.foreign_static, b); p != Snil; p = Scdr(p))
|
||||
if (strcmp(s, (char *)&BVIT(Scar(Scar(p)),0)) == 0) {
|
||||
INITCDR(Scar(p)) = addr_to_ptr(v);
|
||||
goto quit;
|
||||
}
|
||||
SETVECTIT(S_G.foreign_static, b, Scons(Scons(bvstring(s), addr_to_ptr(v)),
|
||||
Svector_ref(S_G.foreign_static, b)));
|
||||
|
||||
quit:
|
||||
tc_mutex_release()
|
||||
}
|
||||
|
||||
static ptr remove_foreign_entry(const char *s) {
|
||||
uptr b;
|
||||
ptr tbl, p1, p2;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = symhash(s);
|
||||
tbl = S_G.foreign_static;
|
||||
p1 = Snil;
|
||||
p2 = Svector_ref(tbl, b);
|
||||
for (; p2 != Snil; p1 = p2, p2 = Scdr(p2)) {
|
||||
if (strcmp(s, (char *)&BVIT(Scar(Scar(p2)), 0)) == 0) {
|
||||
if (p1 == Snil) {
|
||||
SETVECTIT(tbl, b, Scdr(p2))
|
||||
} else {
|
||||
SETCDR(p1, Scdr(p2))
|
||||
}
|
||||
tc_mutex_release()
|
||||
return Strue;
|
||||
}
|
||||
}
|
||||
tc_mutex_release()
|
||||
return Sfalse;
|
||||
}
|
||||
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
static void load_shared_object(const char *path) {
|
||||
void *handle;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
handle = dlopen(path, RTLD_NOW);
|
||||
if (handle == (void *)NULL)
|
||||
S_error2("", "(while loading ~a) ~a", Sstring_utf8(path, -1), s_dlerror());
|
||||
S_foreign_dynamic = Scons(addr_to_ptr(handle), S_foreign_dynamic);
|
||||
|
||||
tc_mutex_release()
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
|
||||
void S_foreign_entry(void) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr name, x, bvname;
|
||||
iptr i, n;
|
||||
|
||||
name = AC0(tc);
|
||||
if (Sfixnump(name) || Sbignump(name)) {
|
||||
AC0(tc) = (ptr)Sinteger_value(name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(Sstringp(name))) {
|
||||
S_error1("foreign-procedure", "invalid foreign procedure handle ~s", name);
|
||||
}
|
||||
|
||||
n = Sstring_length(name);
|
||||
bvname = S_bytevector(n + 1);
|
||||
for (i = 0; i != n; i += 1) {
|
||||
int k = Sstring_ref(name, i);
|
||||
if (k >= 256) k = '?';
|
||||
BVIT(bvname, i) = k;
|
||||
}
|
||||
BVIT(bvname, n) = 0;
|
||||
|
||||
if ((x = lookup((char *)&BVIT(bvname, 0))) == addr_to_ptr(0)) {
|
||||
S_error1("foreign-procedure", "no entry for ~s", name);
|
||||
}
|
||||
|
||||
AC0(tc) = x;
|
||||
}
|
||||
|
||||
static void *lookup_foreign_entry(s) const char *s; {
|
||||
return ptr_to_addr(lookup(s));
|
||||
}
|
||||
|
||||
static ptr foreign_entries(void) {
|
||||
iptr b; ptr p, entries;
|
||||
|
||||
entries = Snil;
|
||||
|
||||
for (b = 0; b < buckets; b++)
|
||||
for (p = Svector_ref(S_G.foreign_static, b); p != Snil; p = Scdr(p))
|
||||
entries = Scons(Sstring_utf8((char *)&BVIT(Scar(Scar(p)), 0), -1), entries);
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
static ptr foreign_static_table(void) { return S_G.foreign_static; }
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
static ptr foreign_dynamic_table(void) { return S_foreign_dynamic; }
|
||||
#else
|
||||
static ptr foreign_dynamic_table(void) { return Sfalse; }
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
|
||||
static octet *foreign_address_name(ptr addr) {
|
||||
iptr b; ptr p;
|
||||
|
||||
b = ptrhash(addr);
|
||||
for (p = Svector_ref(S_G.foreign_names, b); p != Snil; p = Scdr(p))
|
||||
if (Scar(Scar(p)) == (ptr)addr)
|
||||
return &BVIT(Scdr(Scar(p)),0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void S_foreign_init(void) {
|
||||
if (S_boot_time) {
|
||||
S_protect(&S_G.foreign_static);
|
||||
S_G.foreign_static = S_vector(buckets);
|
||||
{iptr i; for (i = 0; i < buckets; i++) INITVECTIT(S_G.foreign_static,i) = Snil;}
|
||||
|
||||
S_protect(&S_G.foreign_names);
|
||||
S_G.foreign_names = S_vector(buckets);
|
||||
{iptr i; for (i = 0; i < buckets; i++) INITVECTIT(S_G.foreign_names,i) = Snil;}
|
||||
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
S_protect(&S_foreign_dynamic);
|
||||
S_foreign_dynamic = Snil;
|
||||
Sforeign_symbol("(cs)load_shared_object", (void *)load_shared_object);
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
|
||||
Sforeign_symbol("(cs)lookup_foreign_entry", (void *)lookup_foreign_entry);
|
||||
Sforeign_symbol("(cs)remove_foreign_entry", (void *)remove_foreign_entry);
|
||||
Sforeign_symbol("(cs)foreign_entries", (void *)foreign_entries);
|
||||
Sforeign_symbol("(cs)foreign_static_table", (void *)foreign_static_table);
|
||||
Sforeign_symbol("(cs)foreign_dynamic_table", (void *)foreign_dynamic_table);
|
||||
Sforeign_symbol("(cs)foreign_address_name", (void *)foreign_address_name);
|
||||
}
|
||||
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
S_foreign_dynamic = Snil;
|
||||
#endif /* LOAD_SHARED_OBJECT */
|
||||
}
|
BIN
ta6ob/c/foreign.o
Normal file
BIN
ta6ob/c/foreign.o
Normal file
Binary file not shown.
23
ta6ob/c/gc-011.c
Normal file
23
ta6ob/c/gc-011.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* gc-011.c
|
||||
* Copyright 1984-2020 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define GCENTRY S_gc_011
|
||||
#define MAX_CG 0
|
||||
#define MIN_TG 1
|
||||
#define MAX_TG 1
|
||||
#define compute_target_generation(g) 1
|
||||
#define NO_LOCKED_OLDSPACE_OBJECTS
|
||||
#include "gc.c"
|
BIN
ta6ob/c/gc-011.o
Normal file
BIN
ta6ob/c/gc-011.o
Normal file
Binary file not shown.
18
ta6ob/c/gc-ocd.c
Normal file
18
ta6ob/c/gc-ocd.c
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* gc-ocd.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define GCENTRY S_gc_ocd
|
||||
#include "gc.c"
|
BIN
ta6ob/c/gc-ocd.o
Normal file
BIN
ta6ob/c/gc-ocd.o
Normal file
Binary file not shown.
19
ta6ob/c/gc-oce.c
Normal file
19
ta6ob/c/gc-oce.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* gc-oce.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define GCENTRY S_gc_oce
|
||||
#define ENABLE_OBJECT_COUNTS
|
||||
#include "gc.c"
|
BIN
ta6ob/c/gc-oce.o
Normal file
BIN
ta6ob/c/gc-oce.o
Normal file
Binary file not shown.
2324
ta6ob/c/gc.c
Normal file
2324
ta6ob/c/gc.c
Normal file
File diff suppressed because it is too large
Load diff
864
ta6ob/c/gcwrapper.c
Normal file
864
ta6ob/c/gcwrapper.c
Normal file
|
@ -0,0 +1,864 @@
|
|||
/* gcwrapper.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* locally defined functions */
|
||||
static IBOOL memqp(ptr x, ptr ls);
|
||||
static IBOOL remove_first_nomorep(ptr x, ptr *pls, IBOOL look);
|
||||
static void segment_tell(uptr seg);
|
||||
static void check_heap_dirty_msg(char *msg, ptr *x);
|
||||
static IBOOL dirty_listedp(seginfo *x, IGEN from_g, IGEN to_g);
|
||||
static void check_dirty_space(ISPC s);
|
||||
static void check_dirty(void);
|
||||
|
||||
static IBOOL checkheap_noisy;
|
||||
|
||||
void S_gc_init(void) {
|
||||
IGEN g; INT i;
|
||||
|
||||
S_checkheap = 0; /* 0 for disabled, 1 for enabled */
|
||||
S_checkheap_errors = 0; /* count of errors detected by checkheap */
|
||||
checkheap_noisy = 0; /* 0 for error output only; 1 for more noisy output */
|
||||
S_G.prcgeneration = static_generation;
|
||||
|
||||
if (S_checkheap) {
|
||||
printf(checkheap_noisy ? "NB: check_heap is enabled and noisy\n" : "NB: check_heap_is_enabled\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
for (g = 0; g <= static_generation; g++) {
|
||||
S_child_processes[g] = Snil;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
if (!S_boot_time) return;
|
||||
|
||||
for (g = 0; g <= static_generation; g++) {
|
||||
S_G.guardians[g] = Snil;
|
||||
S_G.locked_objects[g] = Snil;
|
||||
S_G.unlocked_objects[g] = Snil;
|
||||
}
|
||||
S_G.max_nonstatic_generation =
|
||||
S_G.new_max_nonstatic_generation =
|
||||
S_G.min_free_gen =
|
||||
S_G.new_min_free_gen = default_max_nonstatic_generation;
|
||||
|
||||
for (g = 0; g <= static_generation; g += 1) {
|
||||
for (i = 0; i < countof_types; i += 1) {
|
||||
S_G.countof[g][i] = 0;
|
||||
S_G.bytesof[g][i] = 0;
|
||||
}
|
||||
S_G.gctimestamp[g] = 0;
|
||||
S_G.rtds_with_counts[g] = Snil;
|
||||
}
|
||||
|
||||
S_G.countof[static_generation][countof_oblist] += 1;
|
||||
S_G.bytesof[static_generation][countof_oblist] += S_G.oblist_length * sizeof(bucket *);
|
||||
|
||||
S_protect(&S_G.static_id);
|
||||
S_G.static_id = S_intern((const unsigned char *)"static");
|
||||
|
||||
S_protect(&S_G.countof_names);
|
||||
S_G.countof_names = S_vector(countof_types);
|
||||
for (i = 0; i < countof_types; i += 1) {
|
||||
INITVECTIT(S_G.countof_names, i) = FIX(0);
|
||||
S_G.countof_size[i] = 0;
|
||||
}
|
||||
INITVECTIT(S_G.countof_names, countof_pair) = S_intern((const unsigned char *)"pair");
|
||||
S_G.countof_size[countof_pair] = size_pair;
|
||||
INITVECTIT(S_G.countof_names, countof_symbol) = S_intern((const unsigned char *)"symbol");
|
||||
S_G.countof_size[countof_symbol] = size_symbol;
|
||||
INITVECTIT(S_G.countof_names, countof_flonum) = S_intern((const unsigned char *)"flonum");
|
||||
S_G.countof_size[countof_flonum] = size_flonum;
|
||||
INITVECTIT(S_G.countof_names, countof_closure) = S_intern((const unsigned char *)"procedure");
|
||||
S_G.countof_size[countof_closure] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_continuation) = S_intern((const unsigned char *)"continuation");
|
||||
S_G.countof_size[countof_continuation] = size_continuation;
|
||||
INITVECTIT(S_G.countof_names, countof_bignum) = S_intern((const unsigned char *)"bignum");
|
||||
S_G.countof_size[countof_bignum] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_ratnum) = S_intern((const unsigned char *)"ratnum");
|
||||
S_G.countof_size[countof_ratnum] = size_ratnum;
|
||||
INITVECTIT(S_G.countof_names, countof_inexactnum) = S_intern((const unsigned char *)"inexactnum");
|
||||
S_G.countof_size[countof_inexactnum] = size_inexactnum;
|
||||
INITVECTIT(S_G.countof_names, countof_exactnum) = S_intern((const unsigned char *)"exactnum");
|
||||
S_G.countof_size[countof_exactnum] = size_exactnum;
|
||||
INITVECTIT(S_G.countof_names, countof_box) = S_intern((const unsigned char *)"box");
|
||||
S_G.countof_size[countof_box] = size_box;
|
||||
INITVECTIT(S_G.countof_names, countof_port) = S_intern((const unsigned char *)"port");
|
||||
S_G.countof_size[countof_port] = size_port;
|
||||
INITVECTIT(S_G.countof_names, countof_code) = S_intern((const unsigned char *)"code");
|
||||
S_G.countof_size[countof_code] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_thread) = S_intern((const unsigned char *)"thread");
|
||||
S_G.countof_size[countof_thread] = size_thread;
|
||||
INITVECTIT(S_G.countof_names, countof_tlc) = S_intern((const unsigned char *)"tlc");
|
||||
S_G.countof_size[countof_tlc] = size_tlc;
|
||||
INITVECTIT(S_G.countof_names, countof_rtd_counts) = S_intern((const unsigned char *)"rtd-counts");
|
||||
S_G.countof_size[countof_rtd_counts] = size_rtd_counts;
|
||||
INITVECTIT(S_G.countof_names, countof_stack) = S_intern((const unsigned char *)"stack");
|
||||
S_G.countof_size[countof_stack] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_relocation_table) = S_intern((const unsigned char *)"reloc-table");
|
||||
S_G.countof_size[countof_relocation_table] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_weakpair) = S_intern((const unsigned char *)"weakpair");
|
||||
S_G.countof_size[countof_weakpair] = size_pair;
|
||||
INITVECTIT(S_G.countof_names, countof_vector) = S_intern((const unsigned char *)"vector");
|
||||
S_G.countof_size[countof_vector] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_string) = S_intern((const unsigned char *)"string");
|
||||
S_G.countof_size[countof_string] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_fxvector) = S_intern((const unsigned char *)"fxvector");
|
||||
S_G.countof_size[countof_fxvector] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_bytevector) = S_intern((const unsigned char *)"bytevector");
|
||||
S_G.countof_size[countof_bytevector] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_locked) = S_intern((const unsigned char *)"locked");
|
||||
S_G.countof_size[countof_locked] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_guardian) = S_intern((const unsigned char *)"guardian");
|
||||
S_G.countof_size[countof_guardian] = size_guardian_entry;
|
||||
INITVECTIT(S_G.countof_names, countof_oblist) = S_intern((const unsigned char *)"oblist");
|
||||
S_G.countof_size[countof_guardian] = 0;
|
||||
INITVECTIT(S_G.countof_names, countof_ephemeron) = S_intern((const unsigned char *)"ephemron");
|
||||
S_G.countof_size[countof_ephemeron] = 0;
|
||||
for (i = 0; i < countof_types; i += 1) {
|
||||
if (Svector_ref(S_G.countof_names, i) == FIX(0)) {
|
||||
fprintf(stderr, "uninitialized countof_name at index %d\n", i);
|
||||
S_abnormal_exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IGEN S_maxgen(void) {
|
||||
return S_G.new_max_nonstatic_generation;
|
||||
}
|
||||
|
||||
void S_set_maxgen(IGEN g) {
|
||||
if (g < 0 || g >= static_generation) {
|
||||
fprintf(stderr, "invalid maxgen %d\n", g);
|
||||
S_abnormal_exit();
|
||||
}
|
||||
if (S_G.new_min_free_gen == S_G.new_max_nonstatic_generation || S_G.new_min_free_gen > g) {
|
||||
S_G.new_min_free_gen = g;
|
||||
}
|
||||
S_G.new_max_nonstatic_generation = g;
|
||||
}
|
||||
|
||||
IGEN S_minfreegen(void) {
|
||||
return S_G.new_min_free_gen;
|
||||
}
|
||||
|
||||
void S_set_minfreegen(IGEN g) {
|
||||
S_G.new_min_free_gen = g;
|
||||
if (S_G.new_max_nonstatic_generation == S_G.max_nonstatic_generation) {
|
||||
S_G.min_free_gen = g;
|
||||
}
|
||||
}
|
||||
|
||||
static IBOOL memqp(ptr x, ptr ls) {
|
||||
for (;;) {
|
||||
if (ls == Snil) return 0;
|
||||
if (Scar(ls) == x) return 1;
|
||||
ls = Scdr(ls);
|
||||
}
|
||||
}
|
||||
|
||||
static IBOOL remove_first_nomorep(ptr x, ptr *pls, IBOOL look) {
|
||||
ptr ls;
|
||||
|
||||
for (;;) {
|
||||
ls = *pls;
|
||||
if (ls == Snil) break;
|
||||
if (Scar(ls) == x) {
|
||||
ls = Scdr(ls);
|
||||
*pls = ls;
|
||||
if (look) return !memqp(x, ls);
|
||||
break;
|
||||
}
|
||||
pls = &Scdr(ls);
|
||||
}
|
||||
|
||||
/* must return 0 if we don't look for more */
|
||||
return 0;
|
||||
}
|
||||
|
||||
IBOOL Slocked_objectp(ptr x) {
|
||||
seginfo *si; IGEN g; IBOOL ans; ptr ls;
|
||||
|
||||
if (IMMEDIATE(x) || (si = MaybeSegInfo(ptr_get_segment(x))) == NULL || (g = si->generation) == static_generation) return 1;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
ans = 0;
|
||||
for (ls = S_G.locked_objects[g]; ls != Snil; ls = Scdr(ls)) {
|
||||
if (x == Scar(ls)) {
|
||||
ans = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
ptr S_locked_objects(void) {
|
||||
IGEN g; ptr ans; ptr ls;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
ans = Snil;
|
||||
for (g = 0; g <= static_generation; INCRGEN(g)) {
|
||||
for (ls = S_G.locked_objects[g]; ls != Snil; ls = Scdr(ls)) {
|
||||
ans = Scons(Scar(ls), ans);
|
||||
}
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
void Slock_object(ptr x) {
|
||||
seginfo *si; IGEN g;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
/* weed out pointers that won't be relocated */
|
||||
if (!IMMEDIATE(x) && (si = MaybeSegInfo(ptr_get_segment(x))) != NULL && (g = si->generation) != static_generation) {
|
||||
S_pants_down += 1;
|
||||
/* add x to locked list. remove from unlocked list */
|
||||
S_G.locked_objects[g] = S_cons_in((g == 0 ? space_new : space_impure), g, x, S_G.locked_objects[g]);
|
||||
if (S_G.enable_object_counts) {
|
||||
if (g != 0) S_G.countof[g][countof_pair] += 1;
|
||||
}
|
||||
if (si->space & space_locked)
|
||||
(void)remove_first_nomorep(x, &S_G.unlocked_objects[g], 0);
|
||||
S_pants_down -= 1;
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
}
|
||||
|
||||
void Sunlock_object(ptr x) {
|
||||
seginfo *si; IGEN g;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
if (!IMMEDIATE(x) && (si = MaybeSegInfo(ptr_get_segment(x))) != NULL && (g = si->generation) != static_generation) {
|
||||
S_pants_down += 1;
|
||||
/* remove first occurrence of x from locked list. if there are no
|
||||
others, add x to unlocked list */
|
||||
if (remove_first_nomorep(x, &S_G.locked_objects[g], si->space & space_locked)) {
|
||||
S_G.unlocked_objects[g] = S_cons_in((g == 0 ? space_new : space_impure), g, x, S_G.unlocked_objects[g]);
|
||||
if (S_G.enable_object_counts) {
|
||||
if (g != 0) S_G.countof[g][countof_pair] += 1;
|
||||
}
|
||||
}
|
||||
S_pants_down -= 1;
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
}
|
||||
|
||||
ptr s_help_unregister_guardian(ptr *pls, ptr tconc, ptr result) {
|
||||
ptr rep, ls;
|
||||
while ((ls = *pls) != Snil) {
|
||||
if (GUARDIANTCONC(ls) == tconc) {
|
||||
result = Scons(((rep = GUARDIANREP(ls)) == ftype_guardian_rep ? GUARDIANOBJ(ls) : rep), result);
|
||||
*pls = ls = GUARDIANNEXT(ls);
|
||||
} else {
|
||||
ls = *(pls = &GUARDIANNEXT(ls));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ptr S_unregister_guardian(ptr tconc) {
|
||||
ptr result, tc; IGEN g;
|
||||
tc_mutex_acquire()
|
||||
tc = get_thread_context();
|
||||
/* in the interest of thread safety, gather entries only in the current thread, ignoring any others */
|
||||
result = s_help_unregister_guardian(&GUARDIANENTRIES(tc), tconc, Snil);
|
||||
/* plus, of course, any already known to the storage-management system */
|
||||
for (g = 0; g <= static_generation; INCRGEN(g)) {
|
||||
result = s_help_unregister_guardian(&S_G.guardians[g], tconc, result);
|
||||
}
|
||||
tc_mutex_release()
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
void S_register_child_process(INT child) {
|
||||
tc_mutex_acquire()
|
||||
S_child_processes[0] = Scons(FIX(child), S_child_processes[0]);
|
||||
tc_mutex_release()
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
IBOOL S_enable_object_counts(void) {
|
||||
return S_G.enable_object_counts;
|
||||
}
|
||||
|
||||
void S_set_enable_object_counts(IBOOL eoc) {
|
||||
S_G.enable_object_counts = eoc;
|
||||
}
|
||||
|
||||
ptr S_object_counts(void) {
|
||||
IGEN grtd, g; ptr ls; iptr i; ptr outer_alist;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
outer_alist = Snil;
|
||||
|
||||
/* add rtds w/nonozero counts to the alist */
|
||||
for (grtd = 0; grtd <= static_generation; INCRGEN(grtd)) {
|
||||
for (ls = S_G.rtds_with_counts[grtd]; ls != Snil; ls = Scdr(ls)) {
|
||||
ptr rtd = Scar(ls);
|
||||
ptr counts = RECORDDESCCOUNTS(rtd);
|
||||
IGEN g;
|
||||
uptr size = size_record_inst(UNFIX(RECORDDESCSIZE(rtd)));
|
||||
ptr inner_alist = Snil;
|
||||
|
||||
S_fixup_counts(counts);
|
||||
for (g = 0; g <= static_generation; INCRGEN(g)) {
|
||||
uptr count = RTDCOUNTSIT(counts, g); IGEN gcurrent = g;
|
||||
if (g == S_G.new_max_nonstatic_generation) {
|
||||
while (g < S_G.max_nonstatic_generation) {
|
||||
g += 1;
|
||||
count += RTDCOUNTSIT(counts, g);
|
||||
}
|
||||
}
|
||||
if (count != 0) inner_alist = Scons(Scons((gcurrent == static_generation ? S_G.static_id : FIX(gcurrent)), Scons(Sunsigned(count), Sunsigned(count * size))), inner_alist);
|
||||
}
|
||||
if (inner_alist != Snil) outer_alist = Scons(Scons(rtd, inner_alist), outer_alist);
|
||||
}
|
||||
}
|
||||
|
||||
/* add primary types w/nonozero counts to the alist */
|
||||
for (i = 0 ; i < countof_types; i += 1) {
|
||||
ptr inner_alist = Snil;
|
||||
for (g = 0; g <= static_generation; INCRGEN(g)) {
|
||||
IGEN gcurrent = g;
|
||||
uptr count = S_G.countof[g][i];
|
||||
uptr bytes = S_G.bytesof[g][i];
|
||||
|
||||
if (g == S_G.new_max_nonstatic_generation) {
|
||||
while (g < S_G.max_nonstatic_generation) {
|
||||
g += 1;
|
||||
/* NB: S_G.max_nonstatic_generation + 1 <= static_generation, but coverity complains about overrun */
|
||||
/* coverity[overrun-buffer-val] */
|
||||
count += S_G.countof[g][i];
|
||||
/* coverity[overrun-buffer-val] */
|
||||
bytes += S_G.bytesof[g][i];
|
||||
}
|
||||
}
|
||||
|
||||
if (count != 0) {
|
||||
if (bytes == 0) bytes = count * S_G.countof_size[i];
|
||||
inner_alist = Scons(Scons((gcurrent == static_generation ? S_G.static_id : FIX(gcurrent)), Scons(Sunsigned(count), Sunsigned(bytes))), inner_alist);
|
||||
}
|
||||
}
|
||||
if (inner_alist != Snil) outer_alist = Scons(Scons(Svector_ref(S_G.countof_names, i), inner_alist), outer_alist);
|
||||
}
|
||||
|
||||
tc_mutex_release()
|
||||
|
||||
return outer_alist;
|
||||
}
|
||||
|
||||
/* Scompact_heap(). Compact into as few O/S chunks as possible and
|
||||
* move objects into static generation
|
||||
*/
|
||||
void Scompact_heap(void) {
|
||||
ptr tc = get_thread_context();
|
||||
S_pants_down += 1;
|
||||
S_gc_oce(tc, S_G.max_nonstatic_generation, static_generation, static_generation);
|
||||
S_pants_down -= 1;
|
||||
}
|
||||
|
||||
/* S_check_heap checks for various kinds of heap consistency
|
||||
It currently checks for:
|
||||
dangling references in space_impure (generation > 0) and space_pure
|
||||
extra dirty bits
|
||||
missing dirty bits
|
||||
|
||||
Some additional things it should check for but doesn't:
|
||||
correct dirty bytes, following sweep_dirty conventions
|
||||
dangling references in in space_code and space_continuation
|
||||
dirty bits set for non-impure segments outside of generation zero
|
||||
proper chaining of segments of a space and generation:
|
||||
chains contain all and only the appropriate segments
|
||||
|
||||
If noisy is nonzero, additional comments may be included in the output
|
||||
*/
|
||||
|
||||
static void segment_tell(uptr seg) {
|
||||
seginfo *si;
|
||||
ISPC s, s1;
|
||||
static char *spacename[max_space+1] = { alloc_space_names };
|
||||
|
||||
printf("segment %#tx", (ptrdiff_t)seg);
|
||||
if ((si = MaybeSegInfo(seg)) == NULL) {
|
||||
printf(" out of heap bounds\n");
|
||||
} else {
|
||||
printf(" generation=%d", si->generation);
|
||||
s = si->space;
|
||||
s1 = si->space & ~(space_old|space_locked);
|
||||
if (s1 < 0 || s1 > max_space)
|
||||
printf(" space-bogus (%d)", s);
|
||||
else {
|
||||
printf(" space-%s", spacename[s1]);
|
||||
if (s & space_old) printf(" oldspace");
|
||||
if (s & space_locked) printf(" locked");
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void S_ptr_tell(ptr p) {
|
||||
segment_tell(ptr_get_segment(p));
|
||||
}
|
||||
|
||||
void S_addr_tell(ptr p) {
|
||||
segment_tell(addr_get_segment(p));
|
||||
}
|
||||
|
||||
static void check_heap_dirty_msg(char *msg, ptr *x) {
|
||||
INT d; seginfo *si;
|
||||
|
||||
si = SegInfo(addr_get_segment(x));
|
||||
d = (INT)(((uptr)x >> card_offset_bits) & ((1 << segment_card_offset_bits) - 1));
|
||||
printf("%s dirty byte %d found in segment %#tx, card %d at %#tx\n", msg, si->dirty_bytes[d], (ptrdiff_t)(si->number), d, (ptrdiff_t)x);
|
||||
printf("from "); segment_tell(addr_get_segment(x));
|
||||
printf("to "); segment_tell(addr_get_segment(*x));
|
||||
}
|
||||
|
||||
void S_check_heap(IBOOL aftergc) {
|
||||
uptr seg; INT d; ISPC s; IGEN g; IDIRTYBYTE dirty; IBOOL found_eos; IGEN pg;
|
||||
ptr p, *pp1, *pp2, *nl;
|
||||
iptr i;
|
||||
uptr empty_segments = 0;
|
||||
uptr used_segments = 0;
|
||||
uptr static_segments = 0;
|
||||
uptr nonstatic_segments = 0;
|
||||
|
||||
check_dirty();
|
||||
|
||||
for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) {
|
||||
chunkinfo *chunk = i == -1 ? S_chunks_full : S_chunks[i];
|
||||
while (chunk != NULL) {
|
||||
seginfo *si = chunk->unused_segs;
|
||||
iptr count = 0;
|
||||
while(si) {
|
||||
count += 1;
|
||||
if (si->space != space_empty) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! unused segment has unexpected space\n");
|
||||
}
|
||||
si = si->next;
|
||||
}
|
||||
if ((chunk->segs - count) != chunk->nused_segs) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! unexpected used segs count %td with %td total segs and %td segs on the unused list\n",
|
||||
(ptrdiff_t)chunk->nused_segs, (ptrdiff_t)chunk->segs, (ptrdiff_t)count);
|
||||
}
|
||||
used_segments += chunk->nused_segs;
|
||||
empty_segments += count;
|
||||
chunk = chunk->next;
|
||||
}
|
||||
}
|
||||
|
||||
for (s = 0; s <= max_real_space; s += 1) {
|
||||
seginfo *si;
|
||||
for (g = 0; g <= S_G.max_nonstatic_generation; INCRGEN(g)) {
|
||||
for (si = S_G.occupied_segments[g][s]; si != NULL; si = si->next) {
|
||||
nonstatic_segments += 1;
|
||||
}
|
||||
}
|
||||
for (si = S_G.occupied_segments[static_generation][s]; si != NULL; si = si->next) {
|
||||
static_segments += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (used_segments != nonstatic_segments + static_segments) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! found %#tx used segments and %#tx occupied segments\n",
|
||||
(ptrdiff_t)used_segments,
|
||||
(ptrdiff_t)(nonstatic_segments + static_segments));
|
||||
}
|
||||
|
||||
if (S_G.number_of_nonstatic_segments != nonstatic_segments) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! S_G.number_of_nonstatic_segments %#tx is different from occupied number %#tx\n",
|
||||
(ptrdiff_t)S_G.number_of_nonstatic_segments,
|
||||
(ptrdiff_t)nonstatic_segments);
|
||||
}
|
||||
|
||||
if (S_G.number_of_empty_segments != empty_segments) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! S_G.number_of_empty_segments %#tx is different from unused number %#tx\n",
|
||||
(ptrdiff_t)S_G.number_of_empty_segments,
|
||||
(ptrdiff_t)empty_segments);
|
||||
}
|
||||
|
||||
for (i = PARTIAL_CHUNK_POOLS; i >= -1; i -= 1) {
|
||||
chunkinfo *chunk = i == -1 ? S_chunks_full : S_chunks[i];
|
||||
while (chunk != NULL) {
|
||||
uptr nsegs; seginfo *si;
|
||||
for (si = &chunk->sis[0], nsegs = chunk->segs; nsegs != 0; nsegs -= 1, si += 1) {
|
||||
seginfo *recorded_si; uptr recorded_seg;
|
||||
if ((seg = si->number) != (recorded_seg = (chunk->base + chunk->segs - nsegs))) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! recorded segment number %#tx differs from actual segment number %#tx", (ptrdiff_t)seg, (ptrdiff_t)recorded_seg);
|
||||
}
|
||||
if ((recorded_si = SegInfo(seg)) != si) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! recorded segment %#tx seginfo %#tx differs from actual seginfo %#tx", (ptrdiff_t)seg, (ptrdiff_t)recorded_si, (ptrdiff_t)si);
|
||||
}
|
||||
s = si->space;
|
||||
g = si->generation;
|
||||
|
||||
if (s == space_new) {
|
||||
if (g != 0) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! unexpected generation %d segment %#tx in space_new\n", g, (ptrdiff_t)seg);
|
||||
}
|
||||
} else if (s == space_impure || s == space_symbol || s == space_pure || s == space_weakpair /* || s == space_ephemeron */) {
|
||||
/* out of date: doesn't handle space_port, space_continuation, space_code, space_pure_typed_object, space_impure_record */
|
||||
nl = (ptr *)S_G.next_loc[g][s];
|
||||
|
||||
/* check for dangling references */
|
||||
pp1 = (ptr *)build_ptr(seg, 0);
|
||||
pp2 = (ptr *)build_ptr(seg + 1, 0);
|
||||
if (pp1 <= nl && nl < pp2) pp2 = nl;
|
||||
|
||||
while (pp1 != pp2) {
|
||||
seginfo *psi; ISPC ps;
|
||||
p = *pp1;
|
||||
if (p == forward_marker) break;
|
||||
if (!IMMEDIATE(p) && (psi = MaybeSegInfo(ptr_get_segment(p))) != NULL && ((ps = psi->space) & space_old || ps == space_empty)) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! dangling reference at %#tx to %#tx\n", (ptrdiff_t)pp1, (ptrdiff_t)p);
|
||||
printf("from: "); segment_tell(seg);
|
||||
printf("to: "); segment_tell(ptr_get_segment(p));
|
||||
}
|
||||
pp1 += 1;
|
||||
}
|
||||
|
||||
/* verify that dirty bits are set appropriately */
|
||||
/* out of date: doesn't handle space_impure_record, space_port, and maybe others */
|
||||
/* also doesn't check the SYMCODE for symbols */
|
||||
if (s == space_impure || s == space_symbol || s == space_weakpair /* || s == space_ephemeron */) {
|
||||
found_eos = 0;
|
||||
pp2 = pp1 = build_ptr(seg, 0);
|
||||
for (d = 0; d < cards_per_segment; d += 1) {
|
||||
if (found_eos) {
|
||||
if (si->dirty_bytes[d] != 0xff) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! Dirty byte set past end-of-segment for segment %#tx, card %d\n", (ptrdiff_t)seg, d);
|
||||
segment_tell(seg);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
pp2 += bytes_per_card / sizeof(ptr);
|
||||
if (pp1 <= nl && nl < pp2) {
|
||||
found_eos = 1;
|
||||
pp2 = nl;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("pp1 = %#tx, pp2 = %#tx, nl = %#tx\n", (ptrdiff_t)pp1, (ptrdiff_t)pp2, (ptrdiff_t)nl);
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
dirty = 0xff;
|
||||
while (pp1 != pp2) {
|
||||
seginfo *psi;
|
||||
p = *pp1;
|
||||
|
||||
if (p == forward_marker) {
|
||||
found_eos = 1;
|
||||
break;
|
||||
}
|
||||
if (!IMMEDIATE(p) && (psi = MaybeSegInfo(ptr_get_segment(p))) != NULL && (pg = psi->generation) < g) {
|
||||
if (pg < dirty) dirty = pg;
|
||||
if (si->dirty_bytes[d] > pg) {
|
||||
S_checkheap_errors += 1;
|
||||
check_heap_dirty_msg("!!! INVALID", pp1);
|
||||
}
|
||||
else if (checkheap_noisy)
|
||||
check_heap_dirty_msg("... ", pp1);
|
||||
}
|
||||
pp1 += 1;
|
||||
}
|
||||
if (checkheap_noisy && si->dirty_bytes[d] < dirty) {
|
||||
/* sweep_dirty won't sweep, and update dirty byte, for
|
||||
cards with dirty pointers to segments older than the
|
||||
maximum copied generation, so we can get legitimate
|
||||
conservative dirty bytes even after gc */
|
||||
printf("... Conservative dirty byte %x (%x) %sfor segment %#tx card %d ",
|
||||
si->dirty_bytes[d], dirty,
|
||||
(aftergc ? "after gc " : ""),
|
||||
(ptrdiff_t)seg, d);
|
||||
segment_tell(seg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aftergc && s != space_empty && !(s & space_locked) && (g == 0 || (s != space_impure && s != space_symbol && s != space_port && s != space_weakpair && s != space_ephemeron && s != space_impure_record))) {
|
||||
for (d = 0; d < cards_per_segment; d += 1) {
|
||||
if (si->dirty_bytes[d] != 0xff) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! Unnecessary dirty byte %x (%x) after gc for segment %#tx card %d ",
|
||||
si->dirty_bytes[d], 0xff, (ptrdiff_t)(si->number), d);
|
||||
segment_tell(seg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
chunk = chunk->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static IBOOL dirty_listedp(seginfo *x, IGEN from_g, IGEN to_g) {
|
||||
seginfo *si = DirtySegments(from_g, to_g);
|
||||
while (si != NULL) {
|
||||
if (si == x) return 1;
|
||||
si = si->dirty_next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void check_dirty_space(ISPC s) {
|
||||
IGEN from_g, to_g, min_to_g; INT d; seginfo *si;
|
||||
|
||||
for (from_g = 0; from_g <= static_generation; from_g += 1) {
|
||||
for (si = S_G.occupied_segments[from_g][s]; si != NULL; si = si->next) {
|
||||
if (si->space & space_locked) continue;
|
||||
min_to_g = 0xff;
|
||||
for (d = 0; d < cards_per_segment; d += 1) {
|
||||
to_g = si->dirty_bytes[d];
|
||||
if (to_g != 0xff) {
|
||||
if (to_g < min_to_g) min_to_g = to_g;
|
||||
if (from_g == 0) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): space %d, generation %d segment %#tx card %d is marked dirty\n", s, from_g, (ptrdiff_t)(si->number), d);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (min_to_g != si->min_dirty_byte) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): space %d, generation %d segment %#tx min_dirty_byte is %d while actual min is %d\n", s, from_g, (ptrdiff_t)(si->number), si->min_dirty_byte, min_to_g);
|
||||
segment_tell(si->number);
|
||||
} else if (min_to_g != 0xff) {
|
||||
if (!dirty_listedp(si, from_g, min_to_g)) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): space %d, generation %d segment %#tx is marked dirty but not in dirty-segment list\n", s, from_g, (ptrdiff_t)(si->number));
|
||||
segment_tell(si->number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void check_dirty(void) {
|
||||
IGEN from_g, to_g; seginfo *si;
|
||||
|
||||
for (from_g = 1; from_g <= static_generation; from_g = from_g == S_G.max_nonstatic_generation ? static_generation : from_g + 1) {
|
||||
for (to_g = 0; (from_g == static_generation) ? (to_g <= S_G.max_nonstatic_generation) : (to_g < from_g); to_g += 1) {
|
||||
si = DirtySegments(from_g, to_g);
|
||||
if (from_g > S_G.max_nonstatic_generation && from_g != static_generation) {
|
||||
if (si != NULL) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): unexpected nonempty from-generation %d, to-generation %d dirty segment list\n", from_g, to_g);
|
||||
}
|
||||
} else {
|
||||
while (si != NULL) {
|
||||
ISPC s = si->space & ~space_locked;
|
||||
IGEN g = si->generation;
|
||||
IGEN mingval = si->min_dirty_byte;
|
||||
if (g != from_g) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): generation %d segment %#tx in %d -> %d dirty list\n", g, (ptrdiff_t)(si->number), from_g, to_g);
|
||||
}
|
||||
if (mingval != to_g) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): dirty byte = %d for segment %#tx in %d -> %d dirty list\n", mingval, (ptrdiff_t)(si->number), from_g, to_g);
|
||||
}
|
||||
if (s != space_new && s != space_impure && s != space_symbol && s != space_port && s != space_impure_record && s != space_weakpair && s != space_ephemeron) {
|
||||
S_checkheap_errors += 1;
|
||||
printf("!!! (check_dirty): unexpected space %d for dirty segment %#tx\n", s, (ptrdiff_t)(si->number));
|
||||
}
|
||||
si = si->dirty_next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check_dirty_space(space_impure);
|
||||
check_dirty_space(space_symbol);
|
||||
check_dirty_space(space_port);
|
||||
check_dirty_space(space_impure_record);
|
||||
check_dirty_space(space_weakpair);
|
||||
check_dirty_space(space_ephemeron);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void S_fixup_counts(ptr counts) {
|
||||
IGEN g; U64 timestamp;
|
||||
|
||||
timestamp = RTDCOUNTSTIMESTAMP(counts);
|
||||
for (g = 0; g <= static_generation; INCRGEN(g)) {
|
||||
if (timestamp >= S_G.gctimestamp[g]) break;
|
||||
RTDCOUNTSIT(counts, g) = 0;
|
||||
}
|
||||
RTDCOUNTSTIMESTAMP(counts) = S_G.gctimestamp[0];
|
||||
}
|
||||
|
||||
void S_do_gc(IGEN max_cg, IGEN min_tg, IGEN max_tg) {
|
||||
ptr tc = get_thread_context();
|
||||
ptr code;
|
||||
|
||||
code = CP(tc);
|
||||
if (Sprocedurep(code)) code = CLOSCODE(code);
|
||||
Slock_object(code);
|
||||
|
||||
/* Scheme side grabs mutex before calling S_do_gc */
|
||||
S_pants_down += 1;
|
||||
|
||||
if (S_G.new_max_nonstatic_generation > S_G.max_nonstatic_generation) {
|
||||
S_G.min_free_gen = S_G.new_min_free_gen;
|
||||
S_G.max_nonstatic_generation = S_G.new_max_nonstatic_generation;
|
||||
}
|
||||
|
||||
if (max_tg == max_cg && max_cg == S_G.new_max_nonstatic_generation && max_cg < S_G.max_nonstatic_generation) {
|
||||
IGEN new_g, old_g, from_g, to_g; ISPC s; seginfo *si, *nextsi, *tail;
|
||||
/* reducing max_nonstatic_generation */
|
||||
new_g = S_G.new_max_nonstatic_generation;
|
||||
old_g = S_G.max_nonstatic_generation;
|
||||
/* first, collect everything to old_g, ignoring min_tg */
|
||||
S_gc(tc, old_g, old_g, old_g);
|
||||
/* now transfer old_g info to new_g, and clear old_g info */
|
||||
S_G.bytes_of_generation[new_g] = S_G.bytes_of_generation[old_g]; S_G.bytes_of_generation[old_g] = 0;
|
||||
for (s = 0; s <= max_real_space; s += 1) {
|
||||
S_G.first_loc[new_g][s] = S_G.first_loc[old_g][s]; S_G.first_loc[old_g][s] = FIX(0);
|
||||
S_G.base_loc[new_g][s] = S_G.base_loc[old_g][s]; S_G.base_loc[old_g][s] = FIX(0);
|
||||
S_G.next_loc[new_g][s] = S_G.next_loc[old_g][s]; S_G.next_loc[old_g][s] = FIX(0);
|
||||
S_G.bytes_left[new_g][s] = S_G.bytes_left[old_g][s]; S_G.bytes_left[old_g][s] = 0;
|
||||
S_G.bytes_of_space[new_g][s] = S_G.bytes_of_space[old_g][s]; S_G.bytes_of_space[old_g][s] = 0;
|
||||
S_G.occupied_segments[new_g][s] = S_G.occupied_segments[old_g][s]; S_G.occupied_segments[old_g][s] = NULL;
|
||||
for (si = S_G.occupied_segments[new_g][s]; si != NULL; si = si->next) {
|
||||
si->generation = new_g;
|
||||
}
|
||||
}
|
||||
S_G.guardians[new_g] = S_G.guardians[old_g]; S_G.guardians[old_g] = Snil;
|
||||
S_G.locked_objects[new_g] = S_G.locked_objects[old_g]; S_G.locked_objects[old_g] = Snil;
|
||||
S_G.unlocked_objects[new_g] = S_G.unlocked_objects[old_g]; S_G.unlocked_objects[old_g] = Snil;
|
||||
S_G.buckets_of_generation[new_g] = S_G.buckets_of_generation[old_g]; S_G.buckets_of_generation[old_g] = NULL;
|
||||
if (S_G.enable_object_counts) {
|
||||
INT i; ptr ls;
|
||||
for (i = 0; i < countof_types; i += 1) {
|
||||
S_G.countof[new_g][i] = S_G.countof[old_g][i]; S_G.countof[old_g][i] = 0;
|
||||
S_G.bytesof[new_g][i] = S_G.bytesof[old_g][i]; S_G.bytesof[old_g][i] = 0;
|
||||
}
|
||||
S_G.rtds_with_counts[new_g] = S_G.rtds_with_counts[old_g]; S_G.rtds_with_counts[old_g] = Snil;
|
||||
for (ls = S_G.rtds_with_counts[new_g]; ls != Snil; ls = Scdr(ls)) {
|
||||
ptr counts = RECORDDESCCOUNTS(Scar(ls));
|
||||
RTDCOUNTSIT(counts, new_g) = RTDCOUNTSIT(counts, old_g); RTDCOUNTSIT(counts, old_g) = 0;
|
||||
}
|
||||
for (ls = S_G.rtds_with_counts[static_generation]; ls != Snil; ls = Scdr(ls)) {
|
||||
ptr counts = RECORDDESCCOUNTS(Scar(ls));
|
||||
RTDCOUNTSIT(counts, new_g) = RTDCOUNTSIT(counts, old_g); RTDCOUNTSIT(counts, old_g) = 0;
|
||||
}
|
||||
}
|
||||
#ifndef WIN32
|
||||
S_child_processes[new_g] = S_child_processes[old_g];
|
||||
#endif
|
||||
|
||||
/* change old_g dirty bytes in static generation to new_g; splice list of old_g
|
||||
seginfos onto front of new_g seginfos */
|
||||
for (from_g = 1; from_g <= static_generation; INCRGEN(from_g)) {
|
||||
for (to_g = 0; (from_g == static_generation) ? (to_g <= S_G.max_nonstatic_generation) : (to_g < from_g); to_g += 1) {
|
||||
if ((si = DirtySegments(from_g, to_g)) != NULL) {
|
||||
if (from_g == old_g) {
|
||||
DirtySegments(from_g, to_g) = NULL;
|
||||
DirtySegments(new_g, to_g) = si;
|
||||
si->dirty_prev = &DirtySegments(new_g, to_g);
|
||||
} else if (from_g == static_generation) {
|
||||
if (to_g == old_g) {
|
||||
DirtySegments(from_g, to_g) = NULL;
|
||||
tail = DirtySegments(from_g, new_g);
|
||||
DirtySegments(from_g, new_g) = si;
|
||||
si->dirty_prev = &DirtySegments(from_g, new_g);
|
||||
for (;;) {
|
||||
INT d;
|
||||
si->min_dirty_byte = new_g;
|
||||
for (d = 0; d < cards_per_segment; d += 1) {
|
||||
if (si->dirty_bytes[d] == old_g) si->dirty_bytes[d] = new_g;
|
||||
}
|
||||
nextsi = si->dirty_next;
|
||||
if (nextsi == NULL) break;
|
||||
si = nextsi;
|
||||
}
|
||||
if (tail != NULL) tail->dirty_prev = &si->dirty_next;
|
||||
si->dirty_next = tail;
|
||||
} else {
|
||||
do {
|
||||
INT d;
|
||||
for (d = 0; d < cards_per_segment; d += 1) {
|
||||
if (si->dirty_bytes[d] == old_g) si->dirty_bytes[d] = new_g;
|
||||
}
|
||||
si = si->dirty_next;
|
||||
} while (si != NULL);
|
||||
}
|
||||
} else {
|
||||
S_error_abort("S_do_gc(gc): unexpected nonempty dirty segment list");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* tell profile_release_counters to scan only through new_g */
|
||||
if (S_G.prcgeneration == old_g) S_G.prcgeneration = new_g;
|
||||
|
||||
/* finally reset max_nonstatic_generation */
|
||||
S_G.min_free_gen = S_G.new_min_free_gen;
|
||||
S_G.max_nonstatic_generation = new_g;
|
||||
} else {
|
||||
S_gc(tc, max_cg, min_tg, max_tg);
|
||||
}
|
||||
|
||||
/* eagerly give collecting thread, the only one guaranteed to be
|
||||
active, a fresh allocation area. the other threads have to trap
|
||||
to get_more_room if and when they awake and try to allocate */
|
||||
S_reset_allocation_pointer(tc);
|
||||
|
||||
S_pants_down -= 1;
|
||||
|
||||
Sunlock_object(code);
|
||||
}
|
||||
|
||||
|
||||
void S_gc(ptr tc, IGEN max_cg, IGEN min_tg, IGEN max_tg) {
|
||||
if (max_cg == 0 && min_tg == 1 && max_tg == 1 && S_G.locked_objects[0] == Snil)
|
||||
S_gc_011(tc);
|
||||
else if (max_tg == static_generation || S_G.enable_object_counts)
|
||||
S_gc_oce(tc, max_cg, min_tg, max_tg);
|
||||
else
|
||||
S_gc_ocd(tc, max_cg, min_tg, max_tg);
|
||||
}
|
BIN
ta6ob/c/gcwrapper.o
Normal file
BIN
ta6ob/c/gcwrapper.o
Normal file
Binary file not shown.
156
ta6ob/c/globals.h
Normal file
156
ta6ob/c/globals.h
Normal file
|
@ -0,0 +1,156 @@
|
|||
/* globals.h
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* globals that do NOT need to be preserved in a saved heap.
|
||||
* they must be initialized each time the system is brought up. */
|
||||
|
||||
/* gc.c */
|
||||
EXTERN IBOOL S_checkheap;
|
||||
EXTERN uptr S_checkheap_errors;
|
||||
#ifndef WIN32
|
||||
EXTERN ptr S_child_processes[static_generation+1];
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* scheme.c */
|
||||
EXTERN IBOOL S_boot_time;
|
||||
EXTERN IBOOL S_errors_to_console;
|
||||
EXTERN ptr S_threads;
|
||||
EXTERN uptr S_nthreads;
|
||||
EXTERN uptr S_pagesize;
|
||||
EXTERN void (*S_abnormal_exit_proc)();
|
||||
EXTERN char *Sschemeheapdirs;
|
||||
EXTERN char *Sdefaultheapdirs;
|
||||
#ifdef PTHREADS
|
||||
EXTERN s_thread_key_t S_tc_key;
|
||||
EXTERN scheme_mutex_t S_tc_mutex;
|
||||
EXTERN s_thread_cond_t S_collect_cond;
|
||||
EXTERN INT S_tc_mutex_depth;
|
||||
#endif
|
||||
|
||||
/* segment.c */
|
||||
#ifdef segment_t2_bits
|
||||
#ifdef segment_t3_bits
|
||||
EXTERN t2table *S_segment_info[1<<segment_t3_bits];
|
||||
#else
|
||||
EXTERN t1table *S_segment_info[1<<segment_t2_bits];
|
||||
#endif
|
||||
#else
|
||||
EXTERN seginfo *S_segment_info[1<<segment_t1_bits];
|
||||
#endif
|
||||
|
||||
EXTERN chunkinfo *S_chunks_full;
|
||||
EXTERN chunkinfo *S_chunks[PARTIAL_CHUNK_POOLS+1];
|
||||
|
||||
/* schsig.c */
|
||||
EXTERN IBOOL S_pants_down;
|
||||
|
||||
/* foreign.c */
|
||||
#ifdef LOAD_SHARED_OBJECT
|
||||
EXTERN ptr S_foreign_dynamic;
|
||||
#endif
|
||||
|
||||
/* globals that do need to be preserved in a saved heap */
|
||||
EXTERN struct S_G_struct {
|
||||
/* scheme.c */
|
||||
double thread_context[size_tc / sizeof(double)];
|
||||
ptr active_threads_id;
|
||||
ptr error_invoke_code_object;
|
||||
ptr invoke_code_object;
|
||||
ptr dummy_code_object;
|
||||
ptr heap_reserve_ratio_id;
|
||||
IBOOL retain_static_relocation;
|
||||
IBOOL enable_object_counts;
|
||||
ptr scheme_version_id;
|
||||
ptr make_load_binary_id;
|
||||
ptr load_binary;
|
||||
ptr profile_counters;
|
||||
|
||||
/* foreign.c */
|
||||
ptr foreign_static;
|
||||
ptr foreign_names;
|
||||
|
||||
/* thread.c */
|
||||
ptr threadno;
|
||||
|
||||
/* segment.c */
|
||||
seginfo *occupied_segments[static_generation+1][max_real_space+1];
|
||||
uptr number_of_nonstatic_segments;
|
||||
uptr number_of_empty_segments;
|
||||
|
||||
/* alloc.c */
|
||||
ptr *protected[max_protected];
|
||||
uptr protect_next;
|
||||
ptr first_loc[static_generation+1][max_real_space+1];
|
||||
ptr base_loc[static_generation+1][max_real_space+1];
|
||||
ptr next_loc[static_generation+1][max_real_space+1];
|
||||
iptr bytes_left[static_generation+1][max_real_space+1];
|
||||
uptr bytes_of_space[static_generation+1][max_real_space+1];
|
||||
uptr bytes_of_generation[static_generation+1];
|
||||
uptr g0_bytes_after_last_gc;
|
||||
uptr collect_trip_bytes;
|
||||
ptr nonprocedure_code;
|
||||
ptr null_string;
|
||||
ptr null_vector;
|
||||
ptr null_fxvector;
|
||||
ptr null_bytevector;
|
||||
seginfo *dirty_segments[DIRTY_SEGMENT_LISTS];
|
||||
|
||||
/* schsig.c */
|
||||
ptr error_id;
|
||||
ptr nuate_id;
|
||||
ptr null_continuation_id;
|
||||
ptr collect_request_pending_id;
|
||||
|
||||
/* gc.c */
|
||||
ptr guardians[static_generation+1];
|
||||
ptr locked_objects[static_generation+1];
|
||||
ptr unlocked_objects[static_generation+1];
|
||||
IGEN min_free_gen;
|
||||
IGEN new_min_free_gen;
|
||||
IGEN max_nonstatic_generation;
|
||||
IGEN new_max_nonstatic_generation;
|
||||
uptr countof[static_generation+1][countof_types];
|
||||
uptr bytesof[static_generation+1][countof_types];
|
||||
uptr gctimestamp[static_generation+1];
|
||||
ptr rtds_with_counts[static_generation+1];
|
||||
uptr countof_size[countof_types];
|
||||
ptr static_id;
|
||||
ptr countof_names;
|
||||
IGEN prcgeneration;
|
||||
|
||||
/* intern.c */
|
||||
iptr *oblist_length_pointer;
|
||||
iptr oblist_length;
|
||||
iptr oblist_count;
|
||||
bucket **oblist;
|
||||
bucket_list *buckets_of_generation[static_generation];
|
||||
|
||||
/* prim.c */
|
||||
ptr library_entry_vector;
|
||||
ptr c_entry_vector;
|
||||
|
||||
/* fasl.c */
|
||||
ptr base_rtd;
|
||||
ptr rtd_key;
|
||||
ptr eq_symbol;
|
||||
ptr eq_ht_rtd;
|
||||
ptr symbol_symbol;
|
||||
ptr symbol_ht_rtd;
|
||||
ptr eqp;
|
||||
ptr eqvp;
|
||||
ptr equalp;
|
||||
ptr symboleqp;
|
||||
} S_G;
|
26
ta6ob/c/i3le.c
Normal file
26
ta6ob/c/i3le.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
/* i3le.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef FLUSHCACHE
|
||||
oops, no S_flushcache_max_gap or S_doflush
|
||||
#endif /* FLUSHCACHE */
|
||||
|
||||
void S_machine_init(void) {}
|
BIN
ta6ob/c/i3le.o
Normal file
BIN
ta6ob/c/i3le.o
Normal file
Binary file not shown.
389
ta6ob/c/intern.c
Normal file
389
ta6ob/c/intern.c
Normal file
|
@ -0,0 +1,389 @@
|
|||
/* intern.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
|
||||
/* locally defined functions */
|
||||
static void oblist_insert(ptr sym, iptr idx, IGEN g);
|
||||
static iptr hash(const unsigned char *s, iptr n);
|
||||
static iptr hash_sc(const string_char *s, iptr n);
|
||||
static iptr hash_uname(const string_char *s, iptr n);
|
||||
static ptr mkstring(const string_char *s, iptr n);
|
||||
|
||||
/* list of some primes to use for oblist sizes */
|
||||
#if (ptr_bits == 32)
|
||||
static iptr oblist_lengths[] = {
|
||||
1031,
|
||||
2053,
|
||||
4099,
|
||||
8209,
|
||||
16411,
|
||||
32771,
|
||||
65537,
|
||||
131101,
|
||||
262147,
|
||||
524309,
|
||||
1048583,
|
||||
2097169,
|
||||
4194319,
|
||||
8388617,
|
||||
16777259,
|
||||
33554467,
|
||||
67108879,
|
||||
134217757,
|
||||
268435459,
|
||||
536870923,
|
||||
1073741827,
|
||||
0};
|
||||
#endif
|
||||
#if (ptr_bits == 64)
|
||||
static iptr oblist_lengths[] = {
|
||||
1031,
|
||||
2053,
|
||||
4099,
|
||||
8209,
|
||||
16411,
|
||||
32771,
|
||||
65537,
|
||||
131101,
|
||||
262147,
|
||||
524309,
|
||||
1048583,
|
||||
2097169,
|
||||
4194319,
|
||||
8388617,
|
||||
16777259,
|
||||
33554467,
|
||||
67108879,
|
||||
134217757,
|
||||
268435459,
|
||||
536870923,
|
||||
1073741827,
|
||||
2147483659,
|
||||
4294967311,
|
||||
8589934609,
|
||||
17179869209,
|
||||
34359738421,
|
||||
68719476767,
|
||||
137438953481,
|
||||
274877906951,
|
||||
549755813911,
|
||||
1099511627791,
|
||||
2199023255579,
|
||||
4398046511119,
|
||||
8796093022237,
|
||||
17592186044423,
|
||||
35184372088891,
|
||||
70368744177679,
|
||||
140737488355333,
|
||||
281474976710677,
|
||||
562949953421381,
|
||||
1125899906842679,
|
||||
2251799813685269,
|
||||
4503599627370517,
|
||||
9007199254740997,
|
||||
18014398509482143,
|
||||
36028797018963971,
|
||||
72057594037928017,
|
||||
144115188075855881,
|
||||
288230376151711813,
|
||||
576460752303423619,
|
||||
1152921504606847009,
|
||||
2305843009213693967,
|
||||
4611686018427388039,
|
||||
0};
|
||||
#endif
|
||||
|
||||
void S_intern_init(void) {
|
||||
IGEN g;
|
||||
|
||||
if (!S_boot_time) return;
|
||||
|
||||
S_G.oblist_length_pointer = &oblist_lengths[3];
|
||||
S_G.oblist_length = *S_G.oblist_length_pointer;
|
||||
S_G.oblist_count = 0;
|
||||
S_G.oblist = S_getmem(S_G.oblist_length * sizeof(bucket *), 1);
|
||||
for (g = 0; g < static_generation; g += 1) S_G.buckets_of_generation[g] = NULL;
|
||||
}
|
||||
|
||||
static void oblist_insert(ptr sym, iptr idx, IGEN g) {
|
||||
bucket *b, *oldb, **pb;
|
||||
|
||||
find_room(g == 0 ? space_new : space_data, g, typemod, sizeof(bucket), b);
|
||||
b->sym = sym;
|
||||
if (g == 0) {
|
||||
b->next = S_G.oblist[idx];
|
||||
S_G.oblist[idx] = b;
|
||||
} else {
|
||||
for (pb = &S_G.oblist[idx]; (oldb = *pb) != NULL && SegmentGeneration(addr_get_segment(oldb)) < g; pb = &oldb->next);
|
||||
b->next = oldb;
|
||||
*pb = b;
|
||||
}
|
||||
|
||||
if (g != static_generation) {
|
||||
bucket_list *bl;
|
||||
find_room(g == 0 ? space_new : space_data, g, typemod, sizeof(bucket_list), bl);
|
||||
bl->car = b;
|
||||
bl->cdr = S_G.buckets_of_generation[g];
|
||||
S_G.buckets_of_generation[g] = bl;
|
||||
}
|
||||
|
||||
S_G.oblist_count += 1;
|
||||
}
|
||||
|
||||
void S_resize_oblist(void) {
|
||||
bucket **new_oblist, *b, *oldb, **pb, *bnext;
|
||||
iptr *new_oblist_length_pointer, new_oblist_length, i, idx;
|
||||
ptr sym;
|
||||
IGEN g;
|
||||
|
||||
new_oblist_length_pointer = S_G.oblist_length_pointer;
|
||||
|
||||
if (S_G.oblist_count < S_G.oblist_length) {
|
||||
while (new_oblist_length_pointer != &oblist_lengths[0] && *(new_oblist_length_pointer - 1) >= S_G.oblist_count) {
|
||||
new_oblist_length_pointer -= 1;
|
||||
}
|
||||
} else if (S_G.oblist_count > S_G.oblist_length) {
|
||||
while (*(new_oblist_length_pointer + 1) != 0 && *(new_oblist_length_pointer + 1) <= S_G.oblist_count) {
|
||||
new_oblist_length_pointer += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_oblist_length_pointer == S_G.oblist_length_pointer) return;
|
||||
|
||||
new_oblist_length = *new_oblist_length_pointer;
|
||||
new_oblist = S_getmem(new_oblist_length * sizeof(bucket *), 1);
|
||||
|
||||
for (i = 0; i < S_G.oblist_length; i += 1) {
|
||||
for (b = S_G.oblist[i]; b != NULL; b = bnext) {
|
||||
bnext = b->next;
|
||||
sym = b->sym;
|
||||
idx = UNFIX(SYMHASH(sym)) % new_oblist_length;
|
||||
g = GENERATION(sym);
|
||||
|
||||
for (pb = &new_oblist[idx]; (oldb = *pb) != NULL && SegmentGeneration(addr_get_segment(oldb)) < g; pb = &oldb->next);
|
||||
b->next = oldb;
|
||||
*pb = b;
|
||||
}
|
||||
}
|
||||
|
||||
S_freemem(S_G.oblist, S_G.oblist_length * sizeof(bucket *));
|
||||
S_G.bytesof[static_generation][countof_oblist] += (new_oblist_length - S_G.oblist_length) * sizeof(bucket *);
|
||||
|
||||
S_G.oblist_length_pointer = new_oblist_length_pointer;
|
||||
S_G.oblist_length = new_oblist_length;
|
||||
S_G.oblist = new_oblist;
|
||||
}
|
||||
|
||||
/* hash function: multiplier weights each character, h = n factors in the length */
|
||||
#define multiplier 3
|
||||
|
||||
static iptr hash(const unsigned char *s, iptr n) {
|
||||
iptr h = n + 401887359;
|
||||
while (n--) h = h * multiplier + *s++;
|
||||
return h & most_positive_fixnum;
|
||||
}
|
||||
|
||||
static iptr hash_sc(const string_char *s, iptr n) {
|
||||
iptr h = n + 401887359;
|
||||
while (n--) h = h * multiplier + Schar_value(*s++);
|
||||
return h & most_positive_fixnum;
|
||||
}
|
||||
|
||||
static iptr hash_uname(const string_char *s, iptr n) {
|
||||
/* attempting to get dissimilar hash codes for gensyms created in the same session */
|
||||
iptr i = n, h = 0; iptr pos = 1; int d, c;
|
||||
|
||||
while (i-- > 0) {
|
||||
if ((c = Schar_value(s[i])) == '-') {
|
||||
if (pos <= 10) break;
|
||||
return (h + 523658599) & most_positive_fixnum;
|
||||
}
|
||||
d = c - '0';
|
||||
if (d < 0 || d > 9) break;
|
||||
h += d * pos;
|
||||
pos *= 10;
|
||||
}
|
||||
|
||||
return hash_sc(s, n);
|
||||
}
|
||||
|
||||
static ptr mkstring(const string_char *s, iptr n) {
|
||||
iptr i;
|
||||
ptr str = S_string(NULL, n);
|
||||
for (i = 0; i != n; i += 1) STRIT(str, i) = s[i];
|
||||
return str;
|
||||
}
|
||||
|
||||
/* handles single-byte characters, implicit length */
|
||||
ptr S_intern(const unsigned char *s) {
|
||||
iptr n = strlen((const char *)s);
|
||||
iptr hc = hash(s, n);
|
||||
iptr idx = hc % S_G.oblist_length;
|
||||
ptr sym;
|
||||
bucket *b;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = S_G.oblist[idx];
|
||||
while (b != NULL) {
|
||||
sym = b->sym;
|
||||
if (!GENSYMP(sym)) {
|
||||
ptr str = SYMNAME(sym);
|
||||
if (Sstring_length(str) == n) {
|
||||
iptr i;
|
||||
for (i = 0; ; i += 1) {
|
||||
if (i == n) {
|
||||
tc_mutex_release()
|
||||
return sym;
|
||||
}
|
||||
if (Sstring_ref(str, i) != s[i]) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
sym = S_symbol(S_string((const char *)s, n));
|
||||
INITSYMHASH(sym) = FIX(hc);
|
||||
oblist_insert(sym, idx, 0);
|
||||
|
||||
tc_mutex_release()
|
||||
return sym;
|
||||
}
|
||||
|
||||
/* handles string_chars, explicit length */
|
||||
ptr S_intern_sc(const string_char *name, iptr n, ptr name_str) {
|
||||
iptr hc = hash_sc(name, n);
|
||||
iptr idx = hc % S_G.oblist_length;
|
||||
ptr sym;
|
||||
bucket *b;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = S_G.oblist[idx];
|
||||
while (b != NULL) {
|
||||
sym = b->sym;
|
||||
if (!GENSYMP(sym)) {
|
||||
ptr str = SYMNAME(sym);
|
||||
if (Sstring_length(str) == n) {
|
||||
iptr i;
|
||||
for (i = 0; ; i += 1) {
|
||||
if (i == n) {
|
||||
tc_mutex_release()
|
||||
return sym;
|
||||
}
|
||||
if (STRIT(str, i) != name[i]) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
/* if (name_str == Sfalse) */ name_str = mkstring(name, n);
|
||||
sym = S_symbol(name_str);
|
||||
INITSYMHASH(sym) = FIX(hc);
|
||||
oblist_insert(sym, idx, 0);
|
||||
|
||||
tc_mutex_release()
|
||||
return sym;
|
||||
}
|
||||
|
||||
ptr S_intern3(const string_char *pname, iptr plen, const string_char *uname, iptr ulen, ptr pname_str, ptr uname_str) {
|
||||
iptr hc = hash_uname(uname, ulen);
|
||||
iptr idx = hc % S_G.oblist_length;
|
||||
ptr sym;
|
||||
bucket *b;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = S_G.oblist[idx];
|
||||
while (b != NULL) {
|
||||
sym = b->sym;
|
||||
if (GENSYMP(sym)) {
|
||||
ptr str = Scar(SYMNAME(sym));
|
||||
if (Sstring_length(str) == ulen) {
|
||||
iptr i;
|
||||
for (i = 0; ; i += 1) {
|
||||
if (i == ulen) {
|
||||
tc_mutex_release()
|
||||
return sym;
|
||||
}
|
||||
if (STRIT(str, i) != uname[i]) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
if (pname_str == Sfalse) pname_str = mkstring(pname, plen);
|
||||
if (uname_str == Sfalse) uname_str = mkstring(uname, ulen);
|
||||
sym = S_symbol(Scons(uname_str, pname_str));
|
||||
INITSYMHASH(sym) = FIX(hc);
|
||||
oblist_insert(sym, idx, 0);
|
||||
|
||||
tc_mutex_release()
|
||||
return sym;
|
||||
}
|
||||
|
||||
void S_intern_gensym(ptr sym) {
|
||||
ptr uname_str = Scar(SYMNAME(sym));
|
||||
const string_char *uname = &STRIT(uname_str, 0);
|
||||
iptr ulen = Sstring_length(uname_str);
|
||||
iptr hc = hash_uname(uname, ulen);
|
||||
iptr idx = hc % S_G.oblist_length;
|
||||
bucket *b;
|
||||
|
||||
tc_mutex_acquire()
|
||||
|
||||
b = S_G.oblist[idx];
|
||||
while (b != NULL) {
|
||||
ptr x = b->sym;
|
||||
if (GENSYMP(x)) {
|
||||
ptr str = Scar(SYMNAME(x));
|
||||
if (Sstring_length(str) == ulen) {
|
||||
iptr i;
|
||||
for (i = 0; ; i += 1) {
|
||||
if (i == ulen) {
|
||||
tc_mutex_release()
|
||||
S_error1("intern-gensym", "unique name ~s already interned", uname_str);
|
||||
}
|
||||
if (Sstring_ref(str, i) != uname[i]) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
b = b->next;
|
||||
}
|
||||
|
||||
INITSYMHASH(sym) = FIX(hc);
|
||||
oblist_insert(sym, idx, GENERATION(sym));
|
||||
|
||||
tc_mutex_release()
|
||||
}
|
||||
|
||||
/* retrofit existing symbols once nonprocedure_code is available */
|
||||
void S_retrofit_nonprocedure_code(void) {
|
||||
ptr npc, sym, val; bucket_list *bl;
|
||||
|
||||
npc = S_G.nonprocedure_code;
|
||||
|
||||
/* assuming this happens early, before collector has been called, so need look only for generation 0 symbols */
|
||||
for (bl = S_G.buckets_of_generation[0]; bl != NULL; bl = bl->cdr) {
|
||||
sym = bl->car->sym;
|
||||
val = SYMVAL(sym);
|
||||
SETSYMCODE(sym, Sprocedurep(val) ? CLOSCODE(val) : npc);
|
||||
}
|
||||
}
|
BIN
ta6ob/c/intern.o
Normal file
BIN
ta6ob/c/intern.o
Normal file
Binary file not shown.
277
ta6ob/c/io.c
Normal file
277
ta6ob/c/io.c
Normal file
|
@ -0,0 +1,277 @@
|
|||
/* io.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#include <shlobj.h>
|
||||
#pragma comment(lib, "shell32.lib")
|
||||
#else /* WIN32 */
|
||||
#include <sys/file.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* locally defined functions */
|
||||
#ifdef WIN32
|
||||
static ptr s_wstring_to_bytevector(const wchar_t *s);
|
||||
#else
|
||||
static ptr s_string_to_bytevector(const char *s);
|
||||
#endif
|
||||
|
||||
/* raises an exception if insufficient space cannot be malloc'd.
|
||||
otherwise returns a freshly allocated version of inpath with ~ (home directory)
|
||||
prefix expanded, if possible */
|
||||
char *S_malloc_pathname(const char *inpath) {
|
||||
char *outpath; const char *ip;
|
||||
|
||||
#ifdef WIN32
|
||||
if (*inpath == '~' && (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip))) {
|
||||
wchar_t* homew;
|
||||
if (SUCCEEDED(SHGetKnownFolderPath(&FOLDERID_Profile, 0, NULL, &homew))) {
|
||||
char *home = Swide_to_utf8(homew);
|
||||
CoTaskMemFree(homew);
|
||||
if (NULL != home) {
|
||||
size_t n1, n2;
|
||||
n1 = strlen(home);
|
||||
n2 = strlen(ip) + 1;
|
||||
if ((outpath = malloc(n1 + n2)) == NULL) {
|
||||
free(home);
|
||||
S_error("expand_pathname", "malloc failed");
|
||||
}
|
||||
memcpy(outpath, home, n1);
|
||||
memcpy(outpath + n1, ip, n2);
|
||||
free(home);
|
||||
return outpath;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else /* WIN32 */
|
||||
if (*inpath == '~') {
|
||||
const char *dir; size_t n1, n2; struct passwd *pwent;
|
||||
if (*(ip = inpath + 1) == 0 || DIRMARKERP(*ip)) {
|
||||
if ((dir = getenv("HOME")) == NULL)
|
||||
if ((pwent = getpwuid(getuid())) != NULL)
|
||||
dir = pwent->pw_dir;
|
||||
} else {
|
||||
char *userbuf; const char *user_start = ip;
|
||||
do { ip += 1; } while (*ip != 0 && !DIRMARKERP(*ip));
|
||||
if ((userbuf = malloc(ip - user_start + 1)) == NULL) S_error("expand_pathname", "malloc failed");
|
||||
memcpy(userbuf, user_start, ip - user_start);
|
||||
userbuf[ip - user_start] = 0;
|
||||
dir = (pwent = getpwnam(userbuf)) != NULL ? pwent->pw_dir : NULL;
|
||||
free(userbuf);
|
||||
}
|
||||
if (dir != NULL) {
|
||||
n1 = strlen(dir);
|
||||
n2 = strlen(ip) + 1;
|
||||
if ((outpath = malloc(n1 + n2)) == NULL) S_error("expand_pathname", "malloc failed");
|
||||
memcpy(outpath, dir, n1);
|
||||
memcpy(outpath + n1, ip, n2);
|
||||
return outpath;
|
||||
}
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* if no ~ or tilde dir can't be found, copy inpath */
|
||||
{
|
||||
size_t n = strlen(inpath) + 1;
|
||||
if ((outpath = (char *)malloc(n)) == NULL) S_error("expand_pathname", "malloc failed");
|
||||
memcpy(outpath, inpath, n);
|
||||
return outpath;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
wchar_t *S_malloc_wide_pathname(const char *inpath) {
|
||||
char *path = S_malloc_pathname(inpath);
|
||||
wchar_t *wpath = Sutf8_to_wide(path);
|
||||
free(path);
|
||||
return wpath;
|
||||
}
|
||||
#endif
|
||||
|
||||
IBOOL S_fixedpathp(const char *inpath) {
|
||||
char c; IBOOL res; char *path;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (c = *path) == 0
|
||||
|| DIRMARKERP(c)
|
||||
#ifdef WIN32
|
||||
|| ((*(path + 1) == ':') && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'))
|
||||
#endif
|
||||
|| ((c == '.')
|
||||
&& ((c = *(path + 1)) == 0
|
||||
|| DIRMARKERP(c)
|
||||
|| (c == '.' && ((c = *(path + 2)) == 0 || DIRMARKERP(c)))));
|
||||
free(path);
|
||||
return res;
|
||||
}
|
||||
|
||||
IBOOL S_file_existsp(const char *inpath, IBOOL followp) {
|
||||
#ifdef WIN32
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata);
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
IBOOL S_file_regularp(const char *inpath, IBOOL followp) {
|
||||
#ifdef WIN32
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)
|
||||
&& (filedata.dwFileAttributes & (FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_REPARSE_POINT)) == 0;
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0
|
||||
&& (statbuf.st_mode & S_IFMT) == S_IFREG;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
IBOOL S_file_directoryp(const char *inpath, IBOOL followp) {
|
||||
#ifdef WIN32
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)
|
||||
&& filedata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = (followp ? STAT(path, &statbuf) : LSTAT(path, &statbuf)) == 0
|
||||
&& (statbuf.st_mode & S_IFMT) == S_IFDIR;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
IBOOL S_file_symbolic_linkp(const char *inpath) {
|
||||
#ifdef WIN32
|
||||
wchar_t *wpath; IBOOL res;
|
||||
WIN32_FILE_ATTRIBUTE_DATA filedata;
|
||||
|
||||
if ((wpath = S_malloc_wide_pathname(inpath)) == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
res = GetFileAttributesExW(wpath, GetFileExInfoStandard, &filedata)
|
||||
&& filedata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
free(wpath);
|
||||
return res;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
struct STATBUF statbuf; char *path; IBOOL res;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
res = LSTAT(path, &statbuf) == 0 && (statbuf.st_mode & S_IFMT) == S_IFLNK;
|
||||
free(path);
|
||||
return res;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static ptr s_wstring_to_bytevector(const wchar_t *s) {
|
||||
iptr n; ptr bv;
|
||||
if ((n = wcslen(s)) == 0) return S_G.null_bytevector;
|
||||
n *= sizeof(wchar_t);
|
||||
bv = S_bytevector(n);
|
||||
memcpy(&BVIT(bv,0), s, n);
|
||||
return bv;
|
||||
}
|
||||
|
||||
ptr S_find_files(const char *wildpath) {
|
||||
wchar_t *wwildpath;
|
||||
intptr_t handle;
|
||||
struct _wfinddata_t fileinfo;
|
||||
|
||||
if ((wwildpath = S_malloc_wide_pathname(wildpath)) == NULL)
|
||||
return S_LastErrorString();
|
||||
|
||||
if ((handle = _wfindfirst(wwildpath, &fileinfo)) == (intptr_t)-1) {
|
||||
free(wwildpath);
|
||||
return S_strerror(errno);
|
||||
} else {
|
||||
ptr ls = Snil;
|
||||
do {
|
||||
ls = Scons(s_wstring_to_bytevector(fileinfo.name), ls);
|
||||
} while (_wfindnext(handle, &fileinfo) == 0);
|
||||
_findclose(handle);
|
||||
free(wwildpath);
|
||||
return ls;
|
||||
}
|
||||
}
|
||||
#else /* WIN32 */
|
||||
static ptr s_string_to_bytevector(const char *s) {
|
||||
iptr n; ptr bv;
|
||||
if ((n = strlen(s)) == 0) return S_G.null_bytevector;
|
||||
bv = S_bytevector(n);
|
||||
memcpy(&BVIT(bv,0), s, n);
|
||||
return bv;
|
||||
}
|
||||
|
||||
ptr S_directory_list(const char *inpath) {
|
||||
char *path; DIR *dirp;
|
||||
|
||||
path = S_malloc_pathname(inpath);
|
||||
if ((dirp = opendir(path)) == (DIR *)0) {
|
||||
free(path);
|
||||
return S_strerror(errno);
|
||||
} else {
|
||||
struct dirent *dep; ptr ls = Snil;
|
||||
|
||||
while ((dep = readdir(dirp)) != (struct dirent *)0)
|
||||
ls = Scons(s_string_to_bytevector(dep->d_name), ls);
|
||||
closedir(dirp);
|
||||
free(path);
|
||||
return ls;
|
||||
}
|
||||
}
|
||||
#endif /* WIN32 */
|
BIN
ta6ob/c/io.o
Normal file
BIN
ta6ob/c/io.o
Normal file
Binary file not shown.
247
ta6ob/c/itest.c
Normal file
247
ta6ob/c/itest.c
Normal file
|
@ -0,0 +1,247 @@
|
|||
/* itest.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#define r_EOF 0
|
||||
#define r_LPAREN 1
|
||||
#define r_RPAREN 2
|
||||
#define r_CONST 3
|
||||
|
||||
static INT digit_value(ICHAR c, INT r) {
|
||||
switch (r) {
|
||||
case 2:
|
||||
if ('0' <= c && c <= '1') return c - '0';
|
||||
break;
|
||||
case 8:
|
||||
if ('0' <= c && c <= '8') return c - '0';
|
||||
break;
|
||||
case 10:
|
||||
if ('0' <= c && c <= '9') return c - '0';
|
||||
break;
|
||||
case 16:
|
||||
if ('0' <= c && c <= '9') return c - '0';
|
||||
if ('a' <= c && c <= 'f') return c - 'a';
|
||||
if ('A' <= c && c <= 'F') return c - 'A';
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static INT read_int(ptr *v, ptr n, INT r, IBOOL sign) {
|
||||
INT i, c;
|
||||
|
||||
for (;;) {
|
||||
if ((i = digit_value((c = getchar()), r)) == -1) {
|
||||
ungetc(c, stdin);
|
||||
break;
|
||||
}
|
||||
n = S_add(S_mul(n, FIX(r)), FIX(i));
|
||||
}
|
||||
*v = sign ? S_sub(FIX(0), n) : n;
|
||||
return r_CONST;
|
||||
}
|
||||
|
||||
static INT read_token(ptr *v) {
|
||||
ICHAR c = getchar();
|
||||
switch (c) {
|
||||
case SEOF: return r_EOF;
|
||||
case '\n':
|
||||
case ' ': return read_token(v);
|
||||
case ';':
|
||||
for (;;) {
|
||||
switch (getchar()) {
|
||||
case SEOF:
|
||||
return r_EOF;
|
||||
case '\n':
|
||||
return read_token(v);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
case '(': return r_LPAREN;
|
||||
case ')': return r_RPAREN;
|
||||
case '#': {
|
||||
ICHAR c = getchar();
|
||||
INT r = 10;
|
||||
switch (c) {
|
||||
case 'x':
|
||||
r = 16;
|
||||
case 'o':
|
||||
if (r == 0) r = 8;
|
||||
case 'b':
|
||||
if (r == 10) r = 2;
|
||||
case 'd': {
|
||||
INT i;
|
||||
IBOOL sign = 0;
|
||||
c = getchar();
|
||||
if (c == '+')
|
||||
c = getchar();
|
||||
else if (c == '-') {
|
||||
sign = 1;
|
||||
c = getchar();
|
||||
}
|
||||
|
||||
if ((i = digit_value(c, r)) != -1)
|
||||
return read_int(v, FIX(i), r, sign);
|
||||
}
|
||||
default:
|
||||
printf("malformed hash prefix ignored\n");
|
||||
return read_token(v);
|
||||
}
|
||||
}
|
||||
case '+':
|
||||
case '-': {
|
||||
INT i, c2;
|
||||
if ((i = digit_value((c2 = getchar()), 10)) == -1) {
|
||||
ungetc(c2, stdin);
|
||||
} else {
|
||||
return read_int(v, FIX(i), 10, c == '-');
|
||||
}
|
||||
}
|
||||
case '*':
|
||||
case '/':
|
||||
case 'q':
|
||||
case 'r':
|
||||
case 'g':
|
||||
case '=':
|
||||
case '<':
|
||||
case 'f':
|
||||
case 'c':
|
||||
case 'd':
|
||||
*v = Schar(c);
|
||||
return r_CONST;
|
||||
default: {
|
||||
INT i;
|
||||
if ((i = digit_value(c, 10)) != -1)
|
||||
return read_int(v, FIX(i), 10, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
printf("invalid character %d ignored\n", c);
|
||||
return read_token(v);
|
||||
}
|
||||
|
||||
static ptr readx(INT t, ptr v);
|
||||
|
||||
static ptr read_list(void) {
|
||||
INT t; ptr v, x;
|
||||
|
||||
t = read_token(&v);
|
||||
if (t == r_RPAREN) return Snil;
|
||||
x = readx(t, v);
|
||||
return Scons(x, read_list());
|
||||
}
|
||||
|
||||
static ptr readx(INT t, ptr v) {
|
||||
|
||||
switch (t) {
|
||||
case r_EOF:
|
||||
printf("unexpected EOF\n");
|
||||
exit(1);
|
||||
case r_LPAREN: return read_list();
|
||||
case r_RPAREN:
|
||||
printf("unexpected right paren ignored\n");
|
||||
t = read_token(&v);
|
||||
return readx(t, v);
|
||||
case r_CONST: return v;
|
||||
default:
|
||||
printf("invalid token %d\n", t);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
static ptr read_top(void) {
|
||||
INT t; ptr v;
|
||||
|
||||
t = read_token(&v);
|
||||
switch (t) {
|
||||
case r_EOF: return Seof_object;
|
||||
case r_RPAREN: return read_top();
|
||||
default: return readx(t, v);
|
||||
}
|
||||
}
|
||||
|
||||
static ptr eval(ptr x);
|
||||
|
||||
#define First(x) eval(Scar(Scdr(x)))
|
||||
#define Second(x) eval(Scar(Scdr(Scdr(x))))
|
||||
|
||||
static ptr eval(ptr x) {
|
||||
if (Spairp(x)) {
|
||||
switch (Schar_value(Scar(x))) {
|
||||
case '+': return S_add(First(x), Second(x));
|
||||
case '-': return S_sub(First(x), Second(x));
|
||||
case '*': return S_mul(First(x), Second(x));
|
||||
case '/': return S_div(First(x), Second(x));
|
||||
case 'q': return S_trunc(First(x), Second(x));
|
||||
case 'r': return S_rem(First(x), Second(x));
|
||||
case 'g': return S_gcd(First(x), Second(x));
|
||||
case '=': {
|
||||
ptr x1 = First(x), x2 = Second(x);
|
||||
if (Sfixnump(x1) && Sfixnump(x2))
|
||||
return Sboolean(x1 == x2);
|
||||
else if (Sbignump(x1) && Sbignump(x2))
|
||||
return Sboolean(S_big_eq(x1, x2));
|
||||
else return Sfalse;
|
||||
}
|
||||
case '<': {
|
||||
ptr x1 = First(x), x2 = Second(x);
|
||||
if (Sfixnump(x1))
|
||||
if (Sfixnump(x2))
|
||||
return Sboolean(x1 < x2);
|
||||
else
|
||||
return Sboolean(!BIGSIGN(x2));
|
||||
else
|
||||
if (Sfixnump(x2))
|
||||
return Sboolean(BIGSIGN(x1));
|
||||
else
|
||||
return Sboolean(S_big_lt(x1, x2));
|
||||
}
|
||||
case 'f': return Sflonum(S_floatify(First(x)));
|
||||
case 'c':
|
||||
S_gc(get_thread_context(), UNFIX(First(x)),UNFIX(Second(x)));
|
||||
return Svoid;
|
||||
case 'd': return S_decode_float(Sflonum_value(First(x)));
|
||||
default:
|
||||
S_prin1(x);
|
||||
putchar('\n');
|
||||
printf("unrecognized operator, returning zero\n");
|
||||
return FIX(0);
|
||||
}
|
||||
} else
|
||||
return x;
|
||||
}
|
||||
|
||||
#undef PROMPT
|
||||
#undef NOISY
|
||||
static void bignum_test(void) {
|
||||
ptr x;
|
||||
for (;;) {
|
||||
#ifdef PROMPT
|
||||
putchar('*');
|
||||
putchar(' ');
|
||||
#endif
|
||||
x = read_top();
|
||||
if (x == Seof_object) { putchar('\n'); exit(0); }
|
||||
#ifdef NOISY
|
||||
S_prin1(x);
|
||||
putchar('\n');
|
||||
#endif
|
||||
x = eval(x);
|
||||
S_prin1(x);
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
376
ta6ob/c/main.c
Normal file
376
ta6ob/c/main.c
Normal file
|
@ -0,0 +1,376 @@
|
|||
/* main.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "scheme.h"
|
||||
#include "config.h"
|
||||
|
||||
/****
|
||||
CUSTOM_INIT may be defined as a function with the signature shown to
|
||||
perform boot-time initialization, e.g., registering foreign symbols.
|
||||
****/
|
||||
#ifndef CUSTOM_INIT
|
||||
#define CUSTOM_INIT ((void (*)(void))0)
|
||||
#endif /* CUSTOM_INIT */
|
||||
|
||||
/****
|
||||
ABNORMAL_EXIT may be defined as a function with the signature shown to
|
||||
take some action, such as printing a special error message or performing
|
||||
a nonlocal exit with longjmp, when the Scheme system exits abnormally,
|
||||
i.e., when an unrecoverable error occurs. If left null, the default
|
||||
is to call exit(1).
|
||||
****/
|
||||
#ifndef ABNORMAL_EXIT
|
||||
#define ABNORMAL_EXIT ((void (*)(void))0)
|
||||
#endif /* ABNORMAL_EXIT */
|
||||
|
||||
#ifndef SCHEME_SCRIPT
|
||||
#define SCHEME_SCRIPT "scheme-script"
|
||||
#endif
|
||||
|
||||
static const char *path_last(const char *p) {
|
||||
const char *s;
|
||||
#ifdef WIN32
|
||||
char c;
|
||||
if ((c = *p) >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
|
||||
if (*(p + 1) == ':')
|
||||
p += 2;
|
||||
|
||||
for (s = p; *s != 0; s += 1)
|
||||
if ((c = *s) == '/' || c == '\\') p = ++s;
|
||||
#else /* WIN32 */
|
||||
for (s = p; *s != 0; s += 1) if (*s == '/') p = ++s;
|
||||
#endif /* WIN32 */
|
||||
return p;
|
||||
}
|
||||
|
||||
#if defined(WIN32) && !defined(__MINGW32__)
|
||||
#define GETENV Sgetenv
|
||||
#define GETENV_FREE free
|
||||
int wmain(int argc, wchar_t* wargv[], wchar_t* wenvp[]) {
|
||||
const char** argv = (char**)malloc((argc + 1) * sizeof(char*));
|
||||
int i;
|
||||
for (i = 0; i < argc; i++) {
|
||||
wchar_t* warg = wargv[i];
|
||||
if (NULL == (argv[i] = Swide_to_utf8(warg))) {
|
||||
fprintf_s(stderr, "Invalid argument: %S\n", warg);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
argv[argc] = NULL;
|
||||
#else /* WIN32 */
|
||||
#define GETENV getenv
|
||||
#define GETENV_FREE (void)
|
||||
int main(int argc, const char *argv[]) {
|
||||
#endif /* WIN32 */
|
||||
int n, new_argc = 1;
|
||||
#ifdef SAVEDHEAPS
|
||||
int compact = 1, savefile_level = 0;
|
||||
const char *savefile = (char *)0;
|
||||
#endif /* SAVEDHEAPS */
|
||||
const char *execpath = argv[0];
|
||||
const char *scriptfile = (char *)0;
|
||||
const char *programfile = (char *)0;
|
||||
const char *libdirs = (char *)0;
|
||||
const char *libexts = (char *)0;
|
||||
int status;
|
||||
const char *arg;
|
||||
int quiet = 0;
|
||||
int eoc = 0;
|
||||
int optlevel = 0;
|
||||
int debug_on_exception = 0;
|
||||
int import_notify = 0;
|
||||
int compile_imported_libraries = 0;
|
||||
#ifdef FEATURE_EXPEDITOR
|
||||
int expeditor_enable = 1;
|
||||
const char *expeditor_history_file = ""; /* use "" for default location */
|
||||
#endif /* FEATURE_EXPEDITOR */
|
||||
|
||||
if (strcmp(Skernel_version(), VERSION) != 0) {
|
||||
(void) fprintf(stderr, "unexpected shared library version %s for %s version %s\n", Skernel_version(), execpath, VERSION);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
Sscheme_init(ABNORMAL_EXIT);
|
||||
|
||||
if (strcmp(path_last(execpath), SCHEME_SCRIPT) == 0) {
|
||||
if (argc < 2) {
|
||||
(void) fprintf(stderr,"%s requires program-path argument\n", execpath);
|
||||
exit(1);
|
||||
}
|
||||
argv[0] = programfile = argv[1];
|
||||
n = 1;
|
||||
while (++n < argc) argv[new_argc++] = argv[n];
|
||||
} else {
|
||||
/* process command-line arguments, registering boot and heap files */
|
||||
for (n = 1; n < argc; n += 1) {
|
||||
arg = argv[n];
|
||||
if (strcmp(arg,"--") == 0) {
|
||||
while (++n < argc) argv[new_argc++] = argv[n];
|
||||
} else if (strcmp(arg,"-b") == 0 || strcmp(arg,"--boot") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
Sregister_boot_file(argv[n]);
|
||||
} else if (strcmp(arg,"--eedisable") == 0) {
|
||||
#ifdef FEATURE_EXPEDITOR
|
||||
expeditor_enable = 0;
|
||||
#endif /* FEATURE_EXPEDITOR */
|
||||
} else if (strcmp(arg,"--eehistory") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
#ifdef FEATURE_EXPEDITOR
|
||||
if (strcmp(argv[n], "off") == 0)
|
||||
expeditor_history_file = (char *)0;
|
||||
else
|
||||
expeditor_history_file = argv[n];
|
||||
#endif /* FEATURE_EXPEDITOR */
|
||||
} else if (strcmp(arg,"-q") == 0 || strcmp(arg,"--quiet") == 0) {
|
||||
quiet = 1;
|
||||
} else if (strcmp(arg,"--retain-static-relocation") == 0) {
|
||||
Sretain_static_relocation();
|
||||
} else if (strcmp(arg,"--enable-object-counts") == 0) {
|
||||
eoc = 1;
|
||||
#ifdef SAVEDHEAPS
|
||||
} else if (strcmp(arg,"-c") == 0 || strcmp(arg,"--compact") == 0) {
|
||||
compact = !compact;
|
||||
} else if (strcmp(arg,"-h") == 0 || strcmp(arg,"--heap") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
Sregister_heap_file(argv[n]);
|
||||
} else if (strncmp(arg,"-s",2) == 0 &&
|
||||
(savefile_level = -2,
|
||||
*(arg+2) == 0 ||
|
||||
*(arg+3) == 0 &&
|
||||
((savefile_level = *(arg+2) - '+' - 1) == -1 ||
|
||||
(savefile_level = *(arg+2) - '0') >= 0 &&
|
||||
savefile_level <= 9)) ||
|
||||
strncmp(arg,"--saveheap",10) == 0 &&
|
||||
(savefile_level = -2,
|
||||
*(arg+10) == 0 ||
|
||||
*(arg+11) == 0 &&
|
||||
((savefile_level = *(arg+2) - '+' - 1) == -1 ||
|
||||
(savefile_level = *(arg+10) - '0') >= 0 &&
|
||||
savefile_level <= 9))) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
savefile = argv[n];
|
||||
#else /* SAVEDHEAPS */
|
||||
} else if (strcmp(arg,"-c") == 0 || strcmp(arg,"--compact") == 0) {
|
||||
fprintf(stderr, "-c and --compact options are not presently supported\n");
|
||||
exit(1);
|
||||
} else if (strcmp(arg,"-h") == 0 || strcmp(arg,"--heap") == 0) {
|
||||
fprintf(stderr, "-h and --heap options are not presently supported\n");
|
||||
exit(1);
|
||||
} else if (strncmp(arg,"-s",2) == 0 || strncmp(arg,"--saveheap",10) == 0) {
|
||||
fprintf(stderr, "-s and --saveheap options are not presently supported\n");
|
||||
exit(1);
|
||||
#endif /* SAVEDHEAPS */
|
||||
} else if (strcmp(arg,"--script") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
scriptfile = argv[n];
|
||||
while (++n < argc) argv[new_argc++] = argv[n];
|
||||
} else if (strcmp(arg,"--optimize-level") == 0) {
|
||||
const char *nextarg;
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
nextarg = argv[n];
|
||||
if (strcmp(nextarg,"0") == 0)
|
||||
optlevel = 0;
|
||||
else if (strcmp(nextarg,"1") == 0)
|
||||
optlevel = 1;
|
||||
else if (strcmp(nextarg,"2") == 0)
|
||||
optlevel = 2;
|
||||
else if (strcmp(nextarg,"3") == 0)
|
||||
optlevel = 3;
|
||||
else {
|
||||
(void) fprintf(stderr,"invalid optimize-level %s\n", nextarg);
|
||||
exit(1);
|
||||
}
|
||||
} else if (strcmp(arg,"--debug-on-exception") == 0) {
|
||||
debug_on_exception = 1;
|
||||
} else if (strcmp(arg,"--import-notify") == 0) {
|
||||
import_notify = 1;
|
||||
} else if (strcmp(arg,"--libexts") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
libexts = argv[n];
|
||||
} else if (strcmp(arg,"--libdirs") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
libdirs = argv[n];
|
||||
} else if (strcmp(arg,"--compile-imported-libraries") == 0) {
|
||||
compile_imported_libraries = 1;
|
||||
} else if (strcmp(arg,"--program") == 0) {
|
||||
if (++n == argc) {
|
||||
(void) fprintf(stderr,"%s requires argument\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
programfile = argv[n];
|
||||
while (++n < argc) argv[new_argc++] = argv[n];
|
||||
} else if (strcmp(arg,"--help") == 0) {
|
||||
fprintf(stderr,"usage: %s [options and files]\n", execpath);
|
||||
fprintf(stderr,"options:\n");
|
||||
fprintf(stderr," -q, --quiet suppress greeting and prompt\n");
|
||||
fprintf(stderr," --script <path> run as shell script\n");
|
||||
fprintf(stderr," --program <path> run rnrs program as shell script\n");
|
||||
#ifdef WIN32
|
||||
#define sep ";"
|
||||
#else
|
||||
#define sep ":"
|
||||
#endif
|
||||
fprintf(stderr," --libdirs <dir>%s... set library directories\n", sep);
|
||||
fprintf(stderr," --libexts <ext>%s... set library extensions\n", sep);
|
||||
fprintf(stderr," --compile-imported-libraries compile libraries before loading\n");
|
||||
fprintf(stderr," --import-notify enable import search messages\n");
|
||||
fprintf(stderr," --optimize-level <0 | 1 | 2 | 3> set optimize-level\n");
|
||||
fprintf(stderr," --debug-on-exception on uncaught exception, call debug\n");
|
||||
fprintf(stderr," --eedisable disable expression editor\n");
|
||||
fprintf(stderr," --eehistory <off | path> expression-editor history file\n");
|
||||
fprintf(stderr," --enable-object-counts have collector maintain object counts\n");
|
||||
fprintf(stderr," --retain-static-relocation keep reloc info for compute-size, etc.\n");
|
||||
fprintf(stderr," -b <path>, --boot <path> load boot file\n");
|
||||
// fprintf(stderr," -c, --compact toggle compaction flag\n");
|
||||
// fprintf(stderr," -h <path>, --heap <path> load heap file\n");
|
||||
// fprintf(stderr," -s[<n>] <path>, --saveheap[<n>] <path> save heap file\n");
|
||||
fprintf(stderr," --verbose trace boot/heap search process\n");
|
||||
fprintf(stderr," --version print version and exit\n");
|
||||
fprintf(stderr," --help print help and exit\n");
|
||||
fprintf(stderr," -- pass through remaining args\n");
|
||||
exit(0);
|
||||
} else if (strcmp(arg,"--verbose") == 0) {
|
||||
Sset_verbose(1);
|
||||
} else if (strcmp(arg,"--version") == 0) {
|
||||
fprintf(stderr,"%s\n", VERSION);
|
||||
exit(0);
|
||||
} else {
|
||||
argv[new_argc++] = arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* must call Sbuild_heap after registering boot and heap files.
|
||||
* Sbuild_heap() completes the initialization of the Scheme system
|
||||
* and loads the boot or heap files. If no boot or heap files have
|
||||
* been registered, the first argument to Sbuild_heap must be a
|
||||
* non-null path string; in this case, Sbuild_heap looks for
|
||||
* a heap or boot file named <name>.boot, where <name> is the last
|
||||
* component of the path. If no heap files are loaded and
|
||||
* CUSTOM_INIT is non-null, Sbuild_heap calls CUSTOM_INIT just
|
||||
* prior to loading the boot file(s). */
|
||||
Sbuild_heap(execpath, CUSTOM_INIT);
|
||||
|
||||
#define CALL0(who) Scall0(Stop_level_value(Sstring_to_symbol(who)))
|
||||
#define CALL1(who, arg) Scall1(Stop_level_value(Sstring_to_symbol(who)), arg)
|
||||
#ifdef FunCRepl
|
||||
{
|
||||
ptr p;
|
||||
|
||||
for (;;) {
|
||||
CALL1("display", Sstring("* "));
|
||||
p = CALL0("read");
|
||||
if (Seof_objectp(p)) break;
|
||||
p = CALL1("eval", p);
|
||||
if (p != Svoid) CALL1("pretty-print", p);
|
||||
}
|
||||
CALL0("newline");
|
||||
status = 0;
|
||||
}
|
||||
#else /* FunCRepl */
|
||||
if (quiet) {
|
||||
CALL1("suppress-greeting", Strue);
|
||||
CALL1("waiter-prompt-string", Sstring(""));
|
||||
}
|
||||
if (eoc) {
|
||||
CALL1("enable-object-counts", Strue);
|
||||
}
|
||||
if (optlevel != 0) {
|
||||
CALL1("optimize-level", Sinteger(optlevel));
|
||||
}
|
||||
if (debug_on_exception != 0) {
|
||||
CALL1("debug-on-exception", Strue);
|
||||
}
|
||||
if (import_notify != 0) {
|
||||
CALL1("import-notify", Strue);
|
||||
}
|
||||
if (libdirs == 0) {
|
||||
char *cslibdirs = GETENV("CHEZSCHEMELIBDIRS");
|
||||
if (cslibdirs != 0) {
|
||||
CALL1("library-directories", Sstring_utf8(cslibdirs, -1));
|
||||
GETENV_FREE(cslibdirs);
|
||||
}
|
||||
} else {
|
||||
CALL1("library-directories", Sstring_utf8(libdirs, -1));
|
||||
}
|
||||
if (libexts == 0) {
|
||||
char *cslibexts = GETENV("CHEZSCHEMELIBEXTS");
|
||||
if (cslibexts != 0) {
|
||||
CALL1("library-extensions", Sstring_utf8(cslibexts, -1));
|
||||
GETENV_FREE(cslibexts);
|
||||
}
|
||||
} else {
|
||||
CALL1("library-extensions", Sstring_utf8(libexts, -1));
|
||||
}
|
||||
if (compile_imported_libraries != 0) {
|
||||
CALL1("compile-imported-libraries", Strue);
|
||||
}
|
||||
#ifdef FEATURE_EXPEDITOR
|
||||
/* Senable_expeditor must be called before Scheme_start/Scheme_script (if at all) */
|
||||
if (!quiet && expeditor_enable) Senable_expeditor(expeditor_history_file);
|
||||
#endif /* FEATURE_EXPEDITOR */
|
||||
|
||||
if (scriptfile != (char *)0)
|
||||
/* Sscheme_script invokes the value of the scheme-script parameter */
|
||||
status = Sscheme_script(scriptfile, new_argc, argv);
|
||||
else if (programfile != (char *)0)
|
||||
/* Sscheme_program invokes the value of the scheme-program parameter */
|
||||
status = Sscheme_program(programfile, new_argc, argv);
|
||||
else {
|
||||
/* Sscheme_start invokes the value of the scheme-start parameter */
|
||||
status = Sscheme_start(new_argc, argv);
|
||||
}
|
||||
#endif /* FunCRepl */
|
||||
|
||||
#ifdef SAVEDHEAPS
|
||||
if (status == 0 && savefile != (char *)0) {
|
||||
if (compact) Scompact_heap();
|
||||
Ssave_heap(savefile, savefile_level);
|
||||
}
|
||||
#endif /* SAVEDHEAPS */
|
||||
|
||||
/* must call Scheme_deinit after saving the heap and before exiting */
|
||||
Sscheme_deinit();
|
||||
|
||||
exit(status);
|
||||
}
|
BIN
ta6ob/c/main.o
Normal file
BIN
ta6ob/c/main.o
Normal file
Binary file not shown.
970
ta6ob/c/new-io.c
Normal file
970
ta6ob/c/new-io.c
Normal file
|
@ -0,0 +1,970 @@
|
|||
/* new-io.c
|
||||
* Copyright 1984-2017 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "system.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <limits.h>
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
#else /* WIN32 */
|
||||
#include <sys/file.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
#endif /* WIN32 */
|
||||
#include <fcntl.h>
|
||||
#include "zlib.h"
|
||||
#include "lz4.h"
|
||||
#include "lz4hc.h"
|
||||
|
||||
/* !!! UNLESS you enjoy spending endless days tracking down race conditions
|
||||
!!! involving the garbage collector, please note: DEACTIVATE and
|
||||
!!! REACTIVATE or LOCKandDEACTIVATE and REACTIVATEandLOCK should be used
|
||||
!!! around operations that can block. While deactivated, the process
|
||||
!!! MUST NOT touch any unlocked Scheme objects (ptrs) or allocate any
|
||||
!!! new Scheme objects. It helps to bracket only small pieces of code
|
||||
!!! with DEACTIVATE/REACTIVATE or LOCKandDEACTIVATE/REACTIVATE_and_LOCK. */
|
||||
#ifdef PTHREADS
|
||||
/* assume the scheme wrapper has us in a critical section */
|
||||
#define DEACTIVATE(tc) if (DISABLECOUNT(tc) == FIX(1)) { deactivate_thread(tc); }
|
||||
#define REACTIVATE(tc) if (DISABLECOUNT(tc) == FIX(1)) { reactivate_thread(tc); }
|
||||
#define LOCKandDEACTIVATE(tc,bv) if (DISABLECOUNT(tc) == FIX(1)) { Slock_object(bv); deactivate_thread(tc); }
|
||||
#define REACTIVATEandUNLOCK(tc,bv) if (DISABLECOUNT(tc) == FIX(1)) { reactivate_thread(tc); Sunlock_object(bv); }
|
||||
#else /* PTHREADS */
|
||||
#define DEACTIVATE(tc)
|
||||
#define REACTIVATE(tc)
|
||||
#define LOCKandDEACTIVATE(tc,bv)
|
||||
#define REACTIVATEandUNLOCK(tc,bv)
|
||||
#endif /* PTHREADS */
|
||||
|
||||
/* locally defined functions */
|
||||
static ptr new_open_output_fd_helper(const char *filename, INT mode,
|
||||
INT flags, INT no_create, INT no_fail, INT no_truncate,
|
||||
INT append, INT lock, INT replace, INT compressed);
|
||||
static INT lockfile(INT fd);
|
||||
static int is_valid_zlib_length(iptr count);
|
||||
static int is_valid_lz4_length(iptr count);
|
||||
|
||||
/*
|
||||
not_ok_is_fatal: !ok definitely implies error, so ignore glzerror
|
||||
ok: whether the result of body seems to be ok
|
||||
flag: will be set when an error is detected and cleared if no error
|
||||
fd: the glzFile object to call glzerror on
|
||||
body: the operation we are checking the error on
|
||||
*/
|
||||
#ifdef EINTR
|
||||
/* like FD_EINTR_GUARD and GZ_EINTR_GUARD but ignores EINTR.
|
||||
used for calls to close so we don't close a file descriptor that
|
||||
might already have been reallocated by a different thread */
|
||||
#define FD_GUARD(ok,flag,body) \
|
||||
do { body; \
|
||||
flag = !(ok) && errno != EINTR; \
|
||||
} while (0)
|
||||
#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; } \
|
||||
else { \
|
||||
INT errnum; \
|
||||
S_glzerror((fd),&errnum); \
|
||||
S_glzclearerr((fd)); \
|
||||
if (errnum == Z_ERRNO) { \
|
||||
flag = errno != EINTR; \
|
||||
} else { \
|
||||
flag = not_ok_is_fatal || errnum != Z_OK; \
|
||||
errno = 0; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
/* like FD_GUARD and GZ_GUARD but spins on EINTR */
|
||||
#define FD_EINTR_GUARD(ok,flag,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; break; } \
|
||||
else if (errno != EINTR) { flag = 1; break; } \
|
||||
} while (1)
|
||||
#define GZ_EINTR_GUARD(not_ok_is_fatal,ok,flag,fd,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; break; } \
|
||||
else { \
|
||||
INT errnum; \
|
||||
S_glzerror((fd),&errnum); \
|
||||
S_glzclearerr((fd)); \
|
||||
if (errnum == Z_ERRNO) { \
|
||||
if (errno != EINTR) { flag = 1; break; } \
|
||||
} else { \
|
||||
flag = not_ok_is_fatal || errnum != Z_OK; \
|
||||
errno = 0; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} while (1)
|
||||
#else /* EINTR */
|
||||
#define FD_GUARD(ok,flag,body) do { body; flag = !(ok); } while (0)
|
||||
#define GZ_GUARD(not_ok_is_fatal,ok,flag,fd,body) \
|
||||
do { body; \
|
||||
if (ok) { flag = 0; } \
|
||||
else { \
|
||||
INT errnum; \
|
||||
S_glzerror((fd),&errnum); \
|
||||
S_glzclearerr((fd)); \
|
||||
if (errnum == Z_ERRNO) { flag = 1; } \
|
||||
else { \
|
||||
flag = not_ok_is_fatal || errnum != Z_OK; \
|
||||
errno = 0; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
#define FD_EINTR_GUARD FD_GUARD
|
||||
#define GZ_EINTR_GUARD GZ_GUARD
|
||||
#endif /* EINTR */
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif /* O_BINARY */
|
||||
|
||||
|
||||
/* These functions are intended for use immediately upon opening
|
||||
* (lockfile) fd. They need to be redesigned for general-purpose
|
||||
* locking. */
|
||||
#ifdef FLOCK
|
||||
static INT lockfile(INT fd) { return FLOCK(fd, LOCK_EX); }
|
||||
#endif
|
||||
#ifdef LOCKF
|
||||
static INT lockfile(INT fd) { return lockf(fd, F_LOCK, (off_t)0); }
|
||||
#endif
|
||||
|
||||
#define MAKE_GZXFILE(x) Sinteger((iptr)x)
|
||||
#define GZXFILE_GZFILE(x) ((glzFile)Sinteger_value(x))
|
||||
|
||||
INT S_gzxfile_fd(ptr x) {
|
||||
return GZXFILE_GZFILE(x)->fd;
|
||||
}
|
||||
|
||||
glzFile S_gzxfile_gzfile(ptr x) {
|
||||
return GZXFILE_GZFILE(x);
|
||||
}
|
||||
|
||||
ptr S_new_open_input_fd(const char *infilename, IBOOL compressed) {
|
||||
char *filename;
|
||||
INT saved_errno = 0;
|
||||
INT fd, dupfd, error, result, ok, flag;
|
||||
glzFile file;
|
||||
#ifdef PTHREADS
|
||||
ptr tc = get_thread_context();
|
||||
#endif
|
||||
|
||||
filename = S_malloc_pathname(infilename);
|
||||
|
||||
/* NB: don't use infilename, which might point into a Scheme string, after this point */
|
||||
DEACTIVATE(tc)
|
||||
FD_EINTR_GUARD(fd>=0, error, fd=OPEN(filename,O_BINARY|O_RDONLY,0));
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
||||
/* NB: don't use free'd filename after this point */
|
||||
free(filename);
|
||||
|
||||
if (error) {
|
||||
ptr str = S_strerror(saved_errno);
|
||||
switch (saved_errno) {
|
||||
case EACCES:
|
||||
return Scons(FIX(OPEN_ERROR_PROTECTION), str);
|
||||
case ENOENT:
|
||||
return Scons(FIX(OPEN_ERROR_EXISTSNOT), str);
|
||||
default:
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!compressed) {
|
||||
return MAKE_FD(fd);
|
||||
}
|
||||
|
||||
if ((dupfd = DUP(fd)) == -1) {
|
||||
ptr str = S_strerror(errno);
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), str);
|
||||
}
|
||||
|
||||
DEACTIVATE(tc) /* glzdopen_input reads the magic word from the file */
|
||||
if ((file = S_glzdopen_input(dupfd)) == Z_NULL) {
|
||||
REACTIVATE(tc)
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
FD_GUARD(result == 0, error, result = CLOSE(dupfd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state (too many open files?)"));
|
||||
}
|
||||
|
||||
compressed = !S_glzdirect(file);
|
||||
REACTIVATE(tc)
|
||||
|
||||
if (compressed) {
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
/* box indicates compressed */
|
||||
return Sbox(MAKE_GZXFILE(file));
|
||||
}
|
||||
|
||||
GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = S_glzclose(file));
|
||||
if (flag) {} /* make the compiler happy */
|
||||
if (LSEEK(fd, 0, SEEK_SET) != 0) { /* glzdopen and glzdirect might not leave fd at position 0 */
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER),Sstring("unable to reset after reading header bytes"));
|
||||
}
|
||||
return MAKE_FD(fd);
|
||||
}
|
||||
|
||||
ptr S_compress_input_fd(INT fd, I64 pos) {
|
||||
INT dupfd, error, result, ok, flag; IBOOL compressed;
|
||||
glzFile file;
|
||||
#ifdef PTHREADS
|
||||
ptr tc = get_thread_context();
|
||||
#endif
|
||||
|
||||
if ((dupfd = DUP(fd)) == -1) {
|
||||
return S_strerror(errno);
|
||||
}
|
||||
|
||||
DEACTIVATE(tc)
|
||||
if ((file = S_glzdopen_input(dupfd)) == Z_NULL) {
|
||||
REACTIVATE(tc)
|
||||
FD_GUARD(result == 0, error, result = CLOSE(dupfd));
|
||||
return Sstring("unable to allocate compression state (too many open files?)");
|
||||
}
|
||||
|
||||
compressed = !S_glzdirect(file);
|
||||
REACTIVATE(tc)
|
||||
|
||||
if (compressed) {
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
if (error) {} /* make the compiler happy */
|
||||
/* box indicates compressed */
|
||||
return Sbox(MAKE_GZXFILE(file));
|
||||
}
|
||||
|
||||
GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, file, ok = S_glzclose(file));
|
||||
if (flag) {} /* make the compiler happy */
|
||||
if (LSEEK(fd, pos, SEEK_SET) != pos) { /* glzdirect does not leave fd at same position */
|
||||
return Sstring("unable to reset after reading header bytes");
|
||||
}
|
||||
return MAKE_FD(fd);
|
||||
}
|
||||
|
||||
ptr S_compress_output_fd(INT fd) {
|
||||
glzFile file;
|
||||
ptr tc = get_thread_context();
|
||||
|
||||
file = S_glzdopen_output(fd, (INT)UNFIX(COMPRESSFORMAT(tc)), (INT)UNFIX(COMPRESSLEVEL(tc)));
|
||||
|
||||
if (file == Z_NULL)
|
||||
return Sstring("unable to allocate compression state (too many open files?)");
|
||||
|
||||
/* box indicates compressed */
|
||||
return Sbox(MAKE_GZXFILE(file));
|
||||
}
|
||||
|
||||
static ptr new_open_output_fd_helper(
|
||||
const char *infilename, INT mode, INT flags,
|
||||
IBOOL no_create, IBOOL no_fail, IBOOL no_truncate,
|
||||
IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) {
|
||||
char *filename;
|
||||
INT saved_errno = 0;
|
||||
iptr error;
|
||||
INT fd, result;
|
||||
ptr tc = get_thread_context();
|
||||
|
||||
flags |=
|
||||
(no_create ? 0 : O_CREAT) |
|
||||
((no_fail || no_create) ? 0 : O_EXCL) |
|
||||
(no_truncate ? 0 : O_TRUNC) |
|
||||
((!append) ? 0 : O_APPEND);
|
||||
|
||||
filename = S_malloc_pathname(infilename);
|
||||
|
||||
if (replace && UNLINK(filename) != 0 && errno != ENOENT) {
|
||||
ptr str = S_strerror(errno);
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
return Scons(FIX(OPEN_ERROR_PROTECTION), str);
|
||||
default:
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), str);
|
||||
}
|
||||
}
|
||||
|
||||
/* NB: don't use infilename, which might point into a Scheme string, after this point */
|
||||
DEACTIVATE(tc)
|
||||
FD_EINTR_GUARD(fd >= 0, error, fd = OPEN(filename, flags, mode));
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
||||
/* NB: don't use free'd filename after this point */
|
||||
free(filename);
|
||||
|
||||
if (error) {
|
||||
ptr str = S_strerror(saved_errno);
|
||||
switch (saved_errno) {
|
||||
case EACCES:
|
||||
return Scons(FIX(OPEN_ERROR_PROTECTION), str);
|
||||
case EEXIST:
|
||||
return Scons(FIX(OPEN_ERROR_EXISTS), str);
|
||||
case ENOENT:
|
||||
return Scons(FIX(OPEN_ERROR_EXISTSNOT), str);
|
||||
default:
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), str);
|
||||
}
|
||||
}
|
||||
|
||||
if (lock) {
|
||||
DEACTIVATE(tc)
|
||||
error = lockfile(fd);
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
if (error) {
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), S_strerror(saved_errno));
|
||||
}
|
||||
}
|
||||
|
||||
if (!compressed) {
|
||||
return MAKE_FD(fd);
|
||||
}
|
||||
|
||||
glzFile file;
|
||||
file = S_glzdopen_output(fd, (INT)UNFIX(COMPRESSFORMAT(tc)), (INT)UNFIX(COMPRESSLEVEL(tc)));
|
||||
if (file == Z_NULL) {
|
||||
FD_GUARD(result == 0, error, result = CLOSE(fd));
|
||||
return Scons(FIX(OPEN_ERROR_OTHER), Sstring("unable to allocate compression state"));
|
||||
}
|
||||
|
||||
return MAKE_GZXFILE(file);
|
||||
}
|
||||
|
||||
ptr S_new_open_output_fd(
|
||||
const char *filename, INT mode,
|
||||
IBOOL no_create, IBOOL no_fail, IBOOL no_truncate,
|
||||
IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) {
|
||||
return new_open_output_fd_helper(
|
||||
filename, mode, O_BINARY | O_WRONLY,
|
||||
no_create, no_fail, no_truncate,
|
||||
append, lock, replace, compressed);
|
||||
}
|
||||
|
||||
ptr S_new_open_input_output_fd(
|
||||
const char *filename, INT mode,
|
||||
IBOOL no_create, IBOOL no_fail, IBOOL no_truncate,
|
||||
IBOOL append, IBOOL lock, IBOOL replace, IBOOL compressed) {
|
||||
if (compressed)
|
||||
return Sstring("compressed input/output files not supported");
|
||||
else
|
||||
return new_open_output_fd_helper(
|
||||
filename, mode, O_BINARY | O_RDWR,
|
||||
no_create, no_fail, no_truncate,
|
||||
append, lock, replace, 0);
|
||||
}
|
||||
|
||||
ptr S_close_fd(ptr file, IBOOL gzflag) {
|
||||
INT saved_errno = 0;
|
||||
INT ok, flag;
|
||||
INT fd = gzflag ? 0 : GET_FD(file);
|
||||
glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL;
|
||||
#ifdef PTHREADS
|
||||
ptr tc = get_thread_context();
|
||||
#endif
|
||||
|
||||
/* refuse to close stdin, stdout, and stderr fds */
|
||||
if (!gzflag && fd <= 2) return Strue;
|
||||
|
||||
/* file is not locked; do not reference after deactivating thread! */
|
||||
file = (ptr)-1;
|
||||
|
||||
/* NOTE: close automatically releases locks so we don't to call unlock*/
|
||||
DEACTIVATE(tc)
|
||||
if (!gzflag) {
|
||||
FD_GUARD(ok == 0, flag, ok = CLOSE(fd));
|
||||
} else {
|
||||
/* zlib 1.2.1 returns Z_BUF_ERROR when closing an empty file opened for reading */
|
||||
GZ_GUARD(1, ok == 0 || ok == Z_BUF_ERROR, flag, gzfile, ok = S_glzclose(gzfile));
|
||||
}
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
||||
if (!flag) {
|
||||
return Strue;
|
||||
}
|
||||
|
||||
if (gzflag && saved_errno == 0) {
|
||||
return Sstring("compression failed");
|
||||
}
|
||||
|
||||
return S_strerror(saved_errno);
|
||||
}
|
||||
|
||||
#define GZ_IO_SIZE_T unsigned int
|
||||
|
||||
#ifdef WIN32
|
||||
#define IO_SIZE_T unsigned int
|
||||
static HANDLE hStdin = NULL;
|
||||
static iptr read_console(char* buf, unsigned size) {
|
||||
static char u8buf[1024];
|
||||
static int u8i = 0;
|
||||
static int u8n = 0;
|
||||
iptr n = 0;
|
||||
do {
|
||||
for (; size > 0 && u8n > 0; size--, u8n--, n++)
|
||||
*buf++ = u8buf[u8i++];
|
||||
if (n == 0 && size > 0) {
|
||||
wchar_t wbuf[256];
|
||||
DWORD wn;
|
||||
if (!ReadConsoleW(hStdin, wbuf, 256, &wn, NULL) || wn == 0)
|
||||
return 0;
|
||||
u8n = WideCharToMultiByte(CP_UTF8, 0, wbuf, wn, u8buf, 1024, NULL, NULL);
|
||||
u8i = 0;
|
||||
}
|
||||
} while (n == 0);
|
||||
return n;
|
||||
}
|
||||
#else /* WIN32 */
|
||||
#define IO_SIZE_T size_t
|
||||
#endif /* WIN32 */
|
||||
|
||||
/* Returns string on error, #!eof on end-of-file and integer-count otherwise */
|
||||
ptr S_bytevector_read(ptr file, ptr bv, iptr start, iptr count, IBOOL gzflag) {
|
||||
INT saved_errno = 0;
|
||||
ptr tc = get_thread_context();
|
||||
iptr m, flag = 0;
|
||||
INT fd = gzflag ? 0 : GET_FD(file);
|
||||
glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL;
|
||||
|
||||
/* file is not locked; do not reference after deactivating thread! */
|
||||
file = (ptr)-1;
|
||||
|
||||
#if (iptr_bits > 32)
|
||||
if ((WIN32 || gzflag) && (unsigned int)count != count) count = 0xffffffff;
|
||||
#endif
|
||||
|
||||
LOCKandDEACTIVATE(tc, bv)
|
||||
#ifdef CHECK_FOR_ROSETTA
|
||||
/* If we are running on Apple Silicon under Rosetta 2 translation, work around
|
||||
a bug (present in 11.2.3 at least) in its handling of memory page protection
|
||||
bits. One of the tasks that Rosetta handles is to appropriately twiddle the
|
||||
execute and write bits based on what's happening to the memory in order to
|
||||
preserve the illusion that the pages have RWX permissions, whereas Apple
|
||||
Silicon enforces a W^X (write XOR execute) model. For some reason, this
|
||||
bit-twiddling sometimes fails when the bytevector passed to `read` extends
|
||||
onto a page that's currently R-X, causing the `read` to fail with EFAULT
|
||||
("bad address"). By writing to each subsequent page, we force Rosetta to
|
||||
do the right magic to the protection bits. (Or at least it makes the error
|
||||
go away and all the mats pass.)
|
||||
*/
|
||||
if (is_rosetta) {
|
||||
for (iptr idx = start+count; idx > start; idx -= S_pagesize) {
|
||||
volatile octet b = BVIT(bv,idx);
|
||||
BVIT(bv,idx) = b;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
if (!gzflag && fd == 0 && hStdin != NULL) {
|
||||
DWORD error_code;
|
||||
SetConsoleCtrlHandler(NULL, TRUE);
|
||||
SetLastError(0);
|
||||
m = read_console(&BVIT(bv,start), (IO_SIZE_T)count);
|
||||
error_code = GetLastError();
|
||||
if (m == 0 && error_code == 0x3e3) {
|
||||
/* Guard against Windows calling the ConsoleCtrlHandler after we
|
||||
* turn it back on by waiting a bit. */
|
||||
Sleep(1);
|
||||
#ifdef PTHREADS
|
||||
/* threaded io.ss doesn't handle interrupts because
|
||||
* with-tc-mutex disables them, so bail out. */
|
||||
SetConsoleCtrlHandler(NULL, FALSE);
|
||||
REACTIVATEandUNLOCK(tc, bv)
|
||||
S_noncontinuable_interrupt();
|
||||
#else
|
||||
KEYBOARDINTERRUPTPENDING(tc) = Strue;
|
||||
SOMETHINGPENDING(tc) = Strue;
|
||||
#endif
|
||||
}
|
||||
SetConsoleCtrlHandler(NULL, FALSE);
|
||||
} else
|
||||
#endif /* WIN32 */
|
||||
{
|
||||
if (!gzflag) {
|
||||
FD_EINTR_GUARD(
|
||||
m >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)), flag,
|
||||
m = READ(fd,&BVIT(bv,start),(IO_SIZE_T)count));
|
||||
} else {
|
||||
GZ_EINTR_GUARD(
|
||||
1, m >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)),
|
||||
flag, gzfile,
|
||||
m = S_glzread(gzfile, &BVIT(bv,start), (GZ_IO_SIZE_T)count));
|
||||
}
|
||||
}
|
||||
saved_errno = errno;
|
||||
REACTIVATEandUNLOCK(tc, bv)
|
||||
|
||||
if (Sboolean_value(KEYBOARDINTERRUPTPENDING(tc))) {
|
||||
return Sstring("interrupt");
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
return m == 0 ? Seof_object : FIX(m);
|
||||
}
|
||||
|
||||
if (saved_errno == EAGAIN) {
|
||||
return FIX(0);
|
||||
}
|
||||
|
||||
return S_strerror(saved_errno);
|
||||
}
|
||||
|
||||
/* Returns:
|
||||
string on error, including if not supported,
|
||||
n when read,
|
||||
0 on non-blocking and
|
||||
#!eof otherwise */
|
||||
ptr S_bytevector_read_nb(ptr file, ptr bv, iptr start, iptr count, IBOOL gzflag) {
|
||||
#ifdef WIN32
|
||||
HANDLE h;
|
||||
|
||||
/* assume compressed files are always ready */
|
||||
if (gzflag) return FIX(1);
|
||||
|
||||
if ((h = (HANDLE)_get_osfhandle(GET_FD(file))) != INVALID_HANDLE_VALUE) {
|
||||
switch (GetFileType(h)) {
|
||||
case FILE_TYPE_CHAR:
|
||||
/* if h is hStdin, PeekConsoleInput can tell us if a key down event
|
||||
is waiting, but if it's not a newline, we can't be sure that
|
||||
a read will succeed. so PeekConsoleInput is basically useless
|
||||
for our purposes. */
|
||||
break;
|
||||
case FILE_TYPE_PIPE: {
|
||||
DWORD bytes;
|
||||
if (PeekNamedPipe(h, NULL, 0, NULL, &bytes, NULL) && bytes == 0) return FIX(0);
|
||||
/* try the read on error or if bytes > 0 */
|
||||
return S_bytevector_read(file, bv, start, count, gzflag);
|
||||
}
|
||||
default: {
|
||||
if (WaitForSingleObject(h, 0) == WAIT_TIMEOUT) return FIX(0);
|
||||
/* try the read on error or if bytes > 0 */
|
||||
return S_bytevector_read(file, bv, start, count, gzflag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Sstring("cannot determine ready status");
|
||||
#else /* WIN32 */
|
||||
INT fcntl_flags;
|
||||
ptr result;
|
||||
INT fd;
|
||||
|
||||
/* assume compressed files are always ready */
|
||||
if (gzflag) return FIX(1);
|
||||
|
||||
fd = GET_FD(file);
|
||||
|
||||
/* set NOBLOCK for nonblocking read */
|
||||
fcntl_flags = fcntl(fd, F_GETFL, 0);
|
||||
if (!(fcntl_flags & NOBLOCK)) (void) fcntl(fd, F_SETFL, fcntl_flags | NOBLOCK);
|
||||
|
||||
result = S_bytevector_read(file, bv, start, count, gzflag);
|
||||
|
||||
/* reset NOBLOCK for normal blocking read */
|
||||
if (!(fcntl_flags & NOBLOCK)) (void) fcntl(fd, F_SETFL, fcntl_flags);
|
||||
|
||||
return result;
|
||||
#endif /* WIN32 */
|
||||
}
|
||||
|
||||
ptr S_bytevector_write(ptr file, ptr bv, iptr start, iptr count, IBOOL gzflag) {
|
||||
iptr i, s, c;
|
||||
ptr tc = get_thread_context();
|
||||
INT flag = 0, saved_errno = 0;
|
||||
INT fd = gzflag ? 0 : GET_FD(file);
|
||||
glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL;
|
||||
|
||||
for (s = start, c = count; c > 0; s += i, c -= i) {
|
||||
iptr cx = c;
|
||||
|
||||
#if (iptr_bits > 32)
|
||||
if ((WIN32 || gzflag) && (unsigned int)cx != cx) cx = 0xffffffff;
|
||||
#endif
|
||||
|
||||
/* if we could know that fd is nonblocking, we wouldn't need to deactivate.
|
||||
we could test ioctl, but some other thread could change it before we actually
|
||||
get around to writing. */
|
||||
LOCKandDEACTIVATE(tc, bv)
|
||||
if (gzflag) {
|
||||
/* strangely, gzwrite returns 0 on error */
|
||||
GZ_EINTR_GUARD(
|
||||
i < 0, i > 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)),
|
||||
flag, gzfile,
|
||||
i = S_glzwrite(gzfile, &BVIT(bv,s), (GZ_IO_SIZE_T)cx));
|
||||
} else {
|
||||
FD_EINTR_GUARD(i >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)),
|
||||
flag, i = WRITE(fd, &BVIT(bv,s), (IO_SIZE_T)cx));
|
||||
}
|
||||
saved_errno = errno;
|
||||
REACTIVATEandUNLOCK(tc, bv)
|
||||
|
||||
if (flag) {
|
||||
if (saved_errno == EAGAIN) { flag = 0; }
|
||||
break;
|
||||
}
|
||||
|
||||
/* we escape from loop if keyboard interrupt is pending, but this won't
|
||||
do much good until we fix up the interrupt protocol to guarantee
|
||||
that the interrupt handler is actually called */
|
||||
if (Sboolean_value(KEYBOARDINTERRUPTPENDING(tc))) {
|
||||
if (i >= 0) s += i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
return FIX(s - start);
|
||||
}
|
||||
|
||||
if (saved_errno == EAGAIN) {
|
||||
return FIX(0);
|
||||
}
|
||||
|
||||
if (gzflag && saved_errno == 0) {
|
||||
return Sstring("compression failed");
|
||||
}
|
||||
|
||||
return S_strerror(saved_errno);
|
||||
}
|
||||
|
||||
/* S_put_byte is a simplified version of S_bytevector_write for writing one
|
||||
byte on unbuffered ports */
|
||||
ptr S_put_byte(ptr file, INT byte, IBOOL gzflag) {
|
||||
iptr i;
|
||||
ptr tc = get_thread_context();
|
||||
INT flag = 0, saved_errno = 0;
|
||||
INT fd = gzflag ? 0 : GET_FD(file);
|
||||
glzFile gzfile = gzflag ? GZXFILE_GZFILE(file) : NULL;
|
||||
octet buf[1];
|
||||
|
||||
buf[0] = (octet)byte;
|
||||
|
||||
DEACTIVATE(tc)
|
||||
if (gzflag) {
|
||||
/* strangely, gzwrite returns 0 on error */
|
||||
GZ_EINTR_GUARD(
|
||||
i < 0, i > 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)),
|
||||
flag, gzfile,
|
||||
i = S_glzwrite(gzfile, buf, 1));
|
||||
} else {
|
||||
FD_EINTR_GUARD(i >= 0 || Sboolean_value(KEYBOARDINTERRUPTPENDING(tc)),
|
||||
flag, i = WRITE(fd, buf, 1));
|
||||
}
|
||||
saved_errno = errno;
|
||||
REACTIVATE(tc)
|
||||
|
||||
if (flag) {
|
||||
if (saved_errno == EAGAIN) { flag = 0; }
|
||||
}
|
||||
|
||||
if (!flag) {
|
||||
return FIX(i);
|
||||
}
|
||||
|
||||