mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Merge remote branch 'origin/stable-2.0'
Conflicts: GUILE-VERSION test-suite/tests/srfi-4.test
This commit is contained in:
commit
21c05db45b
182 changed files with 21314 additions and 18452 deletions
|
@ -1,6 +1,7 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
##
|
||||
## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
## Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006, 2007,
|
||||
## 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
|
||||
##
|
||||
## This file is part of GUILE.
|
||||
##
|
||||
|
@ -34,6 +35,7 @@ SUBDIRS = \
|
|||
emacs \
|
||||
test-suite \
|
||||
benchmark-suite \
|
||||
gc-benchmarks \
|
||||
am \
|
||||
doc
|
||||
|
||||
|
|
15
NEWS
15
NEWS
|
@ -5,6 +5,21 @@ See the end for copying conditions.
|
|||
Please send Guile bug reports to bug-guile@gnu.org.
|
||||
|
||||
|
||||
Changes in 2.0.1 (since 2.0.0):
|
||||
|
||||
* New procedures (see the manual for details)
|
||||
|
||||
** exact-integer-sqrt, imported into core from (rnrs base)
|
||||
|
||||
* Bugs fixed
|
||||
|
||||
** exact-integer-sqrt now handles large integers correctly
|
||||
|
||||
exact-integer-sqrt now works correctly when applied to very large
|
||||
integers (too large to be precisely represented by a C double).
|
||||
It has also been imported into core from (rnrs base).
|
||||
|
||||
|
||||
Changes in 2.0.0 (changes since the 1.8.x series):
|
||||
|
||||
* New modules (see the manual for details)
|
||||
|
|
22
README
22
README
|
@ -1,20 +1,8 @@
|
|||
!!! This is not a Guile release; it is a source tree retrieved via
|
||||
Git or as a nightly snapshot at some random time after the
|
||||
Guile 1.8 release. If this were a Guile release, you would not see
|
||||
this message. !!! [fixme: zonk on release]
|
||||
|
||||
This is a 1.9 development version of Guile, Project GNU's extension
|
||||
language library. Guile is an interpreter for Scheme, packaged as a
|
||||
library that you can link into your applications to give them their
|
||||
own scripting language. Guile will eventually support other languages
|
||||
as well, giving users of Guile-based applications a choice of
|
||||
languages.
|
||||
|
||||
Guile versions with an odd middle number, i.e. 1.9.* are unstable
|
||||
development versions. Even middle numbers indicate stable versions.
|
||||
This has been the case since the 1.3.* series.
|
||||
|
||||
The next stable release will likely be version 2.0.0.
|
||||
This is version 2.0 of Guile, Project GNU's extension language library.
|
||||
Guile is an implementation of the Scheme programming language, packaged
|
||||
as a library that can be linked into applications to give them their own
|
||||
extension language. Guile supports other languages as well, giving
|
||||
users of Guile-based applications a choice of languages.
|
||||
|
||||
Please send bug reports to bug-guile@gnu.org.
|
||||
|
||||
|
|
1
THANKS
1
THANKS
|
@ -62,6 +62,7 @@ For fixes or providing information which led to a fix:
|
|||
Barry Fishman
|
||||
Charles Gagnon
|
||||
Fu-gangqiang
|
||||
Aidan Gauland
|
||||
Peter Gavin
|
||||
Nils Gey
|
||||
Eric Gillespie, Jr
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
AUTOMAKE_OPTIONS = gnu
|
||||
|
||||
am_frags = pre-inst-guile maintainer-dirs guilec
|
||||
am_frags = maintainer-dirs guilec
|
||||
|
||||
EXTRA_DIST = $(am_frags) ChangeLog-2008
|
||||
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
## am/pre-inst-guile --- define preinstguile and preinstguiletool vars
|
||||
|
||||
## Copyright (C) 2002, 2006 Free Software Foundation
|
||||
##
|
||||
## 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
|
||||
|
||||
## Commentary:
|
||||
|
||||
## This fragment defines two variables: preinstguile, preinstguiletool.
|
||||
## It can be included in any Makefile.am by adding the line:
|
||||
## include $(top_srcdir)/am/pre-inst-guile
|
||||
## See devel/build/pre-inst-guile.text (CVS only) for more info.
|
||||
|
||||
## Code:
|
||||
|
||||
preinstguile = $(top_builddir_absolute)/meta/guile
|
||||
preinstguiletool = GUILE="$(preinstguile)" $(top_srcdir)/scripts
|
||||
|
||||
## am/pre-inst-guile ends here
|
|
@ -6,6 +6,7 @@ SCM_BENCHMARKS = benchmarks/0-reference.bm \
|
|||
benchmarks/if.bm \
|
||||
benchmarks/logand.bm \
|
||||
benchmarks/ports.bm \
|
||||
benchmarks/r6rs-arithmetic.bm \
|
||||
benchmarks/read.bm \
|
||||
benchmarks/srfi-1.bm \
|
||||
benchmarks/srfi-13.bm \
|
||||
|
@ -14,7 +15,8 @@ SCM_BENCHMARKS = benchmarks/0-reference.bm \
|
|||
benchmarks/uniform-vector-read.bm \
|
||||
benchmarks/vectors.bm \
|
||||
benchmarks/vlists.bm \
|
||||
benchmarks/write.bm
|
||||
benchmarks/write.bm \
|
||||
benchmarks/strings.bm
|
||||
|
||||
EXTRA_DIST = guile-benchmark lib.scm $(SCM_BENCHMARKS) \
|
||||
ChangeLog-2008
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
(repeat (+ 2 <>) 7 100))
|
||||
|
||||
(benchmark "-" 1e7
|
||||
(repeat (+ 2 <>) 7 100))
|
||||
(repeat (- 2 <>) 7 100))
|
||||
|
||||
(benchmark "*" 1e7
|
||||
(repeat (* 1 <>) 1 100))
|
||||
|
|
35
benchmark-suite/benchmarks/r6rs-arithmetic.bm
Normal file
35
benchmark-suite/benchmarks/r6rs-arithmetic.bm
Normal file
|
@ -0,0 +1,35 @@
|
|||
;;; -*- mode: scheme; coding: utf-8; -*-
|
||||
;;; R6RS-specific arithmetic benchmarks
|
||||
;;;
|
||||
;;; Copyright (C) 2011 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, see
|
||||
;;; <http://www.gnu.org/licenses/>.
|
||||
|
||||
(define-module (benchmarks r6rs-arithmetic)
|
||||
#:use-module (benchmark-suite lib)
|
||||
#:use-module (rnrs arithmetic fixnums))
|
||||
|
||||
|
||||
(with-benchmark-prefix "fixnum"
|
||||
|
||||
(benchmark "fixnum? [yes]" 1e7
|
||||
(fixnum? 10000))
|
||||
|
||||
(let ((n (+ most-positive-fixnum 100)))
|
||||
(benchmark "fixnum? [no]" 1e7
|
||||
(fixnum? n)))
|
||||
|
||||
(benchmark "fxxor [2]" 1e7
|
||||
(fxxor 3 8)))
|
537
benchmark-suite/benchmarks/strings.bm
Normal file
537
benchmark-suite/benchmarks/strings.bm
Normal file
|
@ -0,0 +1,537 @@
|
|||
;;; -*- Mode: scheme; coding: utf-8; -*-
|
||||
;;; strings.bm
|
||||
;;;
|
||||
;;; Copyright (C) 2011 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)
|
||||
#:use-module (ice-9 i18n))
|
||||
|
||||
(use-modules (ice-9 i18n))
|
||||
|
||||
(seed->random-state 1)
|
||||
|
||||
;; Start from a known locale state
|
||||
(setlocale LC_ALL "C")
|
||||
|
||||
(define char-set:cased (char-set-union char-set:lower-case
|
||||
char-set:upper-case
|
||||
char-set:title-case))
|
||||
(define *latin1*
|
||||
(char-set->list (char-set-xor
|
||||
(char-set-intersection (ucs-range->char-set 0 255)
|
||||
char-set:cased)
|
||||
(->char-set #\µ)))) ; Can't do a case-insensitive comparison of a string
|
||||
; with mu in fr_FR.iso88591 since it case-folds into a
|
||||
; non-Latin-1 character.
|
||||
|
||||
(define *cased*
|
||||
(char-set->list char-set:cased))
|
||||
|
||||
(define (random-string c-list n)
|
||||
(let ((len (length c-list)))
|
||||
(apply string
|
||||
(map
|
||||
(lambda (x)
|
||||
(list-ref c-list (random len)))
|
||||
(iota n)))))
|
||||
|
||||
(define (diff-at-start str)
|
||||
(string-append "!" (substring str 1)))
|
||||
(define (diff-in-middle str)
|
||||
(let ((x (floor (/ (string-length str) 2))))
|
||||
(string-append (substring str 0 x)
|
||||
"!"
|
||||
(substring str (1+ x)))))
|
||||
(define (diff-at-end str)
|
||||
(string-append (substring str 0 (1- (string-length str)))
|
||||
"!"))
|
||||
|
||||
(define short-latin1-string (random-string *latin1* 10))
|
||||
(define medium-latin1-string (random-string *latin1* 100))
|
||||
(define long-latin1-string (random-string *latin1* 1000))
|
||||
|
||||
(define short-latin1-string-diff-at-start (diff-at-start short-latin1-string))
|
||||
(define medium-latin1-string-diff-at-start (diff-at-start medium-latin1-string))
|
||||
(define long-latin1-string-diff-at-start (diff-at-start long-latin1-string))
|
||||
|
||||
(define short-latin1-string-diff-in-middle (diff-in-middle short-latin1-string))
|
||||
(define medium-latin1-string-diff-in-middle (diff-in-middle medium-latin1-string))
|
||||
(define long-latin1-string-diff-in-middle (diff-in-middle long-latin1-string))
|
||||
|
||||
(define short-latin1-string-diff-at-end (diff-at-end short-latin1-string))
|
||||
(define medium-latin1-string-diff-at-end (diff-at-end medium-latin1-string))
|
||||
(define long-latin1-string-diff-at-end (diff-at-end long-latin1-string))
|
||||
|
||||
(define short-cased-string (random-string *cased* 10))
|
||||
(define medium-cased-string (random-string *cased* 100))
|
||||
(define long-cased-string (random-string *cased* 1000))
|
||||
|
||||
(define short-cased-string-diff-at-start (diff-at-start short-cased-string))
|
||||
(define medium-cased-string-diff-at-start (diff-at-start medium-cased-string))
|
||||
(define long-cased-string-diff-at-start (diff-at-start long-cased-string))
|
||||
|
||||
(define short-cased-string-diff-in-middle (diff-in-middle short-cased-string))
|
||||
(define medium-cased-string-diff-in-middle (diff-in-middle medium-cased-string))
|
||||
(define long-cased-string-diff-in-middle (diff-in-middle long-cased-string))
|
||||
|
||||
(define short-cased-string-diff-at-end (diff-at-end short-cased-string))
|
||||
(define medium-cased-string-diff-at-end (diff-at-end medium-cased-string))
|
||||
(define long-cased-string-diff-at-end (diff-at-end long-cased-string))
|
||||
|
||||
(define %french-locale-name "fr_FR.ISO-8859-1")
|
||||
|
||||
(define %french-utf8-locale-name "fr_FR.UTF-8")
|
||||
|
||||
(define %french-locale
|
||||
(false-if-exception
|
||||
(make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
|
||||
%french-locale-name)))
|
||||
|
||||
(define %french-utf8-locale
|
||||
(false-if-exception
|
||||
(make-locale (list LC_CTYPE LC_COLLATE LC_NUMERIC LC_TIME)
|
||||
%french-utf8-locale-name)))
|
||||
|
||||
(define (under-locale-or-unresolved locale thunk)
|
||||
;; On non-GNU systems, an exception may be raised only when the locale is
|
||||
;; actually used rather than at `make-locale'-time. Thus, we must guard
|
||||
;; against both.
|
||||
(if locale
|
||||
(if (string-contains %host-type "-gnu")
|
||||
(thunk)
|
||||
(catch 'system-error thunk
|
||||
(lambda (key . args)
|
||||
(throw 'unresolved))))
|
||||
(throw 'unresolved)))
|
||||
|
||||
(define (under-french-locale-or-unresolved thunk)
|
||||
(under-locale-or-unresolved %french-locale thunk))
|
||||
|
||||
(define (under-french-utf8-locale-or-unresolved thunk)
|
||||
(under-locale-or-unresolved %french-utf8-locale thunk))
|
||||
|
||||
(define (string-op str1 str2)
|
||||
(string<? str1 str2)
|
||||
(string>? str1 str2))
|
||||
|
||||
(define (string-ci-op str1 str2)
|
||||
(string-ci<? str1 str2)
|
||||
(string-ci>? str1 str2))
|
||||
|
||||
(define (string-fr-op str1 str2)
|
||||
(under-french-locale-or-unresolved
|
||||
(lambda ()
|
||||
(string-locale<? str1 str2 %french-locale)
|
||||
(string-locale>? str1 str2 %french-locale))))
|
||||
|
||||
(define (string-fr-utf8-op str1 str2)
|
||||
(under-french-utf8-locale-or-unresolved
|
||||
(lambda ()
|
||||
(string-locale<? str1 str2 %french-utf8-locale)
|
||||
(string-locale>? str1 str2 %french-utf8-locale))))
|
||||
|
||||
(define (string-fr-ci-op str1 str2)
|
||||
(under-french-locale-or-unresolved
|
||||
(lambda ()
|
||||
(string-locale-ci<? str1 str2 %french-locale)
|
||||
(string-locale-ci>? str1 str2 %french-locale))))
|
||||
|
||||
(define (string-fr-utf8-ci-op str1 str2)
|
||||
(under-french-utf8-locale-or-unresolved
|
||||
(lambda ()
|
||||
(string-locale-ci<? str1 str2 %french-utf8-locale)
|
||||
(string-locale-ci>? str1 str2 %french-utf8-locale))))
|
||||
|
||||
|
||||
(with-benchmark-prefix "string ops"
|
||||
|
||||
(with-benchmark-prefix "short Latin1"
|
||||
|
||||
(benchmark "compare initially differing strings" 100000
|
||||
(string-op short-latin1-string short-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "compare medially differing strings" 100000
|
||||
(string-op short-latin1-string short-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "compare terminally differing strings" 100000
|
||||
(string-op short-latin1-string short-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "compare identical strings" 100000
|
||||
(string-op short-latin1-string short-latin1-string))
|
||||
|
||||
(benchmark "case compare initially differing strings" 100000
|
||||
(string-ci-op short-latin1-string short-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "case compare medially differing strings" 100000
|
||||
(string-ci-op short-latin1-string short-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "case compare terminally differing strings" 100000
|
||||
(string-ci-op short-latin1-string short-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "case compare identical strings" 100000
|
||||
(string-ci-op short-latin1-string short-latin1-string))
|
||||
|
||||
(benchmark "French Latin-1 locale compare initially differing strings" 100000
|
||||
(string-fr-op short-latin1-string short-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French Latin-1 locale compare medially differing strings" 100000
|
||||
(string-fr-op short-latin1-string short-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French Latin-1 locale compare terminally differing strings" 100000
|
||||
(string-fr-op short-latin1-string short-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French Latin-1 locale compare identical strings" 100000
|
||||
(string-fr-op short-latin1-string short-latin1-string))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare initially differing strings" 100000
|
||||
(string-fr-ci-op short-latin1-string short-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare medially differing strings" 100000
|
||||
(string-fr-ci-op short-latin1-string short-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare terminally differing strings" 100000
|
||||
(string-fr-ci-op short-latin1-string short-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare identical strings" 100000
|
||||
(string-fr-ci-op short-latin1-string short-latin1-string))
|
||||
|
||||
(benchmark "French UTF-8 locale compare initially differing strings" 100000
|
||||
(string-fr-utf8-op short-latin1-string short-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale compare medially differing strings" 100000
|
||||
(string-fr-utf8-op short-latin1-string short-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale compare terminally differing strings" 100000
|
||||
(string-fr-utf8-op short-latin1-string short-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale compare identical strings" 100000
|
||||
(string-fr-utf8-op short-latin1-string short-latin1-string))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare initially differing strings" 100000
|
||||
(string-fr-utf8-ci-op short-latin1-string short-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare medially differing strings" 100000
|
||||
(string-fr-utf8-ci-op short-latin1-string short-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare terminally differing strings" 100000
|
||||
(string-fr-utf8-ci-op short-latin1-string short-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare identical strings" 100000
|
||||
(string-fr-utf8-ci-op short-latin1-string short-latin1-string)))
|
||||
|
||||
(with-benchmark-prefix "medium Latin1"
|
||||
|
||||
(benchmark "compare initially differing strings" 10000
|
||||
(string-op medium-latin1-string medium-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "compare medially differing strings" 10000
|
||||
(string-op medium-latin1-string medium-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "compare terminally differing strings" 10000
|
||||
(string-op medium-latin1-string medium-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "compare identical strings" 10000
|
||||
(string-op medium-latin1-string medium-latin1-string))
|
||||
|
||||
(benchmark "case compare initially differing strings" 10000
|
||||
(string-ci-op medium-latin1-string medium-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "case compare medially differing strings" 10000
|
||||
(string-ci-op medium-latin1-string medium-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "case compare terminally differing strings" 10000
|
||||
(string-ci-op medium-latin1-string medium-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "case compare identical strings" 10000
|
||||
(string-ci-op medium-latin1-string medium-latin1-string))
|
||||
|
||||
(benchmark "French Latin-1 locale compare initially differing strings" 10000
|
||||
(string-fr-op medium-latin1-string medium-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French Latin-1 locale compare medially differing strings" 10000
|
||||
(string-fr-op medium-latin1-string medium-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French Latin-1 locale compare terminally differing strings" 10000
|
||||
(string-fr-op medium-latin1-string medium-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French Latin-1 locale compare identical strings" 10000
|
||||
(string-fr-op medium-latin1-string medium-latin1-string))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare initially differing strings" 10000
|
||||
(string-fr-ci-op medium-latin1-string medium-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare medially differing strings" 10000
|
||||
(string-fr-ci-op medium-latin1-string medium-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare terminally differing strings" 10000
|
||||
(string-fr-ci-op medium-latin1-string medium-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare identical strings" 10000
|
||||
(string-fr-ci-op medium-latin1-string medium-latin1-string))
|
||||
|
||||
(benchmark "French UTF-8 locale compare initially differing strings" 10000
|
||||
(string-fr-utf8-op medium-latin1-string medium-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale compare medially differing strings" 10000
|
||||
(string-fr-utf8-op medium-latin1-string medium-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale compare terminally differing strings" 10000
|
||||
(string-fr-utf8-op medium-latin1-string medium-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale compare identical strings" 10000
|
||||
(string-fr-utf8-op medium-latin1-string medium-latin1-string))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare initially differing strings" 10000
|
||||
(string-fr-utf8-ci-op medium-latin1-string medium-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare medially differing strings" 10000
|
||||
(string-fr-utf8-ci-op medium-latin1-string medium-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare terminally differing strings" 10000
|
||||
(string-fr-utf8-ci-op medium-latin1-string medium-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare identical strings" 10000
|
||||
(string-fr-utf8-ci-op medium-latin1-string medium-latin1-string)))
|
||||
|
||||
(with-benchmark-prefix "long Latin1"
|
||||
|
||||
(benchmark "compare initially differing strings" 1000
|
||||
(string-op long-latin1-string long-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "compare medially differing strings" 1000
|
||||
(string-op long-latin1-string long-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "compare terminally differing strings" 1000
|
||||
(string-op long-latin1-string long-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "compare identical strings" 1000
|
||||
(string-op long-latin1-string long-latin1-string))
|
||||
|
||||
(benchmark "case compare initially differing strings" 1000
|
||||
(string-ci-op long-latin1-string long-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "case compare medially differing strings" 1000
|
||||
(string-ci-op long-latin1-string long-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "case compare terminally differing strings" 1000
|
||||
(string-ci-op long-latin1-string long-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "case compare identical strings" 1000
|
||||
(string-ci-op long-latin1-string long-latin1-string))
|
||||
|
||||
(benchmark "French Latin-1 locale compare initially differing strings" 1000
|
||||
(string-fr-op long-latin1-string long-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French Latin-1 locale compare medially differing strings" 1000
|
||||
(string-fr-op long-latin1-string long-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French Latin-1 locale compare terminally differing strings" 1000
|
||||
(string-fr-op long-latin1-string long-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French Latin-1 locale compare identical strings" 1000
|
||||
(string-fr-op long-latin1-string long-latin1-string))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare initially differing strings" 1000
|
||||
(string-fr-ci-op long-latin1-string long-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare medially differing strings" 1000
|
||||
(string-fr-ci-op long-latin1-string long-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare terminally differing strings" 1000
|
||||
(string-fr-ci-op long-latin1-string long-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French Latin-1 locale case compare identical strings" 1000
|
||||
(string-fr-ci-op long-latin1-string long-latin1-string))
|
||||
|
||||
(benchmark "French UTF-8 locale compare initially differing strings" 1000
|
||||
(string-fr-utf8-op long-latin1-string long-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale compare medially differing strings" 1000
|
||||
(string-fr-utf8-op long-latin1-string long-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale compare terminally differing strings" 1000
|
||||
(string-fr-utf8-op long-latin1-string long-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale compare identical strings" 1000
|
||||
(string-fr-utf8-op long-latin1-string long-latin1-string))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare initially differing strings" 1000
|
||||
(string-fr-utf8-ci-op long-latin1-string long-latin1-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare medially differing strings" 1000
|
||||
(string-fr-utf8-ci-op long-latin1-string long-latin1-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare terminally differing strings" 1000
|
||||
(string-fr-utf8-ci-op long-latin1-string long-latin1-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare identical strings" 1000
|
||||
(string-fr-utf8-ci-op long-latin1-string long-latin1-string)))
|
||||
|
||||
(with-benchmark-prefix "short Unicode"
|
||||
|
||||
(benchmark "compare initially differing strings" 100000
|
||||
(string-op short-cased-string short-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "compare medially differing strings" 100000
|
||||
(string-op short-cased-string short-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "compare terminally differing strings" 100000
|
||||
(string-op short-cased-string short-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "compare identical strings" 100000
|
||||
(string-op short-cased-string short-cased-string))
|
||||
|
||||
(benchmark "case compare initially differing strings" 100000
|
||||
(string-ci-op short-cased-string short-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "case compare medially differing strings" 100000
|
||||
(string-ci-op short-cased-string short-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "case compare terminally differing strings" 100000
|
||||
(string-ci-op short-cased-string short-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "case compare identical strings" 100000
|
||||
(string-ci-op short-cased-string short-cased-string))
|
||||
|
||||
(benchmark "French UTF-8 locale compare initially differing strings" 100000
|
||||
(string-fr-utf8-op short-cased-string short-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale compare medially differing strings" 100000
|
||||
(string-fr-utf8-op short-cased-string short-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale compare terminally differing strings" 100000
|
||||
(string-fr-utf8-op short-cased-string short-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale compare identical strings" 100000
|
||||
(string-fr-utf8-op short-cased-string short-cased-string))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare initially differing strings" 100000
|
||||
(string-fr-utf8-ci-op short-cased-string short-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare medially differing strings" 100000
|
||||
(string-fr-utf8-ci-op short-cased-string short-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare terminally differing strings" 100000
|
||||
(string-fr-utf8-ci-op short-cased-string short-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare identical strings" 100000
|
||||
(string-fr-utf8-ci-op short-cased-string short-cased-string)))
|
||||
|
||||
(with-benchmark-prefix "medium Unicode"
|
||||
|
||||
(benchmark "compare initially differing strings" 10000
|
||||
(string-op medium-cased-string medium-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "compare medially differing strings" 10000
|
||||
(string-op medium-cased-string medium-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "compare terminally differing strings" 10000
|
||||
(string-op medium-cased-string medium-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "compare identical strings" 10000
|
||||
(string-op medium-cased-string medium-cased-string))
|
||||
|
||||
(benchmark "case compare initially differing strings" 10000
|
||||
(string-ci-op medium-cased-string medium-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "case compare medially differing strings" 10000
|
||||
(string-ci-op medium-cased-string medium-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "case compare terminally differing strings" 10000
|
||||
(string-ci-op medium-cased-string medium-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "case compare identical strings" 10000
|
||||
(string-ci-op medium-cased-string medium-cased-string))
|
||||
|
||||
(benchmark "French UTF-8 locale compare initially differing strings" 10000
|
||||
(string-fr-utf8-op medium-cased-string medium-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale compare medially differing strings" 10000
|
||||
(string-fr-utf8-op medium-cased-string medium-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale compare terminally differing strings" 10000
|
||||
(string-fr-utf8-op medium-cased-string medium-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale compare identical strings" 10000
|
||||
(string-fr-utf8-op medium-cased-string medium-cased-string))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare initially differing strings" 10000
|
||||
(string-fr-utf8-ci-op medium-cased-string medium-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare medially differing strings" 10000
|
||||
(string-fr-utf8-ci-op medium-cased-string medium-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare terminally differing strings" 10000
|
||||
(string-fr-utf8-ci-op medium-cased-string medium-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare identical strings" 10000
|
||||
(string-fr-utf8-ci-op medium-cased-string medium-cased-string)))
|
||||
|
||||
(with-benchmark-prefix "long Unicode"
|
||||
|
||||
(benchmark "compare initially differing strings" 1000
|
||||
(string-op long-cased-string long-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "compare medially differing strings" 1000
|
||||
(string-op long-cased-string long-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "compare terminally differing strings" 1000
|
||||
(string-op long-cased-string long-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "compare identical strings" 1000
|
||||
(string-op long-cased-string long-cased-string))
|
||||
|
||||
(benchmark "case compare initially differing strings" 1000
|
||||
(string-ci-op long-cased-string long-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "case compare medially differing strings" 1000
|
||||
(string-ci-op long-cased-string long-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "case compare terminally differing strings" 1000
|
||||
(string-ci-op long-cased-string long-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "case compare identical strings" 1000
|
||||
(string-ci-op long-cased-string long-cased-string))
|
||||
|
||||
(benchmark "French UTF-8 locale compare initially differing strings" 1000
|
||||
(string-fr-utf8-op long-cased-string long-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale compare medially differing strings" 1000
|
||||
(string-fr-utf8-op long-cased-string long-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale compare terminally differing strings" 1000
|
||||
(string-fr-utf8-op long-cased-string long-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale compare identical strings" 1000
|
||||
(string-fr-utf8-op long-cased-string long-cased-string))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare initially differing strings" 1000
|
||||
(string-fr-utf8-ci-op long-cased-string long-cased-string-diff-at-start))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare medially differing strings" 1000
|
||||
(string-fr-utf8-ci-op long-cased-string long-cased-string-diff-in-middle))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare terminally differing strings" 1000
|
||||
(string-fr-utf8-ci-op long-cased-string long-cased-string-diff-at-end))
|
||||
|
||||
(benchmark "French UTF-8 locale case compare identical strings" 1000
|
||||
(string-fr-utf8-ci-op long-cased-string long-cased-string))))
|
||||
|
||||
|
|
@ -57,13 +57,6 @@ else
|
|||
aix*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
darwin*)
|
||||
case $cc_basename in
|
||||
xlc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
mingw* | cygwin* | pw32* | os2* | cegcc*)
|
||||
;;
|
||||
hpux9* | hpux10* | hpux11*)
|
||||
|
@ -72,9 +65,7 @@ else
|
|||
irix5* | irix6* | nonstopux*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
newsos6)
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
linux* | k*bsd*-gnu | kopensolaris*-gnu)
|
||||
case $cc_basename in
|
||||
ecc*)
|
||||
wl='-Wl,'
|
||||
|
@ -85,17 +76,26 @@ else
|
|||
lf95*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
pgcc | pgf77 | pgf90)
|
||||
nagfor*)
|
||||
wl='-Wl,-Wl,,'
|
||||
;;
|
||||
pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
ccc*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
xl* | bgxl* | bgf* | mpixl*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
como)
|
||||
wl='-lopt='
|
||||
;;
|
||||
*)
|
||||
case `$CC -V 2>&1 | sed 5q` in
|
||||
*Sun\ F* | *Sun*Fortran*)
|
||||
wl=
|
||||
;;
|
||||
*Sun\ C*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
|
@ -103,14 +103,25 @@ else
|
|||
;;
|
||||
esac
|
||||
;;
|
||||
newsos6)
|
||||
;;
|
||||
*nto* | *qnx*)
|
||||
;;
|
||||
osf3* | osf4* | osf5*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
rdos*)
|
||||
;;
|
||||
solaris*)
|
||||
case $cc_basename in
|
||||
f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
|
||||
wl='-Qoption ld '
|
||||
;;
|
||||
*)
|
||||
wl='-Wl,'
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
sunos4*)
|
||||
wl='-Qoption ld '
|
||||
;;
|
||||
|
@ -171,15 +182,14 @@ if test "$with_gnu_ld" = yes; then
|
|||
fi
|
||||
;;
|
||||
amigaos*)
|
||||
case "$host_cpu" in
|
||||
powerpc)
|
||||
;;
|
||||
m68k)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
# Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports
|
||||
# that the semantics of dynamic libraries on AmigaOS, at least up
|
||||
# to version 4, is to share data among multiple programs linked
|
||||
# with the same dynamic library. Since this doesn't match the
|
||||
# behavior of shared libraries on other platforms, we cannot use
|
||||
# them.
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
beos*)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
|
@ -198,11 +208,13 @@ if test "$with_gnu_ld" = yes; then
|
|||
ld_shlibs=no
|
||||
fi
|
||||
;;
|
||||
haiku*)
|
||||
;;
|
||||
interix[3-9]*)
|
||||
hardcode_direct=no
|
||||
hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
|
||||
;;
|
||||
gnu* | linux* | k*bsd*-gnu)
|
||||
gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
|
||||
if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
|
||||
:
|
||||
else
|
||||
|
@ -325,10 +337,14 @@ else
|
|||
fi
|
||||
;;
|
||||
amigaos*)
|
||||
case "$host_cpu" in
|
||||
powerpc)
|
||||
;;
|
||||
m68k)
|
||||
hardcode_libdir_flag_spec='-L$libdir'
|
||||
hardcode_minus_L=yes
|
||||
# see comment about different semantics on the GNU ld section
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
bsdi[45]*)
|
||||
;;
|
||||
|
@ -342,16 +358,10 @@ else
|
|||
;;
|
||||
darwin* | rhapsody*)
|
||||
hardcode_direct=no
|
||||
if test "$GCC" = yes ; then
|
||||
if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then
|
||||
:
|
||||
else
|
||||
case $cc_basename in
|
||||
xlc*)
|
||||
;;
|
||||
*)
|
||||
ld_shlibs=no
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
dgux*)
|
||||
|
@ -417,6 +427,8 @@ else
|
|||
hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
|
||||
hardcode_libdir_separator=:
|
||||
;;
|
||||
*nto* | *qnx*)
|
||||
;;
|
||||
openbsd*)
|
||||
if test -f /usr/libexec/ld.so; then
|
||||
hardcode_direct=yes
|
||||
|
@ -512,7 +524,12 @@ case "$host_os" in
|
|||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
amigaos*)
|
||||
library_names_spec='$libname.a'
|
||||
case "$host_cpu" in
|
||||
powerpc*)
|
||||
library_names_spec='$libname$shrext' ;;
|
||||
m68k)
|
||||
library_names_spec='$libname.a' ;;
|
||||
esac
|
||||
;;
|
||||
beos*)
|
||||
library_names_spec='$libname$shrext'
|
||||
|
@ -542,6 +559,9 @@ case "$host_os" in
|
|||
gnu*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
haiku*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
hpux9* | hpux10* | hpux11*)
|
||||
case $host_cpu in
|
||||
ia64*)
|
||||
|
@ -577,7 +597,7 @@ case "$host_os" in
|
|||
;;
|
||||
linux*oldld* | linux*aout* | linux*coff*)
|
||||
;;
|
||||
linux* | k*bsd*-gnu)
|
||||
linux* | k*bsd*-gnu | kopensolaris*-gnu)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
knetbsd*-gnu)
|
||||
|
@ -589,7 +609,7 @@ case "$host_os" in
|
|||
newsos6)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
nto-qnx*)
|
||||
*nto* | *qnx*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
openbsd*)
|
||||
|
@ -620,6 +640,9 @@ case "$host_os" in
|
|||
sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
tpf*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
uts4*)
|
||||
library_names_spec='$libname$shrext'
|
||||
;;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
# Print a version string.
|
||||
scriptversion=2011-01-04.17; # UTC
|
||||
scriptversion=2011-02-19.19; # UTC
|
||||
|
||||
# Copyright (C) 2007-2011 Free Software Foundation, Inc.
|
||||
#
|
||||
|
@ -80,6 +80,7 @@ nl='
|
|||
|
||||
# Avoid meddling by environment variable of the same name.
|
||||
v=
|
||||
v_from_git=
|
||||
|
||||
# First see if there is a tarball-only version file.
|
||||
# then try "git describe", then default.
|
||||
|
@ -134,12 +135,17 @@ then
|
|||
# Change the first '-' to a '.', so version-comparing tools work properly.
|
||||
# Remove the "g" in git describe's output string, to save a byte.
|
||||
v=`echo "$v" | sed 's/-/./;s/\(.*\)-g/\1-/'`;
|
||||
v_from_git=1
|
||||
else
|
||||
v=UNKNOWN
|
||||
fi
|
||||
|
||||
v=`echo "$v" |sed 's/^v//'`
|
||||
|
||||
# Test whether to append the "-dirty" suffix only if the version
|
||||
# string we're using came from git. I.e., skip the test if it's "UNKNOWN"
|
||||
# or if it came from .tarball-version.
|
||||
if test -n "$v_from_git"; then
|
||||
# Don't declare a version "dirty" merely because a time stamp has changed.
|
||||
git update-index --refresh > /dev/null 2>&1
|
||||
|
||||
|
@ -152,6 +158,7 @@ case "$dirty" in
|
|||
*) v="$v-dirty" ;;
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Omit the trailing newline, so that m4_esyscmd can use the result directly.
|
||||
echo "$v" | tr -d "$nl"
|
||||
|
|
42
configure.ac
42
configure.ac
|
@ -29,9 +29,7 @@ Floor, Boston, MA 02110-1301, USA.
|
|||
AC_PREREQ(2.61)
|
||||
|
||||
AC_INIT([GNU Guile],
|
||||
m4_esyscmd([build-aux/git-version-gen \
|
||||
.tarball-version \
|
||||
's/^release_\([0-9][0-9]*\)-\([0-9][0-9]*\)-\([0-9][0-9]*\)/v\1.\2\.\3/g']),
|
||||
m4_esyscmd([build-aux/git-version-gen .tarball-version]),
|
||||
[bug-guile@gnu.org])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
@ -775,7 +773,7 @@ AC_CHECK_FUNCS([DINFINITY DQNAN cexp chsize clog clog10 ctermid fesetround ftime
|
|||
# cuserid - on Tru64 5.1b the declaration is documented to be available
|
||||
# only with `_XOPEN_SOURCE' or some such.
|
||||
#
|
||||
AC_CHECK_HEADERS([crypt.h netdb.h pthread.h sys/param.h sys/resource.h sys/file.h])
|
||||
AC_CHECK_HEADERS([crypt.h netdb.h pthread.h sys/param.h sys/resource.h sys/file.h sys/mman.h])
|
||||
AC_CHECK_FUNCS(chroot flock getlogin cuserid getpriority setpriority getpass sethostname gethostname)
|
||||
AC_CHECK_DECLS([sethostname, hstrerror, cuserid])
|
||||
|
||||
|
@ -1240,7 +1238,7 @@ save_LIBS="$LIBS"
|
|||
LIBS="$BDW_GC_LIBS $LIBS"
|
||||
CFLAGS="$BDW_GC_CFLAGS $CFLAGS"
|
||||
|
||||
AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active])
|
||||
AC_CHECK_FUNCS([GC_do_blocking GC_call_with_gc_active GC_pthread_exit GC_pthread_cancel GC_allow_register_threads GC_pthread_sigmask])
|
||||
|
||||
# Though the `GC_do_blocking ()' symbol is present in GC 7.1, it is not
|
||||
# declared, and has a different type (returning void instead of
|
||||
|
@ -1258,6 +1256,13 @@ AC_CHECK_TYPE([GC_fn_type],
|
|||
[],
|
||||
[#include <gc/gc.h>])
|
||||
|
||||
# `GC_stack_base' is not available in GC 7.1 and earlier.
|
||||
AC_CHECK_TYPE([struct GC_stack_base],
|
||||
[AC_DEFINE([HAVE_GC_STACK_BASE], [1],
|
||||
[Define this if the `GC_stack_base' type is available.])],
|
||||
[],
|
||||
[#include <gc/gc.h>])
|
||||
|
||||
LIBS="$save_LIBS"
|
||||
|
||||
|
||||
|
@ -1489,7 +1494,7 @@ if test "$cross_compiling" = "yes"; then
|
|||
AC_MSG_CHECKING(guile for build)
|
||||
GUILE_FOR_BUILD="${GUILE_FOR_BUILD-guile}"
|
||||
else
|
||||
GUILE_FOR_BUILD='$(preinstguile)'
|
||||
GUILE_FOR_BUILD='this-value-will-never-be-used'
|
||||
fi
|
||||
|
||||
## AC_MSG_CHECKING("if we are cross compiling")
|
||||
|
@ -1498,7 +1503,7 @@ if test "$cross_compiling" = "yes"; then
|
|||
AC_MSG_RESULT($GUILE_FOR_BUILD)
|
||||
fi
|
||||
AC_ARG_VAR(GUILE_FOR_BUILD,[guile for build system])
|
||||
AC_SUBST(GUILE_FOR_BUILD)
|
||||
AM_SUBST_NOTMAKE(GUILE_FOR_BUILD)
|
||||
|
||||
## If we're using GCC, ask for aggressive warnings.
|
||||
GCC_CFLAGS=""
|
||||
|
@ -1568,9 +1573,27 @@ AC_SUBST(LIBGUILE_I18N_INTERFACE)
|
|||
|
||||
#######################################################################
|
||||
|
||||
dnl Tell guile-config what flags guile users should compile and link with.
|
||||
dnl Tell guile-config what flags guile users should compile and link
|
||||
dnl with, keeping only `-I' flags from $CPPFLAGS.
|
||||
GUILE_CFLAGS=""
|
||||
next_is_includedir=false
|
||||
for flag in $CPPFLAGS
|
||||
do
|
||||
if $next_is_includedir; then
|
||||
GUILE_CFLAGS="$GUILE_CFLAGS -I $flag"
|
||||
next_is_includedir=false
|
||||
else
|
||||
case "$flag" in
|
||||
-I) next_is_includedir=true;;
|
||||
-I*) GUILE_CFLAGS="$GUILE_CFLAGS $flag";;
|
||||
*) ;;
|
||||
esac
|
||||
fi
|
||||
done
|
||||
|
||||
GUILE_CFLAGS="$GUILE_CFLAGS $PTHREAD_CFLAGS"
|
||||
GUILE_LIBS="$LDFLAGS $LIBS"
|
||||
GUILE_CFLAGS="$CPPFLAGS $PTHREAD_CFLAGS"
|
||||
|
||||
AC_SUBST(GUILE_LIBS)
|
||||
AC_SUBST(GUILE_CFLAGS)
|
||||
|
||||
|
@ -1602,6 +1625,7 @@ AC_CONFIG_FILES([
|
|||
am/Makefile
|
||||
lib/Makefile
|
||||
benchmark-suite/Makefile
|
||||
gc-benchmarks/Makefile
|
||||
doc/Makefile
|
||||
doc/r5rs/Makefile
|
||||
doc/ref/Makefile
|
||||
|
|
291
doc/guile.1
291
doc/guile.1
|
@ -3,113 +3,210 @@
|
|||
.\" Process this file with
|
||||
.\" groff -man -Tascii foo.1
|
||||
.\"
|
||||
.TH GUILE 1
|
||||
.\" title section date source manual
|
||||
.TH GUILE 1 "2011-03-04" GNU "GNU Guile 2.0"
|
||||
.
|
||||
.SH NAME
|
||||
guile \- the GNU extension language
|
||||
guile \- The GNU Project Extension Language
|
||||
.
|
||||
.SH SYNOPSIS
|
||||
.B guile [-L DIRECTORY] [-l FILE] [-e FUNCTION] [\\\\]
|
||||
.B [-c EXPR] [-s SCRIPT] [--] [SCRIPT] [ARG...]
|
||||
.B guile
|
||||
.RB [\| \-L
|
||||
.IR DIRECTORY \|]
|
||||
.RB [\| \-l
|
||||
.IR FILE \|]
|
||||
.RB [\| \-e
|
||||
.IR FUNCTION \|]
|
||||
.\".RI [\| \\\\ \|]
|
||||
.RB [\| \e \|]
|
||||
.RB [\| \-c
|
||||
.IR EXPR \|]
|
||||
.RB [\| \-s
|
||||
.IR SCRIPT \|]
|
||||
.RB [\| \-\- \|]
|
||||
.RI [\| SCRIPT
|
||||
.RI [\| ARGs\ for\ SCRIPT \|]\c
|
||||
.RI ]
|
||||
|
||||
Only the most useful options are listed here; see below for the
|
||||
remainder.
|
||||
Only the most useful options are listed here;
|
||||
see below for the remainder.
|
||||
.
|
||||
.SH DESCRIPTION
|
||||
GNU Guile is an implemention of the Scheme programming language. It
|
||||
extends the R5RS and R6RS language standards, providing additional
|
||||
features necessary for real-world use. Guile works well for interactive
|
||||
use, basic scripting, and extension of larger applications, as well as
|
||||
for stand-alone Scheme application development.
|
||||
GNU Guile is an implementation of the Scheme programming language.
|
||||
It extends the R5RS and R6RS language standards,
|
||||
providing additional features necessary for real-world use.
|
||||
|
||||
Guile works well for interactive use,
|
||||
basic scripting,
|
||||
and extension of larger applications,
|
||||
as well as for stand-alone Scheme application development.
|
||||
|
||||
The
|
||||
.B guile
|
||||
executable itself provides a stand-alone interactive compiler and
|
||||
run-time for Scheme programs, both for interactive use and for executing
|
||||
Scheme scripts or programs.
|
||||
run-time for Scheme programs,
|
||||
both for interactive use and for executing Scheme scripts or programs.
|
||||
|
||||
This manual page provides only brief instruction in invoking
|
||||
.B guile
|
||||
from the command line. Please consult the guile info documentation
|
||||
(type
|
||||
.B info "guile(Invoking Guile)"
|
||||
at a command prompt) for more information.
|
||||
|
||||
from the command line.
|
||||
Please consult the Guile info documentation for more information,
|
||||
(type \fB info "(guile)Invoking Guile"\fR at a command prompt).
|
||||
.
|
||||
.SH OPTIONS
|
||||
.IP -L DIRECTORY
|
||||
Add DIRECTORY to the front of Guile's module load path.
|
||||
.IP -l FILE
|
||||
Load scheme source code from file.
|
||||
.IP -e FUNCTION
|
||||
After reading script, apply FUNCTION to command-line arguments. Note
|
||||
that FUNCTION is evaluated, so e.g.
|
||||
.TP
|
||||
.BI -L \ DIRECTORY
|
||||
Add \fIDIRECTORY\fR to the front of Guile's module load path.
|
||||
.
|
||||
.TP
|
||||
.BI -l \ FILE
|
||||
Load Scheme source code from \fIFILE\fR.
|
||||
.
|
||||
.TP
|
||||
.BI -e \ FUNCTION
|
||||
After reading \fISCRIPT\fR, apply \fIFUNCTION\fR to command-line arguments.
|
||||
Note that \fIFUNCTION\fR is evaluated,
|
||||
so, for example,
|
||||
.B (@ (my-module) my-proc)
|
||||
is valid here.
|
||||
.IP \\\\
|
||||
.
|
||||
.TP
|
||||
.B \e
|
||||
The "meta switch", used to work around limitations in #! scripts.
|
||||
See "The Meta Switch" in the texinfo documentation, for more details.
|
||||
.IP --
|
||||
Stop argument processing, start guile in interactive mode.
|
||||
.IP -c EXPR
|
||||
Stop argument processing, evaluate EXPR as a scheme expression.
|
||||
.IP -s SCRIPT-FILE
|
||||
Load Scheme source from SCRIPT-FILE and execute as a script. Note that
|
||||
the in many cases it is not necessary to use -s; one may invoke Guile
|
||||
just as
|
||||
.B guile SCRIPT-FILE ARG...
|
||||
.IP -ds
|
||||
Do -s SCRIPT at this point. Note that this argument must be used in
|
||||
conjuction with -s.
|
||||
.IP --debug
|
||||
Start guile with the debugging VM. By default, on when invoked
|
||||
interactively, off otherwise.
|
||||
.IP --auto-compile
|
||||
See "The Meta Switch" in the texinfo documentation for more details.
|
||||
.
|
||||
.TP
|
||||
.B --
|
||||
Stop argument processing, and start
|
||||
.B guile
|
||||
in interactive mode.
|
||||
.
|
||||
.TP
|
||||
.BI -c \ EXPR
|
||||
Stop argument processing,
|
||||
and evaluate \fIEXPR\fR as a Scheme expression.
|
||||
.
|
||||
.TP
|
||||
.BI -s \ SCRIPT-FILE
|
||||
Load Scheme source from \fISCRIPT-FILE\fR and execute as a script.
|
||||
Note that in many cases it is not necessary to use \fB-s\fR;
|
||||
one may invoke
|
||||
.B guile
|
||||
simply as
|
||||
.B guile
|
||||
.I SCRIPT-FILE ARG...
|
||||
.
|
||||
.TP
|
||||
.B -ds
|
||||
Carry out \fB\-s \fISCRIPT\fR at this point in the option sequence.
|
||||
Note that this argument must be used in conjunction with \fB\-s\fR.
|
||||
.
|
||||
.TP
|
||||
.B --debug
|
||||
Start
|
||||
.B guile
|
||||
with the debugging VM.
|
||||
By default, debugging is on when
|
||||
.B guile
|
||||
is invoked interactively;
|
||||
it is off otherwise.
|
||||
.
|
||||
.TP
|
||||
.B --no-debug
|
||||
Start
|
||||
.B guile
|
||||
without the debugging VM,
|
||||
even if
|
||||
.B guile
|
||||
is being run interactively.
|
||||
.
|
||||
.TP
|
||||
.B --auto-compile
|
||||
Compile source files automatically (default behavior).
|
||||
.IP --no-auto-compile
|
||||
.
|
||||
.TP
|
||||
.B --no-autocompile
|
||||
Disable automatic source file compilation.
|
||||
.IP --listen[=P]
|
||||
Listen on a port or socket for remote REPL connections. See the manual
|
||||
for more details.
|
||||
.IP --use-srfi=N,M...
|
||||
Load SRFI extensions N, M, etc. For example, "--use-srfi=8,13".
|
||||
.IP -x EXTENSION
|
||||
Add EXTENSION to the Guile's load extension list.
|
||||
.IP --help
|
||||
Describe command line options and exit
|
||||
.IP --version
|
||||
.
|
||||
.TP
|
||||
\fB\-\-listen\fR[=\fIP\fR]
|
||||
Listen on a port or socket for remote REPL connections.
|
||||
See the manual for more details.
|
||||
.
|
||||
.TP
|
||||
\fB\-\-use\-srfi\fR=\fIN,M\fR...
|
||||
Load SRFI extensions \fIN\fR, \fIM\fR, etc.
|
||||
For example,
|
||||
\fB \-\-use\-srfi\fR=\fI8,13\fR.
|
||||
.
|
||||
.TP
|
||||
.BI -x \ EXTENSION
|
||||
Add \fIEXTENSION\fR to the
|
||||
.B guile
|
||||
load extension list.
|
||||
.
|
||||
.TP
|
||||
\fB\-h\fR, \fB\-\-help\fR
|
||||
Describe command-line options and exit.
|
||||
.
|
||||
.TP
|
||||
\fB\-v\fR, \fB\-\-version\fR
|
||||
Display guile version and exit.
|
||||
.IP -q
|
||||
In interactive mode, suppress loading the user's ~/.guile file.
|
||||
|
||||
.
|
||||
.TP
|
||||
.B -q
|
||||
In interactive mode,
|
||||
suppress loading the user's initialization file,
|
||||
.I ~/.guile.
|
||||
.
|
||||
.SH ENVIRONMENT
|
||||
.\".TP \w'MANROFFSEQ\ \ 'u
|
||||
.TP
|
||||
.B GUILE_LOAD_PATH
|
||||
If
|
||||
.RB $ GUILE_LOAD_PATH
|
||||
is set, its value is used to agument the path to search for scheme
|
||||
files when loading. It should be a colon separated list of
|
||||
directories which will be prepended to the default %load-path.
|
||||
|
||||
is set before
|
||||
.B guile
|
||||
is started,
|
||||
its value is used to augment the path to search for Scheme files when
|
||||
loading.
|
||||
It should be a colon-separated list of directories,
|
||||
which will be prefixed to the default
|
||||
.B %load-path.
|
||||
.TP
|
||||
.B GUILE_LOAD_COMPILED_PATH
|
||||
If
|
||||
.RB $ GUILE_LOAD_COMPILED_PATH
|
||||
is set, its value is used to agument the path to search for compiled
|
||||
Scheme files (.go files) when loading. It should be a colon separated
|
||||
list of directories which will be prepended to the default %load-path.
|
||||
|
||||
is set before
|
||||
.B guile
|
||||
is started,
|
||||
its value is used to augment the path to search for compiled
|
||||
Scheme files (.go files) when loading.
|
||||
It should be a colon-separated list of directories,
|
||||
which will be prefixed to the default
|
||||
.B %load-compiled-path.
|
||||
.
|
||||
.SH FILES
|
||||
.TP
|
||||
.I ~/.guile
|
||||
is a guile script that is executed before any other processing occurs.
|
||||
For example, the following .guile activates guile's readline
|
||||
interface:
|
||||
A Guile script that is executed before any other processing occurs.
|
||||
For example, the following
|
||||
.I .guile
|
||||
activates guile's readline interface:
|
||||
|
||||
.RS 4
|
||||
(use-modules (ice-9 readline))
|
||||
.RS 9
|
||||
.B (use-modules (ice-9 readline))
|
||||
.RS 0
|
||||
(activate-readline)
|
||||
|
||||
.B (activate-readline)
|
||||
.
|
||||
.SH "SEE ALSO"
|
||||
The full documentation for guile is maintained as a Texinfo manual. If
|
||||
the info and guile programs are properly installed at your site, the
|
||||
command
|
||||
The full documentation for Guile is maintained as a Texinfo manual.
|
||||
If the
|
||||
.B info
|
||||
and
|
||||
.B guile
|
||||
programs are properly installed at your site,
|
||||
the command
|
||||
.IP
|
||||
.B info guile
|
||||
.PP
|
||||
|
@ -117,39 +214,45 @@ should give you access to the complete manual.
|
|||
|
||||
http://www.schemers.org provides a general introduction to the
|
||||
Scheme language.
|
||||
|
||||
.
|
||||
.SH "REPORTING BUGS"
|
||||
There is a mailing list, bug-guile@gnu.org, for reporting Guile bugs and
|
||||
fixes. But before reporting something as a bug, please try to be sure
|
||||
that it really is a bug, not a misunderstanding or a deliberate feature.
|
||||
There is a mailing list,
|
||||
bug-guile@gnu.org,
|
||||
for reporting Guile bugs and fixes.
|
||||
But before reporting something as a bug,
|
||||
please try to be sure that it really is a bug,
|
||||
not a misunderstanding or a deliberate feature.
|
||||
We ask you to read the section ``Reporting Bugs'' in the Guile reference
|
||||
manual (or Info system) for hints on how and when to report bugs. Also,
|
||||
include the version number of the Guile you are running in every bug
|
||||
report that you send in. Bugs tend actually to be fixed if they can be
|
||||
isolated, so it is in your interest to report them in such a way that
|
||||
they can be easily reproduced.
|
||||
|
||||
manual (or Info system) for hints on how and when to report bugs.
|
||||
Also, include the version number of the Guile you are running in every bug
|
||||
report that you send in.
|
||||
Bugs tend actually to get fixed if they can be isolated,
|
||||
so it is in your interest to report them in such a way that they can be
|
||||
easily reproduced.
|
||||
.
|
||||
.SH COPYING
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
Copyright (C) 2010, 2011 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of this
|
||||
document provided the copyright notice and this permission notice are
|
||||
preserved on all copies.
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
document under the conditions for verbatim copying, provided that the
|
||||
entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
document under the conditions for verbatim copying,
|
||||
provided that the entire resulting derived work is distributed under the
|
||||
terms of a permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this
|
||||
document into another language, under the above conditions for modified
|
||||
versions, except that this permission notice may be stated in a
|
||||
document into another language,
|
||||
under the above conditions for modified versions,
|
||||
except that this permission notice may be stated in a
|
||||
translation approved by the Free Software Foundation.
|
||||
|
||||
.
|
||||
.SH AUTHORS
|
||||
Robert Merkel <rgmerk@mira.net> wrote this manpage.
|
||||
Rob Browning <rlb@cs.utexas.edu> has added to it.
|
||||
|
||||
.B guile
|
||||
is GNU software. Guile is originally based on Aubrey Jaffer's
|
||||
SCM interpreter, and is the work of many individuals.
|
||||
is GNU software.
|
||||
Guile is originally based on Aubrey Jaffer's SCM interpreter,
|
||||
and is the work of many individuals.
|
||||
|
|
|
@ -111,8 +111,6 @@ noinst_DATA = $(PICTURES)
|
|||
|
||||
EXTRA_DIST = ChangeLog-2008 $(PICTURES)
|
||||
|
||||
include $(top_srcdir)/am/pre-inst-guile
|
||||
|
||||
# Automated snarfing
|
||||
|
||||
autoconf.texi: autoconf-macros.texi
|
||||
|
@ -129,7 +127,8 @@ snarf_doc = standard-library
|
|||
$(snarf_doc).am: $(snarf_doc).scm
|
||||
GUILE_AUTO_COMPILE=0 ; \
|
||||
variable="`echo $(snarf_doc) | tr - _`_scm_files" ; \
|
||||
"$(preinstguile)" -l "$(srcdir)/$(snarf_doc).scm" -c " \
|
||||
"$(top_builddir_absolute)/meta/guile" -l "$(srcdir)/$(snarf_doc).scm" \
|
||||
-c " \
|
||||
(format #t \"# Automatically generated, do not edit.~%\") \
|
||||
(format #t \"$$variable = \") \
|
||||
(for-each (lambda (m) \
|
||||
|
@ -143,7 +142,7 @@ include standard-library.am
|
|||
|
||||
$(snarf_doc).texi: $(standard_library_scm_files)
|
||||
GUILE_AUTO_COMPILE=0 \
|
||||
"$(preinstguile)" "$(srcdir)/make-texinfo.scm" \
|
||||
"$(top_builddir_absolute)/meta/guile" "$(srcdir)/make-texinfo.scm" \
|
||||
"$(abs_srcdir)/$(snarf_doc).scm" > "$@.tmp"
|
||||
mv "$@.tmp" "$@"
|
||||
|
||||
|
|
|
@ -959,6 +959,18 @@ Return @var{n} raised to the integer exponent
|
|||
@end lisp
|
||||
@end deffn
|
||||
|
||||
@deftypefn {Scheme Procedure} {} exact-integer-sqrt @var{k}
|
||||
@deftypefnx {C Function} void scm_exact_integer_sqrt (SCM @var{k}, SCM *@var{s}, SCM *@var{r})
|
||||
Return two exact non-negative integers @var{s} and @var{r}
|
||||
such that @math{@var{k} = @var{s}^2 + @var{r}} and
|
||||
@math{@var{s}^2 <= @var{k} < (@var{s} + 1)^2}.
|
||||
An error is raised if @var{k} is not an exact non-negative integer.
|
||||
|
||||
@lisp
|
||||
(exact-integer-sqrt 10) @result{} 3 and 1
|
||||
@end lisp
|
||||
@end deftypefn
|
||||
|
||||
@node Comparison
|
||||
@subsubsection Comparison Predicates
|
||||
@rnindex zero?
|
||||
|
@ -1308,7 +1320,7 @@ both @var{q} and @var{r}, and is more efficient than computing each
|
|||
separately. Note that @var{r}, if non-zero, will have the same sign
|
||||
as @var{y}.
|
||||
|
||||
When @var{x} and @var{y} are exact integers, @code{floor-remainder} is
|
||||
When @var{x} and @var{y} are integers, @code{floor-remainder} is
|
||||
equivalent to the R5RS integer-only operator @code{modulo}.
|
||||
|
||||
@lisp
|
||||
|
@ -1365,7 +1377,7 @@ both @var{q} and @var{r}, and is more efficient than computing each
|
|||
separately. Note that @var{r}, if non-zero, will have the same sign
|
||||
as @var{x}.
|
||||
|
||||
When @var{x} and @var{y} are exact integers, these operators are
|
||||
When @var{x} and @var{y} are integers, these operators are
|
||||
equivalent to the R5RS integer-only operators @code{quotient} and
|
||||
@code{remainder}.
|
||||
|
||||
|
@ -4171,8 +4183,7 @@ using @code{scm_dynwind_free} inside an appropriate dynwind context,
|
|||
@deftypefn {C Function} SCM scm_from_locale_string (const char *str)
|
||||
@deftypefnx {C Function} SCM scm_from_locale_stringn (const char *str, size_t len)
|
||||
Creates a new Scheme string that has the same contents as @var{str} when
|
||||
interpreted in the locale character encoding of the
|
||||
@code{current-input-port}.
|
||||
interpreted in the character encoding of the current locale.
|
||||
|
||||
For @code{scm_from_locale_string}, @var{str} must be null-terminated.
|
||||
|
||||
|
@ -4201,9 +4212,9 @@ can then use @var{str} directly as its internal representation.
|
|||
|
||||
@deftypefn {C Function} {char *} scm_to_locale_string (SCM str)
|
||||
@deftypefnx {C Function} {char *} scm_to_locale_stringn (SCM str, size_t *lenp)
|
||||
Returns a C string with the same contents as @var{str} in the locale
|
||||
encoding of the @code{current-output-port}. The C string must be freed
|
||||
with @code{free} eventually, maybe by using @code{scm_dynwind_free},
|
||||
Returns a C string with the same contents as @var{str} in the character
|
||||
encoding of the current locale. The C string must be freed with
|
||||
@code{free} eventually, maybe by using @code{scm_dynwind_free},
|
||||
@xref{Dynamic Wind}.
|
||||
|
||||
For @code{scm_to_locale_string}, the returned string is
|
||||
|
@ -4217,13 +4228,14 @@ returned string will not be null-terminated in this case. If
|
|||
@var{lenp} is @code{NULL}, @code{scm_to_locale_stringn} behaves like
|
||||
@code{scm_to_locale_string}.
|
||||
|
||||
If a character in @var{str} cannot be represented in the locale encoding
|
||||
of the current output port, the port conversion strategy of the current
|
||||
output port will determine the result, @xref{Ports}. If output port's
|
||||
conversion strategy is @code{error}, an error will be raised. If it is
|
||||
@code{substitute}, a replacement character, such as a question mark, will
|
||||
be inserted in its place. If it is @code{escape}, a hex escape will be
|
||||
inserted in its place.
|
||||
If a character in @var{str} cannot be represented in the character
|
||||
encoding of the current locale, the default port conversion strategy is
|
||||
used. @xref{Ports}, for more on conversion strategies.
|
||||
|
||||
If the conversion strategy is @code{error}, an error will be raised. If
|
||||
it is @code{substitute}, a replacement character, such as a question
|
||||
mark, will be inserted in its place. If it is @code{escape}, a hex
|
||||
escape will be inserted in its place.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {C Function} size_t scm_to_locale_stringbuf (SCM str, char *buf, size_t max_len)
|
||||
|
|
|
@ -426,7 +426,9 @@ Modify the print options.
|
|||
@node Fly Evaluation
|
||||
@subsection Procedures for On the Fly Evaluation
|
||||
|
||||
@xref{Environments}.
|
||||
Scheme has the lovely property that its expressions may be represented
|
||||
as data. The @code{eval} procedure takes a Scheme datum and evaluates
|
||||
it as code.
|
||||
|
||||
@rnindex eval
|
||||
@c ARGFIXME environment/environment specifier
|
||||
|
@ -451,19 +453,46 @@ return the environment in which the implementation would
|
|||
evaluate expressions dynamically typed by the user.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} eval-string string [module]
|
||||
@deffnx {C Function} scm_eval_string (string)
|
||||
@xref{Environments}, for other environments.
|
||||
|
||||
One does not always receive code as Scheme data, of course, and this is
|
||||
especially the case for Guile's other language implementations
|
||||
(@pxref{Other Languages}). For the case in which all you have is a
|
||||
string, we have @code{eval-string}. There is a legacy version of this
|
||||
procedure in the default environment, but you really want the one from
|
||||
@code{(ice-9 eval-string)}, so load it up:
|
||||
|
||||
@example
|
||||
(use-modules (ice-9 eval-string))
|
||||
@end example
|
||||
|
||||
@deffn {Scheme Procedure} eval-string string [module=#f] [file=#f] [line=#f] [column=#f] [lang=(current-language)] [compile?=#f]
|
||||
Parse @var{string} according to the current language, normally Scheme.
|
||||
Evaluate or compile the expressions it contains, in order, returning the
|
||||
last expression.
|
||||
|
||||
If the @var{module} keyword argument is set, save a module excursion
|
||||
(@pxref{Module System Reflection}) and set the current module to
|
||||
@var{module} before evaluation.
|
||||
|
||||
The @var{file}, @var{line}, and @var{column} keyword arguments can be
|
||||
used to indicate that the source string begins at a particular source
|
||||
location.
|
||||
|
||||
Finally, @var{lang} is a language, defaulting to the current language,
|
||||
and the expression is compiled if @var{compile?} is true or there is no
|
||||
evaluator for the given language.
|
||||
@end deffn
|
||||
|
||||
@deffn {C Function} scm_eval_string (string)
|
||||
@deffnx {C Function} scm_eval_string_in_module (string, module)
|
||||
Evaluate @var{string} as the text representation of a Scheme form or
|
||||
forms, and return whatever value they produce. Evaluation takes place
|
||||
in the given module, or in the current module when no module is given.
|
||||
While the code is evaluated, the given module is made the current one.
|
||||
The current module is restored when this procedure returns.
|
||||
These C bindings call @code{eval-string} from @code{(ice-9
|
||||
eval-string)}, evaluating within @var{module} or the current module.
|
||||
@end deffn
|
||||
|
||||
@deftypefn {C Function} SCM scm_c_eval_string (const char *string)
|
||||
@code{scm_eval_string}, but taking a C string instead of an
|
||||
@code{SCM}.
|
||||
@code{scm_eval_string}, but taking a C string in locale encoding instead
|
||||
of an @code{SCM}.
|
||||
@end deftypefn
|
||||
|
||||
@deffn {Scheme Procedure} apply proc arg1 @dots{} argN arglst
|
||||
|
@ -493,9 +522,17 @@ then there's no @var{arg1}@dots{}@var{argN} and @var{arg} is the
|
|||
@deffnx {C Function} scm_call_2 (proc, arg1, arg2)
|
||||
@deffnx {C Function} scm_call_3 (proc, arg1, arg2, arg3)
|
||||
@deffnx {C Function} scm_call_4 (proc, arg1, arg2, arg3, arg4)
|
||||
@deffnx {C Function} scm_call_5 (proc, arg1, arg2, arg3, arg4, arg5)
|
||||
@deffnx {C Function} scm_call_6 (proc, arg1, arg2, arg3, arg4, arg5, arg6)
|
||||
Call @var{proc} with the given arguments.
|
||||
@end deffn
|
||||
|
||||
@deffn {C Function} scm_call_n (proc, argv, nargs)
|
||||
Call @var{proc} with the array of arguments @var{argv}, as a
|
||||
@code{SCM*}. The length of the arguments should be passed in
|
||||
@var{nargs}, as a @code{size_t}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} apply:nconc2last lst
|
||||
@deffnx {C Function} scm_nconc2last (lst)
|
||||
@var{lst} should be a list (@var{arg1} @dots{} @var{argN}
|
||||
|
|
|
@ -79,6 +79,12 @@ Normally, @var{library} is just the name of some shared library file
|
|||
that will be searched for in the places where shared libraries usually
|
||||
reside, such as in @file{/usr/lib} and @file{/usr/local/lib}.
|
||||
|
||||
@var{library} should not contain an extension such as @code{.so}. The
|
||||
correct file name extension for the host operating system is provided
|
||||
automatically, according to libltdl's rules (@pxref{Libltdl interface,
|
||||
lt_dlopenext, @code{lt_dlopenext}, libtool, Shared Library Support for
|
||||
GNU}).
|
||||
|
||||
When @var{library} is omitted, a @dfn{global symbol handle} is returned. This
|
||||
handle provides access to the symbols available to the program at run-time,
|
||||
including those exported by the program itself and the shared libraries already
|
||||
|
@ -196,12 +202,13 @@ In that case, you would statically link your program with the desired
|
|||
library, and register its init function right after Guile has been
|
||||
initialized.
|
||||
|
||||
LIB should be a string denoting a shared library without any file type
|
||||
suffix such as ".so". The suffix is provided automatically. It
|
||||
As for @code{dynamic-link}, @var{lib} should not contain any suffix such
|
||||
as @code{.so} (@pxref{Foreign Libraries, dynamic-link}). It
|
||||
should also not contain any directory components. Libraries that
|
||||
implement Guile Extensions should be put into the normal locations for
|
||||
shared libraries. We recommend to use the naming convention
|
||||
libguile-bla-blum for a extension related to a module `(bla blum)'.
|
||||
@file{libguile-bla-blum} for a extension related to a module @code{(bla
|
||||
blum)}.
|
||||
|
||||
The normal way for a extension to be used is to write a small Scheme
|
||||
file that defines a module, and to load the extension into this
|
||||
|
@ -360,8 +367,8 @@ When loaded with @code{(use-modules (foo bar))}, the
|
|||
@code{load-extension} call looks for the @file{foobar-c-code.so} (etc)
|
||||
object file in Guile's @code{extensiondir}, which is usually a
|
||||
subdirectory of the @code{libdir}. For example, if your libdir is
|
||||
@file{/usr/lib}, the @code{extensiondir} for the Guile 2.0.@var{x}
|
||||
series will be @file{/usr/lib/guile/2.0/}.
|
||||
@file{/usr/lib}, the @code{extensiondir} for the Guile @value{EFFECTIVE-VERSION}.@var{x}
|
||||
series will be @file{/usr/lib/guile/@value{EFFECTIVE-VERSION}/}.
|
||||
|
||||
The extension path includes the major and minor version of Guile (the
|
||||
``effective version''), because Guile guarantees compatibility within a
|
||||
|
@ -399,7 +406,7 @@ with the following in a @file{Makefile}, using @command{sed}
|
|||
|
||||
@example
|
||||
foo.scm: foo.scm.in
|
||||
sed 's|XXextensiondirXX|$(libdir)/guile/2.0|' <foo.scm.in >foo.scm
|
||||
sed 's|XXextensiondirXX|$(libdir)/guile/@value{EFFECTIVE-VERSION}|' <foo.scm.in >foo.scm
|
||||
@end example
|
||||
|
||||
The actual pattern @code{XXextensiondirXX} is arbitrary, it's only something
|
||||
|
@ -561,6 +568,20 @@ A foreign pointer whose value is 0.
|
|||
Return @code{#t} if @var{pointer} is the null pointer, @code{#f} otherwise.
|
||||
@end deffn
|
||||
|
||||
For the purpose of passing SCM values directly to foreign functions, and
|
||||
allowing them to return SCM values, Guile also supports some unsafe
|
||||
casting operators.
|
||||
|
||||
@deffn {Scheme Procedure} scm->pointer scm
|
||||
Return a foreign pointer object with the @code{object-address}
|
||||
of @var{scm}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} pointer->scm pointer
|
||||
Unsafely cast @var{pointer} to a Scheme object.
|
||||
Cross your fingers!
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Void Pointers and Byte Access
|
||||
@subsubsection Void Pointers and Byte Access
|
||||
|
@ -605,20 +626,22 @@ Assuming @var{pointer} points to a memory region that holds a pointer,
|
|||
return this pointer.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} string->pointer string
|
||||
@deffn {Scheme Procedure} string->pointer string [encoding]
|
||||
Return a foreign pointer to a nul-terminated copy of @var{string} in the
|
||||
current locale encoding. The C string is freed when the returned
|
||||
foreign pointer becomes unreachable.
|
||||
given @var{encoding}, defaulting to the current locale encoding. The C
|
||||
string is freed when the returned foreign pointer becomes unreachable.
|
||||
|
||||
This is the Scheme equivalent of @code{scm_to_locale_string}.
|
||||
This is the Scheme equivalent of @code{scm_to_stringn}.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} pointer->string pointer
|
||||
Return the string representing the C nul-terminated string
|
||||
pointed to by @var{pointer}. The C string is assumed to be
|
||||
in the current locale encoding.
|
||||
@deffn {Scheme Procedure} pointer->string pointer [length] [encoding]
|
||||
Return the string representing the C string pointed to by @var{pointer}.
|
||||
If @var{length} is omitted or @code{-1}, the string is assumed to be
|
||||
nul-terminated. Otherwise @var{length} is the number of bytes in memory
|
||||
pointed to by @var{pointer}. The C string is assumed to be in the given
|
||||
@var{encoding}, defaulting to the current locale encoding.
|
||||
|
||||
This is the Scheme equivalent of @code{scm_from_locale_string}.
|
||||
This is the Scheme equivalent of @code{scm_from_stringn}.
|
||||
@end deffn
|
||||
|
||||
@cindex wrapped pointer types
|
||||
|
|
|
@ -949,9 +949,8 @@ used only during port creation are not retained.
|
|||
|
||||
@deffn {Scheme Procedure} port-filename port
|
||||
@deffnx {C Function} scm_port_filename (port)
|
||||
Return the filename associated with @var{port}. This function returns
|
||||
the strings "standard input", "standard output" and "standard error"
|
||||
when called on the current input, output and error ports respectively.
|
||||
Return the filename associated with @var{port}, or @code{#f} if no
|
||||
filename is associated with the port.
|
||||
|
||||
@var{port} must be open, @code{port-filename} cannot be used once the
|
||||
port is closed.
|
||||
|
@ -1156,8 +1155,7 @@ string I/O, that complement or refine Guile's historical port API
|
|||
presented above (@pxref{Input and Output}).
|
||||
|
||||
@c FIXME: Update description when implemented.
|
||||
@emph{Note}: The implementation of this R6RS API is currently far from
|
||||
complete, notably due to the lack of support for Unicode I/O and strings.
|
||||
@emph{Note}: The implementation of this R6RS API is not complete yet.
|
||||
|
||||
@menu
|
||||
* R6RS End-of-File:: The end-of-file object.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -935,6 +935,62 @@ value of @code{scm_c_call_with_current_module} is the return value of
|
|||
@var{func}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn SCM scm_public_variable (SCM @var{module_name}, SCM @var{name})
|
||||
@deftypefnx SCM scm_c_public_variable (const char * @var{module_name}, const char * @var{name})
|
||||
Find a the variable bound to the symbol @var{name} in the public
|
||||
interface of the module named @var{module_name}.
|
||||
|
||||
@var{module_name} should be a list of symbols, when represented as a
|
||||
Scheme object, or a space-separated string, in the @code{const char *}
|
||||
case. See @code{scm_c_define_module} below, for more examples.
|
||||
|
||||
Signals an error if no module was found with the given name. If
|
||||
@var{name} is not bound in the module, just returns @code{#f}.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn SCM scm_private_variable (SCM @var{module_name}, SCM @var{name})
|
||||
@deftypefnx SCM scm_c_private_variable (const char * @var{module_name}, const char * @var{name})
|
||||
Like @code{scm_public_variable}, but looks in the internals of the
|
||||
module named @var{module_name} instead of the public interface.
|
||||
Logically, these procedures should only be called on modules you write.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn SCM scm_public_lookup (SCM @var{module_name}, SCM @var{name})
|
||||
@deftypefnx SCM scm_c_public_lookup (const char * @var{module_name}, const char * @var{name})
|
||||
@deftypefnx SCM scm_private_lookup (SCM @var{module_name}, SCM @var{name})
|
||||
@deftypefnx SCM scm_c_private_lookup (const char * @var{module_name}, const char * @var{name})
|
||||
Like @code{scm_public_variable} or @code{scm_private_variable}, but if
|
||||
the @var{name} is not bound in the module, signals an error. Returns a
|
||||
variable, always.
|
||||
|
||||
@example
|
||||
SCM my_eval_string (SCM str)
|
||||
@{
|
||||
static SCM eval_string_var = SCM_BOOL_F;
|
||||
|
||||
if (scm_is_false (eval_string_var))
|
||||
eval_string_var =
|
||||
scm_c_public_lookup ("ice-9 eval-string", "eval-string");
|
||||
|
||||
return scm_call_1 (scm_variable_ref (eval_string_var), str);
|
||||
@}
|
||||
@end example
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn SCM scm_public_ref (SCM @var{module_name}, SCM @var{name})
|
||||
@deftypefnx SCM scm_c_public_ref (const char * @var{module_name}, const char * @var{name})
|
||||
@deftypefnx SCM scm_private_ref (SCM @var{module_name}, SCM @var{name})
|
||||
@deftypefnx SCM scm_c_private_ref (const char * @var{module_name}, const char * @var{name})
|
||||
Like @code{scm_public_lookup} or @code{scm_private_lookup}, but
|
||||
additionally dereferences the variable. If the variable object is
|
||||
unbound, signals an error. Returns the value bound to @var{name} in
|
||||
@var{module}.
|
||||
@end deftypefn
|
||||
|
||||
In addition, there are a number of other lookup-related procedures. We
|
||||
suggest that you use the @code{scm_public_} and @code{scm_private_}
|
||||
family of procedures instead, if possible.
|
||||
|
||||
@deftypefn {C Procedure} SCM scm_c_lookup (const char *@var{name})
|
||||
Return the variable bound to the symbol indicated by @var{name} in the
|
||||
current module. If there is no such binding or the symbol is not
|
||||
|
@ -951,6 +1007,13 @@ Like @code{scm_c_lookup} and @code{scm_lookup}, but the specified
|
|||
module is used instead of the current one.
|
||||
@end deftypefn
|
||||
|
||||
@deftypefn {C Procedure} SCM scm_module_variable (SCM @var{module}, SCM @var{name})
|
||||
Like @code{scm_module_lookup}, but if the binding does not exist, just
|
||||
returns @code{#f} instead of raising an error.
|
||||
@end deftypefn
|
||||
|
||||
To define a value, use @code{scm_define}:
|
||||
|
||||
@deftypefn {C Procedure} SCM scm_c_define (const char *@var{name}, SCM @var{val})
|
||||
Bind the symbol indicated by @var{name} to a variable in the current
|
||||
module and set that variable to @var{val}. When @var{name} is already
|
||||
|
|
|
@ -171,13 +171,14 @@ guileversion, libguileinterface, buildstamp
|
|||
@end table
|
||||
|
||||
Values are all strings. The value for @code{LIBS} is typically found
|
||||
also as a part of "guile-config link" output. The value for
|
||||
also as a part of @code{pkg-config --libs
|
||||
guile-@value{EFFECTIVE-VERSION}} output. The value for
|
||||
@code{guileversion} has form X.Y.Z, and should be the same as returned
|
||||
by @code{(version)}. The value for @code{libguileinterface} is
|
||||
libtool compatible and has form CURRENT:REVISION:AGE
|
||||
(@pxref{Versioning,, Library interface versions, libtool, GNU
|
||||
Libtool}). The value for @code{buildstamp} is the output of the
|
||||
command @samp{date -u +'%Y-%m-%d %T'} (UTC).
|
||||
by @code{(version)}. The value for @code{libguileinterface} is libtool
|
||||
compatible and has form CURRENT:REVISION:AGE (@pxref{Versioning,,
|
||||
Library interface versions, libtool, GNU Libtool}). The value for
|
||||
@code{buildstamp} is the output of the command @samp{date -u +'%Y-%m-%d
|
||||
%T'} (UTC).
|
||||
|
||||
In the source, @code{%guile-build-info} is initialized from
|
||||
libguile/libpath.h, which is completely generated, so deleting this file
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
|||
* Higher-Order Functions:: Function that take or return functions.
|
||||
* Procedure Properties:: Procedure properties and meta-information.
|
||||
* Procedures with Setters:: Procedures with setters.
|
||||
* Inlinable Procedures:: Procedures that can be inlined.
|
||||
@end menu
|
||||
|
||||
|
||||
|
@ -797,6 +798,32 @@ Return the setter of @var{proc}, which must be either a procedure with
|
|||
setter or an operator struct.
|
||||
@end deffn
|
||||
|
||||
@node Inlinable Procedures
|
||||
@subsection Inlinable Procedures
|
||||
|
||||
You can define an @dfn{inlinable procedure} by using
|
||||
@code{define-inlinable} instead of @code{define}. An inlinable
|
||||
procedure behaves the same as a regular procedure, but direct calls will
|
||||
result in the procedure body being inlined into the caller.
|
||||
|
||||
Procedures defined with @code{define-inlinable} are @emph{always}
|
||||
inlined, at all direct call sites. This eliminates function call
|
||||
overhead at the expense of an increase in code size. Additionally, the
|
||||
caller will not transparently use the new definition if the inline
|
||||
procedure is redefined. It is not possible to trace an inlined
|
||||
procedures or install a breakpoint in it (@pxref{Traps}). For these
|
||||
reasons, you should not make a procedure inlinable unless it
|
||||
demonstrably improves performance in a crucial way.
|
||||
|
||||
In general, only small procedures should be considered for inlining, as
|
||||
making large procedures inlinable will probably result in an increase in
|
||||
code size. Additionally, the elimination of the call overhead rarely
|
||||
matters for for large procedures.
|
||||
|
||||
@deffn {Scheme Syntax} define-inlinable (name parameter ...) body ...
|
||||
Define @var{name} as a procedure with parameters @var{parameter}s and
|
||||
body @var{body}.
|
||||
@end deffn
|
||||
|
||||
@c Local Variables:
|
||||
@c TeX-master: "guile.texi"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2009, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -97,25 +97,25 @@ to instantiate macros at top-level.
|
|||
|
||||
We now include two examples, one simple and one complicated.
|
||||
|
||||
The first example is for a package that uses libguile, and thus needs to know
|
||||
how to compile and link against it. So we use @code{GUILE_FLAGS} to set the
|
||||
vars @code{GUILE_CFLAGS} and @code{GUILE_LDFLAGS}, which are automatically
|
||||
substituted in the Makefile.
|
||||
The first example is for a package that uses libguile, and thus needs to
|
||||
know how to compile and link against it. So we use
|
||||
@code{PKG_CHECK_MODULES} to set the vars @code{GUILE_CFLAGS} and
|
||||
@code{GUILE_LIBS}, which are automatically substituted in the Makefile.
|
||||
|
||||
@example
|
||||
In configure.ac:
|
||||
|
||||
GUILE_FLAGS
|
||||
PKG_CHECK_MODULES([GUILE], [guile-@value{EFFECTIVE-VERSION}])
|
||||
|
||||
In Makefile.in:
|
||||
|
||||
GUILE_CFLAGS = @@GUILE_CFLAGS@@
|
||||
GUILE_LDFLAGS = @@GUILE_LDFLAGS@@
|
||||
GUILE_LIBS = @@GUILE_LIBS@@
|
||||
|
||||
myprog.o: myprog.c
|
||||
$(CC) -o $@ $(GUILE_CFLAGS) $<
|
||||
myprog: myprog.o
|
||||
$(CC) -o $@ $< $(GUILE_LDFLAGS)
|
||||
$(CC) -o $@ $< $(GUILE_LIBS)
|
||||
@end example
|
||||
|
||||
The second example is for a package of Guile Scheme modules that uses an
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 2008, 2010
|
||||
@c Copyright (C) 2008, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -214,15 +214,15 @@ user-space threading was removed in favor of POSIX pre-emptive
|
|||
threads, providing true multiprocessing. Gettext support was added,
|
||||
and Guile's C API was cleaned up and orthogonalized in a massive way.
|
||||
|
||||
@item 2.0 --- April 2010
|
||||
@item 2.0 --- 16 February 2010
|
||||
A virtual machine was added to Guile, along with the associated compiler
|
||||
and toolchain. Support for internationalization was finally
|
||||
reimplemented, in terms of unicode, locales, and libunistring. Running
|
||||
Guile instances became controllable and debuggable from within Emacs,
|
||||
via GDS and Geiser. Guile caught up to features found in a number of
|
||||
other Schemes: SRFI-18 threads, including thread cancellation,
|
||||
module-hygienic macros, a profiler, tracer, and debugger, SSAX XML
|
||||
integration, bytevectors, module versions, and partial support for R6RS.
|
||||
via Geiser. Guile caught up to features found in a number of other
|
||||
Schemes: SRFI-18 threads, module-hygienic macros, a profiler, tracer,
|
||||
and debugger, SSAX XML integration, bytevectors, a dynamic FFI,
|
||||
delimited continuations, module versions, and partial support for R6RS.
|
||||
@end table
|
||||
|
||||
@node Status
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -64,7 +64,7 @@ Consider the following file @file{bessel.c}.
|
|||
SCM
|
||||
j0_wrapper (SCM x)
|
||||
@{
|
||||
return scm_make_real (j0 (scm_num2dbl (x, "j0")));
|
||||
return scm_from_double (j0 (scm_to_double (x)));
|
||||
@}
|
||||
|
||||
void
|
||||
|
@ -78,7 +78,8 @@ This C source file needs to be compiled into a shared library. Here is
|
|||
how to do it on GNU/Linux:
|
||||
|
||||
@smallexample
|
||||
gcc -shared -o libguile-bessel.so -fPIC bessel.c
|
||||
gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` \
|
||||
-shared -o libguile-bessel.so -fPIC bessel.c
|
||||
@end smallexample
|
||||
|
||||
For creating shared libraries portably, we recommend the use of GNU
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -16,16 +16,24 @@ head of any C source file that uses identifiers described in this
|
|||
manual. Once you've compiled your source files, you need to link them
|
||||
against the Guile object code library, @code{libguile}.
|
||||
|
||||
On most systems, you should not need to tell the compiler and linker
|
||||
explicitly where they can find @file{libguile.h} and @file{libguile}.
|
||||
When Guile has been installed in a peculiar way, or when you are on a
|
||||
peculiar system, things might not be so easy and you might need to pass
|
||||
additional @code{-I} or @code{-L} options to the compiler. Guile
|
||||
provides the utility program @code{guile-config} to help you find the
|
||||
right values for these options. You would typically run
|
||||
@code{guile-config} during the configuration phase of your program and
|
||||
@code{<libguile.h>} is not in the default search path for headers,
|
||||
because Guile supports parallel installation of multiple versions of
|
||||
Guile, with each version's headers under their own directories. This is
|
||||
to allow development against, say, both Guile 2.0 and 2.2.
|
||||
|
||||
To compile code that includes @code{<libguile.h>}, or links to
|
||||
@code{libguile}, you need to select the effective version you are
|
||||
interested in, and then ask @code{pkg-config} for the compilation flags
|
||||
or linking instructions. For effective version
|
||||
@value{EFFECTIVE-VERSION}, for example, you would invoke
|
||||
@code{pkg-config --cflags --libs guile-@value{EFFECTIVE-VERSION}} to get
|
||||
the compilation and linking flags necessary to link to version
|
||||
@value{EFFECTIVE-VERSION} of Guile. You would typically run
|
||||
@code{pkg-config} during the configuration phase of your program and
|
||||
use the obtained information in the Makefile.
|
||||
|
||||
See the @code{pkg-config} man page, for more information.
|
||||
|
||||
@menu
|
||||
* Guile Initialization Functions:: What to call first.
|
||||
* A Sample Guile Main Program:: Sources and makefiles.
|
||||
|
@ -98,17 +106,17 @@ ready, it invokes @code{inner_main}, which calls @code{scm_shell} to
|
|||
process the command-line arguments in the usual way.
|
||||
|
||||
Here is a Makefile which you can use to compile the above program. It
|
||||
uses @code{guile-config} to learn about the necessary compiler and
|
||||
uses @code{pkg-config} to learn about the necessary compiler and
|
||||
linker flags.
|
||||
@example
|
||||
# Use GCC, if you have it installed.
|
||||
CC=gcc
|
||||
|
||||
# Tell the C compiler where to find <libguile.h>
|
||||
CFLAGS=`guile-config compile`
|
||||
CFLAGS=`pkg-config --cflags guile-@value{EFFECTIVE-VERSION}`
|
||||
|
||||
# Tell the linker what libraries to use and where to find them.
|
||||
LIBS=`guile-config link`
|
||||
LIBS=`pkg-config --libs guile-@value{EFFECTIVE-VERSION}`
|
||||
|
||||
simple-guile: simple-guile.o
|
||||
$@{CC@} simple-guile.o $@{LIBS@} -o simple-guile
|
||||
|
@ -120,13 +128,11 @@ simple-guile.o: simple-guile.c
|
|||
If you are using the GNU Autoconf package to make your application more
|
||||
portable, Autoconf will settle many of the details in the Makefile above
|
||||
automatically, making it much simpler and more portable; we recommend
|
||||
using Autoconf with Guile. Guile also provides the @code{GUILE_FLAGS}
|
||||
macro for autoconf that performs all necessary checks. Here is a
|
||||
@file{configure.in} file for @code{simple-guile} that uses this macro.
|
||||
Autoconf can use this file as a template to generate a @code{configure}
|
||||
script. In order for Autoconf to find the @code{GUILE_FLAGS} macro, you
|
||||
will need to run @code{aclocal} first (@pxref{Invoking aclocal,,,
|
||||
automake, GNU Automake}).
|
||||
using Autoconf with Guile. Here is a @file{configure.ac} file for
|
||||
@code{simple-guile} that uses the standard @code{PKG_CHECK_MODULES}
|
||||
macro to check for Guile. Autoconf will process this file into a
|
||||
@code{configure} script. We recommend invoking Autoconf via the
|
||||
@code{autoreconf} utility.
|
||||
|
||||
@example
|
||||
AC_INIT(simple-guile.c)
|
||||
|
@ -135,19 +141,21 @@ AC_INIT(simple-guile.c)
|
|||
AC_PROG_CC
|
||||
|
||||
# Check for Guile
|
||||
GUILE_FLAGS
|
||||
PKG_CHECK_MODULES([GUILE], [guile-@value{EFFECTIVE-VERSION}])
|
||||
|
||||
# Generate a Makefile, based on the results.
|
||||
AC_OUTPUT(Makefile)
|
||||
@end example
|
||||
|
||||
Run @code{autoreconf -vif} to generate @code{configure}.
|
||||
|
||||
Here is a @code{Makefile.in} template, from which the @code{configure}
|
||||
script produces a Makefile customized for the host system:
|
||||
@example
|
||||
# The configure script fills in these values.
|
||||
CC=@@CC@@
|
||||
CFLAGS=@@GUILE_CFLAGS@@
|
||||
LIBS=@@GUILE_LDFLAGS@@
|
||||
LIBS=@@GUILE_LIBS@@
|
||||
|
||||
simple-guile: simple-guile.o
|
||||
$@{CC@} simple-guile.o $@{LIBS@} -o simple-guile
|
||||
|
@ -156,23 +164,28 @@ simple-guile.o: simple-guile.c
|
|||
@end example
|
||||
|
||||
The developer should use Autoconf to generate the @file{configure}
|
||||
script from the @file{configure.in} template, and distribute
|
||||
script from the @file{configure.ac} template, and distribute
|
||||
@file{configure} with the application. Here's how a user might go about
|
||||
building the application:
|
||||
|
||||
@example
|
||||
$ ls
|
||||
Makefile.in configure* configure.in simple-guile.c
|
||||
Makefile.in configure* configure.ac simple-guile.c
|
||||
$ ./configure
|
||||
creating cache ./config.cache
|
||||
checking for gcc... (cached) gcc
|
||||
checking whether the C compiler (gcc ) works... yes
|
||||
checking whether the C compiler (gcc ) is a cross-compiler... no
|
||||
checking whether we are using GNU C... (cached) yes
|
||||
checking whether gcc accepts -g... (cached) yes
|
||||
checking for Guile... yes
|
||||
creating ./config.status
|
||||
creating Makefile
|
||||
checking for gcc... ccache gcc
|
||||
checking whether the C compiler works... yes
|
||||
checking for C compiler default output file name... a.out
|
||||
checking for suffix of executables...
|
||||
checking whether we are cross compiling... no
|
||||
checking for suffix of object files... o
|
||||
checking whether we are using the GNU C compiler... yes
|
||||
checking whether ccache gcc accepts -g... yes
|
||||
checking for ccache gcc option to accept ISO C89... none needed
|
||||
checking for pkg-config... /usr/bin/pkg-config
|
||||
checking pkg-config is at least version 0.9.0... yes
|
||||
checking for GUILE... yes
|
||||
configure: creating ./config.status
|
||||
config.status: creating Makefile
|
||||
$ make
|
||||
[...]
|
||||
$ ./simple-guile
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -686,9 +686,9 @@ Here is a sample build and interaction with the code from the
|
|||
|
||||
@example
|
||||
zwingli:example-smob$ make CC=gcc
|
||||
gcc `guile-config compile` -c image-type.c -o image-type.o
|
||||
gcc `guile-config compile` -c myguile.c -o myguile.o
|
||||
gcc image-type.o myguile.o `guile-config link` -o myguile
|
||||
gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` -c image-type.c -o image-type.o
|
||||
gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` -c myguile.c -o myguile.o
|
||||
gcc image-type.o myguile.o `pkg-config --libs guile-@value{EFFECTIVE-VERSION}` -o myguile
|
||||
zwingli:example-smob$ ./myguile
|
||||
guile> make-image
|
||||
#<primitive-procedure make-image>
|
||||
|
|
|
@ -38,9 +38,11 @@ does not restore it. This is a bug.
|
|||
|
||||
@item
|
||||
R6RS unicode escapes within strings are disabled by default, because
|
||||
they conflict with Guile's already-existing escapes. R6RS behavior can
|
||||
be turned on via a reader option. @xref{String Syntax}, for more
|
||||
information.
|
||||
they conflict with Guile's already-existing escapes. The same is the
|
||||
case for R6RS treatment of escaped newlines in strings.
|
||||
|
||||
R6RS behavior can be turned on via a reader option. @xref{String
|
||||
Syntax}, for more information.
|
||||
|
||||
@item
|
||||
A @code{set!} to a variable transformer may only expand to an
|
||||
|
@ -51,11 +53,11 @@ expression was in definition context.
|
|||
Instead of using the algorithm detailed in chapter 10 of the R6RS,
|
||||
expansion of toplevel forms happens sequentially.
|
||||
|
||||
For example, while the expansion of the following set of recursive
|
||||
nested definitions does do the correct thing:
|
||||
For example, while the expansion of the following set of toplevel
|
||||
definitions does the correct thing:
|
||||
|
||||
@example
|
||||
(let ()
|
||||
(begin
|
||||
(define even?
|
||||
(lambda (x)
|
||||
(or (= x 0) (odd? (- x 1)))))
|
||||
|
@ -67,17 +69,16 @@ nested definitions does do the correct thing:
|
|||
@end example
|
||||
|
||||
@noindent
|
||||
The same definitions at the toplevel do not:
|
||||
The same definitions outside of the @code{begin} wrapper do not:
|
||||
|
||||
@example
|
||||
(begin
|
||||
(define even?
|
||||
(lambda (x)
|
||||
(or (= x 0) (odd? (- x 1)))))
|
||||
(define-syntax odd?
|
||||
(syntax-rules ()
|
||||
((odd? x) (not (even? x)))))
|
||||
(even? 10))
|
||||
(even? 10)
|
||||
<unnamed port>:4:18: In procedure even?:
|
||||
<unnamed port>:4:18: Wrong type to apply: #<syntax-transformer odd?>
|
||||
@end example
|
||||
|
@ -86,10 +87,10 @@ This is because when expanding the right-hand-side of @code{even?}, the
|
|||
reference to @code{odd?} is not yet marked as a syntax transformer, so
|
||||
it is assumed to be a function.
|
||||
|
||||
While it is likely that we can fix the case of toplevel forms nested in
|
||||
a @code{begin} or a @code{library} form, a fix for toplevel programs
|
||||
seems trickier to implement in a backward-compatible way. Suggestions
|
||||
and/or patches would be appreciated.
|
||||
This bug will only affect top-level programs, not code in @code{library}
|
||||
forms. Fixing it for toplevel forms seems doable, but tricky to
|
||||
implement in a backward-compatible way. Suggestions and/or patches would
|
||||
be appreciated.
|
||||
|
||||
@item
|
||||
The @code{(rnrs io ports)} module is mostly unimplemented. Work is
|
||||
|
@ -378,6 +379,7 @@ grouped below by the existing manual sections to which they correspond.
|
|||
@deffnx {Scheme Procedure} even? n
|
||||
@deffnx {Scheme Procedure} gcd x ...
|
||||
@deffnx {Scheme Procedure} lcm x ...
|
||||
@deffnx {Scheme Procedure} exact-integer-sqrt k
|
||||
@xref{Integer Operations}, for documentation.
|
||||
@end deffn
|
||||
|
||||
|
@ -524,11 +526,6 @@ This is a consequence of the requirement that
|
|||
@end lisp
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} exact-integer-sqrt k
|
||||
This procedure returns two nonnegative integer objects @code{s} and
|
||||
@code{r} such that k = s^2 + r and k < (s + 1)^2.
|
||||
@end deffn
|
||||
|
||||
@deffn {Scheme Procedure} real-valued? obj
|
||||
@deffnx {Scheme Procedure} rational-valued? obj
|
||||
@deffnx {Scheme Procedure} integer-valued? obj
|
||||
|
|
|
@ -196,6 +196,11 @@ interactive session. When executing a script with @code{-s} or
|
|||
Do not use the debugging VM engine, even when entering an interactive
|
||||
session.
|
||||
|
||||
@item -q
|
||||
Do not the local initialization file, @code{.guile}. This option only
|
||||
has an effect when running interactively; running scripts does not load
|
||||
the @code{.guile} file. @xref{Init File}.
|
||||
|
||||
@item --listen[=@var{p}]
|
||||
While this program runs, listen on a local port or a path for REPL
|
||||
clients. If @var{p} starts with a number, it is assumed to be a local
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 2006, 2010
|
||||
@c Copyright (C) 2006, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -35,6 +35,7 @@ current language is @code{scheme}, and the current module is
|
|||
support for languages other than Scheme.
|
||||
|
||||
@menu
|
||||
* Init File::
|
||||
* Readline::
|
||||
* Value History::
|
||||
* REPL Commands::
|
||||
|
@ -43,6 +44,22 @@ support for languages other than Scheme.
|
|||
@end menu
|
||||
|
||||
|
||||
@node Init File
|
||||
@subsection The Init File, @file{~/.guile}
|
||||
|
||||
@cindex .guile
|
||||
When run interactively, Guile will load a local initialization file from
|
||||
@file{~/.guile}. This file should contain Scheme expressions for
|
||||
evaluation.
|
||||
|
||||
This facility lets the user customize their interactive Guile
|
||||
environment, pulling in extra modules or parameterizing the REPL
|
||||
implementation.
|
||||
|
||||
To run Guile without loading the init file, use the @code{-q}
|
||||
command-line option.
|
||||
|
||||
|
||||
@node Readline
|
||||
@subsection Readline
|
||||
|
||||
|
@ -58,10 +75,8 @@ scheme@@(guile-user)> (activate-readline)
|
|||
@end lisp
|
||||
|
||||
It's a good idea to put these two lines (without the
|
||||
@code{scheme@@(guile-user)>} prompts) in your @file{.guile} file. Guile
|
||||
reads this file when it starts up interactively, so anything in this
|
||||
file has the same effect as if you type it in by hand at the
|
||||
@code{scheme@@(guile-user)>} prompt.
|
||||
@code{scheme@@(guile-user)>} prompts) in your @file{.guile} file.
|
||||
@xref{Init File}, for more on @file{.guile}.
|
||||
|
||||
|
||||
@node Value History
|
||||
|
@ -337,6 +352,12 @@ Show the VM registers associated with the current frame.
|
|||
@xref{Stack Layout}, for more information on VM stack frames.
|
||||
@end deffn
|
||||
|
||||
@deffn {REPL Command} width [cols]
|
||||
Sets the number of display columns in the output of @code{,backtrace}
|
||||
and @code{,locals} to @var{cols}. If @var{cols} is not given, the width
|
||||
of the terminal is used.
|
||||
@end deffn
|
||||
|
||||
The next 3 commands work at any REPL.
|
||||
|
||||
@deffn {REPL Command} break proc
|
||||
|
@ -404,6 +425,35 @@ List/show/set options.
|
|||
Quit this session.
|
||||
@end deffn
|
||||
|
||||
Current REPL options include:
|
||||
|
||||
@table @code
|
||||
@item compile-options
|
||||
The options used when compiling expressions entered at the REPL.
|
||||
@xref{Compilation}, for more on compilation options.
|
||||
@item interp
|
||||
Whether to interpret or compile expressions given at the REPL, if such a
|
||||
choice is available. Off by default (indicating compilation).
|
||||
@item prompt
|
||||
A customized REPL prompt. @code{#f} by default, indicating the default
|
||||
prompt.
|
||||
@item value-history
|
||||
Whether value history is on or not. @xref{Value History}.
|
||||
@item on-error
|
||||
What to do when an error happens. By default, @code{debug}, meaning to
|
||||
enter the debugger. Other values include @code{backtrace}, to show a
|
||||
backtrace without entering the debugger, or @code{report}, to simply
|
||||
show a short error printout.
|
||||
@end table
|
||||
|
||||
Default values for REPL options may be set using
|
||||
@code{repl-default-option-set!} from @code{(system repl common)}:
|
||||
|
||||
@deffn {Scheme Procedure} repl-set-default-option! key value
|
||||
Set the default value of a REPL option. This function is particularly
|
||||
useful in a user's init file. @xref{Init File}.
|
||||
@end deffn
|
||||
|
||||
|
||||
@node Error Handling
|
||||
@subsection Error Handling
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -35,6 +35,7 @@ get the relevant SRFI documents from the SRFI home page
|
|||
* SRFI-17:: Generalized set!
|
||||
* SRFI-18:: Multithreading support
|
||||
* SRFI-19:: Time/Date library.
|
||||
* SRFI-23:: Error reporting
|
||||
* SRFI-26:: Specializing parameters
|
||||
* SRFI-27:: Sources of Random Bits
|
||||
* SRFI-30:: Nested multi-line block comments
|
||||
|
@ -1927,6 +1928,13 @@ The functions created by @code{define-record-type} are ordinary
|
|||
top-level @code{define}s. They can be redefined or @code{set!} as
|
||||
desired, exported from a module, etc.
|
||||
|
||||
@unnumberedsubsubsec Non-toplevel Record Definitions
|
||||
|
||||
The SRFI-9 specification explicitly disallows record definitions in a
|
||||
non-toplevel context, such as inside @code{lambda} body or inside a
|
||||
@var{let} block. However, Guile's implementation does not enforce that
|
||||
restriction.
|
||||
|
||||
@unnumberedsubsubsec Custom Printers
|
||||
|
||||
You may use @code{set-record-type-printer!} to customize the default printing
|
||||
|
@ -3128,6 +3136,11 @@ Conversion is locale-dependent on systems that support it
|
|||
locale.
|
||||
@end defun
|
||||
|
||||
@node SRFI-23
|
||||
@subsection SRFI-23 - Error Reporting
|
||||
@cindex SRFI-23
|
||||
|
||||
The SRFI-23 @code{error} procedure is always available.
|
||||
|
||||
@node SRFI-26
|
||||
@subsection SRFI-26 - specializing parameters
|
||||
|
|
|
@ -303,14 +303,11 @@ is rather byzantine, so for now @emph{NO} doc snarfing programs are installed.
|
|||
@cindex executable modules
|
||||
@cindex scripts
|
||||
|
||||
When Guile is installed, in addition to the @code{(ice-9 FOO)} modules,
|
||||
a set of @dfn{executable modules} @code{(scripts BAR)} is also installed.
|
||||
Each is a regular Scheme module that has some additional packaging so
|
||||
that it can be called as a program in its own right, from the shell. For this
|
||||
reason, we sometimes use the term @dfn{script} in this context to mean the
|
||||
same thing.
|
||||
|
||||
@c wow look at this hole^! variable-width font users eat your heart out.
|
||||
When Guile is installed, in addition to the @code{(ice-9 FOO)} modules, a set
|
||||
of @dfn{guile-tools modules} @code{(scripts BAR)} is also installed. Each is
|
||||
a regular Scheme module that has some additional packaging so that it can be
|
||||
used by guile-tools, from the shell. For this reason, we sometimes use the
|
||||
term @dfn{script} in this context to mean the same thing.
|
||||
|
||||
As a convenience, the @code{guile-tools} wrapper program is installed along w/
|
||||
@code{guile}; it knows where a particular module is installed and calls it
|
||||
|
@ -346,16 +343,10 @@ executable module. Feel free to skip to the next chapter.
|
|||
|
||||
See template file @code{PROGRAM} for a quick start.
|
||||
|
||||
Programs must follow the @dfn{executable module} convention, documented here:
|
||||
Programs must follow the @dfn{guile-tools} convention, documented here:
|
||||
|
||||
@itemize
|
||||
|
||||
@item
|
||||
The file name must not end in ".scm".
|
||||
|
||||
@item
|
||||
The file must be executable (chmod +x).
|
||||
|
||||
@item
|
||||
The module name must be "(scripts PROGRAM)". A procedure named PROGRAM w/
|
||||
signature "(PROGRAM . args)" must be exported. Basically, use some variant
|
||||
|
@ -377,20 +368,10 @@ There must be the alias:
|
|||
|
||||
However, `main' must NOT be exported.
|
||||
|
||||
@item
|
||||
The beginning of the file must use the following invocation sequence:
|
||||
|
||||
@example
|
||||
#!/bin/sh
|
||||
main='(module-ref (resolve-module '\''(scripts PROGRAM)) '\'main')'
|
||||
exec $@{GUILE-guile@} -l $0 -c "(apply $main (cdr (command-line)))" "$@@"
|
||||
!#
|
||||
@end example
|
||||
|
||||
@end itemize
|
||||
|
||||
Following these conventions allows the program file to be used as module
|
||||
@code{(scripts PROGRAM)} in addition to as a standalone executable. Please
|
||||
@code{(scripts PROGRAM)} in addition to being invoked by guile-tools. Please
|
||||
also include a helpful Commentary section w/ some usage info.
|
||||
|
||||
@c tools.texi ends here
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2010
|
||||
@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2006, 2010, 2011
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -115,7 +115,7 @@ can be compiled and linked like this:
|
|||
|
||||
@example
|
||||
$ gcc -o simple-guile simple-guile.c \
|
||||
`pkg-config --cflags --libs guile-2.0`
|
||||
`pkg-config --cflags --libs guile-@value{EFFECTIVE-VERSION}`
|
||||
@end example
|
||||
|
||||
When it is run, it behaves just like the @code{guile} program except
|
||||
|
@ -163,7 +163,8 @@ This C source file needs to be compiled into a shared library. Here is
|
|||
how to do it on GNU/Linux:
|
||||
|
||||
@smallexample
|
||||
gcc -shared -o libguile-bessel.so -fPIC bessel.c
|
||||
gcc `pkg-config --cflags guile-@value{EFFECTIVE-VERSION}` \
|
||||
-shared -o libguile-bessel.so -fPIC bessel.c
|
||||
@end smallexample
|
||||
|
||||
For creating shared libraries portably, we recommend the use of GNU
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
@c -*-texinfo-*-
|
||||
@c This is part of the GNU Guile Reference Manual.
|
||||
@c Copyright (C) 2008, 2009, 2010, 2011
|
||||
@c Copyright (C) 2008,2009,2010
|
||||
@c Free Software Foundation, Inc.
|
||||
@c See the file guile.texi for copying conditions.
|
||||
|
||||
|
@ -1063,7 +1063,7 @@ embedded in the stream as a string.
|
|||
@end deffn
|
||||
@deffn Instruction load-string length
|
||||
Load a string from the instruction stream. The string is assumed to be
|
||||
Latin-1-encoded.
|
||||
encoded in the ``latin1'' locale.
|
||||
@end deffn
|
||||
@deffn Instruction load-wide-string length
|
||||
Load a UTF-32 string from the instruction stream. @var{length} is the
|
||||
|
@ -1071,7 +1071,7 @@ length in bytes, not in codepoints.
|
|||
@end deffn
|
||||
@deffn Instruction load-symbol length
|
||||
Load a symbol from the instruction stream. The symbol is assumed to be
|
||||
Latin-1-encoded. Symbols backed by wide strings may
|
||||
encoded in the ``latin1'' locale. Symbols backed by wide strings may
|
||||
be loaded via @code{load-wide-string} then @code{make-symbol}.
|
||||
@end deffn
|
||||
@deffn Instruction load-array length
|
||||
|
|
|
@ -59,8 +59,8 @@ valid dates. Error handling for a number of basic cases, like invalid
|
|||
dates, occurs on the boundary in which we produce a SRFI 19 date record
|
||||
from other types, like strings.
|
||||
|
||||
With regards to the web, data types are help in the two broad phases of
|
||||
HTTP messages: parsing and generation.
|
||||
With regards to the web, data types are helpful in the two broad phases
|
||||
of HTTP messages: parsing and generation.
|
||||
|
||||
Consider a server, which has to parse a request, and produce a response.
|
||||
Guile will parse the request into an HTTP request object
|
||||
|
@ -339,7 +339,7 @@ For example:
|
|||
|
||||
(string->header "FOO")
|
||||
@result{} foo
|
||||
(header->string 'foo
|
||||
(header->string 'foo)
|
||||
@result{} "Foo"
|
||||
@end example
|
||||
|
||||
|
@ -387,12 +387,6 @@ leaving it as a string. You could register this header with Guile's
|
|||
HTTP stack like this:
|
||||
|
||||
@example
|
||||
(define (parse-ip str)
|
||||
(inet-aton str)
|
||||
(define (validate-ip ip)
|
||||
(define (write-ip ip port)
|
||||
(display (inet-ntoa ip) port))
|
||||
|
||||
(declare-header! "X-Client-Address"
|
||||
(lambda (str)
|
||||
(inet-aton str))
|
||||
|
@ -1331,13 +1325,20 @@ If the read failed, the @code{read} hook may return #f for the client
|
|||
socket, request, and body.
|
||||
|
||||
@item
|
||||
A user-provided handler procedure is called, with the request
|
||||
and body as its arguments. The handler should return two
|
||||
values: the response, as a @code{<response>} record from @code{(web
|
||||
response)}, and the response body as a string, bytevector, or
|
||||
@code{#f} if not present. We also allow the response to be simply an
|
||||
alist of headers, in which case a default response object is
|
||||
constructed with those headers.
|
||||
A user-provided handler procedure is called, with the request and body
|
||||
as its arguments. The handler should return two values: the response,
|
||||
as a @code{<response>} record from @code{(web response)}, and the
|
||||
response body as bytevector, or @code{#f} if not present.
|
||||
|
||||
The respose and response body are run through @code{sanitize-response},
|
||||
documented below. This allows the handler writer to take some
|
||||
convenient shortcuts: for example, instead of a @code{<response>}, the
|
||||
handler can simply return an alist of headers, in which case a default
|
||||
response object is constructed with those headers. Instead of a
|
||||
bytevector for the body, the handler can return a string, which will be
|
||||
serialized into an appropriate encoding; or it can return a procedure,
|
||||
which will be called on a port to write out the data. See the
|
||||
@code{sanitize-response} documentation, for more.
|
||||
|
||||
@item
|
||||
The @code{write} hook is called with three arguments: the client
|
||||
|
@ -1581,7 +1582,7 @@ probably know, we'll want to return a 404 response.
|
|||
(define (not-found request)
|
||||
(values (build-response #:code 404)
|
||||
(string-append "Resource not found: "
|
||||
(unparse-uri (request-uri request)))))
|
||||
(uri->string (request-uri request)))))
|
||||
|
||||
;; Now paste this to let the web server keep going:
|
||||
,continue
|
||||
|
|
55
gc-benchmarks/Makefile.am
Normal file
55
gc-benchmarks/Makefile.am
Normal file
|
@ -0,0 +1,55 @@
|
|||
## Process this file with automake to produce Makefile.in.
|
||||
##
|
||||
## Copyright (C) 2011 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
|
||||
|
||||
EXTRA_DIST = \
|
||||
gc-profile.scm \
|
||||
gcbench.scm \
|
||||
guile-test.scm \
|
||||
loop.scm \
|
||||
run-benchmark.scm \
|
||||
string.scm \
|
||||
$(benchmarks)
|
||||
|
||||
# GPLv2+ Larceny GC benchmarks by Lars Hansen et al. from
|
||||
# <http://www.ccs.neu.edu/home/will/GC/sourcecode.html>.
|
||||
benchmarks = \
|
||||
larceny/GPL \
|
||||
larceny/README \
|
||||
larceny/dumb.sch \
|
||||
larceny/dummy.sch \
|
||||
larceny/dynamic-input-large.sch \
|
||||
larceny/dynamic-input-small.sch \
|
||||
larceny/dynamic.sch \
|
||||
larceny/earley.sch \
|
||||
larceny/gcbench.sch \
|
||||
larceny/gcold.scm \
|
||||
larceny/graphs.sch \
|
||||
larceny/lattice.sch \
|
||||
larceny/nboyer.sch \
|
||||
larceny/nucleic2.sch \
|
||||
larceny/perm.sch \
|
||||
larceny/run-benchmark.chez \
|
||||
larceny/sboyer.sch \
|
||||
larceny/softscheme.sch \
|
||||
larceny/twobit-input-long.sch \
|
||||
larceny/twobit-input-short.sch \
|
||||
larceny/twobit-smaller.sch \
|
||||
larceny/twobit.sch
|
|
@ -3,7 +3,7 @@
|
|||
exec ${GUILE-guile} --no-debug -q -l "$0" \
|
||||
-c '(apply main (cdr (command-line)))' "$@"
|
||||
!#
|
||||
;;; Copyright (C) 2008 Free Software Foundation, Inc.
|
||||
;;; Copyright (C) 2008, 2011 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
|
||||
|
@ -38,13 +38,18 @@ memory mapping of process @var{pid}. This information is obtained by reading
|
|||
@file{/proc/PID/smaps} on Linux. See `procs(5)' for details."
|
||||
|
||||
(define mapping-line-rx
|
||||
;; As of Linux 2.6.32.28, an `smaps' line looks like this:
|
||||
;; "00400000-00401000 r-xp 00000000 fe:00 108264 /home/ludo/soft/bin/guile"
|
||||
(make-regexp
|
||||
"^([[:xdigit:]]+)-([[:xdigit:]]+) ([rwx-]{3}[ps]) ([[:xdigit:]]+) [0-9]{2}:[0-9]{2} [0-9]+[[:blank:]]+(.*)$"))
|
||||
"^([[:xdigit:]]+)-([[:xdigit:]]+) ([rwx-]{3}[ps]) ([[:xdigit:]]+) [[:xdigit:]]{2}:[[:xdigit:]]{2} [0-9]+[[:blank:]]+(.*)$"))
|
||||
|
||||
(define rss-line-rx
|
||||
(make-regexp
|
||||
"^Rss:[[:blank:]]+([[:digit:]]+) kB$"))
|
||||
|
||||
(if (not (string-contains %host-type "-linux-"))
|
||||
(error "this procedure only works on Linux-based systems" %host-type))
|
||||
|
||||
(with-input-from-port (open-input-file (format #f "/proc/~a/smaps" pid))
|
||||
(lambda ()
|
||||
(let loop ((line (read-line))
|
||||
|
@ -83,7 +88,7 @@ memory mapping of process @var{pid}. This information is obtained by reading
|
|||
(loop (read-line) result))))))))
|
||||
|
||||
(define (total-heap-size pid)
|
||||
"Return the total heap size of process @var{pid}."
|
||||
"Return a pair representing the total and RSS heap size of PID."
|
||||
|
||||
(define heap-or-anon-rx
|
||||
(make-regexp "\\[(heap|anon)\\]"))
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
# the same distribution terms as the rest of that program.
|
||||
#
|
||||
# Generated by gnulib-tool.
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl=3 --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap canonicalize-lgpl close connect duplocale environ extensions flock fpieee full-read full-write func gendocs getaddrinfo getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isinf isnan lib-symbol-versions lib-symbol-visibility libunistring listen locale log1p maintainer-makefile malloc-gnu malloca nproc putenv recv recvfrom round send sendto setsockopt shutdown socket stat-time stdlib strcase strftime striconveh string sys_stat trunc verify version-etc-fsf vsnprintf warnings
|
||||
# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=build-aux --lgpl=3 --libtool --macro-prefix=gl --no-vc-files accept alignof alloca-opt announce-gen autobuild bind byteswap canonicalize-lgpl ceil close connect duplocale environ extensions flock floor fpieee frexp full-read full-write func gendocs getaddrinfo getpeername getsockname getsockopt git-version-gen gitlog-to-changelog gnu-web-doc-update gnupload havelib iconv_open-utf inet_ntop inet_pton isinf isnan ldexp lib-symbol-versions lib-symbol-visibility libunistring listen locale log1p maintainer-makefile malloc-gnu malloca nproc putenv recv recvfrom send sendto setsockopt shutdown socket stat-time stdlib strcase strftime striconveh string sys_stat trunc verify version-etc-fsf vsnprintf warnings wchar
|
||||
|
||||
AUTOMAKE_OPTIONS = 1.5 gnits subdir-objects
|
||||
|
||||
|
@ -37,7 +37,9 @@ libgnu_la_DEPENDENCIES = $(gl_LTLIBOBJS)
|
|||
EXTRA_libgnu_la_SOURCES =
|
||||
libgnu_la_LDFLAGS = $(AM_LDFLAGS)
|
||||
libgnu_la_LDFLAGS += -no-undefined
|
||||
libgnu_la_LDFLAGS += $(CEIL_LIBM)
|
||||
libgnu_la_LDFLAGS += $(FLOOR_LIBM)
|
||||
libgnu_la_LDFLAGS += $(FREXP_LIBM)
|
||||
libgnu_la_LDFLAGS += $(GETADDRINFO_LIB)
|
||||
libgnu_la_LDFLAGS += $(HOSTENT_LIB)
|
||||
libgnu_la_LDFLAGS += $(INET_NTOP_LIB)
|
||||
|
@ -45,12 +47,12 @@ libgnu_la_LDFLAGS += $(INET_PTON_LIB)
|
|||
libgnu_la_LDFLAGS += $(ISNAND_LIBM)
|
||||
libgnu_la_LDFLAGS += $(ISNANF_LIBM)
|
||||
libgnu_la_LDFLAGS += $(ISNANL_LIBM)
|
||||
libgnu_la_LDFLAGS += $(LDEXP_LIBM)
|
||||
libgnu_la_LDFLAGS += $(LIBSOCKET)
|
||||
libgnu_la_LDFLAGS += $(LOG1P_LIBM)
|
||||
libgnu_la_LDFLAGS += $(LTLIBICONV)
|
||||
libgnu_la_LDFLAGS += $(LTLIBINTL)
|
||||
libgnu_la_LDFLAGS += $(LTLIBUNISTRING)
|
||||
libgnu_la_LDFLAGS += $(ROUND_LIBM)
|
||||
libgnu_la_LDFLAGS += $(SERVENT_LIB)
|
||||
libgnu_la_LDFLAGS += $(TRUNC_LIBM)
|
||||
|
||||
|
@ -231,6 +233,15 @@ EXTRA_libgnu_la_SOURCES += canonicalize-lgpl.c
|
|||
|
||||
## end gnulib module canonicalize-lgpl
|
||||
|
||||
## begin gnulib module ceil
|
||||
|
||||
|
||||
EXTRA_DIST += ceil.c
|
||||
|
||||
EXTRA_libgnu_la_SOURCES += ceil.c
|
||||
|
||||
## end gnulib module ceil
|
||||
|
||||
## begin gnulib module close
|
||||
|
||||
|
||||
|
@ -257,6 +268,13 @@ EXTRA_libgnu_la_SOURCES += connect.c
|
|||
|
||||
## end gnulib module connect
|
||||
|
||||
## begin gnulib module dosname
|
||||
|
||||
|
||||
EXTRA_DIST += dosname.h
|
||||
|
||||
## end gnulib module dosname
|
||||
|
||||
## begin gnulib module duplocale
|
||||
|
||||
|
||||
|
@ -343,6 +361,15 @@ EXTRA_libgnu_la_SOURCES += floor.c
|
|||
|
||||
## end gnulib module floor
|
||||
|
||||
## begin gnulib module frexp
|
||||
|
||||
|
||||
EXTRA_DIST += frexp.c
|
||||
|
||||
EXTRA_libgnu_la_SOURCES += frexp.c
|
||||
|
||||
## end gnulib module frexp
|
||||
|
||||
## begin gnulib module full-read
|
||||
|
||||
libgnu_la_SOURCES += full-read.h full-read.c
|
||||
|
@ -558,6 +585,15 @@ EXTRA_libgnu_la_SOURCES += isnan.c isnand.c
|
|||
|
||||
## end gnulib module isnand
|
||||
|
||||
## begin gnulib module isnand-nolibm
|
||||
|
||||
|
||||
EXTRA_DIST += float+.h isnan.c isnand-nolibm.h isnand.c
|
||||
|
||||
EXTRA_libgnu_la_SOURCES += isnan.c isnand.c
|
||||
|
||||
## end gnulib module isnand-nolibm
|
||||
|
||||
## begin gnulib module isnanf
|
||||
|
||||
|
||||
|
@ -904,15 +940,6 @@ EXTRA_libgnu_la_SOURCES += recvfrom.c
|
|||
|
||||
## end gnulib module recvfrom
|
||||
|
||||
## begin gnulib module round
|
||||
|
||||
|
||||
EXTRA_DIST += round.c
|
||||
|
||||
EXTRA_libgnu_la_SOURCES += round.c
|
||||
|
||||
## end gnulib module round
|
||||
|
||||
## begin gnulib module safe-read
|
||||
|
||||
|
||||
|
@ -1097,6 +1124,7 @@ stdint.h: stdint.in.h
|
|||
-e 's/@''HAVE_INTTYPES_H''@/$(HAVE_INTTYPES_H)/g' \
|
||||
-e 's/@''HAVE_SYS_INTTYPES_H''@/$(HAVE_SYS_INTTYPES_H)/g' \
|
||||
-e 's/@''HAVE_SYS_BITYPES_H''@/$(HAVE_SYS_BITYPES_H)/g' \
|
||||
-e 's/@''HAVE_WCHAR_H''@/$(HAVE_WCHAR_H)/g' \
|
||||
-e 's/@''HAVE_LONG_LONG_INT''@/$(HAVE_LONG_LONG_INT)/g' \
|
||||
-e 's/@''HAVE_UNSIGNED_LONG_LONG_INT''@/$(HAVE_UNSIGNED_LONG_LONG_INT)/g' \
|
||||
-e 's/@''APPLE_UNIVERSAL_BUILD''@/$(APPLE_UNIVERSAL_BUILD)/g' \
|
||||
|
@ -1229,9 +1257,7 @@ stdio.h: stdio.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
|
|||
mv $@-t $@
|
||||
MOSTLYCLEANFILES += stdio.h stdio.h-t
|
||||
|
||||
EXTRA_DIST += stdio-write.c stdio.in.h
|
||||
|
||||
EXTRA_libgnu_la_SOURCES += stdio-write.c
|
||||
EXTRA_DIST += stdio.in.h
|
||||
|
||||
## end gnulib module stdio
|
||||
|
||||
|
@ -1256,6 +1282,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
|
|||
-e 's|@''GNULIB_GETSUBOPT''@|$(GNULIB_GETSUBOPT)|g' \
|
||||
-e 's|@''GNULIB_GRANTPT''@|$(GNULIB_GRANTPT)|g' \
|
||||
-e 's|@''GNULIB_MALLOC_POSIX''@|$(GNULIB_MALLOC_POSIX)|g' \
|
||||
-e 's|@''GNULIB_MBTOWC''@|$(GNULIB_MBTOWC)|g' \
|
||||
-e 's|@''GNULIB_MKDTEMP''@|$(GNULIB_MKDTEMP)|g' \
|
||||
-e 's|@''GNULIB_MKOSTEMP''@|$(GNULIB_MKOSTEMP)|g' \
|
||||
-e 's|@''GNULIB_MKOSTEMPS''@|$(GNULIB_MKOSTEMPS)|g' \
|
||||
|
@ -1274,6 +1301,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
|
|||
-e 's|@''GNULIB_SYSTEM_POSIX''@|$(GNULIB_SYSTEM_POSIX)|g' \
|
||||
-e 's|@''GNULIB_UNLOCKPT''@|$(GNULIB_UNLOCKPT)|g' \
|
||||
-e 's|@''GNULIB_UNSETENV''@|$(GNULIB_UNSETENV)|g' \
|
||||
-e 's|@''GNULIB_WCTOMB''@|$(GNULIB_WCTOMB)|g' \
|
||||
< $(srcdir)/stdlib.in.h | \
|
||||
sed -e 's|@''HAVE__EXIT''@|$(HAVE__EXIT)|g' \
|
||||
-e 's|@''HAVE_ATOLL''@|$(HAVE_ATOLL)|g' \
|
||||
|
@ -1302,6 +1330,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
|
|||
-e 's|@''REPLACE_CALLOC''@|$(REPLACE_CALLOC)|g' \
|
||||
-e 's|@''REPLACE_CANONICALIZE_FILE_NAME''@|$(REPLACE_CANONICALIZE_FILE_NAME)|g' \
|
||||
-e 's|@''REPLACE_MALLOC''@|$(REPLACE_MALLOC)|g' \
|
||||
-e 's|@''REPLACE_MBTOWC''@|$(REPLACE_MBTOWC)|g' \
|
||||
-e 's|@''REPLACE_MKSTEMP''@|$(REPLACE_MKSTEMP)|g' \
|
||||
-e 's|@''REPLACE_PUTENV''@|$(REPLACE_PUTENV)|g' \
|
||||
-e 's|@''REPLACE_REALLOC''@|$(REPLACE_REALLOC)|g' \
|
||||
|
@ -1309,6 +1338,7 @@ stdlib.h: stdlib.in.h $(CXXDEFS_H) $(ARG_NONNULL_H) $(WARN_ON_USE_H)
|
|||
-e 's|@''REPLACE_SETENV''@|$(REPLACE_SETENV)|g' \
|
||||
-e 's|@''REPLACE_STRTOD''@|$(REPLACE_STRTOD)|g' \
|
||||
-e 's|@''REPLACE_UNSETENV''@|$(REPLACE_UNSETENV)|g' \
|
||||
-e 's|@''REPLACE_WCTOMB''@|$(REPLACE_WCTOMB)|g' \
|
||||
-e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
|
||||
-e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \
|
||||
-e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)'; \
|
||||
|
|
109
lib/ceil.c
Normal file
109
lib/ceil.c
Normal file
|
@ -0,0 +1,109 @@
|
|||
/* Round towards positive infinity.
|
||||
Copyright (C) 2007, 2010-2011 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 of the License, 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 program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Bruno Haible <bruno@clisp.org>, 2007. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <math.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#undef MIN
|
||||
|
||||
#ifdef USE_LONG_DOUBLE
|
||||
# define FUNC ceill
|
||||
# define DOUBLE long double
|
||||
# define MANT_DIG LDBL_MANT_DIG
|
||||
# define MIN LDBL_MIN
|
||||
# define L_(literal) literal##L
|
||||
#elif ! defined USE_FLOAT
|
||||
# define FUNC ceil
|
||||
# define DOUBLE double
|
||||
# define MANT_DIG DBL_MANT_DIG
|
||||
# define MIN DBL_MIN
|
||||
# define L_(literal) literal
|
||||
#else /* defined USE_FLOAT */
|
||||
# define FUNC ceilf
|
||||
# define DOUBLE float
|
||||
# define MANT_DIG FLT_MANT_DIG
|
||||
# define MIN FLT_MIN
|
||||
# define L_(literal) literal##f
|
||||
#endif
|
||||
|
||||
/* -0.0. See minus-zero.h. */
|
||||
#if defined __hpux || defined __sgi || defined __ICC
|
||||
# define MINUS_ZERO (-MIN * MIN)
|
||||
#else
|
||||
# define MINUS_ZERO L_(-0.0)
|
||||
#endif
|
||||
|
||||
/* 2^(MANT_DIG-1). */
|
||||
static const DOUBLE TWO_MANT_DIG =
|
||||
/* Assume MANT_DIG <= 5 * 31.
|
||||
Use the identity
|
||||
n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */
|
||||
(DOUBLE) (1U << ((MANT_DIG - 1) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 1) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 2) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 3) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 4) / 5));
|
||||
|
||||
DOUBLE
|
||||
FUNC (DOUBLE x)
|
||||
{
|
||||
/* The use of 'volatile' guarantees that excess precision bits are dropped
|
||||
at each addition step and before the following comparison at the caller's
|
||||
site. It is necessary on x86 systems where double-floats are not IEEE
|
||||
compliant by default, to avoid that the results become platform and compiler
|
||||
option dependent. 'volatile' is a portable alternative to gcc's
|
||||
-ffloat-store option. */
|
||||
volatile DOUBLE y = x;
|
||||
volatile DOUBLE z = y;
|
||||
|
||||
if (z > L_(0.0))
|
||||
{
|
||||
/* Avoid rounding errors for values near 2^k, where k >= MANT_DIG-1. */
|
||||
if (z < TWO_MANT_DIG)
|
||||
{
|
||||
/* Round to the next integer (nearest or up or down, doesn't matter). */
|
||||
z += TWO_MANT_DIG;
|
||||
z -= TWO_MANT_DIG;
|
||||
/* Enforce rounding up. */
|
||||
if (z < y)
|
||||
z += L_(1.0);
|
||||
}
|
||||
}
|
||||
else if (z < L_(0.0))
|
||||
{
|
||||
/* For -1 < x < 0, return -0.0 regardless of the current rounding
|
||||
mode. */
|
||||
if (z > L_(-1.0))
|
||||
z = MINUS_ZERO;
|
||||
/* Avoid rounding errors for values near -2^k, where k >= MANT_DIG-1. */
|
||||
else if (z > - TWO_MANT_DIG)
|
||||
{
|
||||
/* Round to the next integer (nearest or up or down, doesn't matter). */
|
||||
z -= TWO_MANT_DIG;
|
||||
z += TWO_MANT_DIG;
|
||||
/* Enforce rounding up. */
|
||||
if (z < y)
|
||||
z += L_(1.0);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
53
lib/dosname.h
Normal file
53
lib/dosname.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* File names on MS-DOS/Windows systems.
|
||||
|
||||
Copyright (C) 2000-2001, 2004-2006, 2009-2011 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 of the License, 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 program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
From Paul Eggert and Jim Meyering. */
|
||||
|
||||
#ifndef _DOSNAME_H
|
||||
#define _DOSNAME_H
|
||||
|
||||
#if (defined _WIN32 || defined __WIN32__ || \
|
||||
defined __MSDOS__ || defined __CYGWIN__ || \
|
||||
defined __EMX__ || defined __DJGPP__)
|
||||
/* This internal macro assumes ASCII, but all hosts that support drive
|
||||
letters use ASCII. */
|
||||
# define _IS_DRIVE_LETTER(C) (((unsigned int) (C) | ('a' - 'A')) - 'a' \
|
||||
<= 'z' - 'a')
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) \
|
||||
(_IS_DRIVE_LETTER ((Filename)[0]) && (Filename)[1] == ':' ? 2 : 0)
|
||||
# ifndef __CYGWIN__
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 1
|
||||
# endif
|
||||
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
|
||||
#else
|
||||
# define FILE_SYSTEM_PREFIX_LEN(Filename) 0
|
||||
# define ISSLASH(C) ((C) == '/')
|
||||
#endif
|
||||
|
||||
#ifndef FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE 0
|
||||
#endif
|
||||
|
||||
#if FILE_SYSTEM_DRIVE_PREFIX_CAN_BE_RELATIVE
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) ISSLASH ((F)[FILE_SYSTEM_PREFIX_LEN (F)])
|
||||
# else
|
||||
# define IS_ABSOLUTE_FILE_NAME(F) \
|
||||
(ISSLASH ((F)[0]) || FILE_SYSTEM_PREFIX_LEN (F) != 0)
|
||||
#endif
|
||||
#define IS_RELATIVE_FILE_NAME(F) (! IS_ABSOLUTE_FILE_NAME (F))
|
||||
|
||||
#endif /* DOSNAME_H_ */
|
166
lib/frexp.c
Normal file
166
lib/frexp.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
/* Split a double into fraction and mantissa.
|
||||
Copyright (C) 2007-2011 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 of the License, 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 program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* Written by Paolo Bonzini <bonzini@gnu.org>, 2003, and
|
||||
Bruno Haible <bruno@clisp.org>, 2007. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <math.h>
|
||||
|
||||
#include <float.h>
|
||||
#ifdef USE_LONG_DOUBLE
|
||||
# include "isnanl-nolibm.h"
|
||||
# include "fpucw.h"
|
||||
#else
|
||||
# include "isnand-nolibm.h"
|
||||
#endif
|
||||
|
||||
/* This file assumes FLT_RADIX = 2. If FLT_RADIX is a power of 2 greater
|
||||
than 2, or not even a power of 2, some rounding errors can occur, so that
|
||||
then the returned mantissa is only guaranteed to be <= 1.0, not < 1.0. */
|
||||
|
||||
#ifdef USE_LONG_DOUBLE
|
||||
# define FUNC frexpl
|
||||
# define DOUBLE long double
|
||||
# define ISNAN isnanl
|
||||
# define DECL_ROUNDING DECL_LONG_DOUBLE_ROUNDING
|
||||
# define BEGIN_ROUNDING() BEGIN_LONG_DOUBLE_ROUNDING ()
|
||||
# define END_ROUNDING() END_LONG_DOUBLE_ROUNDING ()
|
||||
# define L_(literal) literal##L
|
||||
#else
|
||||
# define FUNC frexp
|
||||
# define DOUBLE double
|
||||
# define ISNAN isnand
|
||||
# define DECL_ROUNDING
|
||||
# define BEGIN_ROUNDING()
|
||||
# define END_ROUNDING()
|
||||
# define L_(literal) literal
|
||||
#endif
|
||||
|
||||
DOUBLE
|
||||
FUNC (DOUBLE x, int *expptr)
|
||||
{
|
||||
int sign;
|
||||
int exponent;
|
||||
DECL_ROUNDING
|
||||
|
||||
/* Test for NaN, infinity, and zero. */
|
||||
if (ISNAN (x) || x + x == x)
|
||||
{
|
||||
*expptr = 0;
|
||||
return x;
|
||||
}
|
||||
|
||||
sign = 0;
|
||||
if (x < 0)
|
||||
{
|
||||
x = - x;
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
BEGIN_ROUNDING ();
|
||||
|
||||
{
|
||||
/* Since the exponent is an 'int', it fits in 64 bits. Therefore the
|
||||
loops are executed no more than 64 times. */
|
||||
DOUBLE pow2[64]; /* pow2[i] = 2^2^i */
|
||||
DOUBLE powh[64]; /* powh[i] = 2^-2^i */
|
||||
int i;
|
||||
|
||||
exponent = 0;
|
||||
if (x >= L_(1.0))
|
||||
{
|
||||
/* A positive exponent. */
|
||||
DOUBLE pow2_i; /* = pow2[i] */
|
||||
DOUBLE powh_i; /* = powh[i] */
|
||||
|
||||
/* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
|
||||
x * 2^exponent = argument, x >= 1.0. */
|
||||
for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
|
||||
;
|
||||
i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
|
||||
{
|
||||
if (x >= pow2_i)
|
||||
{
|
||||
exponent += (1 << i);
|
||||
x *= powh_i;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
pow2[i] = pow2_i;
|
||||
powh[i] = powh_i;
|
||||
}
|
||||
/* Avoid making x too small, as it could become a denormalized
|
||||
number and thus lose precision. */
|
||||
while (i > 0 && x < pow2[i - 1])
|
||||
{
|
||||
i--;
|
||||
powh_i = powh[i];
|
||||
}
|
||||
exponent += (1 << i);
|
||||
x *= powh_i;
|
||||
/* Here 2^-2^i <= x < 1.0. */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A negative or zero exponent. */
|
||||
DOUBLE pow2_i; /* = pow2[i] */
|
||||
DOUBLE powh_i; /* = powh[i] */
|
||||
|
||||
/* Invariants: pow2_i = 2^2^i, powh_i = 2^-2^i,
|
||||
x * 2^exponent = argument, x < 1.0. */
|
||||
for (i = 0, pow2_i = L_(2.0), powh_i = L_(0.5);
|
||||
;
|
||||
i++, pow2_i = pow2_i * pow2_i, powh_i = powh_i * powh_i)
|
||||
{
|
||||
if (x < powh_i)
|
||||
{
|
||||
exponent -= (1 << i);
|
||||
x *= pow2_i;
|
||||
}
|
||||
else
|
||||
break;
|
||||
|
||||
pow2[i] = pow2_i;
|
||||
powh[i] = powh_i;
|
||||
}
|
||||
/* Here 2^-2^i <= x < 1.0. */
|
||||
}
|
||||
|
||||
/* Invariants: x * 2^exponent = argument, and 2^-2^i <= x < 1.0. */
|
||||
while (i > 0)
|
||||
{
|
||||
i--;
|
||||
if (x < powh[i])
|
||||
{
|
||||
exponent -= (1 << i);
|
||||
x *= pow2[i];
|
||||
}
|
||||
}
|
||||
/* Here 0.5 <= x < 1.0. */
|
||||
}
|
||||
|
||||
if (sign < 0)
|
||||
x = - x;
|
||||
|
||||
END_ROUNDING ();
|
||||
|
||||
*expptr = exponent;
|
||||
return x;
|
||||
}
|
33
lib/isnand-nolibm.h
Normal file
33
lib/isnand-nolibm.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* Test for NaN that does not need libm.
|
||||
Copyright (C) 2007-2011 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 of the License, 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 program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if HAVE_ISNAND_IN_LIBC
|
||||
/* Get declaration of isnan macro. */
|
||||
# include <math.h>
|
||||
# if __GNUC__ >= 4
|
||||
/* GCC 4.0 and newer provides three built-ins for isnan. */
|
||||
# undef isnand
|
||||
# define isnand(x) __builtin_isnan ((double)(x))
|
||||
# else
|
||||
# undef isnand
|
||||
# define isnand(x) isnan ((double)(x))
|
||||
# endif
|
||||
#else
|
||||
/* Test whether X is a NaN. */
|
||||
# undef isnand
|
||||
# define isnand rpl_isnand
|
||||
extern int isnand (double x);
|
||||
#endif
|
168
lib/round.c
168
lib/round.c
|
@ -1,168 +0,0 @@
|
|||
/* Round toward nearest, breaking ties away from zero.
|
||||
Copyright (C) 2007, 2010-2011 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 2, 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 program; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
|
||||
|
||||
/* Written by Ben Pfaff <blp@gnu.org>, 2007.
|
||||
Based heavily on code by Bruno Haible. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <math.h>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#undef MIN
|
||||
|
||||
#ifdef USE_LONG_DOUBLE
|
||||
# define ROUND roundl
|
||||
# define FLOOR floorl
|
||||
# define CEIL ceill
|
||||
# define DOUBLE long double
|
||||
# define MANT_DIG LDBL_MANT_DIG
|
||||
# define MIN LDBL_MIN
|
||||
# define L_(literal) literal##L
|
||||
# define HAVE_FLOOR_AND_CEIL HAVE_FLOORL_AND_CEILL
|
||||
#elif ! defined USE_FLOAT
|
||||
# define ROUND round
|
||||
# define FLOOR floor
|
||||
# define CEIL ceil
|
||||
# define DOUBLE double
|
||||
# define MANT_DIG DBL_MANT_DIG
|
||||
# define MIN DBL_MIN
|
||||
# define L_(literal) literal
|
||||
# define HAVE_FLOOR_AND_CEIL 1
|
||||
#else /* defined USE_FLOAT */
|
||||
# define ROUND roundf
|
||||
# define FLOOR floorf
|
||||
# define CEIL ceilf
|
||||
# define DOUBLE float
|
||||
# define MANT_DIG FLT_MANT_DIG
|
||||
# define MIN FLT_MIN
|
||||
# define L_(literal) literal##f
|
||||
# define HAVE_FLOOR_AND_CEIL HAVE_FLOORF_AND_CEILF
|
||||
#endif
|
||||
|
||||
/* -0.0. See minus-zero.h. */
|
||||
#if defined __hpux || defined __sgi || defined __ICC
|
||||
# define MINUS_ZERO (-MIN * MIN)
|
||||
#else
|
||||
# define MINUS_ZERO L_(-0.0)
|
||||
#endif
|
||||
|
||||
/* If we're being included from test-round2[f].c, it already defined names for
|
||||
our round implementations. Otherwise, pick the preferred implementation for
|
||||
this machine. */
|
||||
#if !defined FLOOR_BASED_ROUND && !defined FLOOR_FREE_ROUND
|
||||
# if HAVE_FLOOR_AND_CEIL
|
||||
# define FLOOR_BASED_ROUND ROUND
|
||||
# else
|
||||
# define FLOOR_FREE_ROUND ROUND
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef FLOOR_BASED_ROUND
|
||||
/* An implementation of the C99 round function based on floor and ceil. We use
|
||||
this when floor and ceil are available, on the assumption that they are
|
||||
faster than the open-coded versions below. */
|
||||
DOUBLE
|
||||
FLOOR_BASED_ROUND (DOUBLE x)
|
||||
{
|
||||
if (x >= L_(0.0))
|
||||
{
|
||||
DOUBLE y = FLOOR (x);
|
||||
if (x - y >= L_(0.5))
|
||||
y += L_(1.0);
|
||||
return y;
|
||||
}
|
||||
else
|
||||
{
|
||||
DOUBLE y = CEIL (x);
|
||||
if (y - x >= L_(0.5))
|
||||
y -= L_(1.0);
|
||||
return y;
|
||||
}
|
||||
}
|
||||
#endif /* FLOOR_BASED_ROUND */
|
||||
|
||||
#ifdef FLOOR_FREE_ROUND
|
||||
/* An implementation of the C99 round function without floor or ceil.
|
||||
We use this when floor or ceil is missing. */
|
||||
DOUBLE
|
||||
FLOOR_FREE_ROUND (DOUBLE x)
|
||||
{
|
||||
/* 2^(MANT_DIG-1). */
|
||||
static const DOUBLE TWO_MANT_DIG =
|
||||
/* Assume MANT_DIG <= 5 * 31.
|
||||
Use the identity
|
||||
n = floor(n/5) + floor((n+1)/5) + ... + floor((n+4)/5). */
|
||||
(DOUBLE) (1U << ((MANT_DIG - 1) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 1) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 2) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 3) / 5))
|
||||
* (DOUBLE) (1U << ((MANT_DIG - 1 + 4) / 5));
|
||||
|
||||
/* The use of 'volatile' guarantees that excess precision bits are dropped at
|
||||
each addition step and before the following comparison at the caller's
|
||||
site. It is necessary on x86 systems where double-floats are not IEEE
|
||||
compliant by default, to avoid that the results become platform and
|
||||
compiler option dependent. 'volatile' is a portable alternative to gcc's
|
||||
-ffloat-store option. */
|
||||
volatile DOUBLE y = x;
|
||||
volatile DOUBLE z = y;
|
||||
|
||||
if (z > L_(0.0))
|
||||
{
|
||||
/* Avoid rounding error for x = 0.5 - 2^(-MANT_DIG-1). */
|
||||
if (z < L_(0.5))
|
||||
z = L_(0.0);
|
||||
/* Avoid rounding errors for values near 2^k, where k >= MANT_DIG-1. */
|
||||
else if (z < TWO_MANT_DIG)
|
||||
{
|
||||
/* Add 0.5 to the absolute value. */
|
||||
y = z += L_(0.5);
|
||||
/* Round to the next integer (nearest or up or down, doesn't
|
||||
matter). */
|
||||
z += TWO_MANT_DIG;
|
||||
z -= TWO_MANT_DIG;
|
||||
/* Enforce rounding down. */
|
||||
if (z > y)
|
||||
z -= L_(1.0);
|
||||
}
|
||||
}
|
||||
else if (z < L_(0.0))
|
||||
{
|
||||
/* Avoid rounding error for x = -(0.5 - 2^(-MANT_DIG-1)). */
|
||||
if (z > - L_(0.5))
|
||||
z = MINUS_ZERO;
|
||||
/* Avoid rounding errors for values near -2^k, where k >= MANT_DIG-1. */
|
||||
else if (z > -TWO_MANT_DIG)
|
||||
{
|
||||
/* Add 0.5 to the absolute value. */
|
||||
y = z -= L_(0.5);
|
||||
/* Round to the next integer (nearest or up or down, doesn't
|
||||
matter). */
|
||||
z -= TWO_MANT_DIG;
|
||||
z += TWO_MANT_DIG;
|
||||
/* Enforce rounding up. */
|
||||
if (z < y)
|
||||
z += L_(1.0);
|
||||
}
|
||||
}
|
||||
return z;
|
||||
}
|
||||
#endif /* FLOOR_FREE_ROUND */
|
||||
|
|
@ -37,6 +37,7 @@ orig_stat (const char *filename, struct stat *buf)
|
|||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "dosname.h"
|
||||
|
||||
/* Store information about NAME into ST. Work around bugs with
|
||||
trailing slashes. Mingw has other bugs (such as st_ino always
|
||||
|
|
|
@ -497,7 +497,12 @@ typedef int _verify_intmax_size[sizeof (intmax_t) == sizeof (uintmax_t)
|
|||
sequence of nested includes
|
||||
<wchar.h> -> <stdio.h> -> <getopt.h> -> <stdlib.h>, and the latter includes
|
||||
<stdint.h> and assumes its types are already defined. */
|
||||
#if ! (defined WCHAR_MIN && defined WCHAR_MAX)
|
||||
#if @HAVE_WCHAR_H@ && ! (defined WCHAR_MIN && defined WCHAR_MAX)
|
||||
/* BSD/OS 4.0.1 has a bug: <stddef.h>, <stdio.h> and <time.h> must be
|
||||
included before <wchar.h>. */
|
||||
# include <stddef.h>
|
||||
# include <stdio.h>
|
||||
# include <time.h>
|
||||
# define _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
|
||||
# include <wchar.h>
|
||||
# undef _GL_JUST_INCLUDE_SYSTEM_WCHAR_H
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
/* POSIX compatible FILE stream write function.
|
||||
Copyright (C) 2008-2011 Free Software Foundation, Inc.
|
||||
Written by Bruno Haible <bruno@clisp.org>, 2008.
|
||||
|
||||
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 of the License, 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 program. If not, see <http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <config.h>
|
||||
|
||||
/* Specification. */
|
||||
#include <stdio.h>
|
||||
|
||||
/* Replace these functions only if module 'sigpipe' is requested. */
|
||||
#if GNULIB_SIGPIPE
|
||||
|
||||
/* On native Windows platforms, SIGPIPE does not exist. When write() is
|
||||
called on a pipe with no readers, WriteFile() fails with error
|
||||
GetLastError() = ERROR_NO_DATA, and write() in consequence fails with
|
||||
error EINVAL. This write() function is at the basis of the function
|
||||
which flushes the buffer of a FILE stream. */
|
||||
|
||||
# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
|
||||
|
||||
# include <errno.h>
|
||||
# include <signal.h>
|
||||
# include <io.h>
|
||||
|
||||
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
|
||||
# include <windows.h>
|
||||
|
||||
# define CALL_WITH_SIGPIPE_EMULATION(RETTYPE, EXPRESSION, FAILED) \
|
||||
if (ferror (stream)) \
|
||||
return (EXPRESSION); \
|
||||
else \
|
||||
{ \
|
||||
RETTYPE ret; \
|
||||
SetLastError (0); \
|
||||
ret = (EXPRESSION); \
|
||||
if (FAILED && GetLastError () == ERROR_NO_DATA && ferror (stream)) \
|
||||
{ \
|
||||
int fd = fileno (stream); \
|
||||
if (fd >= 0 \
|
||||
&& GetFileType ((HANDLE) _get_osfhandle (fd)) == FILE_TYPE_PIPE)\
|
||||
{ \
|
||||
/* Try to raise signal SIGPIPE. */ \
|
||||
raise (SIGPIPE); \
|
||||
/* If it is currently blocked or ignored, change errno from \
|
||||
EINVAL to EPIPE. */ \
|
||||
errno = EPIPE; \
|
||||
} \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
# if !REPLACE_PRINTF_POSIX /* avoid collision with printf.c */
|
||||
int
|
||||
printf (const char *format, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
retval = vfprintf (stdout, format, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
# endif
|
||||
|
||||
# if !REPLACE_FPRINTF_POSIX /* avoid collision with fprintf.c */
|
||||
int
|
||||
fprintf (FILE *stream, const char *format, ...)
|
||||
{
|
||||
int retval;
|
||||
va_list args;
|
||||
|
||||
va_start (args, format);
|
||||
retval = vfprintf (stream, format, args);
|
||||
va_end (args);
|
||||
|
||||
return retval;
|
||||
}
|
||||
# endif
|
||||
|
||||
# if !REPLACE_VPRINTF_POSIX /* avoid collision with vprintf.c */
|
||||
int
|
||||
vprintf (const char *format, va_list args)
|
||||
{
|
||||
return vfprintf (stdout, format, args);
|
||||
}
|
||||
# endif
|
||||
|
||||
# if !REPLACE_VFPRINTF_POSIX /* avoid collision with vfprintf.c */
|
||||
int
|
||||
vfprintf (FILE *stream, const char *format, va_list args)
|
||||
#undef vfprintf
|
||||
{
|
||||
CALL_WITH_SIGPIPE_EMULATION (int, vfprintf (stream, format, args), ret == EOF)
|
||||
}
|
||||
# endif
|
||||
|
||||
int
|
||||
putchar (int c)
|
||||
{
|
||||
return fputc (c, stdout);
|
||||
}
|
||||
|
||||
int
|
||||
fputc (int c, FILE *stream)
|
||||
#undef fputc
|
||||
{
|
||||
CALL_WITH_SIGPIPE_EMULATION (int, fputc (c, stream), ret == EOF)
|
||||
}
|
||||
|
||||
int
|
||||
fputs (const char *string, FILE *stream)
|
||||
#undef fputs
|
||||
{
|
||||
CALL_WITH_SIGPIPE_EMULATION (int, fputs (string, stream), ret == EOF)
|
||||
}
|
||||
|
||||
int
|
||||
puts (const char *string)
|
||||
#undef puts
|
||||
{
|
||||
FILE *stream = stdout;
|
||||
CALL_WITH_SIGPIPE_EMULATION (int, puts (string), ret == EOF)
|
||||
}
|
||||
|
||||
size_t
|
||||
fwrite (const void *ptr, size_t s, size_t n, FILE *stream)
|
||||
#undef fwrite
|
||||
{
|
||||
CALL_WITH_SIGPIPE_EMULATION (size_t, fwrite (ptr, s, n, stream), ret < n)
|
||||
}
|
||||
|
||||
# endif
|
||||
#endif
|
|
@ -274,6 +274,21 @@ _GL_WARN_ON_USE (malloc, "malloc is not POSIX compliant everywhere - "
|
|||
"use gnulib module malloc-posix for portability");
|
||||
#endif
|
||||
|
||||
/* Convert a multibyte character to a wide character. */
|
||||
#if @GNULIB_MBTOWC@
|
||||
# if @REPLACE_MBTOWC@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef mbtowc
|
||||
# define mbtowc rpl_mbtowc
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
|
||||
_GL_CXXALIAS_RPL (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
|
||||
# else
|
||||
_GL_CXXALIAS_SYS (mbtowc, int, (wchar_t *pwc, const char *s, size_t n));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (mbtowc);
|
||||
#endif
|
||||
|
||||
#if @GNULIB_MKDTEMP@
|
||||
/* Create a unique temporary directory from TEMPLATE.
|
||||
The last six characters of TEMPLATE must be "XXXXXX";
|
||||
|
@ -723,6 +738,21 @@ _GL_WARN_ON_USE (unsetenv, "unsetenv is unportable - "
|
|||
# endif
|
||||
#endif
|
||||
|
||||
/* Convert a wide character to a multibyte character. */
|
||||
#if @GNULIB_WCTOMB@
|
||||
# if @REPLACE_WCTOMB@
|
||||
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
|
||||
# undef wctomb
|
||||
# define wctomb rpl_wctomb
|
||||
# endif
|
||||
_GL_FUNCDECL_RPL (wctomb, int, (char *s, wchar_t wc));
|
||||
_GL_CXXALIAS_RPL (wctomb, int, (char *s, wchar_t wc));
|
||||
# else
|
||||
_GL_CXXALIAS_SYS (wctomb, int, (char *s, wchar_t wc));
|
||||
# endif
|
||||
_GL_CXXALIASWARN (wctomb);
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _GL_STDLIB_H */
|
||||
#endif /* _GL_STDLIB_H */
|
||||
|
|
|
@ -24,16 +24,16 @@
|
|||
/* Get size_t. */
|
||||
#include <stddef.h>
|
||||
|
||||
#ifndef __attribute__
|
||||
/* The __attribute__ feature is available in gcc versions 2.5 and later.
|
||||
The __-protected variants of the attributes 'format' and 'printf' are
|
||||
accepted by gcc versions 2.6.4 (effectively 2.7) and later.
|
||||
We enable __attribute__ only if these are supported too, because
|
||||
We enable _GL_ATTRIBUTE_FORMAT only if these are supported too, because
|
||||
gnulib and libintl do '#define printf __printf__' when they override
|
||||
the 'printf' function. */
|
||||
# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7)
|
||||
# define __attribute__(Spec) /* empty */
|
||||
# endif
|
||||
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
|
||||
# define _GL_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec))
|
||||
#else
|
||||
# define _GL_ATTRIBUTE_FORMAT(spec) /* empty */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -69,9 +69,9 @@ extern "C" {
|
|||
# define vasnprintf rpl_vasnprintf
|
||||
#endif
|
||||
extern char * asnprintf (char *resultbuf, size_t *lengthp, const char *format, ...)
|
||||
__attribute__ ((__format__ (__printf__, 3, 4)));
|
||||
_GL_ATTRIBUTE_FORMAT ((__printf__, 3, 4));
|
||||
extern char * vasnprintf (char *resultbuf, size_t *lengthp, const char *format, va_list args)
|
||||
__attribute__ ((__format__ (__printf__, 3, 0)));
|
||||
_GL_ATTRIBUTE_FORMAT ((__printf__, 3, 0));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
# include <stdio.h>
|
||||
|
||||
/* The `sentinel' attribute was added in gcc 4.0. */
|
||||
#ifndef ATTRIBUTE_SENTINEL
|
||||
#ifndef _GL_ATTRIBUTE_SENTINEL
|
||||
# if 4 <= __GNUC__
|
||||
# define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
|
||||
# define _GL_ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
|
||||
# else
|
||||
# define ATTRIBUTE_SENTINEL /* empty */
|
||||
# define _GL_ATTRIBUTE_SENTINEL /* empty */
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -70,7 +70,7 @@ extern void version_etc (FILE *stream,
|
|||
const char *command_name, const char *package,
|
||||
const char *version,
|
||||
/* const char *author1, ..., NULL */ ...)
|
||||
ATTRIBUTE_SENTINEL;
|
||||
_GL_ATTRIBUTE_SENTINEL;
|
||||
|
||||
/* Display the usual `Report bugs to' stanza */
|
||||
extern void emit_bug_reporting_address (void);
|
||||
|
|
|
@ -460,7 +460,9 @@ version_info = @LIBGUILE_INTERFACE_CURRENT@:@LIBGUILE_INTERFACE_REVISION@:@LIBGU
|
|||
|
||||
libguile_@GUILE_EFFECTIVE_VERSION@_la_LDFLAGS = \
|
||||
$(BDW_GC_LIBS) $(LIBFFI_LIBS) \
|
||||
$(CEIL_LIBM) \
|
||||
$(FLOOR_LIBM) \
|
||||
$(FREXP_LIBM) \
|
||||
$(GETADDRINFO_LIB) \
|
||||
$(HOSTENT_LIB) \
|
||||
$(INET_NTOP_LIB) \
|
||||
|
@ -468,12 +470,12 @@ libguile_@GUILE_EFFECTIVE_VERSION@_la_LDFLAGS = \
|
|||
$(ISNAND_LIBM) \
|
||||
$(ISNANF_LIBM) \
|
||||
$(ISNANL_LIBM) \
|
||||
$(LDEXP_LIBM) \
|
||||
$(LIBSOCKET) \
|
||||
$(LOG1P_LIBM) \
|
||||
$(LTLIBICONV) \
|
||||
$(LTLIBINTL) \
|
||||
$(LTLIBUNISTRING) \
|
||||
$(ROUND_LIBM) \
|
||||
$(SERVENT_LIB) \
|
||||
$(TRUNC_LIBM) \
|
||||
-version-info $(version_info) \
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
#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.
|
||||
/* Copyright (C) 1995, 1996, 1997, 1999, 2000, 2001, 2004, 2006,
|
||||
* 2008, 2009, 2011 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
|
||||
|
@ -64,7 +65,8 @@ typedef struct scm_t_array_dim
|
|||
ssize_t inc;
|
||||
} scm_t_array_dim;
|
||||
|
||||
typedef enum {
|
||||
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 */
|
||||
|
@ -81,7 +83,7 @@ typedef enum {
|
|||
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_ARRAY_ELEMENT_TYPE_LAST = 15
|
||||
} scm_t_array_element_type;
|
||||
|
||||
SCM_INTERNAL SCM scm_i_array_element_types[];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004, 2005, 2006, 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,1996,1997,1998,2000,2001,2002,2003,2004, 2005, 2006, 2009, 2010, 2011 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
|
||||
|
@ -860,7 +860,6 @@ SCM
|
|||
scm_i_read_array (SCM port, int c)
|
||||
{
|
||||
ssize_t rank;
|
||||
int got_rank;
|
||||
char tag[80];
|
||||
int tag_len;
|
||||
|
||||
|
@ -888,7 +887,6 @@ scm_i_read_array (SCM port, int c)
|
|||
return SCM_BOOL_F;
|
||||
}
|
||||
rank = 1;
|
||||
got_rank = 1;
|
||||
tag[0] = 'f';
|
||||
tag_len = 1;
|
||||
goto continue_reading_tag;
|
||||
|
|
|
@ -278,9 +278,7 @@ SCM_DEFINE (scm_display_application, "display-application", 1, 2, 0,
|
|||
scm_print_state *pstate;
|
||||
|
||||
/* Create a string port used for adaptation of printing parameters. */
|
||||
sport = scm_mkstrport (SCM_INUM0,
|
||||
scm_make_string (scm_from_int (240),
|
||||
SCM_UNDEFINED),
|
||||
sport = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG,
|
||||
FUNC_NAME);
|
||||
|
||||
|
@ -431,7 +429,7 @@ display_backtrace_body (struct display_backtrace_args *a)
|
|||
#define FUNC_NAME "display_backtrace_body"
|
||||
{
|
||||
int n_frames, beg, end, n, i, j;
|
||||
int nfield, indent_p, indentation;
|
||||
int nfield, indentation;
|
||||
SCM frame, sport, print_state;
|
||||
SCM last_file;
|
||||
scm_print_state *pstate;
|
||||
|
@ -473,8 +471,7 @@ display_backtrace_body (struct display_backtrace_args *a)
|
|||
SCM_ASSERT (n > 0, a->depth, SCM_ARG4, s_display_backtrace);
|
||||
|
||||
/* Create a string port used for adaptation of printing parameters. */
|
||||
sport = scm_mkstrport (SCM_INUM0,
|
||||
scm_make_string (scm_from_int (240), SCM_UNDEFINED),
|
||||
sport = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG,
|
||||
FUNC_NAME);
|
||||
|
||||
|
@ -485,9 +482,6 @@ display_backtrace_body (struct display_backtrace_args *a)
|
|||
pstate->fancyp = 1;
|
||||
pstate->highlight_objects = a->highlight_objects;
|
||||
|
||||
/* First find out if it's reasonable to do indentation. */
|
||||
indent_p = 0;
|
||||
|
||||
/* Determine size of frame number field. */
|
||||
j = end;
|
||||
for (i = 0; j > 0; ++i) j /= 10;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SCM_BDW_GC_H
|
||||
#define SCM_BDW_GC_H
|
||||
|
||||
/* Copyright (C) 2006, 2008, 2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2006, 2008, 2009, 2011 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
|
||||
|
@ -32,6 +32,11 @@
|
|||
# define GC_THREADS 1
|
||||
# define GC_REDIRECT_TO_LOCAL 1
|
||||
|
||||
/* Don't #define pthread routines to their GC_pthread counterparts.
|
||||
Instead we will be careful inside Guile to use the GC_pthread
|
||||
routines. */
|
||||
# define GC_NO_THREAD_REDIRECTS 1
|
||||
|
||||
#endif
|
||||
|
||||
#include <gc/gc.h>
|
||||
|
|
|
@ -460,6 +460,45 @@ scm_i_with_continuation_barrier (scm_t_catch_body body,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
should_print_backtrace (SCM tag, SCM stack)
|
||||
{
|
||||
return SCM_BACKTRACE_P
|
||||
&& scm_is_true (stack)
|
||||
&& scm_initialized_p
|
||||
/* It's generally not useful to print backtraces for errors reading
|
||||
or expanding code in these fallback catch statements. */
|
||||
&& !scm_is_eq (tag, scm_from_latin1_symbol ("read-error"))
|
||||
&& !scm_is_eq (tag, scm_from_latin1_symbol ("syntax-error"));
|
||||
}
|
||||
|
||||
static void
|
||||
print_exception_and_backtrace (SCM port, SCM tag, SCM args)
|
||||
{
|
||||
SCM stack, frame;
|
||||
|
||||
/* We get here via a throw to a catch-all. In that case there is the
|
||||
throw frame active, and this catch closure, so narrow by two
|
||||
frames. */
|
||||
stack = scm_make_stack (SCM_BOOL_T, scm_list_1 (scm_from_int (2)));
|
||||
frame = scm_is_true (stack) ? scm_stack_ref (stack, SCM_INUM0) : SCM_BOOL_F;
|
||||
|
||||
if (should_print_backtrace (tag, stack))
|
||||
{
|
||||
scm_puts ("Backtrace:\n", port);
|
||||
scm_display_backtrace_with_highlights (stack, port,
|
||||
SCM_BOOL_F, SCM_BOOL_F,
|
||||
SCM_EOL);
|
||||
scm_newline (port);
|
||||
}
|
||||
|
||||
scm_print_exception (port, frame, tag, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct c_data {
|
||||
void *(*func) (void *);
|
||||
void *data;
|
||||
|
@ -477,11 +516,27 @@ c_body (void *d)
|
|||
static SCM
|
||||
c_handler (void *d, SCM tag, SCM args)
|
||||
{
|
||||
struct c_data *data = (struct c_data *)d;
|
||||
struct c_data *data;
|
||||
|
||||
/* If TAG is `quit', exit() the process. */
|
||||
if (scm_is_eq (tag, scm_from_latin1_symbol ("quit")))
|
||||
exit (scm_exit_status (args));
|
||||
|
||||
data = (struct c_data *)d;
|
||||
data->result = NULL;
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
static SCM
|
||||
pre_unwind_handler (void *error_port, SCM tag, SCM args)
|
||||
{
|
||||
/* Print the exception unless TAG is `quit'. */
|
||||
if (!scm_is_eq (tag, scm_from_latin1_symbol ("quit")))
|
||||
print_exception_and_backtrace (PTR2SCM (error_port), tag, args);
|
||||
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
||||
void *
|
||||
scm_c_with_continuation_barrier (void *(*func) (void *), void *data)
|
||||
{
|
||||
|
@ -490,7 +545,8 @@ scm_c_with_continuation_barrier (void *(*func) (void *), void *data)
|
|||
c_data.data = data;
|
||||
scm_i_with_continuation_barrier (c_body, &c_data,
|
||||
c_handler, &c_data,
|
||||
scm_handle_by_message_noexit, NULL);
|
||||
pre_unwind_handler,
|
||||
SCM2PTR (scm_current_error_port ()));
|
||||
return c_data.result;
|
||||
}
|
||||
|
||||
|
@ -508,6 +564,10 @@ scm_body (void *d)
|
|||
static SCM
|
||||
scm_handler (void *d, SCM tag, SCM args)
|
||||
{
|
||||
/* Print a message. Note that if TAG is `quit', this will exit() the
|
||||
process. */
|
||||
scm_handle_by_message_noexit (NULL, tag, args);
|
||||
|
||||
return SCM_BOOL_F;
|
||||
}
|
||||
|
||||
|
@ -529,7 +589,8 @@ SCM_DEFINE (scm_with_continuation_barrier, "with-continuation-barrier", 1,0,0,
|
|||
scm_data.proc = proc;
|
||||
return scm_i_with_continuation_barrier (scm_body, &scm_data,
|
||||
scm_handler, &scm_data,
|
||||
scm_handle_by_message_noexit, NULL);
|
||||
pre_unwind_handler,
|
||||
SCM2PTR (scm_current_error_port ()));
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
|
@ -55,18 +55,18 @@ scm_c_make_prompt (SCM k, SCM *fp, SCM *sp, scm_t_uint8 *abort_ip,
|
|||
|
||||
/* Only to be called if the SCM_PROMPT_SETJMP returns 1 */
|
||||
SCM
|
||||
scm_i_prompt_pop_abort_args_x (SCM prompt)
|
||||
scm_i_prompt_pop_abort_args_x (SCM vm)
|
||||
{
|
||||
size_t i, n;
|
||||
SCM vals = SCM_EOL;
|
||||
|
||||
n = scm_to_size_t (SCM_PROMPT_REGISTERS (prompt)->sp[0]);
|
||||
n = scm_to_size_t (SCM_VM_DATA (vm)->sp[0]);
|
||||
for (i = 0; i < n; i++)
|
||||
vals = scm_cons (SCM_PROMPT_REGISTERS (prompt)->sp[-(i + 1)], vals);
|
||||
vals = scm_cons (SCM_VM_DATA (vm)->sp[-(i + 1)], vals);
|
||||
|
||||
/* The abort did reset the VM's registers, but then these values
|
||||
were pushed on; so we need to pop them ourselves. */
|
||||
SCM_VM_DATA (scm_the_vm ())->sp -= n + 1;
|
||||
SCM_VM_DATA (vm)->sp -= n + 1;
|
||||
/* FIXME NULLSTACK */
|
||||
|
||||
return vals;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2010, 2011 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
|
||||
|
@ -46,7 +46,7 @@ SCM_INTERNAL SCM scm_c_make_prompt (SCM k, SCM *fp, SCM *sp,
|
|||
scm_t_uint8 escape_only_p,
|
||||
scm_t_int64 vm_cookie,
|
||||
SCM winds);
|
||||
SCM_INTERNAL SCM scm_i_prompt_pop_abort_args_x (SCM prompt);
|
||||
SCM_INTERNAL SCM scm_i_prompt_pop_abort_args_x (SCM vm);
|
||||
|
||||
SCM_INTERNAL void scm_c_abort (SCM vm, SCM tag, size_t n, SCM *argv,
|
||||
scm_t_int64 cookie) SCM_NORETURN;
|
||||
|
|
|
@ -2281,7 +2281,7 @@ scm_allocate_string (size_t len)
|
|||
{
|
||||
scm_c_issue_deprecation_warning
|
||||
("`scm_allocate_string' is deprecated. Use scm_c_make_string instead.");
|
||||
return scm_i_make_string (len, NULL);
|
||||
return scm_i_make_string (len, NULL, 0);
|
||||
}
|
||||
|
||||
SCM_DEFINE (scm_make_keyword_from_dash_symbol, "make-keyword-from-dash-symbol", 1, 0, 0,
|
||||
|
|
|
@ -115,9 +115,8 @@ sysdep_dynl_value (const char *symb, void *handle, const char *subr)
|
|||
|
||||
fptr = lt_dlsym ((lt_dlhandle) handle, symb);
|
||||
if (!fptr)
|
||||
{
|
||||
scm_misc_error (subr, (char *) lt_dlerror (), SCM_EOL);
|
||||
}
|
||||
scm_misc_error (subr, "Symbol not found: ~a",
|
||||
scm_list_1 (scm_from_locale_string (symb)));
|
||||
return fptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -424,7 +424,7 @@ eval (SCM x, SCM env)
|
|||
{
|
||||
/* The prompt exited nonlocally. */
|
||||
proc = handler;
|
||||
args = scm_i_prompt_pop_abort_args_x (prompt);
|
||||
args = scm_i_prompt_pop_abort_args_x (scm_the_vm ());
|
||||
goto apply_proc;
|
||||
}
|
||||
|
||||
|
@ -476,6 +476,21 @@ scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4)
|
|||
return scm_c_vm_run (scm_the_vm (), proc, args, 4);
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5)
|
||||
{
|
||||
SCM args[] = { arg1, arg2, arg3, arg4, arg5 };
|
||||
return scm_c_vm_run (scm_the_vm (), proc, args, 5);
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4, SCM arg5,
|
||||
SCM arg6)
|
||||
{
|
||||
SCM args[] = { arg1, arg2, arg3, arg4, arg5, arg6 };
|
||||
return scm_c_vm_run (scm_the_vm (), proc, args, 6);
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_call_n (SCM proc, SCM *argv, size_t nargs)
|
||||
{
|
||||
|
@ -543,11 +558,7 @@ SCM_DEFINE (scm_nconc2last, "apply:nconc2last", 1, 0, 0,
|
|||
SCM *lloc;
|
||||
SCM_VALIDATE_NONEMPTYLIST (1, lst);
|
||||
lloc = &lst;
|
||||
while (!scm_is_null (SCM_CDR (*lloc))) /* Perhaps should be
|
||||
SCM_NULL_OR_NIL_P, but not
|
||||
needed in 99.99% of cases,
|
||||
and it could seriously hurt
|
||||
performance. - Neil */
|
||||
while (!scm_is_null (SCM_CDR (*lloc)))
|
||||
lloc = SCM_CDRLOC (*lloc);
|
||||
SCM_ASSERT (scm_ilength (SCM_CAR (*lloc)) >= 0, lst, SCM_ARG1, FUNC_NAME);
|
||||
*lloc = SCM_CAR (*lloc);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef SCM_EVAL_H
|
||||
#define SCM_EVAL_H
|
||||
|
||||
/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003,2004,2008,2009,2010
|
||||
/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002,2003,2004,2008,2009,2010,2011
|
||||
* Free Software Foundation, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -68,6 +68,10 @@ SCM_API SCM scm_call_1 (SCM proc, SCM arg1);
|
|||
SCM_API SCM scm_call_2 (SCM proc, SCM arg1, SCM arg2);
|
||||
SCM_API SCM scm_call_3 (SCM proc, SCM arg1, SCM arg2, SCM arg3);
|
||||
SCM_API SCM scm_call_4 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4);
|
||||
SCM_API SCM scm_call_5 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4,
|
||||
SCM arg5);
|
||||
SCM_API SCM scm_call_6 (SCM proc, SCM arg1, SCM arg2, SCM arg3, SCM arg4,
|
||||
SCM arg5, SCM arg6);
|
||||
SCM_API SCM scm_call_n (SCM proc, SCM *argv, size_t nargs);
|
||||
SCM_API SCM scm_apply_0 (SCM proc, SCM args);
|
||||
SCM_API SCM scm_apply_1 (SCM proc, SCM arg1, SCM args);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1996,1997,1998,1999,2000,2001, 2002, 2004, 2006, 2009, 2010, 2011 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
|
||||
|
@ -845,7 +845,6 @@ SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
|
|||
{
|
||||
struct dirent_or_dirent64 de; /* just for sizeof */
|
||||
DIR *ds = (DIR *) SCM_SMOB_DATA_1 (port);
|
||||
size_t namlen;
|
||||
#ifdef NAME_MAX
|
||||
char buf [SCM_MAX (sizeof (de),
|
||||
sizeof (de) - sizeof (de.d_name) + NAME_MAX + 1)];
|
||||
|
@ -865,8 +864,6 @@ SCM_DEFINE (scm_readdir, "readdir", 1, 0, 0,
|
|||
if (! rdent)
|
||||
return SCM_EOF_VAL;
|
||||
|
||||
namlen = NAMLEN (rdent);
|
||||
|
||||
return (rdent ? scm_from_locale_stringn (rdent->d_name, NAMLEN (rdent))
|
||||
: SCM_EOF_VAL);
|
||||
}
|
||||
|
|
|
@ -177,6 +177,34 @@ SCM_DEFINE (scm_pointer_address, "pointer-address", 1, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_pointer_to_scm, "pointer->scm", 1, 0, 0,
|
||||
(SCM pointer),
|
||||
"Unsafely cast @var{pointer} to a Scheme object.\n"
|
||||
"Cross your fingers!")
|
||||
#define FUNC_NAME s_scm_pointer_to_scm
|
||||
{
|
||||
SCM_VALIDATE_POINTER (1, pointer);
|
||||
|
||||
return SCM_PACK ((scm_t_bits) SCM_POINTER_VALUE (pointer));
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_scm_to_pointer, "scm->pointer", 1, 0, 0,
|
||||
(SCM scm),
|
||||
"Return a foreign pointer object with the @code{object-address}\n"
|
||||
"of @var{scm}.")
|
||||
#define FUNC_NAME s_scm_scm_to_pointer
|
||||
{
|
||||
SCM ret;
|
||||
|
||||
ret = scm_from_pointer ((void*) SCM_UNPACK (scm), NULL);
|
||||
if (SCM_NIMP (ret))
|
||||
register_weak_reference (ret, scm);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_pointer_to_bytevector, "pointer->bytevector", 2, 2, 0,
|
||||
(SCM pointer, SCM len, SCM offset, SCM uvec_type),
|
||||
"Return a bytevector aliasing the @var{len} bytes pointed\n"
|
||||
|
@ -327,13 +355,13 @@ SCM_DEFINE (scm_dereference_pointer, "dereference-pointer", 1, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_string_to_pointer, "string->pointer", 1, 0, 0,
|
||||
(SCM string),
|
||||
SCM_DEFINE (scm_string_to_pointer, "string->pointer", 1, 1, 0,
|
||||
(SCM string, SCM encoding),
|
||||
"Return a foreign pointer to a nul-terminated copy of\n"
|
||||
"@var{string} in the current locale encoding. The C\n"
|
||||
"string is freed when the returned foreign pointer\n"
|
||||
"becomes unreachable.\n\n"
|
||||
"This is the Scheme equivalent of @code{scm_to_locale_string}.")
|
||||
"@var{string} in the given @var{encoding}, defaulting to\n"
|
||||
"the current locale encoding. The C string is freed when\n"
|
||||
"the returned foreign pointer becomes unreachable.\n\n"
|
||||
"This is the Scheme equivalent of @code{scm_to_stringn}.")
|
||||
#define FUNC_NAME s_scm_string_to_pointer
|
||||
{
|
||||
SCM_VALIDATE_STRING (1, string);
|
||||
|
@ -341,21 +369,72 @@ SCM_DEFINE (scm_string_to_pointer, "string->pointer", 1, 0, 0,
|
|||
/* XXX: Finalizers slow down libgc; they could be avoided if
|
||||
`scm_to_string' & co. were able to use libgc-allocated memory. */
|
||||
|
||||
if (SCM_UNBNDP (encoding))
|
||||
return scm_from_pointer (scm_to_locale_string (string), free);
|
||||
else
|
||||
{
|
||||
char *enc;
|
||||
SCM ret;
|
||||
|
||||
SCM_VALIDATE_STRING (2, encoding);
|
||||
|
||||
enc = scm_to_locale_string (encoding);
|
||||
scm_dynwind_begin (0);
|
||||
scm_dynwind_free (enc);
|
||||
|
||||
ret = scm_from_pointer
|
||||
(scm_to_stringn (string, NULL, enc,
|
||||
scm_i_get_conversion_strategy (SCM_BOOL_F)),
|
||||
free);
|
||||
|
||||
scm_dynwind_end ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
SCM_DEFINE (scm_pointer_to_string, "pointer->string", 1, 0, 0,
|
||||
(SCM pointer),
|
||||
"Return the string representing the C nul-terminated string\n"
|
||||
"pointed to by @var{pointer}. The C string is assumed to be\n"
|
||||
"in the current locale encoding.\n\n"
|
||||
"This is the Scheme equivalent of @code{scm_from_locale_string}.")
|
||||
SCM_DEFINE (scm_pointer_to_string, "pointer->string", 1, 2, 0,
|
||||
(SCM pointer, SCM length, SCM encoding),
|
||||
"Return the string representing the C string pointed to by\n"
|
||||
"@var{pointer}. If @var{length} is omitted or @code{-1}, the\n"
|
||||
"string is assumed to be nul-terminated. Otherwise\n"
|
||||
"@var{length} is the number of bytes in memory pointed to by\n"
|
||||
"@var{pointer}. The C string is assumed to be in the given\n"
|
||||
"@var{encoding}, defaulting to the current locale encoding.\n\n"
|
||||
"This is the Scheme equivalent of @code{scm_from_stringn}.")
|
||||
#define FUNC_NAME s_scm_pointer_to_string
|
||||
{
|
||||
size_t len;
|
||||
|
||||
SCM_VALIDATE_POINTER (1, pointer);
|
||||
|
||||
return scm_from_locale_string (SCM_POINTER_VALUE (pointer));
|
||||
if (SCM_UNBNDP (length)
|
||||
|| scm_is_true (scm_eqv_p (length, scm_from_int (-1))))
|
||||
len = (size_t)-1;
|
||||
else
|
||||
len = scm_to_size_t (length);
|
||||
|
||||
if (SCM_UNBNDP (encoding))
|
||||
return scm_from_locale_stringn (SCM_POINTER_VALUE (pointer), len);
|
||||
else
|
||||
{
|
||||
char *enc;
|
||||
SCM ret;
|
||||
|
||||
SCM_VALIDATE_STRING (3, encoding);
|
||||
|
||||
enc = scm_to_locale_string (encoding);
|
||||
scm_dynwind_begin (0);
|
||||
scm_dynwind_free (enc);
|
||||
|
||||
ret = scm_from_stringn (SCM_POINTER_VALUE (pointer), len, enc,
|
||||
scm_i_get_conversion_strategy (SCM_BOOL_F));
|
||||
|
||||
scm_dynwind_end ();
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
@ -402,8 +481,24 @@ SCM_DEFINE (scm_alignof, "alignof", 1, 0, 0, (SCM type),
|
|||
/* a pointer */
|
||||
return scm_from_size_t (alignof (void*));
|
||||
else if (scm_is_pair (type))
|
||||
/* a struct, yo */
|
||||
return scm_alignof (scm_car (type));
|
||||
{
|
||||
/* TYPE is a structure. Section 3-3 of the i386, x86_64, PowerPC,
|
||||
and SPARC P.S. of the System V ABI all say: "Aggregates
|
||||
(structures and arrays) and unions assume the alignment of
|
||||
their most strictly aligned component." */
|
||||
size_t max;
|
||||
|
||||
for (max = 0; scm_is_pair (type); type = SCM_CDR (type))
|
||||
{
|
||||
size_t align;
|
||||
|
||||
align = scm_to_size_t (scm_alignof (SCM_CAR (type)));
|
||||
if (align > max)
|
||||
max = align;
|
||||
}
|
||||
|
||||
return scm_from_size_t (max);
|
||||
}
|
||||
else
|
||||
scm_wrong_type_arg (FUNC_NAME, 1, type);
|
||||
}
|
||||
|
@ -861,6 +956,9 @@ unpack (const ffi_type *type, void *loc, SCM x)
|
|||
SCM_VALIDATE_POINTER (1, x);
|
||||
*(void **) loc = SCM_POINTER_VALUE (x);
|
||||
break;
|
||||
case FFI_TYPE_VOID:
|
||||
/* Do nothing. */
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
|
|
@ -72,8 +72,8 @@ SCM_INTERNAL void scm_i_pointer_print (SCM pointer, SCM port,
|
|||
scm_print_state *pstate);
|
||||
|
||||
SCM_INTERNAL SCM scm_dereference_pointer (SCM pointer);
|
||||
SCM_INTERNAL SCM scm_string_to_pointer (SCM string);
|
||||
SCM_INTERNAL SCM scm_pointer_to_string (SCM pointer);
|
||||
SCM_INTERNAL SCM scm_string_to_pointer (SCM string, SCM encoding);
|
||||
SCM_INTERNAL SCM scm_pointer_to_string (SCM pointer, SCM length, SCM encoding);
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ SCM_DEFINE (scm_frame_num_locals, "frame-num-locals", 1, 0, 0,
|
|||
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
|
||||
while (p <= sp)
|
||||
{
|
||||
if (p + 1 < sp && p[1] == (SCM)0)
|
||||
if (p[0] == (SCM)0)
|
||||
/* skip over not-yet-active frame */
|
||||
p += 3;
|
||||
else
|
||||
|
@ -154,7 +154,7 @@ SCM_DEFINE (scm_frame_local_ref, "frame-local-ref", 2, 0, 0,
|
|||
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
|
||||
while (p <= sp)
|
||||
{
|
||||
if (p + 1 < sp && p[1] == (SCM)0)
|
||||
if (p[0] == (SCM)0)
|
||||
/* skip over not-yet-active frame */
|
||||
p += 3;
|
||||
else if (n == i)
|
||||
|
@ -186,7 +186,7 @@ SCM_DEFINE (scm_frame_local_set_x, "frame-local-set!", 3, 0, 0,
|
|||
p = SCM_FRAME_STACK_ADDRESS (SCM_VM_FRAME_FP (frame));
|
||||
while (p <= sp)
|
||||
{
|
||||
if (p + 1 < sp && p[1] == (SCM)0)
|
||||
if (p[0] == (SCM)0)
|
||||
/* skip over not-yet-active frame */
|
||||
p += 3;
|
||||
else if (n == i)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008, 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,1996,1997,1998,1999,2000,2001, 2002, 2003, 2006, 2008, 2009, 2010, 2011 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
|
||||
|
@ -69,10 +69,6 @@ extern unsigned long * __libc_ia64_register_backing_store_base;
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
/* Lock this mutex before doing lazy sweeping.
|
||||
*/
|
||||
scm_i_pthread_mutex_t scm_i_sweep_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
/* Set this to != 0 if every cell that is accessed shall be checked:
|
||||
*/
|
||||
int scm_debug_cell_accesses_p = 0;
|
||||
|
@ -206,23 +202,13 @@ unsigned long scm_gc_ports_collected = 0;
|
|||
static unsigned long protected_obj_count = 0;
|
||||
|
||||
|
||||
SCM_SYMBOL (sym_cells_allocated, "cells-allocated");
|
||||
SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
|
||||
SCM_SYMBOL (sym_heap_size, "heap-size");
|
||||
SCM_SYMBOL (sym_heap_free_size, "heap-free-size");
|
||||
SCM_SYMBOL (sym_heap_total_allocated, "heap-total-allocated");
|
||||
SCM_SYMBOL (sym_mallocated, "bytes-malloced");
|
||||
SCM_SYMBOL (sym_mtrigger, "gc-malloc-threshold");
|
||||
SCM_SYMBOL (sym_heap_segments, "cell-heap-segments");
|
||||
SCM_SYMBOL (sym_gc_time_taken, "gc-time-taken");
|
||||
SCM_SYMBOL (sym_gc_mark_time_taken, "gc-mark-time-taken");
|
||||
SCM_SYMBOL (sym_times, "gc-times");
|
||||
SCM_SYMBOL (sym_cells_marked, "cells-marked");
|
||||
SCM_SYMBOL (sym_cells_marked_conservatively, "cells-marked-conservatively");
|
||||
SCM_SYMBOL (sym_cells_swept, "cells-swept");
|
||||
SCM_SYMBOL (sym_malloc_yield, "malloc-yield");
|
||||
SCM_SYMBOL (sym_cell_yield, "cell-yield");
|
||||
SCM_SYMBOL (sym_heap_allocated_since_gc, "heap-allocated-since-gc");
|
||||
SCM_SYMBOL (sym_protected_objects, "protected-objects");
|
||||
SCM_SYMBOL (sym_total_cells_allocated, "total-cells-allocated");
|
||||
SCM_SYMBOL (sym_times, "gc-times");
|
||||
|
||||
|
||||
/* Number of calls to SCM_NEWCELL since startup. */
|
||||
|
@ -287,33 +273,14 @@ SCM_DEFINE (scm_gc_stats, "gc-stats", 0, 0, 0,
|
|||
total_bytes = GC_get_total_bytes ();
|
||||
gc_times = GC_gc_no;
|
||||
|
||||
/* njrev: can any of these scm_cons's or scm_list_n signal a memory
|
||||
error? If so we need a frame here. */
|
||||
answer =
|
||||
scm_list_n (scm_cons (sym_gc_time_taken, SCM_INUM0),
|
||||
#if 0
|
||||
scm_cons (sym_cells_allocated,
|
||||
scm_from_ulong (local_scm_cells_allocated)),
|
||||
scm_cons (sym_mallocated,
|
||||
scm_from_ulong (local_scm_mallocated)),
|
||||
scm_cons (sym_mtrigger,
|
||||
scm_from_ulong (local_scm_mtrigger)),
|
||||
scm_cons (sym_gc_mark_time_taken,
|
||||
scm_from_ulong (local_scm_gc_mark_time_taken)),
|
||||
scm_cons (sym_cells_marked,
|
||||
scm_from_double (local_scm_gc_cells_marked)),
|
||||
scm_cons (sym_cells_swept,
|
||||
scm_from_double (local_scm_gc_cells_swept)),
|
||||
scm_cons (sym_malloc_yield,
|
||||
scm_from_long (local_scm_gc_malloc_yield_percentage)),
|
||||
scm_cons (sym_cell_yield,
|
||||
scm_from_long (local_scm_gc_cell_yield_percentage)),
|
||||
scm_cons (sym_heap_segments, heap_segs),
|
||||
#endif
|
||||
scm_cons (sym_heap_size, scm_from_size_t (heap_size)),
|
||||
scm_cons (sym_heap_free_size, scm_from_size_t (free_bytes)),
|
||||
scm_cons (sym_heap_total_allocated,
|
||||
scm_from_size_t (total_bytes)),
|
||||
scm_cons (sym_heap_allocated_since_gc,
|
||||
scm_from_size_t (bytes_since_gc)),
|
||||
scm_cons (sym_protected_objects,
|
||||
scm_from_ulong (protected_obj_count)),
|
||||
scm_cons (sym_times, scm_from_size_t (gc_times)),
|
||||
|
@ -377,17 +344,7 @@ SCM_DEFINE (scm_gc, "gc", 0, 0, 0,
|
|||
"no longer accessible.")
|
||||
#define FUNC_NAME s_scm_gc
|
||||
{
|
||||
scm_i_scm_pthread_mutex_lock (&scm_i_sweep_mutex);
|
||||
scm_i_gc ("call");
|
||||
/* njrev: It looks as though other places, e.g. scm_realloc,
|
||||
can call scm_i_gc without acquiring the sweep mutex. Does this
|
||||
matter? Also scm_i_gc (or its descendants) touch the
|
||||
scm_sys_protects, which are protected in some cases
|
||||
(e.g. scm_permobjs above in scm_gc_stats) by a critical section,
|
||||
not by the sweep mutex. Shouldn't all the GC-relevant objects be
|
||||
protected in the same way? */
|
||||
scm_i_pthread_mutex_unlock (&scm_i_sweep_mutex);
|
||||
scm_c_hook_run (&scm_after_gc_c_hook, 0);
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
@ -587,6 +544,23 @@ scm_gc_unregister_roots (SCM *b, unsigned long n)
|
|||
scm_gc_unregister_root (p);
|
||||
}
|
||||
|
||||
static void
|
||||
scm_c_register_gc_callback (void *key, void (*func) (void *, void *),
|
||||
void *data)
|
||||
{
|
||||
if (!key)
|
||||
key = GC_MALLOC_ATOMIC (sizeof (void*));
|
||||
|
||||
GC_REGISTER_FINALIZER_NO_ORDER (key, func, data, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
system_gc_callback (void *key, void *data)
|
||||
{
|
||||
scm_c_register_gc_callback (key, system_gc_callback, data);
|
||||
scm_c_hook_run (&scm_after_gc_c_hook, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -642,6 +616,8 @@ scm_storage_prehistory ()
|
|||
scm_c_hook_init (&scm_before_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
|
||||
scm_c_hook_init (&scm_after_sweep_c_hook, 0, SCM_C_HOOK_NORMAL);
|
||||
scm_c_hook_init (&scm_after_gc_c_hook, 0, SCM_C_HOOK_NORMAL);
|
||||
|
||||
scm_c_register_gc_callback (NULL, system_gc_callback, NULL);
|
||||
}
|
||||
|
||||
scm_i_pthread_mutex_t scm_i_gc_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/* GDB interface for Guile
|
||||
* Copyright (C) 1996,1997,1999,2000,2001,2002,2004,2009
|
||||
* Copyright (C) 1996,1997,1999,2000,2001,2002,2004,2009,2011
|
||||
* Free Software Foundation, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
|
@ -249,14 +249,12 @@ scm_init_gdbint ()
|
|||
|
||||
scm_print_carefully_p = 0;
|
||||
|
||||
port = scm_mkstrport (SCM_INUM0,
|
||||
scm_c_make_string (0, SCM_UNDEFINED),
|
||||
port = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG,
|
||||
s);
|
||||
gdb_output_port = scm_permanent_object (port);
|
||||
|
||||
port = scm_mkstrport (SCM_INUM0,
|
||||
scm_c_make_string (0, SCM_UNDEFINED),
|
||||
port = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_RDNG | SCM_WRTNG,
|
||||
s);
|
||||
gdb_input_port = scm_permanent_object (port);
|
||||
|
|
|
@ -318,6 +318,24 @@ main (int argc, char *argv[])
|
|||
pf ("#define SCM_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER %d /* 0 or 1 */\n",
|
||||
SCM_I_GSC_NEED_BRACES_ON_PTHREAD_MUTEX_INITIALIZER);
|
||||
|
||||
#ifdef HAVE_GC_PTHREAD_CANCEL
|
||||
pf ("#define SCM_HAVE_GC_PTHREAD_CANCEL 1 /* 0 or 1 */\n");
|
||||
#else
|
||||
pf ("#define SCM_HAVE_GC_PTHREAD_CANCEL 0 /* 0 or 1 */\n");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GC_PTHREAD_EXIT
|
||||
pf ("#define SCM_HAVE_GC_PTHREAD_EXIT 1 /* 0 or 1 */\n");
|
||||
#else
|
||||
pf ("#define SCM_HAVE_GC_PTHREAD_EXIT 0 /* 0 or 1 */\n");
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GC_PTHREAD_SIGMASK
|
||||
pf ("#define SCM_HAVE_GC_PTHREAD_SIGMASK 1 /* 0 or 1 */\n");
|
||||
#else
|
||||
pf ("#define SCM_HAVE_GC_PTHREAD_SIGMASK 0 /* 0 or 1 */\n");
|
||||
#endif
|
||||
|
||||
pf ("\n\n/*** File system access ***/\n");
|
||||
|
||||
pf ("/* Define to 1 if `struct dirent64' is available. */\n");
|
||||
|
|
|
@ -670,7 +670,7 @@ SCM_DEFINE (scm_sys_prep_layout_x, "%prep-layout!", 1, 0, 0,
|
|||
SCM_MISC_ERROR ("class object doesn't have enough fields: ~S",
|
||||
scm_list_1 (nfields));
|
||||
|
||||
layout = scm_i_make_string (n, &s);
|
||||
layout = scm_i_make_string (n, &s, 0);
|
||||
i = 0;
|
||||
while (scm_is_pair (getters_n_setters))
|
||||
{
|
||||
|
|
|
@ -51,7 +51,20 @@ modern_snarf () # writes stdout
|
|||
## empty file.
|
||||
echo "/* cpp arguments: $@ */" ;
|
||||
${cpp} -DSCM_MAGIC_SNARF_INITS -DSCM_MAGIC_SNARFER "$@" > ${temp} && cpp_ok_p=true
|
||||
grep "^ *\^ *\^" ${temp} | sed -e "s/ *\^ *\^//g" -e "s/\^ *: *\^/;/g"
|
||||
sed -ne 's/ *\^ *: *\^/\
|
||||
/
|
||||
h
|
||||
s/\n.*//
|
||||
t x
|
||||
d
|
||||
: x
|
||||
s/.*\^ *\^ *\(.*\)/\1;/
|
||||
t y
|
||||
d
|
||||
: y
|
||||
p
|
||||
x
|
||||
D' ${temp}
|
||||
}
|
||||
|
||||
## main
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "libguile/root.h"
|
||||
#include "libguile/vectors.h"
|
||||
#include "libguile/ports.h"
|
||||
#include "libguile/bdw-gc.h"
|
||||
|
||||
#include "libguile/validate.h"
|
||||
#include "libguile/hashtab.h"
|
||||
|
@ -120,6 +121,26 @@ scm_fixup_weak_alist (SCM alist, size_t *removed_items)
|
|||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
vacuum_weak_hash_table (SCM table)
|
||||
{
|
||||
SCM buckets = SCM_HASHTABLE_VECTOR (table);
|
||||
unsigned long k = SCM_SIMPLE_VECTOR_LENGTH (buckets);
|
||||
size_t len = SCM_HASHTABLE_N_ITEMS (table);
|
||||
|
||||
while (k--)
|
||||
{
|
||||
size_t removed;
|
||||
SCM alist = SCM_SIMPLE_VECTOR_REF (buckets, k);
|
||||
alist = scm_fixup_weak_alist (alist, &removed);
|
||||
assert (removed <= len);
|
||||
len -= removed;
|
||||
SCM_SIMPLE_VECTOR_SET (buckets, k, alist);
|
||||
}
|
||||
|
||||
SCM_SET_HASHTABLE_N_ITEMS (table, len);
|
||||
}
|
||||
|
||||
|
||||
/* Packed arguments for `do_weak_bucket_fixup'. */
|
||||
struct t_fixup_args
|
||||
|
@ -397,6 +418,34 @@ SCM_DEFINE (scm_make_hash_table, "make-hash-table", 0, 1, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
static void
|
||||
weak_gc_callback (void *ptr, void *data)
|
||||
{
|
||||
void **weak = ptr;
|
||||
void *val = *weak;
|
||||
|
||||
if (val)
|
||||
{
|
||||
void (*callback) (SCM) = data;
|
||||
|
||||
GC_REGISTER_FINALIZER_NO_ORDER (ptr, weak_gc_callback, data, NULL, NULL);
|
||||
|
||||
callback (PTR2SCM (val));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
scm_c_register_weak_gc_callback (SCM obj, void (*callback) (SCM))
|
||||
{
|
||||
void **weak = GC_MALLOC_ATOMIC (sizeof (void**));
|
||||
|
||||
*weak = SCM2PTR (obj);
|
||||
GC_GENERAL_REGISTER_DISAPPEARING_LINK (weak, SCM2PTR (obj));
|
||||
|
||||
GC_REGISTER_FINALIZER_NO_ORDER (weak, weak_gc_callback, (void*)callback,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 0, 1, 0,
|
||||
(SCM n),
|
||||
"@deffnx {Scheme Procedure} make-weak-value-hash-table size\n"
|
||||
|
@ -407,11 +456,17 @@ SCM_DEFINE (scm_make_weak_key_hash_table, "make-weak-key-hash-table", 0, 1, 0,
|
|||
"would modify regular hash tables. (@pxref{Hash Tables})")
|
||||
#define FUNC_NAME s_scm_make_weak_key_hash_table
|
||||
{
|
||||
SCM ret;
|
||||
|
||||
if (SCM_UNBNDP (n))
|
||||
return make_hash_table (SCM_HASHTABLEF_WEAK_CAR, 0, FUNC_NAME);
|
||||
ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR, 0, FUNC_NAME);
|
||||
else
|
||||
return make_hash_table (SCM_HASHTABLEF_WEAK_CAR,
|
||||
ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR,
|
||||
scm_to_ulong (n), FUNC_NAME);
|
||||
|
||||
scm_c_register_weak_gc_callback (ret, vacuum_weak_hash_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
@ -422,13 +477,17 @@ SCM_DEFINE (scm_make_weak_value_hash_table, "make-weak-value-hash-table", 0, 1,
|
|||
"(@pxref{Hash Tables})")
|
||||
#define FUNC_NAME s_scm_make_weak_value_hash_table
|
||||
{
|
||||
SCM ret;
|
||||
|
||||
if (SCM_UNBNDP (n))
|
||||
return make_hash_table (SCM_HASHTABLEF_WEAK_CDR, 0, FUNC_NAME);
|
||||
ret = make_hash_table (SCM_HASHTABLEF_WEAK_CDR, 0, FUNC_NAME);
|
||||
else
|
||||
{
|
||||
return make_hash_table (SCM_HASHTABLEF_WEAK_CDR,
|
||||
ret = make_hash_table (SCM_HASHTABLEF_WEAK_CDR,
|
||||
scm_to_ulong (n), FUNC_NAME);
|
||||
}
|
||||
|
||||
scm_c_register_weak_gc_callback (ret, vacuum_weak_hash_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
@ -439,16 +498,18 @@ SCM_DEFINE (scm_make_doubly_weak_hash_table, "make-doubly-weak-hash-table", 1, 0
|
|||
"buckets. (@pxref{Hash Tables})")
|
||||
#define FUNC_NAME s_scm_make_doubly_weak_hash_table
|
||||
{
|
||||
SCM ret;
|
||||
|
||||
if (SCM_UNBNDP (n))
|
||||
return make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
|
||||
0,
|
||||
FUNC_NAME);
|
||||
ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
|
||||
0, FUNC_NAME);
|
||||
else
|
||||
{
|
||||
return make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
|
||||
scm_to_ulong (n),
|
||||
FUNC_NAME);
|
||||
}
|
||||
ret = make_hash_table (SCM_HASHTABLEF_WEAK_CAR | SCM_HASHTABLEF_WEAK_CDR,
|
||||
scm_to_ulong (n), FUNC_NAME);
|
||||
|
||||
scm_c_register_weak_gc_callback (ret, vacuum_weak_hash_table);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
@ -651,12 +712,9 @@ scm_hash_fn_create_handle_x (SCM table, SCM obj, SCM init,
|
|||
}
|
||||
SCM_SETCDR (new_bucket, SCM_SIMPLE_VECTOR_REF (buckets, k));
|
||||
SCM_SIMPLE_VECTOR_SET (buckets, k, new_bucket);
|
||||
/* Update element count and maybe rehash the table. The
|
||||
table might have too few entries here since weak hash
|
||||
tables used with the hashx_* functions can not be
|
||||
rehashed after GC.
|
||||
*/
|
||||
SCM_HASHTABLE_INCREMENT (table);
|
||||
|
||||
/* Maybe rehash the table. */
|
||||
if (SCM_HASHTABLE_N_ITEMS (table) < SCM_HASHTABLE_LOWER (table)
|
||||
|| SCM_HASHTABLE_N_ITEMS (table) > SCM_HASHTABLE_UPPER (table))
|
||||
scm_i_rehash (table, hash_fn, closure, FUNC_NAME);
|
||||
|
|
|
@ -766,16 +766,10 @@ compare_u32_strings (SCM s1, SCM s2, SCM locale, const char *func_name)
|
|||
static const char *
|
||||
locale_language ()
|
||||
{
|
||||
/* FIXME: If the locale has been set with 'uselocale',
|
||||
libunistring's uc_locale_language will return the incorrect
|
||||
language: it will return the language appropriate for the global
|
||||
(non-thread-specific) locale.
|
||||
|
||||
There appears to be no portable way to extract the language from
|
||||
the thread-specific locale_t. There is no LANGUAGE capability in
|
||||
nl_langinfo or nl_langinfo_l.
|
||||
|
||||
Thus, uc_locale_language needs to be fixed upstream. */
|
||||
/* Note: If the locale has been set with 'uselocale', uc_locale_language
|
||||
from libunistring versions 0.9.1 and older will return the incorrect
|
||||
(non-thread-specific) locale. This is fixed in versions 0.9.2 and
|
||||
newer. */
|
||||
return uc_locale_language ();
|
||||
}
|
||||
|
||||
|
@ -1113,23 +1107,19 @@ chr_to_case (SCM chr, scm_t_locale c_locale,
|
|||
#define FUNC_NAME func_name
|
||||
{
|
||||
int ret;
|
||||
scm_t_wchar *buf;
|
||||
scm_t_uint32 c;
|
||||
scm_t_uint32 *convbuf;
|
||||
size_t convlen;
|
||||
SCM str, convchar;
|
||||
SCM convchar;
|
||||
|
||||
str = scm_i_make_wide_string (1, &buf);
|
||||
buf[0] = SCM_CHAR (chr);
|
||||
c = SCM_CHAR (chr);
|
||||
|
||||
if (c_locale != NULL)
|
||||
RUN_IN_LOCALE_SECTION (c_locale, ret =
|
||||
u32_locale_tocase ((scm_t_uint32 *) buf, 1,
|
||||
&convbuf,
|
||||
&convlen, func));
|
||||
u32_locale_tocase (&c, 1, &convbuf, &convlen, func));
|
||||
else
|
||||
ret =
|
||||
u32_locale_tocase ((scm_t_uint32 *) buf, 1, &convbuf,
|
||||
&convlen, func);
|
||||
u32_locale_tocase (&c, 1, &convbuf, &convlen, func);
|
||||
|
||||
if (SCM_UNLIKELY (ret != 0))
|
||||
{
|
||||
|
@ -1256,7 +1246,7 @@ str_to_case (SCM str, scm_t_locale c_locale,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
convstr = scm_i_make_wide_string (convlen, &c_buf);
|
||||
convstr = scm_i_make_wide_string (convlen, &c_buf, 0);
|
||||
memcpy (c_buf, c_convstr, convlen * sizeof (scm_t_wchar));
|
||||
free (c_convstr);
|
||||
|
||||
|
@ -1564,11 +1554,14 @@ SCM_DEFINE (scm_nl_langinfo, "nl-langinfo", 1, 1, 0,
|
|||
{
|
||||
char *p;
|
||||
|
||||
/* In this cases, the result is to be interpreted as a list of
|
||||
numbers. If the last item is `CHARS_MAX', it has the special
|
||||
meaning "no more grouping". */
|
||||
/* In this cases, the result is to be interpreted as a list
|
||||
of numbers. If the last item is `CHAR_MAX' or a negative
|
||||
number, it has the special meaning "no more grouping"
|
||||
(negative numbers aren't specified in POSIX but can be
|
||||
used by glibc; see
|
||||
<http://lists.gnu.org/archive/html/bug-guile/2011-02/msg00159.html>). */
|
||||
result = SCM_EOL;
|
||||
for (p = c_result; (*p != '\0') && (*p != CHAR_MAX); p++)
|
||||
for (p = c_result; (*p > 0) && (*p != CHAR_MAX); p++)
|
||||
result = scm_cons (SCM_I_MAKINUM ((int) *p), result);
|
||||
|
||||
{
|
||||
|
@ -1576,7 +1569,7 @@ SCM_DEFINE (scm_nl_langinfo, "nl-langinfo", 1, 1, 0,
|
|||
|
||||
result = scm_reverse_x (result, SCM_EOL);
|
||||
|
||||
if (*p != CHAR_MAX)
|
||||
if (*p == 0)
|
||||
{
|
||||
/* Cyclic grouping information. */
|
||||
if (last_pair != SCM_EOL)
|
||||
|
|
|
@ -157,7 +157,6 @@ typedef struct
|
|||
{
|
||||
int fdes;
|
||||
char *mode;
|
||||
char *name;
|
||||
} stream_body_data;
|
||||
|
||||
/* proc to be called in scope of exception handler stream_handler. */
|
||||
|
@ -165,8 +164,7 @@ static SCM
|
|||
stream_body (void *data)
|
||||
{
|
||||
stream_body_data *body_data = (stream_body_data *) data;
|
||||
SCM port = scm_fdes_to_port (body_data->fdes, body_data->mode,
|
||||
scm_from_locale_string (body_data->name));
|
||||
SCM port = scm_fdes_to_port (body_data->fdes, body_data->mode, SCM_BOOL_F);
|
||||
|
||||
SCM_REVEALED (port) = 1;
|
||||
return port;
|
||||
|
@ -182,21 +180,19 @@ stream_handler (void *data SCM_UNUSED,
|
|||
}
|
||||
|
||||
/* Convert a file descriptor to a port, using scm_fdes_to_port.
|
||||
- NAME is a C string, not a Guile string
|
||||
- set the revealed count for FILE's file descriptor to 1, so
|
||||
that fdes won't be closed when the port object is GC'd.
|
||||
- catch exceptions: allow Guile to be able to start up even
|
||||
if it has been handed bogus stdin/stdout/stderr. replace the
|
||||
bad ports with void ports. */
|
||||
static SCM
|
||||
scm_standard_stream_to_port (int fdes, char *mode, char *name)
|
||||
scm_standard_stream_to_port (int fdes, char *mode)
|
||||
{
|
||||
SCM port;
|
||||
stream_body_data body_data;
|
||||
|
||||
body_data.fdes = fdes;
|
||||
body_data.mode = mode;
|
||||
body_data.name = name;
|
||||
port = scm_internal_catch (SCM_BOOL_T, stream_body, &body_data,
|
||||
stream_handler, NULL);
|
||||
if (scm_is_false (port))
|
||||
|
@ -223,17 +219,11 @@ scm_init_standard_ports ()
|
|||
block buffering for higher performance. */
|
||||
|
||||
scm_set_current_input_port
|
||||
(scm_standard_stream_to_port (0,
|
||||
isatty (0) ? "r0" : "r",
|
||||
"standard input"));
|
||||
(scm_standard_stream_to_port (0, isatty (0) ? "r0" : "r"));
|
||||
scm_set_current_output_port
|
||||
(scm_standard_stream_to_port (1,
|
||||
isatty (1) ? "w0" : "w",
|
||||
"standard output"));
|
||||
(scm_standard_stream_to_port (1, isatty (1) ? "w0" : "w"));
|
||||
scm_set_current_error_port
|
||||
(scm_standard_stream_to_port (2,
|
||||
isatty (2) ? "w0" : "w",
|
||||
"standard error"));
|
||||
(scm_standard_stream_to_port (2, isatty (2) ? "w0" : "w"));
|
||||
}
|
||||
|
||||
|
||||
|
@ -386,17 +376,11 @@ cleanup_for_exit ()
|
|||
}
|
||||
|
||||
void
|
||||
scm_i_init_guile (SCM_STACKITEM *base)
|
||||
scm_i_init_guile (void *base)
|
||||
{
|
||||
if (scm_initialized_p)
|
||||
return;
|
||||
|
||||
if (base == NULL)
|
||||
{
|
||||
fprintf (stderr, "cannot determine stack base!\n");
|
||||
abort ();
|
||||
}
|
||||
|
||||
if (sizeof (mpz_t) > (3 * sizeof (scm_t_bits)))
|
||||
{
|
||||
fprintf (stderr,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef SCM_INIT_H
|
||||
#define SCM_INIT_H
|
||||
|
||||
/* Copyright (C) 1995,1996,1997,2000, 2006, 2008 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,1996,1997,2000, 2006, 2008, 2011 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
|
||||
|
@ -38,7 +38,7 @@ SCM_API void scm_boot_guile (int argc, char **argv,
|
|||
char **argv),
|
||||
void *closure);
|
||||
|
||||
SCM_INTERNAL void scm_i_init_guile (SCM_STACKITEM *base);
|
||||
SCM_INTERNAL void scm_i_init_guile (void *base);
|
||||
|
||||
SCM_API void scm_load_startup_files (void);
|
||||
|
||||
|
|
|
@ -56,6 +56,9 @@ static SCM module_public_interface_var;
|
|||
static SCM module_export_x_var;
|
||||
static SCM default_duplicate_binding_procedures_var;
|
||||
|
||||
/* The #:ensure keyword. */
|
||||
static SCM k_ensure;
|
||||
|
||||
|
||||
static SCM unbound_variable (const char *func, SCM sym)
|
||||
{
|
||||
|
@ -751,6 +754,124 @@ scm_lookup (SCM sym)
|
|||
return var;
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_public_variable (SCM module_name, SCM name)
|
||||
{
|
||||
SCM mod, iface;
|
||||
|
||||
mod = scm_call_3 (scm_variable_ref (resolve_module_var), module_name,
|
||||
k_ensure, SCM_BOOL_F);
|
||||
|
||||
if (scm_is_false (mod))
|
||||
scm_misc_error ("public-lookup", "Module named ~s does not exist",
|
||||
scm_list_1 (module_name));
|
||||
|
||||
iface = scm_module_public_interface (mod);
|
||||
|
||||
if (scm_is_false (iface))
|
||||
scm_misc_error ("public-lookup", "Module ~s has no public interface",
|
||||
scm_list_1 (mod));
|
||||
|
||||
return scm_module_variable (iface, name);
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_private_variable (SCM module_name, SCM name)
|
||||
{
|
||||
SCM mod;
|
||||
|
||||
mod = scm_call_3 (scm_variable_ref (resolve_module_var), module_name,
|
||||
k_ensure, SCM_BOOL_F);
|
||||
|
||||
if (scm_is_false (mod))
|
||||
scm_misc_error ("private-lookup", "Module named ~s does not exist",
|
||||
scm_list_1 (module_name));
|
||||
|
||||
return scm_module_variable (mod, name);
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_public_variable (const char *module_name, const char *name)
|
||||
{
|
||||
return scm_public_variable (convert_module_name (module_name),
|
||||
scm_from_locale_symbol (name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_private_variable (const char *module_name, const char *name)
|
||||
{
|
||||
return scm_private_variable (convert_module_name (module_name),
|
||||
scm_from_locale_symbol (name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_public_lookup (SCM module_name, SCM name)
|
||||
{
|
||||
SCM var;
|
||||
|
||||
var = scm_public_variable (module_name, name);
|
||||
|
||||
if (scm_is_false (var))
|
||||
scm_misc_error ("public-lookup", "No variable bound to ~s in module ~s",
|
||||
scm_list_2 (name, module_name));
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_private_lookup (SCM module_name, SCM name)
|
||||
{
|
||||
SCM var;
|
||||
|
||||
var = scm_private_variable (module_name, name);
|
||||
|
||||
if (scm_is_false (var))
|
||||
scm_misc_error ("private-lookup", "No variable bound to ~s in module ~s",
|
||||
scm_list_2 (name, module_name));
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_public_lookup (const char *module_name, const char *name)
|
||||
{
|
||||
return scm_public_lookup (convert_module_name (module_name),
|
||||
scm_from_locale_symbol (name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_private_lookup (const char *module_name, const char *name)
|
||||
{
|
||||
return scm_private_lookup (convert_module_name (module_name),
|
||||
scm_from_locale_symbol (name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_public_ref (SCM module_name, SCM name)
|
||||
{
|
||||
return scm_variable_ref (scm_public_lookup (module_name, name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_private_ref (SCM module_name, SCM name)
|
||||
{
|
||||
return scm_variable_ref (scm_private_lookup (module_name, name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_public_ref (const char *module_name, const char *name)
|
||||
{
|
||||
return scm_public_ref (convert_module_name (module_name),
|
||||
scm_from_locale_symbol (name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_private_ref (const char *module_name, const char *name)
|
||||
{
|
||||
return scm_private_ref (convert_module_name (module_name),
|
||||
scm_from_locale_symbol (name));
|
||||
}
|
||||
|
||||
SCM
|
||||
scm_c_module_define (SCM module, const char *name, SCM value)
|
||||
{
|
||||
|
@ -903,6 +1024,7 @@ scm_post_boot_init_modules ()
|
|||
default_duplicate_binding_procedures_var =
|
||||
scm_c_lookup ("default-duplicate-binding-procedures");
|
||||
module_public_interface_var = scm_c_lookup ("module-public-interface");
|
||||
k_ensure = scm_from_locale_keyword ("ensure");
|
||||
|
||||
scm_module_system_booted_p = 1;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef SCM_MODULES_H
|
||||
#define SCM_MODULES_H
|
||||
|
||||
/* Copyright (C) 1998, 2000, 2001, 2002, 2003, 2006, 2007, 2008 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1998, 2000, 2001, 2002, 2003, 2006, 2007, 2008, 2011 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
|
||||
|
@ -93,6 +93,21 @@ SCM_API SCM scm_module_define (SCM module, SCM symbol, SCM val);
|
|||
SCM_API SCM scm_module_export (SCM module, SCM symbol_list);
|
||||
SCM_API SCM scm_module_reverse_lookup (SCM module, SCM variable);
|
||||
|
||||
SCM_API SCM scm_public_variable (SCM module_name, SCM name);
|
||||
SCM_API SCM scm_private_variable (SCM module_name, SCM name);
|
||||
SCM_API SCM scm_c_public_variable (const char *module_name, const char *name);
|
||||
SCM_API SCM scm_c_private_variable (const char *module_name, const char *name);
|
||||
|
||||
SCM_API SCM scm_public_lookup (SCM module_name, SCM name);
|
||||
SCM_API SCM scm_private_lookup (SCM module_name, SCM name);
|
||||
SCM_API SCM scm_c_public_lookup (const char *module_name, const char *name);
|
||||
SCM_API SCM scm_c_private_lookup (const char *module_name, const char *name);
|
||||
|
||||
SCM_API SCM scm_public_ref (SCM module_name, SCM name);
|
||||
SCM_API SCM scm_private_ref (SCM module_name, SCM name);
|
||||
SCM_API SCM scm_c_public_ref (const char *module_name, const char *name);
|
||||
SCM_API SCM scm_c_private_ref (const char *module_name, const char *name);
|
||||
|
||||
SCM_API SCM scm_c_resolve_module (const char *name);
|
||||
SCM_API SCM scm_resolve_module (SCM name);
|
||||
SCM_API SCM scm_c_define_module (const char *name,
|
||||
|
|
|
@ -146,7 +146,7 @@ static double atanh (double x) { return 0.5 * log ((1 + x) / (1 - x)); }
|
|||
|
||||
|
||||
#if defined (GUILE_I)
|
||||
#if HAVE_COMPLEX_DOUBLE
|
||||
#if defined HAVE_COMPLEX_DOUBLE
|
||||
|
||||
/* For an SCM object Z which is a complex number (ie. satisfies
|
||||
SCM_COMPLEXP), return its value as a C level "complex double". */
|
||||
|
@ -5668,7 +5668,7 @@ mem2decimal_from_point (SCM result, SCM mem,
|
|||
if (sign == 1)
|
||||
result = scm_product (result, e);
|
||||
else
|
||||
result = scm_divide2real (result, e);
|
||||
result = scm_divide (result, e);
|
||||
|
||||
/* We've seen an exponent, thus the value is implicitly inexact. */
|
||||
x = INEXACT;
|
||||
|
@ -9449,7 +9449,8 @@ SCM_PRIMITIVE_GENERIC (scm_log, "log", 1, 0, 0,
|
|||
{
|
||||
if (SCM_COMPLEXP (z))
|
||||
{
|
||||
#if HAVE_COMPLEX_DOUBLE && HAVE_CLOG && defined (SCM_COMPLEX_VALUE)
|
||||
#if defined HAVE_COMPLEX_DOUBLE && defined HAVE_CLOG \
|
||||
&& defined (SCM_COMPLEX_VALUE)
|
||||
return scm_from_complex_double (clog (SCM_COMPLEX_VALUE (z)));
|
||||
#else
|
||||
double re = SCM_COMPLEX_REAL (z);
|
||||
|
@ -9534,7 +9535,8 @@ SCM_PRIMITIVE_GENERIC (scm_exp, "exp", 1, 0, 0,
|
|||
{
|
||||
if (SCM_COMPLEXP (z))
|
||||
{
|
||||
#if HAVE_COMPLEX_DOUBLE && HAVE_CEXP && defined (SCM_COMPLEX_VALUE)
|
||||
#if defined HAVE_COMPLEX_DOUBLE && defined HAVE_CEXP \
|
||||
&& defined (SCM_COMPLEX_VALUE)
|
||||
return scm_from_complex_double (cexp (SCM_COMPLEX_VALUE (z)));
|
||||
#else
|
||||
return scm_c_make_polar (exp (SCM_COMPLEX_REAL (z)),
|
||||
|
@ -9553,6 +9555,70 @@ SCM_PRIMITIVE_GENERIC (scm_exp, "exp", 1, 0, 0,
|
|||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM_DEFINE (scm_i_exact_integer_sqrt, "exact-integer-sqrt", 1, 0, 0,
|
||||
(SCM k),
|
||||
"Return two exact non-negative integers @var{s} and @var{r}\n"
|
||||
"such that @math{@var{k} = @var{s}^2 + @var{r}} and\n"
|
||||
"@math{@var{s}^2 <= @var{k} < (@var{s} + 1)^2}.\n"
|
||||
"An error is raised if @var{k} is not an exact non-negative integer.\n"
|
||||
"\n"
|
||||
"@lisp\n"
|
||||
"(exact-integer-sqrt 10) @result{} 3 and 1\n"
|
||||
"@end lisp")
|
||||
#define FUNC_NAME s_scm_i_exact_integer_sqrt
|
||||
{
|
||||
SCM s, r;
|
||||
|
||||
scm_exact_integer_sqrt (k, &s, &r);
|
||||
return scm_values (scm_list_2 (s, r));
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
void
|
||||
scm_exact_integer_sqrt (SCM k, SCM *sp, SCM *rp)
|
||||
{
|
||||
if (SCM_LIKELY (SCM_I_INUMP (k)))
|
||||
{
|
||||
scm_t_inum kk = SCM_I_INUM (k);
|
||||
scm_t_inum uu = kk;
|
||||
scm_t_inum ss;
|
||||
|
||||
if (SCM_LIKELY (kk > 0))
|
||||
{
|
||||
do
|
||||
{
|
||||
ss = uu;
|
||||
uu = (ss + kk/ss) / 2;
|
||||
} while (uu < ss);
|
||||
*sp = SCM_I_MAKINUM (ss);
|
||||
*rp = SCM_I_MAKINUM (kk - ss*ss);
|
||||
}
|
||||
else if (SCM_LIKELY (kk == 0))
|
||||
*sp = *rp = SCM_INUM0;
|
||||
else
|
||||
scm_wrong_type_arg_msg ("exact-integer-sqrt", SCM_ARG1, k,
|
||||
"exact non-negative integer");
|
||||
}
|
||||
else if (SCM_LIKELY (SCM_BIGP (k)))
|
||||
{
|
||||
SCM s, r;
|
||||
|
||||
if (mpz_sgn (SCM_I_BIG_MPZ (k)) < 0)
|
||||
scm_wrong_type_arg_msg ("exact-integer-sqrt", SCM_ARG1, k,
|
||||
"exact non-negative integer");
|
||||
s = scm_i_mkbig ();
|
||||
r = scm_i_mkbig ();
|
||||
mpz_sqrtrem (SCM_I_BIG_MPZ (s), SCM_I_BIG_MPZ (r), SCM_I_BIG_MPZ (k));
|
||||
scm_remember_upto_here_1 (k);
|
||||
*sp = scm_i_normbig (s);
|
||||
*rp = scm_i_normbig (r);
|
||||
}
|
||||
else
|
||||
scm_wrong_type_arg_msg ("exact-integer-sqrt", SCM_ARG1, k,
|
||||
"exact non-negative integer");
|
||||
}
|
||||
|
||||
|
||||
SCM_PRIMITIVE_GENERIC (scm_sqrt, "sqrt", 1, 0, 0,
|
||||
(SCM z),
|
||||
"Return the square root of @var{z}. Of the two possible roots\n"
|
||||
|
|
|
@ -289,6 +289,7 @@ SCM_API SCM scm_log (SCM z);
|
|||
SCM_API SCM scm_log10 (SCM z);
|
||||
SCM_API SCM scm_exp (SCM z);
|
||||
SCM_API SCM scm_sqrt (SCM z);
|
||||
SCM_API void scm_exact_integer_sqrt (SCM k, SCM *s, SCM *r);
|
||||
|
||||
SCM_INTERNAL SCM scm_i_min (SCM x, SCM y, SCM rest);
|
||||
SCM_INTERNAL SCM scm_i_max (SCM x, SCM y, SCM rest);
|
||||
|
@ -296,6 +297,7 @@ SCM_INTERNAL SCM scm_i_sum (SCM x, SCM y, SCM rest);
|
|||
SCM_INTERNAL SCM scm_i_difference (SCM x, SCM y, SCM rest);
|
||||
SCM_INTERNAL SCM scm_i_product (SCM x, SCM y, SCM rest);
|
||||
SCM_INTERNAL SCM scm_i_divide (SCM x, SCM y, SCM rest);
|
||||
SCM_INTERNAL SCM scm_i_exact_integer_sqrt (SCM k);
|
||||
|
||||
/* bignum internal functions */
|
||||
SCM_INTERNAL SCM scm_i_mkbig (void);
|
||||
|
|
|
@ -23,12 +23,18 @@
|
|||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <assert.h>
|
||||
#include <alignof.h>
|
||||
|
||||
#include <full-read.h>
|
||||
|
||||
#include "_scm.h"
|
||||
#include "programs.h"
|
||||
#include "objcodes.h"
|
||||
|
@ -44,6 +50,52 @@ verify (((sizeof (SCM_OBJCODE_COOKIE) - 1) & 7) == 0);
|
|||
* Objcode type
|
||||
*/
|
||||
|
||||
static void
|
||||
verify_cookie (char *cookie, struct stat *st, int map_fd, void *map_addr)
|
||||
#define FUNC_NAME "make_objcode_from_file"
|
||||
{
|
||||
/* The cookie ends with a version of the form M.N, where M is the
|
||||
major version and N is the minor version. For this Guile to be
|
||||
able to load an objcode, M must be SCM_OBJCODE_MAJOR_VERSION, and N
|
||||
must be less than or equal to SCM_OBJCODE_MINOR_VERSION. Since N
|
||||
is the last character, we do a strict comparison on all but the
|
||||
last, then a <= on the last one. */
|
||||
if (memcmp (cookie, SCM_OBJCODE_COOKIE, strlen (SCM_OBJCODE_COOKIE) - 1))
|
||||
{
|
||||
SCM args = scm_list_1 (scm_from_latin1_stringn
|
||||
(cookie, strlen (SCM_OBJCODE_COOKIE)));
|
||||
if (map_fd >= 0)
|
||||
{
|
||||
(void) close (map_fd);
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
(void) munmap (map_addr, st->st_size);
|
||||
#endif
|
||||
}
|
||||
scm_misc_error (FUNC_NAME, "bad header on object file: ~s", args);
|
||||
}
|
||||
|
||||
{
|
||||
char minor_version = cookie[strlen (SCM_OBJCODE_COOKIE) - 1];
|
||||
|
||||
if (minor_version > SCM_OBJCODE_MINOR_VERSION_STRING[0])
|
||||
{
|
||||
if (map_fd >= 0)
|
||||
{
|
||||
(void) close (map_fd);
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
(void) munmap (map_addr, st->st_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
scm_misc_error (FUNC_NAME, "objcode minor version too new (~a > ~a)",
|
||||
scm_list_2 (scm_from_latin1_stringn (&minor_version, 1),
|
||||
scm_from_latin1_string
|
||||
(SCM_OBJCODE_MINOR_VERSION_STRING)));
|
||||
}
|
||||
}
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
/* The words in an objcode SCM object are as follows:
|
||||
- scm_tc7_objcode | type | flags
|
||||
- the struct scm_objcode C object
|
||||
|
@ -53,77 +105,91 @@ verify (((sizeof (SCM_OBJCODE_COOKIE) - 1) & 7) == 0);
|
|||
*/
|
||||
|
||||
static SCM
|
||||
make_objcode_by_mmap (int fd)
|
||||
#define FUNC_NAME "make_objcode_by_mmap"
|
||||
make_objcode_from_file (int fd)
|
||||
#define FUNC_NAME "make_objcode_from_file"
|
||||
{
|
||||
int ret;
|
||||
char *addr;
|
||||
/* The SCM_OBJCODE_COOKIE is a string literal, and thus has an extra
|
||||
trailing NUL, hence the - 1. */
|
||||
char cookie[sizeof (SCM_OBJCODE_COOKIE) - 1];
|
||||
struct stat st;
|
||||
SCM sret = SCM_BOOL_F;
|
||||
struct scm_objcode *data;
|
||||
|
||||
ret = fstat (fd, &st);
|
||||
if (ret < 0)
|
||||
SCM_SYSERROR;
|
||||
|
||||
if (st.st_size <= sizeof (struct scm_objcode) + strlen (SCM_OBJCODE_COOKIE))
|
||||
if (st.st_size <= sizeof (struct scm_objcode) + sizeof cookie)
|
||||
scm_misc_error (FUNC_NAME, "object file too small (~a bytes)",
|
||||
scm_list_1 (SCM_I_MAKINUM (st.st_size)));
|
||||
|
||||
addr = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
#ifdef HAVE_SYS_MMAN_H
|
||||
{
|
||||
char *addr;
|
||||
struct scm_objcode *data;
|
||||
|
||||
addr = mmap (0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (addr == MAP_FAILED)
|
||||
{
|
||||
int errno_save = errno;
|
||||
(void) close (fd);
|
||||
errno = errno_save;
|
||||
SCM_SYSERROR;
|
||||
}
|
||||
|
||||
/* The cookie ends with a version of the form M.N, where M is the
|
||||
major version and N is the minor version. For this Guile to be
|
||||
able to load an objcode, M must be SCM_OBJCODE_MAJOR_VERSION, and N
|
||||
must be less than or equal to SCM_OBJCODE_MINOR_VERSION. Since N
|
||||
is the last character, we do a strict comparison on all but the
|
||||
last, then a <= on the last one. */
|
||||
if (memcmp (addr, SCM_OBJCODE_COOKIE, strlen (SCM_OBJCODE_COOKIE) - 1))
|
||||
else
|
||||
{
|
||||
SCM args = scm_list_1 (scm_from_latin1_stringn
|
||||
(addr, strlen (SCM_OBJCODE_COOKIE)));
|
||||
(void) close (fd);
|
||||
(void) munmap (addr, st.st_size);
|
||||
scm_misc_error (FUNC_NAME, "bad header on object file: ~s", args);
|
||||
memcpy (cookie, addr, sizeof cookie);
|
||||
data = (struct scm_objcode *) (addr + sizeof cookie);
|
||||
}
|
||||
|
||||
verify_cookie (cookie, &st, fd, addr);
|
||||
|
||||
|
||||
if (data->len + data->metalen
|
||||
!= (st.st_size - sizeof (*data) - sizeof cookie))
|
||||
{
|
||||
char minor_version = addr[strlen (SCM_OBJCODE_COOKIE) - 1];
|
||||
size_t total_len = sizeof (*data) + data->len + data->metalen;
|
||||
|
||||
if (minor_version > SCM_OBJCODE_MINOR_VERSION_STRING[0])
|
||||
scm_misc_error (FUNC_NAME, "objcode minor version too new (~a > ~a)",
|
||||
scm_list_2 (scm_from_latin1_stringn (&minor_version, 1),
|
||||
scm_from_latin1_string
|
||||
(SCM_OBJCODE_MINOR_VERSION_STRING)));
|
||||
}
|
||||
|
||||
data = (struct scm_objcode*)(addr + strlen (SCM_OBJCODE_COOKIE));
|
||||
|
||||
if (data->len + data->metalen != (st.st_size - sizeof (*data) - strlen (SCM_OBJCODE_COOKIE)))
|
||||
{
|
||||
(void) close (fd);
|
||||
(void) munmap (addr, st.st_size);
|
||||
|
||||
scm_misc_error (FUNC_NAME, "bad length header (~a, ~a)",
|
||||
scm_list_2 (scm_from_size_t (st.st_size),
|
||||
scm_from_uint32 (sizeof (*data) + data->len
|
||||
+ data->metalen)));
|
||||
scm_from_size_t (total_len)));
|
||||
}
|
||||
|
||||
sret = scm_double_cell (SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_MMAP, 0),
|
||||
(scm_t_bits)(addr + strlen (SCM_OBJCODE_COOKIE)),
|
||||
SCM_UNPACK (scm_from_int (fd)), 0);
|
||||
|
||||
/* FIXME: we leak ourselves and the file descriptor. but then again so does
|
||||
dlopen(). */
|
||||
return scm_permanent_object (sret);
|
||||
return scm_permanent_object
|
||||
(scm_double_cell (SCM_MAKE_OBJCODE_TAG (SCM_OBJCODE_TYPE_MMAP, 0),
|
||||
(scm_t_bits)(addr + strlen (SCM_OBJCODE_COOKIE)),
|
||||
SCM_UNPACK (scm_from_int (fd)), 0));
|
||||
}
|
||||
#else
|
||||
{
|
||||
SCM bv = scm_c_make_bytevector (st.st_size - sizeof cookie);
|
||||
|
||||
if (full_read (fd, cookie, sizeof cookie) != sizeof cookie
|
||||
|| full_read (fd, SCM_BYTEVECTOR_CONTENTS (bv),
|
||||
SCM_BYTEVECTOR_LENGTH (bv)) != SCM_BYTEVECTOR_LENGTH (bv))
|
||||
{
|
||||
int errno_save = errno;
|
||||
(void) close (fd);
|
||||
errno = errno_save;
|
||||
SCM_SYSERROR;
|
||||
}
|
||||
|
||||
(void) close (fd);
|
||||
|
||||
verify_cookie (cookie, &st, -1, NULL);
|
||||
|
||||
return scm_bytecode_to_objcode (bv);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
SCM
|
||||
scm_c_make_objcode_slice (SCM parent, const scm_t_uint8 *ptr)
|
||||
#define FUNC_NAME "make-objcode-slice"
|
||||
|
@ -233,7 +299,7 @@ SCM_DEFINE (scm_load_objcode, "load-objcode", 1, 0, 0,
|
|||
free (c_file);
|
||||
if (fd < 0) SCM_SYSERROR;
|
||||
|
||||
return make_objcode_by_mmap (fd);
|
||||
return make_objcode_from_file (fd);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
|
@ -352,7 +352,7 @@ SCM_DEFINE (scm_drain_input, "drain-input", 1, 0, 0,
|
|||
|
||||
if (count)
|
||||
{
|
||||
result = scm_i_make_string (count, &data);
|
||||
result = scm_i_make_string (count, &data, 0);
|
||||
scm_take_from_input_buffers (port, data, count);
|
||||
}
|
||||
else
|
||||
|
@ -522,12 +522,9 @@ static void finalize_port (GC_PTR, GC_PTR);
|
|||
static SCM_C_INLINE_KEYWORD void
|
||||
register_finalizer_for_port (SCM port)
|
||||
{
|
||||
long port_type;
|
||||
GC_finalization_proc prev_finalizer;
|
||||
GC_PTR prev_finalization_data;
|
||||
|
||||
port_type = SCM_TC2PTOBNUM (SCM_CELL_TYPE (port));
|
||||
|
||||
/* Register a finalizer for PORT so that its iconv CDs get freed and
|
||||
optionally its type's `free' function gets called. */
|
||||
GC_REGISTER_FINALIZER_NO_ORDER (SCM2PTR (port), finalize_port, 0,
|
||||
|
@ -661,6 +658,19 @@ scm_i_remove_port (SCM port)
|
|||
scm_port_non_buffer (p);
|
||||
p->putback_buf = NULL;
|
||||
p->putback_buf_size = 0;
|
||||
|
||||
if (p->input_cd != (iconv_t) -1)
|
||||
{
|
||||
iconv_close (p->input_cd);
|
||||
p->input_cd = (iconv_t) -1;
|
||||
}
|
||||
|
||||
if (p->output_cd != (iconv_t) -1)
|
||||
{
|
||||
iconv_close (p->output_cd);
|
||||
p->output_cd = (iconv_t) -1;
|
||||
}
|
||||
|
||||
SCM_SETPTAB_ENTRY (port, 0);
|
||||
|
||||
scm_hashq_remove_x (scm_i_port_weak_hash, port);
|
||||
|
@ -1929,9 +1939,8 @@ SCM_DEFINE (scm_set_port_column_x, "set-port-column!", 2, 0, 0,
|
|||
|
||||
SCM_DEFINE (scm_port_filename, "port-filename", 1, 0, 0,
|
||||
(SCM port),
|
||||
"Return the filename associated with @var{port}. This function returns\n"
|
||||
"the strings \"standard input\", \"standard output\" and \"standard error\"\n"
|
||||
"when called on the current input, output and error ports respectively.")
|
||||
"Return the filename associated with @var{port}, or @code{#f}\n"
|
||||
"if no filename is associated with the port.")
|
||||
#define FUNC_NAME s_scm_port_filename
|
||||
{
|
||||
port = SCM_COERCE_OUTPORT (port);
|
||||
|
@ -2099,6 +2108,7 @@ SCM_DEFINE (scm_set_port_encoding_x, "set-port-encoding!", 2, 0, 0,
|
|||
|
||||
enc_str = scm_to_locale_string (enc);
|
||||
scm_i_set_port_encoding_x (port, enc_str);
|
||||
free (enc_str);
|
||||
|
||||
return SCM_UNSPECIFIED;
|
||||
}
|
||||
|
|
|
@ -1713,12 +1713,10 @@ SCM_DEFINE (scm_nice, "nice", 1, 0, 0,
|
|||
"The return value is unspecified.")
|
||||
#define FUNC_NAME s_scm_nice
|
||||
{
|
||||
int nice_value;
|
||||
|
||||
/* nice() returns "prio-NZERO" on success or -1 on error, but -1 can arise
|
||||
from "prio-NZERO", so an error must be detected from errno changed */
|
||||
errno = 0;
|
||||
nice_value = nice (scm_to_int (incr));
|
||||
nice (scm_to_int (incr));
|
||||
if (errno != 0)
|
||||
SCM_SYSERROR;
|
||||
|
||||
|
|
185
libguile/print.c
185
libguile/print.c
|
@ -309,15 +309,10 @@ print_circref (SCM port, scm_print_state *pstate, SCM ref)
|
|||
/* Print the name of a symbol. */
|
||||
|
||||
static int
|
||||
quote_keywordish_symbol (SCM symbol)
|
||||
quote_keywordish_symbols (void)
|
||||
{
|
||||
SCM option;
|
||||
SCM option = SCM_PRINT_KEYWORD_STYLE;
|
||||
|
||||
if (scm_i_symbol_ref (symbol, 0) != ':'
|
||||
&& scm_i_symbol_ref (symbol, scm_i_symbol_length (symbol) - 1) != ':')
|
||||
return 0;
|
||||
|
||||
option = SCM_PRINT_KEYWORD_STYLE;
|
||||
if (scm_is_false (option))
|
||||
return 0;
|
||||
if (scm_is_eq (option, sym_reader))
|
||||
|
@ -325,93 +320,116 @@ quote_keywordish_symbol (SCM symbol)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
scm_i_print_symbol_name (SCM str, SCM port)
|
||||
{
|
||||
/* This points to the first character that has not yet been written to the
|
||||
* port. */
|
||||
size_t pos = 0;
|
||||
/* This points to the character we're currently looking at. */
|
||||
size_t end;
|
||||
/* If the name contains weird characters, we'll escape them with
|
||||
* backslashes and set this flag; it indicates that we should surround the
|
||||
* name with "#{" and "}#". */
|
||||
int weird = 0;
|
||||
/* Backslashes are not sufficient to make a name weird, but if a name is
|
||||
* weird because of other characters, backslahes need to be escaped too.
|
||||
* The first time we see a backslash, we set maybe_weird, and mw_pos points
|
||||
* to the backslash. Then if the name turns out to be weird, we re-process
|
||||
* everything starting from mw_pos.
|
||||
* We could instead make backslashes always weird. This is not necessary
|
||||
* to ensure that the output is (read)-able, but it would make this code
|
||||
* simpler and faster. */
|
||||
int maybe_weird = 0;
|
||||
size_t mw_pos = 0;
|
||||
size_t len = scm_i_symbol_length (str);
|
||||
scm_t_wchar str0 = scm_i_symbol_ref (str, 0);
|
||||
#define INITIAL_IDENTIFIER_MASK \
|
||||
(UC_CATEGORY_MASK_Lu | UC_CATEGORY_MASK_Ll | UC_CATEGORY_MASK_Lt \
|
||||
| UC_CATEGORY_MASK_Lm | UC_CATEGORY_MASK_Lo | UC_CATEGORY_MASK_Mn \
|
||||
| UC_CATEGORY_MASK_Nl | UC_CATEGORY_MASK_No | UC_CATEGORY_MASK_Pd \
|
||||
| UC_CATEGORY_MASK_Pc | UC_CATEGORY_MASK_Po | UC_CATEGORY_MASK_Sc \
|
||||
| UC_CATEGORY_MASK_Sm | UC_CATEGORY_MASK_Sk | UC_CATEGORY_MASK_So \
|
||||
| UC_CATEGORY_MASK_Co)
|
||||
|
||||
if (len == 0 || str0 == '\'' || str0 == '`' || str0 == ','
|
||||
|| quote_keywordish_symbol (str)
|
||||
|| (str0 == '.' && len == 1)
|
||||
|| scm_is_true (scm_i_string_to_number (scm_symbol_to_string (str), 10)))
|
||||
#define SUBSEQUENT_IDENTIFIER_MASK \
|
||||
(INITIAL_IDENTIFIER_MASK \
|
||||
| UC_CATEGORY_MASK_Nd | UC_CATEGORY_MASK_Mc | UC_CATEGORY_MASK_Me)
|
||||
|
||||
static int
|
||||
symbol_has_extended_read_syntax (SCM sym)
|
||||
{
|
||||
scm_lfwrite ("#{", 2, port);
|
||||
weird = 1;
|
||||
size_t pos, len = scm_i_symbol_length (sym);
|
||||
scm_t_wchar c;
|
||||
|
||||
/* The empty symbol. */
|
||||
if (len == 0)
|
||||
return 1;
|
||||
|
||||
c = scm_i_symbol_ref (sym, 0);
|
||||
|
||||
/* Single dot; conflicts with dotted-pair notation. */
|
||||
if (len == 1 && c == '.')
|
||||
return 1;
|
||||
|
||||
/* Other initial-character constraints. */
|
||||
if (c == '\'' || c == '`' || c == ',' || c == '"' || c == ';' || c == '#')
|
||||
return 1;
|
||||
|
||||
/* Keywords can be identified by trailing colons too. */
|
||||
if (c == ':' || scm_i_symbol_ref (sym, len - 1) == ':')
|
||||
return quote_keywordish_symbols ();
|
||||
|
||||
/* Number-ish symbols. */
|
||||
if (scm_is_true (scm_i_string_to_number (scm_symbol_to_string (sym), 10)))
|
||||
return 1;
|
||||
|
||||
/* Other disallowed first characters. */
|
||||
if (!uc_is_general_category_withtable (c, INITIAL_IDENTIFIER_MASK))
|
||||
return 1;
|
||||
|
||||
/* Otherwise, any character that's in the identifier category mask is
|
||||
fine to pass through as-is, provided it's not one of the ASCII
|
||||
delimiters like `;'. */
|
||||
for (pos = 1; pos < len; pos++)
|
||||
{
|
||||
c = scm_i_symbol_ref (sym, pos);
|
||||
if (!uc_is_general_category_withtable (c, SUBSEQUENT_IDENTIFIER_MASK))
|
||||
return 1;
|
||||
else if (c == '"' || c == ';' || c == '#')
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (end = pos; end < len; ++end)
|
||||
switch (scm_i_symbol_ref (str, end))
|
||||
{
|
||||
#ifdef BRACKETS_AS_PARENS
|
||||
case '[':
|
||||
case ']':
|
||||
#endif
|
||||
case '(':
|
||||
case ')':
|
||||
case '"':
|
||||
case ';':
|
||||
case '#':
|
||||
case SCM_WHITE_SPACES:
|
||||
case SCM_LINE_INCREMENTORS:
|
||||
weird_handler:
|
||||
if (maybe_weird)
|
||||
{
|
||||
end = mw_pos;
|
||||
maybe_weird = 0;
|
||||
return 0;
|
||||
}
|
||||
if (!weird)
|
||||
|
||||
static void
|
||||
print_normal_symbol (SCM sym, SCM port)
|
||||
{
|
||||
scm_display (scm_symbol_to_string (sym), port);
|
||||
}
|
||||
|
||||
static void
|
||||
print_extended_symbol (SCM sym, SCM port)
|
||||
{
|
||||
size_t pos, len;
|
||||
scm_t_string_failed_conversion_handler strategy;
|
||||
|
||||
len = scm_i_symbol_length (sym);
|
||||
strategy = scm_i_get_conversion_strategy (port);
|
||||
|
||||
scm_lfwrite ("#{", 2, port);
|
||||
weird = 1;
|
||||
}
|
||||
if (pos < end)
|
||||
scm_lfwrite_substr (scm_symbol_to_string (str), pos, end, port);
|
||||
|
||||
for (pos = 0; pos < len; pos++)
|
||||
{
|
||||
char buf[2];
|
||||
buf[0] = '\\';
|
||||
buf[1] = (char) (unsigned char) scm_i_symbol_ref (str, end);
|
||||
scm_lfwrite (buf, 2, port);
|
||||
}
|
||||
pos = end + 1;
|
||||
break;
|
||||
case '\\':
|
||||
if (weird)
|
||||
goto weird_handler;
|
||||
if (!maybe_weird)
|
||||
scm_t_wchar c = scm_i_symbol_ref (sym, pos);
|
||||
|
||||
if (uc_is_general_category_withtable (c,
|
||||
SUBSEQUENT_IDENTIFIER_MASK
|
||||
| UC_CATEGORY_MASK_Zs))
|
||||
{
|
||||
maybe_weird = 1;
|
||||
mw_pos = pos;
|
||||
if (!display_character (c, port, strategy))
|
||||
scm_encoding_error ("print_extended_symbol", errno,
|
||||
"cannot convert to output locale",
|
||||
port, SCM_MAKE_CHAR (c));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
else
|
||||
{
|
||||
display_string ("\\x", 1, 2, port, iconveh_question_mark);
|
||||
scm_intprint (c, 16, port);
|
||||
display_character (';', port, iconveh_question_mark);
|
||||
}
|
||||
if (pos < end)
|
||||
scm_lfwrite_substr (scm_symbol_to_string (str), pos, end, port);
|
||||
if (weird)
|
||||
}
|
||||
|
||||
scm_lfwrite ("}#", 2, port);
|
||||
}
|
||||
|
||||
/* FIXME: allow R6RS hex escapes instead of #{...}#. */
|
||||
void
|
||||
scm_i_print_symbol_name (SCM sym, SCM port)
|
||||
{
|
||||
if (symbol_has_extended_read_syntax (sym))
|
||||
print_extended_symbol (sym, port);
|
||||
else
|
||||
print_normal_symbol (sym, port);
|
||||
}
|
||||
|
||||
void
|
||||
scm_print_symbol_name (const char *str, size_t len, SCM port)
|
||||
{
|
||||
|
@ -862,6 +880,8 @@ display_string (const void *str, int narrow_p,
|
|||
|
||||
if (SCM_UNLIKELY (done == (size_t) -1))
|
||||
{
|
||||
int errno_save = errno;
|
||||
|
||||
/* Reset the `iconv' state. */
|
||||
iconv (pt->output_cd, NULL, NULL, NULL, NULL);
|
||||
|
||||
|
@ -873,7 +893,7 @@ display_string (const void *str, int narrow_p,
|
|||
codepoints_read = offsets[input - utf8_buf] - printed;
|
||||
printed += codepoints_read;
|
||||
|
||||
if (errno == EILSEQ &&
|
||||
if (errno_save == EILSEQ &&
|
||||
strategy != SCM_FAILED_CONVERSION_ERROR)
|
||||
{
|
||||
/* Conversion failed somewhere in INPUT and we want to
|
||||
|
@ -1282,8 +1302,7 @@ SCM_DEFINE (scm_simple_format, "simple-format", 2, 0, 1,
|
|||
else if (scm_is_false (destination))
|
||||
{
|
||||
fReturnString = 1;
|
||||
port = scm_mkstrport (SCM_INUM0,
|
||||
scm_make_string (SCM_INUM0, SCM_UNDEFINED),
|
||||
port = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG,
|
||||
FUNC_NAME);
|
||||
destination = port;
|
||||
|
|
|
@ -149,7 +149,8 @@ SCM_PRIMITIVE_GENERIC (scm_setter, "setter", 1, 0, 0,
|
|||
SCM_GASSERT1 (SCM_STRUCTP (proc), g_scm_setter, proc, SCM_ARG1, FUNC_NAME);
|
||||
if (SCM_STRUCT_SETTER_P (proc))
|
||||
return SCM_STRUCT_SETTER (proc);
|
||||
if (SCM_PUREGENERICP (proc))
|
||||
if (SCM_PUREGENERICP (proc)
|
||||
&& SCM_IS_A_P (proc, scm_class_generic_with_setter))
|
||||
/* FIXME: might not be an accessor */
|
||||
return SCM_GENERIC_SETTER (proc);
|
||||
SCM_WTA_DISPATCH_1 (g_scm_setter, proc, SCM_ARG1, FUNC_NAME);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#ifndef SCM_PTHREADS_THREADS_H
|
||||
#define SCM_PTHREADS_THREADS_H
|
||||
|
||||
/* Copyright (C) 2002, 2005, 2006 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2002, 2005, 2006, 2011 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
|
||||
|
@ -29,24 +29,39 @@
|
|||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
|
||||
/* `libgc' intercepts pthread calls by defining wrapping macros. */
|
||||
/* `libgc' defines wrapper procedures for pthread calls. */
|
||||
#include "libguile/bdw-gc.h"
|
||||
|
||||
/* Threads
|
||||
*/
|
||||
#define scm_i_pthread_t pthread_t
|
||||
#define scm_i_pthread_self pthread_self
|
||||
#define scm_i_pthread_create pthread_create
|
||||
#define scm_i_pthread_detach pthread_detach
|
||||
#define scm_i_pthread_create GC_pthread_create
|
||||
#define scm_i_pthread_detach GC_pthread_detach
|
||||
|
||||
#if SCM_HAVE_GC_PTHREAD_EXIT
|
||||
#define scm_i_pthread_exit GC_pthread_exit
|
||||
#else
|
||||
#define scm_i_pthread_exit pthread_exit
|
||||
#endif
|
||||
|
||||
#if SCM_HAVE_GC_PTHREAD_CANCEL
|
||||
#define scm_i_pthread_cancel GC_pthread_cancel
|
||||
#else
|
||||
#define scm_i_pthread_cancel pthread_cancel
|
||||
#endif
|
||||
|
||||
#define scm_i_pthread_cleanup_push pthread_cleanup_push
|
||||
#define scm_i_pthread_cleanup_pop pthread_cleanup_pop
|
||||
#define scm_i_sched_yield sched_yield
|
||||
|
||||
/* Signals
|
||||
*/
|
||||
#if SCM_HAVE_GC_PTHREAD_SIGMASK
|
||||
#define scm_i_pthread_sigmask GC_pthread_sigmask
|
||||
#else
|
||||
#define scm_i_pthread_sigmask pthread_sigmask
|
||||
#endif
|
||||
|
||||
/* Mutexes
|
||||
*/
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2009, 2010, 2011 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
|
||||
|
@ -136,7 +136,7 @@ bip_seek (SCM port, scm_t_off offset, int whence)
|
|||
/* Fall through. */
|
||||
|
||||
case SEEK_SET:
|
||||
if (c_port->read_buf + offset < c_port->read_end)
|
||||
if (c_port->read_buf + offset <= c_port->read_end)
|
||||
{
|
||||
c_port->read_pos = c_port->read_buf + offset;
|
||||
c_result = offset;
|
||||
|
@ -1221,6 +1221,46 @@ SCM_DEFINE (scm_i_make_transcoded_port,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
/* Textual I/O */
|
||||
|
||||
SCM_DEFINE (scm_get_string_n_x,
|
||||
"get-string-n!", 4, 0, 0,
|
||||
(SCM port, SCM str, SCM start, SCM count),
|
||||
"Read up to @var{count} characters from @var{port} into "
|
||||
"@var{str}, starting at @var{start}. If no characters "
|
||||
"can be read before the end of file is encountered, the end "
|
||||
"of file object is returned. Otherwise, the number of "
|
||||
"characters read is returned.")
|
||||
#define FUNC_NAME s_scm_get_string_n_x
|
||||
{
|
||||
size_t c_start, c_count, c_len, c_end, j;
|
||||
scm_t_wchar c;
|
||||
|
||||
SCM_VALIDATE_OPINPORT (1, port);
|
||||
SCM_VALIDATE_STRING (2, str);
|
||||
c_len = scm_c_string_length (str);
|
||||
c_start = scm_to_size_t (start);
|
||||
c_count = scm_to_size_t (count);
|
||||
c_end = c_start + c_count;
|
||||
|
||||
if (SCM_UNLIKELY (c_end > c_len))
|
||||
scm_out_of_range (FUNC_NAME, count);
|
||||
|
||||
for (j = c_start; j < c_end; j++)
|
||||
{
|
||||
c = scm_getc (port);
|
||||
if (c == EOF)
|
||||
{
|
||||
size_t chars_read = j - c_start;
|
||||
return chars_read == 0 ? SCM_EOF_VAL : scm_from_size_t (chars_read);
|
||||
}
|
||||
scm_c_string_set_x (str, j, SCM_MAKE_CHAR (c));
|
||||
}
|
||||
return count;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
||||
/* Initialization. */
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef SCM_R6RS_PORTS_H
|
||||
#define SCM_R6RS_PORTS_H
|
||||
|
||||
/* Copyright (C) 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 2009, 2010, 2011 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
|
||||
|
@ -38,6 +38,7 @@ SCM_API SCM scm_put_u8 (SCM, SCM);
|
|||
SCM_API SCM scm_put_bytevector (SCM, SCM, SCM, SCM);
|
||||
SCM_API SCM scm_open_bytevector_output_port (SCM);
|
||||
SCM_API SCM scm_make_custom_binary_output_port (SCM, SCM, SCM, SCM, SCM);
|
||||
SCM_API SCM scm_get_string_n_x (SCM, SCM, SCM, SCM);
|
||||
|
||||
SCM_API void scm_init_r6rs_ports (void);
|
||||
SCM_INTERNAL void scm_register_r6rs_ports (void);
|
||||
|
|
133
libguile/read.c
133
libguile/read.c
|
@ -516,7 +516,7 @@ scm_read_string (int chr, SCM port)
|
|||
unsigned c_str_len = 0;
|
||||
scm_t_wchar c;
|
||||
|
||||
str = scm_i_make_string (READER_STRING_BUFFER_SIZE, NULL);
|
||||
str = scm_i_make_string (READER_STRING_BUFFER_SIZE, NULL, 0);
|
||||
while ('"' != (c = scm_getc (port)))
|
||||
{
|
||||
if (c == EOF)
|
||||
|
@ -528,7 +528,7 @@ scm_read_string (int chr, SCM port)
|
|||
|
||||
if (c_str_len + 1 >= scm_i_string_length (str))
|
||||
{
|
||||
SCM addy = scm_i_make_string (READER_STRING_BUFFER_SIZE, NULL);
|
||||
SCM addy = scm_i_make_string (READER_STRING_BUFFER_SIZE, NULL, 0);
|
||||
|
||||
str = scm_string_append (scm_list_2 (str, addy));
|
||||
}
|
||||
|
@ -1116,13 +1116,9 @@ scm_read_scsh_block_comment (scm_t_wchar chr, SCM port)
|
|||
{
|
||||
int bang_seen = 0;
|
||||
|
||||
/* We can use the get_byte here because there is no need to get the
|
||||
locale correct when reading comments. This presumes that
|
||||
hash and exclamation points always represent themselves no
|
||||
matter what the source encoding is.*/
|
||||
for (;;)
|
||||
{
|
||||
int c = scm_get_byte_or_eof (port);
|
||||
int c = scm_getc (port);
|
||||
|
||||
if (c == EOF)
|
||||
scm_i_input_error ("skip_block_comment", port,
|
||||
|
@ -1234,9 +1230,9 @@ scm_read_extended_symbol (scm_t_wchar chr, SCM port)
|
|||
#{This is all a symbol name}#
|
||||
|
||||
So here, CHR is expected to be `{'. */
|
||||
int saw_brace = 0, finished = 0;
|
||||
int saw_brace = 0;
|
||||
size_t len = 0;
|
||||
SCM buf = scm_i_make_string (1024, NULL);
|
||||
SCM buf = scm_i_make_string (1024, NULL, 0);
|
||||
|
||||
buf = scm_i_string_start_writing (buf);
|
||||
|
||||
|
@ -1246,18 +1242,55 @@ scm_read_extended_symbol (scm_t_wchar chr, SCM port)
|
|||
{
|
||||
if (chr == '#')
|
||||
{
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
saw_brace = 0;
|
||||
scm_i_string_set_x (buf, len++, '}');
|
||||
scm_i_string_set_x (buf, len++, chr);
|
||||
}
|
||||
}
|
||||
else if (chr == '}')
|
||||
|
||||
if (chr == '}')
|
||||
saw_brace = 1;
|
||||
else if (chr == '\\')
|
||||
{
|
||||
/* It used to be that print.c would print extended-read-syntax
|
||||
symbols with backslashes before "non-standard" chars, but
|
||||
this routine wouldn't do anything with those escapes.
|
||||
Bummer. What we've done is to change print.c to output
|
||||
R6RS hex escapes for those characters, relying on the fact
|
||||
that the extended read syntax would never put a `\' before
|
||||
an `x'. For now, we just ignore other instances of
|
||||
backslash in the string. */
|
||||
switch ((chr = scm_getc (port)))
|
||||
{
|
||||
case EOF:
|
||||
goto done;
|
||||
case 'x':
|
||||
{
|
||||
scm_t_wchar c;
|
||||
|
||||
SCM_READ_HEX_ESCAPE (10, ';');
|
||||
scm_i_string_set_x (buf, len++, c);
|
||||
break;
|
||||
|
||||
str_eof:
|
||||
chr = EOF;
|
||||
goto done;
|
||||
|
||||
bad_escaped:
|
||||
scm_i_string_stop_writing ();
|
||||
scm_i_input_error ("scm_read_extended_symbol", port,
|
||||
"illegal character in escape sequence: ~S",
|
||||
scm_list_1 (SCM_MAKE_CHAR (c)));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
scm_i_string_set_x (buf, len++, chr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
scm_i_string_set_x (buf, len++, chr);
|
||||
|
||||
|
@ -1266,16 +1299,18 @@ scm_read_extended_symbol (scm_t_wchar chr, SCM port)
|
|||
SCM addy;
|
||||
|
||||
scm_i_string_stop_writing ();
|
||||
addy = scm_i_make_string (1024, NULL);
|
||||
addy = scm_i_make_string (1024, NULL, 0);
|
||||
buf = scm_string_append (scm_list_2 (buf, addy));
|
||||
len = 0;
|
||||
buf = scm_i_string_start_writing (buf);
|
||||
}
|
||||
|
||||
if (finished)
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
scm_i_string_stop_writing ();
|
||||
if (chr == EOF)
|
||||
scm_i_input_error ("scm_read_extended_symbol", port,
|
||||
"end of file while reading symbol", SCM_EOL);
|
||||
|
||||
return (scm_string_to_symbol (scm_c_substring (buf, 0, len)));
|
||||
}
|
||||
|
@ -1333,6 +1368,7 @@ scm_read_sharp (scm_t_wchar chr, SCM port)
|
|||
case 's':
|
||||
case 'u':
|
||||
case 'f':
|
||||
case 'c':
|
||||
/* This one may return either a boolean or an SRFI-4 vector. */
|
||||
return (scm_read_srfi4_vector (chr, port));
|
||||
case 'v':
|
||||
|
@ -1352,7 +1388,6 @@ scm_read_sharp (scm_t_wchar chr, SCM port)
|
|||
#if SCM_ENABLE_DEPRECATED
|
||||
/* See below for 'i' and 'e'. */
|
||||
case 'a':
|
||||
case 'c':
|
||||
case 'y':
|
||||
case 'h':
|
||||
case 'l':
|
||||
|
@ -1654,6 +1689,7 @@ scm_get_hash_procedure (int c)
|
|||
char *
|
||||
scm_i_scan_for_encoding (SCM port)
|
||||
{
|
||||
scm_t_port *pt;
|
||||
char header[SCM_ENCODING_SEARCH_SIZE+1];
|
||||
size_t bytes_read, encoding_length, i;
|
||||
char *encoding = NULL;
|
||||
|
@ -1661,15 +1697,46 @@ scm_i_scan_for_encoding (SCM port)
|
|||
char *pos, *encoding_start;
|
||||
int in_comment;
|
||||
|
||||
pt = SCM_PTAB_ENTRY (port);
|
||||
|
||||
if (pt->rw_active == SCM_PORT_WRITE)
|
||||
scm_flush (port);
|
||||
|
||||
if (pt->rw_random)
|
||||
pt->rw_active = SCM_PORT_READ;
|
||||
|
||||
if (pt->read_pos == pt->read_end)
|
||||
{
|
||||
/* We can use the read buffer, and thus avoid a seek. */
|
||||
if (scm_fill_input (port) == EOF)
|
||||
return NULL;
|
||||
|
||||
bytes_read = pt->read_end - pt->read_pos;
|
||||
if (bytes_read > SCM_ENCODING_SEARCH_SIZE)
|
||||
bytes_read = SCM_ENCODING_SEARCH_SIZE;
|
||||
|
||||
if (bytes_read <= 1)
|
||||
/* An unbuffered port -- don't scan. */
|
||||
return NULL;
|
||||
|
||||
memcpy (header, pt->read_pos, bytes_read);
|
||||
header[bytes_read] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try to read some bytes and then seek back. Not all ports
|
||||
support seeking back; and indeed some file ports (like
|
||||
/dev/urandom) will succeed on an lseek (fd, 0, SEEK_CUR)---the
|
||||
check performed by SCM_FPORT_FDES---but fail to seek
|
||||
backwards. Hence this block comes second. We prefer to use
|
||||
the read buffer in-place. */
|
||||
if (SCM_FPORTP (port) && !SCM_FDES_RANDOM_P (SCM_FPORT_FDES (port)))
|
||||
/* PORT is a non-seekable file port (e.g., as created by Bash when using
|
||||
"guile <(echo '(display "hello")')") so bail out. */
|
||||
return NULL;
|
||||
|
||||
bytes_read = scm_c_read (port, header, SCM_ENCODING_SEARCH_SIZE);
|
||||
header[bytes_read] = '\0';
|
||||
|
||||
scm_seek (port, scm_from_int (0), scm_from_int (SEEK_SET));
|
||||
}
|
||||
|
||||
if (bytes_read > 3
|
||||
&& header[0] == '\xef' && header[1] == '\xbb' && header[2] == '\xbf')
|
||||
|
@ -1718,22 +1785,26 @@ scm_i_scan_for_encoding (SCM port)
|
|||
pos = encoding_start;
|
||||
while (pos >= header)
|
||||
{
|
||||
if (*pos == '\n')
|
||||
{
|
||||
/* This wasn't in a semicolon comment. Check for a
|
||||
hash-bang comment. */
|
||||
char *beg = strstr (header, "#!");
|
||||
char *end = strstr (header, "!#");
|
||||
if (beg < encoding_start && encoding_start + encoding_length < end)
|
||||
in_comment = 1;
|
||||
break;
|
||||
}
|
||||
if (*pos == ';')
|
||||
{
|
||||
in_comment = 1;
|
||||
break;
|
||||
}
|
||||
else if (*pos == '\n' || pos == header)
|
||||
{
|
||||
/* This wasn't in a semicolon comment. Check for a
|
||||
hash-bang comment. */
|
||||
char *beg = strstr (header, "#!");
|
||||
char *end = strstr (header, "!#");
|
||||
if (beg < encoding_start && encoding_start + encoding_length <= end)
|
||||
in_comment = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos --;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!in_comment)
|
||||
/* This wasn't in a comment */
|
||||
|
@ -1761,6 +1832,8 @@ SCM_DEFINE (scm_file_encoding, "file-encoding", 1, 0, 0,
|
|||
char *enc;
|
||||
SCM s_enc;
|
||||
|
||||
SCM_VALIDATE_OPINPORT (SCM_ARG1, port);
|
||||
|
||||
enc = scm_i_scan_for_encoding (port);
|
||||
if (enc == NULL)
|
||||
return SCM_BOOL_F;
|
||||
|
|
|
@ -53,11 +53,17 @@
|
|||
* The SCM_SNARF_INIT text goes into the corresponding .x file
|
||||
* up through the first occurrence of SCM_SNARF_DOC_START on that
|
||||
* line, if any.
|
||||
*
|
||||
* Some debugging options can cause the preprocessor to echo #define
|
||||
* directives to its output. Keeping the snarfing markers on separate
|
||||
* lines prevents guile-snarf from inadvertently snarfing the definition
|
||||
* of SCM_SNARF_INIT if those options are in effect.
|
||||
*/
|
||||
|
||||
#ifdef SCM_MAGIC_SNARF_INITS
|
||||
# define SCM_SNARF_HERE(X)
|
||||
# define SCM_SNARF_INIT(X) ^^ X ^:^
|
||||
# define SCM_SNARF_INIT_PREFIX ^^
|
||||
# define SCM_SNARF_INIT(X) SCM_SNARF_INIT_PREFIX X ^:^
|
||||
# define SCM_SNARF_DOCS(TYPE, CNAME, FNAME, ARGLIST, REQ, OPT, VAR, DOCSTRING)
|
||||
#else
|
||||
# ifdef SCM_MAGIC_SNARF_DOCS
|
||||
|
|
|
@ -1426,7 +1426,7 @@ SCM_DEFINE (scm_recv, "recv!", 2, 1, 0,
|
|||
"use a bytevector instead.");
|
||||
|
||||
len = scm_i_string_length (buf);
|
||||
msg = scm_i_make_string (len, &dest);
|
||||
msg = scm_i_make_string (len, &dest, 0);
|
||||
SCM_SYSCALL (rv = recv (fd, dest, len, flg));
|
||||
scm_string_copy_x (buf, scm_from_int (0),
|
||||
msg, scm_from_int (0), scm_from_size_t (len));
|
||||
|
|
|
@ -251,14 +251,14 @@ SCM_DEFINE (scm_string_tabulate, "string-tabulate", 2, 0, 0,
|
|||
if (wide)
|
||||
{
|
||||
scm_t_wchar *wbuf = NULL;
|
||||
res = scm_i_make_wide_string (clen, &wbuf);
|
||||
res = scm_i_make_wide_string (clen, &wbuf, 0);
|
||||
memcpy (wbuf, buf, clen * sizeof (scm_t_wchar));
|
||||
free (buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *nbuf = NULL;
|
||||
res = scm_i_make_string (clen, &nbuf);
|
||||
res = scm_i_make_string (clen, &nbuf, 0);
|
||||
for (i = 0; i < clen; i ++)
|
||||
nbuf[i] = (unsigned char) buf[i];
|
||||
free (buf);
|
||||
|
@ -336,7 +336,7 @@ SCM_DEFINE (scm_reverse_list_to_string, "reverse-list->string", 1, 0, 0,
|
|||
|
||||
if (i < 0)
|
||||
SCM_WRONG_TYPE_ARG (1, chrs);
|
||||
result = scm_i_make_string (i, &data);
|
||||
result = scm_i_make_string (i, &data, 0);
|
||||
|
||||
{
|
||||
SCM rest;
|
||||
|
@ -439,7 +439,7 @@ SCM_DEFINE (scm_string_join, "string-join", 1, 2, 0,
|
|||
SCM_MISC_ERROR ("strict-infix grammar requires non-empty list",
|
||||
SCM_EOL);
|
||||
|
||||
result = scm_i_make_string (0, NULL);
|
||||
result = scm_i_make_string (0, NULL, 0);
|
||||
|
||||
tmp = ls;
|
||||
switch (gram)
|
||||
|
@ -1181,7 +1181,9 @@ SCM_DEFINE (scm_string_eq, "string=", 2, 4, 0,
|
|||
len1 = scm_i_string_length (s1);
|
||||
len2 = scm_i_string_length (s2);
|
||||
|
||||
if (SCM_LIKELY (len1 == len2))
|
||||
if (len1 != len2)
|
||||
return SCM_BOOL_F;
|
||||
else
|
||||
{
|
||||
if (!scm_i_is_narrow_string (s1))
|
||||
len1 *= 4;
|
||||
|
@ -2484,7 +2486,7 @@ SCM_DEFINE (scm_string_map, "string-map", 2, 2, 0,
|
|||
MY_VALIDATE_SUBSTRING_SPEC (2, s,
|
||||
3, start, cstart,
|
||||
4, end, cend);
|
||||
result = scm_i_make_string (cend - cstart, NULL);
|
||||
result = scm_i_make_string (cend - cstart, NULL, 0);
|
||||
p = 0;
|
||||
while (cstart < cend)
|
||||
{
|
||||
|
@ -2622,7 +2624,7 @@ SCM_DEFINE (scm_string_unfold, "string-unfold", 4, 2, 0,
|
|||
ans = base;
|
||||
}
|
||||
else
|
||||
ans = scm_i_make_string (0, NULL);
|
||||
ans = scm_i_make_string (0, NULL, 0);
|
||||
if (!SCM_UNBNDP (make_final))
|
||||
SCM_VALIDATE_PROC (6, make_final);
|
||||
|
||||
|
@ -2634,7 +2636,7 @@ SCM_DEFINE (scm_string_unfold, "string-unfold", 4, 2, 0,
|
|||
SCM ch = scm_call_1 (f, seed);
|
||||
if (!SCM_CHARP (ch))
|
||||
SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
|
||||
str = scm_i_make_string (1, NULL);
|
||||
str = scm_i_make_string (1, NULL, 0);
|
||||
str = scm_i_string_start_writing (str);
|
||||
scm_i_string_set_x (str, i, SCM_CHAR (ch));
|
||||
scm_i_string_stop_writing ();
|
||||
|
@ -2688,7 +2690,7 @@ SCM_DEFINE (scm_string_unfold_right, "string-unfold-right", 4, 2, 0,
|
|||
ans = base;
|
||||
}
|
||||
else
|
||||
ans = scm_i_make_string (0, NULL);
|
||||
ans = scm_i_make_string (0, NULL, 0);
|
||||
if (!SCM_UNBNDP (make_final))
|
||||
SCM_VALIDATE_PROC (6, make_final);
|
||||
|
||||
|
@ -2700,7 +2702,7 @@ SCM_DEFINE (scm_string_unfold_right, "string-unfold-right", 4, 2, 0,
|
|||
SCM ch = scm_call_1 (f, seed);
|
||||
if (!SCM_CHARP (ch))
|
||||
SCM_MISC_ERROR ("procedure ~S returned non-char", scm_list_1 (f));
|
||||
str = scm_i_make_string (1, NULL);
|
||||
str = scm_i_make_string (1, NULL, 0);
|
||||
str = scm_i_string_start_writing (str);
|
||||
scm_i_string_set_x (str, i, SCM_CHAR (ch));
|
||||
scm_i_string_stop_writing ();
|
||||
|
@ -2815,7 +2817,7 @@ SCM_DEFINE (scm_xsubstring, "xsubstring", 2, 3, 0,
|
|||
if (cstart == cend && cfrom != cto)
|
||||
SCM_MISC_ERROR ("start and end indices must not be equal", SCM_EOL);
|
||||
|
||||
result = scm_i_make_string (cto - cfrom, NULL);
|
||||
result = scm_i_make_string (cto - cfrom, NULL, 0);
|
||||
result = scm_i_string_start_writing (result);
|
||||
|
||||
p = 0;
|
||||
|
@ -3127,7 +3129,7 @@ SCM_DEFINE (scm_string_filter, "string-filter", 2, 2, 0,
|
|||
else
|
||||
{
|
||||
size_t dst = 0;
|
||||
result = scm_i_make_string (count, NULL);
|
||||
result = scm_i_make_string (count, NULL, 0);
|
||||
result = scm_i_string_start_writing (result);
|
||||
|
||||
/* decrement "count" in this loop as well as using idx, so that if
|
||||
|
@ -3237,7 +3239,7 @@ SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
|
|||
{
|
||||
int i = 0;
|
||||
/* new string for retained portion */
|
||||
result = scm_i_make_string (count, NULL);
|
||||
result = scm_i_make_string (count, NULL, 0);
|
||||
result = scm_i_string_start_writing (result);
|
||||
/* decrement "count" in this loop as well as using idx, so that if
|
||||
another thread is simultaneously changing "s" there's no chance
|
||||
|
@ -3279,7 +3281,7 @@ SCM_DEFINE (scm_string_delete, "string-delete", 2, 2, 0,
|
|||
{
|
||||
size_t i = 0;
|
||||
/* new string for retained portion */
|
||||
result = scm_i_make_string (count, NULL);
|
||||
result = scm_i_make_string (count, NULL, 0);
|
||||
result = scm_i_string_start_writing (result);
|
||||
|
||||
/* decrement "count" in this loop as well as using idx, so that if
|
||||
|
|
|
@ -1515,9 +1515,9 @@ SCM_DEFINE (scm_char_set_to_string, "char-set->string", 1, 0, 0,
|
|||
|
||||
count = scm_to_int (scm_char_set_size (cs));
|
||||
if (wide)
|
||||
result = scm_i_make_wide_string (count, &wbuf);
|
||||
result = scm_i_make_wide_string (count, &wbuf, 0);
|
||||
else
|
||||
result = scm_i_make_string (count, &buf);
|
||||
result = scm_i_make_string (count, &buf, 0);
|
||||
|
||||
for (k = 0; k < cs_data->len; k++)
|
||||
for (n = cs_data->ranges[k].lo; n <= cs_data->ranges[k].hi; n++)
|
||||
|
|
|
@ -247,7 +247,6 @@ SCM_DEFINE (scm_make_stack, "make-stack", 1, 0, 1,
|
|||
#define FUNC_NAME s_scm_make_stack
|
||||
{
|
||||
long n;
|
||||
int maxp;
|
||||
SCM frame;
|
||||
SCM stack;
|
||||
SCM inner_cut, outer_cut;
|
||||
|
@ -289,7 +288,6 @@ SCM_DEFINE (scm_make_stack, "make-stack", 1, 0, 1,
|
|||
/* Count number of frames. Also get stack id tag and check whether
|
||||
there are more stackframes than we want to record
|
||||
(SCM_BACKTRACE_MAXDEPTH). */
|
||||
maxp = 0;
|
||||
n = stack_depth (frame);
|
||||
|
||||
/* Make the stack object. */
|
||||
|
|
|
@ -262,30 +262,34 @@ SCM scm_nullstr;
|
|||
|
||||
/* Create a scheme string with space for LEN 8-bit Latin-1-encoded
|
||||
characters. CHARSP, if not NULL, will be set to location of the
|
||||
char array. */
|
||||
char array. If READ_ONLY_P, the returned string is read-only;
|
||||
otherwise it is writable. */
|
||||
SCM
|
||||
scm_i_make_string (size_t len, char **charsp)
|
||||
scm_i_make_string (size_t len, char **charsp, int read_only_p)
|
||||
{
|
||||
SCM buf = make_stringbuf (len);
|
||||
SCM res;
|
||||
if (charsp)
|
||||
*charsp = (char *) STRINGBUF_CHARS (buf);
|
||||
res = scm_double_cell (STRING_TAG, SCM_UNPACK(buf),
|
||||
res = scm_double_cell (read_only_p ? RO_STRING_TAG : STRING_TAG,
|
||||
SCM_UNPACK (buf),
|
||||
(scm_t_bits) 0, (scm_t_bits) len);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Create a scheme string with space for LEN 32-bit UCS-4-encoded
|
||||
characters. CHARSP, if not NULL, will be set to location of the
|
||||
character array. */
|
||||
character array. If READ_ONLY_P, the returned string is read-only;
|
||||
otherwise it is writable. */
|
||||
SCM
|
||||
scm_i_make_wide_string (size_t len, scm_t_wchar **charsp)
|
||||
scm_i_make_wide_string (size_t len, scm_t_wchar **charsp, int read_only_p)
|
||||
{
|
||||
SCM buf = make_wide_stringbuf (len);
|
||||
SCM res;
|
||||
if (charsp)
|
||||
*charsp = STRINGBUF_WIDE_CHARS (buf);
|
||||
res = scm_double_cell (STRING_TAG, SCM_UNPACK (buf),
|
||||
res = scm_double_cell (read_only_p ? RO_STRING_TAG : STRING_TAG,
|
||||
SCM_UNPACK (buf),
|
||||
(scm_t_bits) 0, (scm_t_bits) len);
|
||||
return res;
|
||||
}
|
||||
|
@ -889,7 +893,7 @@ SCM_DEFINE (scm_sys_string_dump, "%string-dump", 1, 0, 0, (SCM str),
|
|||
{
|
||||
size_t len = STRINGBUF_LENGTH (buf);
|
||||
char *cbuf;
|
||||
SCM sbc = scm_i_make_string (len, &cbuf);
|
||||
SCM sbc = scm_i_make_string (len, &cbuf, 0);
|
||||
memcpy (cbuf, STRINGBUF_CHARS (buf), len);
|
||||
e6 = scm_cons (scm_from_latin1_symbol ("stringbuf-chars"),
|
||||
sbc);
|
||||
|
@ -898,7 +902,7 @@ SCM_DEFINE (scm_sys_string_dump, "%string-dump", 1, 0, 0, (SCM str),
|
|||
{
|
||||
size_t len = STRINGBUF_LENGTH (buf);
|
||||
scm_t_wchar *cbuf;
|
||||
SCM sbc = scm_i_make_wide_string (len, &cbuf);
|
||||
SCM sbc = scm_i_make_wide_string (len, &cbuf, 0);
|
||||
u32_cpy ((scm_t_uint32 *) cbuf,
|
||||
(scm_t_uint32 *) STRINGBUF_WIDE_CHARS (buf), len);
|
||||
e6 = scm_cons (scm_from_latin1_symbol ("stringbuf-chars"),
|
||||
|
@ -962,7 +966,7 @@ SCM_DEFINE (scm_sys_symbol_dump, "%symbol-dump", 1, 0, 0, (SCM sym),
|
|||
{
|
||||
size_t len = STRINGBUF_LENGTH (buf);
|
||||
char *cbuf;
|
||||
SCM sbc = scm_i_make_string (len, &cbuf);
|
||||
SCM sbc = scm_i_make_string (len, &cbuf, 0);
|
||||
memcpy (cbuf, STRINGBUF_CHARS (buf), len);
|
||||
e4 = scm_cons (scm_from_latin1_symbol ("stringbuf-chars"),
|
||||
sbc);
|
||||
|
@ -971,7 +975,7 @@ SCM_DEFINE (scm_sys_symbol_dump, "%symbol-dump", 1, 0, 0, (SCM sym),
|
|||
{
|
||||
size_t len = STRINGBUF_LENGTH (buf);
|
||||
scm_t_wchar *cbuf;
|
||||
SCM sbc = scm_i_make_wide_string (len, &cbuf);
|
||||
SCM sbc = scm_i_make_wide_string (len, &cbuf, 0);
|
||||
u32_cpy ((scm_t_uint32 *) cbuf,
|
||||
(scm_t_uint32 *) STRINGBUF_WIDE_CHARS (buf), len);
|
||||
e4 = scm_cons (scm_from_latin1_symbol ("stringbuf-chars"),
|
||||
|
@ -1066,7 +1070,7 @@ SCM_DEFINE (scm_string, "string", 0, 0, 1,
|
|||
{
|
||||
char *buf;
|
||||
|
||||
result = scm_i_make_string (len, NULL);
|
||||
result = scm_i_make_string (len, NULL, 0);
|
||||
result = scm_i_string_start_writing (result);
|
||||
buf = scm_i_string_writable_chars (result);
|
||||
while (len > 0 && scm_is_pair (rest))
|
||||
|
@ -1083,7 +1087,7 @@ SCM_DEFINE (scm_string, "string", 0, 0, 1,
|
|||
{
|
||||
scm_t_wchar *buf;
|
||||
|
||||
result = scm_i_make_wide_string (len, NULL);
|
||||
result = scm_i_make_wide_string (len, NULL, 0);
|
||||
result = scm_i_string_start_writing (result);
|
||||
buf = scm_i_string_writable_wide_chars (result);
|
||||
while (len > 0 && scm_is_pair (rest))
|
||||
|
@ -1125,7 +1129,7 @@ scm_c_make_string (size_t len, SCM chr)
|
|||
{
|
||||
size_t p;
|
||||
char *contents = NULL;
|
||||
SCM res = scm_i_make_string (len, &contents);
|
||||
SCM res = scm_i_make_string (len, &contents, 0);
|
||||
|
||||
/* If no char is given, initialize string contents to NULL. */
|
||||
if (SCM_UNBNDP (chr))
|
||||
|
@ -1372,9 +1376,9 @@ SCM_DEFINE (scm_string_append, "string-append", 0, 0, 1,
|
|||
}
|
||||
data.narrow = NULL;
|
||||
if (!wide)
|
||||
res = scm_i_make_string (len, &data.narrow);
|
||||
res = scm_i_make_string (len, &data.narrow, 0);
|
||||
else
|
||||
res = scm_i_make_wide_string (len, &data.wide);
|
||||
res = scm_i_make_wide_string (len, &data.wide, 0);
|
||||
|
||||
for (l = args; !scm_is_null (l); l = SCM_CDR (l))
|
||||
{
|
||||
|
@ -1419,8 +1423,8 @@ scm_encoding_error (const char *subr, int err, const char *message,
|
|||
SCM port, SCM chr)
|
||||
{
|
||||
scm_throw (scm_encoding_error_key,
|
||||
scm_list_n (scm_from_locale_string (subr),
|
||||
scm_from_locale_string (message),
|
||||
scm_list_n (scm_from_latin1_string (subr),
|
||||
scm_from_latin1_string (message),
|
||||
scm_from_int (err),
|
||||
port, chr,
|
||||
SCM_UNDEFINED));
|
||||
|
@ -1432,8 +1436,8 @@ void
|
|||
scm_decoding_error (const char *subr, int err, const char *message, SCM port)
|
||||
{
|
||||
scm_throw (scm_decoding_error_key,
|
||||
scm_list_n (scm_from_locale_string (subr),
|
||||
scm_from_locale_string (message),
|
||||
scm_list_n (scm_from_latin1_string (subr),
|
||||
scm_from_latin1_string (message),
|
||||
scm_from_int (err),
|
||||
port,
|
||||
SCM_UNDEFINED));
|
||||
|
@ -1463,7 +1467,7 @@ scm_from_stringn (const char *str, size_t len, const char *encoding,
|
|||
{
|
||||
/* If encoding is null, use Latin-1. */
|
||||
char *buf;
|
||||
res = scm_i_make_string (len, &buf);
|
||||
res = scm_i_make_string (len, &buf, 0);
|
||||
memcpy (buf, str, len);
|
||||
return res;
|
||||
}
|
||||
|
@ -1502,7 +1506,7 @@ scm_from_stringn (const char *str, size_t len, const char *encoding,
|
|||
if (!wide)
|
||||
{
|
||||
char *dst;
|
||||
res = scm_i_make_string (u32len, &dst);
|
||||
res = scm_i_make_string (u32len, &dst, 0);
|
||||
for (i = 0; i < u32len; i ++)
|
||||
dst[i] = (unsigned char) u32[i];
|
||||
dst[u32len] = '\0';
|
||||
|
@ -1510,7 +1514,7 @@ scm_from_stringn (const char *str, size_t len, const char *encoding,
|
|||
else
|
||||
{
|
||||
scm_t_wchar *wdst;
|
||||
res = scm_i_make_wide_string (u32len, &wdst);
|
||||
res = scm_i_make_wide_string (u32len, &wdst, 0);
|
||||
u32_cpy ((scm_t_uint32 *) wdst, (scm_t_uint32 *) u32, u32len);
|
||||
wdst[u32len] = 0;
|
||||
}
|
||||
|
@ -1528,25 +1532,8 @@ scm_from_locale_string (const char *str)
|
|||
SCM
|
||||
scm_from_locale_stringn (const char *str, size_t len)
|
||||
{
|
||||
const char *enc;
|
||||
scm_t_string_failed_conversion_handler hndl;
|
||||
SCM inport;
|
||||
scm_t_port *pt;
|
||||
|
||||
inport = scm_current_input_port ();
|
||||
if (!SCM_UNBNDP (inport) && SCM_OPINPORTP (inport))
|
||||
{
|
||||
pt = SCM_PTAB_ENTRY (inport);
|
||||
enc = pt->encoding;
|
||||
hndl = pt->ilseq_handler;
|
||||
}
|
||||
else
|
||||
{
|
||||
enc = NULL;
|
||||
hndl = SCM_FAILED_CONVERSION_ERROR;
|
||||
}
|
||||
|
||||
return scm_from_stringn (str, len, enc, hndl);
|
||||
return scm_from_stringn (str, len, locale_charset (),
|
||||
scm_i_get_conversion_strategy (SCM_BOOL_F));
|
||||
}
|
||||
|
||||
SCM
|
||||
|
@ -1565,7 +1552,7 @@ scm_from_latin1_stringn (const char *str, size_t len)
|
|||
len = strlen (str);
|
||||
|
||||
/* Make a narrow string and copy STR as is. */
|
||||
result = scm_i_make_string (len, &buf);
|
||||
result = scm_i_make_string (len, &buf, 0);
|
||||
memcpy (buf, str, len);
|
||||
|
||||
return result;
|
||||
|
@ -1598,7 +1585,7 @@ scm_from_utf32_stringn (const scm_t_wchar *str, size_t len)
|
|||
if (len == (size_t) -1)
|
||||
len = u32_strlen ((uint32_t *) str);
|
||||
|
||||
result = scm_i_make_wide_string (len, &buf);
|
||||
result = scm_i_make_wide_string (len, &buf, 0);
|
||||
memcpy (buf, str, len * sizeof (scm_t_wchar));
|
||||
scm_i_try_narrow_string (result);
|
||||
|
||||
|
@ -1771,21 +1758,8 @@ scm_to_locale_string (SCM str)
|
|||
char *
|
||||
scm_to_locale_stringn (SCM str, size_t *lenp)
|
||||
{
|
||||
SCM outport;
|
||||
scm_t_port *pt;
|
||||
const char *enc;
|
||||
|
||||
outport = scm_current_output_port ();
|
||||
if (!SCM_UNBNDP (outport) && SCM_OPOUTPORTP (outport))
|
||||
{
|
||||
pt = SCM_PTAB_ENTRY (outport);
|
||||
enc = pt->encoding;
|
||||
}
|
||||
else
|
||||
enc = NULL;
|
||||
|
||||
return scm_to_stringn (str, lenp,
|
||||
enc,
|
||||
locale_charset (),
|
||||
scm_i_get_conversion_strategy (SCM_BOOL_F));
|
||||
}
|
||||
|
||||
|
@ -2029,7 +2003,7 @@ normalize_str (SCM string, uninorm_t form)
|
|||
|
||||
w_str = u32_normalize (form, w_str, len, NULL, &rlen);
|
||||
|
||||
ret = scm_i_make_wide_string (rlen, &cbuf);
|
||||
ret = scm_i_make_wide_string (rlen, &cbuf, 0);
|
||||
u32_cpy ((scm_t_uint32 *) cbuf, w_str, rlen);
|
||||
free (w_str);
|
||||
|
||||
|
@ -2241,7 +2215,7 @@ SCM_VECTOR_IMPLEMENTATION (SCM_ARRAY_ELEMENT_TYPE_CHAR, scm_make_string)
|
|||
void
|
||||
scm_init_strings ()
|
||||
{
|
||||
scm_nullstr = scm_i_make_string (0, NULL);
|
||||
scm_nullstr = scm_i_make_string (0, NULL, 1);
|
||||
|
||||
#include "libguile/strings.x"
|
||||
}
|
||||
|
|
|
@ -177,8 +177,11 @@ SCM_API SCM scm_makfromstrs (int argc, char **argv);
|
|||
|
||||
/* internal accessor functions. Arguments must be valid. */
|
||||
|
||||
SCM_INTERNAL SCM scm_i_make_string (size_t len, char **datap);
|
||||
SCM_INTERNAL SCM scm_i_make_wide_string (size_t len, scm_t_wchar **datap);
|
||||
SCM_INTERNAL SCM scm_i_make_string (size_t len, char **datap,
|
||||
int read_only_p);
|
||||
SCM_INTERNAL SCM scm_i_make_wide_string (size_t len, scm_t_wchar **datap,
|
||||
int read_only_p);
|
||||
SCM_INTERNAL SCM scm_i_set_string_read_only_x (SCM str);
|
||||
SCM_INTERNAL SCM scm_i_substring (SCM str, size_t start, size_t end);
|
||||
SCM_INTERNAL SCM scm_i_substring_read_only (SCM str, size_t start, size_t end);
|
||||
SCM_INTERNAL SCM scm_i_substring_shared (SCM str, size_t start, size_t end);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002, 2003, 2005, 2006, 2009, 2010 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995,1996,1998,1999,2000,2001,2002, 2003, 2005, 2006, 2009, 2010, 2011 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
|
||||
|
@ -30,7 +30,7 @@
|
|||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "libguile/arrays.h"
|
||||
#include "libguile/bytevectors.h"
|
||||
#include "libguile/eval.h"
|
||||
#include "libguile/ports.h"
|
||||
#include "libguile/read.h"
|
||||
|
@ -55,15 +55,8 @@
|
|||
|
||||
/* NOTES:
|
||||
|
||||
We break the rules set forth by strings.h about accessing the
|
||||
internals of strings here. We can do this since we can guarantee
|
||||
that the string used as pt->stream is not in use by anyone else.
|
||||
Thus, it's representation will not change asynchronously.
|
||||
|
||||
(Ports aren't thread-safe yet anyway...)
|
||||
|
||||
write_buf/write_end point to the ends of the allocated string.
|
||||
read_buf/read_end in principle point to the part of the string which
|
||||
write_buf/write_end point to the ends of the allocated bytevector.
|
||||
read_buf/read_end in principle point to the part of the bytevector which
|
||||
has been written to, but this is only updated after a flush.
|
||||
read_pos and write_pos in principle should be equal, but this is only true
|
||||
when rw_active is SCM_PORT_NEITHER.
|
||||
|
@ -106,25 +99,23 @@ stfill_buffer (SCM port)
|
|||
return scm_return_first_int (*pt->read_pos, port);
|
||||
}
|
||||
|
||||
/* change the size of a port's string to new_size. this doesn't
|
||||
change read_buf_size. */
|
||||
/* Change the size of a port's bytevector to NEW_SIZE. This doesn't
|
||||
change `read_buf_size'. */
|
||||
static void
|
||||
st_resize_port (scm_t_port *pt, scm_t_off new_size)
|
||||
{
|
||||
SCM old_stream = SCM_PACK (pt->stream);
|
||||
const char *src = scm_i_string_chars (old_stream);
|
||||
char *dst;
|
||||
SCM new_stream = scm_i_make_string (new_size, &dst);
|
||||
unsigned long int old_size = scm_i_string_length (old_stream);
|
||||
const signed char *src = SCM_BYTEVECTOR_CONTENTS (old_stream);
|
||||
SCM new_stream = scm_c_make_bytevector (new_size);
|
||||
signed char *dst = SCM_BYTEVECTOR_CONTENTS (new_stream);
|
||||
unsigned long int old_size = SCM_BYTEVECTOR_LENGTH (old_stream);
|
||||
unsigned long int min_size = min (old_size, new_size);
|
||||
unsigned long int i;
|
||||
|
||||
scm_t_off index = pt->write_pos - pt->write_buf;
|
||||
|
||||
pt->write_buf_size = new_size;
|
||||
|
||||
for (i = 0; i != min_size; ++i)
|
||||
dst[i] = src[i];
|
||||
memcpy (dst, src, min_size);
|
||||
|
||||
scm_remember_upto_here_1 (old_stream);
|
||||
|
||||
|
@ -138,27 +129,17 @@ st_resize_port (scm_t_port *pt, scm_t_off new_size)
|
|||
}
|
||||
}
|
||||
|
||||
/* amount by which write_buf is expanded. */
|
||||
#define SCM_WRITE_BLOCK 80
|
||||
|
||||
/* ensure that write_pos < write_end by enlarging the buffer when
|
||||
necessary. update read_buf to account for written chars.
|
||||
|
||||
The buffer is enlarged by 1.5 times, plus SCM_WRITE_BLOCK. Adding just a
|
||||
fixed amount is no good, because there's a block copy for each increment,
|
||||
and that copying would take quadratic time. In the past it was found to
|
||||
be very slow just adding 80 bytes each time (eg. about 10 seconds for
|
||||
writing a 100kbyte string). */
|
||||
|
||||
/* Ensure that `write_pos' < `write_end' by enlarging the buffer when
|
||||
necessary. Update `read_buf' to account for written chars. The
|
||||
buffer is enlarged geometrically. */
|
||||
static void
|
||||
st_flush (SCM port)
|
||||
{
|
||||
scm_t_port *pt = SCM_PTAB_ENTRY (port);
|
||||
|
||||
if (pt->write_pos == pt->write_end)
|
||||
{
|
||||
st_resize_port (pt, pt->write_buf_size * 3 / 2 + SCM_WRITE_BLOCK);
|
||||
}
|
||||
st_resize_port (pt, pt->write_buf_size * 2);
|
||||
|
||||
pt->read_pos = pt->write_pos;
|
||||
if (pt->read_pos > pt->read_end)
|
||||
{
|
||||
|
@ -255,12 +236,8 @@ st_seek (SCM port, scm_t_off offset, int whence)
|
|||
SCM_EOL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
st_resize_port (pt, target + (target == pt->write_buf_size
|
||||
? SCM_WRITE_BLOCK
|
||||
: 0));
|
||||
}
|
||||
else if (target == pt->write_buf_size)
|
||||
st_resize_port (pt, target * 2);
|
||||
}
|
||||
pt->read_pos = pt->write_pos = pt->read_buf + target;
|
||||
if (pt->read_pos > pt->read_end)
|
||||
|
@ -289,16 +266,19 @@ st_truncate (SCM port, scm_t_off length)
|
|||
pt->write_pos = pt->read_end;
|
||||
}
|
||||
|
||||
/* The initial size in bytes of a string port's buffer. */
|
||||
#define INITIAL_BUFFER_SIZE 128
|
||||
|
||||
/* Return a new string port with MODES. If STR is #f, a new backing
|
||||
buffer is allocated; otherwise STR must be a string and a copy of it
|
||||
serves as the buffer for the new port. */
|
||||
SCM
|
||||
scm_mkstrport (SCM pos, SCM str, long modes, const char *caller)
|
||||
{
|
||||
SCM z;
|
||||
SCM z, buf;
|
||||
scm_t_port *pt;
|
||||
size_t str_len, c_pos;
|
||||
char *buf, *c_str;
|
||||
|
||||
SCM_ASSERT (scm_is_string (str), str, SCM_ARG1, caller);
|
||||
c_pos = scm_to_unsigned_integer (pos, 0, scm_i_string_length (str));
|
||||
char *c_buf;
|
||||
|
||||
if (!((modes & SCM_WRTNG) || (modes & SCM_RDNG)))
|
||||
scm_misc_error ("scm_mkstrport", "port must read or write", SCM_EOL);
|
||||
|
@ -308,19 +288,44 @@ scm_mkstrport (SCM pos, SCM str, long modes, const char *caller)
|
|||
|
||||
z = scm_new_port_table_entry (scm_tc16_strport);
|
||||
pt = SCM_PTAB_ENTRY(z);
|
||||
SCM_SETSTREAM (z, SCM_UNPACK (str));
|
||||
|
||||
if (scm_is_false (str))
|
||||
{
|
||||
/* Allocate a new buffer to write to. */
|
||||
str_len = INITIAL_BUFFER_SIZE;
|
||||
buf = scm_c_make_bytevector (str_len);
|
||||
c_buf = (char *) SCM_BYTEVECTOR_CONTENTS (buf);
|
||||
|
||||
/* Reset `read_buf_size'. It will contain the actual number of
|
||||
bytes written to PT. */
|
||||
pt->read_buf_size = 0;
|
||||
c_pos = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* STR is a string. */
|
||||
char *copy;
|
||||
|
||||
SCM_ASSERT (scm_is_string (str), str, SCM_ARG1, caller);
|
||||
|
||||
/* Create a copy of STR in the encoding of PT. */
|
||||
copy = scm_to_stringn (str, &str_len, pt->encoding,
|
||||
SCM_FAILED_CONVERSION_ERROR);
|
||||
buf = scm_c_make_bytevector (str_len);
|
||||
c_buf = (char *) SCM_BYTEVECTOR_CONTENTS (buf);
|
||||
memcpy (c_buf, copy, str_len);
|
||||
free (copy);
|
||||
|
||||
c_pos = scm_to_unsigned_integer (pos, 0, str_len);
|
||||
pt->read_buf_size = str_len;
|
||||
}
|
||||
|
||||
SCM_SETSTREAM (z, SCM_UNPACK (buf));
|
||||
SCM_SET_CELL_TYPE (z, scm_tc16_strport | modes);
|
||||
|
||||
/* Create a copy of STR in the encoding of Z. */
|
||||
buf = scm_to_stringn (str, &str_len, pt->encoding,
|
||||
SCM_FAILED_CONVERSION_ERROR);
|
||||
c_str = scm_gc_malloc (str_len, "strport");
|
||||
memcpy (c_str, buf, str_len);
|
||||
free (buf);
|
||||
|
||||
pt->write_buf = pt->read_buf = (unsigned char *) c_str;
|
||||
pt->write_buf = pt->read_buf = (unsigned char *) c_buf;
|
||||
pt->read_pos = pt->write_pos = pt->read_buf + c_pos;
|
||||
pt->write_buf_size = pt->read_buf_size = str_len;
|
||||
pt->write_buf_size = str_len;
|
||||
pt->write_end = pt->read_end = pt->read_buf + pt->read_buf_size;
|
||||
|
||||
pt->rw_random = 1;
|
||||
|
@ -352,7 +357,7 @@ scm_strport_to_string (SCM port)
|
|||
if (pt->encoding == NULL)
|
||||
{
|
||||
char *buf;
|
||||
str = scm_i_make_string (pt->read_buf_size, &buf);
|
||||
str = scm_i_make_string (pt->read_buf_size, &buf, 0);
|
||||
memcpy (buf, pt->read_buf, pt->read_buf_size);
|
||||
}
|
||||
else
|
||||
|
@ -369,20 +374,30 @@ SCM_DEFINE (scm_object_to_string, "object->string", 1, 1, 0,
|
|||
"argument @var{printer} (default: @code{write}).")
|
||||
#define FUNC_NAME s_scm_object_to_string
|
||||
{
|
||||
SCM str, port;
|
||||
SCM port, result;
|
||||
|
||||
if (!SCM_UNBNDP (printer))
|
||||
SCM_VALIDATE_PROC (2, printer);
|
||||
|
||||
str = scm_c_make_string (0, SCM_UNDEFINED);
|
||||
port = scm_mkstrport (SCM_INUM0, str, SCM_OPN | SCM_WRTNG, FUNC_NAME);
|
||||
port = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG, FUNC_NAME);
|
||||
|
||||
if (SCM_UNBNDP (printer))
|
||||
scm_write (obj, port);
|
||||
else
|
||||
scm_call_2 (printer, obj, port);
|
||||
|
||||
return scm_strport_to_string (port);
|
||||
result = scm_strport_to_string (port);
|
||||
|
||||
/* Explicitly close PORT so that the iconv CDs associated with it are
|
||||
deallocated right away. This is important because CDs use a lot of
|
||||
memory that's not visible to the GC, so not freeing them can lead
|
||||
to almost large heap usage. See
|
||||
<http://wingolog.org/archives/2011/02/25/ports-weaks-gc-and-dark-matter>
|
||||
for details. */
|
||||
scm_close_port (port);
|
||||
|
||||
return result;
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
@ -395,8 +410,7 @@ SCM_DEFINE (scm_call_with_output_string, "call-with-output-string", 1, 0, 0,
|
|||
{
|
||||
SCM p;
|
||||
|
||||
p = scm_mkstrport (SCM_INUM0,
|
||||
scm_make_string (SCM_INUM0, SCM_UNDEFINED),
|
||||
p = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG,
|
||||
FUNC_NAME);
|
||||
scm_call_1 (proc, p);
|
||||
|
@ -441,8 +455,7 @@ SCM_DEFINE (scm_open_output_string, "open-output-string", 0, 0, 0,
|
|||
{
|
||||
SCM p;
|
||||
|
||||
p = scm_mkstrport (SCM_INUM0,
|
||||
scm_make_string (SCM_INUM0, SCM_UNDEFINED),
|
||||
p = scm_mkstrport (SCM_INUM0, SCM_BOOL_F,
|
||||
SCM_OPN | SCM_WRTNG,
|
||||
FUNC_NAME);
|
||||
return p;
|
||||
|
@ -467,15 +480,12 @@ SCM_DEFINE (scm_get_output_string, "get-output-string", 1, 0, 0,
|
|||
SCM
|
||||
scm_c_read_string (const char *expr)
|
||||
{
|
||||
/* FIXME: the c string gets packed into a string, only to get
|
||||
immediately unpacked in scm_mkstrport. */
|
||||
SCM port = scm_mkstrport (SCM_INUM0,
|
||||
scm_from_locale_string (expr),
|
||||
SCM_OPN | SCM_RDNG,
|
||||
"scm_c_read_string");
|
||||
SCM form;
|
||||
|
||||
/* Read expressions from that port; ignore the values. */
|
||||
form = scm_read (port);
|
||||
|
||||
scm_close_port (port);
|
||||
|
@ -497,25 +507,6 @@ scm_c_eval_string_in_module (const char *expr, SCM module)
|
|||
}
|
||||
|
||||
|
||||
static SCM
|
||||
inner_eval_string (void *data)
|
||||
{
|
||||
SCM port = (SCM)data;
|
||||
SCM form;
|
||||
SCM ans = SCM_UNSPECIFIED;
|
||||
|
||||
/* Read expressions from that port; ignore the values. */
|
||||
while (!SCM_EOF_OBJECT_P (form = scm_read (port)))
|
||||
ans = scm_primitive_eval_x (form);
|
||||
|
||||
/* Don't close the port here; if we re-enter this function via a
|
||||
continuation, then the next time we enter it, we'll get an error.
|
||||
It's a string port anyway, so there's no advantage to closing it
|
||||
early. */
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
SCM_DEFINE (scm_eval_string_in_module, "eval-string", 1, 1, 0,
|
||||
(SCM string, SCM module),
|
||||
"Evaluate @var{string} as the text representation of a Scheme\n"
|
||||
|
@ -527,14 +518,20 @@ SCM_DEFINE (scm_eval_string_in_module, "eval-string", 1, 1, 0,
|
|||
"procedure returns.")
|
||||
#define FUNC_NAME s_scm_eval_string_in_module
|
||||
{
|
||||
SCM port = scm_mkstrport (SCM_INUM0, string, SCM_OPN | SCM_RDNG,
|
||||
FUNC_NAME);
|
||||
static SCM eval_string = SCM_BOOL_F, k_module = SCM_BOOL_F;
|
||||
|
||||
if (scm_is_false (eval_string))
|
||||
{
|
||||
eval_string = scm_c_public_lookup ("ice-9 eval-string", "eval-string");
|
||||
k_module = scm_from_locale_keyword ("module");
|
||||
}
|
||||
|
||||
if (SCM_UNBNDP (module))
|
||||
module = scm_current_module ();
|
||||
else
|
||||
SCM_VALIDATE_MODULE (2, module);
|
||||
return scm_c_call_with_current_module (module,
|
||||
inner_eval_string, (void *)port);
|
||||
|
||||
return scm_call_3 (scm_variable_ref (eval_string), string, k_module, module);
|
||||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Copyright (C) 1995,1996,1997,1998,2000,2001, 2003, 2004, 2006, 2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001, 2003, 2004,
|
||||
* 2006, 2009, 2011 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
|
||||
|
@ -341,6 +342,9 @@ SCM_DEFINE (scm_string_ci_to_symbol, "string-ci->symbol", 1, 0, 0,
|
|||
}
|
||||
#undef FUNC_NAME
|
||||
|
||||
/* The default prefix for `gensym'd symbols. */
|
||||
static SCM default_gensym_prefix;
|
||||
|
||||
#define MAX_PREFIX_LENGTH 30
|
||||
|
||||
SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
|
||||
|
@ -359,7 +363,7 @@ SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
|
|||
char buf[SCM_INTBUFLEN];
|
||||
|
||||
if (SCM_UNBNDP (prefix))
|
||||
prefix = scm_from_locale_string (" g");
|
||||
prefix = default_gensym_prefix;
|
||||
|
||||
/* mutex in case another thread looks and incs at the exact same moment */
|
||||
scm_i_scm_pthread_mutex_lock (&scm_i_misc_mutex);
|
||||
|
@ -367,7 +371,7 @@ SCM_DEFINE (scm_gensym, "gensym", 0, 1, 0,
|
|||
scm_i_pthread_mutex_unlock (&scm_i_misc_mutex);
|
||||
|
||||
n_digits = scm_iint2str (n, 10, buf);
|
||||
suffix = scm_from_locale_stringn (buf, n_digits);
|
||||
suffix = scm_from_latin1_stringn (buf, n_digits);
|
||||
name = scm_string_append (scm_list_2 (prefix, suffix));
|
||||
return scm_string_to_symbol (name);
|
||||
}
|
||||
|
@ -506,6 +510,8 @@ void
|
|||
scm_init_symbols ()
|
||||
{
|
||||
#include "libguile/symbols.x"
|
||||
|
||||
default_gensym_prefix = scm_from_latin1_string (" g");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -79,6 +79,122 @@ typedef void * (* GC_fn_type) (void *);
|
|||
#endif
|
||||
|
||||
|
||||
#ifndef GC_SUCCESS
|
||||
#define GC_SUCCESS 0
|
||||
#endif
|
||||
|
||||
#ifndef GC_UNIMPLEMENTED
|
||||
#define GC_UNIMPLEMENTED 3
|
||||
#endif
|
||||
|
||||
/* Likewise struct GC_stack_base is missing before 7.1. */
|
||||
#ifndef HAVE_GC_STACK_BASE
|
||||
struct GC_stack_base {
|
||||
void * mem_base; /* Base of memory stack. */
|
||||
#ifdef __ia64__
|
||||
void * reg_base; /* Base of separate register stack. */
|
||||
#endif
|
||||
};
|
||||
|
||||
static int
|
||||
GC_register_my_thread (struct GC_stack_base *stack_base)
|
||||
{
|
||||
return GC_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
static void
|
||||
GC_unregister_my_thread ()
|
||||
{
|
||||
}
|
||||
|
||||
#if !SCM_USE_PTHREAD_THREADS
|
||||
/* No threads; we can just use GC_stackbottom. */
|
||||
static void *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
return GC_stackbottom;
|
||||
}
|
||||
|
||||
#elif defined HAVE_PTHREAD_ATTR_GETSTACK && defined HAVE_PTHREAD_GETATTR_NP \
|
||||
&& defined PTHREAD_ATTR_GETSTACK_WORKS
|
||||
/* This method for GNU/Linux and perhaps some other systems.
|
||||
It's not for MacOS X or Solaris 10, since pthread_getattr_np is not
|
||||
available on them. */
|
||||
static void *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
void *start, *end;
|
||||
size_t size;
|
||||
|
||||
pthread_getattr_np (pthread_self (), &attr);
|
||||
pthread_attr_getstack (&attr, &start, &size);
|
||||
end = (char *)start + size;
|
||||
|
||||
#if SCM_STACK_GROWS_UP
|
||||
return start;
|
||||
#else
|
||||
return end;
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined HAVE_PTHREAD_GET_STACKADDR_NP
|
||||
/* This method for MacOS X.
|
||||
It'd be nice if there was some documentation on pthread_get_stackaddr_np,
|
||||
but as of 2006 there's nothing obvious at apple.com. */
|
||||
static void *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
return pthread_get_stackaddr_np (pthread_self ());
|
||||
}
|
||||
|
||||
#else
|
||||
#error Threads enabled with old BDW-GC, but missing get_thread_stack_base impl. Please upgrade to libgc >= 7.1.
|
||||
#endif
|
||||
|
||||
static int
|
||||
GC_get_stack_base (struct GC_stack_base *stack_base)
|
||||
{
|
||||
stack_base->mem_base = get_thread_stack_base ();
|
||||
#ifdef __ia64__
|
||||
/* Calculate and store off the base of this thread's register
|
||||
backing store (RBS). Unfortunately our implementation(s) of
|
||||
scm_ia64_register_backing_store_base are only reliable for the
|
||||
main thread. For other threads, therefore, find out the current
|
||||
top of the RBS, and use that as a maximum. */
|
||||
stack_base->reg_base = scm_ia64_register_backing_store_base ();
|
||||
{
|
||||
ucontext_t ctx;
|
||||
void *bsp;
|
||||
getcontext (&ctx);
|
||||
bsp = scm_ia64_ar_bsp (&ctx);
|
||||
if (stack_base->reg_base > bsp)
|
||||
stack_base->reg_base = bsp;
|
||||
}
|
||||
#endif
|
||||
return GC_SUCCESS;
|
||||
}
|
||||
|
||||
static void *
|
||||
GC_call_with_stack_base(void * (*fn) (struct GC_stack_base*, void*), void *arg)
|
||||
{
|
||||
struct GC_stack_base stack_base;
|
||||
|
||||
stack_base.mem_base = (void*)&stack_base;
|
||||
#ifdef __ia64__
|
||||
/* FIXME: Untested. */
|
||||
{
|
||||
ucontext_t ctx;
|
||||
getcontext (&ctx);
|
||||
stack_base.reg_base = scm_ia64_ar_bsp (&ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
return fn (&stack_base, arg);
|
||||
}
|
||||
#endif /* HAVE_GC_STACK_BASE */
|
||||
|
||||
|
||||
/* Now define with_gc_active and with_gc_inactive. */
|
||||
|
||||
#if (defined(HAVE_GC_DO_BLOCKING) && defined (HAVE_DECL_GC_DO_BLOCKING) && defined (HAVE_GC_CALL_WITH_GC_ACTIVE))
|
||||
|
@ -343,6 +459,12 @@ unblock_from_queue (SCM queue)
|
|||
/* Getting into and out of guile mode.
|
||||
*/
|
||||
|
||||
/* Key used to attach a cleanup handler to a given thread. Also, if
|
||||
thread-local storage is unavailable, this key is used to retrieve the
|
||||
current thread with `pthread_getspecific ()'. */
|
||||
scm_i_pthread_key_t scm_i_thread_key;
|
||||
|
||||
|
||||
#ifdef SCM_HAVE_THREAD_STORAGE_CLASS
|
||||
|
||||
/* When thread-local storage (TLS) is available, a pointer to the
|
||||
|
@ -352,17 +474,7 @@ unblock_from_queue (SCM queue)
|
|||
represent. */
|
||||
SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread = NULL;
|
||||
|
||||
# define SET_CURRENT_THREAD(_t) scm_i_current_thread = (_t)
|
||||
|
||||
#else /* !SCM_HAVE_THREAD_STORAGE_CLASS */
|
||||
|
||||
/* Key used to retrieve the current thread with `pthread_getspecific ()'. */
|
||||
scm_i_pthread_key_t scm_i_thread_key;
|
||||
|
||||
# define SET_CURRENT_THREAD(_t) \
|
||||
scm_i_pthread_setspecific (scm_i_thread_key, (_t))
|
||||
|
||||
#endif /* !SCM_HAVE_THREAD_STORAGE_CLASS */
|
||||
#endif /* SCM_HAVE_THREAD_STORAGE_CLASS */
|
||||
|
||||
|
||||
static scm_i_pthread_mutex_t thread_admin_mutex = SCM_I_PTHREAD_MUTEX_INITIALIZER;
|
||||
|
@ -374,67 +486,75 @@ static SCM scm_i_default_dynamic_state;
|
|||
/* Perform first stage of thread initialisation, in non-guile mode.
|
||||
*/
|
||||
static void
|
||||
guilify_self_1 (SCM_STACKITEM *base)
|
||||
guilify_self_1 (struct GC_stack_base *base)
|
||||
{
|
||||
scm_i_thread *t = scm_gc_malloc (sizeof (scm_i_thread), "thread");
|
||||
scm_i_thread t;
|
||||
|
||||
t->pthread = scm_i_pthread_self ();
|
||||
t->handle = SCM_BOOL_F;
|
||||
t->result = SCM_BOOL_F;
|
||||
t->cleanup_handler = SCM_BOOL_F;
|
||||
t->mutexes = SCM_EOL;
|
||||
t->held_mutex = NULL;
|
||||
t->join_queue = SCM_EOL;
|
||||
t->dynamic_state = SCM_BOOL_F;
|
||||
t->dynwinds = SCM_EOL;
|
||||
t->active_asyncs = SCM_EOL;
|
||||
t->block_asyncs = 1;
|
||||
t->pending_asyncs = 1;
|
||||
t->critical_section_level = 0;
|
||||
t->base = base;
|
||||
/* We must arrange for SCM_I_CURRENT_THREAD to point to a valid value
|
||||
before allocating anything in this thread, because allocation could
|
||||
cause GC to run, and GC could cause finalizers, which could invoke
|
||||
Scheme functions, which need the current thread to be set. */
|
||||
|
||||
t.pthread = scm_i_pthread_self ();
|
||||
t.handle = SCM_BOOL_F;
|
||||
t.result = SCM_BOOL_F;
|
||||
t.cleanup_handler = SCM_BOOL_F;
|
||||
t.mutexes = SCM_EOL;
|
||||
t.held_mutex = NULL;
|
||||
t.join_queue = SCM_EOL;
|
||||
t.dynamic_state = SCM_BOOL_F;
|
||||
t.dynwinds = SCM_EOL;
|
||||
t.active_asyncs = SCM_EOL;
|
||||
t.block_asyncs = 1;
|
||||
t.pending_asyncs = 1;
|
||||
t.critical_section_level = 0;
|
||||
t.base = base->mem_base;
|
||||
#ifdef __ia64__
|
||||
/* Calculate and store off the base of this thread's register
|
||||
backing store (RBS). Unfortunately our implementation(s) of
|
||||
scm_ia64_register_backing_store_base are only reliable for the
|
||||
main thread. For other threads, therefore, find out the current
|
||||
top of the RBS, and use that as a maximum. */
|
||||
t->register_backing_store_base = scm_ia64_register_backing_store_base ();
|
||||
{
|
||||
ucontext_t ctx;
|
||||
void *bsp;
|
||||
getcontext (&ctx);
|
||||
bsp = scm_ia64_ar_bsp (&ctx);
|
||||
if (t->register_backing_store_base > bsp)
|
||||
t->register_backing_store_base = bsp;
|
||||
}
|
||||
t.register_backing_store_base = base->reg-base;
|
||||
#endif
|
||||
t->continuation_root = SCM_EOL;
|
||||
t->continuation_base = base;
|
||||
scm_i_pthread_cond_init (&t->sleep_cond, NULL);
|
||||
t->sleep_mutex = NULL;
|
||||
t->sleep_object = SCM_BOOL_F;
|
||||
t->sleep_fd = -1;
|
||||
t.continuation_root = SCM_EOL;
|
||||
t.continuation_base = t.base;
|
||||
scm_i_pthread_cond_init (&t.sleep_cond, NULL);
|
||||
t.sleep_mutex = NULL;
|
||||
t.sleep_object = SCM_BOOL_F;
|
||||
t.sleep_fd = -1;
|
||||
|
||||
if (pipe (t->sleep_pipe) != 0)
|
||||
if (pipe (t.sleep_pipe) != 0)
|
||||
/* FIXME: Error conditions during the initialization phase are handled
|
||||
gracelessly since public functions such as `scm_init_guile ()'
|
||||
currently have type `void'. */
|
||||
abort ();
|
||||
|
||||
scm_i_pthread_mutex_init (&t->admin_mutex, NULL);
|
||||
t->current_mark_stack_ptr = NULL;
|
||||
t->current_mark_stack_limit = NULL;
|
||||
t->canceled = 0;
|
||||
t->exited = 0;
|
||||
t->guile_mode = 0;
|
||||
scm_i_pthread_mutex_init (&t.admin_mutex, NULL);
|
||||
t.current_mark_stack_ptr = NULL;
|
||||
t.current_mark_stack_limit = NULL;
|
||||
t.canceled = 0;
|
||||
t.exited = 0;
|
||||
t.guile_mode = 0;
|
||||
|
||||
SET_CURRENT_THREAD (t);
|
||||
/* The switcheroo. */
|
||||
{
|
||||
scm_i_thread *t_ptr = &t;
|
||||
|
||||
GC_disable ();
|
||||
t_ptr = GC_malloc (sizeof (scm_i_thread));
|
||||
memcpy (t_ptr, &t, sizeof t);
|
||||
|
||||
scm_i_pthread_setspecific (scm_i_thread_key, t_ptr);
|
||||
|
||||
#ifdef SCM_HAVE_THREAD_STORAGE_CLASS
|
||||
/* Cache the current thread in TLS for faster lookup. */
|
||||
scm_i_current_thread = t_ptr;
|
||||
#endif
|
||||
|
||||
scm_i_pthread_mutex_lock (&thread_admin_mutex);
|
||||
t->next_thread = all_threads;
|
||||
all_threads = t;
|
||||
t_ptr->next_thread = all_threads;
|
||||
all_threads = t_ptr;
|
||||
thread_count++;
|
||||
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
|
||||
|
||||
GC_enable ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform second stage of thread initialisation, in guile mode.
|
||||
|
@ -537,6 +657,15 @@ do_thread_exit (void *v)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
do_thread_exit_trampoline (struct GC_stack_base *sb, void *v)
|
||||
{
|
||||
/* Won't hurt if we are already registered. */
|
||||
GC_register_my_thread (sb);
|
||||
|
||||
return scm_with_guile (do_thread_exit, v);
|
||||
}
|
||||
|
||||
static void
|
||||
on_thread_exit (void *v)
|
||||
{
|
||||
|
@ -551,19 +680,18 @@ on_thread_exit (void *v)
|
|||
t->held_mutex = NULL;
|
||||
}
|
||||
|
||||
SET_CURRENT_THREAD (v);
|
||||
/* Reinstate the current thread for purposes of scm_with_guile
|
||||
guile-mode cleanup handlers. Only really needed in the non-TLS
|
||||
case but it doesn't hurt to be consistent. */
|
||||
scm_i_pthread_setspecific (scm_i_thread_key, t);
|
||||
|
||||
/* Ensure the signal handling thread has been launched, because we might be
|
||||
shutting it down. */
|
||||
scm_i_ensure_signal_delivery_thread ();
|
||||
|
||||
/* Unblocking the joining threads needs to happen in guile mode
|
||||
since the queue is a SCM data structure. */
|
||||
|
||||
/* Note: Since `do_thread_exit ()' uses allocates memory via `libgc', we
|
||||
assume the GC is usable at this point, and notably that thread-local
|
||||
storage (TLS) hasn't been deallocated yet. */
|
||||
do_thread_exit (v);
|
||||
/* Scheme-level thread finalizers and other cleanup needs to happen in
|
||||
guile mode. */
|
||||
GC_call_with_stack_base (do_thread_exit_trampoline, t);
|
||||
|
||||
/* Removing ourself from the list of all threads needs to happen in
|
||||
non-guile mode since all SCM values on our stack become
|
||||
|
@ -590,21 +718,21 @@ on_thread_exit (void *v)
|
|||
|
||||
scm_i_pthread_mutex_unlock (&thread_admin_mutex);
|
||||
|
||||
SET_CURRENT_THREAD (NULL);
|
||||
}
|
||||
scm_i_pthread_setspecific (scm_i_thread_key, NULL);
|
||||
|
||||
#ifndef SCM_HAVE_THREAD_STORAGE_CLASS
|
||||
#if !SCM_USE_NULL_THREADS
|
||||
GC_unregister_my_thread ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static scm_i_pthread_once_t init_thread_key_once = SCM_I_PTHREAD_ONCE_INIT;
|
||||
|
||||
static void
|
||||
init_thread_key (void)
|
||||
{
|
||||
scm_i_pthread_key_create (&scm_i_thread_key, NULL);
|
||||
scm_i_pthread_key_create (&scm_i_thread_key, on_thread_exit);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Perform any initializations necessary to make the current thread
|
||||
known to Guile (via SCM_I_CURRENT_THREAD), initializing Guile itself,
|
||||
if necessary.
|
||||
|
@ -623,11 +751,9 @@ init_thread_key (void)
|
|||
be sure. New threads are put into guile mode implicitly. */
|
||||
|
||||
static int
|
||||
scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent)
|
||||
scm_i_init_thread_for_guile (struct GC_stack_base *base, SCM parent)
|
||||
{
|
||||
#ifndef SCM_HAVE_THREAD_STORAGE_CLASS
|
||||
scm_i_pthread_once (&init_thread_key_once, init_thread_key);
|
||||
#endif
|
||||
|
||||
if (SCM_I_CURRENT_THREAD)
|
||||
{
|
||||
|
@ -647,6 +773,12 @@ scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent)
|
|||
initialization.
|
||||
*/
|
||||
scm_i_init_guile (base);
|
||||
|
||||
#ifdef HAVE_GC_ALLOW_REGISTER_THREADS
|
||||
/* Allow other threads to come in later. */
|
||||
GC_allow_register_threads ();
|
||||
#endif
|
||||
|
||||
scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
|
||||
}
|
||||
else
|
||||
|
@ -655,6 +787,10 @@ scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent)
|
|||
the first time. Only initialize this thread.
|
||||
*/
|
||||
scm_i_pthread_mutex_unlock (&scm_i_init_mutex);
|
||||
|
||||
/* Register this thread with libgc. */
|
||||
GC_register_my_thread (base);
|
||||
|
||||
guilify_self_1 (base);
|
||||
guilify_self_2 (parent);
|
||||
}
|
||||
|
@ -662,97 +798,19 @@ scm_i_init_thread_for_guile (SCM_STACKITEM *base, SCM parent)
|
|||
}
|
||||
}
|
||||
|
||||
#if SCM_USE_PTHREAD_THREADS
|
||||
|
||||
#if defined HAVE_PTHREAD_ATTR_GETSTACK && defined HAVE_PTHREAD_GETATTR_NP
|
||||
/* This method for GNU/Linux and perhaps some other systems.
|
||||
It's not for MacOS X or Solaris 10, since pthread_getattr_np is not
|
||||
available on them. */
|
||||
#define HAVE_GET_THREAD_STACK_BASE
|
||||
|
||||
static SCM_STACKITEM *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
void *start, *end;
|
||||
size_t size;
|
||||
|
||||
pthread_getattr_np (pthread_self (), &attr);
|
||||
pthread_attr_getstack (&attr, &start, &size);
|
||||
end = (char *)start + size;
|
||||
|
||||
/* XXX - pthread_getattr_np from LinuxThreads does not seem to work
|
||||
for the main thread, but we can use scm_get_stack_base in that
|
||||
case.
|
||||
*/
|
||||
|
||||
#ifndef PTHREAD_ATTR_GETSTACK_WORKS
|
||||
if ((void *)&attr < start || (void *)&attr >= end)
|
||||
return (SCM_STACKITEM *) GC_stackbottom;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
#if SCM_STACK_GROWS_UP
|
||||
return start;
|
||||
#else
|
||||
return end;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined HAVE_PTHREAD_GET_STACKADDR_NP
|
||||
/* This method for MacOS X.
|
||||
It'd be nice if there was some documentation on pthread_get_stackaddr_np,
|
||||
but as of 2006 there's nothing obvious at apple.com. */
|
||||
#define HAVE_GET_THREAD_STACK_BASE
|
||||
static SCM_STACKITEM *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
return pthread_get_stackaddr_np (pthread_self ());
|
||||
}
|
||||
|
||||
#elif defined (__MINGW32__)
|
||||
/* This method for mingw. In mingw the basic scm_get_stack_base can be used
|
||||
in any thread. We don't like hard-coding the name of a system, but there
|
||||
doesn't seem to be a cleaner way of knowing scm_get_stack_base can
|
||||
work. */
|
||||
#define HAVE_GET_THREAD_STACK_BASE
|
||||
static SCM_STACKITEM *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
return (SCM_STACKITEM *) GC_stackbottom;
|
||||
}
|
||||
|
||||
#endif /* pthread methods of get_thread_stack_base */
|
||||
|
||||
#else /* !SCM_USE_PTHREAD_THREADS */
|
||||
|
||||
#define HAVE_GET_THREAD_STACK_BASE
|
||||
|
||||
static SCM_STACKITEM *
|
||||
get_thread_stack_base ()
|
||||
{
|
||||
return (SCM_STACKITEM *) GC_stackbottom;
|
||||
}
|
||||
|
||||
#endif /* !SCM_USE_PTHREAD_THREADS */
|
||||
|
||||
#ifdef HAVE_GET_THREAD_STACK_BASE
|
||||
|
||||
void
|
||||
scm_init_guile ()
|
||||
{
|
||||
scm_i_init_thread_for_guile (get_thread_stack_base (),
|
||||
struct GC_stack_base stack_base;
|
||||
|
||||
if (GC_get_stack_base (&stack_base) == GC_SUCCESS)
|
||||
scm_i_init_thread_for_guile (&stack_base,
|
||||
scm_i_default_dynamic_state);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *
|
||||
scm_with_guile (void *(*func)(void *), void *data)
|
||||
else
|
||||
{
|
||||
return scm_i_with_guile_and_parent (func, data,
|
||||
scm_i_default_dynamic_state);
|
||||
fprintf (stderr, "Failed to get stack base for current thread.\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
SCM_UNUSED static void
|
||||
|
@ -761,38 +819,37 @@ scm_leave_guile_cleanup (void *x)
|
|||
on_thread_exit (SCM_I_CURRENT_THREAD);
|
||||
}
|
||||
|
||||
struct with_guile_trampoline_args
|
||||
struct with_guile_args
|
||||
{
|
||||
GC_fn_type func;
|
||||
void *data;
|
||||
SCM parent;
|
||||
};
|
||||
|
||||
static void *
|
||||
with_guile_trampoline (void *data)
|
||||
{
|
||||
struct with_guile_trampoline_args *args = data;
|
||||
struct with_guile_args *args = data;
|
||||
|
||||
return scm_c_with_continuation_barrier (args->func, args->data);
|
||||
}
|
||||
|
||||
void *
|
||||
scm_i_with_guile_and_parent (void *(*func)(void *), void *data, SCM parent)
|
||||
static void *
|
||||
with_guile_and_parent (struct GC_stack_base *base, void *data)
|
||||
{
|
||||
void *res;
|
||||
int new_thread;
|
||||
scm_i_thread *t;
|
||||
SCM_STACKITEM base_item;
|
||||
struct with_guile_args *args = data;
|
||||
|
||||
new_thread = scm_i_init_thread_for_guile (&base_item, parent);
|
||||
new_thread = scm_i_init_thread_for_guile (base, args->parent);
|
||||
t = SCM_I_CURRENT_THREAD;
|
||||
if (new_thread)
|
||||
{
|
||||
/* We are in Guile mode. */
|
||||
assert (t->guile_mode);
|
||||
|
||||
scm_i_pthread_cleanup_push (scm_leave_guile_cleanup, NULL);
|
||||
res = scm_c_with_continuation_barrier (func, data);
|
||||
scm_i_pthread_cleanup_pop (0);
|
||||
res = scm_c_with_continuation_barrier (args->func, args->data);
|
||||
|
||||
/* Leave Guile mode. */
|
||||
t->guile_mode = 0;
|
||||
|
@ -800,14 +857,10 @@ scm_i_with_guile_and_parent (void *(*func)(void *), void *data, SCM parent)
|
|||
else if (t->guile_mode)
|
||||
{
|
||||
/* Already in Guile mode. */
|
||||
res = scm_c_with_continuation_barrier (func, data);
|
||||
res = scm_c_with_continuation_barrier (args->func, args->data);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct with_guile_trampoline_args args;
|
||||
args.func = func;
|
||||
args.data = data;
|
||||
|
||||
/* We are not in Guile mode, either because we are not within a
|
||||
scm_with_guile, or because we are within a scm_without_guile.
|
||||
|
||||
|
@ -816,20 +869,39 @@ scm_i_with_guile_and_parent (void *(*func)(void *), void *data, SCM parent)
|
|||
when this thread was first guilified. Thus, `base' must be
|
||||
updated. */
|
||||
#if SCM_STACK_GROWS_UP
|
||||
if (SCM_STACK_PTR (&base_item) < t->base)
|
||||
t->base = SCM_STACK_PTR (&base_item);
|
||||
if (SCM_STACK_PTR (base->mem_base) < t->base)
|
||||
t->base = SCM_STACK_PTR (base->mem_base);
|
||||
#else
|
||||
if (SCM_STACK_PTR (&base_item) > t->base)
|
||||
t->base = SCM_STACK_PTR (&base_item);
|
||||
if (SCM_STACK_PTR (base->mem_base) > t->base)
|
||||
t->base = SCM_STACK_PTR (base->mem_base);
|
||||
#endif
|
||||
|
||||
t->guile_mode = 1;
|
||||
res = with_gc_active (with_guile_trampoline, &args);
|
||||
res = with_gc_active (with_guile_trampoline, args);
|
||||
t->guile_mode = 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void *
|
||||
scm_i_with_guile_and_parent (void *(*func)(void *), void *data, SCM parent)
|
||||
{
|
||||
struct with_guile_args args;
|
||||
|
||||
args.func = func;
|
||||
args.data = data;
|
||||
args.parent = parent;
|
||||
|
||||
return GC_call_with_stack_base (with_guile_and_parent, &args);
|
||||
}
|
||||
|
||||
void *
|
||||
scm_with_guile (void *(*func)(void *), void *data)
|
||||
{
|
||||
return scm_i_with_guile_and_parent (func, data,
|
||||
scm_i_default_dynamic_state);
|
||||
}
|
||||
|
||||
void *
|
||||
scm_without_guile (void *(*func)(void *), void *data)
|
||||
{
|
||||
|
@ -880,9 +952,6 @@ really_launch (void *d)
|
|||
else
|
||||
t->result = scm_catch (SCM_BOOL_T, thunk, handler);
|
||||
|
||||
/* Trigger a call to `on_thread_exit ()'. */
|
||||
pthread_exit (NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1965,7 +2034,7 @@ pthread_mutexattr_t scm_i_pthread_mutexattr_recursive[1];
|
|||
#endif
|
||||
|
||||
void
|
||||
scm_threads_prehistory (SCM_STACKITEM *base)
|
||||
scm_threads_prehistory (void *base)
|
||||
{
|
||||
#if SCM_USE_PTHREAD_THREADS
|
||||
pthread_mutexattr_init (scm_i_pthread_mutexattr_recursive);
|
||||
|
@ -1978,7 +2047,7 @@ scm_threads_prehistory (SCM_STACKITEM *base)
|
|||
scm_i_pthread_mutex_init (&scm_i_misc_mutex, NULL);
|
||||
scm_i_pthread_cond_init (&wake_up_cond, NULL);
|
||||
|
||||
guilify_self_1 (base);
|
||||
guilify_self_1 ((struct GC_stack_base *) base);
|
||||
}
|
||||
|
||||
scm_t_bits scm_tc16_thread;
|
||||
|
|
|
@ -136,13 +136,7 @@ SCM_API SCM scm_spawn_thread (scm_t_catch_body body, void *body_data,
|
|||
SCM_API void *scm_without_guile (void *(*func)(void *), void *data);
|
||||
SCM_API void *scm_with_guile (void *(*func)(void *), void *data);
|
||||
|
||||
SCM_INTERNAL void *scm_i_with_guile_and_parent (void *(*func)(void *),
|
||||
void *data, SCM parent);
|
||||
|
||||
|
||||
void scm_threads_prehistory (SCM_STACKITEM *);
|
||||
void scm_threads_init_first_thread (void);
|
||||
|
||||
SCM_INTERNAL void scm_threads_prehistory (void *);
|
||||
SCM_INTERNAL void scm_init_threads (void);
|
||||
SCM_INTERNAL void scm_init_thread_procs (void);
|
||||
SCM_INTERNAL void scm_init_threads_default_dynamic_state (void);
|
||||
|
@ -192,6 +186,10 @@ SCM_API void scm_dynwind_critical_section (SCM mutex);
|
|||
|
||||
#ifdef BUILDING_LIBGUILE
|
||||
|
||||
/* Though we don't need the key for SCM_I_CURRENT_THREAD if we have TLS,
|
||||
we do use it for cleanup purposes. */
|
||||
SCM_INTERNAL scm_i_pthread_key_t scm_i_thread_key;
|
||||
|
||||
# ifdef SCM_HAVE_THREAD_STORAGE_CLASS
|
||||
|
||||
SCM_INTERNAL SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread;
|
||||
|
@ -199,7 +197,6 @@ SCM_INTERNAL SCM_THREAD_LOCAL scm_i_thread *scm_i_current_thread;
|
|||
|
||||
# else /* !SCM_HAVE_THREAD_STORAGE_CLASS */
|
||||
|
||||
SCM_INTERNAL scm_i_pthread_key_t scm_i_thread_key;
|
||||
# define SCM_I_CURRENT_THREAD \
|
||||
((scm_i_thread *) scm_i_pthread_getspecific (scm_i_thread_key))
|
||||
|
||||
|
|
|
@ -467,7 +467,7 @@ pre_init_catch (SCM tag, SCM thunk, SCM handler, SCM pre_unwind_handler)
|
|||
if (SCM_PROMPT_SETJMP (prompt))
|
||||
{
|
||||
/* nonlocal exit */
|
||||
SCM args = scm_i_prompt_pop_abort_args_x (prompt);
|
||||
SCM args = scm_i_prompt_pop_abort_args_x (vm);
|
||||
/* cdr past the continuation */
|
||||
return scm_apply_0 (handler, scm_cdr (args));
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue