1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-14 23:50:19 +02:00

Merge branch 'master' into boehm-demers-weiser-gc

Conflicts:
	libguile/Makefile.am
	libguile/bytevectors.c
	libguile/gc-card.c
	libguile/gc-mark.c
	libguile/programs.c
	libguile/srcprop.c
	libguile/srfi-14.c
	libguile/symbols.c
	libguile/threads.c
	libguile/unif.c
	libguile/vm.c
This commit is contained in:
Ludovic Courtès 2009-08-28 19:01:19 +02:00
commit 7af531508c
205 changed files with 18774 additions and 8289 deletions

5
.gitignore vendored
View file

@ -12,7 +12,6 @@ config.guess
config.status config.status
config.log config.log
config.h config.h
guile-readline-config.h
*.doc *.doc
*.x *.x
*.lo *.lo
@ -65,8 +64,6 @@ pre-inst-guile-env
stamp-h1 stamp-h1
guile-procedures.txt guile-procedures.txt
guile-config/guile-config guile-config/guile-config
guile-readline/guile-readline-config.h
guile-readline/guile-readline-config.h.in
*.go *.go
TAGS TAGS
/meta/guile-2.0.pc /meta/guile-2.0.pc
@ -75,6 +72,8 @@ gdb-pre-inst-guile
cscope.out cscope.out
cscope.files cscope.files
*.log *.log
gds-test.debug
gds-test.transcript
INSTALL INSTALL
*.aux *.aux
*.cp *.cp

29
AUTHORS
View file

@ -206,8 +206,34 @@ In the subdirectory doc, changes to:
Many changes throughout. Many changes throughout.
Neil Jerram: Neil Jerram:
In the subdirectory emacs, wrote:
gds.el gds-scheme.el gds-server.el
gds-test.el gds-test.sh gds-test.stdin
gds-tutorial.txt gds-faq.txt
In the subdirectory ice-9, wrote: In the subdirectory ice-9, wrote:
buffered-input.scm buffered-input.scm gds-client.scm gds-server.scm
In the subdirectory ice-9/debugging, wrote:
example-fns.scm ice-9-debugger-extensions.scm
steps.scm trace.scm traps.scm
trc.scm
In the subdirectory lang/elisp, wrote:
base.scm example.el interface.scm
transform.scm variables.scm
In the subdirectory lang/elisp/internals, wrote:
evaluation.scm format.scm fset.scm
lambda.scm load.scm null.scm
set.scm signal.scm time.scm
trace.scm
In the subdirectory lang/elisp/primitives, wrote:
buffers.scm char-table.scm features.scm
fns.scm format.scm guile.scm
keymaps.scm lists.scm load.scm
match.scm numbers.scm pure.scm
read.scm signal.scm strings.scm
symprop.scm syntax.scm system.scm
time.scm
In the subdirectory srfi, wrote:
srfi-34.scm
In the subdirectory doc, wrote: In the subdirectory doc, wrote:
deprecated.texi goops.texi scheme-ideas.texi deprecated.texi goops.texi scheme-ideas.texi
scheme-reading.texi scheme-reading.texi
@ -227,6 +253,7 @@ In the subdirectory doc, changes to:
scm.texi scripts.texi script-getopt.texi scm.texi scripts.texi script-getopt.texi
In the subdirectory doc/maint, wrote: In the subdirectory doc/maint, wrote:
docstring.el docstring.el
Many other changes throughout.
Thien-Thi Nguyen: Thien-Thi Nguyen:
In the top-level directory, wrote: In the top-level directory, wrote:

View file

@ -42,6 +42,9 @@ DISTCLEANFILES = check-guile.log
dist-hook: gen-ChangeLog dist-hook: gen-ChangeLog
clean-local:
rm -rf cache/
gen_start_rev = 61db429e251bfd2f75cb4632972e0238056eb24b gen_start_rev = 61db429e251bfd2f75cb4632972e0238056eb24b
.PHONY: gen-ChangeLog .PHONY: gen-ChangeLog
gen-ChangeLog: gen-ChangeLog:

157
NEWS
View file

@ -8,100 +8,25 @@ Please send Guile bug reports to bug-guile@gnu.org.
(During the 1.9 series, we will keep an incremental NEWS for the latest (During the 1.9 series, we will keep an incremental NEWS for the latest
prerelease, and a full NEWS corresponding to 1.8 -> 2.0.) prerelease, and a full NEWS corresponding to 1.8 -> 2.0.)
Changes in 1.9.2 (since the 1.9.1 prerelease): Changes in 1.9.3 (since the 1.9.2 prerelease):
** VM speed improvements ** Removed deprecated uniform array procedures: scm_make_uve,
scm_array_prototype, scm_list_to_uniform_array,
scm_dimensions_to_uniform_array, scm_make_ra, scm_shap2ra, scm_cvref,
scm_ra_set_contp, scm_aind, scm_raprin1
Closures now copy the free variables that they need into a flat vector These functions have been deprecated since early 2005.
instead of capturing all heap-allocated variables. This speeds up access
to free variables, avoids unnecessary garbage retention, and allows all
variables to be allocated on the stack.
Variables which are `set!' are now allocated on the stack, but in ** scm_array_p has one argument, not two
"boxes". This allows a more uniform local variable allocation
discipline, and allows faster access to these variables.
The VM has new special-case operations, `add1' and `sub1'. Use of the second argument produced a deprecation warning, so it is
unlikely that any code out there actually used this functionality.
** VM robustness improvements ** Removed deprecated uniform array procedures:
dimensions->uniform-array, list->uniform-array, array-prototype
The maximum number of live local variables has been increased from 256 Instead, use make-typed-array, list->typed-array, or array-type,
to 65535. respectively.
The default VM stack size is 64 kilo-words, up from 16 kilo-words. This
allows more programs to execute in the default stack space. In the
future we will probably implement extensible stacks via overflow
handlers.
Some lingering cases in which the VM could perform unaligned accesses
have been fixed.
The address range for relative jumps has been expanded from 16-bit
addresses to 19-bit addresses via 8-byte alignment of jump targets. This
will probably change to a 24-bit byte-addressable strategy before Guile
2.0.
** Compiler optimizations
Procedures bound by `letrec' are no longer allocated on the heap,
subject to a few constraints. In many cases, procedures bound by
`letrec' and `let' can be rendered inline to their parent function, with
loop detection for mutually tail-recursive procedures.
Unreferenced variables are now optimized away.
** Compiler robustness
Guile may now warn about unused lexically-bound variables. Pass
`-Wunused-variable' to `guile-tools compile', or `#:warnings
(unused-variable)' within the #:opts argument to the `compile' procedure
from `(system base compile)'.
** Incomplete support for Unicode characters and strings
Preliminary support for Unicode has landed. Characters may be entered in
octal format via e.g. `#\454', or created via (integer->char 300). A hex
external representation will probably be introduced at some point.
Internally, strings are now represented either in the `latin-1'
encoding, one byte per character, or in UTF-32, with four bytes per
character. Strings manage their own allocation, switching if needed.
Currently no locale conversion is performed. Extended characters may be
written in a string using the hexadecimal escapes `\xXX', `\uXXXX', or
`\UXXXXXX', for 8-bit, 16-bit, or 24-bit codepoints, respectively.
This support is obviously incomplete. Many C functions have not yet been
updated to deal with the new representations. Users are advised to wait
for the next release for more serious use of Unicode strings.
** `defined?' may accept a module as its second argument
Previously it only accepted internal structures from the evaluator.
** `let-values' is now implemented with a hygienic macro
This could have implications discussed below in the NEWS entry titled,
"Lexical bindings introduced by hygienic macros may not be referenced by
nonhygienic macros".
** Global variables `scm_charnames' and `scm_charnums' are removed
These variables contained the names of control characters and were
used when writing characters. While these were global, they were
never intended to be public API. They have been replaced with private
functions.
** EBCDIC support is removed
There was an EBCDIC compile flag that altered some of the character
processing. It appeared that full EBCDIC support was never completed
and was unmaintained.
** Packaging changes
Guile now provides `guile-2.0.pc' (used by pkg-config) instead of
`guile-1.8.pc'.
** And of course, the usual collection of bugfixes ** And of course, the usual collection of bugfixes
@ -555,6 +480,35 @@ This decision may be revisited before the 2.0 release. Feedback welcome
to guile-devel@gnu.org (subscription required) or bug-guile@gnu.org (no to guile-devel@gnu.org (subscription required) or bug-guile@gnu.org (no
subscription required). subscription required).
** Unicode characters
Unicode characters may be entered in octal format via e.g. `#\454', or
created via (integer->char 300). A hex external representation will
probably be introduced at some point.
** Unicode strings
Internally, strings are now represented either in the `latin-1'
encoding, one byte per character, or in UTF-32, with four bytes per
character. Strings manage their own allocation, switching if needed.
Currently no locale conversion is performed. Extended characters may be
written in a string using the hexadecimal escapes `\xXX', `\uXXXX', or
`\UXXXXXX', for 8-bit, 16-bit, or 24-bit codepoints, respectively.
** Global variables `scm_charnames' and `scm_charnums' are removed
These variables contained the names of control characters and were
used when writing characters. While these were global, they were
never intended to be public API. They have been replaced with private
functions.
** EBCDIC support is removed
There was an EBCDIC compile flag that altered some of the character
processing. It appeared that full EBCDIC support was never completed
and was unmaintained.
** New macro type: syncase-macro ** New macro type: syncase-macro
XXX Need to decide whether to document this for 2.0, probably should: XXX Need to decide whether to document this for 2.0, probably should:
@ -588,6 +542,10 @@ These are analogous to %load-path and %load-extensions.
`(make-promise (lambda () foo))' is equivalent to `(delay foo)'. `(make-promise (lambda () foo))' is equivalent to `(delay foo)'.
** `defined?' may accept a module as its second argument
Previously it only accepted internal structures from the evaluator.
** New entry into %guile-build-info: `ccachedir' ** New entry into %guile-build-info: `ccachedir'
** Fix bug in `module-bound?'. ** Fix bug in `module-bound?'.
@ -601,6 +559,12 @@ the variable. This was an error, and was fixed.
As syntax-case is available by default, importing `(ice-9 syncase)' has As syntax-case is available by default, importing `(ice-9 syncase)' has
no effect, and will trigger a deprecation warning. no effect, and will trigger a deprecation warning.
** Removed deprecated uniform array procedures:
dimensions->uniform-array, list->uniform-array, array-prototype
Instead, use make-typed-array, list->typed-array, or array-type,
respectively.
* Changes to the C interface * Changes to the C interface
** The GH interface (deprecated in version 1.6, 2001) was removed. ** The GH interface (deprecated in version 1.6, 2001) was removed.
@ -629,6 +593,18 @@ definition depends on the application's value for `_FILE_OFFSET_BITS'.
** The `long_long' C type, deprecated in 1.8, has been removed ** The `long_long' C type, deprecated in 1.8, has been removed
** Removed deprecated uniform array procedures: scm_make_uve,
scm_array_prototype, scm_list_to_uniform_array,
scm_dimensions_to_uniform_array, scm_make_ra, scm_shap2ra, scm_cvref,
scm_ra_set_contp, scm_aind, scm_raprin1
These functions have been deprecated since early 2005.
** scm_array_p has one argument, not two
Use of the second argument produced a deprecation warning, so it is
unlikely that any code out there actually used this functionality.
* Changes to the distribution * Changes to the distribution
** Guile's license is now LGPLv3+ ** Guile's license is now LGPLv3+
@ -656,8 +632,8 @@ to /usr/lib/guile/1.9/ccache. These files are architecture-specific.
** New dependency: GNU libunistring. ** New dependency: GNU libunistring.
See http://www.gnu.org/software/libunistring/. We hope to merge in See http://www.gnu.org/software/libunistring/, for more information. Our
Unicode support in the next prerelease. unicode support uses routines from libunistring.
@ -666,6 +642,7 @@ Changes in 1.8.8 (since 1.8.7)
* Bugs fixed * Bugs fixed
** Fix possible buffer overruns when parsing numbers ** Fix possible buffer overruns when parsing numbers
** Avoid clash with system setjmp/longjmp on IA64
Changes in 1.8.7 (since 1.8.6) Changes in 1.8.7 (since 1.8.6)

5
README
View file

@ -299,9 +299,8 @@ Guile Documentation ==================================================
If you've never used Scheme before, then the Guile Tutorial If you've never used Scheme before, then the Guile Tutorial
(guile-tut.info) is a good starting point. The Guile Reference Manual (guile-tut.info) is a good starting point. The Guile Reference Manual
(guile.info) is the primary documentation for Guile. The Goops object (guile.info) is the primary documentation for Guile. A copy of the
system is documented separately (goops.info). A copy of the R5RS R5RS Scheme specification is included too (r5rs.info).
Scheme specification is included too (r5rs.info).
Info format versions of this documentation are installed as part of Info format versions of this documentation are installed as part of
the normal build process. The texinfo sources are under the doc the normal build process. The texinfo sources are under the doc

4
THANKS
View file

@ -30,6 +30,7 @@ For fixes or providing information which led to a fix:
Rob Browning Rob Browning
Adrian Bunk Adrian Bunk
Michael Carmack Michael Carmack
R Clayton
Stephen Compall Stephen Compall
Brian Crowder Brian Crowder
Christopher Cramer Christopher Cramer
@ -52,6 +53,7 @@ For fixes or providing information which led to a fix:
Roland Haeder Roland Haeder
Sven Hartrumpf Sven Hartrumpf
Eric Hanchrow Eric Hanchrow
Judy Hawkins
Sam Hocevar Sam Hocevar
Patrick Horgan Patrick Horgan
Ales Hvezda Ales Hvezda
@ -94,6 +96,7 @@ For fixes or providing information which led to a fix:
Werner Scheinast Werner Scheinast
Bill Schottstaedt Bill Schottstaedt
Frank Schwidom Frank Schwidom
John Steele Scott
Thiemo Seufer Thiemo Seufer
Scott Shedden Scott Shedden
Alex Shinn Alex Shinn
@ -114,6 +117,7 @@ For fixes or providing information which led to a fix:
Andreas Vögele Andreas Vögele
Michael Talbot-Wilson Michael Talbot-Wilson
Michael Tuexen Michael Tuexen
Thomas Wawrzinek
Mark H. Weaver Mark H. Weaver
Jon Wilson Jon Wilson
Andy Wingo Andy Wingo

View file

@ -1,3 +1,5 @@
dnl -*- Autoconf -*-
dnl On the NeXT, #including <utime.h> doesn't give you a definition for dnl On the NeXT, #including <utime.h> doesn't give you a definition for
dnl struct utime, unless you #define _POSIX_SOURCE. dnl struct utime, unless you #define _POSIX_SOURCE.
@ -308,3 +310,70 @@ else
fi fi
AC_LANG_RESTORE AC_LANG_RESTORE
])dnl ACX_PTHREAD ])dnl ACX_PTHREAD
dnl GUILE_READLINE
dnl
dnl Check all the things needed by `guile-readline', the Readline
dnl bindings.
AC_DEFUN([GUILE_READLINE], [
for termlib in ncurses curses termcap terminfo termlib ; do
AC_CHECK_LIB(${termlib}, [tgoto],
[READLINE_LIBS="-l${termlib} $READLINE_LIBS"; break])
done
AC_LIB_LINKFLAGS([readline])
if test "x$LTLIBREADLINE" = "x"; then
AC_MSG_WARN([GNU Readline was not found on your system.])
else
rl_save_LIBS="$LIBS"
LIBS="$LIBREADLINE $READLINE_LIBS $LIBS"
AC_CHECK_FUNCS([siginterrupt rl_clear_signals rl_cleanup_after_signal])
dnl Check for modern readline naming
AC_CHECK_FUNCS([rl_filename_completion_function])
dnl Check for rl_get_keymap. We only use this for deciding whether to
dnl install paren matching on the Guile command line (when using
dnl readline for input), so it's completely optional.
AC_CHECK_FUNCS([rl_get_keymap])
AC_CACHE_CHECK([for rl_getc_function pointer in readline],
ac_cv_var_rl_getc_function,
[AC_TRY_LINK([
#include <stdio.h>
#include <readline/readline.h>],
[printf ("%ld", (long) rl_getc_function)],
[ac_cv_var_rl_getc_function=yes],
[ac_cv_var_rl_getc_function=no])])
if test "${ac_cv_var_rl_getc_function}" = "yes"; then
AC_DEFINE([HAVE_RL_GETC_FUNCTION], 1,
[Define if your readline library has the rl_getc_function variable.])
fi
if test $ac_cv_var_rl_getc_function = no; then
AC_MSG_WARN([*** GNU Readline is too old on your system.])
AC_MSG_WARN([*** You need readline version 2.1 or later.])
LTLIBREADLINE=""
LIBREADLINE=""
fi
LIBS="$rl_save_LIBS"
READLINE_LIBS="$LTLIBREADLINE $READLINE_LIBS"
fi
AM_CONDITIONAL([HAVE_READLINE], [test "x$LTLIBREADLINE" != "x"])
AC_CHECK_FUNCS([strdup])
AC_SUBST([READLINE_LIBS])
. $srcdir/guile-readline/LIBGUILEREADLINE-VERSION
AC_SUBST(LIBGUILEREADLINE_MAJOR)
AC_SUBST(LIBGUILEREADLINE_INTERFACE_CURRENT)
AC_SUBST(LIBGUILEREADLINE_INTERFACE_REVISION)
AC_SUBST(LIBGUILEREADLINE_INTERFACE_AGE)
AC_SUBST(LIBGUILEREADLINE_INTERFACE)
])

View file

@ -0,0 +1,57 @@
;;; -*- mode: scheme; coding: latin-1; -*-
;;; chars.bm
;;;
;;; Copyright (C) 2009 Free Software Foundation, Inc.
;;;
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Lesser General Public License
;;; as published by the Free Software Foundation; either version 3, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public
;;; License along with this software; see the file COPYING.LESSER. If
;;; not, write to the Free Software Foundation, Inc., 51 Franklin
;;; Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (benchmarks chars)
:use-module (benchmark-suite lib))
(with-benchmark-prefix "chars"
(benchmark "char" 1000000
#\a)
(benchmark "octal" 1000000
#\123)
(benchmark "char? eq" 1000000
(char? #\a))
(benchmark "char=?" 1000000
(char=? #\a #\a))
(benchmark "char<?" 1000000
(char=? #\a #\a))
(benchmark "char-ci=?" 1000000
(char=? #\a #\a))
(benchmark "char-ci<? " 1000000
(char=? #\a #\a))
(benchmark "char->integer" 1000000
(char->integer #\a))
(benchmark "char-alphabetic?" 1000000
(char-upcase #\a))
(benchmark "char-numeric?" 1000000
(char-upcase #\a)))

View file

@ -0,0 +1,310 @@
;;; -*- mode: scheme; coding: latin-1; -*-
;;; srfi-13.bm
;;;
;;; Copyright (C) 2009 Free Software Foundation, Inc.
;;;
;;;
;;; This program is free software; you can redistribute it and/or
;;; modify it under the terms of the GNU Lesser General Public License
;;; as published by the Free Software Foundation; either version 3, or
;;; (at your option) any later version.
;;;
;;; This program is distributed in the hope that it will be useful,
;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU Lesser General Public License for more details.
;;;
;;; You should have received a copy of the GNU Lesser General Public
;;; License along with this software; see the file COPYING.LESSER. If
;;; not, write to the Free Software Foundation, Inc., 51 Franklin
;;; Street, Fifth Floor, Boston, MA 02110-1301 USA
(define-module (benchmarks strings)
:use-module (benchmark-suite lib))
(seed->random-state 1)
(define short-string "Hi")
(define medium-string
"ARMA virumque cano, Troiae qui primus ab oris
Italiam, fato profugus, Laviniaque venit")
(define long-string
(string-tabulate
(lambda (n) (integer->char (+ 32 (random 90))))
1000))
(define short-chlist (string->list short-string))
(define medium-chlist (string->list medium-string))
(define long-chlist (string->list long-string))
(define str1 (string-copy short-string))
(define str2 (string-copy medium-string))
(define str3 (string-copy long-string))
(with-benchmark-prefix "strings"
(with-benchmark-prefix "predicates"
(benchmark "string?" 1190000
(string? short-string)
(string? medium-string)
(string? long-string))
(benchmark "null?" 969000
(string-null? short-string)
(string-null? medium-string)
(string-null? long-string))
(benchmark "any" 94000
(string-any #\a short-string)
(string-any #\a medium-string)
(string-any #\a long-string))
(benchmark "every" 94000
(string-every #\a short-string)
(string-every #\a medium-string)
(string-every #\a long-string)))
(with-benchmark-prefix "constructors"
(benchmark "string" 5000
(apply string short-chlist)
(apply string medium-chlist)
(apply string long-chlist))
(benchmark "list->" 4500
(list->string short-chlist)
(list->string medium-chlist)
(list->string long-chlist))
(benchmark "reverse-list->" 5000
(reverse-list->string short-chlist)
(reverse-list->string medium-chlist)
(reverse-list->string long-chlist))
(benchmark "make" 22000
(make-string 250 #\x))
(benchmark "tabulate" 17000
(string-tabulate integer->char 250))
(benchmark "join" 5500
(string-join (list short-string medium-string long-string) "|" 'suffix)))
(with-benchmark-prefix "list/string"
(benchmark "->list" 7300
(string->list short-string)
(string->list medium-string)
(string->list long-string))
(benchmark "split" 60000
(string-split short-string #\a)
(string-split medium-string #\a)
(string-split long-string #\a)))
(with-benchmark-prefix "selection"
(benchmark "ref" 660
(let loop ((k 0))
(if (< k (string-length short-string))
(begin
(string-ref short-string k)
(loop (+ k 1)))))
(let loop ((k 0))
(if (< k (string-length medium-string))
(begin
(string-ref medium-string k)
(loop (+ k 1)))))
(let loop ((k 0))
(if (< k (string-length long-string))
(begin
(string-ref long-string k)
(loop (+ k 1))))))
(benchmark "copy" 1100
(string-copy short-string)
(string-copy medium-string)
(string-copy long-string)
(substring/copy short-string 0 1)
(substring/copy medium-string 10 20)
(substring/copy long-string 100 200))
(benchmark "pad" 6800
(string-pad short-string 100)
(string-pad medium-string 100)
(string-pad long-string 100))
(benchmark "trim trim-right trim-both" 60000
(string-trim short-string char-alphabetic?)
(string-trim medium-string char-alphabetic?)
(string-trim long-string char-alphabetic?)
(string-trim-right short-string char-alphabetic?)
(string-trim-right medium-string char-alphabetic?)
(string-trim-right long-string char-alphabetic?)
(string-trim-both short-string char-alphabetic?)
(string-trim-both medium-string char-alphabetic?)
(string-trim-both long-string char-alphabetic?)))
(with-benchmark-prefix "modification"
(set! str1 (string-copy short-string))
(set! str2 (string-copy medium-string))
(set! str3 (string-copy long-string))
(benchmark "set!" 3000
(let loop ((k 1))
(if (< k (string-length short-string))
(begin
(string-set! str1 k #\x)
(loop (+ k 1)))))
(let loop ((k 20))
(if (< k (string-length medium-string))
(begin
(string-set! str2 k #\x)
(loop (+ k 1)))))
(let loop ((k 900))
(if (< k (string-length long-string))
(begin
(string-set! str3 k #\x)
(loop (+ k 1))))))
(set! str1 (string-copy short-string))
(set! str2 (string-copy medium-string))
(set! str3 (string-copy long-string))
(benchmark "sub-move!" 230000
(substring-move! short-string 0 2 str2 10)
(substring-move! medium-string 10 20 str3 20))
(set! str1 (string-copy short-string))
(set! str2 (string-copy medium-string))
(set! str3 (string-copy long-string))
(benchmark "fill!" 230000
(string-fill! str1 #\y 0 1)
(string-fill! str2 #\y 10 20)
(string-fill! str3 #\y 20 30))
(with-benchmark-prefix "comparison"
(benchmark "compare compare-ci" 140000
(string-compare short-string medium-string string<? string=? string>?)
(string-compare long-string medium-string string<? string=? string>?)
(string-compare-ci short-string medium-string string<? string=? string>?)
(string-compare-ci long-string medium-string string<? string=? string>?))
(benchmark "hash hash-ci" 1000
(string-hash short-string)
(string-hash medium-string)
(string-hash long-string)
(string-hash-ci short-string)
(string-hash-ci medium-string)
(string-hash-ci long-string))))
(with-benchmark-prefix "searching" 20000
(benchmark "prefix-length suffix-length" 270
(string-prefix-length short-string
(string-append short-string medium-string))
(string-prefix-length long-string
(string-append long-string medium-string))
(string-suffix-length short-string
(string-append medium-string short-string))
(string-suffix-length long-string
(string-append medium-string long-string))
(string-prefix-length-ci short-string
(string-append short-string medium-string))
(string-prefix-length-ci long-string
(string-append long-string medium-string))
(string-suffix-length-ci short-string
(string-append medium-string short-string))
(string-suffix-length-ci long-string
(string-append medium-string long-string)))
(benchmark "prefix? suffix?" 270
(string-prefix? short-string
(string-append short-string medium-string))
(string-prefix? long-string
(string-append long-string medium-string))
(string-suffix? short-string
(string-append medium-string short-string))
(string-suffix? long-string
(string-append medium-string long-string))
(string-prefix-ci? short-string
(string-append short-string medium-string))
(string-prefix-ci? long-string
(string-append long-string medium-string))
(string-suffix-ci? short-string
(string-append medium-string short-string))
(string-suffix-ci? long-string
(string-append medium-string long-string)))
(benchmark "index index-right rindex" 100000
(string-index short-string #\T)
(string-index medium-string #\T)
(string-index long-string #\T)
(string-index-right short-string #\T)
(string-index-right medium-string #\T)
(string-index-right long-string #\T)
(string-rindex short-string #\T)
(string-rindex medium-string #\T)
(string-rindex long-string #\T))
(benchmark "skip skip-right?" 100000
(string-skip short-string char-alphabetic?)
(string-skip medium-string char-alphabetic?)
(string-skip long-string char-alphabetic?)
(string-skip-right short-string char-alphabetic?)
(string-skip-right medium-string char-alphabetic?)
(string-skip-right long-string char-alphabetic?))
(benchmark "count" 10000
(string-count short-string char-alphabetic?)
(string-count medium-string char-alphabetic?)
(string-count long-string char-alphabetic?))
(benchmark "contains contains-ci" 34000
(string-contains short-string short-string)
(string-contains medium-string (substring medium-string 10 15))
(string-contains long-string (substring long-string 100 130))
(string-contains-ci short-string short-string)
(string-contains-ci medium-string (substring medium-string 10 15))
(string-contains-ci long-string (substring long-string 100 130)))
(set! str1 (string-copy short-string))
(set! str2 (string-copy medium-string))
(set! str3 (string-copy long-string))
(benchmark "upcase downcase upcase! downcase!" 600
(string-upcase short-string)
(string-upcase medium-string)
(string-upcase long-string)
(string-downcase short-string)
(string-downcase medium-string)
(string-downcase long-string)
(string-upcase! str1 0 1)
(string-upcase! str2 10 20)
(string-upcase! str3 100 130)
(string-downcase! str1 0 1)
(string-downcase! str2 10 20)
(string-downcase! str3 100 130)))
(with-benchmark-prefix "readers"
(benchmark "read token, method 1" 1200
(let ((buf (make-string 512)))
(let loop ((i 0))
(if (< i 512)
(begin
(string-set! buf i #\x)
(loop (+ i 1)))
buf))))
(benchmark "read token, method 2" 1200
(let ((lst '()))
(let loop ((i 0))
(set! lst (append! lst (list #\x)))
(if (< i 512)
(loop (+ i 1))
(list->string lst)))))))

View file

@ -41,7 +41,7 @@ if [ ! -f guile-procedures.txt ] ; then
fi fi
exec $guile \ exec $guile \
-e main -s "$TEST_SUITE_DIR/guile-test" \ --no-autocompile -e main -s "$TEST_SUITE_DIR/guile-test" \
--test-suite "$TEST_SUITE_DIR/tests" \ --test-suite "$TEST_SUITE_DIR/tests" \
--log-file check-guile.log "$@" --log-file check-guile.log "$@"

View file

@ -51,14 +51,6 @@ AC_CONFIG_SRCDIR([GUILE-VERSION])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AH_TOP(/*GUILE_CONFIGURE_COPYRIGHT*/) AH_TOP(/*GUILE_CONFIGURE_COPYRIGHT*/)
#--------------------------------------------------------------------
#
# Independent Subdirectories
#
#--------------------------------------------------------------------
AC_CONFIG_SUBDIRS(guile-readline)
#-------------------------------------------------------------------- #--------------------------------------------------------------------
AC_LANG([C]) AC_LANG([C])
@ -1456,6 +1448,9 @@ LIBLOBJS="`echo ${LIB@&t@OBJS} | sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'`"
EXTRA_DOT_DOC_FILES="`echo ${LIB@&t@OBJS} | sed 's,\.[[^.]]* ,.doc ,g;s,\.[[^.]]*$,.doc,'`" EXTRA_DOT_DOC_FILES="`echo ${LIB@&t@OBJS} | sed 's,\.[[^.]]* ,.doc ,g;s,\.[[^.]]*$,.doc,'`"
EXTRA_DOT_X_FILES="`echo ${LIB@&t@OBJS} | sed 's,\.[[^.]]* ,.x ,g;s,\.[[^.]]*$,.x,'`" EXTRA_DOT_X_FILES="`echo ${LIB@&t@OBJS} | sed 's,\.[[^.]]* ,.x ,g;s,\.[[^.]]*$,.x,'`"
# GNU Readline bindings.
GUILE_READLINE
AC_SUBST(GUILE_MAJOR_VERSION) AC_SUBST(GUILE_MAJOR_VERSION)
AC_SUBST(GUILE_MINOR_VERSION) AC_SUBST(GUILE_MINOR_VERSION)
AC_SUBST(GUILE_MICRO_VERSION) AC_SUBST(GUILE_MICRO_VERSION)
@ -1542,7 +1537,6 @@ AC_CONFIG_FILES([
lib/Makefile lib/Makefile
benchmark-suite/Makefile benchmark-suite/Makefile
doc/Makefile doc/Makefile
doc/goops/Makefile
doc/r5rs/Makefile doc/r5rs/Makefile
doc/ref/Makefile doc/ref/Makefile
doc/tutorial/Makefile doc/tutorial/Makefile
@ -1551,6 +1545,7 @@ AC_CONFIG_FILES([
lang/Makefile lang/Makefile
libguile/Makefile libguile/Makefile
srfi/Makefile srfi/Makefile
guile-readline/Makefile
test-suite/Makefile test-suite/Makefile
test-suite/standalone/Makefile test-suite/standalone/Makefile
meta/Makefile meta/Makefile
@ -1578,6 +1573,7 @@ AC_CONFIG_FILES([test-suite/standalone/test-use-srfi],
[chmod +x test-suite/standalone/test-use-srfi]) [chmod +x test-suite/standalone/test-use-srfi])
AC_CONFIG_FILES([test-suite/standalone/test-fast-slot-ref], AC_CONFIG_FILES([test-suite/standalone/test-fast-slot-ref],
[chmod +x test-suite/standalone/test-fast-slot-ref]) [chmod +x test-suite/standalone/test-fast-slot-ref])
AC_CONFIG_FILES([doc/ref/effective-version.texi])
AC_OUTPUT AC_OUTPUT

View file

@ -21,7 +21,7 @@
AUTOMAKE_OPTIONS = gnu AUTOMAKE_OPTIONS = gnu
SUBDIRS = ref tutorial goops r5rs SUBDIRS = ref tutorial r5rs
dist_man1_MANS = guile.1 dist_man1_MANS = guile.1

View file

@ -8,10 +8,6 @@ The documentation consists of the following manuals.
- The Guile Reference Manual (guile.texi) contains (or is intended to - The Guile Reference Manual (guile.texi) contains (or is intended to
contain) reference documentation on all aspects of Guile. contain) reference documentation on all aspects of Guile.
- The GOOPS Manual (goops.texi) contains both tutorial-style and
reference documentation for using GOOPS, Guile's Object Oriented
Programming System.
- The Revised^5 Report on the Algorithmic Language Scheme (r5rs.texi). - The Revised^5 Report on the Algorithmic Language Scheme (r5rs.texi).
Please be aware that this is all very much work in progress (apart Please be aware that this is all very much work in progress (apart

View file

@ -1,29 +0,0 @@
## Process this file with Automake to create Makefile.in
##
## Copyright (C) 1998, 2004, 2006, 2008 Free Software Foundation, Inc.
##
## This file is part of GUILE.
##
## GUILE is free software; you can redistribute it and/or modify it
## under the terms of the GNU Lesser General Public License as
## published by the Free Software Foundation; either version 3, or
## (at your option) any later version.
##
## GUILE is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU Lesser General Public License for more details.
##
## You should have received a copy of the GNU Lesser General Public
## License along with GUILE; see the file COPYING.LESSER. If not,
## write to the Free Software Foundation, Inc., 51 Franklin Street,
## Fifth Floor, Boston, MA 02110-1301 USA
AUTOMAKE_OPTIONS = gnu
info_TEXINFOS = goops.texi
goops_TEXINFOS = goops-tutorial.texi \
hierarchy.eps hierarchy.png hierarchy.txt hierarchy.pdf
EXTRA_DIST = ChangeLog-2008

1
doc/ref/.gitignore vendored
View file

@ -1,2 +1,3 @@
autoconf-macros.texi autoconf-macros.texi
lib-version.texi lib-version.texi
effective-version.texi

View file

@ -78,11 +78,20 @@ guile_TEXINFOS = preface.texi \
libguile-linking.texi \ libguile-linking.texi \
libguile-extensions.texi \ libguile-extensions.texi \
api-init.texi \ api-init.texi \
mod-getopt-long.texi mod-getopt-long.texi \
goops.texi \
goops-tutorial.texi \
effective-version.texi
ETAGS_ARGS = $(info_TEXINFOS) $(guile_TEXINFOS) ETAGS_ARGS = $(info_TEXINFOS) $(guile_TEXINFOS)
EXTRA_DIST = ChangeLog-2008 PICTURES = hierarchy.eps \
hierarchy.pdf \
hierarchy.png \
hierarchy.txt \
mop.text
EXTRA_DIST = ChangeLog-2008 $(PICTURES)
include $(top_srcdir)/am/pre-inst-guile include $(top_srcdir)/am/pre-inst-guile

View file

@ -1344,9 +1344,9 @@ otherwise.
@deftypefn {C Function} SCM scm_take_u8vector (const scm_t_uint8 *data, size_t len) @deftypefn {C Function} SCM scm_take_u8vector (const scm_t_uint8 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_s8vector (const scm_t_int8 *data, size_t len) @deftypefnx {C Function} SCM scm_take_s8vector (const scm_t_int8 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_u16vector (const scm_t_uint16 *data, size_t len) @deftypefnx {C Function} SCM scm_take_u16vector (const scm_t_uint16 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_s168vector (const scm_t_int16 *data, size_t len) @deftypefnx {C Function} SCM scm_take_s16vector (const scm_t_int16 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_u32vector (const scm_t_uint32 *data, size_t len) @deftypefnx {C Function} SCM scm_take_u32vector (const scm_t_uint32 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_s328vector (const scm_t_int32 *data, size_t len) @deftypefnx {C Function} SCM scm_take_s32vector (const scm_t_int32 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_u64vector (const scm_t_uint64 *data, size_t len) @deftypefnx {C Function} SCM scm_take_u64vector (const scm_t_uint64 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_s64vector (const scm_t_int64 *data, size_t len) @deftypefnx {C Function} SCM scm_take_s64vector (const scm_t_int64 *data, size_t len)
@deftypefnx {C Function} SCM scm_take_f32vector (const float *data, size_t len) @deftypefnx {C Function} SCM scm_take_f32vector (const float *data, size_t len)
@ -2001,13 +2001,24 @@ enclosed array is unspecified.
For example, For example,
@lisp @lisp
(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1) (enclose-array '#3(((a b c)
(d e f))
((1 2 3)
(4 5 6)))
1)
@result{} @result{}
#<enclosed-array (#1(a d) #1(b e) #1(c f)) (#1(1 4) #1(2 5) #1(3 6))> #<enclosed-array (#1(a d) #1(b e) #1(c f))
(#1(1 4) #1(2 5) #1(3 6))>
(enclose-array '#3(((a b c) (d e f)) ((1 2 3) (4 5 6))) 1 0) (enclose-array '#3(((a b c)
(d e f))
((1 2 3)
(4 5 6)))
1 0)
@result{} @result{}
#<enclosed-array #2((a 1) (d 4)) #2((b 2) (e 5)) #2((c 3) (f 6))> #<enclosed-array #2((a 1) (d 4))
#2((b 2) (e 5))
#2((c 3) (f 6))>
@end lisp @end lisp
@end deffn @end deffn
@ -3083,8 +3094,10 @@ which can be changed.
(color ball) (color ball)
(owner ball))) (owner ball)))
ball-color)) ball-color))
(define (color ball) (struct-ref (struct-vtable ball) vtable-offset-user)) (define (color ball)
(define (owner ball) (struct-ref ball 0)) (struct-ref (struct-vtable ball) vtable-offset-user))
(define (owner ball)
(struct-ref ball 0))
(define red (make-ball-type 'red)) (define red (make-ball-type 'red))
(define green (make-ball-type 'green)) (define green (make-ball-type 'green))
@ -3460,7 +3473,8 @@ whole is not a proper list:
(assoc "mary" '((1 . 2) ("key" . "door") . "open sesame")) (assoc "mary" '((1 . 2) ("key" . "door") . "open sesame"))
@result{} @result{}
ERROR: In procedure assoc in expression (assoc "mary" (quote #)): ERROR: In procedure assoc in expression (assoc "mary" (quote #)):
ERROR: Wrong type argument in position 2 (expecting association list): ((1 . 2) ("key" . "door") . "open sesame") ERROR: Wrong type argument in position 2 (expecting
association list): ((1 . 2) ("key" . "door") . "open sesame")
(sloppy-assoc "mary" '((1 . 2) ("key" . "door") . "open sesame")) (sloppy-assoc "mary" '((1 . 2) ("key" . "door") . "open sesame"))
@result{} @result{}
@ -3474,7 +3488,8 @@ Secondly, if one of the entries in the specified alist is not a pair:
(assoc 2 '((1 . 1) 2 (3 . 9))) (assoc 2 '((1 . 1) 2 (3 . 9)))
@result{} @result{}
ERROR: In procedure assoc in expression (assoc 2 (quote #)): ERROR: In procedure assoc in expression (assoc 2 (quote #)):
ERROR: Wrong type argument in position 2 (expecting association list): ((1 . 1) 2 (3 . 9)) ERROR: Wrong type argument in position 2 (expecting
association list): ((1 . 1) 2 (3 . 9))
(sloppy-assoc 2 '((1 . 1) 2 (3 . 9))) (sloppy-assoc 2 '((1 . 1) 2 (3 . 9)))
@result{} @result{}

View file

@ -22,6 +22,7 @@ flow of Scheme affects C code.
* Error Reporting:: Procedures for signaling errors. * Error Reporting:: Procedures for signaling errors.
* Dynamic Wind:: Dealing with non-local entrance/exit. * Dynamic Wind:: Dealing with non-local entrance/exit.
* Handling Errors:: How to handle errors in C code. * Handling Errors:: How to handle errors in C code.
* Continuation Barriers:: Protection from non-local control flow.
@end menu @end menu
@node begin @node begin
@ -1501,6 +1502,33 @@ which is the name of the procedure incorrectly invoked.
@end deftypefn @end deftypefn
@node Continuation Barriers
@subsection Continuation Barriers
The non-local flow of control caused by continuations might sometimes
not be wanted. You can use @code{with-continuation-barrier} etc to
errect fences that continuations can not pass.
@deffn {Scheme Procedure} with-continuation-barrier proc
@deffnx {C Function} scm_with_continuation_barrier (proc)
Call @var{proc} and return its result. Do not allow the invocation of
continuations that would leave or enter the dynamic extent of the call
to @code{with-continuation-barrier}. Such an attempt causes an error
to be signaled.
Throws (such as errors) that are not caught from within @var{proc} are
caught by @code{with-continuation-barrier}. In that case, a short
message is printed to the current error port and @code{#f} is returned.
Thus, @code{with-continuation-barrier} returns exactly once.
@end deffn
@deftypefn {C Function} {void *} scm_c_with_continuation_barrier (void *(*func) (void *), void *data)
Like @code{scm_with_continuation_barrier} but call @var{func} on
@var{data}. When an error is caught, @code{NULL} is returned.
@end deftypefn
@c Local Variables: @c Local Variables:
@c TeX-master: "guile.texi" @c TeX-master: "guile.texi"
@c End: @c End:

View file

@ -3477,9 +3477,9 @@ allocated string.
@deffnx {C Function} scm_string_concatenate_reverse (ls, final_string, end) @deffnx {C Function} scm_string_concatenate_reverse (ls, final_string, end)
Without optional arguments, this procedure is equivalent to Without optional arguments, this procedure is equivalent to
@smalllisp @lisp
(string-concatenate (reverse ls)) (string-concatenate (reverse ls))
@end smalllisp @end lisp
If the optional argument @var{final_string} is specified, it is If the optional argument @var{final_string} is specified, it is
consed onto the beginning to @var{ls} before performing the consed onto the beginning to @var{ls} before performing the
@ -3535,11 +3535,12 @@ For example, to change characters to alternately upper and lower case,
@example @example
(define str (string-copy "studly")) (define str (string-copy "studly"))
(string-for-each-index (lambda (i) (string-for-each-index
(string-set! str i (lambda (i)
((if (even? i) char-upcase char-downcase) (string-set! str i
(string-ref str i)))) ((if (even? i) char-upcase char-downcase)
str) (string-ref str i))))
str)
str @result{} "StUdLy" str @result{} "StUdLy"
@end example @end example
@end deffn @end deffn
@ -4447,7 +4448,8 @@ Or matching a @sc{yyyymmdd} format date such as @samp{20020828} and
re-ordering and hyphenating the fields. re-ordering and hyphenating the fields.
@lisp @lisp
(define date-regex "([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])") (define date-regex
"([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])")
(define s "Date 20020429 12am.") (define s "Date 20020429 12am.")
(regexp-substitute #f (string-match date-regex s) (regexp-substitute #f (string-match date-regex s)
'pre 2 "-" 3 "-" 1 'post " (" 0 ")") 'pre 2 "-" 3 "-" 1 'post " (" 0 ")")
@ -4507,7 +4509,8 @@ example the following is the date example from
@code{string-match} call. @code{string-match} call.
@lisp @lisp
(define date-regex "([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])") (define date-regex
"([0-9][0-9][0-9][0-9])([0-9][0-9])([0-9][0-9])")
(define s "Date 20020429 12am.") (define s "Date 20020429 12am.")
(regexp-substitute/global #f date-regex s (regexp-substitute/global #f date-regex s
'pre 2 "-" 3 "-" 1 'post " (" 0 ")") 'pre 2 "-" 3 "-" 1 'post " (" 0 ")")
@ -5502,7 +5505,7 @@ the @code{read-set!} procedure documented in @ref{User level options
interfaces} and @ref{Reader options}. Note that the @code{prefix} and interfaces} and @ref{Reader options}. Note that the @code{prefix} and
@code{postfix} syntax are mutually exclusive. @code{postfix} syntax are mutually exclusive.
@smalllisp @lisp
(read-set! keywords 'prefix) (read-set! keywords 'prefix)
#:type #:type
@ -5534,7 +5537,7 @@ type:
ERROR: In expression :type: ERROR: In expression :type:
ERROR: Unbound variable: :type ERROR: Unbound variable: :type
ABORT: (unbound-variable) ABORT: (unbound-variable)
@end smalllisp @end lisp
@node Keyword Procedures @node Keyword Procedures
@subsubsection Keyword Procedures @subsubsection Keyword Procedures

View file

@ -283,9 +283,9 @@ runs a script non-interactively.
The following procedures can be used to access and set the source The following procedures can be used to access and set the source
properties of read expressions. properties of read expressions.
@deffn {Scheme Procedure} set-source-properties! obj plist @deffn {Scheme Procedure} set-source-properties! obj alist
@deffnx {C Function} scm_set_source_properties_x (obj, plist) @deffnx {C Function} scm_set_source_properties_x (obj, alist)
Install the association list @var{plist} as the source property Install the association list @var{alist} as the source property
list for @var{obj}. list for @var{obj}.
@end deffn @end deffn
@ -302,12 +302,12 @@ Return the source property association list of @var{obj}.
@deffn {Scheme Procedure} source-property obj key @deffn {Scheme Procedure} source-property obj key
@deffnx {C Function} scm_source_property (obj, key) @deffnx {C Function} scm_source_property (obj, key)
Return the source property specified by @var{key} from Return the property specified by @var{key} from @var{obj}'s source
@var{obj}'s source property list. properties.
@end deffn @end deffn
In practice there are only two ways that you should use the ability to In practice there are only two ways that you should use the ability to
set an expression's source breakpoints. set an expression's source properties.
@itemize @itemize
@item @item
@ -330,9 +330,9 @@ involved in a backtrace or error report.
If you are looking for a way to attach arbitrary information to an If you are looking for a way to attach arbitrary information to an
expression other than these properties, you should use expression other than these properties, you should use
@code{make-object-property} instead (@pxref{Object Properties}), because @code{make-object-property} instead (@pxref{Object Properties}). That
that will avoid bloating the source property hash table, which is really will avoid bloating the source property hash table, which is really
only intended for the specific purposes described in this section. only intended for the debugging purposes just described.
@node Decoding Memoized Source Expressions @node Decoding Memoized Source Expressions
@ -1708,7 +1708,7 @@ facilities just described.
A good way to explore in detail what a Scheme procedure does is to set A good way to explore in detail what a Scheme procedure does is to set
a trap on it and then single step through what it does. To do this, a trap on it and then single step through what it does. To do this,
make and install a @code{<procedure-trap>} with the @code{debug-trap} make and install a @code{<procedure-trap>} with the @code{debug-trap}
behaviour from @code{(ice-9 debugging ice-9-debugger-extensions)}. behaviour from @code{(ice-9 debugger)}.
The following sample session illustrates this. It assumes that the The following sample session illustrates this. It assumes that the
file @file{matrix.scm} defines a procedure @code{mkmatrix}, which is file @file{matrix.scm} defines a procedure @code{mkmatrix}, which is
@ -1718,7 +1718,6 @@ calls @code{mkmatrix}.
@lisp @lisp
$ /usr/bin/guile -q $ /usr/bin/guile -q
guile> (use-modules (ice-9 debugger) guile> (use-modules (ice-9 debugger)
(ice-9 debugging ice-9-debugger-extensions)
(ice-9 debugging traps)) (ice-9 debugging traps))
guile> (load "matrix.scm") guile> (load "matrix.scm")
guile> (install-trap (make <procedure-trap> guile> (install-trap (make <procedure-trap>
@ -1732,16 +1731,16 @@ Frame 2 at matrix.scm:8:3
[mkmatrix] [mkmatrix]
debug> next debug> next
Frame 3 at matrix.scm:4:3 Frame 3 at matrix.scm:4:3
(let ((x 1)) (quote this-is-a-matric)) (let ((x 1)) (quote hi!))
debug> info frame debug> info frame
Stack frame: 3 Stack frame: 3
This frame is an evaluation. This frame is an evaluation.
The expression being evaluated is: The expression being evaluated is:
matrix.scm:4:3: matrix.scm:4:3:
(let ((x 1)) (quote this-is-a-matric)) (let ((x 1)) (quote hi!))
debug> next debug> next
Frame 3 at matrix.scm:5:21 Frame 3 at matrix.scm:5:21
(quote this-is-a-matric) (quote hi!)
debug> bt debug> bt
In unknown file: In unknown file:
?: 0* [primitive-eval (do-main 4)] ?: 0* [primitive-eval (do-main 4)]
@ -1750,18 +1749,17 @@ In standard input:
In matrix.scm: In matrix.scm:
8: 2 [mkmatrix] 8: 2 [mkmatrix]
... ...
5: 3 (quote this-is-a-matric) 5: 3 (quote hi!)
debug> quit debug> quit
this-is-a-matric hi!
guile> guile>
@end lisp @end lisp
Or you can use Guile's Emacs interface (GDS), by using the module Or you can use Guile's Emacs interface (GDS), by using the module
@code{(ice-9 gds-client)} instead of @code{(ice-9 debugger)} and @code{(ice-9 gds-client)} instead of @code{(ice-9 debugger)} and
@code{(ice-9 debugging ice-9-debugger-extensions)}, and changing changing @code{debug-trap} to @code{gds-debug-trap}. Then the stack and
@code{debug-trap} to @code{gds-debug-trap}. Then the stack and corresponding source locations are displayed in Emacs instead of on the
corresponding source locations are displayed in Emacs instead of on Guile command line.
the Guile command line.
@node Profiling or Tracing a Procedure's Code @node Profiling or Tracing a Procedure's Code
@ -1813,7 +1811,7 @@ guile> (do-main 4)
| 5: (memq sym bindings) | 5: (memq sym bindings)
| 5: [memq let (debug)] | 5: [memq let (debug)]
| 5: =>#f | 5: =>#f
| 2: (letrec ((yy 23)) (let ((x 1)) (quote this-is-a-matric))) | 2: (letrec ((yy 23)) (let ((x 1)) (quote hi!)))
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...)) | 4: (and (memq sym bindings) (let ...))
@ -1832,7 +1830,7 @@ guile> (do-main 4)
| 5: (memq sym bindings) | 5: (memq sym bindings)
| 5: [memq let (debug)] | 5: [memq let (debug)]
| 5: =>#f | 5: =>#f
| 2: (let ((x 1)) (quote this-is-a-matric)) | 2: (let ((x 1)) (quote hi!))
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f] | 3: [#<procedure #f (a sym definep)> #<autoload # b7c93870> let #f]
| 4: (and (memq sym bindings) (let ...)) | 4: (and (memq sym bindings) (let ...))
@ -1841,15 +1839,15 @@ guile> (do-main 4)
| 5: =>#f | 5: =>#f
| 2: [let (let # #) (# # #)] | 2: [let (let # #) (# # #)]
| 2: [let (let # #) (# # #)] | 2: [let (let # #) (# # #)]
| 2: =>(#@@let* (x 1) #@@let (quote this-is-a-matric)) | 2: =>(#@@let* (x 1) #@@let (quote hi!))
this-is-a-matric hi!
guile> (do-main 4) guile> (do-main 4)
| 2: [mkmatrix] | 2: [mkmatrix]
| 2: (letrec ((yy 23)) (let* ((x 1)) (quote this-is-a-matric))) | 2: (letrec ((yy 23)) (let* ((x 1)) (quote hi!)))
| 2: (let* ((x 1)) (quote this-is-a-matric)) | 2: (let* ((x 1)) (quote hi!))
| 2: (quote this-is-a-matric) | 2: (quote hi!)
| 2: =>this-is-a-matric | 2: =>hi!
this-is-a-matric hi!
guile> guile>
@end lisp @end lisp
@ -1881,11 +1879,11 @@ each trace line instead of the stack depth.
guile> (set-trace-layout "|~16@@a: ~a\n" trace/source trace/info) guile> (set-trace-layout "|~16@@a: ~a\n" trace/source trace/info)
guile> (do-main 4) guile> (do-main 4)
| matrix.scm:7:2: [mkmatrix] | matrix.scm:7:2: [mkmatrix]
| : (letrec ((yy 23)) (let* ((x 1)) (quote this-is-a-matric))) | : (letrec ((yy 23)) (let* ((x 1)) (quote hi!)))
| matrix.scm:3:2: (let* ((x 1)) (quote this-is-a-matric)) | matrix.scm:3:2: (let* ((x 1)) (quote hi!))
| matrix.scm:4:4: (quote this-is-a-matric) | matrix.scm:4:4: (quote hi!)
| matrix.scm:4:4: =>this-is-a-matric | matrix.scm:4:4: =>hi!
this-is-a-matric hi!
guile> guile>
@end lisp @end lisp

View file

@ -424,9 +424,9 @@ the current size, but this is not mandatory in the POSIX standard.
The delimited-I/O module can be accessed with: The delimited-I/O module can be accessed with:
@smalllisp @lisp
(use-modules (ice-9 rdelim)) (use-modules (ice-9 rdelim))
@end smalllisp @end lisp
It can be used to read or write lines of text, or read text delimited by It can be used to read or write lines of text, or read text delimited by
a specified set of characters. It's similar to the @code{(scsh rdelim)} a specified set of characters. It's similar to the @code{(scsh rdelim)}
@ -536,9 +536,9 @@ delimiter may be either a newline or the @var{eof-object}; if
The Block-string-I/O module can be accessed with: The Block-string-I/O module can be accessed with:
@smalllisp @lisp
(use-modules (ice-9 rw)) (use-modules (ice-9 rw))
@end smalllisp @end lisp
It currently contains procedures that help to implement the It currently contains procedures that help to implement the
@code{(scsh rw)} module in guile-scsh. @code{(scsh rw)} module in guile-scsh.
@ -795,17 +795,17 @@ current interfaces.
@rnindex open-input-file @rnindex open-input-file
@deffn {Scheme Procedure} open-input-file filename @deffn {Scheme Procedure} open-input-file filename
Open @var{filename} for input. Equivalent to Open @var{filename} for input. Equivalent to
@smalllisp @lisp
(open-file @var{filename} "r") (open-file @var{filename} "r")
@end smalllisp @end lisp
@end deffn @end deffn
@rnindex open-output-file @rnindex open-output-file
@deffn {Scheme Procedure} open-output-file filename @deffn {Scheme Procedure} open-output-file filename
Open @var{filename} for output. Equivalent to Open @var{filename} for output. Equivalent to
@smalllisp @lisp
(open-file @var{filename} "w") (open-file @var{filename} "w")
@end smalllisp @end lisp
@end deffn @end deffn
@deffn {Scheme Procedure} call-with-input-file filename proc @deffn {Scheme Procedure} call-with-input-file filename proc

View file

@ -60,15 +60,15 @@ Library files in SLIB @emph{provide} a feature, and when user programs
For example, the file @file{random.scm} in the SLIB package contains the For example, the file @file{random.scm} in the SLIB package contains the
line line
@smalllisp @lisp
(provide 'random) (provide 'random)
@end smalllisp @end lisp
so to use its procedures, a user would type so to use its procedures, a user would type
@smalllisp @lisp
(require 'random) (require 'random)
@end smalllisp @end lisp
and they would magically become available, @emph{but still have the same and they would magically become available, @emph{but still have the same
names!} So this method is nice, but not as good as a full-featured names!} So this method is nice, but not as good as a full-featured
@ -99,9 +99,9 @@ i.e., passed as the second argument to @code{eval}.
Note: the following two procedures are available only when the Note: the following two procedures are available only when the
@code{(ice-9 r5rs)} module is loaded: @code{(ice-9 r5rs)} module is loaded:
@smalllisp @lisp
(use-modules (ice-9 r5rs)) (use-modules (ice-9 r5rs))
@end smalllisp @end lisp
@deffn {Scheme Procedure} scheme-report-environment version @deffn {Scheme Procedure} scheme-report-environment version
@deffnx {Scheme Procedure} null-environment version @deffnx {Scheme Procedure} null-environment version
@ -224,9 +224,9 @@ An @dfn{interface specification} has one of two forms. The first
variation is simply to name the module, in which case its public variation is simply to name the module, in which case its public
interface is the one accessed. For example: interface is the one accessed. For example:
@smalllisp @lisp
(use-modules (ice-9 popen)) (use-modules (ice-9 popen))
@end smalllisp @end lisp
Here, the interface specification is @code{(ice-9 popen)}, and the Here, the interface specification is @code{(ice-9 popen)}, and the
result is that the current module now has access to @code{open-pipe}, result is that the current module now has access to @code{open-pipe},
@ -241,11 +241,11 @@ module to be accessed, but also selects bindings from it and renames
them to suit the current module's needs. For example: them to suit the current module's needs. For example:
@cindex binding renamer @cindex binding renamer
@smalllisp @lisp
(use-modules ((ice-9 popen) (use-modules ((ice-9 popen)
:select ((open-pipe . pipe-open) close-pipe) #:select ((open-pipe . pipe-open) close-pipe)
:renamer (symbol-prefix-proc 'unixy:))) #:renamer (symbol-prefix-proc 'unixy:)))
@end smalllisp @end lisp
Here, the interface specification is more complex than before, and the Here, the interface specification is more complex than before, and the
result is that a custom interface with only two bindings is created and result is that a custom interface with only two bindings is created and
@ -270,10 +270,10 @@ You can also directly refer to bindings in a module by using the
open-pipe)}. Thus an alternative to the complete @code{use-modules} open-pipe)}. Thus an alternative to the complete @code{use-modules}
statement would be statement would be
@smalllisp @lisp
(define unixy:pipe-open (@@ (ice-9 popen) open-pipe)) (define unixy:pipe-open (@@ (ice-9 popen) open-pipe))
(define unixy:close-pipe (@@ (ice-9 popen) close-pipe)) (define unixy:close-pipe (@@ (ice-9 popen) close-pipe))
@end smalllisp @end lisp
There is also @code{@@@@}, which can be used like @code{@@}, but does There is also @code{@@@@}, which can be used like @code{@@}, but does
not check whether the variable that is being accessed is actually not check whether the variable that is being accessed is actually
@ -307,9 +307,9 @@ whose public interface is found and used.
@var{spec} can also be of the form: @var{spec} can also be of the form:
@cindex binding renamer @cindex binding renamer
@smalllisp @lisp
(MODULE-NAME [:select SELECTION] [:renamer RENAMER]) (MODULE-NAME [:select SELECTION] [:renamer RENAMER])
@end smalllisp @end lisp
in which case a custom interface is newly created and used. in which case a custom interface is newly created and used.
@var{module-name} is a list of symbols, as above; @var{selection} is a @var{module-name} is a list of symbols, as above; @var{selection} is a
@ -373,9 +373,9 @@ by using @code{define-public} or @code{export} (both documented below).
@var{module-name} is of the form @code{(hierarchy file)}. One @var{module-name} is of the form @code{(hierarchy file)}. One
example of this is example of this is
@smalllisp @lisp
(define-module (ice-9 popen)) (define-module (ice-9 popen))
@end smalllisp @end lisp
@code{define-module} makes this module available to Guile programs under @code{define-module} makes this module available to Guile programs under
the given @var{module-name}. the given @var{module-name}.
@ -541,9 +541,9 @@ duplication to the next handler in @var{list}.
The default duplicate binding resolution policy is given by the The default duplicate binding resolution policy is given by the
@code{default-duplicate-binding-handler} procedure, and is @code{default-duplicate-binding-handler} procedure, and is
@smalllisp @lisp
(replace warn-override-core warn last) (replace warn-override-core warn last)
@end smalllisp @end lisp
@item #:no-backtrace @item #:no-backtrace
@cindex no backtrace @cindex no backtrace
@ -758,7 +758,7 @@ Record definition with @code{define-record-type} (@pxref{SRFI-9}).
Read hash extension @code{#,()} (@pxref{SRFI-10}). Read hash extension @code{#,()} (@pxref{SRFI-10}).
@item (srfi srfi-11) @item (srfi srfi-11)
Multiple-value handling with @code{let-values} and @code{let-values*} Multiple-value handling with @code{let-values} and @code{let*-values}
(@pxref{SRFI-11}). (@pxref{SRFI-11}).
@item (srfi srfi-13) @item (srfi srfi-13)
@ -1138,12 +1138,12 @@ gcc -shared -o libbessel.so -fPIC bessel.c
Now fire up Guile: Now fire up Guile:
@smalllisp @lisp
(define bessel-lib (dynamic-link "./libbessel.so")) (define bessel-lib (dynamic-link "./libbessel.so"))
(dynamic-call "init_math_bessel" bessel-lib) (dynamic-call "init_math_bessel" bessel-lib)
(j0 2) (j0 2)
@result{} 0.223890779141236 @result{} 0.223890779141236
@end smalllisp @end lisp
The filename @file{./libbessel.so} should be pointing to the shared The filename @file{./libbessel.so} should be pointing to the shared
library produced with the @code{gcc} command above, of course. The library produced with the @code{gcc} command above, of course. The

View file

@ -82,10 +82,11 @@ general are stored. On Unix-like systems, this is usually
@deffnx {C Function} scm_sys_library_dir () @deffnx {C Function} scm_sys_library_dir ()
Return the name of the directory where the Guile Scheme files that Return the name of the directory where the Guile Scheme files that
belong to the core Guile installation (as opposed to files from a 3rd belong to the core Guile installation (as opposed to files from a 3rd
party package) are installed. On Unix-like systems, this is usually party package) are installed. On Unix-like systems this is usually
@file{/usr/local/share/guile/<GUILE_EFFECTIVE_VERSION>} or @file{/usr/local/share/guile/<GUILE_EFFECTIVE_VERSION>} or
@file{/usr/share/guile/<GUILE_EFFECTIVE_VERSION>}, for example: @file{/usr/share/guile/<GUILE_EFFECTIVE_VERSION>};
@file{/usr/local/share/guile/1.6}.
@noindent for example @file{/usr/local/share/guile/1.6}.
@end deffn @end deffn
@deffn {Scheme Procedure} %site-dir @deffn {Scheme Procedure} %site-dir
@ -503,9 +504,9 @@ Guile is case-sensitive by default.
To make Guile case insensitive, you can type To make Guile case insensitive, you can type
@smalllisp @lisp
(read-enable 'case-insensitive) (read-enable 'case-insensitive)
@end smalllisp @end lisp
@node Printing options @node Printing options
@subsubsection Printing options @subsubsection Printing options
@ -680,7 +681,8 @@ the maximum stack size, use @code{debug-set!}, for example:
@lisp @lisp
(debug-set! stack 200000) (debug-set! stack 200000)
@result{} @result{}
(show-file-name #t stack 200000 debug backtrace depth 20 maxdepth 1000 frames 3 indent 10 width 79 procnames cheap) (show-file-name #t stack 200000 debug backtrace depth 20
maxdepth 1000 frames 3 indent 10 width 79 procnames cheap)
(non-tail-recursive-factorial 500) (non-tail-recursive-factorial 500)
@result{} @result{}
@ -717,7 +719,6 @@ backtrace. Need to give a better example, possibly putting debugging
option examples in a separate session.] option examples in a separate session.]
@end enumerate @end enumerate
@smalllisp @smalllisp
guile> (define abc "hello") guile> (define abc "hello")
guile> abc guile> abc

View file

@ -8,14 +8,9 @@
@node Scheduling @node Scheduling
@section Threads, Mutexes, Asyncs and Dynamic Roots @section Threads, Mutexes, Asyncs and Dynamic Roots
[FIXME: This is pasted in from Tom Lord's original guile.texi chapter
plus the Cygnus programmer's manual; it should be *very* carefully
reviewed and largely reorganized.]
@menu @menu
* Arbiters:: Synchronization primitives. * Arbiters:: Synchronization primitives.
* Asyncs:: Asynchronous procedure invocation. * Asyncs:: Asynchronous procedure invocation.
* Continuation Barriers:: Protection from non-local control flow.
* Threads:: Multiple threads of execution. * Threads:: Multiple threads of execution.
* Mutexes and Condition Variables:: Synchronization primitives. * Mutexes and Condition Variables:: Synchronization primitives.
* Blocking:: How to block properly in guile mode. * Blocking:: How to block properly in guile mode.
@ -47,7 +42,6 @@ process synchronization.
@deffn {Scheme Procedure} try-arbiter arb @deffn {Scheme Procedure} try-arbiter arb
@deffnx {C Function} scm_try_arbiter (arb) @deffnx {C Function} scm_try_arbiter (arb)
@deffnx {C Function} scm_try_arbiter (arb)
If @var{arb} is unlocked, then lock it and return @code{#t}. If @var{arb} is unlocked, then lock it and return @code{#t}.
If @var{arb} is already locked, then do nothing and return If @var{arb} is already locked, then do nothing and return
@code{#f}. @code{#f}.
@ -70,7 +64,7 @@ release it, but that's not required, any thread can release it.
@cindex user asyncs @cindex user asyncs
@cindex system asyncs @cindex system asyncs
Asyncs are a means of deferring the excution of Scheme code until it is Asyncs are a means of deferring the execution of Scheme code until it is
safe to do so. safe to do so.
Guile provides two kinds of asyncs that share the basic concept but are Guile provides two kinds of asyncs that share the basic concept but are
@ -132,43 +126,42 @@ This procedure is not safe to be called from signal handlers. Use
signal handlers. signal handlers.
@end deffn @end deffn
@c FIXME: The use of @deffnx for scm_c_call_with_blocked_asyncs and
@c scm_c_call_with_unblocked_asyncs puts "void" into the function
@c index. Would prefer to use @deftypefnx if makeinfo allowed that,
@c or a @deftypefn with an empty return type argument if it didn't
@c introduce an extra space.
@deffn {Scheme Procedure} call-with-blocked-asyncs proc @deffn {Scheme Procedure} call-with-blocked-asyncs proc
@deffnx {C Function} scm_call_with_blocked_asyncs (proc) @deffnx {C Function} scm_call_with_blocked_asyncs (proc)
@deffnx {C Function} {void *} scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data)
@findex scm_c_call_with_blocked_asyncs
Call @var{proc} and block the execution of system asyncs by one level Call @var{proc} and block the execution of system asyncs by one level
for the current thread while it is running. Return the value returned for the current thread while it is running. Return the value returned
by @var{proc}. For the first two variants, call @var{proc} with no by @var{proc}. For the first two variants, call @var{proc} with no
arguments; for the third, call it with @var{data}. arguments; for the third, call it with @var{data}.
@end deffn @end deffn
@deftypefn {C Function} {void *} scm_c_call_with_blocked_asyncs (void * (*proc) (void *data), void *data)
The same but with a C function @var{proc} instead of a Scheme thunk.
@end deftypefn
@deffn {Scheme Procedure} call-with-unblocked-asyncs proc @deffn {Scheme Procedure} call-with-unblocked-asyncs proc
@deffnx {C Function} scm_call_with_unblocked_asyncs (proc) @deffnx {C Function} scm_call_with_unblocked_asyncs (proc)
@deffnx {C Function} {void *} scm_c_call_with_unblocked_asyncs (void *(*p) (void *d), void *d)
@findex scm_c_call_with_unblocked_asyncs
Call @var{proc} and unblock the execution of system asyncs by one Call @var{proc} and unblock the execution of system asyncs by one
level for the current thread while it is running. Return the value level for the current thread while it is running. Return the value
returned by @var{proc}. For the first two variants, call @var{proc} returned by @var{proc}. For the first two variants, call @var{proc}
with no arguments; for the third, call it with @var{data}. with no arguments; for the third, call it with @var{data}.
@end deffn @end deffn
@deftypefn {C Function} {void *} scm_c_call_with_unblocked_asyncs (void *(*proc) (void *data), void *data)
The same but with a C function @var{proc} instead of a Scheme thunk.
@end deftypefn
@deftypefn {C Function} void scm_dynwind_block_asyncs () @deftypefn {C Function} void scm_dynwind_block_asyncs ()
This function must be used inside a pair of calls to During the current dynwind context, increase the blocking of asyncs by
one level. This function must be used inside a pair of calls to
@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic @code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic
Wind}). During the dynwind context, asyncs are blocked by one level. Wind}).
@end deftypefn @end deftypefn
@deftypefn {C Function} void scm_dynwind_unblock_asyncs () @deftypefn {C Function} void scm_dynwind_unblock_asyncs ()
This function must be used inside a pair of calls to During the current dynwind context, decrease the blocking of asyncs by
one level. This function must be used inside a pair of calls to
@code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic @code{scm_dynwind_begin} and @code{scm_dynwind_end} (@pxref{Dynamic
Wind}). During the dynwind context, asyncs are unblocked by one Wind}).
level.
@end deftypefn @end deftypefn
@node User asyncs @node User asyncs
@ -197,32 +190,6 @@ Mark the user async @var{a} for future execution.
Execute all thunks from the marked asyncs of the list @var{list_of_a}. Execute all thunks from the marked asyncs of the list @var{list_of_a}.
@end deffn @end deffn
@node Continuation Barriers
@subsection Continuation Barriers
The non-local flow of control caused by continuations might sometimes
not be wanted. You can use @code{with-continuation-barrier} etc to
errect fences that continuations can not pass.
@deffn {Scheme Procedure} with-continuation-barrier proc
@deffnx {C Function} scm_with_continuation_barrier (proc)
Call @var{proc} and return its result. Do not allow the invocation of
continuations that would leave or enter the dynamic extent of the call
to @code{with-continuation-barrier}. Such an attempt causes an error
to be signaled.
Throws (such as errors) that are not caught from within @var{proc} are
caught by @code{with-continuation-barrier}. In that case, a short
message is printed to the current error port and @code{#f} is returned.
Thus, @code{with-continuation-barrier} returns exactly once.
@end deffn
@deftypefn {C Function} {void *} scm_c_with_continuation_barrier (void *(*func) (void *), void *data)
Like @code{scm_with_continuation_barrier} but call @var{func} on
@var{data}. When an error is caught, @code{NULL} is returned.
@end deftypefn
@node Threads @node Threads
@subsection Threads @subsection Threads
@cindex threads @cindex threads

View file

@ -48,19 +48,18 @@ checks.
@cindex pkg-config @cindex pkg-config
@cindex autoconf @cindex autoconf
GNU Guile provides a @dfn{pkg-config} description file, installed as GNU Guile provides a @dfn{pkg-config} description file, which contains
@file{@var{prefix}/lib/pkgconfig/guile-2.0.pc}, which contains all the all the information necessary to compile and link C applications that
information necessary to compile and link C applications that use Guile. use Guile. The @code{pkg-config} program is able to read this file
The @code{pkg-config} program is able to read this file and provide this and provide this information to application programmers; it can be
information to application programmers; it can be obtained at obtained at @url{http://pkg-config.freedesktop.org/}.
@url{http://pkg-config.freedesktop.org/}.
The following command lines give respectively the C compilation and link The following command lines give respectively the C compilation and link
flags needed to build Guile-using programs: flags needed to build Guile-using programs:
@example @example
pkg-config guile-2.0 --cflags pkg-config guile-@value{EFFECTIVE-VERSION} --cflags
pkg-config guile-2.0 --libs pkg-config guile-@value{EFFECTIVE-VERSION} --libs
@end example @end example
To ease use of pkg-config with Autoconf, pkg-config comes with a To ease use of pkg-config with Autoconf, pkg-config comes with a
@ -71,7 +70,7 @@ accordingly, or prints an error and exits if Guile was not found:
@findex PKG_CHECK_MODULES @findex PKG_CHECK_MODULES
@example @example
PKG_CHECK_MODULES([GUILE], [guile-2.0]) PKG_CHECK_MODULES([GUILE], [guile-@value{EFFECTIVE-VERSION}])
@end example @end example
Guile comes with additional Autoconf macros providing more information, Guile comes with additional Autoconf macros providing more information,

View file

@ -536,7 +536,8 @@ be wrapped in a thunk that declares the arity of the expression:
@example @example
scheme@@(guile-user)> ,language glil scheme@@(guile-user)> ,language glil
Guile Lowlevel Intermediate Language (GLIL) interpreter 0.3 on Guile 1.9.0 Guile Lowlevel Intermediate Language (GLIL) interpreter 0.3 on
Guile 1.9.0
Copyright (C) 2001-2008 Free Software Foundation, Inc. Copyright (C) 2001-2008 Free Software Foundation, Inc.
Enter `,help' for help. Enter `,help' for help.

View file

@ -0,0 +1 @@
@set EFFECTIVE-VERSION @GUILE_EFFECTIVE_VERSION@

View file

@ -10,9 +10,9 @@
The macros in this section are made available with: The macros in this section are made available with:
@smalllisp @lisp
(use-modules (ice-9 expect)) (use-modules (ice-9 expect))
@end smalllisp @end lisp
@code{expect} is a macro for selecting actions based on the output from @code{expect} is a macro for selecting actions based on the output from
a port. The name comes from a tool of similar functionality by Don Libes. a port. The name comes from a tool of similar functionality by Don Libes.
@ -30,14 +30,14 @@ which is matched against each of the patterns. When a
pattern matches, the remaining expression(s) in pattern matches, the remaining expression(s) in
the clause are evaluated and the value of the last is returned. For example: the clause are evaluated and the value of the last is returned. For example:
@smalllisp @lisp
(with-input-from-file "/etc/passwd" (with-input-from-file "/etc/passwd"
(lambda () (lambda ()
(expect-strings (expect-strings
("^nobody" (display "Got a nobody user.\n") ("^nobody" (display "Got a nobody user.\n")
(display "That's no problem.\n")) (display "That's no problem.\n"))
("^daemon" (display "Got a daemon user.\n"))))) ("^daemon" (display "Got a daemon user.\n")))))
@end smalllisp @end lisp
The regular expression is compiled with the @code{REG_NEWLINE} flag, so The regular expression is compiled with the @code{REG_NEWLINE} flag, so
that the ^ and $ anchors will match at any newline, not just at the start that the ^ and $ anchors will match at any newline, not just at the start
@ -54,13 +54,13 @@ The symbol @code{=>} can be used to indicate that the expression is a
procedure which will accept the result of a successful regular expression procedure which will accept the result of a successful regular expression
match. E.g., match. E.g.,
@smalllisp @lisp
("^daemon" => write) ("^daemon" => write)
("^d(aemon)" => (lambda args (for-each write args))) ("^d(aemon)" => (lambda args (for-each write args)))
("^da(em)on" => (lambda (all sub) ("^da(em)on" => (lambda (all sub)
(write all) (newline) (write all) (newline)
(write sub) (newline))) (write sub) (newline)))
@end smalllisp @end lisp
The order of the substrings corresponds to the order in which the The order of the substrings corresponds to the order in which the
opening brackets occur. opening brackets occur.
@ -135,12 +135,12 @@ expression.
In the following example, a string will only be matched at the beginning In the following example, a string will only be matched at the beginning
of the file: of the file:
@smalllisp @lisp
(let ((expect-port (open-input-file "/etc/passwd"))) (let ((expect-port (open-input-file "/etc/passwd")))
(expect (expect
((lambda (s eof?) (string=? s "fnord!")) ((lambda (s eof?) (string=? s "fnord!"))
(display "Got a nobody user!\n")))) (display "Got a nobody user!\n"))))
@end smalllisp @end lisp
The control variables described for @code{expect-strings} also The control variables described for @code{expect-strings} also
influence the behaviour of @code{expect}, with the exception of influence the behaviour of @code{expect}, with the exception of

View file

@ -1,3 +1,9 @@
@c -*-texinfo-*-
@c This is part of the GNU Guile Reference Manual.
@c Copyright (C) 2008, 2009
@c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions.
@c Original attribution: @c Original attribution:
@c @c
@ -24,19 +30,33 @@
@c Guile @c Guile
@c @end macro @c @end macro
This is chapter was originally written by Erick Gallesio as an appendix This section introduces the @goops{} package in more detail. It was
for the STk reference manual, and subsequently adapted to @goops{}. originally written by Erick Gallesio as an appendix for the STk
reference manual, and subsequently adapted to @goops{}.
The procedures and syntax described in this tutorial are provided by
Guile modules that may need to be imported before being available.
The main @goops{} module is imported by evaluating:
@lisp
(use-modules (oop goops))
@end lisp
@findex (oop goops)
@cindex main module
@cindex loading
@cindex preparing
@menu @menu
* Copyright:: * Copyright::
* Intro:: * Class definition::
* Class definition and instantiation:: * Instance creation and slot access::
* Slot description::
* Inheritance:: * Inheritance::
* Generic functions:: * Generic functions::
@end menu @end menu
@node Copyright, Intro, Tutorial, Tutorial @node Copyright
@section Copyright @subsection Copyright
Original attribution: Original attribution:
@ -52,52 +72,13 @@ required for any of the authorized uses.
This software is provided ``AS IS'' without express or implied This software is provided ``AS IS'' without express or implied
warranty. warranty.
Adapted for use in Guile with the authors permission Adapted for use in Guile with the author's permission
@node Intro, Class definition and instantiation, Copyright, Tutorial @node Class definition
@section Introduction
@goops{} is the object oriented extension to @guile{}. Its
implementation is derived from @w{STk-3.99.3} by Erick Gallesio and
version 1.3 of the Gregor Kiczales @cite{Tiny-Clos}. It is very close
to CLOS, the Common Lisp Object System (@cite{CLtL2}) but is adapted for
the Scheme language.
Briefly stated, the @goops{} extension gives the user a full object
oriented system with multiple inheritance and generic functions with
multi-method dispatch. Furthermore, the implementation relies on a true
meta object protocol, in the spirit of the one defined for CLOS
(@cite{Gregor Kiczales: A Metaobject Protocol}).
The purpose of this tutorial is to introduce briefly the @goops{}
package and in no case will it replace the @goops{} reference manual
(which needs to be urgently written now@ @dots{}).
Note that the operations described in this tutorial resides in modules
that may need to be imported before being available. The main module is
imported by evaluating:
@lisp
(use-modules (oop goops))
@end lisp
@findex (oop goops)
@cindex main module
@cindex loading
@cindex preparing
@node Class definition and instantiation, Inheritance, Intro, Tutorial
@section Class definition and instantiation
@menu
* Class definition::
@end menu
@node Class definition, , Class definition and instantiation, Class definition and instantiation
@subsection Class definition @subsection Class definition
A new class is defined with the @code{define-class}@footnote{Don't A new class is defined with the @code{define-class} macro. The syntax
forget to import the @code{(oop goops)} module} macro. The syntax of of @code{define-class} is close to CLOS @code{defclass}:
@code{define-class} is close to CLOS @code{defclass}:
@findex define-class @findex define-class
@cindex class @cindex class
@ -107,105 +88,36 @@ forget to import the @code{(oop goops)} module} macro. The syntax of
@var{class-option} @dots{}) @var{class-option} @dots{})
@end lisp @end lisp
Class options will not be discussed in this tutorial. The list of @var{class} is the class being defined. The list of
@var{superclass}es specifies which classes to inherit properties from @var{superclass}es specifies which existing classes, if any, to
@var{class} (see @ref{Inheritance} for more details). A inherit slots and properties from. Each @var{slot-description} gives
@var{slot-description} gives the name of a slot and, eventually, some the name of a slot and optionally some ``properties'' of this slot;
``properties'' of this slot (such as its initial value, the function for example its initial value, the name of a function which will
which permit to access its value, @dots{}). Slot descriptions will be access its value, and so on. Slot descriptions and inheritance are
discussed in @ref{Slot description}. discussed more below. For class options, see @ref{Class Options}.
@cindex slot @cindex slot
As an example, let us define a type for representation of complex As an example, let us define a type for representing a complex number
numbers in terms of real numbers. This can be done with the following in terms of two real numbers.@footnote{Of course Guile already
class definition: provides complex numbers, and @code{<complex>} is in fact a predefined
class in GOOPS; but the definition here is still useful as an
example.} This can be done with the following class definition:
@lisp @lisp
(define-class <complex> (<number>) (define-class <my-complex> (<number>)
r i) r i)
@end lisp @end lisp
This binds the variable @code{<complex>}@footnote{@code{<complex>} is in This binds the variable @code{<my-complex>} to a new class whose
fact a builtin class in GOOPS. Because of this, GOOPS will create a new instances will contain two slots. These slots are called @code{r} and
class. The old class will still serve as the type for Guile's native @code{i} and will hold the real and imaginary parts of a complex
complex numbers.} to a new class whose instances contain two number. Note that this class inherits from @code{<number>}, which is a
slots. These slots are called @code{r} an @code{i} and we suppose here predefined class.@footnote{@code{<number>} is the direct superclass of
that they contain respectively the real part and the imaginary part of a the predefined class @code{<complex>}; @code{<complex>} is the
complex number. Note that this class inherits from @code{<number>} which superclass of @code{<real>}, and @code{<real>} is the superclass of
is a pre-defined class. (@code{<number>} is the direct super class of @code{<integer>}.}
the pre-defined class @code{<complex>} which, in turn, is the super
class of @code{<real>} which is the super of
@code{<integer>}.)@footnote{With the new definition of @code{<complex>},
a @code{<real>} is not a @code{<complex>} since @code{<real>} inherits
from @code{ <number>} rather than @code{<complex>}. In practice,
inheritance could be modified @emph{a posteriori}, if needed. However,
this necessitates some knowledge of the meta object protocol and it will
not be shown in this document}.
@node Inheritance, Generic functions, Class definition and instantiation, Tutorial @node Instance creation and slot access
@section Inheritance
@c \label{inheritance}
@menu
* Class hierarchy and inheritance of slots::
* Instance creation and slot access::
* Slot description::
* Class precedence list::
@end menu
@node Class hierarchy and inheritance of slots, Instance creation and slot access, Inheritance, Inheritance
@subsection Class hierarchy and inheritance of slots
Inheritance is specified upon class definition. As said in the
introduction, @goops{} supports multiple inheritance. Here are some
class definitions:
@lisp
(define-class A () a)
(define-class B () b)
(define-class C () c)
(define-class D (A B) d a)
(define-class E (A C) e c)
(define-class F (D E) f)
@end lisp
@code{A}, @code{B}, @code{C} have a null list of super classes. In this
case, the system will replace it by the list which only contains
@code{<object>}, the root of all the classes defined by
@code{define-class}. @code{D}, @code{E}, @code{F} use multiple
inheritance: each class inherits from two previously defined classes.
Those class definitions define a hierarchy which is shown in Figure@ 1.
In this figure, the class @code{<top>} is also shown; this class is the
super class of all Scheme objects. In particular, @code{<top>} is the
super class of all standard Scheme types.
@example
@group
@image{hierarchy}
@center @emph{Fig 1: A class hierarchy}
@iftex
@emph{(@code{<complex>} which is the direct subclass of @code{<number>}
and the direct superclass of @code{<real>} has been omitted in this
figure.)}
@end iftex
@end group
@end example
The set of slots of a given class is calculated by taking the union of the
slots of all its super class. For instance, each instance of the class
D, defined before will have three slots (@code{a}, @code{b} and
@code{d}). The slots of a class can be obtained by the @code{class-slots}
primitive. For instance,
@lisp
(class-slots A) @result{} ((a))
(class-slots E) @result{} ((a) (e) (c))
(class-slots F) @result{} ((e) (c) (b) (d) (a) (f))
@c used to be ((d) (a) (b) (c) (f))
@end lisp
@emph{Note: } The order of slots is not significant.
@node Instance creation and slot access, Slot description, Class hierarchy and inheritance of slots, Inheritance
@subsection Instance creation and slot access @subsection Instance creation and slot access
Creation of an instance of a previously defined Creation of an instance of a previously defined
@ -218,16 +130,16 @@ slots of the newly created instance. For instance, the following form
@findex make @findex make
@cindex instance @cindex instance
@lisp @lisp
(define c (make <complex>)) (define c (make <my-complex>))
@end lisp @end lisp
will create a new @code{<complex>} object and will bind it to the @code{c} @noindent
will create a new @code{<my-complex>} object and will bind it to the @code{c}
Scheme variable. Scheme variable.
Accessing the slots of the new complex number can be done with the Accessing the slots of the new complex number can be done with the
@code{slot-ref} and the @code{slot-set!} primitives. @code{Slot-set!} @code{slot-ref} and the @code{slot-set!} primitives. @code{slot-set!}
primitive permits to set the value of an object slot and @code{slot-ref} sets the value of an object slot and @code{slot-ref} retrieves it.
permits to get its value.
@findex slot-set! @findex slot-set!
@findex slot-ref @findex slot-ref
@ -250,52 +162,60 @@ First load the module @code{(oop goops describe)}:
@code{(use-modules (oop goops describe))} @code{(use-modules (oop goops describe))}
@end example @end example
The expression @noindent
Then the expression
@smalllisp
(describe c)
@end smalllisp
will now print the following information on the standard output:
@lisp @lisp
#<<complex> 401d8638> is an instance of class <complex> (describe c)
@end lisp
@noindent
will print the following information on the standard output:
@smalllisp
#<<my-complex> 401d8638> is an instance of class <my-complex>
Slots are: Slots are:
r = 10 r = 10
i = 3 i = 3
@end lisp @end smalllisp
@node Slot description, Class precedence list, Instance creation and slot access, Inheritance @node Slot description
@subsection Slot description @subsection Slot description
@c \label{slot-description} @c \label{slot-description}
When specifying a slot, a set of options can be given to the When specifying a slot (in a @code{(define-class @dots{})} form),
system. Each option is specified with a keyword. The list of authorized various options can be specified in addition to the slot's name. Each
keywords is given below: option is specified by a keyword. The list of authorized keywords is
given below:
@cindex keyword @cindex keyword
@itemize @bullet @itemize @bullet
@item @item
@code{#:init-value} permits to supply a default value for the slot. This @code{#:init-value} permits to supply a constant default value for the
default value is obtained by evaluating the form given after the slot. The value is obtained by evaluating the form given after the
@code{#:init-form} in the global environment, at class definition time. @code{#:init-value} at class definition time.
@cindex default slot value @cindex default slot value
@findex #:init-value @findex #:init-value
@cindex top level environment
@item
@code{#:init-form} specifies a form that, when evaluated, will return
an initial value for the slot. The form is evaluated each time that
an instance of the class is created, in the lexical environment of the
containing @code{define-class} expression.
@cindex default slot value
@findex #:init-form
@item @item
@code{#:init-thunk} permits to supply a thunk that will provide a @code{#:init-thunk} permits to supply a thunk that will provide a
default value for the slot. The value is obtained by evaluating the default value for the slot. The value is obtained by invoking the
thunk a instance creation time. thunk at instance creation time.
@c CHECKME: in the global environment?
@findex default slot value @findex default slot value
@findex #:init-thunk @findex #:init-thunk
@cindex top level environment
@item @item
@code{#:init-keyword} permits to specify the keyword for initializing a @code{#:init-keyword} permits to specify a keyword for initializing the
slot. The init-keyword may be provided during instance creation (i.e. in slot. The init-keyword may be provided during instance creation (i.e. in
the @code{make} optional parameter list). Specifying such a keyword the @code{make} optional parameter list). Specifying such a keyword
during instance initialization will supersede the default slot during instance initialization will supersede the default slot
initialization possibly given with @code{#:init-form}. initialization possibly given with @code{#:init-form}.
@findex #:init-keyword @findex #:init-keyword
@ -361,11 +281,11 @@ and @code{#:slot-set!} options. See the example below.
@end itemize @end itemize
@end itemize @end itemize
To illustrate slot description, we shall redefine the @code{<complex>} class To illustrate slot description, we shall redefine the @code{<my-complex>} class
seen before. A definition could be: seen before. A definition could be:
@lisp @lisp
(define-class <complex> (<number>) (define-class <my-complex> (<number>)
(r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r) (r #:init-value 0 #:getter get-r #:setter set-r! #:init-keyword #:r)
(i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i)) (i #:init-value 0 #:getter get-i #:setter set-i! #:init-keyword #:i))
@end lisp @end lisp
@ -378,11 +298,11 @@ functions @code{get-r} and @code{set-r!} (resp. @code{get-i} and
the @code{r} (resp. @code{i}) slot. the @code{r} (resp. @code{i}) slot.
@lisp @lisp
(define c1 (make <complex> #:r 1 #:i 2)) (define c1 (make <my-complex> #:r 1 #:i 2))
(get-r c1) @result{} 1 (get-r c1) @result{} 1
(set-r! c1 12) (set-r! c1 12)
(get-r c1) @result{} 12 (get-r c1) @result{} 12
(define c2 (make <complex> #:r 2)) (define c2 (make <my-complex> #:r 2))
(get-r c2) @result{} 2 (get-r c2) @result{} 2
(get-i c2) @result{} 0 (get-i c2) @result{} 0
@end lisp @end lisp
@ -390,12 +310,12 @@ the @code{r} (resp. @code{i}) slot.
Accessors provide an uniform access for reading and writing an object Accessors provide an uniform access for reading and writing an object
slot. Writing a slot is done with an extended form of @code{set!} slot. Writing a slot is done with an extended form of @code{set!}
which is close to the Common Lisp @code{setf} macro. So, another which is close to the Common Lisp @code{setf} macro. So, another
definition of the previous @code{<complex>} class, using the definition of the previous @code{<my-complex>} class, using the
@code{#:accessor} option, could be: @code{#:accessor} option, could be:
@findex set! @findex set!
@lisp @lisp
(define-class <complex> (<number>) (define-class <my-complex> (<number>)
(r #:init-value 0 #:accessor real-part #:init-keyword #:r) (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
(i #:init-value 0 #:accessor imag-part #:init-keyword #:i)) (i #:init-value 0 #:accessor imag-part #:init-keyword #:i))
@end lisp @end lisp
@ -416,13 +336,13 @@ coordinates as well as with polar coordinates. One solution could be to
have a definition of complex numbers which uses one particular have a definition of complex numbers which uses one particular
representation and some conversion functions to pass from one representation and some conversion functions to pass from one
representation to the other. A better solution uses virtual slots. A representation to the other. A better solution uses virtual slots. A
complete definition of the @code{<complex>} class using virtual slots is complete definition of the @code{<my-complex>} class using virtual slots is
given in Figure@ 2. given in Figure@ 2.
@example @example
@group @group
@lisp @lisp
(define-class <complex> (<number>) (define-class <my-complex> (<number>)
;; True slots use rectangular coordinates ;; True slots use rectangular coordinates
(r #:init-value 0 #:accessor real-part #:init-keyword #:r) (r #:init-value 0 #:accessor real-part #:init-keyword #:r)
(i #:init-value 0 #:accessor imag-part #:init-keyword #:i) (i #:init-value 0 #:accessor imag-part #:init-keyword #:i)
@ -446,7 +366,7 @@ given in Figure@ 2.
(slot-set! o 'i (* m (sin a))))))) (slot-set! o 'i (* m (sin a)))))))
@end lisp @end lisp
@center @emph{Fig 2: A @code{<complex>} number class definition using virtual slots} @center @emph{Fig 2: A @code{<my-complex>} number class definition using virtual slots}
@end group @end group
@end example @end example
@ -480,20 +400,21 @@ A more complete example is given below:
@example @example
@group @group
@lisp @smalllisp
(define c (make <complex> #:r 12 #:i 20)) (define c (make <my-complex> #:r 12 #:i 20))
(real-part c) @result{} 12 (real-part c) @result{} 12
(angle c) @result{} 1.03037682652431 (angle c) @result{} 1.03037682652431
(slot-set! c 'i 10) (slot-set! c 'i 10)
(set! (real-part c) 1) (set! (real-part c) 1)
(describe c) @result{} (describe c)
#<<complex> 401e9b58> is an instance of class <complex> @print{}
Slots are: #<<my-complex> 401e9b58> is an instance of class <my-complex>
r = 1 Slots are:
i = 10 r = 1
m = 10.0498756211209 i = 10
a = 1.47112767430373 m = 10.0498756211209
@end lisp a = 1.47112767430373
@end smalllisp
@end group @end group
@end example @end example
@ -503,14 +424,75 @@ Scheme primitives.
@lisp @lisp
(define make-rectangular (define make-rectangular
(lambda (x y) (make <complex> #:r x #:i y))) (lambda (x y) (make <my-complex> #:r x #:i y)))
(define make-polar (define make-polar
(lambda (x y) (make <complex> #:magn x #:angle y))) (lambda (x y) (make <my-complex> #:magn x #:angle y)))
@end lisp @end lisp
@node Class precedence list, , Slot description, Inheritance @node Inheritance
@subsection Class precedence list @subsection Inheritance
@c \label{inheritance}
@menu
* Class hierarchy and inheritance of slots::
* Class precedence list::
@end menu
@node Class hierarchy and inheritance of slots
@subsubsection Class hierarchy and inheritance of slots
Inheritance is specified upon class definition. As said in the
introduction, @goops{} supports multiple inheritance. Here are some
class definitions:
@lisp
(define-class A () a)
(define-class B () b)
(define-class C () c)
(define-class D (A B) d a)
(define-class E (A C) e c)
(define-class F (D E) f)
@end lisp
@code{A}, @code{B}, @code{C} have a null list of super classes. In this
case, the system will replace it by the list which only contains
@code{<object>}, the root of all the classes defined by
@code{define-class}. @code{D}, @code{E}, @code{F} use multiple
inheritance: each class inherits from two previously defined classes.
Those class definitions define a hierarchy which is shown in Figure@ 1.
In this figure, the class @code{<top>} is also shown; this class is the
super class of all Scheme objects. In particular, @code{<top>} is the
super class of all standard Scheme types.
@example
@group
@image{hierarchy}
@center @emph{Fig 1: A class hierarchy}
@iftex
@emph{(@code{<complex>} which is the direct subclass of @code{<number>}
and the direct superclass of @code{<real>} has been omitted in this
figure.)}
@end iftex
@end group
@end example
The set of slots of a given class is calculated by taking the union of the
slots of all its super class. For instance, each instance of the class
D, defined before will have three slots (@code{a}, @code{b} and
@code{d}). The slots of a class can be obtained by the @code{class-slots}
primitive. For instance,
@lisp
(class-slots A) @result{} ((a))
(class-slots E) @result{} ((a) (e) (c))
(class-slots F) @result{} ((e) (c) (b) (d) (a) (f))
@c used to be ((d) (a) (b) (c) (f))
@end lisp
@emph{Note: } The order of slots is not significant.
@node Class precedence list
@subsubsection Class precedence list
A class may have more than one superclass. @footnote{This section is an A class may have more than one superclass. @footnote{This section is an
adaptation of Jeff Dalton's (J.Dalton@@ed.ac.uk) @cite{Brief adaptation of Jeff Dalton's (J.Dalton@@ed.ac.uk) @cite{Brief
@ -587,8 +569,8 @@ However, this result is not too much readable; using the function
(map class-name (class-precedence-list B)) @result{} (B <object> <top>) (map class-name (class-precedence-list B)) @result{} (B <object> <top>)
@end lisp @end lisp
@node Generic functions, , Inheritance, Tutorial @node Generic functions
@section Generic functions @subsection Generic functions
@menu @menu
* Generic functions and methods:: * Generic functions and methods::
@ -596,8 +578,8 @@ However, this result is not too much readable; using the function
* Example:: * Example::
@end menu @end menu
@node Generic functions and methods, Next-method, Generic functions, Generic functions @node Generic functions and methods
@subsection Generic functions and methods @subsubsection Generic functions and methods
@c \label{gf-n-methods} @c \label{gf-n-methods}
Neither @goops{} nor CLOS use the message mechanism for methods as most Neither @goops{} nor CLOS use the message mechanism for methods as most
@ -687,8 +669,8 @@ In this case,
(G 'a 1) @result{} top-number (G 'a 1) @result{} top-number
@end lisp @end lisp
@node Next-method, Example, Generic functions and methods, Generic functions @node Next-method
@subsection Next-method @subsubsection Next-method
When you call a generic function, with a particular set of arguments, When you call a generic function, with a particular set of arguments,
GOOPS builds a list of all the methods that are applicable to those GOOPS builds a list of all the methods that are applicable to those
@ -737,16 +719,16 @@ Number is in range
lead to an infinite recursion, but this consideration is just the same lead to an infinite recursion, but this consideration is just the same
as in Scheme code in general.) as in Scheme code in general.)
@node Example, , Next-method, Generic functions @node Example
@subsection Example @subsubsection Example
In this section we shall continue to define operations on the @code{<complex>} In this section we shall continue to define operations on the @code{<my-complex>}
class defined in Figure@ 2. Suppose that we want to use it to implement class defined in Figure@ 2. Suppose that we want to use it to implement
complex numbers completely. For instance a definition for the addition of complex numbers completely. For instance a definition for the addition of
two complexes could be two complexes could be
@lisp @lisp
(define-method (new-+ (a <complex>) (b <complex>)) (define-method (new-+ (a <my-complex>) (b <my-complex>))
(make-rectangular (+ (real-part a) (real-part b)) (make-rectangular (+ (real-part a) (real-part b))
(+ (imag-part a) (imag-part b)))) (+ (imag-part a) (imag-part b))))
@end lisp @end lisp
@ -758,7 +740,7 @@ addition we can do:
(define-generic new-+) (define-generic new-+)
(let ((+ +)) (let ((+ +))
(define-method (new-+ (a <complex>) (b <complex>)) (define-method (new-+ (a <my-complex>) (b <my-complex>))
(make-rectangular (+ (real-part a) (real-part b)) (make-rectangular (+ (real-part a) (real-part b))
(+ (imag-part a) (imag-part b))))) (+ (imag-part a) (imag-part b)))))
@end lisp @end lisp
@ -778,13 +760,13 @@ Figure@ 3.
(define-method (new-+ (a <real>) (b <real>)) (+ a b)) (define-method (new-+ (a <real>) (b <real>)) (+ a b))
(define-method (new-+ (a <real>) (b <complex>)) (define-method (new-+ (a <real>) (b <my-complex>))
(make-rectangular (+ a (real-part b)) (imag-part b))) (make-rectangular (+ a (real-part b)) (imag-part b)))
(define-method (new-+ (a <complex>) (b <real>)) (define-method (new-+ (a <my-complex>) (b <real>))
(make-rectangular (+ (real-part a) b) (imag-part a))) (make-rectangular (+ (real-part a) b) (imag-part a)))
(define-method (new-+ (a <complex>) (b <complex>)) (define-method (new-+ (a <my-complex>) (b <my-complex>))
(make-rectangular (+ (real-part a) (real-part b)) (make-rectangular (+ (real-part a) (real-part b))
(+ (imag-part a) (imag-part b)))) (+ (imag-part a) (imag-part b))))
@ -823,7 +805,7 @@ To terminate our implementation (integration?) of complex numbers, we can
redefine standard Scheme predicates in the following manner: redefine standard Scheme predicates in the following manner:
@lisp @lisp
(define-method (complex? c <complex>) #t) (define-method (complex? c <my-complex>) #t)
(define-method (complex? c) #f) (define-method (complex? c) #f)
(define-method (number? n <number>) #t) (define-method (number? n <number>) #t)

View file

@ -1,19 +1,8 @@
\input texinfo
@c -*-texinfo-*- @c -*-texinfo-*-
@c %**start of header @c This is part of the GNU Guile Reference Manual.
@setfilename goops.info @c Copyright (C) 2008, 2009
@settitle Goops Manual @c Free Software Foundation, Inc.
@set goops @c See the file guile.texi for copying conditions.
@setchapternewpage odd
@paragraphindent 0
@c %**end of header
@set VERSION 0.3
@dircategory The Algorithmic Language Scheme
@direntry
* GOOPS: (goops). The GOOPS reference manual.
@end direntry
@macro goops @macro goops
GOOPS GOOPS
@ -23,77 +12,8 @@ GOOPS
Guile Guile
@end macro @end macro
@ifinfo @node GOOPS
This file documents GOOPS, an object oriented extension for Guile. @chapter GOOPS
Copyright (C) 1999, 2000, 2001, 2003, 2006 Free Software Foundation
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@end ifinfo
@c This title page illustrates only one of the
@c two methods of forming a title page.
@titlepage
@title Goops Manual
@subtitle For use with GOOPS @value{VERSION}
@c AUTHORS
@c The GOOPS tutorial was written by Christian Lynbech and Mikael
@c Djurfeldt, who also wrote GOOPS itself. The GOOPS reference manual
@c and MOP documentation were written by Neil Jerram and reviewed by
@c Mikael Djurfeldt.
@author Christian Lynbech
@author @email{chl@@tbit.dk}
@author
@author Mikael Djurfeldt
@author @email{djurfeldt@@nada.kth.se}
@author
@author Neil Jerram
@author @email{neil@@ossau.uklinux.net}
@c The following two commands
@c start the copyright page.
@page
@vskip 0pt plus 1filll
Copyright @copyright{} 1999, 2006 Free Software Foundation
Permission is granted to make and distribute verbatim copies of
this manual provided the copyright notice and this permission notice
are preserved on all copies.
@end titlepage
@node Top, Introduction, (dir), (dir)
@menu
* Introduction::
* Getting Started::
* Reference Manual::
* MOP Specification::
* Tutorial::
* Concept Index::
* Function and Variable Index::
@end menu
@iftex
@chapter Preliminaries
@end iftex
@node Introduction, Getting Started, Top, Top
@iftex
@section Introduction
@end iftex
@ifnottex
@chapter Introduction
@end ifnottex
@goops{} is the object oriented extension to @guile{}. Its @goops{} is the object oriented extension to @guile{}. Its
implementation is derived from @w{STk-3.99.3} by Erick Gallesio and implementation is derived from @w{STk-3.99.3} by Erick Gallesio and
@ -109,71 +29,58 @@ multi-method dispatch. Furthermore, the implementation relies on a true
meta object protocol, in the spirit of the one defined for CLOS meta object protocol, in the spirit of the one defined for CLOS
(@cite{Gregor Kiczales: A Metaobject Protocol}). (@cite{Gregor Kiczales: A Metaobject Protocol}).
@node Getting Started, Reference Manual, Introduction, Top
@iftex
@section Getting Started
@end iftex
@ifnottex
@chapter Getting Started
@end ifnottex
@menu @menu
* Running GOOPS:: * Quick Start::
* Tutorial::
Examples of some basic GOOPS functionality. * Reference Manual::
* MOP Specification::
* Methods::
* User-defined types::
* Asking for the type of an object::
See further in the GOOPS tutorial available in this distribution in
info (goops.info) and texinfo format.
@end menu @end menu
@node Running GOOPS, Methods, Getting Started, Getting Started @node Quick Start
@subsection Running GOOPS @section Quick Start
@enumerate To give an immediate flavour of what GOOPS can do, here is a very
@item brief introduction to its main operations.
Type
@smalllisp To start using GOOPS, load the @code{(oop goops)} module:
guile-oops
@end smalllisp
You should now be at the Guile prompt ("guile> "). @lisp
@item
Type
@smalllisp
(use-modules (oop goops)) (use-modules (oop goops))
@end smalllisp @end lisp
to load GOOPS. (If your system supports dynamic loading, you
should be able to do this not only from `guile-oops' but from an
arbitrary Guile interpreter.)
@end enumerate
We're now ready to try some basic GOOPS functionality. We're now ready to try some basic GOOPS functionality.
@node Methods, User-defined types, Running GOOPS, Getting Started @menu
* Methods::
* User-defined types::
* Asking for the type of an object::
@end menu
@node Methods
@subsection Methods @subsection Methods
@smalllisp A GOOPS method is like a Scheme procedure except that it is
@group specialized for a particular set of argument types.
@lisp
(define-method (+ (x <string>) (y <string>)) (define-method (+ (x <string>) (y <string>))
(string-append x y)) (string-append x y))
(+ 1 2) --> 3 (+ "abc" "de") @result{} "abcde"
(+ "abc" "de") --> "abcde" @end lisp
@end group
@end smalllisp
@node User-defined types, Asking for the type of an object, Methods, Getting Started If @code{+} is used with arguments that do not match the method's
types, Guile falls back to using the normal Scheme @code{+} procedure.
@lisp
(+ 1 2) @result{} 3
@end lisp
@node User-defined types
@subsection User-defined types @subsection User-defined types
@smalllisp @lisp
(define-class <2D-vector> () (define-class <2D-vector> ()
(x #:init-value 0 #:accessor x-component #:init-keyword #:x) (x #:init-value 0 #:accessor x-component #:init-keyword #:x)
(y #:init-value 0 #:accessor y-component #:init-keyword #:y)) (y #:init-value 0 #:accessor y-component #:init-keyword #:y))
@ -182,12 +89,11 @@ We're now ready to try some basic GOOPS functionality.
(use-modules (ice-9 format)) (use-modules (ice-9 format))
(define-method (write (obj <2D-vector>) port) (define-method (write (obj <2D-vector>) port)
(display (format #f "<~S, ~S>" (x-component obj) (y-component obj)) (format port "<~S, ~S>" (x-component obj) (y-component obj)))
port))
(define v (make <2D-vector> #:x 3 #:y 4)) (define v (make <2D-vector> #:x 3 #:y 4))
v --> <3, 4> v @result{} <3, 4>
@end group @end group
@group @group
@ -196,24 +102,28 @@ v --> <3, 4>
#:x (+ (x-component x) (x-component y)) #:x (+ (x-component x) (x-component y))
#:y (+ (y-component x) (y-component y)))) #:y (+ (y-component x) (y-component y))))
(+ v v) --> <6, 8> (+ v v) @result{} <6, 8>
@end group @end group
@end smalllisp @end lisp
@node Asking for the type of an object, , User-defined types, Getting Started @node Asking for the type of an object
@subsection Types @subsection Types
@example @example
(class-of v) --> #<<class> <2D-vector> 40241ac0> (class-of v) @result{} #<<class> <2D-vector> 40241ac0>
<2D-vector> --> #<<class> <2D-vector> 40241ac0> <2D-vector> @result{} #<<class> <2D-vector> 40241ac0>
(class-of 1) --> #<<class> <integer> 401b2a98> (class-of 1) @result{} #<<class> <integer> 401b2a98>
<integer> --> #<<class> <integer> 401b2a98> <integer> @result{} #<<class> <integer> 401b2a98>
(is-a? v <2D-vector>) --> #t (is-a? v <2D-vector>) @result{} #t
@end example @end example
@node Reference Manual, MOP Specification, Getting Started, Top @node Tutorial
@chapter Reference Manual @section Tutorial
@include goops-tutorial.texi
@node Reference Manual
@section Reference Manual
This chapter is the GOOPS reference manual. It aims to describe all the This chapter is the GOOPS reference manual. It aims to describe all the
syntax, procedures, options and associated concepts that a typical syntax, procedures, options and associated concepts that a typical
@ -241,7 +151,7 @@ For a detailed specification of the GOOPS metaobject protocol, see
@end menu @end menu
@node Introductory Remarks @node Introductory Remarks
@section Introductory Remarks @subsection Introductory Remarks
GOOPS is an object-oriented programming system based on a ``metaobject GOOPS is an object-oriented programming system based on a ``metaobject
protocol'' derived from the ones used in CLOS (the Common Lisp Object protocol'' derived from the ones used in CLOS (the Common Lisp Object
@ -261,19 +171,19 @@ GOOPS' power, by customizing the behaviour of GOOPS itself.
Each of the following sections of the reference manual is arranged Each of the following sections of the reference manual is arranged
such that the most basic usage is introduced first, and then subsequent such that the most basic usage is introduced first, and then subsequent
subsections discuss the related internal functions and metaobject subsubsections discuss the related internal functions and metaobject
protocols, finishing with a description of how to customize that area of protocols, finishing with a description of how to customize that area of
functionality. functionality.
These introductory remarks continue with a few words about metaobjects These introductory remarks continue with a few words about metaobjects
and the MOP. Readers who do not want to be bothered yet with the MOP and the MOP. Readers who do not want to be bothered yet with the MOP
and customization could safely skip this subsection on a first reading, and customization could safely skip this subsubsection on a first reading,
and should correspondingly skip subsequent subsections that are and should correspondingly skip subsequent subsubsections that are
concerned with internals and customization. concerned with internals and customization.
In general, this reference manual assumes familiarity with standard In general, this reference manual assumes familiarity with standard
object oriented concepts and terminology. However, some of the terms object oriented concepts and terminology. However, some of the terms
used in GOOPS are less well known, so the Terminology subsection used in GOOPS are less well known, so the Terminology subsubsection
provides definitions for these terms. provides definitions for these terms.
@menu @menu
@ -282,7 +192,7 @@ provides definitions for these terms.
@end menu @end menu
@node Metaobjects and the Metaobject Protocol @node Metaobjects and the Metaobject Protocol
@subsection Metaobjects and the Metaobject Protocol @subsubsection Metaobjects and the Metaobject Protocol
The conceptual building blocks of GOOPS are classes, slot definitions, The conceptual building blocks of GOOPS are classes, slot definitions,
instances, generic functions and methods. A class is a grouping of instances, generic functions and methods. A class is a grouping of
@ -377,7 +287,7 @@ Each subsequent section of the reference manual covers a particular area
of GOOPS functionality, and describes the generic functions that are of GOOPS functionality, and describes the generic functions that are
relevant for customization of that area. relevant for customization of that area.
We conclude this subsection by emphasizing a point that may seem We conclude this subsubsection by emphasizing a point that may seem
obvious, but contrasts with the corresponding situation in some other obvious, but contrasts with the corresponding situation in some other
MOP implementations, such as CLOS. The point is simply that an MOP implementations, such as CLOS. The point is simply that an
identifier which represents a GOOPS class or generic function is a identifier which represents a GOOPS class or generic function is a
@ -392,7 +302,7 @@ class names), but it is worth noting that GOOPS conforms fully to this
Schemely principle. Schemely principle.
@node Terminology @node Terminology
@subsection Terminology @subsubsection Terminology
It is assumed that the reader is already familiar with standard object It is assumed that the reader is already familiar with standard object
orientation concepts such as classes, objects/instances, orientation concepts such as classes, objects/instances,
@ -403,14 +313,7 @@ This section explains some of the less well known concepts and
terminology that GOOPS uses, which are assumed by the following sections terminology that GOOPS uses, which are assumed by the following sections
of the reference manual. of the reference manual.
@menu @subsubheading Metaclass
* Metaclass::
* Class Precedence List::
* Accessor::
@end menu
@node Metaclass
@subsubsection Metaclass
A @dfn{metaclass} is the class of an object which represents a GOOPS A @dfn{metaclass} is the class of an object which represents a GOOPS
class. Put more succinctly, a metaclass is a class's class. class. Put more succinctly, a metaclass is a class's class.
@ -517,8 +420,7 @@ The metaclass of @code{<my-metaclass>} is @code{<class>}.
@code{<class>}. @code{<class>}.
@end itemize @end itemize
@node Class Precedence List @subsubheading Class Precedence List
@subsubsection Class Precedence List
The @dfn{class precedence list} of a class is the list of all direct and The @dfn{class precedence list} of a class is the list of all direct and
indirect superclasses of that class, including the class itself. indirect superclasses of that class, including the class itself.
@ -548,8 +450,7 @@ precedence list}.
``Class precedence list'' is often abbreviated, in documentation and ``Class precedence list'' is often abbreviated, in documentation and
Scheme variable names, to @dfn{cpl}. Scheme variable names, to @dfn{cpl}.
@node Accessor @subsubheading Accessor
@subsubsection Accessor
An @dfn{accessor} is a generic function with both reference and setter An @dfn{accessor} is a generic function with both reference and setter
methods. methods.
@ -583,7 +484,7 @@ be invoked using the generalized @code{set!} syntax, as in:
@end example @end example
@node Defining New Classes @node Defining New Classes
@section Defining New Classes @subsection Defining New Classes
[ *fixme* Somewhere in this manual there needs to be an introductory [ *fixme* Somewhere in this manual there needs to be an introductory
discussion about GOOPS classes, generic functions and methods, covering discussion about GOOPS classes, generic functions and methods, covering
@ -622,7 +523,7 @@ the discussion there. ]
@end menu @end menu
@node Basic Class Definition @node Basic Class Definition
@subsection Basic Class Definition @subsubsection Basic Class Definition
New classes are defined using the @code{define-class} syntax, with New classes are defined using the @code{define-class} syntax, with
arguments that specify the classes that the new class should inherit arguments that specify the classes that the new class should inherit
@ -651,7 +552,7 @@ keywords and corresponding values.
@end deffn @end deffn
The standard GOOPS class and slot options are described in the following The standard GOOPS class and slot options are described in the following
subsections: see @ref{Class Options} and @ref{Slot Options}. subsubsections: see @ref{Class Options} and @ref{Slot Options}.
Example 1. Define a class that combines two pre-existing classes by Example 1. Define a class that combines two pre-existing classes by
inheritance but adds no new slots. inheritance but adds no new slots.
@ -681,13 +582,13 @@ customized via an application-defined metaclass.
@end example @end example
@node Class Options @node Class Options
@subsection Class Options @subsubsection Class Options
@deffn {class option} #:metaclass metaclass @deffn {class option} #:metaclass metaclass
The @code{#:metaclass} class option specifies the metaclass of the class The @code{#:metaclass} class option specifies the metaclass of the class
being defined. @var{metaclass} must be a class that inherits from being defined. @var{metaclass} must be a class that inherits from
@code{<class>}. For an introduction to the use of metaclasses, see @code{<class>}. For an introduction to the use of metaclasses, see
@ref{Metaobjects and the Metaobject Protocol} and @ref{Metaclass}. @ref{Metaobjects and the Metaobject Protocol} and @ref{Terminology}.
If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a If the @code{#:metaclass} option is absent, GOOPS reuses or constructs a
metaclass for the new class by calling @code{ensure-metaclass} metaclass for the new class by calling @code{ensure-metaclass}
@ -714,7 +615,7 @@ environment defaults to the top-level environment in which the
@end deffn @end deffn
@node Slot Options @node Slot Options
@subsection Slot Options @subsubsection Slot Options
@deffn {slot option} #:allocation allocation @deffn {slot option} #:allocation allocation
The @code{#:allocation} option tells GOOPS how to allocate storage for The @code{#:allocation} option tells GOOPS how to allocate storage for
@ -917,7 +818,7 @@ classes.
@end deffn @end deffn
@node Class Definition Internals @node Class Definition Internals
@subsection Class Definition Internals @subsubsection Class Definition Internals
Implementation notes: @code{define-class} expands to an expression which Implementation notes: @code{define-class} expands to an expression which
@ -1030,7 +931,7 @@ class object, are described in @ref{Customizing Instance Creation},
which covers the creation and initialization of instances in general. which covers the creation and initialization of instances in general.
@node Customizing Class Definition @node Customizing Class Definition
@subsection Customizing Class Definition @subsubsection Customizing Class Definition
During the initialization of a new class, GOOPS calls a number of generic During the initialization of a new class, GOOPS calls a number of generic
functions with the newly allocated class instance as the first functions with the newly allocated class instance as the first
@ -1124,7 +1025,8 @@ allocation to do this.
(let ((batch-allocation-count 0) (let ((batch-allocation-count 0)
(batch-get-n-set #f)) (batch-get-n-set #f))
(define-method (compute-get-n-set (class <batched-allocation-metaclass>) s) (define-method (compute-get-n-set
(class <batched-allocation-metaclass>) s)
(case (slot-definition-allocation s) (case (slot-definition-allocation s)
((#:batched) ((#:batched)
;; If we've already used the same slot storage for 10 instances, ;; If we've already used the same slot storage for 10 instances,
@ -1165,7 +1067,7 @@ typically it would perform additional class initialization steps before
and/or after calling @code{(next-method)} for the standard behaviour. and/or after calling @code{(next-method)} for the standard behaviour.
@node STKlos Compatibility @node STKlos Compatibility
@subsection STKlos Compatibility @subsubsection STKlos Compatibility
If the STKlos compatibility module is loaded, @code{define-class} is If the STKlos compatibility module is loaded, @code{define-class} is
overwritten by a STKlos-specific definition; the standard GOOPS overwritten by a STKlos-specific definition; the standard GOOPS
@ -1178,7 +1080,7 @@ definition of @code{define-class} remains available in
@end deffn @end deffn
@node Creating Instances @node Creating Instances
@section Creating Instances @subsection Creating Instances
@menu @menu
* Basic Instance Creation:: * Basic Instance Creation::
@ -1186,7 +1088,7 @@ definition of @code{define-class} remains available in
@end menu @end menu
@node Basic Instance Creation @node Basic Instance Creation
@subsection Basic Instance Creation @subsubsection Basic Instance Creation
To create a new instance of any GOOPS class, use the generic function To create a new instance of any GOOPS class, use the generic function
@code{make} or @code{make-instance}, passing the required class and any @code{make} or @code{make-instance}, passing the required class and any
@ -1223,7 +1125,7 @@ instance's class. Any unprocessed keyword value pairs are ignored.
@end deffn @end deffn
@node Customizing Instance Creation @node Customizing Instance Creation
@subsection Customizing Instance Creation @subsubsection Customizing Instance Creation
@code{make} itself is a generic function. Hence the @code{make} @code{make} itself is a generic function. Hence the @code{make}
invocation itself can be customized in the case where the new instance's invocation itself can be customized in the case where the new instance's
@ -1290,7 +1192,7 @@ and closures in the slot definitions, it is neater to write an
and initializes all the dependent slot values according to the results. and initializes all the dependent slot values according to the results.
@node Accessing Slots @node Accessing Slots
@section Accessing Slots @subsection Accessing Slots
The definition of a slot contains at the very least a slot name, and may The definition of a slot contains at the very least a slot name, and may
also contain various slot options, including getter, setter and/or also contain various slot options, including getter, setter and/or
@ -1298,7 +1200,7 @@ accessor functions for the slot.
It is always possible to access slots by name, using the various It is always possible to access slots by name, using the various
``slot-ref'' and ``slot-set!'' procedures described in the following ``slot-ref'' and ``slot-set!'' procedures described in the following
subsections. For example, subsubsections. For example,
@example @example
(define-class <my-class> () ;; Define a class with slots (define-class <my-class> () ;; Define a class with slots
@ -1354,7 +1256,7 @@ closures, see @ref{Customizing Class Definition,, compute-get-n-set}.)
@end menu @end menu
@node Instance Slots @node Instance Slots
@subsection Instance Slots @subsubsection Instance Slots
Any slot, regardless of its allocation, can be queried, referenced and Any slot, regardless of its allocation, can be queried, referenced and
set using the following four primitive procedures. set using the following four primitive procedures.
@ -1451,7 +1353,7 @@ slot-missing}).
@end deffn @end deffn
@node Class Slots @node Class Slots
@subsection Class Slots @subsubsection Class Slots
Slots whose allocation is per-class rather than per-instance can be Slots whose allocation is per-class rather than per-instance can be
referenced and set without needing to specify any particular instance. referenced and set without needing to specify any particular instance.
@ -1479,7 +1381,7 @@ function with arguments @var{class} and @var{slot-name}.
@end deffn @end deffn
@node Handling Slot Access Errors @node Handling Slot Access Errors
@subsection Handling Slot Access Errors @subsubsection Handling Slot Access Errors
GOOPS calls one of the following generic functions when a ``slot-ref'' GOOPS calls one of the following generic functions when a ``slot-ref''
or ``slot-set!'' call specifies a non-existent slot name, or tries to or ``slot-set!'' call specifies a non-existent slot name, or tries to
@ -1510,7 +1412,7 @@ message.
@end deffn @end deffn
@node Creating Generic Functions @node Creating Generic Functions
@section Creating Generic Functions @subsection Creating Generic Functions
A generic function is a collection of methods, with rules for A generic function is a collection of methods, with rules for
determining which of the methods should be applied for any given determining which of the methods should be applied for any given
@ -1526,7 +1428,7 @@ GOOPS represents generic functions as metaobjects of the class
@end menu @end menu
@node Basic Generic Function Creation @node Basic Generic Function Creation
@subsection Basic Generic Function Creation @subsubsection Basic Generic Function Creation
The following forms may be used to bind a variable to a generic The following forms may be used to bind a variable to a generic
function. Depending on that variable's pre-existing value, the generic function. Depending on that variable's pre-existing value, the generic
@ -1586,20 +1488,20 @@ This can be resolved automagically with the duplicates handler
@code{merge-generics} which gives the module system license to merge @code{merge-generics} which gives the module system license to merge
all generic functions sharing a common name: all generic functions sharing a common name:
@smalllisp @lisp
(define-module (math 2D-vectors) (define-module (math 2D-vectors)
:use-module (oop goops) #:use-module (oop goops)
:export (x y ...)) #:export (x y ...))
(define-module (math 3D-vectors) (define-module (math 3D-vectors)
:use-module (oop goops) #:use-module (oop goops)
:export (x y z ...)) #:export (x y z ...))
(define-module (my-module) (define-module (my-module)
:use-module (math 2D-vectors) #:use-module (math 2D-vectors)
:use-module (math 3D-vectors) #:use-module (math 3D-vectors)
:duplicates merge-generics) #:duplicates merge-generics)
@end smalllisp @end lisp
The generic function @code{x} in @code{(my-module)} will now share The generic function @code{x} in @code{(my-module)} will now share
methods with @code{x} in both imported modules. methods with @code{x} in both imported modules.
@ -1629,14 +1531,14 @@ Sharing is dynamic, so that adding new methods to a descendant implies
adding it to the ancestor. adding it to the ancestor.
If duplicates checking is desired in the above example, the following If duplicates checking is desired in the above example, the following
form of the @code{:duplicates} option can be used instead: form of the @code{#:duplicates} option can be used instead:
@smalllisp @lisp
:duplicates (merge-generics check) #:duplicates (merge-generics check)
@end smalllisp @end lisp
@node Generic Function Internals @node Generic Function Internals
@subsection Generic Function Internals @subsubsection Generic Function Internals
@code{define-generic} calls @code{ensure-generic} to upgrade a @code{define-generic} calls @code{ensure-generic} to upgrade a
pre-existing procedure value, or @code{make} with metaclass pre-existing procedure value, or @code{make} with metaclass
@ -1705,7 +1607,7 @@ accessor, passing the setter generic function as the value of the
@code{#:setter} keyword. @code{#:setter} keyword.
@node Extending Guiles Primitives @node Extending Guiles Primitives
@subsection Extending Guile's Primitives @subsubsection Extending Guile's Primitives
When GOOPS is loaded, many of Guile's primitive procedures can be When GOOPS is loaded, many of Guile's primitive procedures can be
extended by giving them a generic function definition that operates extended by giving them a generic function definition that operates
@ -1752,7 +1654,7 @@ integrated into the core of Guile. Consequently, the
procedures described in this section may disappear as well. procedures described in this section may disappear as well.
@node Adding Methods to Generic Functions @node Adding Methods to Generic Functions
@section Adding Methods to Generic Functions @subsection Adding Methods to Generic Functions
@menu @menu
* Basic Method Definition:: * Basic Method Definition::
@ -1760,7 +1662,7 @@ procedures described in this section may disappear as well.
@end menu @end menu
@node Basic Method Definition @node Basic Method Definition
@subsection Basic Method Definition @subsubsection Basic Method Definition
To add a method to a generic function, use the @code{define-method} form. To add a method to a generic function, use the @code{define-method} form.
@ -1819,7 +1721,7 @@ invocation error handling, and generic function invocation in general,
see @ref{Invoking Generic Functions}. see @ref{Invoking Generic Functions}.
@node Method Definition Internals @node Method Definition Internals
@subsection Method Definition Internals @subsubsection Method Definition Internals
@code{define-method} @code{define-method}
@ -1906,7 +1808,7 @@ function.
@end deffn @end deffn
@node Invoking Generic Functions @node Invoking Generic Functions
@section Invoking Generic Functions @subsection Invoking Generic Functions
When a variable with a generic function definition appears as the first When a variable with a generic function definition appears as the first
element of a list that is being evaluated, the Guile evaluator tries element of a list that is being evaluated, the Guile evaluator tries
@ -1928,7 +1830,7 @@ may be applied subsequently if a method that is being applied calls
@end menu @end menu
@node Determining Which Methods to Apply @node Determining Which Methods to Apply
@subsection Determining Which Methods to Apply @subsubsection Determining Which Methods to Apply
[ *fixme* Sorry - this is the area of GOOPS that I understand least of [ *fixme* Sorry - this is the area of GOOPS that I understand least of
all, so I'm afraid I have to pass on this section. Would some other all, so I'm afraid I have to pass on this section. Would some other
@ -1959,7 +1861,7 @@ kind person consider filling it in? ]
@end deffn @end deffn
@node Handling Invocation Errors @node Handling Invocation Errors
@subsection Handling Invocation Errors @subsubsection Handling Invocation Errors
@deffn generic no-method @deffn generic no-method
@deffnx method no-method (gf <generic>) args @deffnx method no-method (gf <generic>) args
@ -1987,7 +1889,7 @@ default method calls @code{goops-error} with an appropriate message.
@end deffn @end deffn
@node Redefining a Class @node Redefining a Class
@section Redefining a Class @subsection Redefining a Class
Suppose that a class @code{<my-class>} is defined using @code{define-class} Suppose that a class @code{<my-class>} is defined using @code{define-class}
(@pxref{Basic Class Definition,, define-class}), with slots that have (@pxref{Basic Class Definition,, define-class}), with slots that have
@ -2002,7 +1904,7 @@ make}). What then happens if @code{<my-class>} is redefined by calling
@end menu @end menu
@node Default Class Redefinition Behaviour @node Default Class Redefinition Behaviour
@subsection Default Class Redefinition Behaviour @subsubsection Default Class Redefinition Behaviour
GOOPS' default answer to this question is as follows. GOOPS' default answer to this question is as follows.
@ -2055,7 +1957,7 @@ Also bear in mind that, like most of GOOPS' default behaviour, it can
be customized@dots{} be customized@dots{}
@node Customizing Class Redefinition @node Customizing Class Redefinition
@subsection Customizing Class Redefinition @subsubsection Customizing Class Redefinition
When @code{define-class} notices that a class is being redefined, When @code{define-class} notices that a class is being redefined,
it constructs the new class metaobject as usual, and then invokes the it constructs the new class metaobject as usual, and then invokes the
@ -2092,7 +1994,8 @@ is specialized for this metaclass:
@example @example
(define-class <can-be-nameless> (<class>)) (define-class <can-be-nameless> (<class>))
(define-method (class-redefinition (old <can-be-nameless>) (new <class>)) (define-method (class-redefinition (old <can-be-nameless>)
(new <class>))
new) new)
@end example @end example
@ -2119,7 +2022,7 @@ generic functions, and so on@dots{} The detailed protocol for all of these
is described in @ref{MOP Specification}. is described in @ref{MOP Specification}.
@node Changing the Class of an Instance @node Changing the Class of an Instance
@section Changing the Class of an Instance @subsection Changing the Class of an Instance
You can change the class of an existing instance by invoking the You can change the class of an existing instance by invoking the
generic function @code{change-class} with two arguments: the instance generic function @code{change-class} with two arguments: the instance
@ -2158,7 +2061,7 @@ invokes the @code{change-class} generic function for each existing
instance of the redefined class. instance of the redefined class.
@node Introspection @node Introspection
@section Introspection @subsection Introspection
@dfn{Introspection}, also known as @dfn{reflection}, is the name given @dfn{Introspection}, also known as @dfn{reflection}, is the name given
to the ability to obtain information dynamically about GOOPS metaobjects. to the ability to obtain information dynamically about GOOPS metaobjects.
@ -2197,7 +2100,7 @@ GOOPS equivalents --- to be obtained dynamically, at run time.
@end menu @end menu
@node Classes @node Classes
@subsection Classes @subsubsection Classes
@deffn {primitive procedure} class-name class @deffn {primitive procedure} class-name class
Return the name of class @var{class}. Return the name of class @var{class}.
@ -2257,7 +2160,7 @@ Return a list of all methods that use @var{class} or a subclass of
@end deffn @end deffn
@node Slots @node Slots
@subsection Slots @subsubsection Slots
@deffn procedure class-slot-definition class slot-name @deffn procedure class-slot-definition class slot-name
Return the slot definition for the slot named @var{slot-name} in class Return the slot definition for the slot named @var{slot-name} in class
@ -2338,7 +2241,7 @@ see @ref{Slot Options,, init-value}.
@end deffn @end deffn
@node Instances @node Instances
@subsection Instances @subsubsection Instances
@deffn {primitive procedure} class-of value @deffn {primitive procedure} class-of value
Return the GOOPS class of any Scheme @var{value}. Return the GOOPS class of any Scheme @var{value}.
@ -2359,7 +2262,7 @@ Implementation notes: @code{is-a?} uses @code{class-of} and
@var{object}. @var{object}.
@node Generic Functions @node Generic Functions
@subsection Generic Functions @subsubsection Generic Functions
@deffn {primitive procedure} generic-function-name gf @deffn {primitive procedure} generic-function-name gf
Return the name of generic function @var{gf}. Return the name of generic function @var{gf}.
@ -2371,7 +2274,7 @@ This is the value of the @var{gf} metaobject's @code{methods} slot.
@end deffn @end deffn
@node Generic Function Methods @node Generic Function Methods
@subsection Generic Function Methods @subsubsection Generic Function Methods
@deffn {primitive procedure} method-generic-function method @deffn {primitive procedure} method-generic-function method
Return the generic function that @var{method} belongs to. Return the generic function that @var{method} belongs to.
@ -2409,18 +2312,18 @@ Return an expression that prints to show the definition of method
@end deffn @end deffn
@node Miscellaneous Functions @node Miscellaneous Functions
@section Miscellaneous Functions @subsection Miscellaneous Functions
@menu @menu
* Administrative Functions:: * Administrative Functions::
* Error Handling:: * GOOPS Error Handling::
* Object Comparisons:: * Object Comparisons::
* Cloning Objects:: * Cloning Objects::
* Write and Display:: * Write and Display::
@end menu @end menu
@node Administrative Functions @node Administrative Functions
@subsection Administration Functions @subsubsection Administration Functions
This section describes administrative, non-technical GOOPS functions. This section describes administrative, non-technical GOOPS functions.
@ -2428,8 +2331,8 @@ This section describes administrative, non-technical GOOPS functions.
Return the current GOOPS version as a string, for example ``0.2''. Return the current GOOPS version as a string, for example ``0.2''.
@end deffn @end deffn
@node Error Handling @node GOOPS Error Handling
@subsection Error Handling @subsubsection Error Handling
The procedure @code{goops-error} is called to raise an appropriate error The procedure @code{goops-error} is called to raise an appropriate error
by the default methods of the following generic functions: by the default methods of the following generic functions:
@ -2464,7 +2367,7 @@ as done by @code{scm-error}.
@end deffn @end deffn
@node Object Comparisons @node Object Comparisons
@subsection Object Comparisons @subsubsection Object Comparisons
@deffn generic eqv? @deffn generic eqv?
@deffnx method eqv? ((x <top>) (y <top>)) @deffnx method eqv? ((x <top>) (y <top>))
@ -2493,7 +2396,7 @@ and the Guile reference manual.
@end deffn @end deffn
@node Cloning Objects @node Cloning Objects
@subsection Cloning Objects @subsubsection Cloning Objects
@deffn generic shallow-clone @deffn generic shallow-clone
@deffnx method shallow-clone (self <object>) @deffnx method shallow-clone (self <object>)
@ -2514,7 +2417,7 @@ or by reference.
@end deffn @end deffn
@node Write and Display @node Write and Display
@subsection Write and Display @subsubsection Write and Display
@deffn {primitive generic} write object port @deffn {primitive generic} write object port
@deffnx {primitive generic} display object port @deffnx {primitive generic} display object port
@ -2542,8 +2445,8 @@ methods - instances of the class @code{<method>}.
as the Guile primitive @code{write} and @code{display} functions. as the Guile primitive @code{write} and @code{display} functions.
@end deffn @end deffn
@node MOP Specification, Tutorial, Reference Manual, Top @node MOP Specification
@chapter MOP Specification @section MOP Specification
For an introduction to metaobjects and the metaobject protocol, For an introduction to metaobjects and the metaobject protocol,
see @ref{Metaobjects and the Metaobject Protocol}. see @ref{Metaobjects and the Metaobject Protocol}.
@ -2598,7 +2501,7 @@ what the caller expects to get as the applied method's return value.
@end menu @end menu
@node Class Definition @node Class Definition
@section Class Definition @subsection Class Definition
@code{define-class} (syntax) @code{define-class} (syntax)
@ -2731,7 +2634,7 @@ or @code{#:accessor} option.
@end itemize @end itemize
@node Instance Creation @node Instance Creation
@section Instance Creation @subsection Instance Creation
@code{make <class> . @var{initargs}} (method) @code{make <class> . @var{initargs}} (method)
@ -2752,13 +2655,13 @@ return value is ignored.
@end itemize @end itemize
@node Class Redefinition @node Class Redefinition
@section Class Redefinition @subsection Class Redefinition
The default @code{class-redefinition} method, specialized for classes The default @code{class-redefinition} method, specialized for classes
with the default metaclass @code{<class>}, has the following internal with the default metaclass @code{<class>}, has the following internal
protocol. protocol.
@code{class-redefinition @var{(old <class>)} @var{(new <class>)}} @code{class-redefinition (@var{old <class>}) (@var{new <class>})}
(method) (method)
@itemize @bullet @itemize @bullet
@ -2797,7 +2700,7 @@ to the modified instance, and initializes new slots, as described in
generic function invocation that can be used to customize the instance generic function invocation that can be used to customize the instance
update algorithm. update algorithm.
@code{change-class @var{(old-instance <object>)} @var{(new <class>)}} (method) @code{change-class (@var{old-instance <object>}) (@var{new <class>})} (method)
@itemize @bullet @itemize @bullet
@item @item
@ -2814,7 +2717,7 @@ nothing.
@end itemize @end itemize
@node Method Definition @node Method Definition
@section Method Definition @subsection Method Definition
@code{define-method} (syntax) @code{define-method} (syntax)
@ -2842,7 +2745,7 @@ theoretically handle adding methods to further types of target.
@end itemize @end itemize
@node Generic Function Invocation @node Generic Function Invocation
@section Generic Function Invocation @subsection Generic Function Invocation
[ *fixme* Description required here. ] [ *fixme* Description required here. ]
@ -2885,21 +2788,3 @@ theoretically handle adding methods to further types of target.
@item @item
@code{no-next-method} @code{no-next-method}
@end itemize @end itemize
@node Tutorial, Concept Index, MOP Specification, Top
@chapter Tutorial
@include goops-tutorial.texi
@node Concept Index, Function and Variable Index, Tutorial, Top
@unnumberedsec Concept Index
@printindex cp
@node Function and Variable Index, , Concept Index, Top
@unnumberedsec Function and Variable Index
@printindex fn
@summarycontents
@contents
@bye

View file

@ -4,22 +4,21 @@
@setfilename guile.info @setfilename guile.info
@settitle Guile Reference Manual @settitle Guile Reference Manual
@set guile @set guile
@set MANUAL-EDITION 1.1 @set MANUAL-REVISION 1
@c %**end of header @c %**end of header
@include version.texi @include version.texi
@include lib-version.texi @include lib-version.texi
@include effective-version.texi
@copying @copying
This reference manual documents Guile, GNU's Ubiquitous Intelligent This manual documents Guile version @value{VERSION}.
Language for Extensions. This is edition @value{MANUAL-EDITION}
corresponding to Guile @value{VERSION}.
Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005 Free Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2009 Free
Software Foundation. Software Foundation.
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.2 or under the terms of the GNU Free Documentation License, Version 1.2 or
any later version published by the Free Software Foundation; with the any later version published by the Free Software Foundation; with
no Invariant Sections, with the Front-Cover Texts being ``A GNU no Invariant Sections, with the Front-Cover Texts being ``A GNU
Manual,'' and with the Back-Cover Text ``You are free to copy and Manual,'' and with the Back-Cover Text ``You are free to copy and
modify this GNU Manual.''. A copy of the license is included in the modify this GNU Manual.''. A copy of the license is included in the
@ -137,7 +136,7 @@ x
@sp 10 @sp 10
@comment The title is printed in a large font. @comment The title is printed in a large font.
@title Guile Reference Manual @title Guile Reference Manual
@subtitle Edition @value{MANUAL-EDITION}, for use with Guile @value{VERSION} @subtitle Edition @value{EDITION}, revision @value{MANUAL-REVISION}, for use with Guile @value{VERSION}
@c @subtitle $Id: guile.texi,v 1.49 2008-03-19 22:51:23 ossau Exp $ @c @subtitle $Id: guile.texi,v 1.49 2008-03-19 22:51:23 ossau Exp $
@c See preface.texi for the list of authors @c See preface.texi for the list of authors
@ -177,6 +176,8 @@ x
* Guile Modules:: * Guile Modules::
* GOOPS::
* Guile Implementation:: * Guile Implementation::
* Autoconf Support:: * Autoconf Support::
@ -365,6 +366,8 @@ available through both Scheme and C interfaces.
@include scsh.texi @include scsh.texi
@include scheme-debugging.texi @include scheme-debugging.texi
@include goops.texi
@node Guile Implementation @node Guile Implementation
@chapter Guile Implementation @chapter Guile Implementation

View file

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Before After
Before After

View file

@ -80,6 +80,7 @@ To unbundle Guile use the instruction
zcat guile-@value{VERSION}.tar.gz | tar xvf - zcat guile-@value{VERSION}.tar.gz | tar xvf -
@end example @end example
@noindent
which will create a directory called @file{guile-@value{VERSION}} with which will create a directory called @file{guile-@value{VERSION}} with
all the sources. You can look at the file @file{INSTALL} for detailed all the sources. You can look at the file @file{INSTALL} for detailed
instructions on how to build and install Guile, but you should be able instructions on how to build and install Guile, but you should be able
@ -93,7 +94,7 @@ make install
@end example @end example
This will install the Guile executable @file{guile}, the Guile library This will install the Guile executable @file{guile}, the Guile library
@file{-lguile} and various associated header files and support @file{libguile} and various associated header files and support
libraries. It will also install the Guile tutorial and reference libraries. It will also install the Guile tutorial and reference
manual. manual.
@ -101,14 +102,14 @@ manual.
Since this manual frequently refers to the Scheme ``standard'', also Since this manual frequently refers to the Scheme ``standard'', also
known as R5RS, or the known as R5RS, or the
@iftex @tex
``Revised$^5$ Report on the Algorithmic Language Scheme'', ``Revised$^5$ Report on the Algorithmic Language Scheme'',
@end iftex @end tex
@ifnottex @ifnottex
``Revised^5 Report on the Algorithmic Language Scheme'', ``Revised^5 Report on the Algorithmic Language Scheme'',
@end ifnottex @end ifnottex
we have included the report in the Guile distribution; we have included the report in the Guile distribution; see
@xref{Top, , Introduction, r5rs, Revised(5) Report on the Algorithmic @ref{Top, , Introduction, r5rs, Revised(5) Report on the Algorithmic
Language Scheme}. Language Scheme}.
This will also be installed in your info directory. This will also be installed in your info directory.
@ -471,11 +472,12 @@ You can get the version number by invoking the command
@example @example
$ guile --version $ guile --version
Guile 1.9.0 Guile 1.9.0
Copyright (c) 1995, 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation Copyright (c) 1995, 1996, 1997, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007, 2008, 2009 Free Software Foundation
Guile may be distributed under the terms of the GNU Lesser General Guile may be distributed under the terms of the GNU Lesser General
Public Licence. For details, see the files `COPYING.LESSER' and Public Licence. For details, see the files `COPYING.LESSER' and
`COPYING', which are included in the Guile distribution. There is no `COPYING', which are included in the Guile distribution. There is
warranty, to the extent permitted by law. no warranty, to the extent permitted by law.
@end example @end example
@item @item

View file

@ -94,11 +94,11 @@ we are going to call the function @code{init_bessel} which will make
@file{.so} when invoking @code{load-extension}. The right extension for @file{.so} when invoking @code{load-extension}. The right extension for
the host platform will be provided automatically. the host platform will be provided automatically.
@smalllisp @lisp
(load-extension "libguile-bessel" "init_bessel") (load-extension "libguile-bessel" "init_bessel")
(j0 2) (j0 2)
@result{} 0.223890779141236 @result{} 0.223890779141236
@end smalllisp @end lisp
For this to work, @code{load-extension} must be able to find For this to work, @code{load-extension} must be able to find
@file{libguile-bessel}, of course. It will look in the places that @file{libguile-bessel}, of course. It will look in the places that

View file

@ -173,7 +173,8 @@ creating ./config.status
creating Makefile creating Makefile
$ make $ make
gcc -c -I/usr/local/include simple-guile.c gcc -c -I/usr/local/include simple-guile.c
gcc simple-guile.o -L/usr/local/lib -lguile -lqthreads -lpthread -lm -o simple-guile gcc simple-guile.o -L/usr/local/lib -lguile -lqthreads -lpthread -lm
-o simple-guile
$ ./simple-guile $ ./simple-guile
guile> (+ 1 2 3) guile> (+ 1 2 3)
6 6

View file

@ -28,7 +28,7 @@ datatypes described here.)
@menu @menu
* Describing a New Type:: * Describing a New Type::
* Creating Instances:: * Creating Smob Instances::
* Type checking:: * Type checking::
* Garbage Collecting Smobs:: * Garbage Collecting Smobs::
* Garbage Collecting Simple Smobs:: * Garbage Collecting Simple Smobs::
@ -132,8 +132,8 @@ init_image_type (void)
@end example @end example
@node Creating Instances @node Creating Smob Instances
@subsection Creating Instances @subsection Creating Smob Instances
Normally, smobs can have one @emph{immediate} word of data. This word Normally, smobs can have one @emph{immediate} word of data. This word
stores either a pointer to an additional memory block that holds the stores either a pointer to an additional memory block that holds the
@ -211,7 +211,8 @@ make_image (SCM name, SCM s_width, SCM s_height)
/* Step 1: Allocate the memory block. /* Step 1: Allocate the memory block.
*/ */
image = (struct image *) scm_gc_malloc (sizeof (struct image), "image"); image = (struct image *)
scm_gc_malloc (sizeof (struct image), "image");
/* Step 2: Initialize it with straight code. /* Step 2: Initialize it with straight code.
*/ */
@ -228,7 +229,8 @@ make_image (SCM name, SCM s_width, SCM s_height)
/* Step 4: Finish the initialization. /* Step 4: Finish the initialization.
*/ */
image->name = name; image->name = name;
image->pixels = scm_gc_malloc (width * height, "image pixels"); image->pixels =
scm_gc_malloc (width * height, "image pixels");
return smob; return smob;
@} @}
@ -404,7 +406,9 @@ free_image (SCM image_smob)
@{ @{
struct image *image = (struct image *) SCM_SMOB_DATA (image_smob); struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
scm_gc_free (image->pixels, image->width * image->height, "image pixels"); scm_gc_free (image->pixels,
image->width * image->height,
"image pixels");
scm_gc_free (image, sizeof (struct image), "image"); scm_gc_free (image, sizeof (struct image), "image");
return 0; return 0;
@ -583,7 +587,8 @@ make_image (SCM name, SCM s_width, SCM s_height)
/* Step 1: Allocate the memory block. /* Step 1: Allocate the memory block.
*/ */
image = (struct image *) scm_gc_malloc (sizeof (struct image), "image"); image = (struct image *)
scm_gc_malloc (sizeof (struct image), "image");
/* Step 2: Initialize it with straight code. /* Step 2: Initialize it with straight code.
*/ */
@ -600,7 +605,8 @@ make_image (SCM name, SCM s_width, SCM s_height)
/* Step 4: Finish the initialization. /* Step 4: Finish the initialization.
*/ */
image->name = name; image->name = name;
image->pixels = scm_gc_malloc (width * height, "image pixels"); image->pixels =
scm_gc_malloc (width * height, "image pixels");
return smob; return smob;
@} @}
@ -642,7 +648,9 @@ free_image (SCM image_smob)
@{ @{
struct image *image = (struct image *) SCM_SMOB_DATA (image_smob); struct image *image = (struct image *) SCM_SMOB_DATA (image_smob);
scm_gc_free (image->pixels, image->width * image->height, "image pixels"); scm_gc_free (image->pixels,
image->width * image->height,
"image pixels");
scm_gc_free (image, sizeof (struct image), "image"); scm_gc_free (image, sizeof (struct image), "image");
return 0; return 0;

View file

@ -2072,9 +2072,9 @@ The following procedures are similar to the @code{popen} and
@code{pclose} system routines. The code is in a separate ``popen'' @code{pclose} system routines. The code is in a separate ``popen''
module: module:
@smalllisp @lisp
(use-modules (ice-9 popen)) (use-modules (ice-9 popen))
@end smalllisp @end lisp
@findex popen @findex popen
@deffn {Scheme Procedure} open-pipe command mode @deffn {Scheme Procedure} open-pipe command mode

View file

@ -7,12 +7,9 @@
@node Preface @node Preface
@chapter Preface @chapter Preface
This reference manual documents Guile, GNU's Ubiquitous Intelligent This manual documents version @value{VERSION} of Guile, GNU's
Language for Extensions. It describes how to use Guile in many useful Ubiquitous Intelligent Language for Extensions. It describes how to
and interesting ways. use Guile in many useful and interesting ways.
This is edition @value{MANUAL-EDITION} of the reference manual, and
corresponds to Guile version @value{VERSION}.
@menu @menu
* Manual Layout:: * Manual Layout::
@ -25,7 +22,7 @@ corresponds to Guile version @value{VERSION}.
@node Manual Layout @node Manual Layout
@section Layout of this Manual @section Layout of this Manual
The manual is divided into five chapters. The manual is divided into the following chapters.
@table @strong @table @strong
@item Chapter 1: Introduction to Guile @item Chapter 1: Introduction to Guile
@ -38,7 +35,7 @@ the later parts of the manual. This part also explains how to obtain
and install new versions of Guile, and how to report bugs effectively. and install new versions of Guile, and how to report bugs effectively.
@item Chapter 2: Programming in Scheme @item Chapter 2: Programming in Scheme
This part provides an overview over programming in Scheme with Guile. This part provides an overview of programming in Scheme with Guile.
It covers how to invoke the @code{guile} program from the command-line It covers how to invoke the @code{guile} program from the command-line
and how to write scripts in Scheme. It also gives an introduction and how to write scripts in Scheme. It also gives an introduction
into the basic ideas of Scheme itself and to the various extensions into the basic ideas of Scheme itself and to the various extensions
@ -61,6 +58,10 @@ Describes some important modules, distributed as part of the Guile
distribution, that extend the functionality provided by the Guile distribution, that extend the functionality provided by the Guile
Scheme core. Scheme core.
@item Chapter 6: GOOPS
Describes GOOPS, an object oriented extension to Guile that provides
classes, multiple inheritance and generic functions.
@end table @end table
@ -72,7 +73,7 @@ We use some conventions in this manual.
@itemize @bullet @itemize @bullet
@item @item
For some procedures, notably type predicates, we use @dfn{iff} to mean For some procedures, notably type predicates, we use ``iff'' to mean
``if and only if''. The construct is usually something like: `Return ``if and only if''. The construct is usually something like: `Return
@var{val} iff @var{condition}', where @var{val} is usually @var{val} iff @var{condition}', where @var{val} is usually
``@nicode{#t}'' or ``non-@nicode{#f}''. This typically means that ``@nicode{#t}'' or ``non-@nicode{#f}''. This typically means that
@ -144,6 +145,9 @@ filling out a lot of the documentation of Scheme data types, control
mechanisms and procedures. In addition, he wrote the documentation mechanisms and procedures. In addition, he wrote the documentation
for Guile's SRFI modules and modules associated with the Guile REPL. for Guile's SRFI modules and modules associated with the Guile REPL.
The chapter on GOOPS was written by Christian Lynbech, Mikael
Djurfeldt and Neil Jerram.
@node Guile License @node Guile License
@section The Guile License @section The Guile License
@cindex copying @cindex copying
@ -179,7 +183,7 @@ C code linking to the Guile readline module is subject to the terms of
that module. Basically such code must be published on Free terms. that module. Basically such code must be published on Free terms.
Scheme level code written to be run by Guile (but not derived from Scheme level code written to be run by Guile (but not derived from
Guile itself) is not resticted in any way, and may be published on any Guile itself) is not restricted in any way, and may be published on any
terms. We encourage authors to publish on Free terms. terms. We encourage authors to publish on Free terms.
You must be aware there is no warranty whatsoever for Guile. This is You must be aware there is no warranty whatsoever for Guile. This is

View file

@ -14,9 +14,9 @@ call to that procedure is reported to the user during a program run.
The idea is that you can mark a collection of procedures for tracing, The idea is that you can mark a collection of procedures for tracing,
and Guile will subsequently print out a line of the form and Guile will subsequently print out a line of the form
@smalllisp @lisp
| | [@var{procedure} @var{args} @dots{}] | | [@var{procedure} @var{args} @dots{}]
@end smalllisp @end lisp
whenever a marked procedure is about to be applied to its arguments. whenever a marked procedure is about to be applied to its arguments.
This can help a programmer determine whether a function is being called This can help a programmer determine whether a function is being called
@ -27,7 +27,7 @@ how the traced applications are or are not tail recursive with respect
to each other. Thus, a trace of a non-tail recursive factorial to each other. Thus, a trace of a non-tail recursive factorial
implementation looks like this: implementation looks like this:
@smalllisp @lisp
[fact1 4] [fact1 4]
| [fact1 3] | [fact1 3]
| | [fact1 2] | | [fact1 2]
@ -38,11 +38,11 @@ implementation looks like this:
| | 2 | | 2
| 6 | 6
24 24
@end smalllisp @end lisp
While a typical tail recursive implementation would look more like this: While a typical tail recursive implementation would look more like this:
@smalllisp @lisp
[fact2 4] [fact2 4]
[facti 1 4] [facti 1 4]
[facti 4 3] [facti 4 3]
@ -50,7 +50,7 @@ While a typical tail recursive implementation would look more like this:
[facti 24 1] [facti 24 1]
[facti 24 0] [facti 24 0]
24 24
@end smalllisp @end lisp
@deffn {Scheme Procedure} trace procedure @deffn {Scheme Procedure} trace procedure
Enable tracing for @code{procedure}. While a program is being run, Enable tracing for @code{procedure}. While a program is being run,

View file

@ -390,7 +390,11 @@ this:
@noindent @noindent
This is a valid procedure invocation expression, and its result is the This is a valid procedure invocation expression, and its result is the
string @code{"Name=FSF:Address=Cambridge"}. string:
@lisp
"Name=FSF:Address=Cambridge"
@end lisp
It is more common, though, to store the procedure value in a variable --- It is more common, though, to store the procedure value in a variable ---

View file

@ -19,8 +19,8 @@ For information about scsh see
The closest emulation of scsh can be obtained by running: The closest emulation of scsh can be obtained by running:
@smalllisp @lisp
(load-from-path "scsh/init") (load-from-path "scsh/init")
@end smalllisp @end lisp
See the USAGE file supplied with guile-scsh for more details. See the USAGE file supplied with guile-scsh for more details.

View file

@ -4,7 +4,6 @@
@c Free Software Foundation, Inc. @c Free Software Foundation, Inc.
@c See the file guile.texi for copying conditions. @c See the file guile.texi for copying conditions.
@page
@node SLIB @node SLIB
@section SLIB @section SLIB
@cindex SLIB @cindex SLIB
@ -12,9 +11,9 @@
Before the SLIB facilities can be used, the following Scheme expression Before the SLIB facilities can be used, the following Scheme expression
must be executed: must be executed:
@smalllisp @lisp
(use-modules (ice-9 slib)) (use-modules (ice-9 slib))
@end smalllisp @end lisp
@findex require @findex require
@code{require} can then be used in the usual way (@pxref{Require,,, @code{require} can then be used in the usual way (@pxref{Require,,,
@ -64,7 +63,7 @@ Alternatively, you can create a symlink in the Guile directory to SLIB,
e.g.: e.g.:
@example @example
ln -s /usr/local/lib/slib /usr/local/share/guile/1.8/slib ln -s /usr/local/lib/slib /usr/local/share/guile/@value{EFFECTIVE-VERSION}/slib
@end example @end example
@item @item
@ -78,7 +77,7 @@ guile> (quit)
@end example @end example
The catalog data should now be in The catalog data should now be in
@file{/usr/local/share/guile/1.8/slibcat}. @file{/usr/local/share/guile/@value{EFFECTIVE-VERSION}/slibcat}.
If instead you get an error such as: If instead you get an error such as:
@ -104,11 +103,11 @@ It is usually installed as an extra package in SLIB.
You can use Guile's interface to SLIB to invoke Jacal: You can use Guile's interface to SLIB to invoke Jacal:
@smalllisp @lisp
(use-modules (ice-9 slib)) (use-modules (ice-9 slib))
(slib:load "math") (slib:load "math")
(math) (math)
@end smalllisp @end lisp
@noindent @noindent
For complete documentation on Jacal, please read the Jacal manual. If For complete documentation on Jacal, please read the Jacal manual. If

View file

@ -232,8 +232,8 @@ is a expression suitable for initializing a new variable.
For procedures, you can use @code{SCM_DEFINE} for most purposes. Use For procedures, you can use @code{SCM_DEFINE} for most purposes. Use
@code{SCM_PROC} along with @code{SCM_REGISTER_PROC} when you don't @code{SCM_PROC} along with @code{SCM_REGISTER_PROC} when you don't
want to be bothered with docstrings. Use @code{SCM_GPROC} for generic want to be bothered with docstrings. Use @code{SCM_GPROC} for generic
functions (@pxref{Creating Generic Functions,,, goops, GOOPS}). All functions (@pxref{Creating Generic Functions}). All procedures are
procedures are declared with return type @code{SCM}. declared with return type @code{SCM}.
For everything else, use the appropriate macro (@code{SCM_SYMBOL} for For everything else, use the appropriate macro (@code{SCM_SYMBOL} for
symbols, and so on). Without "_GLOBAL_", the declarations are symbols, and so on). Without "_GLOBAL_", the declarations are
@ -364,7 +364,7 @@ of the form:
@example @example
(define-module (scripts PROGRAM) (define-module (scripts PROGRAM)
:export (PROGRAM)) #:export (PROGRAM))
@end example @end example
Feel free to export other definitions useful in the module context. Feel free to export other definitions useful in the module context.

View file

@ -159,17 +159,19 @@ The structure of the fixed part of an application frame is as follows:
@example @example
Stack Stack
| | <- fp + bp->nargs + bp->nlocs + 3 | ... |
+------------------+ = SCM_FRAME_UPPER_ADDRESS (fp) | Intermed. val. 0 | <- fp + bp->nargs + bp->nlocs = SCM_FRAME_UPPER_ADDRESS (fp)
| Return address | +==================+
| MV return address| | Local variable 1 |
| Dynamic link | <- fp + bp->nargs + bp->nlocs
| Local variable 1 | = SCM_FRAME_DATA_ADDRESS (fp)
| Local variable 0 | <- fp + bp->nargs | Local variable 0 | <- fp + bp->nargs
| Argument 1 | | Argument 1 |
| Argument 0 | <- fp | Argument 0 | <- fp
| Program | <- fp - 1 | Program | <- fp - 1
+------------------+ = SCM_FRAME_LOWER_ADDRESS (fp) +------------------+
| Return address |
| MV return address|
| Dynamic link | <- fp - 4 = SCM_FRAME_DATA_ADDRESS (fp) = SCM_FRAME_LOWER_ADDRESS (fp)
+==================+
| | | |
@end example @end example
@ -306,19 +308,19 @@ scheme@@(guile-user)> (define (foo a) (lambda (b) (list foo a b)))
scheme@@(guile-user)> ,x foo scheme@@(guile-user)> ,x foo
Disassembly of #<program foo (a)>: Disassembly of #<program foo (a)>:
0 (object-ref 1) ;; #<program b7e478b0 at <unknown port>:0:16 (b)> 0 (object-ref 1) ;; #<program b7e478b0 at <unknown port>:0:16 (b)>
2 (local-ref 0) ;; `a' (arg) 2 (local-ref 0) ;; `a' (arg)
4 (vector 0 1) ;; 1 element 4 (vector 0 1) ;; 1 element
7 (make-closure) 7 (make-closure)
8 (return) 8 (return)
---------------------------------------- ----------------------------------------
Disassembly of #<program b7e478b0 at <unknown port>:0:16 (b)>: Disassembly of #<program b7e478b0 at <unknown port>:0:16 (b)>:
0 (toplevel-ref 1) ;; `foo' 0 (toplevel-ref 1) ;; `foo'
2 (free-ref 0) ;; (closure variable) 2 (free-ref 0) ;; (closure variable)
4 (local-ref 0) ;; `b' (arg) 4 (local-ref 0) ;; `b' (arg)
6 (list 0 3) ;; 3 elements at (unknown file):0:28 6 (list 0 3) ;; 3 elements at (unknown file):0:28
9 (return) 9 (return)
@end smallexample @end smallexample
@ -649,32 +651,30 @@ closures.
@node Procedural Instructions @node Procedural Instructions
@subsubsection Procedural Instructions @subsubsection Procedural Instructions
@deffn Instruction return @deffn Instructions new-frame
Free the program's frame, returning the top value from the stack to Push a new frame on the stack, reserving space for the dynamic link,
the current continuation. (The stack should have exactly one value on return address, and the multiple-values return address. The frame
it.) pointer is not yet updated, because the frame is not yet active -- it
has to be patched by a @code{call} instruction to get the return
Specifically, the @code{sp} is decremented to one below the current address.
@code{fp}, the @code{ip} is reset to the current return address, the
@code{fp} is reset to the value of the current dynamic link, and then
the top item on the stack (formerly the procedure being applied) is
set to the returned value.
@end deffn @end deffn
@deffn Instruction call nargs @deffn Instruction call nargs
Call the procedure located at @code{sp[-nargs]} with the @var{nargs} Call the procedure located at @code{sp[-nargs]} with the @var{nargs}
arguments located from @code{sp[-nargs + 1]} to @code{sp[0]}. arguments located from @code{sp[-nargs + 1]} to @code{sp[0]}.
For compiled procedures, this instruction sets up a new stack frame, This instruction requires that a new frame be pushed on the stack
as described in @ref{Stack Layout}, and then dispatches to the first before the procedure, via @code{new-frame}. @xref{Stack Layout}, for
instruction in the called procedure, relying on the called procedure more information. It patches up that frame with the current @code{ip}
to return one value to the newly-created continuation. Because the new as the return address, then dispatches to the first instruction in the
frame pointer will point to sp[-nargs + 1], the arguments don't have called procedure, relying on the called procedure to return one value
to be shuffled around -- they are already in place. to the newly-created continuation. Because the new frame pointer will
point to sp[-nargs + 1], the arguments don't have to be shuffled
around -- they are already in place.
For non-compiled procedures (continuations, primitives, and For non-compiled procedures (continuations, primitives, and
interpreted procedures), @code{call} will pop the procedure and interpreted procedures), @code{call} will pop the frame, procedure,
arguments off the stack, and push the result of calling and arguments off the stack, and push the result of calling
@code{scm_apply}. @code{scm_apply}.
@end deffn @end deffn
@ -682,10 +682,10 @@ arguments off the stack, and push the result of calling
Like @code{call}, but reusing the current continuation. This Like @code{call}, but reusing the current continuation. This
instruction implements tail calls as required by RnRS. instruction implements tail calls as required by RnRS.
For compiled procedures, that means that @code{goto/args} reuses the For compiled procedures, that means that @code{goto/args} simply
current frame instead of building a new one. The @code{goto/*} shuffles down the procedure and arguments to the current stack frame.
instruction family is named as it is because tail calls are equivalent The @code{goto/*} instruction family is named as it is because tail
to @code{goto}, along with relabeled variables. calls are equivalent to @code{goto}, along with relabeled variables.
For non-VM procedures, the result is the same, but the current VM For non-VM procedures, the result is the same, but the current VM
invocation remains on the C stack. True tail calls are not currently invocation remains on the C stack. True tail calls are not currently
@ -708,15 +708,6 @@ These instructions are used in the implementation of multiple value
returns, where the actual number of values is pushed on the stack. returns, where the actual number of values is pushed on the stack.
@end deffn @end deffn
@deffn Instruction call/cc
@deffnx Instruction goto/cc
Capture the current continuation, and then call (or tail-call) the
procedure on the top of the stack, with the continuation as the
argument.
Both the VM continuation and the C continuation are captured.
@end deffn
@deffn Instruction mv-call nargs offset @deffn Instruction mv-call nargs offset
Like @code{call}, except that a multiple-value continuation is created Like @code{call}, except that a multiple-value continuation is created
in addition to a single-value continuation. in addition to a single-value continuation.
@ -729,6 +720,18 @@ the stack to be the number of values, and below that values
themselves, pushed separately. themselves, pushed separately.
@end deffn @end deffn
@deffn Instruction return
Free the program's frame, returning the top value from the stack to
the current continuation. (The stack should have exactly one value on
it.)
Specifically, the @code{sp} is decremented to one below the current
@code{fp}, the @code{ip} is reset to the current return address, the
@code{fp} is reset to the value of the current dynamic link, and then
the top item on the stack (formerly the procedure being applied) is
set to the returned value.
@end deffn
@deffn Instruction return/values nvalues @deffn Instruction return/values nvalues
Return the top @var{nvalues} to the current continuation. Return the top @var{nvalues} to the current continuation.
@ -763,6 +766,19 @@ be 1 (to indicate that one of the bindings was a rest argument).
Signals an error if there is an insufficient number of values. Signals an error if there is an insufficient number of values.
@end deffn @end deffn
@deffn Instruction call/cc
@deffnx Instruction goto/cc
Capture the current continuation, and then call (or tail-call) the
procedure on the top of the stack, with the continuation as the
argument.
@code{call/cc} does not require a @code{new-frame} to be pushed on the
stack, as @code{call} does, because it needs to capture the stack
before the frame is pushed.
Both the VM continuation and the C continuation are captured.
@end deffn
@node Data Control Instructions @node Data Control Instructions
@subsubsection Data Control Instructions @subsubsection Data Control Instructions
@ -838,32 +854,6 @@ popping off those values and pushing on the resulting vector. @var{n}
is a two-byte value, like in @code{vector}. is a two-byte value, like in @code{vector}.
@end deffn @end deffn
@deffn Instruction mark
Pushes a special value onto the stack that other stack instructions
like @code{list-mark} can use.
@end deffn
@deffn Instruction list-mark
Create a list from values from the stack, as in @code{list}, but
instead of knowing beforehand how many there will be, keep going until
we see a @code{mark} value.
@end deffn
@deffn Instruction cons-mark
As the scheme procedure @code{cons*} is to the scheme procedure
@code{list}, so the instruction @code{cons-mark} is to the instruction
@code{list-mark}.
@end deffn
@deffn Instruction vector-mark
Like @code{list-mark}, but makes a vector instead of a list.
@end deffn
@deffn Instruction list-break
The opposite of @code{list}: pops a value, which should be a list, and
pushes its elements on the stack.
@end deffn
@node Miscellaneous Instructions @node Miscellaneous Instructions
@subsubsection Miscellaneous Instructions @subsubsection Miscellaneous Instructions

225
emacs/gds-faq.txt Executable file
View file

@ -0,0 +1,225 @@
* Installation
** How do I install guile-debugging?
After unpacking the .tar.gz file, run the usual sequence of commands:
$ ./configure
$ make
$ sudo make install
Then you need to make sure that the directory where guile-debugging's
Scheme files were installed is included in your Guile's load path.
(The sequence above will usually install guile-debugging under
/usr/local, and /usr/local is not in Guile's load path by default,
unless Guile itself was installed under /usr/local.) You can discover
your Guile's default load path by typing
$ guile -q -c '(begin (write %load-path) (newline))'
There are two ways to add guile-debugging's installation directory to
Guile's load path, if it isn't already there.
1. Edit or create the `init.scm' file, which Guile reads on startup,
so that it includes a line like this:
(set! %load-path (cons "/usr/local/share/guile" %load-path))
but with "/usr/local" replaced by the prefix that you installed
guile-debugging under, if not /usr/local.
The init.scm file must be installed (if it does not already exist
there) in one of the directories in Guile's default load-path.
2. Add this line to your .emacs file:
(setq gds-scheme-directory "/usr/local/share/guile")
before the `require' or `load' line that loads GDS, but with
"/usr/local" replaced by the prefix that you installed
guile-debugging under, if not /usr/local.
Finally, if you want guile-debugging's GDS interface to be loaded
automatically whenever you run Emacs, add this line to your .emacs:
(require 'gds)
* Troubleshooting
** "error in process filter" when starting Emacs (or loading GDS)
This is caused by an internal error in GDS's Scheme code, for which a
backtrace will have appeared in the gds-debug buffer, so please switch
to the gds-debug buffer and see what it says there.
The most common cause is a load path problem: Guile cannot find GDS's
Scheme code because it is not in the known load path. In this case
you should see the error message "no code for module" somewhere in the
backtrace. If you see this, please try the remedies described in `How
do I install guile-debugging?' above, then restart Emacs and see if
the problem has been cured.
If you don't see "no code for module", or if the described remedies
don't fix the problem, please send the contents of the gds-debug
buffer to me at <neil@ossau.uklinux.net>, so I can debug the problem.
If you don't see a backtrace at all in the gds-debug buffer, try the
next item ...
** "error in process filter" at some other time
This is caused by an internal error somewhere in GDS's Emacs Lisp
code. If possible, please
- switch on the `debug-on-error' option (M-x set-variable RET
debug-on-error RET t RET)
- do whatever you were doing so that the same error happens again
- send the Emacs Lisp stack trace which pops up to me at
<neil@ossau.uklinux.net>.
If that doesn't work, please just mail me with as much detail as
possible of what you were doing when the error occurred.
* GDS Features
** How do I inspect variable values?
Type `e' followed by the name of the variable, then <RET>. This
works whenever GDS is displaying a stack for an error at at a
breakpoint. (You can actually `e' to evaluate any expression in the
local environment of the selected stack frame; inspecting variables is
the special case of this where the expression is only a variable name.)
If GDS is displaying the associated source code in the window above or
below the stack, you can see the values of any variables in the
highlighted code just by hovering your mouse over them.
** How do I change a variable's value?
Type `e' and then `(set! VARNAME NEWVAL)', where VARNAME is the name
of the variable you want to set and NEWVAL is an expression which
Guile can evaluate to get the new value. This works whenever GDS is
displaying a stack for an error at at a breakpoint. The setting will
take effect in the local environment of the selected stack frame.
** How do I change the expression that Guile is about to evaluate?
Type `t' followed by the expression that you want Guile to evaluate
instead, then <RET>.
Then type one of the commands that tells Guile to continue execution.
(Tweaking expressions, as described here, is only supported by the
latest CVS version of Guile. The GDS stack display tells you when
tweaking is possible by adding "(tweakable)" to the first line of the
stack window.)
** How do I return a value from the current stack frame different to what the evaluator has calculated?
You have to be at the normal exit of the relevant frame first, so if
GDS is not already showing you the normally calculated return value,
type `o' to finish the evaluation of the selected frame.
Then type `t' followed by the value you want to return, and <RET>.
The value that you type can be any expression, but note that it will
not be evaluated before being returned; for example if you type `(+ 2
3)', the return value will be a three-element list, not 5.
Finally type one of the commands that tells Guile to continue
execution.
(Tweaking return values, as described here, is only supported by the
latest CVS version of Guile. The GDS stack display tells you when
tweaking is possible by adding "(tweakable)" to the first line of the
stack window.)
** How do I step over a line of code?
Scheme isn't organized by lines, so it doesn't really make sense to
think of stepping over lines. Instead please see the next entry on
stepping over expressions.
** How do I step over an expression?
It depends what you mean by "step over". If you mean that you want
Guile to evaluate that expression normally, but then show you its
return value, type `o', which does exactly that.
If you mean that you want to skip the evaluation of that expression
(for example because it has side effects that you don't want to
happen), use `t' to change the expression to something else which
Guile will evaluate instead.
There has to be a substitute expression so Guile can calculate a value
to return to the calling frame. If you know at a particular point
that the return value is not important, you can type `t #f <RET>' or
`t 0 <RET>'.
See `How do I change the expression that Guile is about to evaluate?'
above for more on using `t'.
** How do I move up and down the call stack?
Type `u' to move up and `d' to move down. "Up" in GDS means to a more
"inner" frame, and "down" means to a more "outer" frame.
** How do I run until the next breakpoint?
Type `g' (for "go").
** How do I run until the end of the selected stack frame?
Type `o'.
** How do I set a breakpoint?
First identify the code that you want to set the breakpoint in, and
what kind of breakpoint you want. To set a breakpoint on entry to a
top level procedure, move the cursor to anywhere in the procedure
definition, and make sure that the region/mark is inactive. To set a
breakpoint on a particular expression (or sequence of expressions) set
point and mark so that the region covers the opening parentheses of
all the target expressions.
Then type ...
`C-c C-b d' for a `debug' breakpoint, which means that GDS will
display the stack when the breakpoint is hit
`C-c C-b t' for a `trace' breakpoint, which means that the start and
end of the relevant procedure or expression(s) will be traced to the
*GDS Trace* buffer
`C-c C-b T' for a `trace-subtree' breakpoint, which means that every
evaluation step involved in the evaluation of the relevant procedure
or expression(s) will be traced to the *GDS Trace* buffer.
You can also type `C-x <SPC>', which does the same as one of the
above, depending on the value of `gds-default-breakpoint-type'.
** How do I clear a breakpoint?
Select a region containing the breakpoints that you want to clear, and
type `C-c C-b <DEL>'.
** How do I trace calls to a particular procedure or evaluations of a particular expression?
In GDS this means setting a breakpoint whose type is `trace' or
`trace-subtree'. See `How do I set a breakpoint?' above.
* Development
** How can I follow or contribute to guile-debugging's development?
guile-debugging is hosted at http://gna.org, so please see the project
page there. Feel free to raise bugs, tasks containing patches or
feature requests, and so on. You can also write directly to me by
email: <neil@ossau.uklinux.net>.
Local Variables:
mode: outline
End:

View file

@ -206,23 +206,28 @@ Emacs to display an error or trap so that the user can debug it."
"-q" "-q"
"--debug" "--debug"
"-c" "-c"
code)) code)))
(client nil))
;; Note that this process can be killed automatically on Emacs ;; Note that this process can be killed automatically on Emacs
;; exit. ;; exit.
(process-kill-without-query proc) (process-kill-without-query proc)
;; Set up a process filter to catch the new client's number. ;; Set up a process filter to catch the new client's number.
(set-process-filter proc (set-process-filter proc
(lambda (proc string) (lambda (proc string)
(setq client (string-to-number string))
(if (process-buffer proc) (if (process-buffer proc)
(with-current-buffer (process-buffer proc) (with-current-buffer (process-buffer proc)
(insert string))))) (insert string)
(or gds-client
(save-excursion
(goto-char (point-min))
(setq gds-client
(condition-case nil
(read (current-buffer))
(error nil)))))))))
;; Accept output from the new process until we have its number. ;; Accept output from the new process until we have its number.
(while (not client) (while (not (with-current-buffer (process-buffer proc) gds-client))
(accept-process-output proc)) (accept-process-output proc))
;; Return the new process's client number. ;; Return the new process's client number.
client)) (with-current-buffer (process-buffer proc) gds-client)))
;;;; Evaluating code. ;;;; Evaluating code.

View file

@ -43,25 +43,24 @@
:group 'gds :group 'gds
:type '(choice (const :tag "nil" nil) directory)) :type '(choice (const :tag "nil" nil) directory))
(defun gds-start-server (procname port-or-path protocol-handler &optional bufname) (defun gds-start-server (procname unix-socket-name tcp-port protocol-handler)
"Start a GDS server process called PROCNAME, listening on TCP port "Start a GDS server process called PROCNAME, listening on Unix
or Unix domain socket PORT-OR-PATH. PROTOCOL-HANDLER should be a domain socket UNIX-SOCKET-NAME and TCP port number TCP-PORT.
function that accepts and processes one protocol form. Optional arg PROTOCOL-HANDLER should be a function that accepts and processes
BUFNAME specifies the name of the buffer that is used for process one protocol form."
output; if not specified the buffer name is the same as the process (with-current-buffer (get-buffer-create procname)
name."
(with-current-buffer (get-buffer-create (or bufname procname))
(erase-buffer) (erase-buffer)
(let* ((code (format "(begin (let* ((code (format "(begin
%s %s
(use-modules (ice-9 gds-server)) (use-modules (ice-9 gds-server))
(run-server %S))" (run-server %S %S))"
(if gds-scheme-directory (if gds-scheme-directory
(concat "(set! %load-path (cons " (concat "(set! %load-path (cons "
(format "%S" gds-scheme-directory) (format "%S" gds-scheme-directory)
" %load-path))") " %load-path))")
"") "")
port-or-path)) unix-socket-name
tcp-port))
(process-connection-type nil) ; use a pipe (process-connection-type nil) ; use a pipe
(proc (start-process procname (proc (start-process procname
(current-buffer) (current-buffer)

166
emacs/gds-test.el Normal file
View file

@ -0,0 +1,166 @@
;; Test utility code.
(defun gds-test-execute-keys (keys &optional keys2)
(execute-kbd-macro (apply 'vector (listify-key-sequence keys))))
(defvar gds-test-expecting nil)
(defun gds-test-protocol-hook (form)
(message "[protocol: %s]" (car form))
(if (eq (car form) gds-test-expecting)
(setq gds-test-expecting nil)))
(defun gds-test-expect-protocol (proc &optional timeout)
(message "[expect: %s]" proc)
(setq gds-test-expecting proc)
(while gds-test-expecting
(or (accept-process-output gds-debug-server (or timeout 5))
(error "Timed out after %ds waiting for %s" (or timeout 5) proc))))
(defun gds-test-check-buffer (name &rest strings)
(let ((buf (or (get-buffer name) (error "No %s buffer" name))))
(save-excursion
(set-buffer buf)
(goto-char (point-min))
(while strings
(search-forward (car strings))
(setq strings (cdr strings))))))
(defun TEST (desc)
(message "TEST: %s" desc))
;; Make sure we take GDS elisp code from this code tree.
(setq load-path (cons (concat default-directory "emacs/") load-path))
;; Protect the tests so we can do some cleanups in case of error.
(unwind-protect
(progn
;; Visit the tutorial.
(find-file "gds-tutorial.txt")
(TEST "Load up GDS.")
(search-forward "(require 'gds)")
(setq load-path (cons (concat default-directory "emacs/") load-path))
(gds-test-execute-keys "\C-x\C-e")
;; Install our testing hook.
(add-hook 'gds-protocol-hook 'gds-test-protocol-hook)
(TEST "Help.")
(search-forward "(list-ref")
(backward-char 2)
(gds-test-execute-keys "\C-hg\C-m")
(gds-test-expect-protocol 'eval-results 10)
(gds-test-check-buffer "*Guile Help*"
"help list-ref"
"is a primitive procedure in the (guile) module")
(TEST "Completion.")
(re-search-forward "^with-output-to-s")
(gds-test-execute-keys "\e\C-i")
(beginning-of-line)
(or (looking-at "with-output-to-string")
(error "Expected completion `with-output-to-string' failed"))
(TEST "Eval defun.")
(search-forward "(display z)")
(gds-test-execute-keys "\e\C-x")
(gds-test-expect-protocol 'eval-results)
(gds-test-check-buffer "*Guile Evaluation*"
"(let ((x 1) (y 2))"
"Arctangent is: 0.46"
"=> 0.46")
(TEST "Multiple values.")
(search-forward "(values 'a ")
(gds-test-execute-keys "\e\C-x")
(gds-test-expect-protocol 'eval-results)
(gds-test-check-buffer "*Guile Evaluation*"
"(values 'a"
"hello world"
"=> a"
"=> b"
"=> c")
(TEST "Eval region with multiple expressions.")
(search-forward "(display \"Arctangent is: \")")
(beginning-of-line)
(push-mark nil nil t)
(forward-line 3)
(gds-test-execute-keys "\C-c\C-r")
(gds-test-expect-protocol 'eval-results)
(gds-test-check-buffer "*Guile Evaluation*"
"(display \"Arctangent is"
"Arctangent is:"
"=> no (or unspecified) value"
"ERROR: Unbound variable: z"
"=> error-in-evaluation"
"Evaluating expression 3"
"=> no (or unspecified) value")
(TEST "Eval syntactically unbalanced region.")
(search-forward "(let ((z (atan x y)))")
(beginning-of-line)
(push-mark nil nil t)
(forward-line 4)
(gds-test-execute-keys "\C-c\C-r")
(gds-test-expect-protocol 'eval-results)
(gds-test-check-buffer "*Guile Evaluation*"
"(let ((z (atan"
"Reading expressions to evaluate"
"ERROR"
"end of file"
"=> error-in-read")
(TEST "Stepping through an evaluation.")
(search-forward "(for-each (lambda (x)")
(forward-line 1)
(push-mark nil nil t)
(forward-line 1)
(gds-test-execute-keys "\C-u\e\C-x")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys " ")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "o")
(gds-test-expect-protocol 'stack)
(gds-test-execute-keys "g")
(gds-test-expect-protocol 'eval-results)
(gds-test-check-buffer "*Guile Evaluation*"
"(for-each (lambda"
"Evaluating in current module"
"3 cubed is 27"
"=> no (or unspecified) value")
;; Done.
(message "====================================")
(message "gds-test.el completed without errors")
(message "====================================")
)
(switch-to-buffer "gds-debug")
(write-region (point-min) (point-max) "gds-test.debug")
(switch-to-buffer "*GDS Transcript*")
(write-region (point-min) (point-max) "gds-test.transcript")
)

2
emacs/gds-test.sh Executable file
View file

@ -0,0 +1,2 @@
#!/bin/sh
GUILE_LOAD_PATH=$(pwd) emacs --batch --no-site-file -q -l gds-test.el < gds-test.stdin

1
emacs/gds-test.stdin Normal file
View file

@ -0,0 +1 @@

223
emacs/gds-tutorial.txt Executable file
View file

@ -0,0 +1,223 @@
;; Welcome to the GDS tutorial!
;; This tutorial teaches the use of GDS by leading you through a set
;; of examples where you actually use GDS, in Emacs, along the way.
;; To get maximum benefit, therefore, you should be reading this
;; tutorial in Emacs.
;; ** GDS setup
;; The first thing to do, if you haven't already, is to load the GDS
;; library into Emacs. The Emacs Lisp expression for this is:
(require 'gds)
;; So, if you don't already have this in your .emacs, either add it
;; and then restart Emacs, or evaluate it just for this Emacs session
;; by moving the cursor to just after the closing parenthesis and
;; typing `C-x C-e'.
;; (Note that if you _have_ already loaded GDS, and you type `C-x C-e'
;; after this expression, you will see a *Guile Evaluation* window
;; telling you that the evaluation failed because `require' is
;; unbound. Don't worry; this is not a problem, and the rest of the
;; tutorial should still work just fine.)
;; ** Help
;; GDS makes it easy to access the Guile help system when working on a
;; Scheme program in Emacs. For example, suppose that you are writing
;; code that uses list-ref, and need to remind yourself about
;; list-ref's arguments ...
(define (penultimate l)
(list-ref
;; Just place the cursor on the word "list-ref" and type `C-h g RET'.
;; Try it now!
;; If GDS is working correctly, a window should have popped up above
;; or below showing the Guile help for list-ref.
;; You can also do an "apropos" search through Guile's help. If you
;; couldn't remember the name list-ref, for example, you could search
;; for anything matching "list" by typing `C-h C-g' and entering
;; "list" at the minibuffer prompt. Try doing this now: you should
;; see a longish list of Guile definitions whose names include "list".
;; As usual in Emacs, you can use `M-PageUp' and `M-PageDown' to
;; conveniently scroll the other window without having to select it.
;; The functions called by `C-h g' and `C-h C-g' are gds-help-symbol
;; and gds-apropos. They both look up the symbol or word at point by
;; default, but that default can be overidden by typing something else
;; at the minibuffer prompt.
;; ** Completion
;; As you are typing Scheme code, you can ask GDS to complete the
;; symbol before point for you, by typing `ESC TAB'. GDS selects
;; possible completions by matching the text so far against all
;; definitions in the Guile environment. (This may be contrasted with
;; the "dabbrev" completion performed by `M-/', which selects possible
;; completions from the contents of Emacs buffers. So, if you are
;; trying to complete "with-ou", to get "with-output-to-string", for
;; example, `ESC TAB' will always work, because with-output-to-string
;; is always defined in Guile's default environment, whereas `M-/'
;; will only work if one of Emacs's buffers happens to contain the
;; full name "with-output-to-string".)
;; To illustrate the idea, here are some partial names that you can
;; try completing. For each one, move the cursor to the end of the
;; line and type `ESC TAB' to try to complete it.
list-
with-ou
with-output-to-s
mkst
;; (If you are not familiar with any of the completed definitions,
;; feel free to use `C-h g' to find out about them!)
;; ** Evaluation
;; GDS provides several ways for you to evaluate Scheme code from
;; within Emacs.
;; Just like in Emacs Lisp, a single expression in a buffer can be
;; evaluated using `C-x C-e' or `C-M-x'. For `C-x C-e', the
;; expression is that which ends immediately before point (so that it
;; is useful for evaluating something just after you have typed it).
;; For `C-M-x', the expression is the "top level defun" around point;
;; this means the balanced chunk of code around point whose opening
;; parenthesis is in column 0.
;; Take this code fragment as an example:
(let ((x 1) (y 2))
(let ((z (atan x y)))
(display "Arctangent is: ")
(display z)
(newline)
z))
;; If you move the cursor to the end of the (display z) line and type
;; `C-x C-e', the code evaluated is just "(display z)", which normally
;; produces an error, because z is not defined in the usual Guile
;; environment. If, however, you type `C-M-x' with the cursor in the
;; same place, the code evaluated is the whole "(let ((x 1) (y 2))
;; ...)" kaboodle, because that is the most recent expression before
;; point that starts in column 0.
;; Try these now. The Guile Evaluation window should pop up again,
;; and show you:
;; - the expression that was evaluated (probably abbreviated)
;; - the module that it was evaluated in
;; - anything that the code wrote to its standard output
;; - the return value(s) of the evaluation.
;; Following the convention of the Emacs Lisp and Guile manuals,
;; return values are indicated by the symbol "=>".
;; To see what happens when an expression has multiple return values,
;; try evaluating this one:
(values 'a (begin (display "hello world\n") 'b) 'c)
;; You can also evaluate a region of a buffer using `C-c C-r'. If the
;; code in the region consists of multiple expressions, GDS evaluates
;; them sequentially. For example, try selecting the following three
;; lines and typing `C-c C-r'.
(display "Arctangent is: ")
(display z)
(newline)
;; If the code in the region evaluated isn't syntactically balanced,
;; GDS will indicate a read error, for example for this code:
(let ((z (atan x y)))
(display "Arctangent is: ")
(display z)
(newline)
;; Finally, if you want to evaluate something quickly that is not in a
;; buffer, you can use `C-c C-e' and type the code to evaluate at the
;; minibuffer prompt. The results are popped up in the same way as
;; for code from a buffer.
;; ** Breakpoints
;; Before evaluating Scheme code from an Emacs buffer, you may want to
;; set some breakpoints in it. With GDS you can set breakpoints in
;; Scheme code by typing `C-x SPC'.
;;
;; To see how this works, select the second line of the following code
;; (the `(format ...)' line) and type `C-x SPC'.
(for-each (lambda (x)
(format #t "~A cubed is ~A\n" x (* x x x)))
(iota 6))
;; The two opening parentheses in that line should now be highlighted
;; in red, to show that breakpoints have been set at the start of the
;; `(format ...)' and `(* x x x)' expressions. Then evaluate the
;; whole for-each expression by typing `C-M-x' ...
;;
;; In the upper half of your Emacs, a buffer appears showing you the
;; Scheme stack.
;;
;; In the lower half, the `(format ...)' expression is highlighted.
;;
;; What has happened is that Guile started evaluating the for-each
;; code, but then hit the breakpoint that you set on the start of the
;; format expression. Guile therefore pauses the evaluation at that
;; point and passes the stack (which encapsulates everything that is
;; interesting about the state of Guile at that point) to GDS. You
;; can then explore the stack and decide how to tell Guile to
;; continue.
;;
;; - If you move your mouse over any of the identifiers in the
;; highlighted code, a help echo (or tooltip) will appear to tell
;; you that identifier's current value. (Note though that this only
;; works when the stack buffer is selected. So if you have switched
;; to this buffer in order to scroll down and read these lines, you
;; will need to switch back to the stack buffer before trying this
;; out.)
;;
;; - In the stack buffer, the "=>" on the left shows you that the top
;; frame is currently selected. You can move up and down the stack
;; by pressing the up and down arrows (or `u' and `d'). As you do
;; this, GDS will change the highlight in the lower window to show
;; the code that corresponds to the selected stack frame.
;;
;; - You can evaluate an arbitrary expression in the local environment
;; of the selected stack frame by typing `e' followed by the
;; expression.
;;
;; - You can show various bits of information about the selected frame
;; by typing `I', `A' and `S'. Feel free to try these now, to see
;; what they do.
;;
;; You also have control over the continuing evaluation of this code.
;; Here are some of the things you can do - please try them as you
;; read.
;;
;; - `g' tells Guile to continue execution normally. In this case
;; that means that evaluation will continue until it hits the next
;; breakpoint, which is on the `(* x x x)' expression.
;;
;; - `SPC' tells Guile to continue until the next significant event in
;; the same source file as the selected frame. A "significant
;; event" means either beginning to evaluate an expression in the
;; relevant file, or completing such an evaluation, in which case
;; GDS tells you the value that it is returning. Pressing `SPC'
;; repeatedly is a nice way to step through all the details of the
;; code in a given file, but stepping over calls that involve code
;; from other files.
;;
;; - `o' tells Guile to continue execution until the selected stack
;; frame completes, and then to show its return value.
;; Local Variables:
;; mode: scheme
;; End:

View file

@ -36,10 +36,11 @@
;; The subprocess object for the debug server. ;; The subprocess object for the debug server.
(defvar gds-debug-server nil) (defvar gds-debug-server nil)
(defvar gds-socket-type-alist '((tcp . 8333) (defvar gds-unix-socket-name (format "/tmp/.gds-socket-%d" (emacs-pid))
(unix . "/tmp/.gds_socket")) "Name of the Unix domain socket that GDS will listen on.")
"Maps each of the possible socket types that the GDS server can
listen on to the path that it should bind to for each one.") (defvar gds-tcp-port 8333
"The TCP port number that GDS will listen on.")
(defun gds-run-debug-server () (defun gds-run-debug-server ()
"Start (or restart, if already running) the GDS debug server process." "Start (or restart, if already running) the GDS debug server process."
@ -47,10 +48,14 @@ listen on to the path that it should bind to for each one.")
(if gds-debug-server (gds-kill-debug-server)) (if gds-debug-server (gds-kill-debug-server))
(setq gds-debug-server (setq gds-debug-server
(gds-start-server "gds-debug" (gds-start-server "gds-debug"
(cdr (assq gds-server-socket-type gds-unix-socket-name
gds-socket-type-alist)) gds-tcp-port
'gds-debug-protocol)) 'gds-debug-protocol))
(process-kill-without-query gds-debug-server)) (process-kill-without-query gds-debug-server)
;; Add the Unix socket name to the environment, so that Guile
;; clients started from within this Emacs will be able to use it,
;; and thereby ensure that they connect to the GDS in this Emacs.
(setenv "GDS_UNIX_SOCKET_NAME" gds-unix-socket-name))
(defun gds-kill-debug-server () (defun gds-kill-debug-server ()
"Kill the GDS debug server process." "Kill the GDS debug server process."
@ -137,7 +142,13 @@ listen on to the path that it should bind to for each one.")
;;;; Debugger protocol ;;;; Debugger protocol
(defcustom gds-protocol-hook nil
"Hook called on receipt of a protocol form from the GDS client."
:type 'hook
:group 'gds)
(defun gds-debug-protocol (client form) (defun gds-debug-protocol (client form)
(run-hook-with-args 'gds-protocol-hook form)
(or (eq client '*) (or (eq client '*)
(let ((proc (car form))) (let ((proc (car form)))
(cond ((eq proc 'name) (cond ((eq proc 'name)
@ -610,7 +621,7 @@ you would add an element to this alist to transform
:group 'gds) :group 'gds)
(defcustom gds-server-socket-type 'tcp (defcustom gds-server-socket-type 'tcp
"What kind of socket the GDS server should listen on." "This option is now obsolete and has no effect."
:group 'gds :group 'gds
:type '(choice (const :tag "TCP" tcp) :type '(choice (const :tag "TCP" tcp)
(const :tag "Unix" unix))) (const :tag "Unix" unix)))

View file

@ -1,6 +1,6 @@
## Process this file with Automake to create Makefile.in ## Process this file with Automake to create Makefile.in
## ##
## Copyright (C) 1998, 1999, 2000, 2001, 2004, 2006, 2007, 2008 Free Software Foundation, Inc. ## Copyright (C) 1998, 1999, 2000, 2001, 2004, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
## ##
## This file is part of guile-readline. ## This file is part of guile-readline.
## ##
@ -19,15 +19,24 @@
## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth ## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
## Floor, Boston, MA 02110-1301 USA ## Floor, Boston, MA 02110-1301 USA
SUBDIRS = ice-9
## Prevent automake from adding extra -I options ## Prevent automake from adding extra -I options
DEFS = @DEFS@ @EXTRA_DEFS@ DEFS = @DEFS@ @EXTRA_DEFS@
if HAVE_READLINE
# `ice-9' subdirectory.
ice9dir = $(pkgdatadir)/$(GUILE_EFFECTIVE_VERSION)
nobase_ice9_DATA = ice-9/readline.scm
EXTRA_DIST = $(nobase_ice9_DATA)
## Check for headers in $(srcdir)/.., so that #include ## Check for headers in $(srcdir)/.., so that #include
## <libguile/MUMBLE.h> will find MUMBLE.h in this dir when we're ## <libguile/MUMBLE.h> will find MUMBLE.h in this dir when we're
## building. Also look for Gnulib headers in `lib'. ## building. Also look for Gnulib headers in `lib'.
INCLUDES = -I. -I.. -I$(srcdir)/.. \ AM_CPPFLAGS = -I. -I.. -I$(srcdir)/.. \
-I$(top_srcdir)/lib -I$(top_builddir)/lib -I$(top_srcdir)/lib -I$(top_builddir)/lib
AM_CFLAGS = $(GCC_CFLAGS)
GUILE_SNARF = ../libguile/guile-snarf GUILE_SNARF = ../libguile/guile-snarf
@ -35,25 +44,33 @@ lib_LTLIBRARIES = libguilereadline-v-@LIBGUILEREADLINE_MAJOR@.la
libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_SOURCES = readline.c libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_SOURCES = readline.c
libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_LIBADD = \ libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_LIBADD = \
../libguile/libguile.la ../lib/libgnu.la $(READLINE_LIBS) \
libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_LDFLAGS = -version-info @LIBGUILEREADLINE_INTERFACE@ -export-dynamic -no-undefined ../libguile/libguile.la ../lib/libgnu.la
libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_LDFLAGS = \
-version-info @LIBGUILEREADLINE_INTERFACE@ -export-dynamic \
-no-undefined
BUILT_SOURCES = readline.x BUILT_SOURCES = readline.x
pkginclude_HEADERS = readline.h pkginclude_HEADERS = readline.h
snarfcppopts = $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) snarfcppopts = $(DEFS) $(AM_CPPFLAGS) $(CPPFLAGS) $(CFLAGS)
SUFFIXES = .x SUFFIXES = .x
.c.x: .c.x:
$(GUILE_SNARF) -o $@ $< $(snarfcppopts) $(GUILE_SNARF) -o $@ $< $(snarfcppopts)
EXTRA_DIST = LIBGUILEREADLINE-VERSION ChangeLog-2008 EXTRA_DIST += LIBGUILEREADLINE-VERSION ChangeLog-2008
MKDEP = gcc -M -MG $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) ETAGS_ARGS = \
$(nobase_ice9_DATA) \
$(libguilereadline_v_@LIBGUILEREADLINE_MAJOR@_la_SOURCES)
CLEANFILES = *.x CLEANFILES = *.x
endif HAVE_READLINE
dist-hook: dist-hook:
(temp="/tmp/mangle-deps.$$$$"; \ (temp="/tmp/mangle-deps.$$$$"; \
trap "rm -f $$temp" 0 1 2 15; \ trap "rm -f $$temp" 0 1 2 15; \

View file

@ -1,8 +0,0 @@
#!/bin/sh
[ -f readline-activator.scm ] || {
echo "autogen.sh: run this command only in the guile-readline directory."
exit 1
}
autoreconf -i --force

View file

@ -1,88 +0,0 @@
AC_PREREQ(2.50)
dnl Don't use "echo -n", which is not portable (e.g., not available on
dnl MacOS X). Instead, use `patsubst' to remove the newline.
AC_INIT(guile-readline,
patsubst(m4_esyscmd(. ../GUILE-VERSION && echo ${GUILE_VERSION}), [
]),
[bug-guile@gnu.org])
AC_CONFIG_AUX_DIR([../build-aux])
AC_CONFIG_SRCDIR(readline.c)
AM_CONFIG_HEADER([guile-readline-config.h])
AM_INIT_AUTOMAKE([foreign no-define])
. $srcdir/../GUILE-VERSION
AC_PROG_INSTALL
AC_PROG_CC
AM_PROG_CC_STDC
AC_LIBTOOL_WIN32_DLL
AC_PROG_LIBTOOL
dnl
dnl Check for Winsock and other functionality on Win32 (*not* CygWin)
dnl
AC_CYGWIN
AC_MINGW32
EXTRA_DEFS=""
if test "$MINGW32" = "yes" ; then
if test $enable_shared = yes ; then
EXTRA_DEFS="-DSCM_IMPORT"
fi
fi
AC_SUBST(EXTRA_DEFS)
for termlib in ncurses curses termcap terminfo termlib ; do
AC_CHECK_LIB(${termlib}, tgoto,
[LIBS="-l${termlib} $LIBS"; break])
done
AC_LIB_LINKFLAGS(readline)
AC_CHECK_LIB(readline, readline)
if test $ac_cv_lib_readline_readline = no; then
AC_MSG_WARN([libreadline was not found on your system.])
fi
AC_CHECK_FUNCS(siginterrupt rl_clear_signals rl_cleanup_after_signal)
dnl Check for modern readline naming
AC_CHECK_FUNCS(rl_filename_completion_function)
dnl Check for rl_get_keymap. We only use this for deciding whether to
dnl install paren matching on the Guile command line (when using
dnl readline for input), so it's completely optional.
AC_CHECK_FUNCS(rl_get_keymap)
AC_CACHE_CHECK([for rl_getc_function pointer in readline],
ac_cv_var_rl_getc_function,
[AC_TRY_LINK([
#include <stdio.h>
#include <readline/readline.h>],
[printf ("%ld", (long) rl_getc_function)],
[ac_cv_var_rl_getc_function=yes],
[ac_cv_var_rl_getc_function=no])])
if test "${ac_cv_var_rl_getc_function}" = "yes"; then
AC_DEFINE(HAVE_RL_GETC_FUNCTION, 1,
[Define if your readline library has the rl_getc_function variable.])
fi
if test $ac_cv_lib_readline_readline = yes \
-a $ac_cv_var_rl_getc_function = no; then
AC_MSG_WARN([*** libreadline is too old on your system.])
AC_MSG_WARN([*** You need readline version 2.1 or later.])
fi
AC_CHECK_FUNCS(strdup)
. $srcdir/LIBGUILEREADLINE-VERSION
AC_SUBST(LIBGUILEREADLINE_MAJOR)
AC_SUBST(LIBGUILEREADLINE_INTERFACE_CURRENT)
AC_SUBST(LIBGUILEREADLINE_INTERFACE_REVISION)
AC_SUBST(LIBGUILEREADLINE_INTERFACE_AGE)
AC_SUBST(LIBGUILEREADLINE_INTERFACE)
AC_SUBST(GUILE_EFFECTIVE_VERSION)
AC_CONFIG_FILES(Makefile ice-9/Makefile)
AC_OUTPUT

View file

@ -1,28 +0,0 @@
## Process this file with Automake to create Makefile.in
##
## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
##
## This file is part of guile-readline.
##
## guile-readline is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3, or
## (at your option) any later version.
##
## guile-readline is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with guile-readline; see the file COPYING. If not, write
## to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
## Floor, Boston, MA 02110-1301 USA
# Guile's `pkgdatadir'.
guile_pdd = $(datadir)/guile
ice9dir = $(guile_pdd)/$(GUILE_EFFECTIVE_VERSION)/ice-9
ice9_DATA = readline.scm
ETAGS_ARGS = $(ice9_DATA)
EXTRA_DIST = $(ice9_DATA)

View file

@ -1,6 +1,6 @@
/* readline.c --- line editing support for Guile */ /* readline.c --- line editing support for Guile */
/* Copyright (C) 1997,1999,2000,2001, 2002, 2003, 2006, 2007, 2008 Free Software Foundation, Inc. /* Copyright (C) 1997,1999,2000,2001, 2002, 2003, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -21,9 +21,9 @@
#ifdef HAVE_CONFIG_H
/* Include private, configure generated header (i.e. config.h). */ # include <config.h>
#include "guile-readline-config.h" #endif
#ifdef HAVE_RL_GETC_FUNCTION #ifdef HAVE_RL_GETC_FUNCTION
#include "libguile.h" #include "libguile.h"

View file

@ -20,7 +20,10 @@
(define (eval-elisp x) (define (eval-elisp x)
"Evaluate the Elisp expression @var{x}." "Evaluate the Elisp expression @var{x}."
(eval x the-elisp-module)) (save-module-excursion
(lambda ()
(set-current-module the-elisp-module)
(primitive-eval x))))
(define (translate-elisp x) (define (translate-elisp x)
"Translate the Elisp expression @var{x} to equivalent Scheme code." "Translate the Elisp expression @var{x} to equivalent Scheme code."

View file

@ -31,8 +31,12 @@ extern "C" {
#include "libguile/__scm.h" #include "libguile/__scm.h"
#include "libguile/alist.h" #include "libguile/alist.h"
#include "libguile/arbiters.h" #include "libguile/arbiters.h"
#include "libguile/array-handle.h"
#include "libguile/array-map.h"
#include "libguile/arrays.h"
#include "libguile/async.h" #include "libguile/async.h"
#include "libguile/boolean.h" #include "libguile/boolean.h"
#include "libguile/bitvectors.h"
#include "libguile/bytevectors.h" #include "libguile/bytevectors.h"
#include "libguile/chars.h" #include "libguile/chars.h"
#include "libguile/continuations.h" #include "libguile/continuations.h"
@ -50,6 +54,8 @@ extern "C" {
#include "libguile/futures.h" #include "libguile/futures.h"
#include "libguile/gc.h" #include "libguile/gc.h"
#include "libguile/gdbint.h" #include "libguile/gdbint.h"
#include "libguile/generalized-arrays.h"
#include "libguile/generalized-vectors.h"
#include "libguile/goops.h" #include "libguile/goops.h"
#include "libguile/gsubr.h" #include "libguile/gsubr.h"
#include "libguile/guardians.h" #include "libguile/guardians.h"
@ -78,7 +84,6 @@ extern "C" {
#include "libguile/properties.h" #include "libguile/properties.h"
#include "libguile/procs.h" #include "libguile/procs.h"
#include "libguile/r6rs-ports.h" #include "libguile/r6rs-ports.h"
#include "libguile/ramap.h"
#include "libguile/random.h" #include "libguile/random.h"
#include "libguile/read.h" #include "libguile/read.h"
#include "libguile/root.h" #include "libguile/root.h"
@ -101,7 +106,7 @@ extern "C" {
#include "libguile/symbols.h" #include "libguile/symbols.h"
#include "libguile/tags.h" #include "libguile/tags.h"
#include "libguile/throw.h" #include "libguile/throw.h"
#include "libguile/unif.h" #include "libguile/uniform.h"
#include "libguile/validate.h" #include "libguile/validate.h"
#include "libguile/values.h" #include "libguile/values.h"
#include "libguile/variable.h" #include "libguile/variable.h"

View file

@ -105,26 +105,103 @@ guile_LDFLAGS = $(GUILE_CFLAGS)
libguile_la_CFLAGS = $(GUILE_CFLAGS) $(AM_CFLAGS) libguile_la_CFLAGS = $(GUILE_CFLAGS) $(AM_CFLAGS)
libguile_la_SOURCES = alist.c arbiters.c async.c backtrace.c boolean.c \ libguile_la_SOURCES = \
bytevectors.c chars.c continuations.c \ alist.c \
convert.c debug.c deprecation.c \ arbiters.c \
deprecated.c discouraged.c dynwind.c eq.c error.c \ array-handle.c \
eval.c evalext.c extensions.c feature.c fluids.c fports.c \ array-map.c \
futures.c gc.c gc-malloc.c \ arrays.c \
gdbint.c gettext.c goops.c gsubr.c \ async.c \
guardians.c hash.c hashtab.c hooks.c init.c inline.c \ backtrace.c \
ioext.c keywords.c lang.c list.c load.c macros.c mallocs.c \ boolean.c \
modules.c numbers.c objects.c objprop.c options.c pairs.c ports.c \ bitvectors.c \
print.c procprop.c procs.c properties.c \ bytevectors.c \
r6rs-ports.c random.c rdelim.c read.c \ chars.c \
root.c rw.c scmsigs.c script.c simpos.c smob.c sort.c srcprop.c \ continuations.c \
stackchk.c stacks.c stime.c strings.c srfi-4.c srfi-13.c srfi-14.c \ debug.c \
strorder.c strports.c struct.c symbols.c threads.c null-threads.c \ deprecated.c \
throw.c values.c variable.c vectors.c version.c vports.c weaks.c \ deprecation.c \
ramap.c unif.c discouraged.c \
dynwind.c \
# vm-related sources eq.c \
libguile_la_SOURCES += frames.c instructions.c objcodes.c programs.c vm.c error.c \
eval.c \
evalext.c \
extensions.c \
feature.c \
fluids.c \
fports.c \
frames.c \
futures.c \
gc-malloc.c \
gc.c \
gdbint.c \
gettext.c \
generalized-arrays.c \
generalized-vectors.c \
goops.c \
gsubr.c \
guardians.c \
hash.c \
hashtab.c \
hooks.c \
init.c \
inline.c \
instructions.c \
ioext.c \
keywords.c \
lang.c \
list.c \
load.c \
macros.c \
mallocs.c \
modules.c \
null-threads.c \
numbers.c \
objcodes.c \
objects.c \
objprop.c \
options.c \
pairs.c \
ports.c \
print.c \
procprop.c \
procs.c \
programs.c \
properties.c \
r6rs-ports.c \
random.c \
rdelim.c \
read.c \
root.c \
rw.c \
scmsigs.c \
script.c \
simpos.c \
smob.c \
sort.c \
srcprop.c \
srfi-13.c \
srfi-14.c \
srfi-4.c \
stackchk.c \
stacks.c \
stime.c \
strings.c \
strorder.c \
strports.c \
struct.c \
symbols.c \
threads.c \
throw.c \
uniform.c \
values.c \
variable.c \
vectors.c \
version.c \
vm.c \
vports.c \
weaks.c
libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_SOURCES = i18n.c libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_SOURCES = i18n.c
libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_CFLAGS = \ libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_CFLAGS = \
@ -135,46 +212,194 @@ libguile_i18n_v_@LIBGUILE_I18N_MAJOR@_la_LDFLAGS = \
-module -L$(builddir) -lguile \ -module -L$(builddir) -lguile \
-version-info @LIBGUILE_I18N_INTERFACE@ -version-info @LIBGUILE_I18N_INTERFACE@
DOT_X_FILES = alist.x arbiters.x async.x backtrace.x boolean.x \ DOT_X_FILES = \
bytevectors.x chars.x \ alist.x \
continuations.x debug.x deprecation.x deprecated.x discouraged.x \ arbiters.x \
dynl.x dynwind.x environments.x eq.x error.x eval.x evalext.x \ array-handle.x \
extensions.x feature.x fluids.x fports.x futures.x gc.x \ array-map.x \
gettext.x goops.x gsubr.x guardians.x \ arrays.x \
hash.x hashtab.x hooks.x i18n.x init.x ioext.x keywords.x lang.x \ async.x \
list.x load.x macros.x mallocs.x modules.x numbers.x objects.x \ backtrace.x \
objprop.x options.x pairs.x ports.x print.x procprop.x procs.x \ boolean.x \
properties.x r6rs-ports.x random.x rdelim.x \ bitvectors.x \
read.x root.x rw.x scmsigs.x \ bytevectors.x \
script.x simpos.x smob.x sort.x srcprop.x stackchk.x stacks.x \ chars.x \
stime.x strings.x srfi-4.x srfi-13.x srfi-14.x strorder.x \ continuations.x \
strports.x struct.x symbols.x threads.x throw.x values.x \ debug.x \
variable.x vectors.x version.x vports.x weaks.x ramap.x unif.x deprecated.x \
deprecation.x \
discouraged.x \
dynl.x \
dynwind.x \
eq.x \
error.x \
eval.x \
evalext.x \
extensions.x \
feature.x \
fluids.x \
fports.x \
futures.x \
gc-malloc.x \
gc.x \
gettext.x \
generalized-arrays.x \
generalized-vectors.x \
goops.x \
gsubr.x \
guardians.x \
hash.x \
hashtab.x \
hooks.x \
i18n.x \
init.x \
ioext.x \
keywords.x \
lang.x \
list.x \
load.x \
macros.x \
mallocs.x \
modules.x \
numbers.x \
objects.x \
objprop.x \
options.x \
pairs.x \
ports.x \
print.x \
procprop.x \
procs.x \
properties.x \
r6rs-ports.x \
random.x \
rdelim.x \
read.x \
root.x \
rw.x \
scmsigs.x \
script.x \
simpos.x \
smob.x \
sort.x \
srcprop.x \
srfi-13.x \
srfi-14.x \
srfi-4.x \
stackchk.x \
stacks.x \
stime.x \
strings.x \
strorder.x \
strports.x \
struct.x \
symbols.x \
threads.x \
throw.x \
uniform.x \
values.x \
variable.x \
vectors.x \
version.x \
vports.x \
weaks.x
# vm-related snarfs # vm-related snarfs
DOT_X_FILES += frames.x instructions.x objcodes.x programs.x vm.x DOT_X_FILES += frames.x instructions.x objcodes.x programs.x vm.x
EXTRA_DOT_X_FILES = @EXTRA_DOT_X_FILES@ EXTRA_DOT_X_FILES = @EXTRA_DOT_X_FILES@
DOT_DOC_FILES = alist.doc arbiters.doc async.doc backtrace.doc \ DOT_DOC_FILES = \
boolean.doc bytevectors.doc chars.doc \ alist.doc \
continuations.doc debug.doc deprecation.doc \ arbiters.doc \
deprecated.doc discouraged.doc dynl.doc dynwind.doc \ array-handle.doc \
eq.doc error.doc eval.doc evalext.doc \ array-map.doc \
extensions.doc feature.doc fluids.doc fports.doc futures.doc \ arrays.doc \
gc.doc goops.doc gsubr.doc \ async.doc \
gc-malloc.doc gettext.doc guardians.doc hash.doc hashtab.doc \ backtrace.doc \
hooks.doc i18n.doc init.doc ioext.doc keywords.doc lang.doc \ boolean.doc \
list.doc load.doc macros.doc mallocs.doc modules.doc numbers.doc \ bitvectors.doc \
objects.doc objprop.doc options.doc pairs.doc ports.doc print.doc \ bytevectors.doc \
procprop.doc procs.doc properties.doc r6rs-ports.doc \ chars.doc \
random.doc rdelim.doc \ continuations.doc \
read.doc root.doc rw.doc scmsigs.doc script.doc simpos.doc \ debug.doc \
smob.doc sort.doc srcprop.doc stackchk.doc stacks.doc stime.doc \ deprecated.doc \
strings.doc srfi-4.doc srfi-13.doc srfi-14.doc strorder.doc \ deprecation.doc \
strports.doc struct.doc symbols.doc threads.doc throw.doc \ discouraged.doc \
values.doc variable.doc vectors.doc version.doc vports.doc \ dynl.doc \
weaks.doc ramap.doc unif.doc dynwind.doc \
eq.doc \
error.doc \
eval.doc \
evalext.doc \
extensions.doc \
feature.doc \
fluids.doc \
fports.doc \
futures.doc \
gc-malloc.doc \
gc.doc \
gettext.doc \
generalized-arrays.doc \
generalized-vectors.doc \
goops.doc \
gsubr.doc \
guardians.doc \
hash.doc \
hashtab.doc \
hooks.doc \
i18n.doc \
init.doc \
ioext.doc \
keywords.doc \
lang.doc \
list.doc \
load.doc \
macros.doc \
mallocs.doc \
modules.doc \
numbers.doc \
objects.doc \
objprop.doc \
options.doc \
pairs.doc \
ports.doc \
print.doc \
procprop.doc \
procs.doc \
properties.doc \
r6rs-ports.doc \
random.doc \
rdelim.doc \
read.doc \
root.doc \
rw.doc \
scmsigs.doc \
script.doc \
simpos.doc \
smob.doc \
sort.doc \
srcprop.doc \
srfi-13.doc \
srfi-14.doc \
srfi-4.doc \
stackchk.doc \
stacks.doc \
stime.doc \
strings.doc \
strorder.doc \
strports.doc \
struct.doc \
symbols.doc \
threads.doc \
throw.doc \
uniform.doc \
values.doc \
variable.doc \
vectors.doc \
version.doc \
vports.doc \
weaks.doc
EXTRA_DOT_DOC_FILES = @EXTRA_DOT_DOC_FILES@ EXTRA_DOT_DOC_FILES = @EXTRA_DOT_DOC_FILES@
@ -205,10 +430,9 @@ install-exec-hook:
## compile, since they are #included. So instead we list them here. ## compile, since they are #included. So instead we list them here.
## Perhaps we can deal with them normally once the merge seems to be ## Perhaps we can deal with them normally once the merge seems to be
## working. ## working.
noinst_HEADERS = convert.i.c \ noinst_HEADERS = conv-integer.i.c conv-uinteger.i.c \
conv-integer.i.c conv-uinteger.i.c \
eval.i.c ieee-754.h \ eval.i.c ieee-754.h \
srfi-4.i.c \ srfi-4.i.c srfi-14.i.c \
quicksort.i.c \ quicksort.i.c \
win32-uname.h win32-dirent.h win32-socket.h \ win32-uname.h win32-dirent.h win32-socket.h \
private-gc.h private-options.h private-gc.h private-options.h
@ -232,28 +456,119 @@ pkginclude_HEADERS =
# These are headers visible as <libguile/mumble.h>. # These are headers visible as <libguile/mumble.h>.
modincludedir = $(includedir)/libguile modincludedir = $(includedir)/libguile
modinclude_HEADERS = __scm.h alist.h arbiters.h async.h backtrace.h \ modinclude_HEADERS = \
boehm-gc.h bytevectors.h \ __scm.h \
boolean.h chars.h continuations.h convert.h debug.h debug-malloc.h \ alist.h \
deprecation.h deprecated.h discouraged.h dynl.h dynwind.h \ arbiters.h \
eq.h error.h eval.h evalext.h extensions.h \ array-handle.h \
feature.h filesys.h fluids.h fports.h futures.h gc.h \ array-map.h \
gdb_interface.h gdbint.h gettext.h goops.h \ arrays.h \
gsubr.h guardians.h hash.h \ async.h \
hashtab.h hooks.h i18n.h init.h inline.h ioext.h iselect.h \ backtrace.h \
keywords.h lang.h list.h load.h macros.h mallocs.h modules.h \ boolean.h \
net_db.h numbers.h objects.h objprop.h options.h pairs.h ports.h \ bitvectors.h \
posix.h r6rs-ports.h regex-posix.h print.h \ bytevectors.h \
procprop.h procs.h properties.h \ chars.h \
random.h ramap.h rdelim.h read.h root.h rw.h scmsigs.h validate.h \ continuations.h \
script.h simpos.h smob.h snarf.h socket.h sort.h srcprop.h \ debug-malloc.h \
stackchk.h stacks.h stime.h strings.h srfi-4.h srfi-13.h srfi-14.h \ debug.h \
strorder.h strports.h struct.h symbols.h tags.h threads.h \ deprecated.h \
pthread-threads.h null-threads.h throw.h unif.h values.h \ deprecation.h \
variable.h vectors.h vports.h weaks.h discouraged.h \
dynl.h \
modinclude_HEADERS += vm-bootstrap.h frames.h instructions.h objcodes.h \ dynwind.h \
programs.h vm.h vm-engine.h vm-expand.h eq.h \
error.h \
eval.h \
evalext.h \
extensions.h \
feature.h \
filesys.h \
fluids.h \
fports.h \
frames.h \
futures.h \
gc.h \
gdb_interface.h \
gdbint.h \
gettext.h \
generalized-arrays.h \
generalized-vectors.h \
goops.h \
gsubr.h \
guardians.h \
hash.h \
hashtab.h \
hooks.h \
i18n.h \
init.h \
inline.h \
instructions.h \
ioext.h \
iselect.h \
keywords.h \
lang.h \
list.h \
load.h \
macros.h \
mallocs.h \
modules.h \
net_db.h \
null-threads.h \
numbers.h \
objcodes.h \
objects.h \
objprop.h \
options.h \
pairs.h \
ports.h \
posix.h \
print.h \
procprop.h \
procs.h \
programs.h \
properties.h \
pthread-threads.h \
r6rs-ports.h \
random.h \
rdelim.h \
read.h \
regex-posix.h \
root.h \
rw.h \
scmsigs.h \
script.h \
simpos.h \
smob.h \
snarf.h \
socket.h \
sort.h \
srcprop.h \
srfi-13.h \
srfi-14.h \
srfi-4.h \
stackchk.h \
stacks.h \
stime.h \
strings.h \
strorder.h \
strports.h \
struct.h \
symbols.h \
tags.h \
threads.h \
throw.h \
validate.h \
uniform.h \
values.h \
variable.h \
vectors.h \
vm-bootstrap.h \
vm-engine.h \
vm-expand.h \
vm.h \
vports.h \
weaks.h
nodist_modinclude_HEADERS = version.h scmconfig.h nodist_modinclude_HEADERS = version.h scmconfig.h
@ -268,7 +583,7 @@ EXTRA_DIST = ChangeLog-scm ChangeLog-threads \
cpp_errno.c cpp_err_symbols.in cpp_err_symbols.c \ cpp_errno.c cpp_err_symbols.in cpp_err_symbols.c \
cpp_sig_symbols.c cpp_sig_symbols.in cpp_cnvt.awk \ cpp_sig_symbols.c cpp_sig_symbols.in cpp_cnvt.awk \
c-tokenize.lex version.h.in \ c-tokenize.lex version.h.in \
scmconfig.h.top libgettext.h libguile.map scmconfig.h.top libgettext.h unidata_to_charset.pl libguile.map
# $(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES) \ # $(DOT_DOC_FILES) $(EXTRA_DOT_DOC_FILES) \
# guile-procedures.txt guile.texi # guile-procedures.txt guile.texi

View file

@ -423,19 +423,28 @@
typedef struct { typedef struct {
ucontext_t ctx; ucontext_t ctx;
int fresh; int fresh;
} jmp_buf; } scm_i_jmp_buf;
# define setjmp(JB) \ # define SCM_I_SETJMP(JB) \
( (JB).fresh = 1, \ ( (JB).fresh = 1, \
getcontext (&((JB).ctx)), \ getcontext (&((JB).ctx)), \
((JB).fresh ? ((JB).fresh = 0, 0) : 1) ) ((JB).fresh ? ((JB).fresh = 0, 0) : 1) )
# define longjmp(JB,VAL) scm_ia64_longjmp (&(JB), VAL) # define SCM_I_LONGJMP(JB,VAL) scm_ia64_longjmp (&(JB), VAL)
void scm_ia64_longjmp (jmp_buf *, int); void scm_ia64_longjmp (scm_i_jmp_buf *, int);
# else /* ndef __ia64__ */ # else /* ndef __ia64__ */
# include <setjmp.h> # include <setjmp.h>
# endif /* ndef __ia64__ */ # endif /* ndef __ia64__ */
# endif /* ndef _CRAY1 */ # endif /* ndef _CRAY1 */
#endif /* ndef vms */ #endif /* ndef vms */
/* For any platform where SCM_I_SETJMP hasn't been defined in some
special way above, map SCM_I_SETJMP, SCM_I_LONGJMP and
scm_i_jmp_buf to setjmp, longjmp and jmp_buf. */
#ifndef SCM_I_SETJMP
#define scm_i_jmp_buf jmp_buf
#define SCM_I_SETJMP setjmp
#define SCM_I_LONGJMP longjmp
#endif
/* James Clark came up with this neat one instruction fix for /* James Clark came up with this neat one instruction fix for
* continuations on the SPARC. It flushes the register windows so * continuations on the SPARC. It flushes the register windows so
* that all the state of the process is contained in the stack. * that all the state of the process is contained in the stack.
@ -556,6 +565,13 @@ SCM_API SCM scm_call_generic_1 (SCM gf, SCM a1);
return (SCM_UNPACK (gf) \ return (SCM_UNPACK (gf) \
? scm_call_generic_1 ((gf), (a1)) \ ? scm_call_generic_1 ((gf), (a1)) \
: (scm_wrong_type_arg ((subr), (pos), (a1)), SCM_UNSPECIFIED)) : (scm_wrong_type_arg ((subr), (pos), (a1)), SCM_UNSPECIFIED))
/* This form is for dispatching a subroutine. */
#define SCM_WTA_DISPATCH_1_SUBR(subr, a1, pos) \
return (SCM_UNPACK ((*SCM_SUBR_GENERIC (subr))) \
? scm_call_generic_1 ((*SCM_SUBR_GENERIC (subr)), (a1)) \
: (scm_i_wrong_type_arg_symbol (SCM_SUBR_NAME (subr), (pos), (a1)), SCM_UNSPECIFIED))
#define SCM_GASSERT1(cond, gf, a1, pos, subr) \ #define SCM_GASSERT1(cond, gf, a1, pos, subr) \
if (SCM_UNLIKELY (!(cond))) \ if (SCM_UNLIKELY (!(cond))) \
SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr)) SCM_WTA_DISPATCH_1((gf), (a1), (pos), (subr))

View file

@ -172,7 +172,7 @@
/* Major and minor versions must be single characters. */ /* Major and minor versions must be single characters. */
#define SCM_OBJCODE_MAJOR_VERSION 0 #define SCM_OBJCODE_MAJOR_VERSION 0
#define SCM_OBJCODE_MINOR_VERSION B #define SCM_OBJCODE_MINOR_VERSION D
#define SCM_OBJCODE_MAJOR_VERSION_STRING \ #define SCM_OBJCODE_MAJOR_VERSION_STRING \
SCM_CPP_STRINGIFY(SCM_OBJCODE_MAJOR_VERSION) SCM_CPP_STRINGIFY(SCM_OBJCODE_MAJOR_VERSION)
#define SCM_OBJCODE_MINOR_VERSION_STRING \ #define SCM_OBJCODE_MINOR_VERSION_STRING \

162
libguile/array-handle.c Normal file
View file

@ -0,0 +1,162 @@
/* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004, 2005, 2006, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libguile/_scm.h"
#include "libguile/__scm.h"
#include "libguile/array-handle.h"
SCM scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_LAST + 1];
#define ARRAY_IMPLS_N_STATIC_ALLOC 7
static scm_t_array_implementation array_impls[ARRAY_IMPLS_N_STATIC_ALLOC];
static int num_array_impls_registered = 0;
void
scm_i_register_array_implementation (scm_t_array_implementation *impl)
{
if (num_array_impls_registered >= ARRAY_IMPLS_N_STATIC_ALLOC)
/* need to increase ARRAY_IMPLS_N_STATIC_ALLOC, buster */
abort ();
else
array_impls[num_array_impls_registered++] = *impl;
}
scm_t_array_implementation*
scm_i_array_implementation_for_obj (SCM obj)
{
int i;
for (i = 0; i < num_array_impls_registered; i++)
if (SCM_NIMP (obj)
&& (SCM_CELL_TYPE (obj) & array_impls[i].mask) == array_impls[i].tag)
return &array_impls[i];
return NULL;
}
void
scm_array_get_handle (SCM array, scm_t_array_handle *h)
{
scm_t_array_implementation *impl = scm_i_array_implementation_for_obj (array);
if (!impl)
scm_wrong_type_arg_msg (NULL, 0, array, "array");
h->array = array;
h->impl = impl;
h->base = 0;
h->ndims = 0;
h->dims = NULL;
h->element_type = SCM_ARRAY_ELEMENT_TYPE_SCM; /* have to default to
something... */
h->elements = NULL;
h->writable_elements = NULL;
h->impl->get_handle (array, h);
}
ssize_t
scm_array_handle_pos (scm_t_array_handle *h, SCM indices)
{
scm_t_array_dim *s = scm_array_handle_dims (h);
ssize_t pos = 0, i;
size_t k = scm_array_handle_rank (h);
while (k > 0 && scm_is_pair (indices))
{
i = scm_to_signed_integer (SCM_CAR (indices), s->lbnd, s->ubnd);
pos += (i - s->lbnd) * s->inc;
k--;
s++;
indices = SCM_CDR (indices);
}
if (k > 0 || !scm_is_null (indices))
scm_misc_error (NULL, "wrong number of indices, expecting ~a",
scm_list_1 (scm_from_size_t (scm_array_handle_rank (h))));
return pos;
}
SCM
scm_array_handle_element_type (scm_t_array_handle *h)
{
if (h->element_type < 0 || h->element_type > SCM_ARRAY_ELEMENT_TYPE_LAST)
abort (); /* guile programming error */
return scm_i_array_element_types[h->element_type];
}
void
scm_array_handle_release (scm_t_array_handle *h)
{
/* Nothing to do here until arrays need to be reserved for real.
*/
}
const SCM *
scm_array_handle_elements (scm_t_array_handle *h)
{
if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
scm_wrong_type_arg_msg (NULL, 0, h->array, "non-uniform array");
return ((const SCM*)h->elements) + h->base;
}
SCM *
scm_array_handle_writable_elements (scm_t_array_handle *h)
{
if (h->element_type != SCM_ARRAY_ELEMENT_TYPE_SCM)
scm_wrong_type_arg_msg (NULL, 0, h->array, "non-uniform array");
return ((SCM*)h->elements) + h->base;
}
void
scm_init_array_handle (void)
{
#define DEFINE_ARRAY_TYPE(tag, TAG) \
scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_##TAG] \
= (scm_permanent_object (scm_from_locale_symbol (#tag)))
scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_SCM] = SCM_BOOL_T;
DEFINE_ARRAY_TYPE (a, CHAR);
DEFINE_ARRAY_TYPE (b, BIT);
DEFINE_ARRAY_TYPE (vu8, VU8);
DEFINE_ARRAY_TYPE (u8, U8);
DEFINE_ARRAY_TYPE (s8, S8);
DEFINE_ARRAY_TYPE (u16, U16);
DEFINE_ARRAY_TYPE (s16, S16);
DEFINE_ARRAY_TYPE (u32, U32);
DEFINE_ARRAY_TYPE (s32, S32);
DEFINE_ARRAY_TYPE (u64, U64);
DEFINE_ARRAY_TYPE (s64, S64);
DEFINE_ARRAY_TYPE (f32, F32);
DEFINE_ARRAY_TYPE (f64, F64);
DEFINE_ARRAY_TYPE (c32, C32);
DEFINE_ARRAY_TYPE (c64, C64);
#include "libguile/array-handle.x"
}
/*
Local Variables:
c-file-style: "gnu"
End:
*/

129
libguile/array-handle.h Normal file
View file

@ -0,0 +1,129 @@
/* classes: h_files */
#ifndef SCM_ARRAY_HANDLE_H
#define SCM_ARRAY_HANDLE_H
/* Copyright (C) 1995,1996,1997,1999,2000,2001, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "libguile/__scm.h"
struct scm_t_array_handle;
typedef SCM (*scm_i_t_array_ref) (struct scm_t_array_handle *, size_t);
typedef void (*scm_i_t_array_set) (struct scm_t_array_handle *, size_t, SCM);
typedef struct
{
scm_t_bits tag;
scm_t_bits mask;
scm_i_t_array_ref vref;
scm_i_t_array_set vset;
void (*get_handle)(SCM, struct scm_t_array_handle*);
} scm_t_array_implementation;
#define SCM_ARRAY_IMPLEMENTATION(tag_,mask_,vref_,vset_,handle_) \
SCM_SNARF_INIT ({ \
scm_t_array_implementation impl; \
impl.tag = tag_; impl.mask = mask_; \
impl.vref = vref_; impl.vset = vset_; \
impl.get_handle = handle_; \
scm_i_register_array_implementation (&impl); \
})
SCM_INTERNAL void scm_i_register_array_implementation (scm_t_array_implementation *impl);
SCM_INTERNAL scm_t_array_implementation* scm_i_array_implementation_for_obj (SCM obj);
typedef struct scm_t_array_dim
{
ssize_t lbnd;
ssize_t ubnd;
ssize_t inc;
} scm_t_array_dim;
typedef enum {
SCM_ARRAY_ELEMENT_TYPE_SCM = 0, /* SCM values */
SCM_ARRAY_ELEMENT_TYPE_CHAR = 1, /* characters */
SCM_ARRAY_ELEMENT_TYPE_BIT = 2, /* packed numeric values */
SCM_ARRAY_ELEMENT_TYPE_VU8 = 3,
SCM_ARRAY_ELEMENT_TYPE_U8 = 4,
SCM_ARRAY_ELEMENT_TYPE_S8 = 5,
SCM_ARRAY_ELEMENT_TYPE_U16 = 6,
SCM_ARRAY_ELEMENT_TYPE_S16 = 7,
SCM_ARRAY_ELEMENT_TYPE_U32 = 8,
SCM_ARRAY_ELEMENT_TYPE_S32 = 9,
SCM_ARRAY_ELEMENT_TYPE_U64 = 10,
SCM_ARRAY_ELEMENT_TYPE_S64 = 11,
SCM_ARRAY_ELEMENT_TYPE_F32 = 12,
SCM_ARRAY_ELEMENT_TYPE_F64 = 13,
SCM_ARRAY_ELEMENT_TYPE_C32 = 14,
SCM_ARRAY_ELEMENT_TYPE_C64 = 15,
SCM_ARRAY_ELEMENT_TYPE_LAST = 15,
} scm_t_array_element_type;
SCM_INTERNAL SCM scm_i_array_element_types[];
typedef struct scm_t_array_handle {
SCM array;
scm_t_array_implementation *impl;
/* `Base' is an offset into elements or writable_elements, corresponding to
the first element in the array. It would be nicer just to adjust the
elements/writable_elements pointer, but we can't because that element might
not even be byte-addressable, as is the case with bitvectors. A nicer
solution would be, well, nice.
*/
size_t base;
size_t ndims; /* ndims == the rank of the array */
scm_t_array_dim *dims;
scm_t_array_dim dim0;
scm_t_array_element_type element_type;
const void *elements;
void *writable_elements;
} scm_t_array_handle;
#define scm_array_handle_rank(h) ((h)->ndims)
#define scm_array_handle_dims(h) ((h)->dims)
SCM_API void scm_array_get_handle (SCM array, scm_t_array_handle *h);
SCM_API ssize_t scm_array_handle_pos (scm_t_array_handle *h, SCM indices);
SCM_API SCM scm_array_handle_element_type (scm_t_array_handle *h);
SCM_API void scm_array_handle_release (scm_t_array_handle *h);
SCM_API const SCM* scm_array_handle_elements (scm_t_array_handle *h);
SCM_API SCM* scm_array_handle_writable_elements (scm_t_array_handle *h);
/* See inline.h for scm_array_handle_ref and scm_array_handle_set */
SCM_INTERNAL void scm_init_array_handle (void);
#endif /* SCM_ARRAY_HANDLE_H */
/*
Local Variables:
c-file-style: "gnu"
End:
*/

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1996,1998,2000,2001,2004,2005, 2006, 2008 Free Software Foundation, Inc. /* Copyright (C) 1996,1998,2000,2001,2004,2005, 2006, 2008, 2009 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -17,10 +17,6 @@
*/ */
/*
HWN:FIXME::
Someone should rename this to arraymap.c; that would reflect the
contents better. */
@ -31,7 +27,7 @@
#include "libguile/_scm.h" #include "libguile/_scm.h"
#include "libguile/strings.h" #include "libguile/strings.h"
#include "libguile/unif.h" #include "libguile/arrays.h"
#include "libguile/smob.h" #include "libguile/smob.h"
#include "libguile/chars.h" #include "libguile/chars.h"
#include "libguile/eq.h" #include "libguile/eq.h"
@ -39,11 +35,14 @@
#include "libguile/feature.h" #include "libguile/feature.h"
#include "libguile/root.h" #include "libguile/root.h"
#include "libguile/vectors.h" #include "libguile/vectors.h"
#include "libguile/bitvectors.h"
#include "libguile/srfi-4.h" #include "libguile/srfi-4.h"
#include "libguile/dynwind.h" #include "libguile/dynwind.h"
#include "libguile/generalized-arrays.h"
#include "libguile/generalized-vectors.h"
#include "libguile/validate.h" #include "libguile/validate.h"
#include "libguile/ramap.h" #include "libguile/array-map.h"
typedef struct typedef struct
@ -223,7 +222,7 @@ scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
if (!SCM_I_ARRAYP (vra0)) if (!SCM_I_ARRAYP (vra0))
{ {
size_t length = scm_c_generalized_vector_length (vra0); size_t length = scm_c_generalized_vector_length (vra0);
vra1 = scm_i_make_ra (1, 0); vra1 = scm_i_make_array (1);
SCM_I_ARRAY_BASE (vra1) = 0; SCM_I_ARRAY_BASE (vra1) = 0;
SCM_I_ARRAY_DIMS (vra1)->lbnd = 0; SCM_I_ARRAY_DIMS (vra1)->lbnd = 0;
SCM_I_ARRAY_DIMS (vra1)->ubnd = length - 1; SCM_I_ARRAY_DIMS (vra1)->ubnd = length - 1;
@ -236,7 +235,7 @@ scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
for (z = lra; SCM_NIMP (z); z = SCM_CDR (z)) for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
{ {
ra1 = SCM_CAR (z); ra1 = SCM_CAR (z);
vra1 = scm_i_make_ra (1, 0); vra1 = scm_i_make_array (1);
SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd; SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd; SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
if (!SCM_I_ARRAYP (ra1)) if (!SCM_I_ARRAYP (ra1))
@ -259,7 +258,7 @@ scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra)); return (SCM_UNBNDP (data) ? cproc(vra0, lvra) : cproc(vra0, data, lvra));
case 1: case 1:
gencase: /* Have to loop over all dimensions. */ gencase: /* Have to loop over all dimensions. */
vra0 = scm_i_make_ra (1, 0); vra0 = scm_i_make_array (1);
if (SCM_I_ARRAYP (ra0)) if (SCM_I_ARRAYP (ra0))
{ {
kmax = SCM_I_ARRAY_NDIM (ra0) - 1; kmax = SCM_I_ARRAY_NDIM (ra0) - 1;
@ -294,7 +293,7 @@ scm_ramapc (int (*cproc)(), SCM data, SCM ra0, SCM lra, const char *what)
for (z = lra; SCM_NIMP (z); z = SCM_CDR (z)) for (z = lra; SCM_NIMP (z); z = SCM_CDR (z))
{ {
ra1 = SCM_CAR (z); ra1 = SCM_CAR (z);
vra1 = scm_i_make_ra (1, 0); vra1 = scm_i_make_array (1);
SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd; SCM_I_ARRAY_DIMS (vra1)->lbnd = SCM_I_ARRAY_DIMS (vra0)->lbnd;
SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd; SCM_I_ARRAY_DIMS (vra1)->ubnd = SCM_I_ARRAY_DIMS (vra0)->ubnd;
if (SCM_I_ARRAYP (ra1)) if (SCM_I_ARRAYP (ra1))
@ -1222,13 +1221,13 @@ init_raprocs (ra_iproc *subra)
void void
scm_init_ramap () scm_init_array_map (void)
{ {
init_raprocs (ra_rpsubrs); init_raprocs (ra_rpsubrs);
init_raprocs (ra_asubrs); init_raprocs (ra_asubrs);
scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p); scm_c_define_subr (s_array_equal_p, scm_tc7_rpsubr, scm_array_equal_p);
scm_smobs[SCM_TC2SMOBNUM (scm_i_tc16_array)].equalp = scm_raequal; scm_smobs[SCM_TC2SMOBNUM (scm_i_tc16_array)].equalp = scm_raequal;
#include "libguile/ramap.x" #include "libguile/array-map.x"
scm_add_feature (s_scm_array_for_each); scm_add_feature (s_scm_array_for_each);
} }

View file

@ -1,9 +1,9 @@
/* classes: h_files */ /* classes: h_files */
#ifndef SCM_RAMAP_H #ifndef SCM_ARRAY_MAP_H
#define SCM_RAMAP_H #define SCM_ARRAY_MAP_H
/* Copyright (C) 1995,1996,1997,2000, 2006, 2008 Free Software Foundation, Inc. /* Copyright (C) 1995,1996,1997,2000, 2006, 2008, 2009 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -48,9 +48,9 @@ SCM_API SCM scm_array_for_each (SCM proc, SCM ra0, SCM lra);
SCM_API SCM scm_array_index_map_x (SCM ra, SCM proc); SCM_API SCM scm_array_index_map_x (SCM ra, SCM proc);
SCM_API SCM scm_raequal (SCM ra0, SCM ra1); SCM_API SCM scm_raequal (SCM ra0, SCM ra1);
SCM_API SCM scm_array_equal_p (SCM ra0, SCM ra1); SCM_API SCM scm_array_equal_p (SCM ra0, SCM ra1);
SCM_INTERNAL void scm_init_ramap (void); SCM_INTERNAL void scm_init_array_map (void);
#endif /* SCM_RAMAP_H */ #endif /* SCM_ARRAY_MAP_H */
/* /*
Local Variables: Local Variables:

1156
libguile/arrays.c Normal file

File diff suppressed because it is too large Load diff

91
libguile/arrays.h Normal file
View file

@ -0,0 +1,91 @@
/* classes: h_files */
#ifndef SCM_ARRAY_H
#define SCM_ARRAY_H
/* Copyright (C) 1995,1996,1997,1999,2000,2001, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "libguile/__scm.h"
#include "libguile/print.h"
/* Multidimensional arrays. Woo hoo!
Also see ....
*/
/** Arrays */
SCM_API SCM scm_make_array (SCM fill, SCM bounds);
SCM_API SCM scm_make_typed_array (SCM type, SCM fill, SCM bounds);
SCM_API SCM scm_from_contiguous_typed_array (SCM type, SCM bounds,
const void *bytes,
size_t byte_len);
SCM_API SCM scm_shared_array_root (SCM ra);
SCM_API SCM scm_shared_array_offset (SCM ra);
SCM_API SCM scm_shared_array_increments (SCM ra);
SCM_API SCM scm_make_shared_array (SCM oldra, SCM mapfunc, SCM dims);
SCM_API SCM scm_transpose_array (SCM ra, SCM args);
SCM_API SCM scm_array_contents (SCM ra, SCM strict);
SCM_API SCM scm_uniform_array_read_x (SCM ra, SCM port_or_fd,
SCM start, SCM end);
SCM_API SCM scm_uniform_array_write (SCM v, SCM port_or_fd,
SCM start, SCM end);
SCM_API SCM scm_list_to_array (SCM ndim, SCM lst);
SCM_API SCM scm_list_to_typed_array (SCM type, SCM ndim, SCM lst);
SCM_API SCM scm_ra2contig (SCM ra, int copy);
/* internal. */
typedef struct scm_i_t_array
{
SCM v; /* the contents of the array, e.g., a vector or uniform vector. */
unsigned long base;
} scm_i_t_array;
SCM_API scm_t_bits scm_i_tc16_array;
#define SCM_I_ARRAY_FLAG_CONTIGUOUS (1 << 16)
#define SCM_I_ARRAYP(a) SCM_TYP16_PREDICATE (scm_i_tc16_array, a)
#define SCM_I_ARRAY_NDIM(x) ((size_t) (SCM_CELL_WORD_0 (x) >> 17))
#define SCM_I_ARRAY_CONTP(x) (SCM_CELL_WORD_0(x) & SCM_I_ARRAY_FLAG_CONTIGUOUS)
#define SCM_I_ARRAY_MEM(a) ((scm_i_t_array *) SCM_CELL_WORD_1 (a))
#define SCM_I_ARRAY_V(a) (SCM_I_ARRAY_MEM (a)->v)
#define SCM_I_ARRAY_BASE(a) (SCM_I_ARRAY_MEM (a)->base)
#define SCM_I_ARRAY_DIMS(a) \
((scm_t_array_dim *)((char *) SCM_I_ARRAY_MEM (a) + sizeof (scm_i_t_array)))
SCM_INTERNAL SCM scm_i_make_array (int ndim);
SCM_INTERNAL SCM scm_i_read_array (SCM port, int c);
SCM_INTERNAL void scm_init_arrays (void);
#endif /* SCM_ARRAYS_H */
/*
Local Variables:
c-file-style: "gnu"
End:
*/

910
libguile/bitvectors.c Normal file
View file

@ -0,0 +1,910 @@
/* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004, 2005, 2006, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <string.h>
#include "libguile/_scm.h"
#include "libguile/__scm.h"
#include "libguile/smob.h"
#include "libguile/strings.h"
#include "libguile/array-handle.h"
#include "libguile/bitvectors.h"
#include "libguile/arrays.h"
#include "libguile/generalized-vectors.h"
#include "libguile/srfi-4.h"
/* Bit vectors. Would be nice if they were implemented on top of bytevectors,
* but alack, all we have is this crufty C.
*/
static scm_t_bits scm_tc16_bitvector;
#define IS_BITVECTOR(obj) SCM_SMOB_PREDICATE(scm_tc16_bitvector,(obj))
#define BITVECTOR_BITS(obj) ((scm_t_uint32 *)SCM_SMOB_DATA(obj))
#define BITVECTOR_LENGTH(obj) ((size_t)SCM_SMOB_DATA_2(obj))
static size_t
bitvector_free (SCM vec)
{
scm_gc_free (BITVECTOR_BITS (vec),
sizeof (scm_t_uint32) * ((BITVECTOR_LENGTH (vec)+31)/32),
"bitvector");
return 0;
}
static int
bitvector_print (SCM vec, SCM port, scm_print_state *pstate)
{
size_t bit_len = BITVECTOR_LENGTH (vec);
size_t word_len = (bit_len+31)/32;
scm_t_uint32 *bits = BITVECTOR_BITS (vec);
size_t i, j;
scm_puts ("#*", port);
for (i = 0; i < word_len; i++, bit_len -= 32)
{
scm_t_uint32 mask = 1;
for (j = 0; j < 32 && j < bit_len; j++, mask <<= 1)
scm_putc ((bits[i] & mask)? '1' : '0', port);
}
return 1;
}
static SCM
bitvector_equalp (SCM vec1, SCM vec2)
{
size_t bit_len = BITVECTOR_LENGTH (vec1);
size_t word_len = (bit_len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - bit_len);
scm_t_uint32 *bits1 = BITVECTOR_BITS (vec1);
scm_t_uint32 *bits2 = BITVECTOR_BITS (vec2);
/* compare lengths */
if (BITVECTOR_LENGTH (vec2) != bit_len)
return SCM_BOOL_F;
/* avoid underflow in word_len-1 below. */
if (bit_len == 0)
return SCM_BOOL_T;
/* compare full words */
if (memcmp (bits1, bits2, sizeof (scm_t_uint32) * (word_len-1)))
return SCM_BOOL_F;
/* compare partial last words */
if ((bits1[word_len-1] & last_mask) != (bits2[word_len-1] & last_mask))
return SCM_BOOL_F;
return SCM_BOOL_T;
}
int
scm_is_bitvector (SCM vec)
{
return IS_BITVECTOR (vec);
}
SCM_DEFINE (scm_bitvector_p, "bitvector?", 1, 0, 0,
(SCM obj),
"Return @code{#t} when @var{obj} is a bitvector, else\n"
"return @code{#f}.")
#define FUNC_NAME s_scm_bitvector_p
{
return scm_from_bool (scm_is_bitvector (obj));
}
#undef FUNC_NAME
SCM
scm_c_make_bitvector (size_t len, SCM fill)
{
size_t word_len = (len + 31) / 32;
scm_t_uint32 *bits;
SCM res;
bits = scm_gc_malloc (sizeof (scm_t_uint32) * word_len,
"bitvector");
SCM_NEWSMOB2 (res, scm_tc16_bitvector, bits, len);
if (!SCM_UNBNDP (fill))
scm_bitvector_fill_x (res, fill);
return res;
}
SCM_DEFINE (scm_make_bitvector, "make-bitvector", 1, 1, 0,
(SCM len, SCM fill),
"Create a new bitvector of length @var{len} and\n"
"optionally initialize all elements to @var{fill}.")
#define FUNC_NAME s_scm_make_bitvector
{
return scm_c_make_bitvector (scm_to_size_t (len), fill);
}
#undef FUNC_NAME
SCM_DEFINE (scm_bitvector, "bitvector", 0, 0, 1,
(SCM bits),
"Create a new bitvector with the arguments as elements.")
#define FUNC_NAME s_scm_bitvector
{
return scm_list_to_bitvector (bits);
}
#undef FUNC_NAME
size_t
scm_c_bitvector_length (SCM vec)
{
scm_assert_smob_type (scm_tc16_bitvector, vec);
return BITVECTOR_LENGTH (vec);
}
SCM_DEFINE (scm_bitvector_length, "bitvector-length", 1, 0, 0,
(SCM vec),
"Return the length of the bitvector @var{vec}.")
#define FUNC_NAME s_scm_bitvector_length
{
return scm_from_size_t (scm_c_bitvector_length (vec));
}
#undef FUNC_NAME
const scm_t_uint32 *
scm_array_handle_bit_elements (scm_t_array_handle *h)
{
return scm_array_handle_bit_writable_elements (h);
}
scm_t_uint32 *
scm_array_handle_bit_writable_elements (scm_t_array_handle *h)
{
SCM vec = h->array;
if (SCM_I_ARRAYP (vec))
vec = SCM_I_ARRAY_V (vec);
if (IS_BITVECTOR (vec))
return BITVECTOR_BITS (vec) + h->base/32;
scm_wrong_type_arg_msg (NULL, 0, h->array, "bit array");
}
size_t
scm_array_handle_bit_elements_offset (scm_t_array_handle *h)
{
return h->base % 32;
}
const scm_t_uint32 *
scm_bitvector_elements (SCM vec,
scm_t_array_handle *h,
size_t *offp,
size_t *lenp,
ssize_t *incp)
{
return scm_bitvector_writable_elements (vec, h, offp, lenp, incp);
}
scm_t_uint32 *
scm_bitvector_writable_elements (SCM vec,
scm_t_array_handle *h,
size_t *offp,
size_t *lenp,
ssize_t *incp)
{
scm_generalized_vector_get_handle (vec, h);
if (offp)
{
scm_t_array_dim *dim = scm_array_handle_dims (h);
*offp = scm_array_handle_bit_elements_offset (h);
*lenp = dim->ubnd - dim->lbnd + 1;
*incp = dim->inc;
}
return scm_array_handle_bit_writable_elements (h);
}
SCM
scm_c_bitvector_ref (SCM vec, size_t idx)
{
scm_t_array_handle handle;
const scm_t_uint32 *bits;
if (IS_BITVECTOR (vec))
{
if (idx >= BITVECTOR_LENGTH (vec))
scm_out_of_range (NULL, scm_from_size_t (idx));
bits = BITVECTOR_BITS(vec);
return scm_from_bool (bits[idx/32] & (1L << (idx%32)));
}
else
{
SCM res;
size_t len, off;
ssize_t inc;
bits = scm_bitvector_elements (vec, &handle, &off, &len, &inc);
if (idx >= len)
scm_out_of_range (NULL, scm_from_size_t (idx));
idx = idx*inc + off;
res = scm_from_bool (bits[idx/32] & (1L << (idx%32)));
scm_array_handle_release (&handle);
return res;
}
}
SCM_DEFINE (scm_bitvector_ref, "bitvector-ref", 2, 0, 0,
(SCM vec, SCM idx),
"Return the element at index @var{idx} of the bitvector\n"
"@var{vec}.")
#define FUNC_NAME s_scm_bitvector_ref
{
return scm_c_bitvector_ref (vec, scm_to_size_t (idx));
}
#undef FUNC_NAME
void
scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val)
{
scm_t_array_handle handle;
scm_t_uint32 *bits, mask;
if (IS_BITVECTOR (vec))
{
if (idx >= BITVECTOR_LENGTH (vec))
scm_out_of_range (NULL, scm_from_size_t (idx));
bits = BITVECTOR_BITS(vec);
}
else
{
size_t len, off;
ssize_t inc;
bits = scm_bitvector_writable_elements (vec, &handle, &off, &len, &inc);
if (idx >= len)
scm_out_of_range (NULL, scm_from_size_t (idx));
idx = idx*inc + off;
}
mask = 1L << (idx%32);
if (scm_is_true (val))
bits[idx/32] |= mask;
else
bits[idx/32] &= ~mask;
if (!IS_BITVECTOR (vec))
scm_array_handle_release (&handle);
}
SCM_DEFINE (scm_bitvector_set_x, "bitvector-set!", 3, 0, 0,
(SCM vec, SCM idx, SCM val),
"Set the element at index @var{idx} of the bitvector\n"
"@var{vec} when @var{val} is true, else clear it.")
#define FUNC_NAME s_scm_bitvector_set_x
{
scm_c_bitvector_set_x (vec, scm_to_size_t (idx), val);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bitvector_fill_x, "bitvector-fill!", 2, 0, 0,
(SCM vec, SCM val),
"Set all elements of the bitvector\n"
"@var{vec} when @var{val} is true, else clear them.")
#define FUNC_NAME s_scm_bitvector_fill_x
{
scm_t_array_handle handle;
size_t off, len;
ssize_t inc;
scm_t_uint32 *bits;
bits = scm_bitvector_writable_elements (vec, &handle,
&off, &len, &inc);
if (off == 0 && inc == 1 && len > 0)
{
/* the usual case
*/
size_t word_len = (len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
if (scm_is_true (val))
{
memset (bits, 0xFF, sizeof(scm_t_uint32)*(word_len-1));
bits[word_len-1] |= last_mask;
}
else
{
memset (bits, 0x00, sizeof(scm_t_uint32)*(word_len-1));
bits[word_len-1] &= ~last_mask;
}
}
else
{
size_t i;
for (i = 0; i < len; i++)
scm_array_handle_set (&handle, i*inc, val);
}
scm_array_handle_release (&handle);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_list_to_bitvector, "list->bitvector", 1, 0, 0,
(SCM list),
"Return a new bitvector initialized with the elements\n"
"of @var{list}.")
#define FUNC_NAME s_scm_list_to_bitvector
{
size_t bit_len = scm_to_size_t (scm_length (list));
SCM vec = scm_c_make_bitvector (bit_len, SCM_UNDEFINED);
size_t word_len = (bit_len+31)/32;
scm_t_array_handle handle;
scm_t_uint32 *bits = scm_bitvector_writable_elements (vec, &handle,
NULL, NULL, NULL);
size_t i, j;
for (i = 0; i < word_len && scm_is_pair (list); i++, bit_len -= 32)
{
scm_t_uint32 mask = 1;
bits[i] = 0;
for (j = 0; j < 32 && j < bit_len;
j++, mask <<= 1, list = SCM_CDR (list))
if (scm_is_true (SCM_CAR (list)))
bits[i] |= mask;
}
scm_array_handle_release (&handle);
return vec;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bitvector_to_list, "bitvector->list", 1, 0, 0,
(SCM vec),
"Return a new list initialized with the elements\n"
"of the bitvector @var{vec}.")
#define FUNC_NAME s_scm_bitvector_to_list
{
scm_t_array_handle handle;
size_t off, len;
ssize_t inc;
scm_t_uint32 *bits;
SCM res = SCM_EOL;
bits = scm_bitvector_writable_elements (vec, &handle,
&off, &len, &inc);
if (off == 0 && inc == 1)
{
/* the usual case
*/
size_t word_len = (len + 31) / 32;
size_t i, j;
for (i = 0; i < word_len; i++, len -= 32)
{
scm_t_uint32 mask = 1;
for (j = 0; j < 32 && j < len; j++, mask <<= 1)
res = scm_cons ((bits[i] & mask)? SCM_BOOL_T : SCM_BOOL_F, res);
}
}
else
{
size_t i;
for (i = 0; i < len; i++)
res = scm_cons (scm_array_handle_ref (&handle, i*inc), res);
}
scm_array_handle_release (&handle);
return scm_reverse_x (res, SCM_EOL);
}
#undef FUNC_NAME
/* From mmix-arith.w by Knuth.
Here's a fun way to count the number of bits in a tetrabyte.
[This classical trick is called the ``Gillies--Miller method for
sideways addition'' in {\sl The Preparation of Programs for an
Electronic Digital Computer\/} by Wilkes, Wheeler, and Gill, second
edition (Reading, Mass.:\ Addison--Wesley, 1957), 191--193. Some of
the tricks used here were suggested by Balbir Singh, Peter
Rossmanith, and Stefan Schwoon.]
*/
static size_t
count_ones (scm_t_uint32 x)
{
x=x-((x>>1)&0x55555555);
x=(x&0x33333333)+((x>>2)&0x33333333);
x=(x+(x>>4))&0x0f0f0f0f;
x=x+(x>>8);
return (x+(x>>16)) & 0xff;
}
SCM_DEFINE (scm_bit_count, "bit-count", 2, 0, 0,
(SCM b, SCM bitvector),
"Return the number of occurrences of the boolean @var{b} in\n"
"@var{bitvector}.")
#define FUNC_NAME s_scm_bit_count
{
scm_t_array_handle handle;
size_t off, len;
ssize_t inc;
scm_t_uint32 *bits;
int bit = scm_to_bool (b);
size_t count = 0;
bits = scm_bitvector_writable_elements (bitvector, &handle,
&off, &len, &inc);
if (off == 0 && inc == 1 && len > 0)
{
/* the usual case
*/
size_t word_len = (len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
size_t i;
for (i = 0; i < word_len-1; i++)
count += count_ones (bits[i]);
count += count_ones (bits[i] & last_mask);
}
else
{
size_t i;
for (i = 0; i < len; i++)
if (scm_is_true (scm_array_handle_ref (&handle, i*inc)))
count++;
}
scm_array_handle_release (&handle);
return scm_from_size_t (bit? count : len-count);
}
#undef FUNC_NAME
/* returns 32 for x == 0.
*/
static size_t
find_first_one (scm_t_uint32 x)
{
size_t pos = 0;
/* do a binary search in x. */
if ((x & 0xFFFF) == 0)
x >>= 16, pos += 16;
if ((x & 0xFF) == 0)
x >>= 8, pos += 8;
if ((x & 0xF) == 0)
x >>= 4, pos += 4;
if ((x & 0x3) == 0)
x >>= 2, pos += 2;
if ((x & 0x1) == 0)
pos += 1;
return pos;
}
SCM_DEFINE (scm_bit_position, "bit-position", 3, 0, 0,
(SCM item, SCM v, SCM k),
"Return the index of the first occurrance of @var{item} in bit\n"
"vector @var{v}, starting from @var{k}. If there is no\n"
"@var{item} entry between @var{k} and the end of\n"
"@var{bitvector}, then return @code{#f}. For example,\n"
"\n"
"@example\n"
"(bit-position #t #*000101 0) @result{} 3\n"
"(bit-position #f #*0001111 3) @result{} #f\n"
"@end example")
#define FUNC_NAME s_scm_bit_position
{
scm_t_array_handle handle;
size_t off, len, first_bit;
ssize_t inc;
const scm_t_uint32 *bits;
int bit = scm_to_bool (item);
SCM res = SCM_BOOL_F;
bits = scm_bitvector_elements (v, &handle, &off, &len, &inc);
first_bit = scm_to_unsigned_integer (k, 0, len);
if (off == 0 && inc == 1 && len > 0)
{
size_t i, word_len = (len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
size_t first_word = first_bit / 32;
scm_t_uint32 first_mask =
((scm_t_uint32)-1) << (first_bit - 32*first_word);
scm_t_uint32 w;
for (i = first_word; i < word_len; i++)
{
w = (bit? bits[i] : ~bits[i]);
if (i == first_word)
w &= first_mask;
if (i == word_len-1)
w &= last_mask;
if (w)
{
res = scm_from_size_t (32*i + find_first_one (w));
break;
}
}
}
else
{
size_t i;
for (i = first_bit; i < len; i++)
{
SCM elt = scm_array_handle_ref (&handle, i*inc);
if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
{
res = scm_from_size_t (i);
break;
}
}
}
scm_array_handle_release (&handle);
return res;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bit_set_star_x, "bit-set*!", 3, 0, 0,
(SCM v, SCM kv, SCM obj),
"Set entries of bit vector @var{v} to @var{obj}, with @var{kv}\n"
"selecting the entries to change. The return value is\n"
"unspecified.\n"
"\n"
"If @var{kv} is a bit vector, then those entries where it has\n"
"@code{#t} are the ones in @var{v} which are set to @var{obj}.\n"
"@var{kv} and @var{v} must be the same length. When @var{obj}\n"
"is @code{#t} it's like @var{kv} is OR'ed into @var{v}. Or when\n"
"@var{obj} is @code{#f} it can be seen as an ANDNOT.\n"
"\n"
"@example\n"
"(define bv #*01000010)\n"
"(bit-set*! bv #*10010001 #t)\n"
"bv\n"
"@result{} #*11010011\n"
"@end example\n"
"\n"
"If @var{kv} is a u32vector, then its elements are\n"
"indices into @var{v} which are set to @var{obj}.\n"
"\n"
"@example\n"
"(define bv #*01000010)\n"
"(bit-set*! bv #u32(5 2 7) #t)\n"
"bv\n"
"@result{} #*01100111\n"
"@end example")
#define FUNC_NAME s_scm_bit_set_star_x
{
scm_t_array_handle v_handle;
size_t v_off, v_len;
ssize_t v_inc;
scm_t_uint32 *v_bits;
int bit;
/* Validate that OBJ is a boolean so this is done even if we don't
need BIT.
*/
bit = scm_to_bool (obj);
v_bits = scm_bitvector_writable_elements (v, &v_handle,
&v_off, &v_len, &v_inc);
if (scm_is_bitvector (kv))
{
scm_t_array_handle kv_handle;
size_t kv_off, kv_len;
ssize_t kv_inc;
const scm_t_uint32 *kv_bits;
kv_bits = scm_bitvector_elements (v, &kv_handle,
&kv_off, &kv_len, &kv_inc);
if (v_len != kv_len)
scm_misc_error (NULL,
"bit vectors must have equal length",
SCM_EOL);
if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
{
size_t word_len = (kv_len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - kv_len);
size_t i;
if (bit == 0)
{
for (i = 0; i < word_len-1; i++)
v_bits[i] &= ~kv_bits[i];
v_bits[i] &= ~(kv_bits[i] & last_mask);
}
else
{
for (i = 0; i < word_len-1; i++)
v_bits[i] |= kv_bits[i];
v_bits[i] |= kv_bits[i] & last_mask;
}
}
else
{
size_t i;
for (i = 0; i < kv_len; i++)
if (scm_is_true (scm_array_handle_ref (&kv_handle, i*kv_inc)))
scm_array_handle_set (&v_handle, i*v_inc, obj);
}
scm_array_handle_release (&kv_handle);
}
else if (scm_is_true (scm_u32vector_p (kv)))
{
scm_t_array_handle kv_handle;
size_t i, kv_len;
ssize_t kv_inc;
const scm_t_uint32 *kv_elts;
kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
scm_array_handle_set (&v_handle, (*kv_elts)*v_inc, obj);
scm_array_handle_release (&kv_handle);
}
else
scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
scm_array_handle_release (&v_handle);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM_DEFINE (scm_bit_count_star, "bit-count*", 3, 0, 0,
(SCM v, SCM kv, SCM obj),
"Return a count of how many entries in bit vector @var{v} are\n"
"equal to @var{obj}, with @var{kv} selecting the entries to\n"
"consider.\n"
"\n"
"If @var{kv} is a bit vector, then those entries where it has\n"
"@code{#t} are the ones in @var{v} which are considered.\n"
"@var{kv} and @var{v} must be the same length.\n"
"\n"
"If @var{kv} is a u32vector, then it contains\n"
"the indexes in @var{v} to consider.\n"
"\n"
"For example,\n"
"\n"
"@example\n"
"(bit-count* #*01110111 #*11001101 #t) @result{} 3\n"
"(bit-count* #*01110111 #u32(7 0 4) #f) @result{} 2\n"
"@end example")
#define FUNC_NAME s_scm_bit_count_star
{
scm_t_array_handle v_handle;
size_t v_off, v_len;
ssize_t v_inc;
const scm_t_uint32 *v_bits;
size_t count = 0;
int bit;
/* Validate that OBJ is a boolean so this is done even if we don't
need BIT.
*/
bit = scm_to_bool (obj);
v_bits = scm_bitvector_elements (v, &v_handle,
&v_off, &v_len, &v_inc);
if (scm_is_bitvector (kv))
{
scm_t_array_handle kv_handle;
size_t kv_off, kv_len;
ssize_t kv_inc;
const scm_t_uint32 *kv_bits;
kv_bits = scm_bitvector_elements (v, &kv_handle,
&kv_off, &kv_len, &kv_inc);
if (v_len != kv_len)
scm_misc_error (NULL,
"bit vectors must have equal length",
SCM_EOL);
if (v_off == 0 && v_inc == 1 && kv_off == 0 && kv_inc == 1 && kv_len > 0)
{
size_t i, word_len = (kv_len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - kv_len);
scm_t_uint32 xor_mask = bit? 0 : ((scm_t_uint32)-1);
for (i = 0; i < word_len-1; i++)
count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i]);
count += count_ones ((v_bits[i]^xor_mask) & kv_bits[i] & last_mask);
}
else
{
size_t i;
for (i = 0; i < kv_len; i++)
if (scm_is_true (scm_array_handle_ref (&kv_handle, i)))
{
SCM elt = scm_array_handle_ref (&v_handle, i*v_inc);
if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
count++;
}
}
scm_array_handle_release (&kv_handle);
}
else if (scm_is_true (scm_u32vector_p (kv)))
{
scm_t_array_handle kv_handle;
size_t i, kv_len;
ssize_t kv_inc;
const scm_t_uint32 *kv_elts;
kv_elts = scm_u32vector_elements (kv, &kv_handle, &kv_len, &kv_inc);
for (i = 0; i < kv_len; i++, kv_elts += kv_inc)
{
SCM elt = scm_array_handle_ref (&v_handle, (*kv_elts)*v_inc);
if ((bit && scm_is_true (elt)) || (!bit && scm_is_false (elt)))
count++;
}
scm_array_handle_release (&kv_handle);
}
else
scm_wrong_type_arg_msg (NULL, 0, kv, "bitvector or u32vector");
scm_array_handle_release (&v_handle);
return scm_from_size_t (count);
}
#undef FUNC_NAME
SCM_DEFINE (scm_bit_invert_x, "bit-invert!", 1, 0, 0,
(SCM v),
"Modify the bit vector @var{v} by replacing each element with\n"
"its negation.")
#define FUNC_NAME s_scm_bit_invert_x
{
scm_t_array_handle handle;
size_t off, len;
ssize_t inc;
scm_t_uint32 *bits;
bits = scm_bitvector_writable_elements (v, &handle, &off, &len, &inc);
if (off == 0 && inc == 1 && len > 0)
{
size_t word_len = (len + 31) / 32;
scm_t_uint32 last_mask = ((scm_t_uint32)-1) >> (32*word_len - len);
size_t i;
for (i = 0; i < word_len-1; i++)
bits[i] = ~bits[i];
bits[i] = bits[i] ^ last_mask;
}
else
{
size_t i;
for (i = 0; i < len; i++)
scm_array_handle_set (&handle, i*inc,
scm_not (scm_array_handle_ref (&handle, i*inc)));
}
scm_array_handle_release (&handle);
return SCM_UNSPECIFIED;
}
#undef FUNC_NAME
SCM
scm_istr2bve (SCM str)
{
scm_t_array_handle handle;
size_t len = scm_i_string_length (str);
SCM vec = scm_c_make_bitvector (len, SCM_UNDEFINED);
SCM res = vec;
scm_t_uint32 mask;
size_t k, j;
const char *c_str;
scm_t_uint32 *data;
data = scm_bitvector_writable_elements (vec, &handle, NULL, NULL, NULL);
c_str = scm_i_string_chars (str);
for (k = 0; k < (len + 31) / 32; k++)
{
data[k] = 0L;
j = len - k * 32;
if (j > 32)
j = 32;
for (mask = 1L; j--; mask <<= 1)
switch (*c_str++)
{
case '0':
break;
case '1':
data[k] |= mask;
break;
default:
res = SCM_BOOL_F;
goto exit;
}
}
exit:
scm_array_handle_release (&handle);
scm_remember_upto_here_1 (str);
return res;
}
/* FIXME: h->array should be h->vector */
static SCM
bitvector_handle_ref (scm_t_array_handle *h, size_t pos)
{
return scm_c_bitvector_ref (h->array, pos);
}
static void
bitvector_handle_set (scm_t_array_handle *h, size_t pos, SCM val)
{
scm_c_bitvector_set_x (h->array, pos, val);
}
static void
bitvector_get_handle (SCM bv, scm_t_array_handle *h)
{
h->array = bv;
h->ndims = 1;
h->dims = &h->dim0;
h->dim0.lbnd = 0;
h->dim0.ubnd = BITVECTOR_LENGTH (bv) - 1;
h->dim0.inc = 1;
h->element_type = SCM_ARRAY_ELEMENT_TYPE_BIT;
h->elements = h->writable_elements = BITVECTOR_BITS (bv);
}
SCM_ARRAY_IMPLEMENTATION (scm_tc16_bitvector, 0xffff,
bitvector_handle_ref, bitvector_handle_set,
bitvector_get_handle);
SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_BIT, scm_make_bitvector);
void
scm_init_bitvectors ()
{
scm_tc16_bitvector = scm_make_smob_type ("bitvector", 0);
scm_set_smob_free (scm_tc16_bitvector, bitvector_free);
scm_set_smob_print (scm_tc16_bitvector, bitvector_print);
scm_set_smob_equalp (scm_tc16_bitvector, bitvector_equalp);
#include "libguile/bitvectors.x"
}
/*
Local Variables:
c-file-style: "gnu"
End:
*/

81
libguile/bitvectors.h Normal file
View file

@ -0,0 +1,81 @@
/* classes: h_files */
#ifndef SCM_BITVECTORS_H
#define SCM_BITVECTORS_H
/* Copyright (C) 1995,1996,1997,1999,2000,2001, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "libguile/__scm.h"
#include "libguile/array-handle.h"
/* Bitvectors. Exciting stuff, maybe!
*/
/** Bit vectors */
SCM_API SCM scm_bitvector_p (SCM vec);
SCM_API SCM scm_bitvector (SCM bits);
SCM_API SCM scm_make_bitvector (SCM len, SCM fill);
SCM_API SCM scm_bitvector_length (SCM vec);
SCM_API SCM scm_bitvector_ref (SCM vec, SCM idx);
SCM_API SCM scm_bitvector_set_x (SCM vec, SCM idx, SCM val);
SCM_API SCM scm_list_to_bitvector (SCM list);
SCM_API SCM scm_bitvector_to_list (SCM vec);
SCM_API SCM scm_bitvector_fill_x (SCM vec, SCM val);
SCM_API SCM scm_bit_count (SCM item, SCM seq);
SCM_API SCM scm_bit_position (SCM item, SCM v, SCM k);
SCM_API SCM scm_bit_set_star_x (SCM v, SCM kv, SCM obj);
SCM_API SCM scm_bit_count_star (SCM v, SCM kv, SCM obj);
SCM_API SCM scm_bit_invert_x (SCM v);
SCM_API SCM scm_istr2bve (SCM str);
SCM_API int scm_is_bitvector (SCM obj);
SCM_API SCM scm_c_make_bitvector (size_t len, SCM fill);
SCM_API size_t scm_c_bitvector_length (SCM vec);
SCM_API SCM scm_c_bitvector_ref (SCM vec, size_t idx);
SCM_API void scm_c_bitvector_set_x (SCM vec, size_t idx, SCM val);
SCM_API const scm_t_uint32 *scm_array_handle_bit_elements (scm_t_array_handle *h);
SCM_API scm_t_uint32 *scm_array_handle_bit_writable_elements (scm_t_array_handle *h);
SCM_API size_t scm_array_handle_bit_elements_offset (scm_t_array_handle *h);
SCM_API const scm_t_uint32 *scm_bitvector_elements (SCM vec,
scm_t_array_handle *h,
size_t *offp,
size_t *lenp,
ssize_t *incp);
SCM_API scm_t_uint32 *scm_bitvector_writable_elements (SCM vec,
scm_t_array_handle *h,
size_t *offp,
size_t *lenp,
ssize_t *incp);
SCM_INTERNAL void scm_init_bitvectors (void);
#endif /* SCM_BITVECTORS_H */
/*
Local Variables:
c-file-style: "gnu"
End:
*/

View file

@ -31,7 +31,9 @@
#include "libguile/strings.h" #include "libguile/strings.h"
#include "libguile/validate.h" #include "libguile/validate.h"
#include "libguile/ieee-754.h" #include "libguile/ieee-754.h"
#include "libguile/unif.h" #include "libguile/arrays.h"
#include "libguile/array-handle.h"
#include "libguile/uniform.h"
#include "libguile/srfi-4.h" #include "libguile/srfi-4.h"
#include <byteswap.h> #include <byteswap.h>
@ -175,48 +177,99 @@
scm_t_bits scm_tc16_bytevector; scm_t_bits scm_tc16_bytevector;
#define SCM_BYTEVECTOR_SET_LENGTH(_bv, _len) \ #define SCM_BYTEVECTOR_INLINE_THRESHOLD (2 * sizeof (SCM))
#define SCM_BYTEVECTOR_INLINEABLE_SIZE_P(_size) \
((_size) <= SCM_BYTEVECTOR_INLINE_THRESHOLD)
#define SCM_BYTEVECTOR_SET_LENGTH(_bv, _len) \
SCM_SET_SMOB_DATA ((_bv), (scm_t_bits) (_len)) SCM_SET_SMOB_DATA ((_bv), (scm_t_bits) (_len))
#define SCM_BYTEVECTOR_SET_CONTENTS(_bv, _buf) \ #define SCM_BYTEVECTOR_SET_CONTENTS(_bv, _buf) \
SCM_SET_SMOB_DATA_2 ((_bv), (scm_t_bits) (_buf)) SCM_SET_SMOB_DATA_2 ((_bv), (scm_t_bits) (_buf))
#define SCM_BYTEVECTOR_SET_INLINE(bv) \
SCM_SET_SMOB_FLAGS (bv, SCM_SMOB_FLAGS (bv) | SCM_F_BYTEVECTOR_INLINE)
#define SCM_BYTEVECTOR_SET_ELEMENT_TYPE(bv, hint) \
SCM_SET_SMOB_FLAGS (bv, (SCM_SMOB_FLAGS (bv) & 0xFF) | (hint << 8))
#define SCM_BYTEVECTOR_TYPE_SIZE(var) \
(scm_i_array_element_type_sizes[SCM_BYTEVECTOR_ELEMENT_TYPE (var)]/8)
#define SCM_BYTEVECTOR_TYPED_LENGTH(var) \
SCM_BYTEVECTOR_LENGTH (var) / SCM_BYTEVECTOR_TYPE_SIZE (var)
/* The empty bytevector. */ /* The empty bytevector. */
SCM scm_null_bytevector = SCM_UNSPECIFIED; SCM scm_null_bytevector = SCM_UNSPECIFIED;
static inline SCM static inline SCM
make_bytevector_from_buffer (size_t len, signed char *contents) make_bytevector_from_buffer (size_t len, void *contents,
scm_t_array_element_type element_type)
{ {
/* Assuming LEN > SCM_BYTEVECTOR_INLINE_THRESHOLD. */ SCM ret;
SCM_RETURN_NEWSMOB2 (scm_tc16_bytevector, len, contents); size_t c_len;
if (SCM_UNLIKELY (element_type > SCM_ARRAY_ELEMENT_TYPE_LAST
|| scm_i_array_element_type_sizes[element_type] < 8
|| len >= (SCM_I_SIZE_MAX
/ (scm_i_array_element_type_sizes[element_type]/8))))
/* This would be an internal Guile programming error */
abort ();
c_len = len * (scm_i_array_element_type_sizes[element_type] / 8);
if (!SCM_BYTEVECTOR_INLINEABLE_SIZE_P (c_len))
SCM_NEWSMOB2 (ret, scm_tc16_bytevector, c_len, contents);
else
{
SCM_NEWSMOB2 (ret, scm_tc16_bytevector, c_len, NULL);
SCM_BYTEVECTOR_SET_INLINE (ret);
if (contents)
{
memcpy (SCM_BYTEVECTOR_CONTENTS (ret), contents, c_len);
scm_gc_free (contents, c_len, SCM_GC_BYTEVECTOR);
}
}
SCM_BYTEVECTOR_SET_ELEMENT_TYPE (ret, element_type);
return ret;
} }
static inline SCM static inline SCM
make_bytevector (size_t len) make_bytevector (size_t len, scm_t_array_element_type element_type)
{ {
SCM bv; size_t c_len;
if (SCM_UNLIKELY (len == 0)) if (SCM_UNLIKELY (len == 0 && element_type == 0))
bv = scm_null_bytevector; return scm_null_bytevector;
else if (SCM_UNLIKELY (element_type > SCM_ARRAY_ELEMENT_TYPE_LAST
|| scm_i_array_element_type_sizes[element_type] < 8
|| len >= (SCM_I_SIZE_MAX
/ (scm_i_array_element_type_sizes[element_type]/8))))
/* This would be an internal Guile programming error */
abort ();
c_len = len * (scm_i_array_element_type_sizes[element_type]/8);
if (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (c_len))
{
SCM ret;
SCM_NEWSMOB2 (ret, scm_tc16_bytevector, c_len, NULL);
SCM_BYTEVECTOR_SET_INLINE (ret);
SCM_BYTEVECTOR_SET_ELEMENT_TYPE (ret, element_type);
return ret;
}
else else
{ {
signed char *contents = NULL; void *buf = scm_gc_malloc_pointerless (c_len, SCM_GC_BYTEVECTOR);
return make_bytevector_from_buffer (len, buf, element_type);
if (!SCM_BYTEVECTOR_INLINEABLE_SIZE_P (len))
contents = (signed char *)
scm_gc_malloc_pointerless (len, SCM_GC_BYTEVECTOR);
bv = make_bytevector_from_buffer (len, contents);
} }
return bv;
} }
/* Return a new bytevector of size LEN octets. */ /* Return a new bytevector of size LEN octets. */
SCM SCM
scm_c_make_bytevector (size_t len) scm_c_make_bytevector (size_t len)
{ {
return (make_bytevector (len)); return make_bytevector (len, SCM_ARRAY_ELEMENT_TYPE_VU8);
}
/* Return a new bytevector of size LEN elements. */
SCM
scm_i_make_typed_bytevector (size_t len, scm_t_array_element_type element_type)
{
return make_bytevector (len, element_type);
} }
/* Return a bytevector of size LEN made up of CONTENTS. The area pointed to /* Return a bytevector of size LEN made up of CONTENTS. The area pointed to
@ -224,22 +277,14 @@ scm_c_make_bytevector (size_t len)
SCM SCM
scm_c_take_bytevector (signed char *contents, size_t len) scm_c_take_bytevector (signed char *contents, size_t len)
{ {
SCM bv; return make_bytevector_from_buffer (len, contents, SCM_ARRAY_ELEMENT_TYPE_VU8);
}
if (SCM_UNLIKELY (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (len))) SCM
{ scm_c_take_typed_bytevector (signed char *contents, size_t len,
/* Copy CONTENTS into an "in-line" buffer, then free CONTENTS. */ scm_t_array_element_type element_type)
signed char *c_bv; {
return make_bytevector_from_buffer (len, contents, element_type);
bv = make_bytevector (len);
c_bv = SCM_BYTEVECTOR_CONTENTS (bv);
memcpy (c_bv, contents, len);
scm_gc_free (contents, len, SCM_GC_BYTEVECTOR);
}
else
bv = make_bytevector_from_buffer (len, contents);
return bv;
} }
/* Shrink BV to C_NEW_LEN (which is assumed to be smaller than its current /* Shrink BV to C_NEW_LEN (which is assumed to be smaller than its current
@ -247,6 +292,10 @@ scm_c_take_bytevector (signed char *contents, size_t len)
SCM SCM
scm_i_shrink_bytevector (SCM bv, size_t c_new_len) scm_i_shrink_bytevector (SCM bv, size_t c_new_len)
{ {
if (SCM_UNLIKELY (c_new_len % SCM_BYTEVECTOR_TYPE_SIZE (bv)))
/* This would be an internal Guile programming error */
abort ();
if (!SCM_BYTEVECTOR_INLINE_P (bv)) if (!SCM_BYTEVECTOR_INLINE_P (bv))
{ {
size_t c_len; size_t c_len;
@ -260,6 +309,7 @@ scm_i_shrink_bytevector (SCM bv, size_t c_new_len)
if (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (c_new_len)) if (SCM_BYTEVECTOR_INLINEABLE_SIZE_P (c_new_len))
{ {
/* Copy to the in-line buffer and free the current buffer. */ /* Copy to the in-line buffer and free the current buffer. */
SCM_BYTEVECTOR_SET_INLINE (bv);
c_new_bv = SCM_BYTEVECTOR_CONTENTS (bv); c_new_bv = SCM_BYTEVECTOR_CONTENTS (bv);
memcpy (c_new_bv, c_bv, c_new_len); memcpy (c_new_bv, c_bv, c_new_len);
scm_gc_free (c_bv, c_len, SCM_GC_BYTEVECTOR); scm_gc_free (c_bv, c_len, SCM_GC_BYTEVECTOR);
@ -272,6 +322,8 @@ scm_i_shrink_bytevector (SCM bv, size_t c_new_len)
SCM_BYTEVECTOR_SET_CONTENTS (bv, c_new_bv); SCM_BYTEVECTOR_SET_CONTENTS (bv, c_new_bv);
} }
} }
else
SCM_BYTEVECTOR_SET_LENGTH (bv, c_new_len);
return bv; return bv;
} }
@ -330,38 +382,30 @@ scm_c_bytevector_set_x (SCM bv, size_t index, scm_t_uint8 value)
} }
#undef FUNC_NAME #undef FUNC_NAME
/* This procedure is used by `scm_c_generalized_vector_set_x ()'. */
void
scm_i_bytevector_generalized_set_x (SCM bv, size_t index, SCM value)
#define FUNC_NAME "scm_i_bytevector_generalized_set_x"
{
scm_c_bytevector_set_x (bv, index, scm_to_uint8 (value));
}
#undef FUNC_NAME
static int static int
print_bytevector (SCM bv, SCM port, scm_print_state *pstate) print_bytevector (SCM bv, SCM port, scm_print_state *pstate SCM_UNUSED)
{ {
unsigned c_len, i; ssize_t ubnd, inc, i;
unsigned char *c_bv; scm_t_array_handle h;
scm_array_get_handle (bv, &h);
c_len = SCM_BYTEVECTOR_LENGTH (bv); scm_putc ('#', port);
c_bv = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv); scm_write (scm_array_handle_element_type (&h), port);
scm_putc ('(', port);
scm_puts ("#vu8(", port); for (i = h.dims[0].lbnd, ubnd = h.dims[0].ubnd, inc = h.dims[0].inc;
for (i = 0; i < c_len; i++) i <= ubnd; i += inc)
{ {
if (i > 0) if (i > 0)
scm_putc (' ', port); scm_putc (' ', port);
scm_write (scm_array_handle_ref (&h, i), port);
scm_uintprint (c_bv[i], 10, port);
} }
scm_putc (')', port); scm_putc (')', port);
/* Make GCC think we use it. */
scm_remember_upto_here ((SCM) pstate);
return 1; return 1;
} }
@ -430,7 +474,7 @@ SCM_DEFINE (scm_make_bytevector, "make-bytevector", 1, 1, 0,
c_fill = (signed char) value; c_fill = (signed char) value;
} }
bv = make_bytevector (c_len); bv = make_bytevector (c_len, SCM_ARRAY_ELEMENT_TYPE_VU8);
if (fill != SCM_UNDEFINED) if (fill != SCM_UNDEFINED)
{ {
unsigned i; unsigned i;
@ -556,7 +600,7 @@ SCM_DEFINE (scm_bytevector_copy, "bytevector-copy", 1, 0, 0,
c_len = SCM_BYTEVECTOR_LENGTH (bv); c_len = SCM_BYTEVECTOR_LENGTH (bv);
c_bv = SCM_BYTEVECTOR_CONTENTS (bv); c_bv = SCM_BYTEVECTOR_CONTENTS (bv);
copy = make_bytevector (c_len); copy = make_bytevector (c_len, SCM_BYTEVECTOR_ELEMENT_TYPE (bv));
c_copy = SCM_BYTEVECTOR_CONTENTS (copy); c_copy = SCM_BYTEVECTOR_CONTENTS (copy);
memcpy (c_copy, c_bv, c_len); memcpy (c_copy, c_bv, c_len);
@ -586,7 +630,7 @@ SCM_DEFINE (scm_uniform_array_to_bytevector, "uniform-array->bytevector",
len = h.dims->inc * (h.dims->ubnd - h.dims->lbnd + 1); len = h.dims->inc * (h.dims->ubnd - h.dims->lbnd + 1);
sz = scm_array_handle_uniform_element_size (&h); sz = scm_array_handle_uniform_element_size (&h);
ret = make_bytevector (len * sz); ret = make_bytevector (len * sz, SCM_ARRAY_ELEMENT_TYPE_VU8);
memcpy (SCM_BYTEVECTOR_CONTENTS (ret), base, len * sz); memcpy (SCM_BYTEVECTOR_CONTENTS (ret), base, len * sz);
scm_array_handle_release (&h); scm_array_handle_release (&h);
@ -675,7 +719,7 @@ SCM_DEFINE (scm_u8_list_to_bytevector, "u8-list->bytevector", 1, 0, 0,
SCM_VALIDATE_LIST_COPYLEN (1, lst, c_len); SCM_VALIDATE_LIST_COPYLEN (1, lst, c_len);
bv = make_bytevector (c_len); bv = make_bytevector (c_len, SCM_ARRAY_ELEMENT_TYPE_VU8);
c_bv = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv); c_bv = (unsigned char *) SCM_BYTEVECTOR_CONTENTS (bv);
for (i = 0; i < c_len; lst = SCM_CDR (lst), i++) for (i = 0; i < c_len; lst = SCM_CDR (lst), i++)
@ -1112,7 +1156,7 @@ SCM_DEFINE (scm_bytevector_to_uint_list, "bytevector->uint-list",
if (SCM_UNLIKELY ((c_size == 0) || (c_size >= (ULONG_MAX >> 3L)))) \ if (SCM_UNLIKELY ((c_size == 0) || (c_size >= (ULONG_MAX >> 3L)))) \
scm_out_of_range (FUNC_NAME, size); \ scm_out_of_range (FUNC_NAME, size); \
\ \
bv = make_bytevector (c_len * c_size); \ bv = make_bytevector (c_len * c_size, SCM_ARRAY_ELEMENT_TYPE_VU8); \
c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv); \ c_bv = (char *) SCM_BYTEVECTOR_CONTENTS (bv); \
\ \
for (c_bv_ptr = c_bv; \ for (c_bv_ptr = c_bv; \
@ -1611,6 +1655,12 @@ double_from_foreign_endianness (const union scm_ieee754_double *source)
_c_type ## _to_foreign_endianness _c_type ## _to_foreign_endianness
/* FIXME: SCM_VALIDATE_REAL rejects integers, etc. grrr */
#define VALIDATE_REAL(pos, v) \
do { \
SCM_ASSERT_TYPE (scm_is_true (scm_rational_p (v)), v, pos, FUNC_NAME, "real"); \
} while (0)
/* Templace getters and setters. */ /* Templace getters and setters. */
#define IEEE754_ACCESSOR_PROLOGUE(_type) \ #define IEEE754_ACCESSOR_PROLOGUE(_type) \
@ -1647,7 +1697,7 @@ double_from_foreign_endianness (const union scm_ieee754_double *source)
_type c_value; \ _type c_value; \
\ \
IEEE754_ACCESSOR_PROLOGUE (_type); \ IEEE754_ACCESSOR_PROLOGUE (_type); \
SCM_VALIDATE_REAL (3, value); \ VALIDATE_REAL (3, value); \
SCM_VALIDATE_SYMBOL (4, endianness); \ SCM_VALIDATE_SYMBOL (4, endianness); \
c_value = IEEE754_FROM_SCM (_type) (value); \ c_value = IEEE754_FROM_SCM (_type) (value); \
\ \
@ -1667,7 +1717,7 @@ double_from_foreign_endianness (const union scm_ieee754_double *source)
_type c_value; \ _type c_value; \
\ \
IEEE754_ACCESSOR_PROLOGUE (_type); \ IEEE754_ACCESSOR_PROLOGUE (_type); \
SCM_VALIDATE_REAL (3, value); \ VALIDATE_REAL (3, value); \
c_value = IEEE754_FROM_SCM (_type) (value); \ c_value = IEEE754_FROM_SCM (_type) (value); \
\ \
memcpy (&c_bv[c_index], &c_value, sizeof (c_value)); \ memcpy (&c_bv[c_index], &c_value, sizeof (c_value)); \
@ -1883,7 +1933,8 @@ utf_encoding_name (char *name, size_t utf_width, SCM endianness)
scm_dynwind_begin (0); \ scm_dynwind_begin (0); \
scm_dynwind_free (c_utf); \ scm_dynwind_free (c_utf); \
\ \
utf = make_bytevector (c_utf_len); \ utf = make_bytevector (c_utf_len, \
SCM_ARRAY_ELEMENT_TYPE_VU8); \
memcpy (SCM_BYTEVECTOR_CONTENTS (utf), c_utf, \ memcpy (SCM_BYTEVECTOR_CONTENTS (utf), c_utf, \
c_utf_len); \ c_utf_len); \
\ \
@ -1928,7 +1979,8 @@ SCM_DEFINE (scm_string_to_utf8, "string->utf8",
scm_dynwind_begin (0); scm_dynwind_begin (0);
scm_dynwind_free (c_utf); scm_dynwind_free (c_utf);
utf = make_bytevector (UTF_STRLEN (8, c_utf)); utf = make_bytevector (UTF_STRLEN (8, c_utf),
SCM_ARRAY_ELEMENT_TYPE_VU8);
memcpy (SCM_BYTEVECTOR_CONTENTS (utf), c_utf, memcpy (SCM_BYTEVECTOR_CONTENTS (utf), c_utf,
UTF_STRLEN (8, c_utf)); UTF_STRLEN (8, c_utf));
@ -2058,6 +2110,127 @@ SCM_DEFINE (scm_utf32_to_string, "utf32->string",
#undef FUNC_NAME #undef FUNC_NAME
/* Bytevectors as generalized vectors & arrays. */
static SCM
bytevector_ref_c32 (SCM bv, SCM idx)
{ /* FIXME add some checks */
const float *contents = (const float*)SCM_BYTEVECTOR_CONTENTS (bv);
size_t i = scm_to_size_t (idx);
return scm_c_make_rectangular (contents[i/8], contents[i/8 + 1]);
}
static SCM
bytevector_ref_c64 (SCM bv, SCM idx)
{ /* FIXME add some checks */
const double *contents = (const double*)SCM_BYTEVECTOR_CONTENTS (bv);
size_t i = scm_to_size_t (idx);
return scm_c_make_rectangular (contents[i/16], contents[i/16 + 1]);
}
typedef SCM (*scm_t_bytevector_ref_fn)(SCM, SCM);
const scm_t_bytevector_ref_fn bytevector_ref_fns[SCM_ARRAY_ELEMENT_TYPE_LAST + 1] =
{
NULL, /* SCM */
NULL, /* CHAR */
NULL, /* BIT */
scm_bytevector_u8_ref, /* VU8 */
scm_bytevector_u8_ref, /* U8 */
scm_bytevector_s8_ref,
scm_bytevector_u16_native_ref,
scm_bytevector_s16_native_ref,
scm_bytevector_u32_native_ref,
scm_bytevector_s32_native_ref,
scm_bytevector_u64_native_ref,
scm_bytevector_s64_native_ref,
scm_bytevector_ieee_single_native_ref,
scm_bytevector_ieee_double_native_ref,
bytevector_ref_c32,
bytevector_ref_c64
};
static SCM
bv_handle_ref (scm_t_array_handle *h, size_t index)
{
SCM byte_index;
scm_t_bytevector_ref_fn ref_fn;
ref_fn = bytevector_ref_fns[h->element_type];
byte_index =
scm_from_size_t (index * scm_array_handle_uniform_element_size (h));
return ref_fn (h->array, byte_index);
}
static SCM
bytevector_set_c32 (SCM bv, SCM idx, SCM val)
{ /* checks are unnecessary here */
float *contents = (float*)SCM_BYTEVECTOR_CONTENTS (bv);
size_t i = scm_to_size_t (idx);
contents[i/8] = scm_c_real_part (val);
contents[i/8 + 1] = scm_c_imag_part (val);
return SCM_UNSPECIFIED;
}
static SCM
bytevector_set_c64 (SCM bv, SCM idx, SCM val)
{ /* checks are unnecessary here */
double *contents = (double*)SCM_BYTEVECTOR_CONTENTS (bv);
size_t i = scm_to_size_t (idx);
contents[i/16] = scm_c_real_part (val);
contents[i/16 + 1] = scm_c_imag_part (val);
return SCM_UNSPECIFIED;
}
typedef SCM (*scm_t_bytevector_set_fn)(SCM, SCM, SCM);
const scm_t_bytevector_set_fn bytevector_set_fns[SCM_ARRAY_ELEMENT_TYPE_LAST + 1] =
{
NULL, /* SCM */
NULL, /* CHAR */
NULL, /* BIT */
scm_bytevector_u8_set_x, /* VU8 */
scm_bytevector_u8_set_x, /* U8 */
scm_bytevector_s8_set_x,
scm_bytevector_u16_native_set_x,
scm_bytevector_s16_native_set_x,
scm_bytevector_u32_native_set_x,
scm_bytevector_s32_native_set_x,
scm_bytevector_u64_native_set_x,
scm_bytevector_s64_native_set_x,
scm_bytevector_ieee_single_native_set_x,
scm_bytevector_ieee_double_native_set_x,
bytevector_set_c32,
bytevector_set_c64
};
static void
bv_handle_set_x (scm_t_array_handle *h, size_t index, SCM val)
{
SCM byte_index;
scm_t_bytevector_set_fn set_fn;
set_fn = bytevector_set_fns[h->element_type];
byte_index =
scm_from_size_t (index * scm_array_handle_uniform_element_size (h));
set_fn (h->array, byte_index, val);
}
static void
bytevector_get_handle (SCM v, scm_t_array_handle *h)
{
h->array = v;
h->ndims = 1;
h->dims = &h->dim0;
h->dim0.lbnd = 0;
h->dim0.ubnd = SCM_BYTEVECTOR_TYPED_LENGTH (v) - 1;
h->dim0.inc = 1;
h->element_type = SCM_BYTEVECTOR_ELEMENT_TYPE (v);
h->elements = h->writable_elements = SCM_BYTEVECTOR_CONTENTS (v);
}
/* Initialization. */ /* Initialization. */
@ -2072,7 +2245,8 @@ scm_bootstrap_bytevectors (void)
scm_set_smob_equalp (scm_tc16_bytevector, bytevector_equal_p); scm_set_smob_equalp (scm_tc16_bytevector, bytevector_equal_p);
scm_null_bytevector = scm_null_bytevector =
scm_gc_protect_object (make_bytevector_from_buffer (0, NULL)); scm_gc_protect_object
(make_bytevector_from_buffer (0, NULL, SCM_ARRAY_ELEMENT_TYPE_VU8));
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
scm_i_native_endianness = scm_permanent_object (scm_from_locale_symbol ("big")); scm_i_native_endianness = scm_permanent_object (scm_from_locale_symbol ("big"));
@ -2083,6 +2257,20 @@ scm_bootstrap_bytevectors (void)
scm_c_register_extension ("libguile", "scm_init_bytevectors", scm_c_register_extension ("libguile", "scm_init_bytevectors",
(scm_t_extension_init_func) scm_init_bytevectors, (scm_t_extension_init_func) scm_init_bytevectors,
NULL); NULL);
{
scm_t_array_implementation impl;
impl.tag = scm_tc16_bytevector;
impl.mask = 0xffff;
impl.vref = bv_handle_ref;
impl.vset = bv_handle_set_x;
impl.get_handle = bytevector_get_handle;
scm_i_register_array_implementation (&impl);
scm_i_register_vector_constructor
(scm_i_array_element_types[SCM_ARRAY_ELEMENT_TYPE_VU8],
scm_make_bytevector);
}
} }
void void

View file

@ -116,17 +116,21 @@ SCM_API SCM scm_utf32_to_string (SCM, SCM);
i.e., without allocating memory beside the SMOB itself (a double cell). i.e., without allocating memory beside the SMOB itself (a double cell).
This optimization is necessary since small bytevectors are expected to be This optimization is necessary since small bytevectors are expected to be
common. */ common. */
#define SCM_BYTEVECTOR_P(_bv) \ #define SCM_BYTEVECTOR_P(_bv) \
SCM_SMOB_PREDICATE (scm_tc16_bytevector, _bv) SCM_SMOB_PREDICATE (scm_tc16_bytevector, _bv)
#define SCM_BYTEVECTOR_INLINE_THRESHOLD (2 * sizeof (SCM)) #define SCM_F_BYTEVECTOR_INLINE 0x1
#define SCM_BYTEVECTOR_INLINEABLE_SIZE_P(_size) \ #define SCM_BYTEVECTOR_INLINE_P(_bv) \
((_size) <= SCM_BYTEVECTOR_INLINE_THRESHOLD) (SCM_SMOB_FLAGS (_bv) & SCM_F_BYTEVECTOR_INLINE)
#define SCM_BYTEVECTOR_INLINE_P(_bv) \ #define SCM_BYTEVECTOR_ELEMENT_TYPE(_bv) \
(SCM_BYTEVECTOR_INLINEABLE_SIZE_P (SCM_BYTEVECTOR_LENGTH (_bv))) (SCM_SMOB_FLAGS (_bv) >> 8)
/* Hint that is passed to `scm_gc_malloc ()' and friends. */ /* Hint that is passed to `scm_gc_malloc ()' and friends. */
#define SCM_GC_BYTEVECTOR "bytevector" #define SCM_GC_BYTEVECTOR "bytevector"
SCM_INTERNAL SCM scm_i_make_typed_bytevector (size_t, scm_t_array_element_type);
SCM_INTERNAL SCM scm_c_take_typed_bytevector (signed char *, size_t,
scm_t_array_element_type);
SCM_INTERNAL void scm_bootstrap_bytevectors (void); SCM_INTERNAL void scm_bootstrap_bytevectors (void);
SCM_INTERNAL void scm_init_bytevectors (void); SCM_INTERNAL void scm_init_bytevectors (void);

View file

@ -296,20 +296,14 @@ TODO: change name to scm_i_.. ? --hwn
scm_t_wchar scm_t_wchar
scm_c_upcase (scm_t_wchar c) scm_c_upcase (scm_t_wchar c)
{ {
if (c > 255) return uc_toupper ((int) c);
return c;
return toupper ((int) c);
} }
scm_t_wchar scm_t_wchar
scm_c_downcase (scm_t_wchar c) scm_c_downcase (scm_t_wchar c)
{ {
if (c > 255) return uc_tolower ((int) c);
return c;
return tolower ((int) c);
} }

View file

@ -24,7 +24,11 @@
#include "libguile/__scm.h" #include "libguile/__scm.h"
#include "libguile/numbers.h"
#ifndef SCM_T_WCHAR_DEFINED
typedef scm_t_int32 scm_t_wchar;
#define SCM_T_WCHAR_DEFINED
#endif /* SCM_T_WCHAR_DEFINED */
/* Immediate Characters /* Immediate Characters
@ -32,9 +36,15 @@
#define SCM_CHARP(x) (SCM_ITAG8(x) == scm_tc8_char) #define SCM_CHARP(x) (SCM_ITAG8(x) == scm_tc8_char)
#define SCM_CHAR(x) ((scm_t_wchar)SCM_ITAG8_DATA(x)) #define SCM_CHAR(x) ((scm_t_wchar)SCM_ITAG8_DATA(x))
#define SCM_MAKE_CHAR(x) \ /* SCM_MAKE_CHAR maps signed chars (-128 to 127) and unsigned chars (0
((scm_t_int32) (x) < 0 \ to 255) to Latin-1 codepoints (0 to 255) while allowing higher
? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char) \ codepoints (256 to 1114111) to pass through unchanged.
This macro evaluates x twice, which may lead to side effects if not
used properly. */
#define SCM_MAKE_CHAR(x) \
((x) <= 1 \
? SCM_MAKE_ITAG8 ((scm_t_bits) (unsigned char) (x), scm_tc8_char) \
: SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char)) : SCM_MAKE_ITAG8 ((scm_t_bits) (x), scm_tc8_char))
#define SCM_CODEPOINT_MAX (0x10ffff) #define SCM_CODEPOINT_MAX (0x10ffff)

View file

@ -95,7 +95,7 @@ scm_make_continuation (int *first)
SCM_NEWSMOB (cont, scm_tc16_continuation, continuation); SCM_NEWSMOB (cont, scm_tc16_continuation, continuation);
*first = !setjmp (continuation->jmpbuf); *first = !SCM_I_SETJMP (continuation->jmpbuf);
if (*first) if (*first)
{ {
#ifdef __ia64__ #ifdef __ia64__
@ -193,12 +193,12 @@ copy_stack_and_call (scm_t_contregs *continuation, SCM val,
scm_i_set_last_debug_frame (continuation->dframe); scm_i_set_last_debug_frame (continuation->dframe);
continuation->throw_value = val; continuation->throw_value = val;
longjmp (continuation->jmpbuf, 1); SCM_I_LONGJMP (continuation->jmpbuf, 1);
} }
#ifdef __ia64__ #ifdef __ia64__
void void
scm_ia64_longjmp (jmp_buf *JB, int VAL) scm_ia64_longjmp (scm_i_jmp_buf *JB, int VAL)
{ {
scm_i_thread *t = SCM_I_CURRENT_THREAD; scm_i_thread *t = SCM_I_CURRENT_THREAD;

View file

@ -44,7 +44,7 @@ SCM_API scm_t_bits scm_tc16_continuation;
typedef struct typedef struct
{ {
SCM throw_value; SCM throw_value;
jmp_buf jmpbuf; scm_i_jmp_buf jmpbuf;
SCM dynenv; SCM dynenv;
#ifdef __ia64__ #ifdef __ia64__
void *backing_store; void *backing_store;

View file

@ -53,10 +53,17 @@ SCM_TO_TYPE_PROTO (SCM val)
#if SIZEOF_TYPE != 0 && SIZEOF_TYPE > SCM_SIZEOF_LONG #if SIZEOF_TYPE != 0 && SIZEOF_TYPE > SCM_SIZEOF_LONG
return n; return n;
#else #else
if (n >= TYPE_MIN && n <= TYPE_MAX)
return n; #if TYPE_MIN == 0
else if (n <= TYPE_MAX)
goto out_of_range; return n;
#else /* TYPE_MIN != 0 */
if (n >= TYPE_MIN && n <= TYPE_MAX)
return n;
#endif /* TYPE_MIN != 0 */
else
goto out_of_range;
#endif #endif
} }
else else
@ -76,10 +83,16 @@ SCM_TO_TYPE_PROTO (SCM val)
mpz_export (&n, &count, 1, sizeof (TYPE), 0, 0, SCM_I_BIG_MPZ (val)); mpz_export (&n, &count, 1, sizeof (TYPE), 0, 0, SCM_I_BIG_MPZ (val));
#if TYPE_MIN == 0
if (n <= TYPE_MAX)
return n;
#else /* TYPE_MIN != 0 */
if (n >= TYPE_MIN && n <= TYPE_MAX) if (n >= TYPE_MIN && n <= TYPE_MAX)
return n; return n;
else #endif /* TYPE_MIN != 0 */
goto out_of_range; else
goto out_of_range;
} }
} }
else else

View file

@ -1,147 +0,0 @@
/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "libguile/_scm.h"
#include "libguile/validate.h"
#include "libguile/strings.h"
#include "libguile/vectors.h"
#include "libguile/pairs.h"
#include "libguile/unif.h"
#include "libguile/srfi-4.h"
#include "libguile/convert.h"
#ifdef HAVE_STRING_H
#include <string.h>
#endif
/* char *scm_c_scm2chars (SCM obj, char *dst);
SCM scm_c_chars2scm (const char *src, long n);
SCM scm_c_chars2byvect (const char *src, long n);
*/
#define CTYPE char
#define FROM_CTYPE scm_from_char
#define SCM2CTYPES scm_c_scm2chars
#define CTYPES2SCM scm_c_chars2scm
#define CTYPES2UVECT scm_c_chars2byvect
#if CHAR_MIN == 0
/* 'char' is unsigned. */
#define UVEC_TAG u8
#define UVEC_CTYPE scm_t_uint8
#else
/* 'char' is signed. */
#define UVEC_TAG s8
#define UVEC_CTYPE scm_t_int8
#endif
#include "libguile/convert.i.c"
/* short *scm_c_scm2shorts (SCM obj, short *dst);
SCM scm_c_shorts2scm (const short *src, long n);
SCM scm_c_shorts2svect (const short *src, long n);
*/
#define CTYPE short
#define FROM_CTYPE scm_from_short
#define SCM2CTYPES scm_c_scm2shorts
#define CTYPES2SCM scm_c_shorts2scm
#define CTYPES2UVECT scm_c_shorts2svect
#define UVEC_TAG s16
#define UVEC_CTYPE scm_t_int16
#include "libguile/convert.i.c"
/* int *scm_c_scm2ints (SCM obj, int *dst);
SCM scm_c_ints2scm (const int *src, long n);
SCM scm_c_ints2ivect (const int *src, long n);
SCM scm_c_uints2uvect (const unsigned int *src, long n);
*/
#define CTYPE int
#define FROM_CTYPE scm_from_int
#define SCM2CTYPES scm_c_scm2ints
#define CTYPES2SCM scm_c_ints2scm
#define CTYPES2UVECT scm_c_ints2ivect
#define UVEC_TAG s32
#define UVEC_CTYPE scm_t_int32
#define CTYPES2UVECT_2 scm_c_uints2uvect
#define CTYPE_2 unsigned int
#define UVEC_TAG_2 u32
#define UVEC_CTYPE_2 scm_t_uint32
#include "libguile/convert.i.c"
/* long *scm_c_scm2longs (SCM obj, long *dst);
SCM scm_c_longs2scm (const long *src, long n);
SCM scm_c_longs2ivect (const long *src, long n);
SCM scm_c_ulongs2uvect (const unsigned long *src, long n);
*/
#define CTYPE long
#define FROM_CTYPE scm_from_long
#define SCM2CTYPES scm_c_scm2longs
#define CTYPES2SCM scm_c_longs2scm
#define CTYPES2UVECT scm_c_longs2ivect
#define UVEC_TAG s32
#define UVEC_CTYPE scm_t_int32
#define CTYPES2UVECT_2 scm_c_ulongs2uvect
#define CTYPE_2 unsigned int
#define UVEC_TAG_2 u32
#define UVEC_CTYPE_2 scm_t_uint32
#include "libguile/convert.i.c"
/* float *scm_c_scm2floats (SCM obj, float *dst);
SCM scm_c_floats2scm (const float *src, long n);
SCM scm_c_floats2fvect (const float *src, long n);
*/
#define CTYPE float
#define FROM_CTYPE scm_from_double
#define SCM2CTYPES scm_c_scm2floats
#define CTYPES2SCM scm_c_floats2scm
#define CTYPES2UVECT scm_c_floats2fvect
#define UVEC_TAG f32
#define UVEC_CTYPE float
#include "libguile/convert.i.c"
/* double *scm_c_scm2doubles (SCM obj, double *dst);
SCM scm_c_doubles2scm (const double *src, long n);
SCM scm_c_doubles2dvect (const double *src, long n);
*/
#define CTYPE double
#define FROM_CTYPE scm_from_double
#define SCM2CTYPES scm_c_scm2doubles
#define CTYPES2SCM scm_c_doubles2scm
#define CTYPES2UVECT scm_c_doubles2dvect
#define UVEC_TAG f64
#define UVEC_CTYPE double
#include "libguile/convert.i.c"
/*
Local Variables:
c-file-style: "gnu"
End:
*/

View file

@ -1,51 +0,0 @@
/* classes: h_files */
#ifndef SCM_CONVERT_H
#define SCM_CONVERT_H
/* Copyright (C) 2002, 2006 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include "libguile/__scm.h"
SCM_API char *scm_c_scm2chars (SCM obj, char *dst);
SCM_API short *scm_c_scm2shorts (SCM obj, short *dst);
SCM_API int *scm_c_scm2ints (SCM obj, int *dst);
SCM_API long *scm_c_scm2longs (SCM obj, long *dst);
SCM_API float *scm_c_scm2floats (SCM obj, float *dst);
SCM_API double *scm_c_scm2doubles (SCM obj, double *dst);
SCM_API SCM scm_c_chars2scm (const char *src, long n);
SCM_API SCM scm_c_shorts2scm (const short *src, long n);
SCM_API SCM scm_c_ints2scm (const int *src, long n);
SCM_API SCM scm_c_longs2scm (const long *src, long n);
SCM_API SCM scm_c_floats2scm (const float *src, long n);
SCM_API SCM scm_c_doubles2scm (const double *src, long n);
SCM_API SCM scm_c_chars2byvect (const char *src, long n);
SCM_API SCM scm_c_shorts2svect (const short *src, long n);
SCM_API SCM scm_c_ints2ivect (const int *src, long n);
SCM_API SCM scm_c_uints2uvect (const unsigned int *src, long n);
SCM_API SCM scm_c_longs2ivect (const long *src, long n);
SCM_API SCM scm_c_ulongs2uvect (const unsigned long *src, long n);
SCM_API SCM scm_c_floats2fvect (const float *src, long n);
SCM_API SCM scm_c_doubles2dvect (const double *src, long n);
#endif /* SCM_CONVERT_H */

View file

@ -1,171 +0,0 @@
/* this file is #include'd (x times) by convert.c */
/* You need to define the following macros before including this
template. They are undefined at the end of this file to give a
clean slate for the next inclusion.
- CTYPE
The type of an element of the C array, for example 'char'.
- FROM_CTYPE
The function that converts a CTYPE to a SCM, for example
scm_from_char.
- UVEC_TAG
The tag of a suitable uniform vector that can hold the CTYPE, for
example 's8'.
- UVEC_CTYPE
The C type of an element of the uniform vector, for example
scm_t_int8.
- SCM2CTYPES
The name of the 'SCM-to-C' function, for example scm_c_scm2chars.
- CTYPES2SCM
The name of the 'C-to-SCM' function, for example, scm_c_chars2scm.
- CTYPES2UVECT
The name of the 'C-to-uniform-vector' function, for example
scm_c_chars2byvect. It will create a uniform vector of kind
UVEC_TAG.
- CTYPES2UVECT_2
The name of a second 'C-to-uniform-vector' function. Leave
undefined if you want only one such function.
- CTYPE_2
- UVEC_TAG_2
- UVEC_CTYPE_2
The tag and C type of the second kind of uniform vector, for use
with the function described above.
*/
/* The first level does not expand macros in the arguments. */
#define paste(a1,a2,a3) a1##a2##a3
#define stringify(a) #a
/* But the second level does. */
#define F(pre,T,suf) paste(pre,T,suf)
#define S(T) stringify(T)
/* Convert a vector, list or uniform vector into a C array. If the
result array in argument 2 is NULL, malloc() a new one.
*/
CTYPE *
SCM2CTYPES (SCM obj, CTYPE *data)
{
scm_t_array_handle handle;
size_t i, len;
ssize_t inc;
const UVEC_CTYPE *uvec_elements;
obj = F(scm_any_to_,UVEC_TAG,vector) (obj);
uvec_elements = F(scm_,UVEC_TAG,vector_elements) (obj, &handle, &len, &inc);
if (data == NULL)
data = scm_malloc (len * sizeof (CTYPE));
for (i = 0; i < len; i++, uvec_elements += inc)
data[i] = uvec_elements[i];
scm_array_handle_release (&handle);
return data;
}
/* Converts a C array into a vector. */
SCM
CTYPES2SCM (const CTYPE *data, long n)
{
long i;
SCM v;
v = scm_c_make_vector (n, SCM_UNSPECIFIED);
for (i = 0; i < n; i++)
SCM_SIMPLE_VECTOR_SET (v, i, FROM_CTYPE (data[i]));
return v;
}
/* Converts a C array into a uniform vector. */
SCM
CTYPES2UVECT (const CTYPE *data, long n)
{
scm_t_array_handle handle;
long i;
SCM uvec;
UVEC_CTYPE *uvec_elements;
uvec = F(scm_make_,UVEC_TAG,vector) (scm_from_long (n), SCM_UNDEFINED);
uvec_elements = F(scm_,UVEC_TAG,vector_writable_elements) (uvec, &handle,
NULL, NULL);
for (i = 0; i < n; i++)
uvec_elements[i] = data[i];
scm_array_handle_release (&handle);
return uvec;
}
#ifdef CTYPE2UVECT_2
SCM
CTYPES2UVECT_2 (const CTYPE_2 *data, long n)
{
scm_t_array_handle handle;
long i;
SCM uvec;
UVEC_CTYPE_2 *uvec_elements;
uvec = F(scm_make_,UVEC_TAG_2,vector) (scm_from_long (n), SCM_UNDEFINED);
uvec_elements = F(scm_,UVEC_TAG_2,vector_writable_elements) (uvec, &handle,
NULL, NULL);
for (i = 0; i < n; i++)
uvec_elements[i] = data[i];
scm_array_handle_release (&handle);
return uvec;
}
#endif
#undef paste
#undef stringify
#undef F
#undef S
#undef CTYPE
#undef FROM_CTYPE
#undef UVEC_TAG
#undef UVEC_CTYPE
#undef SCM2CTYPES
#undef CTYPES2SCM
#undef CTYPES2UVECT
#ifdef CTYPES2UVECT_2
#undef CTYPES2UVECT_2
#undef CTYPE_2
#undef UVEC_TAG_2
#undef UVEC_CTYPE_2
#endif
/*
Local Variables:
c-file-style: "gnu"
End:
*/

View file

@ -363,6 +363,7 @@ SCM_DEFINE (scm_procedure_source, "procedure-source", 1, 0, 0,
if (!SCM_SMOB_DESCRIPTOR (proc).apply) if (!SCM_SMOB_DESCRIPTOR (proc).apply)
break; break;
case scm_tcs_subrs: case scm_tcs_subrs:
case scm_tc7_program:
procprop: procprop:
/* It would indeed be a nice thing if we supplied source even for /* It would indeed be a nice thing if we supplied source even for
built in procedures! */ built in procedures! */

View file

@ -34,6 +34,7 @@
#include "libguile/strings.h" #include "libguile/strings.h"
#include "libguile/srfi-13.h" #include "libguile/srfi-13.h"
#include "libguile/modules.h" #include "libguile/modules.h"
#include "libguile/generalized-arrays.h"
#include "libguile/eval.h" #include "libguile/eval.h"
#include "libguile/smob.h" #include "libguile/smob.h"
#include "libguile/procprop.h" #include "libguile/procprop.h"
@ -749,17 +750,13 @@ scm_sym2ovcell (SCM sym, SCM obarray)
return (SYMBOL . SCM_UNDEFINED). */ return (SYMBOL . SCM_UNDEFINED). */
SCM static SCM
scm_intern_obarray_soft (const char *name,size_t len,SCM obarray,unsigned int softness) intern_obarray_soft (SCM symbol, SCM obarray, unsigned int softness)
{ {
SCM symbol = scm_from_locale_symboln (name, len);
size_t raw_hash = scm_i_symbol_hash (symbol); size_t raw_hash = scm_i_symbol_hash (symbol);
size_t hash; size_t hash;
SCM lsym; SCM lsym;
scm_c_issue_deprecation_warning ("`scm_intern_obarray_soft' is deprecated. "
"Use hashtables instead.");
if (scm_is_false (obarray)) if (scm_is_false (obarray))
{ {
if (softness) if (softness)
@ -795,6 +792,18 @@ scm_intern_obarray_soft (const char *name,size_t len,SCM obarray,unsigned int so
} }
SCM
scm_intern_obarray_soft (const char *name, size_t len, SCM obarray,
unsigned int softness)
{
SCM symbol = scm_from_locale_symboln (name, len);
scm_c_issue_deprecation_warning ("`scm_intern_obarray_soft' is deprecated. "
"Use hashtables instead.");
return intern_obarray_soft (symbol, obarray, softness);
}
SCM SCM
scm_intern_obarray (const char *name,size_t len,SCM obarray) scm_intern_obarray (const char *name,size_t len,SCM obarray)
{ {
@ -850,10 +859,7 @@ SCM_DEFINE (scm_string_to_obarray_symbol, "string->obarray-symbol", 2, 1, 0,
else if (scm_is_eq (o, SCM_BOOL_T)) else if (scm_is_eq (o, SCM_BOOL_T))
o = SCM_BOOL_F; o = SCM_BOOL_F;
vcell = scm_intern_obarray_soft (scm_i_string_chars (s), vcell = intern_obarray_soft (scm_string_to_symbol (s), o, softness);
scm_i_string_length (s),
o,
softness);
if (scm_is_false (vcell)) if (scm_is_false (vcell))
return vcell; return vcell;
answer = SCM_CAR (vcell); answer = SCM_CAR (vcell);
@ -1070,7 +1076,8 @@ SCM_DEFINE (scm_gentemp, "gentemp", 0, 2, 0,
{ {
char buf[MAX_PREFIX_LENGTH + SCM_INTBUFLEN]; char buf[MAX_PREFIX_LENGTH + SCM_INTBUFLEN];
char *name = buf; char *name = buf;
int len, n_digits; int n_digits;
size_t len;
scm_c_issue_deprecation_warning ("`gentemp' is deprecated. " scm_c_issue_deprecation_warning ("`gentemp' is deprecated. "
"Use `gensym' instead."); "Use `gensym' instead.");
@ -1084,9 +1091,8 @@ SCM_DEFINE (scm_gentemp, "gentemp", 0, 2, 0,
{ {
SCM_VALIDATE_STRING (1, prefix); SCM_VALIDATE_STRING (1, prefix);
len = scm_i_string_length (prefix); len = scm_i_string_length (prefix);
if (len > MAX_PREFIX_LENGTH) name = scm_to_locale_stringn (prefix, &len);
name = SCM_MUST_MALLOC (MAX_PREFIX_LENGTH + SCM_INTBUFLEN); name = scm_realloc (name, len + SCM_INTBUFLEN);
strncpy (name, scm_i_string_chars (prefix), len);
} }
if (SCM_UNBNDP (obarray)) if (SCM_UNBNDP (obarray))
@ -1108,7 +1114,7 @@ SCM_DEFINE (scm_gentemp, "gentemp", 0, 2, 0,
obarray, obarray,
0); 0);
if (name != buf) if (name != buf)
scm_must_free (name); free (name);
return SCM_CAR (vcell); return SCM_CAR (vcell);
} }
} }
@ -1309,7 +1315,7 @@ scm_i_arrayp (SCM a)
{ {
scm_c_issue_deprecation_warning scm_c_issue_deprecation_warning
("SCM_ARRAYP is deprecated. Use scm_is_array instead."); ("SCM_ARRAYP is deprecated. Use scm_is_array instead.");
return SCM_I_ARRAYP(a) || SCM_I_ENCLOSED_ARRAYP(a); return SCM_I_ARRAYP(a);
} }
size_t size_t

View file

@ -24,6 +24,7 @@
*/ */
#include "libguile/__scm.h" #include "libguile/__scm.h"
#include "libguile/arrays.h"
#include "libguile/strings.h" #include "libguile/strings.h"
#if (SCM_ENABLE_DEPRECATED == 1) #if (SCM_ENABLE_DEPRECATED == 1)

View file

@ -265,7 +265,7 @@ SCM_DEFINE (scm_make_keyword_from_dash_symbol, "make-keyword-from-dash-symbol",
SCM dash_string, non_dash_symbol; SCM dash_string, non_dash_symbol;
SCM_ASSERT (scm_is_symbol (symbol) SCM_ASSERT (scm_is_symbol (symbol)
&& ('-' == scm_i_symbol_chars(symbol)[0]), && (scm_i_symbol_ref (symbol, 0) == '-'),
symbol, SCM_ARG1, FUNC_NAME); symbol, SCM_ARG1, FUNC_NAME);
dash_string = scm_symbol_to_string (symbol); dash_string = scm_symbol_to_string (symbol);

View file

@ -1,4 +1,4 @@
/* Copyright (C) 1995,1996,1997,1998,2000,2001,2003, 2004, 2006 Free Software Foundation, Inc. /* Copyright (C) 1995,1996,1997,1998,2000,2001,2003, 2004, 2006, 2009 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -22,13 +22,13 @@
#endif #endif
#include "libguile/_scm.h" #include "libguile/_scm.h"
#include "libguile/ramap.h" #include "libguile/array-map.h"
#include "libguile/stackchk.h" #include "libguile/stackchk.h"
#include "libguile/strorder.h" #include "libguile/strorder.h"
#include "libguile/async.h" #include "libguile/async.h"
#include "libguile/root.h" #include "libguile/root.h"
#include "libguile/smob.h" #include "libguile/smob.h"
#include "libguile/unif.h" #include "libguile/arrays.h"
#include "libguile/vectors.h" #include "libguile/vectors.h"
#include "libguile/struct.h" #include "libguile/struct.h"

View file

@ -232,6 +232,19 @@ scm_wrong_type_arg (const char *subr, int pos, SCM bad_value)
scm_list_1 (bad_value)); scm_list_1 (bad_value));
} }
void
scm_i_wrong_type_arg_symbol (SCM symbol, int pos, SCM bad_value)
{
scm_error_scm (scm_arg_type_key,
scm_symbol_to_string (symbol),
(pos == 0) ? scm_from_locale_string ("Wrong type: ~S")
: scm_from_locale_string ("Wrong type argument in position ~A: ~S"),
(pos == 0) ? scm_list_1 (bad_value)
: scm_list_2 (scm_from_int (pos), bad_value),
scm_list_1 (bad_value));
scm_remember_upto_here_2 (symbol, bad_value);
}
void void
scm_wrong_type_arg_msg (const char *subr, int pos, SCM bad_value, const char *szMessage) scm_wrong_type_arg_msg (const char *subr, int pos, SCM bad_value, const char *szMessage)
{ {

View file

@ -53,6 +53,8 @@ SCM_API void scm_wrong_num_args (SCM proc) SCM_NORETURN;
SCM_API void scm_error_num_args_subr (const char* subr) SCM_NORETURN; SCM_API void scm_error_num_args_subr (const char* subr) SCM_NORETURN;
SCM_API void scm_wrong_type_arg (const char *subr, int pos, SCM_API void scm_wrong_type_arg (const char *subr, int pos,
SCM bad_value) SCM_NORETURN; SCM bad_value) SCM_NORETURN;
SCM_INTERNAL void scm_i_wrong_type_arg_symbol (SCM symbol, int pos,
SCM bad_value) SCM_NORETURN;
SCM_API void scm_wrong_type_arg_msg (const char *subr, int pos, SCM_API void scm_wrong_type_arg_msg (const char *subr, int pos,
SCM bad_value, const char *sz) SCM_NORETURN; SCM bad_value, const char *sz) SCM_NORETURN;
SCM_API void scm_memory_error (const char *subr) SCM_NORETURN; SCM_API void scm_memory_error (const char *subr) SCM_NORETURN;

View file

@ -3328,6 +3328,7 @@ scm_trampoline_0 (SCM proc)
case scm_tc7_rpsubr: case scm_tc7_rpsubr:
case scm_tc7_gsubr: case scm_tc7_gsubr:
case scm_tc7_pws: case scm_tc7_pws:
case scm_tc7_program:
trampoline = scm_call_0; trampoline = scm_call_0;
break; break;
default: default:
@ -3380,8 +3381,7 @@ call_dsubr_1 (SCM proc, SCM arg1)
{ {
return (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1)))); return (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
} }
SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1, SCM_WTA_DISPATCH_1_SUBR (proc, arg1, SCM_ARG1);
SCM_ARG1, scm_i_symbol_chars (SCM_SUBR_NAME (proc)));
} }
static SCM static SCM
@ -3454,6 +3454,7 @@ scm_trampoline_1 (SCM proc)
case scm_tc7_rpsubr: case scm_tc7_rpsubr:
case scm_tc7_gsubr: case scm_tc7_gsubr:
case scm_tc7_pws: case scm_tc7_pws:
case scm_tc7_program:
trampoline = scm_call_1; trampoline = scm_call_1;
break; break;
default: default:
@ -3548,6 +3549,7 @@ scm_trampoline_2 (SCM proc)
break; break;
case scm_tc7_gsubr: case scm_tc7_gsubr:
case scm_tc7_pws: case scm_tc7_pws:
case scm_tc7_program:
trampoline = scm_call_2; trampoline = scm_call_2;
break; break;
default: default:

View file

@ -1132,6 +1132,8 @@ dispatch:
RETURN (SCM_BOOL_T); RETURN (SCM_BOOL_T);
case scm_tc7_asubr: case scm_tc7_asubr:
RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED)); RETURN (SCM_SUBRF (proc) (SCM_UNDEFINED, SCM_UNDEFINED));
case scm_tc7_program:
RETURN (scm_c_vm_run (scm_the_vm (), proc, NULL, 0));
case scm_tc7_smob: case scm_tc7_smob:
if (!SCM_SMOB_APPLICABLE_P (proc)) if (!SCM_SMOB_APPLICABLE_P (proc))
goto badfun; goto badfun;
@ -1236,13 +1238,13 @@ dispatch:
{ {
RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1)))); RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
} }
SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1, SCM_WTA_DISPATCH_1_SUBR (proc, arg1, SCM_ARG1);
SCM_ARG1,
scm_i_symbol_chars (SCM_SUBR_NAME (proc)));
case scm_tc7_cxr: case scm_tc7_cxr:
RETURN (scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc))); RETURN (scm_i_chase_pairs (arg1, (scm_t_bits) SCM_SUBRF (proc)));
case scm_tc7_rpsubr: case scm_tc7_rpsubr:
RETURN (SCM_BOOL_T); RETURN (SCM_BOOL_T);
case scm_tc7_program:
RETURN (scm_c_vm_run (scm_the_vm (), proc, &arg1, 1));
case scm_tc7_asubr: case scm_tc7_asubr:
RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED)); RETURN (SCM_SUBRF (proc) (arg1, SCM_UNDEFINED));
case scm_tc7_lsubr: case scm_tc7_lsubr:
@ -1353,6 +1355,12 @@ dispatch:
case scm_tc7_rpsubr: case scm_tc7_rpsubr:
case scm_tc7_asubr: case scm_tc7_asubr:
RETURN (SCM_SUBRF (proc) (arg1, arg2)); RETURN (SCM_SUBRF (proc) (arg1, arg2));
case scm_tc7_program:
{ SCM args[2];
args[0] = arg1;
args[1] = arg2;
RETURN (scm_c_vm_run (scm_the_vm (), proc, args, 2));
}
case scm_tc7_smob: case scm_tc7_smob:
if (!SCM_SMOB_APPLICABLE_P (proc)) if (!SCM_SMOB_APPLICABLE_P (proc))
goto badfun; goto badfun;
@ -1492,6 +1500,8 @@ dispatch:
SCM_CDDR (debug.info->a.args))); SCM_CDDR (debug.info->a.args)));
case scm_tc7_gsubr: case scm_tc7_gsubr:
RETURN (scm_i_gsubr_apply_list (proc, debug.info->a.args)); RETURN (scm_i_gsubr_apply_list (proc, debug.info->a.args));
case scm_tc7_program:
RETURN (scm_vm_apply (scm_the_vm (), proc, debug.info->a.args));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
debug.info->a.proc = proc; debug.info->a.proc = proc;
@ -1563,6 +1573,11 @@ dispatch:
scm_cons2 (arg1, arg2, scm_cons2 (arg1, arg2,
scm_ceval_args (x, env, scm_ceval_args (x, env,
proc)))); proc))));
case scm_tc7_program:
RETURN (scm_vm_apply
(scm_the_vm (), proc,
scm_cons (arg1, scm_cons (arg2,
scm_ceval_args (x, env, proc)))));
case scm_tc7_pws: case scm_tc7_pws:
proc = SCM_PROCEDURE (proc); proc = SCM_PROCEDURE (proc);
if (!SCM_CLOSUREP (proc)) if (!SCM_CLOSUREP (proc))
@ -1764,8 +1779,7 @@ tail:
{ {
RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1)))); RETURN (scm_from_double (SCM_DSUBRF (proc) (scm_i_fraction2double (arg1))));
} }
SCM_WTA_DISPATCH_1 (*SCM_SUBR_GENERIC (proc), arg1, SCM_WTA_DISPATCH_1_SUBR (proc, arg1, SCM_ARG1);
SCM_ARG1, scm_i_symbol_chars (SCM_SUBR_NAME (proc)));
case scm_tc7_cxr: case scm_tc7_cxr:
if (SCM_UNLIKELY (SCM_UNBNDP (arg1) || !scm_is_null (args))) if (SCM_UNLIKELY (SCM_UNBNDP (arg1) || !scm_is_null (args)))
scm_wrong_num_args (proc); scm_wrong_num_args (proc);
@ -1798,6 +1812,11 @@ tail:
args = SCM_CDR (args); args = SCM_CDR (args);
} }
RETURN (arg1); RETURN (arg1);
case scm_tc7_program:
if (SCM_UNBNDP (arg1))
RETURN (scm_c_vm_run (scm_the_vm (), proc, NULL, 0));
else
RETURN (scm_vm_apply (scm_the_vm (), proc, scm_cons (arg1, args)));
case scm_tc7_rpsubr: case scm_tc7_rpsubr:
if (scm_is_null (args)) if (scm_is_null (args))
RETURN (SCM_BOOL_T); RETURN (SCM_BOOL_T);

View file

@ -82,6 +82,7 @@ SCM_DEFINE (scm_self_evaluating_p, "self-evaluating?", 1, 0, 0,
case scm_tc7_string: case scm_tc7_string:
case scm_tc7_smob: case scm_tc7_smob:
case scm_tc7_pws: case scm_tc7_pws:
case scm_tc7_program:
case scm_tcs_subrs: case scm_tcs_subrs:
case scm_tcs_struct: case scm_tcs_struct:
return SCM_BOOL_T; return SCM_BOOL_T;

View file

@ -1,6 +1,6 @@
/* extensions.c - registering and loading extensions. /* extensions.c - registering and loading extensions.
* *
* Copyright (C) 2001, 2006 Free Software Foundation, Inc. * Copyright (C) 2001, 2006, 2009 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@ -41,7 +41,7 @@ typedef struct extension_t
void *data; void *data;
} extension_t; } extension_t;
static extension_t *registered_extensions; static extension_t *registered_extensions = NULL;
/* Register a LIB/INIT pair for use by `scm_load_extension'. LIB is /* Register a LIB/INIT pair for use by `scm_load_extension'. LIB is
allowed to be NULL and then only INIT is used to identify the allowed to be NULL and then only INIT is used to identify the
@ -157,7 +157,6 @@ SCM_DEFINE (scm_load_extension, "load-extension", 2, 0, 0,
void void
scm_init_extensions () scm_init_extensions ()
{ {
registered_extensions = NULL;
#include "libguile/extensions.x" #include "libguile/extensions.x"
} }

View file

@ -1573,31 +1573,39 @@ SCM_DEFINE (scm_dirname, "dirname", 1, 0, 0,
"component, @code{.} is returned.") "component, @code{.} is returned.")
#define FUNC_NAME s_scm_dirname #define FUNC_NAME s_scm_dirname
{ {
const char *s;
long int i; long int i;
unsigned long int len; unsigned long int len;
SCM_VALIDATE_STRING (1, filename); SCM_VALIDATE_STRING (1, filename);
s = scm_i_string_chars (filename);
len = scm_i_string_length (filename); len = scm_i_string_length (filename);
i = len - 1; i = len - 1;
#ifdef __MINGW32__ #ifdef __MINGW32__
while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i; while (i >= 0 && (scm_i_string_ref (filename, i) == '/'
while (i >= 0 && (s[i] != '/' && s[i] != '\\')) --i; || scm_i_string_ref (filename, i) == '\\'))
while (i >= 0 && (s[i] == '/' || s[i] == '\\')) --i; --i;
while (i >= 0 && (scm_i_string_ref (filename, i) != '/'
&& scm_i_string_ref (filename, i) != '\\'))
--i;
while (i >= 0 && (scm_i_string_ref (filename, i) == '/'
|| scm_i_string_ref (filename, i) == '\\'))
--i;
#else #else
while (i >= 0 && s[i] == '/') --i; while (i >= 0 && scm_i_string_ref (filename, i) == '/')
while (i >= 0 && s[i] != '/') --i; --i;
while (i >= 0 && s[i] == '/') --i; while (i >= 0 && scm_i_string_ref (filename, i) != '/')
--i;
while (i >= 0 && scm_i_string_ref (filename, i) == '/')
--i;
#endif /* ndef __MINGW32__ */ #endif /* ndef __MINGW32__ */
if (i < 0) if (i < 0)
{ {
#ifdef __MINGW32__ #ifdef __MINGW32__
if (len > 0 && (s[0] == '/' || s[0] == '\\')) if (len > 0 && (scm_i_string_ref (filename, 0) == '/'
|| scm_i_string_ref (filename, 0) == '\\'))
#else #else
if (len > 0 && s[0] == '/') if (len > 0 && scm_i_string_ref (filename, 0) == '/')
#endif /* ndef __MINGW32__ */ #endif /* ndef __MINGW32__ */
return scm_c_substring (filename, 0, 1); return scm_c_substring (filename, 0, 1);
else else
@ -1616,11 +1624,9 @@ SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
"@var{basename}, it is removed also.") "@var{basename}, it is removed also.")
#define FUNC_NAME s_scm_basename #define FUNC_NAME s_scm_basename
{ {
const char *f, *s = 0;
int i, j, len, end; int i, j, len, end;
SCM_VALIDATE_STRING (1, filename); SCM_VALIDATE_STRING (1, filename);
f = scm_i_string_chars (filename);
len = scm_i_string_length (filename); len = scm_i_string_length (filename);
if (SCM_UNBNDP (suffix)) if (SCM_UNBNDP (suffix))
@ -1628,32 +1634,44 @@ SCM_DEFINE (scm_basename, "basename", 1, 1, 0,
else else
{ {
SCM_VALIDATE_STRING (2, suffix); SCM_VALIDATE_STRING (2, suffix);
s = scm_i_string_chars (suffix);
j = scm_i_string_length (suffix) - 1; j = scm_i_string_length (suffix) - 1;
} }
i = len - 1; i = len - 1;
#ifdef __MINGW32__ #ifdef __MINGW32__
while (i >= 0 && (f[i] == '/' || f[i] == '\\')) --i; while (i >= 0 && (scm_i_string_ref (filename, i) == '/'
|| scm_i_string_ref (filename, i) == '\\'))
--i;
#else #else
while (i >= 0 && f[i] == '/') --i; while (i >= 0 && scm_i_string_ref (filename, i) == '/')
--i;
#endif /* ndef __MINGW32__ */ #endif /* ndef __MINGW32__ */
end = i; end = i;
while (i >= 0 && j >= 0 && f[i] == s[j]) --i, --j; while (i >= 0 && j >= 0
&& (scm_i_string_ref (filename, i)
== scm_i_string_ref (suffix, j)))
{
--i;
--j;
}
if (j == -1) if (j == -1)
end = i; end = i;
#ifdef __MINGW32__ #ifdef __MINGW32__
while (i >= 0 && f[i] != '/' && f[i] != '\\') --i; while (i >= 0 && (scm_i_string_ref (filename, i) != '/'
&& scm_i_string_ref (filename, i) != '\\'))
--i;
#else #else
while (i >= 0 && f[i] != '/') --i; while (i >= 0 && scm_i_string_ref (filename, i) != '/')
--i;
#endif /* ndef __MINGW32__ */ #endif /* ndef __MINGW32__ */
if (i == end) if (i == end)
{ {
#ifdef __MINGW32__ #ifdef __MINGW32__
if (len > 0 && (f[0] == '/' || f[0] == '\\')) if (len > 0 && (scm_i_string_ref (filename, 0) == '/'
|| scm_i_string_ref (filename, 0) == '\\'))
#else #else
if (len > 0 && f[0] == '/') if (len > 0 && scm_i_string_ref (filename, 0) == '/')
#endif /* ndef __MINGW32__ */ #endif /* ndef __MINGW32__ */
return scm_c_substring (filename, 0, 1); return scm_c_substring (filename, 0, 1);
else else
return scm_dot_string; return scm_dot_string;
} }

View file

@ -594,7 +594,7 @@ static void fport_flush (SCM port);
/* fill a port's read-buffer with a single read. returns the first /* fill a port's read-buffer with a single read. returns the first
char or EOF if end of file. */ char or EOF if end of file. */
static int static scm_t_wchar
fport_fill_input (SCM port) fport_fill_input (SCM port)
{ {
long count; long count;
@ -608,7 +608,7 @@ fport_fill_input (SCM port)
if (count == -1) if (count == -1)
scm_syserror ("fport_fill_input"); scm_syserror ("fport_fill_input");
if (count == 0) if (count == 0)
return EOF; return (scm_t_wchar) EOF;
else else
{ {
pt->read_pos = pt->read_buf; pt->read_pos = pt->read_buf;

View file

@ -33,7 +33,7 @@ scm_t_bits scm_tc16_vm_frame;
SCM SCM
scm_c_make_vm_frame (SCM stack_holder, SCM *fp, SCM *sp, scm_c_make_vm_frame (SCM stack_holder, SCM *fp, SCM *sp,
scm_byte_t *ip, scm_t_ptrdiff offset) scm_t_uint8 *ip, scm_t_ptrdiff offset)
{ {
struct scm_vm_frame *p = scm_gc_malloc (sizeof (struct scm_vm_frame), struct scm_vm_frame *p = scm_gc_malloc (sizeof (struct scm_vm_frame),
"vmframe"); "vmframe");
@ -98,12 +98,12 @@ SCM_DEFINE (scm_vm_frame_arguments, "vm-frame-arguments", 1, 0, 0,
if (!bp->nargs) if (!bp->nargs)
return SCM_EOL; return SCM_EOL;
else if (bp->nrest) else if (bp->nrest)
ret = fp[bp->nargs - 1]; ret = SCM_FRAME_VARIABLE (fp, bp->nargs - 1);
else else
ret = scm_cons (fp[bp->nargs - 1], SCM_EOL); ret = scm_cons (SCM_FRAME_VARIABLE (fp, bp->nargs - 1), SCM_EOL);
for (i = bp->nargs - 2; i >= 0; i--) for (i = bp->nargs - 2; i >= 0; i--)
ret = scm_cons (fp[i], ret); ret = scm_cons (SCM_FRAME_VARIABLE (fp, i), ret);
return ret; return ret;
} }

View file

@ -30,39 +30,46 @@
/* VM Frame Layout /* VM Frame Layout
--------------- ---------------
| | <- fp + bp->nargs + bp->nlocs + 3 | ... |
+------------------+ = SCM_FRAME_UPPER_ADDRESS (fp) | Intermed. val. 0 | <- fp + bp->nargs + bp->nlocs = SCM_FRAME_UPPER_ADDRESS (fp)
| Return address | +==================+
| MV return address| | Local variable 1 |
| Dynamic link | <- fp + bp->nargs + bp->blocs
| Local variable 1 | = SCM_FRAME_DATA_ADDRESS (fp)
| Local variable 0 | <- fp + bp->nargs | Local variable 0 | <- fp + bp->nargs
| Argument 1 | | Argument 1 |
| Argument 0 | <- fp | Argument 0 | <- fp
| Program | <- fp - 1 | Program | <- fp - 1
+------------------+ = SCM_FRAME_LOWER_ADDRESS (fp) +------------------+
| Return address |
| MV return address|
| Dynamic link | <- fp - 4 = SCM_FRAME_DATA_ADDRESS (fp) = SCM_FRAME_LOWER_ADDRESS (fp)
+==================+
| | | |
As can be inferred from this drawing, it is assumed that As can be inferred from this drawing, it is assumed that
`sizeof (SCM *) == sizeof (SCM)', since pointers (the `link' parts) are `sizeof (SCM *) == sizeof (SCM)', since pointers (the `link' parts) are
assumed to be as long as SCM objects. */ assumed to be as long as SCM objects. */
#define SCM_FRAME_DATA_ADDRESS(fp) \ #define SCM_FRAME_DATA_ADDRESS(fp) (fp - 4)
(fp + SCM_PROGRAM_DATA (SCM_FRAME_PROGRAM (fp))->nargs \ #define SCM_FRAME_UPPER_ADDRESS(fp) \
+ SCM_PROGRAM_DATA (SCM_FRAME_PROGRAM (fp))->nlocs) (fp \
#define SCM_FRAME_UPPER_ADDRESS(fp) (SCM_FRAME_DATA_ADDRESS (fp) + 3) + SCM_PROGRAM_DATA (SCM_FRAME_PROGRAM (fp))->nargs \
#define SCM_FRAME_LOWER_ADDRESS(fp) (fp - 1) + SCM_PROGRAM_DATA (SCM_FRAME_PROGRAM (fp))->nlocs)
#define SCM_FRAME_LOWER_ADDRESS(fp) (fp - 4)
#define SCM_FRAME_BYTE_CAST(x) ((scm_byte_t *) SCM_UNPACK (x)) #define SCM_FRAME_BYTE_CAST(x) ((scm_t_uint8 *) SCM_UNPACK (x))
#define SCM_FRAME_STACK_CAST(x) ((SCM *) SCM_UNPACK (x)) #define SCM_FRAME_STACK_CAST(x) ((SCM *) SCM_UNPACK (x))
#define SCM_FRAME_RETURN_ADDRESS(fp) \ #define SCM_FRAME_RETURN_ADDRESS(fp) \
(SCM_FRAME_BYTE_CAST (SCM_FRAME_DATA_ADDRESS (fp)[2])) (SCM_FRAME_BYTE_CAST (SCM_FRAME_DATA_ADDRESS (fp)[2]))
#define SCM_FRAME_SET_RETURN_ADDRESS(fp, ra) \
((SCM_FRAME_DATA_ADDRESS (fp)[2])) = (SCM)(ra);
#define SCM_FRAME_MV_RETURN_ADDRESS(fp) \ #define SCM_FRAME_MV_RETURN_ADDRESS(fp) \
(SCM_FRAME_BYTE_CAST (SCM_FRAME_DATA_ADDRESS (fp)[1])) (SCM_FRAME_BYTE_CAST (SCM_FRAME_DATA_ADDRESS (fp)[1]))
#define SCM_FRAME_SET_MV_RETURN_ADDRESS(fp, mvra) \
((SCM_FRAME_DATA_ADDRESS (fp)[1])) = (SCM)(mvra);
#define SCM_FRAME_DYNAMIC_LINK(fp) \ #define SCM_FRAME_DYNAMIC_LINK(fp) \
(SCM_FRAME_STACK_CAST (SCM_FRAME_DATA_ADDRESS (fp)[0])) (SCM_FRAME_STACK_CAST (SCM_FRAME_DATA_ADDRESS (fp)[0]))
#define SCM_FRAME_SET_DYNAMIC_LINK(fp, dl) \ #define SCM_FRAME_SET_DYNAMIC_LINK(fp, dl) \
((SCM_FRAME_DATA_ADDRESS (fp)[0])) = (SCM)(dl); ((SCM_FRAME_DATA_ADDRESS (fp)[0])) = (SCM)(dl);
#define SCM_FRAME_VARIABLE(fp,i) fp[i] #define SCM_FRAME_VARIABLE(fp,i) fp[i]
#define SCM_FRAME_PROGRAM(fp) fp[-1] #define SCM_FRAME_PROGRAM(fp) fp[-1]
@ -79,7 +86,7 @@ struct scm_vm_frame
SCM stack_holder; SCM stack_holder;
SCM *fp; SCM *fp;
SCM *sp; SCM *sp;
scm_byte_t *ip; scm_t_uint8 *ip;
scm_t_ptrdiff offset; scm_t_ptrdiff offset;
}; };
@ -92,9 +99,8 @@ struct scm_vm_frame
#define SCM_VM_FRAME_OFFSET(f) SCM_VM_FRAME_DATA(f)->offset #define SCM_VM_FRAME_OFFSET(f) SCM_VM_FRAME_DATA(f)->offset
#define SCM_VALIDATE_VM_FRAME(p,x) SCM_MAKE_VALIDATE (p, x, VM_FRAME_P) #define SCM_VALIDATE_VM_FRAME(p,x) SCM_MAKE_VALIDATE (p, x, VM_FRAME_P)
/* FIXME rename scm_byte_t */
SCM_API SCM scm_c_make_vm_frame (SCM stack_holder, SCM *fp, SCM *sp, SCM_API SCM scm_c_make_vm_frame (SCM stack_holder, SCM *fp, SCM *sp,
scm_byte_t *ip, scm_t_ptrdiff offset); scm_t_uint8 *ip, scm_t_ptrdiff offset);
SCM_API SCM scm_vm_frame_p (SCM obj); SCM_API SCM scm_vm_frame_p (SCM obj);
SCM_API SCM scm_vm_frame_program (SCM frame); SCM_API SCM scm_vm_frame_program (SCM frame);
SCM_API SCM scm_vm_frame_arguments (SCM frame); SCM_API SCM scm_vm_frame_arguments (SCM frame);

Some files were not shown because too many files have changed in this diff Show more