summaryrefslogtreecommitdiffstats
path: root/guile/modules
diff options
context:
space:
mode:
Diffstat (limited to 'guile/modules')
-rw-r--r--guile/modules/gnutls.in616
-rw-r--r--guile/modules/gnutls/build/enums.scm730
-rw-r--r--guile/modules/gnutls/build/smobs.scm231
-rw-r--r--guile/modules/gnutls/build/tests.scm93
-rw-r--r--guile/modules/gnutls/build/utils.scm46
-rw-r--r--guile/modules/gnutls/extra.scm83
-rw-r--r--guile/modules/system/documentation/README15
-rw-r--r--guile/modules/system/documentation/c-snarf.scm210
-rw-r--r--guile/modules/system/documentation/output.scm176
9 files changed, 2200 insertions, 0 deletions
diff --git a/guile/modules/gnutls.in b/guile/modules/gnutls.in
new file mode 100644
index 0000000..67f0a29
--- /dev/null
+++ b/guile/modules/gnutls.in
@@ -0,0 +1,616 @@
+;;; GnuTLS --- Guile bindings for GnuTLS.
+;;; Copyright (C) 2007-2012, 2014, 2015, 2016, 2019, 2021-2022 Free Software
+;;; Foundation, Inc.
+;;;
+;;; GnuTLS 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.1 of the License, or (at your option) any later version.
+;;;
+;;; GnuTLS 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 GnuTLS; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+;;; Written by Ludovic Courtès <ludo@gnu.org>
+
+(define-module (gnutls)
+ ;; Note: The export list must be manually kept in sync with the build
+ ;; system.
+ :export (;; versioning
+ gnutls-version
+
+ ;; sessions
+ session?
+ make-session bye handshake rehandshake reauthenticate
+ alert-get alert-send
+ session-cipher session-kx session-mac session-protocol
+ session-compression-method session-certificate-type
+ session-authentication-type session-server-authentication-type
+ session-client-authentication-type
+ session-peer-certificate-chain session-our-certificate-chain
+ set-session-transport-fd! set-session-transport-port!
+ set-session-credentials! set-server-session-certificate-request!
+ set-session-server-name!
+
+ ;; anonymous credentials
+ anonymous-client-credentials? anonymous-server-credentials?
+ make-anonymous-client-credentials make-anonymous-server-credentials
+ set-anonymous-server-dh-parameters!
+
+ ;; certificate credentials
+ certificate-credentials? make-certificate-credentials
+ set-certificate-credentials-dh-parameters!
+ set-certificate-credentials-x509-key-files!
+ set-certificate-credentials-x509-trust-file!
+ set-certificate-credentials-x509-crl-file!
+ set-certificate-credentials-x509-key-data!
+ set-certificate-credentials-x509-trust-data!
+ set-certificate-credentials-x509-crl-data!
+ set-certificate-credentials-x509-keys!
+ set-certificate-credentials-verify-limits!
+ set-certificate-credentials-verify-flags!
+ peer-certificate-status
+
+ ;; SRP credentials
+ srp-client-credentials? srp-server-credentials?
+ make-srp-client-credentials make-srp-server-credentials
+ set-srp-client-credentials!
+ set-srp-server-credentials-files!
+ server-session-srp-username
+ srp-base64-encode srp-base64-decode
+
+ ;; PSK credentials
+ psk-client-credentials? psk-server-credentials?
+ make-psk-client-credentials make-psk-server-credentials
+ set-psk-client-credentials!
+ set-psk-server-credentials-file!
+ server-session-psk-username
+
+ ;; priorities
+ set-session-priorities!
+ set-session-default-priority!
+
+ ;; DH
+ set-session-dh-prime-bits!
+ make-dh-parameters dh-parameters?
+ pkcs3-import-dh-parameters pkcs3-export-dh-parameters
+
+ ;; X.509
+ x509-certificate? x509-private-key?
+ import-x509-certificate x509-certificate-matches-hostname?
+ x509-certificate-dn x509-certificate-dn-oid
+ x509-certificate-issuer-dn x509-certificate-issuer-dn-oid
+ x509-certificate-signature-algorithm x509-certificate-version
+ x509-certificate-key-id x509-certificate-authority-key-id
+ x509-certificate-subject-key-id
+ x509-certificate-subject-alternative-name
+ x509-certificate-public-key-algorithm x509-certificate-key-usage
+ x509-certificate-fingerprint import-x509-private-key
+ pkcs8-import-x509-private-key
+
+ ;; record layer
+ record-send record-receive!
+ session-record-port
+ set-session-record-port-close!
+
+ ;; debugging
+ set-log-procedure! set-log-level!
+
+ ;; enum->string functions
+ cipher->string kx->string params->string credentials->string
+ mac->string digest->string compression-method->string
+ connection-end->string connection-flag->string
+ alert-level->string
+ alert-description->string handshake-description->string
+ certificate-status->string certificate-request->string
+ close-request->string
+ protocol->string certificate-type->string
+ x509-certificate-format->string
+ x509-subject-alternative-name->string pk-algorithm->string
+ sign-algorithm->string psk-key-format->string key-usage->string
+ certificate-verify->string error->string
+ cipher-suite->string server-name-type->string
+
+ ;; enum values
+ cipher/null
+ cipher/arcfour cipher/arcfour-128
+ cipher/3des-cbc
+ cipher/aes-128-cbc cipher/rijndael-cbc cipher/rijndael-128-cbc
+ cipher/aes-256-cbc cipher/rijndael-256-cbc
+ cipher/arcfour-40
+ cipher/rc2-40-cbc
+ cipher/des-cbc
+ kx/rsa
+ kx/dhe-dss
+ kx/dhe-rsa
+ kx/anon-dh
+ kx/srp
+ kx/rsa-export
+ kx/srp-rsa
+ kx/srp-dss
+ kx/psk
+ kx/dhe-dss
+ params/rsa-export
+ params/dh
+ credentials/certificate
+ credentials/anon
+ credentials/anonymous
+ credentials/srp
+ credentials/psk
+ credentials/ia
+ mac/unknown
+ mac/null
+ mac/md5
+ mac/sha1
+ mac/rmd160
+ mac/md2
+ digest/null
+ digest/md5
+ digest/sha1
+ digest/rmd160
+ digest/md2
+ digest/sha256
+ compression-method/null
+ compression-method/deflate
+ compression-method/lzo
+ connection-end/server
+ connection-end/client
+ connection-flag/datagram
+ connection-flag/nonblock
+ connection-flag/no-extensions
+ connection-flag/no-replay-protection
+ connection-flag/no-signal
+ connection-flag/allow-id-change
+ connection-flag/enable-false-start
+ connection-flag/force-client-cert
+ connection-flag/no-tickets
+ connection-flag/key-share-top
+ connection-flag/key-share-top2
+ connection-flag/key-share-top3
+ connection-flag/post-handshake-auth
+ connection-flag/no-auto-rekey
+ connection-flag/safe-padding-check
+ connection-flag/enable-early-start
+ connection-flag/enable-rawpk
+ connection-flag/auto-reauth
+ connection-flag/enable-early-data
+ alert-level/warning
+ alert-level/fatal
+ alert-description/close-notify
+ alert-description/unexpected-message
+ alert-description/bad-record-mac
+ alert-description/decryption-failed
+ alert-description/record-overflow
+ alert-description/decompression-failure
+ alert-description/handshake-failure
+ alert-description/ssl3-no-certificate
+ alert-description/bad-certificate
+ alert-description/unsupported-certificate
+ alert-description/certificate-revoked
+ alert-description/certificate-expired
+ alert-description/certificate-unknown
+ alert-description/illegal-parameter
+ alert-description/unknown-ca
+ alert-description/access-denied
+ alert-description/decode-error
+ alert-description/decrypt-error
+ alert-description/export-restriction
+ alert-description/protocol-version
+ alert-description/insufficient-security
+ alert-description/internal-error
+ alert-description/user-canceled
+ alert-description/no-renegotiation
+ alert-description/unsupported-extension
+ alert-description/certificate-unobtainable
+ alert-description/unrecognized-name
+ alert-description/unknown-psk-identity
+ alert-description/inner-application-failure
+ alert-description/inner-application-verification
+ handshake-description/hello-request
+ handshake-description/client-hello
+ handshake-description/server-hello
+ handshake-description/certificate-pkt
+ handshake-description/server-key-exchange
+ handshake-description/certificate-request
+ handshake-description/server-hello-done
+ handshake-description/certificate-verify
+ handshake-description/client-key-exchange
+ handshake-description/finished
+ certificate-status/invalid
+ certificate-status/revoked
+ certificate-status/signer-not-found
+ certificate-status/signer-not-ca
+ certificate-status/insecure-algorithm
+ certificate-status/not-activated
+ certificate-status/expired
+ certificate-status/signature-failure
+ certificate-status/revocation-data-superseded
+ certificate-status/unexpected-owner
+ certificate-status/revocation-data-issued-in-future
+ certificate-status/signer-constraints-failed
+ certificate-status/mismatch
+ certificate-status/purpose-mismatch
+ certificate-status/missing-ocsp-status
+ certificate-status/invalid-ocsp-status
+ certificate-status/unknown-crit-extensions
+ certificate-request/ignore
+ certificate-request/request
+ certificate-request/require
+ close-request/rdwr
+ close-request/wr
+ protocol/ssl-3
+ protocol/tls-1.0
+ protocol/tls-1.1
+ protocol/version-unknown
+ certificate-type/x509
+ certificate-type/openpgp
+ x509-certificate-format/der
+ x509-certificate-format/pem
+ x509-subject-alternative-name/dnsname
+ x509-subject-alternative-name/rfc822name
+ x509-subject-alternative-name/uri
+ x509-subject-alternative-name/ipaddress
+ pk-algorithm/rsa
+ pk-algorithm/dsa
+ pk-algorithm/unknown
+ sign-algorithm/unknown
+ sign-algorithm/rsa-sha1
+ sign-algorithm/dsa-sha1
+ sign-algorithm/rsa-md5
+ sign-algorithm/rsa-md2
+ sign-algorithm/rsa-rmd160
+ psk-key-format/raw
+ psk-key-format/hex
+ key-usage/digital-signature
+ key-usage/non-repudiation
+ key-usage/key-encipherment
+ key-usage/data-encipherment
+ key-usage/key-agreement
+ key-usage/key-cert-sign
+ key-usage/crl-sign
+ key-usage/encipher-only
+ key-usage/decipher-only
+ certificate-verify/disable-ca-sign
+ certificate-verify/allow-x509-v1-ca-crt
+ certificate-verify/allow-x509-v1-ca-certificate
+ certificate-verify/do-not-allow-same
+ certificate-verify/allow-any-x509-v1-ca-crt
+ certificate-verify/allow-any-x509-v1-ca-certificate
+ certificate-verify/allow-sign-rsa-md2
+ certificate-verify/allow-sign-rsa-md5
+ server-name-type/dns
+
+ ;; FIXME: Automate this:
+ ;; grep '^#define GNUTLS_E_' ../../lib/includes/gnutls/gnutls.h.in | \
+ ;; sed -r -e 's|^#define GNUTLS_E_([^ ]+).*$|error/\1|' | tr A-Z_ a-z-
+ error/success
+ error/unsupported-version-packet
+ error/tls-packet-decoding-error
+ error/unexpected-packet-length
+ error/invalid-session
+ error/fatal-alert-received
+ error/unexpected-packet
+ error/warning-alert-received
+ error/error-in-finished-packet
+ error/unexpected-handshake-packet
+ error/decryption-failed
+ error/memory-error
+ error/decompression-failed
+ error/compression-failed
+ error/again
+ error/expired
+ error/db-error
+ error/srp-pwd-error
+ error/keyfile-error
+ error/insufficient-credentials
+ error/insuficient-credentials
+ error/insufficient-cred
+ error/insuficient-cred
+ error/hash-failed
+ error/base64-decoding-error
+ error/rehandshake
+ error/got-application-data
+ error/record-limit-reached
+ error/encryption-failed
+ error/pk-encryption-failed
+ error/pk-decryption-failed
+ error/pk-sign-failed
+ error/x509-unsupported-critical-extension
+ error/key-usage-violation
+ error/no-certificate-found
+ error/invalid-request
+ error/short-memory-buffer
+ error/interrupted
+ error/push-error
+ error/pull-error
+ error/received-illegal-parameter
+ error/requested-data-not-available
+ error/pkcs1-wrong-pad
+ error/received-illegal-extension
+ error/internal-error
+ error/dh-prime-unacceptable
+ error/file-error
+ error/too-many-empty-packets
+ error/unknown-pk-algorithm
+ error/too-many-handshake-packets
+ error/received-disallowed-name
+ error/certificate-required
+ error/no-temporary-rsa-params
+ error/no-compression-algorithms
+ error/no-cipher-suites
+ error/openpgp-getkey-failed
+ error/pk-sig-verify-failed
+ error/illegal-srp-username
+ error/srp-pwd-parsing-error
+ error/keyfile-parsing-error
+ error/no-temporary-dh-params
+ error/asn1-element-not-found
+ error/asn1-identifier-not-found
+ error/asn1-der-error
+ error/asn1-value-not-found
+ error/asn1-generic-error
+ error/asn1-value-not-valid
+ error/asn1-tag-error
+ error/asn1-tag-implicit
+ error/asn1-type-any-error
+ error/asn1-syntax-error
+ error/asn1-der-overflow
+ error/openpgp-uid-revoked
+ error/certificate-error
+ error/x509-certificate-error
+ error/certificate-key-mismatch
+ error/unsupported-certificate-type
+ error/x509-unknown-san
+ error/openpgp-fingerprint-unsupported
+ error/x509-unsupported-attribute
+ error/unknown-hash-algorithm
+ error/unknown-pkcs-content-type
+ error/unknown-pkcs-bag-type
+ error/invalid-password
+ error/mac-verify-failed
+ error/constraint-error
+ error/warning-ia-iphf-received
+ error/warning-ia-fphf-received
+ error/ia-verify-failed
+ error/unknown-algorithm
+ error/unsupported-signature-algorithm
+ error/safe-renegotiation-failed
+ error/unsafe-renegotiation-denied
+ error/unknown-srp-username
+ error/premature-termination
+ error/malformed-cidr
+ error/base64-encoding-error
+ error/incompatible-gcrypt-library
+ error/incompatible-crypto-library
+ error/incompatible-libtasn1-library
+ error/openpgp-keyring-error
+ error/x509-unsupported-oid
+ error/random-failed
+ error/base64-unexpected-header-error
+ error/openpgp-subkey-error
+ error/crypto-already-registered
+ error/already-registered
+ error/handshake-too-large
+ error/cryptodev-ioctl-error
+ error/cryptodev-device-error
+ error/channel-binding-not-available
+ error/bad-cookie
+ error/openpgp-preferred-key-error
+ error/incompat-dsa-key-with-tls-protocol
+ error/insufficient-security
+ error/heartbeat-pong-received
+ error/heartbeat-ping-received
+ error/unrecognized-name
+ error/pkcs11-error
+ error/pkcs11-load-error
+ error/parsing-error
+ error/pkcs11-pin-error
+ error/pkcs11-slot-error
+ error/locking-error
+ error/pkcs11-attribute-error
+ error/pkcs11-device-error
+ error/pkcs11-data-error
+ error/pkcs11-unsupported-feature-error
+ error/pkcs11-key-error
+ error/pkcs11-pin-expired
+ error/pkcs11-pin-locked
+ error/pkcs11-session-error
+ error/pkcs11-signature-error
+ error/pkcs11-token-error
+ error/pkcs11-user-error
+ error/crypto-init-failed
+ error/timedout
+ error/user-error
+ error/ecc-no-supported-curves
+ error/ecc-unsupported-curve
+ error/pkcs11-requested-object-not-availble
+ error/certificate-list-unsorted
+ error/illegal-parameter
+ error/no-priorities-were-set
+ error/x509-unsupported-extension
+ error/session-eof
+ error/tpm-error
+ error/tpm-key-password-error
+ error/tpm-srk-password-error
+ error/tpm-session-error
+ error/tpm-key-not-found
+ error/tpm-uninitialized
+ error/tpm-no-lib
+ error/no-certificate-status
+ error/ocsp-response-error
+ error/random-device-error
+ error/auth-error
+ error/no-application-protocol
+ error/sockets-init-error
+ error/key-import-failed
+ error/inappropriate-fallback
+ error/certificate-verification-error
+ error/privkey-verification-error
+ error/unexpected-extensions-length
+ error/asn1-embedded-null-in-string
+ error/self-test-error
+ error/no-self-test
+ error/lib-in-error-state
+ error/pk-generation-error
+ error/idna-error
+ error/need-fallback
+ error/session-user-id-changed
+ error/handshake-during-false-start
+ error/unavailable-during-handshake
+ error/pk-invalid-pubkey
+ error/pk-invalid-privkey
+ error/not-yet-activated
+ error/invalid-utf8-string
+ error/no-embedded-data
+ error/invalid-utf8-email
+ error/invalid-password-string
+ error/certificate-time-error
+ error/record-overflow
+ error/asn1-time-error
+ error/incompatible-sig-with-key
+ error/pk-invalid-pubkey-params
+ error/pk-no-validation-params
+ error/ocsp-mismatch-with-certs
+ error/no-common-key-share
+ error/reauth-request
+ error/too-many-matches
+ error/crl-verification-error
+ error/missing-extension
+ error/db-entry-exists
+ error/early-data-rejected
+ error/unimplemented-feature
+ error/int-ret-0
+ error/int-check-again
+ error/application-error-max
+ error/application-error-min
+
+ fatal-error?
+
+ ;; OpenPGP keys (formerly in GnuTLS-extra)
+ openpgp-certificate? openpgp-private-key?
+ import-openpgp-certificate import-openpgp-private-key
+ openpgp-certificate-id openpgp-certificate-id!
+ openpgp-certificate-fingerprint openpgp-certificate-fingerprint!
+ openpgp-certificate-name openpgp-certificate-names
+ openpgp-certificate-algorithm openpgp-certificate-version
+ openpgp-certificate-usage
+
+ ;; OpenPGP keyrings
+ openpgp-keyring? import-openpgp-keyring
+ openpgp-keyring-contains-key-id?
+
+ ;; certificate credentials
+ set-certificate-credentials-openpgp-keys!
+
+ ;; enum->string functions
+ openpgp-certificate-format->string
+
+ ;; enum values
+ openpgp-certificate-format/raw
+ openpgp-certificate-format/base64))
+
+(eval-when (expand load eval)
+ (define %libdir
+ (or (getenv "GNUTLS_GUILE_EXTENSION_DIR")
+
+ ;; The .scm file is supposed to be architecture-independent. Thus,
+ ;; save 'extensiondir' only if it's different from what Guile expects.
+ @maybe_guileextensiondir@))
+
+ (unless (getenv "GNUTLS_GUILE_CROSS_COMPILING")
+ (load-extension (if %libdir
+ (string-append %libdir "/guile-gnutls-v-2")
+ "guile-gnutls-v-2")
+ "scm_init_gnutls")))
+
+(define-syntax define-deprecated
+ (lambda (s)
+ "Define a deprecated variable or procedure, along these lines:
+
+ (define-deprecated variable alias)
+
+This defines 'variable' as an alias for 'alias', and emits a warning when
+'variable' is used."
+ (syntax-case s ()
+ ((_ variable)
+ (with-syntax ((alias (datum->syntax
+ #'variable
+ (symbol-append
+ '% (syntax->datum #'variable)))))
+ #'(define-deprecated variable alias)))
+ ((_ variable alias)
+ (identifier? #'variable)
+ #`(define-syntax variable
+ (lambda (s)
+ (issue-deprecation-warning
+ (format #f "GnuTLS variable '~a' is deprecated"
+ (syntax->datum #'variable)))
+ (syntax-case s ()
+ ((_ args (... ...))
+ #'(alias args (... ...)))
+ (id
+ (identifier? #'id)
+ #'alias))))))))
+
+
+;; Renaming.
+(define protocol/ssl-3 protocol/ssl3)
+(define protocol/tls-1.0 protocol/tls1-0)
+(define protocol/tls-1.1 protocol/tls1-1)
+
+;; Aliases.
+(define credentials/anonymous credentials/anon)
+(define cipher/rijndael-256-cbc cipher/aes-256-cbc)
+(define cipher/rijndael-128-cbc cipher/aes-128-cbc)
+(define cipher/rijndael-cbc cipher/aes-128-cbc)
+(define cipher/arcfour-128 cipher/arcfour)
+(define certificate-verify/allow-any-x509-v1-ca-certificate
+ certificate-verify/allow-any-x509-v1-ca-crt)
+(define certificate-verify/allow-x509-v1-ca-certificate
+ certificate-verify/allow-x509-v1-ca-crt)
+
+;; Deprecated OpenPGP bindings.
+(define-deprecated certificate-type/openpgp)
+(define-deprecated error/openpgp-getkey-failed)
+(define-deprecated error/openpgp-uid-revoked)
+(define-deprecated error/openpgp-fingerprint-unsupported)
+(define-deprecated error/openpgp-keyring-error)
+(define-deprecated error/openpgp-subkey-error)
+(define-deprecated error/openpgp-preferred-key-error)
+(define-deprecated openpgp-private-key?)
+(define-deprecated import-openpgp-certificate)
+(define-deprecated import-openpgp-private-key)
+(define-deprecated openpgp-certificate-id)
+(define-deprecated openpgp-certificate-id!)
+(define-deprecated openpgp-certificate-fingerprint)
+(define-deprecated openpgp-certificate-fingerprint!)
+(define-deprecated openpgp-certificate-name)
+(define-deprecated openpgp-certificate-names)
+(define-deprecated openpgp-certificate-algorithm)
+(define-deprecated openpgp-certificate-version)
+(define-deprecated openpgp-certificate-usage)
+(define-deprecated openpgp-keyring?)
+(define-deprecated import-openpgp-keyring)
+(define-deprecated openpgp-keyring-contains-key-id?)
+(define-deprecated set-certificate-credentials-openpgp-keys!)
+
+;; XXX: The following bindings should be marked as deprecated as well, but due
+;; to the way binding names are constructed for enums and smobs, it's
+;; complicated. Oh well.
+;;
+;; (define-deprecated openpgp-certificate?)
+;; (define-deprecated openpgp-certificate-format->string)
+;; (define-deprecated openpgp-certificate-format/raw)
+;; (define-deprecated openpgp-certificate-format/base64)
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
+
+;;; arch-tag: 3394732c-d9fa-48dd-a093-9fba3a325b8b
diff --git a/guile/modules/gnutls/build/enums.scm b/guile/modules/gnutls/build/enums.scm
new file mode 100644
index 0000000..4bfbb45
--- /dev/null
+++ b/guile/modules/gnutls/build/enums.scm
@@ -0,0 +1,730 @@
+;;; GnuTLS --- Guile bindings for GnuTLS.
+;;; Copyright (C) 2007-2012, 2014, 2019 Free Software Foundation, Inc.
+;;;
+;;; GnuTLS 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.1 of the License, or (at your option) any later version.
+;;;
+;;; GnuTLS 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 GnuTLS; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+;;; Written by Ludovic Courtès <ludo@chbouib.org>
+
+(define-module (gnutls build enums)
+ :use-module (srfi srfi-1)
+ :use-module (srfi srfi-9)
+ :use-module (gnutls build utils)
+
+ :export (make-enum-type enum-type-subsystem enum-type-value-alist
+ enum-type-c-type enum-type-get-name-function
+ enum-type-automatic-get-name-function
+ enum-type-smob-name
+ enum-type-to-c-function enum-type-from-c-function
+
+ output-enum-smob-definitions output-enum-definitions
+ output-enum-declarations
+ output-enum-definition-function output-c->enum-converter
+ output-enum->c-converter
+
+ %cipher-enum %mac-enum %compression-method-enum %kx-enum
+ %protocol-enum %certificate-type-enum
+
+ %gnutls-enums))
+
+;;;
+;;; This module helps with the creation of bindings for the C enumerate
+;;; types. It aims at providing strong typing (i.e., one cannot use an
+;;; enumerate value of the wrong type) along with authenticity checks (i.e.,
+;;; values of a given enumerate type cannot be forged---for instance, one
+;;; cannot use some random integer as an enumerate value). Additionally,
+;;; Scheme enums representing the same C enum value should be `eq?'.
+;;;
+;;; To that end, Scheme->C conversions are optimized (a simple
+;;; `SCM_SMOB_DATA'), since that is the most common usage pattern.
+;;; Conversely, C->Scheme conversions take time proportional to the number of
+;;; value in the enum type.
+;;;
+
+
+;;;
+;;; Enumeration tools.
+;;;
+
+(define-record-type <enum-type>
+ (%make-enum-type subsystem c-type enum-map get-name value-prefix)
+ enum-type?
+ (subsystem enum-type-subsystem)
+ (enum-map enum-type-value-alist)
+ (c-type enum-type-c-type)
+ (get-name enum-type-get-name-function)
+ (value-prefix enum-type-value-prefix))
+
+
+(define (make-enum-type subsystem c-type values get-name . value-prefix)
+ ;; Return a new enumeration type.
+ (let ((value-prefix (if (null? value-prefix)
+ #f
+ (car value-prefix))))
+ (%make-enum-type subsystem c-type
+ (make-enum-map subsystem values value-prefix)
+ get-name value-prefix)))
+
+
+(define (make-enum-map subsystem values value-prefix)
+ ;; Return an alist mapping C enum values (strings) to Scheme symbols.
+ (define (value-symbol->string value)
+ (string-upcase (scheme-symbol->c-name value)))
+
+ (define (make-c-name value)
+ (case value-prefix
+ ((#f)
+ ;; automatically derive the C value name.
+ (string-append "GNUTLS_" (string-upcase (symbol->string subsystem))
+ "_" (value-symbol->string value)))
+ (else
+ (string-append value-prefix (value-symbol->string value)))))
+
+ (map (lambda (value)
+ (cons (make-c-name value) value))
+ values))
+
+(define (enum-type-smob-name enum)
+ ;; Return the C name of the smob type for ENUM.
+ (string-append "scm_tc16_gnutls_"
+ (scheme-symbol->c-name (enum-type-subsystem enum))
+ "_enum"))
+
+(define (enum-type-smob-list enum)
+ ;; Return the name of the C variable holding a list of value (SMOBs) for
+ ;; ENUM. This list is used when converting from C to Scheme.
+ (string-append "scm_gnutls_"
+ (scheme-symbol->c-name (enum-type-subsystem enum))
+ "_enum_values"))
+
+(define (enum-type-to-c-function enum)
+ ;; Return the name of the C `scm_to_' function for ENUM.
+ (string-append "scm_to_gnutls_"
+ (scheme-symbol->c-name (enum-type-subsystem enum))))
+
+(define (enum-type-from-c-function enum)
+ ;; Return the name of the C `scm_from_' function for ENUM.
+ (string-append "scm_from_gnutls_"
+ (scheme-symbol->c-name (enum-type-subsystem enum))))
+
+(define (enum-type-automatic-get-name-function enum)
+ ;; Return the name of an automatically-generated C function that returns a
+ ;; string describing the given enum value of type ENUM.
+ (string-append "scm_gnutls_"
+ (scheme-symbol->c-name (enum-type-subsystem enum))
+ "_to_c_string"))
+
+
+;;;
+;;; C code generation.
+;;;
+
+(define (output-enum-smob-definitions enum port)
+ (let ((smob (enum-type-smob-name enum))
+ (get-name (enum-type-get-name-function enum)))
+ (format port "SCM_GLOBAL_SMOB (~a, \"~a\", 0);~%"
+ smob (enum-type-subsystem enum))
+ (format port "SCM ~a = SCM_EOL;~%"
+ (enum-type-smob-list enum))
+
+ (if (not (string? get-name))
+ ;; Generate a "get name" function.
+ (output-enum-get-name-function enum port))
+
+ ;; Generate the printer and `->string' function.
+ (let ((get-name (or get-name
+ (enum-type-automatic-get-name-function enum))))
+ (let ((subsystem (scheme-symbol->c-name (enum-type-subsystem enum))))
+ ;; SMOB printer.
+ (format port "SCM_SMOB_PRINT (~a, ~a_print, obj, port, pstate)~%{~%"
+ smob subsystem)
+ (format port " scm_puts (\"#<gnutls-~a-enum \", port);~%"
+ (enum-type-subsystem enum))
+ (format port " scm_puts (~a (~a (obj, 1, \"~a_print\")), port);~%"
+ get-name (enum-type-to-c-function enum) subsystem)
+ (format port " scm_puts (\">\", port);~%")
+ (format port " return 1;~%")
+ (format port "}~%")
+
+ ;; Enum-to-string.
+ (format port "SCM_DEFINE (scm_gnutls_~a_to_string, \"~a->string\", "
+ subsystem (enum-type-subsystem enum))
+ (format port "1, 0, 0,~%")
+ (format port " (SCM enumval),~%")
+ (format port " \"Return a string describing ")
+ (format port "@var{enumval}, a @code{~a} value.\")~%"
+ (enum-type-subsystem enum))
+ (format port "#define FUNC_NAME s_scm_gnutls_~a_to_string~%"
+ subsystem)
+ (format port "{~%")
+ (format port " ~a c_enum;~%"
+ (enum-type-c-type enum))
+ (format port " const char *c_string;~%")
+ (format port " c_enum = ~a (enumval, 1, FUNC_NAME);~%"
+ (enum-type-to-c-function enum))
+ (format port " c_string = ~a (c_enum);~%"
+ get-name)
+ (format port " return (scm_from_locale_string (c_string));~%")
+ (format port "}~%")
+ (format port "#undef FUNC_NAME~%")))))
+
+(define (output-enum-definitions enum port)
+ ;; Output to PORT the Guile C code that defines the values of ENUM-ALIST.
+ (let ((subsystem (scheme-symbol->c-name (enum-type-subsystem enum))))
+ (format port " enum_values = SCM_EOL;~%")
+ (for-each (lambda (c+scheme)
+ (format port " SCM_NEWSMOB (enum_smob, ~a, "
+ (enum-type-smob-name enum))
+ (format port "(scm_t_bits) ~a);~%"
+ (car c+scheme))
+ (format port " enum_values = scm_cons (enum_smob, ")
+ (format port "enum_values);~%")
+ (format port " scm_c_define (\"~a\", enum_smob);~%"
+ (symbol-append (enum-type-subsystem enum) '/
+ (cdr c+scheme))))
+ (enum-type-value-alist enum))
+ (format port " ~a = scm_permanent_object (enum_values);~%"
+ (enum-type-smob-list enum))))
+
+(define (output-enum-declarations enum port)
+ ;; Issue header file declarations needed for the inline functions that
+ ;; handle ENUM values.
+ (format port "SCM_API scm_t_bits ~a;~%"
+ (enum-type-smob-name enum))
+ (format port "SCM_API SCM ~a;~%"
+ (enum-type-smob-list enum)))
+
+(define (output-enum-definition-function enums port)
+ ;; Output a C function that does all the `scm_c_define ()' for the enums
+ ;; listed in ENUMS.
+ (format port "static inline void~%scm_gnutls_define_enums (void)~%{~%")
+ (format port " SCM enum_values, enum_smob;~%")
+ (for-each (lambda (enum)
+ (output-enum-definitions enum port))
+ enums)
+ (format port "}~%"))
+
+(define (output-c->enum-converter enum port)
+ ;; Output a C->Scheme converted for ENUM. This works by walking the list
+ ;; of available enum values (SMOBs) for ENUM and then returning the
+ ;; matching SMOB, so that users can then compare enums using `eq?'. While
+ ;; this may look inefficient, this shouldn't be a problem since (i)
+ ;; conversion in that direction is rarely needed and (ii) the number of
+ ;; values per enum is expected to be small.
+ (format port "static inline SCM~%~a (~a c_obj)~%{~%"
+ (enum-type-from-c-function enum)
+ (enum-type-c-type enum))
+ (format port " SCM pair, result = SCM_BOOL_F;~%")
+ (format port " for (pair = ~a; scm_is_pair (pair); "
+ (enum-type-smob-list enum))
+ (format port "pair = SCM_CDR (pair))~%")
+ (format port " {~%")
+ (format port " SCM enum_smob;~%")
+ (format port " enum_smob = SCM_CAR (pair);~%")
+ (format port " if ((~a) SCM_SMOB_DATA (enum_smob) == c_obj)~%"
+ (enum-type-c-type enum))
+ (format port " {~%")
+ (format port " result = enum_smob;~%")
+ (format port " break;~%")
+ (format port " }~%")
+ (format port " }~%")
+ (format port " return result;~%")
+ (format port "}~%"))
+
+(define (output-enum->c-converter enum port)
+ (let* ((c-type-name (enum-type-c-type enum))
+ (subsystem (scheme-symbol->c-name (enum-type-subsystem enum))))
+
+ (format port
+ "static inline ~a~%~a (SCM obj, unsigned pos, const char *func)~%"
+ c-type-name (enum-type-to-c-function enum))
+ (format port "#define FUNC_NAME func~%")
+ (format port "{~%")
+ (format port " SCM_VALIDATE_SMOB (pos, obj, ~a);~%"
+ (string-append "gnutls_" subsystem "_enum"))
+ (format port " return ((~a) SCM_SMOB_DATA (obj));~%"
+ c-type-name)
+ (format port "}~%")
+ (format port "#undef FUNC_NAME~%")))
+
+(define (output-enum-get-name-function enum port)
+ ;; Output a C function that, when passed a C ENUM value, returns a C string
+ ;; representing that value.
+ (let ((function (enum-type-automatic-get-name-function enum)))
+ (format port
+ "static const char *~%~a (~a c_obj)~%"
+ function (enum-type-c-type enum))
+ (format port "{~%")
+ (format port " static const struct ")
+ (format port "{ ~a value; const char *name; } "
+ (enum-type-c-type enum))
+ (format port "table[] =~%")
+ (format port " {~%")
+ (for-each (lambda (c+scheme)
+ (format port " { ~a, \"~a\" },~%"
+ (car c+scheme) (cdr c+scheme)))
+ (enum-type-value-alist enum))
+ (format port " };~%")
+ (format port " unsigned i;~%")
+ (format port " const char *name = NULL;~%")
+ (format port " for (i = 0; i < ~a; i++)~%"
+ (length (enum-type-value-alist enum)))
+ (format port " {~%")
+ (format port " if (table[i].value == c_obj)~%")
+ (format port " {~%")
+ (format port " name = table[i].name;~%")
+ (format port " break;~%")
+ (format port " }~%")
+ (format port " }~%")
+ (format port " return (name);~%")
+ (format port "}~%")))
+
+
+;;;
+;;; Actual enumerations.
+;;;
+
+(define %cipher-enum
+ (make-enum-type 'cipher "gnutls_cipher_algorithm_t"
+ '(null arcfour 3des-cbc aes-128-cbc aes-256-cbc
+ arcfour-40 rc2-40-cbc des-cbc)
+ "gnutls_cipher_get_name"))
+
+(define %kx-enum
+ (make-enum-type 'kx "gnutls_kx_algorithm_t"
+ '(rsa dhe-dss dhe-rsa anon-dh srp rsa-export
+ srp-rsa srp-dss psk dhe-dss)
+ "gnutls_kx_get_name"))
+
+(define %params-enum
+ (make-enum-type 'params "gnutls_params_type_t"
+ '(rsa-export dh)
+ #f))
+
+(define %credentials-enum
+ (make-enum-type 'credentials "gnutls_credentials_type_t"
+ '(certificate anon srp psk ia)
+ #f
+ "GNUTLS_CRD_"))
+
+(define %mac-enum
+ (make-enum-type 'mac "gnutls_mac_algorithm_t"
+ '(unknown null md5 sha1 rmd160 md2)
+ "gnutls_mac_get_name"))
+
+(define %digest-enum
+ (make-enum-type 'digest "gnutls_digest_algorithm_t"
+ '(null md5 sha1 rmd160 md2 sha256)
+ #f
+ "GNUTLS_DIG_"))
+
+(define %compression-method-enum
+ (make-enum-type 'compression-method "gnutls_compression_method_t"
+ '(null deflate)
+ "gnutls_compression_get_name"
+ "GNUTLS_COMP_"))
+
+(define %connection-end-enum
+ (make-enum-type 'connection-end "gnutls_connection_end_t"
+ '(server client)
+ #f
+ "GNUTLS_"))
+
+(define %connection-flag-enum
+ (make-enum-type 'connection-flag "gnutls_init_flags_t"
+ '(datagram
+ nonblock
+ no-extensions
+ no-replay-protection
+ no-signal
+ allow-id-change
+ enable-false-start
+ force-client-cert
+ no-tickets
+ key-share-top
+ key-share-top2
+ key-share-top3
+ post-handshake-auth
+ no-auto-rekey
+ safe-padding-check
+ enable-early-start
+ enable-rawpk
+ auto-reauth
+ enable-early-data)
+ #f
+ "GNUTLS_"))
+
+(define %alert-level-enum
+ (make-enum-type 'alert-level "gnutls_alert_level_t"
+ '(warning fatal)
+ #f
+ "GNUTLS_AL_"))
+
+(define %alert-description-enum
+ (make-enum-type 'alert-description "gnutls_alert_description_t"
+ '(close-notify unexpected-message bad-record-mac
+decryption-failed record-overflow decompression-failure handshake-failure
+ssl3-no-certificate bad-certificate unsupported-certificate
+certificate-revoked certificate-expired certificate-unknown illegal-parameter
+unknown-ca access-denied decode-error decrypt-error export-restriction
+protocol-version insufficient-security internal-error user-canceled
+no-renegotiation unsupported-extension certificate-unobtainable
+unrecognized-name unknown-psk-identity)
+ #f
+ "GNUTLS_A_"))
+
+(define %handshake-description-enum
+ (make-enum-type 'handshake-description "gnutls_handshake_description_t"
+ '(hello-request client-hello server-hello certificate-pkt
+ server-key-exchange certificate-request server-hello-done
+ certificate-verify client-key-exchange finished)
+ #f
+ "GNUTLS_HANDSHAKE_"))
+
+(define %certificate-status-enum
+ (make-enum-type 'certificate-status "gnutls_certificate_status_t"
+ '(invalid revoked signer-not-found signer-not-ca
+ insecure-algorithm not-activated expired
+ signature-failure revocation-data-superseded
+ unexpected-owner revocation-data-issued-in-future
+ signer-constraints-failure mismatch purpose-mismatch
+ missing-ocsp-status invalid-ocsp-status
+ unknown-crit-extensions)
+ #f
+ "GNUTLS_CERT_"))
+
+(define %certificate-request-enum
+ (make-enum-type 'certificate-request "gnutls_certificate_request_t"
+ '(ignore request require)
+ #f
+ "GNUTLS_CERT_"))
+
+;; XXX: Broken naming convention.
+; (define %openpgp-key-status-enum
+; (make-enum-type 'openpgp-key-status "gnutls_openpgp_key_status_t"
+; '(key fingerprint)
+; #f
+; "GNUTLS_OPENPGP_"))
+
+(define %close-request-enum
+ (make-enum-type 'close-request "gnutls_close_request_t"
+ '(rdwr wr) ;; FIXME: Check the meaning and rename
+ #f
+ "GNUTLS_SHUT_"))
+
+(define %protocol-enum
+ (make-enum-type 'protocol "gnutls_protocol_t"
+ '(ssl3 tls1-0 tls1-1 version-unknown)
+ #f
+ "GNUTLS_"))
+
+(define %certificate-type-enum
+ (make-enum-type 'certificate-type "gnutls_certificate_type_t"
+ '(x509 openpgp)
+ "gnutls_certificate_type_get_name"
+ "GNUTLS_CRT_"))
+
+(define %x509-certificate-format-enum
+ (make-enum-type 'x509-certificate-format "gnutls_x509_crt_fmt_t"
+ '(der pem)
+ #f
+ "GNUTLS_X509_FMT_"))
+
+(define %x509-subject-alternative-name-enum
+ (make-enum-type 'x509-subject-alternative-name
+ "gnutls_x509_subject_alt_name_t"
+ '(dnsname rfc822name uri ipaddress)
+ #f
+ "GNUTLS_SAN_"))
+
+(define %pk-algorithm-enum
+ (make-enum-type 'pk-algorithm "gnutls_pk_algorithm_t"
+ '(unknown rsa dsa)
+ "gnutls_pk_algorithm_get_name"
+ "GNUTLS_PK_"))
+
+(define %sign-algorithm-enum
+ (make-enum-type 'sign-algorithm "gnutls_sign_algorithm_t"
+ '(unknown rsa-sha1 dsa-sha1 rsa-md5 rsa-md2
+ rsa-rmd160)
+ "gnutls_sign_algorithm_get_name"
+ "GNUTLS_SIGN_"))
+
+(define %psk-key-format-enum
+ (make-enum-type 'psk-key-format "gnutls_psk_key_flags"
+ '(raw hex)
+ #f
+ "GNUTLS_PSK_KEY_"))
+
+(define %key-usage-enum
+ ;; Not actually an enum on the C side.
+ (make-enum-type 'key-usage "int"
+ '(digital-signature non-repudiation key-encipherment
+ data-encipherment key-agreement key-cert-sign
+ crl-sign encipher-only decipher-only)
+ #f
+ "GNUTLS_KEY_"))
+
+(define %certificate-verify-enum
+ (make-enum-type 'certificate-verify "gnutls_certificate_verify_flags"
+ '(disable-ca-sign allow-x509-v1-ca-crt
+ do-not-allow-same allow-any-x509-v1-ca-crt
+ allow-sign-rsa-md2 allow-sign-rsa-md5)
+ #f
+ "GNUTLS_VERIFY_"))
+
+(define %error-enum
+ (make-enum-type 'error "int"
+ '(
+;; FIXME: Automate this:
+;; grep '^#define GNUTLS_E_' ../../../lib/includes/gnutls/gnutls.h.in \
+;; | sed -r -e 's/^#define GNUTLS_E_([^ ]+).*$/\1/' | tr A-Z_ a-z-
+success
+unsupported-version-packet
+tls-packet-decoding-error
+unexpected-packet-length
+invalid-session
+fatal-alert-received
+unexpected-packet
+warning-alert-received
+error-in-finished-packet
+unexpected-handshake-packet
+decryption-failed
+memory-error
+decompression-failed
+compression-failed
+again
+expired
+db-error
+srp-pwd-error
+keyfile-error
+insufficient-credentials
+insuficient-credentials
+insufficient-cred
+insuficient-cred
+hash-failed
+base64-decoding-error
+rehandshake
+got-application-data
+record-limit-reached
+encryption-failed
+pk-encryption-failed
+pk-decryption-failed
+pk-sign-failed
+x509-unsupported-critical-extension
+key-usage-violation
+no-certificate-found
+invalid-request
+short-memory-buffer
+interrupted
+push-error
+pull-error
+received-illegal-parameter
+requested-data-not-available
+pkcs1-wrong-pad
+received-illegal-extension
+internal-error
+dh-prime-unacceptable
+file-error
+too-many-empty-packets
+unknown-pk-algorithm
+too-many-handshake-packets
+received-disallowed-name
+certificate-required
+no-temporary-rsa-params
+no-compression-algorithms
+no-cipher-suites
+openpgp-getkey-failed
+pk-sig-verify-failed
+illegal-srp-username
+srp-pwd-parsing-error
+keyfile-parsing-error
+no-temporary-dh-params
+asn1-element-not-found
+asn1-identifier-not-found
+asn1-der-error
+asn1-value-not-found
+asn1-generic-error
+asn1-value-not-valid
+asn1-tag-error
+asn1-tag-implicit
+asn1-type-any-error
+asn1-syntax-error
+asn1-der-overflow
+openpgp-uid-revoked
+certificate-error
+x509-certificate-error
+certificate-key-mismatch
+unsupported-certificate-type
+x509-unknown-san
+openpgp-fingerprint-unsupported
+x509-unsupported-attribute
+unknown-hash-algorithm
+unknown-pkcs-content-type
+unknown-pkcs-bag-type
+invalid-password
+mac-verify-failed
+constraint-error
+warning-ia-iphf-received
+warning-ia-fphf-received
+ia-verify-failed
+unknown-algorithm
+unsupported-signature-algorithm
+safe-renegotiation-failed
+unsafe-renegotiation-denied
+unknown-srp-username
+premature-termination
+malformed-cidr
+base64-encoding-error
+incompatible-gcrypt-library
+incompatible-crypto-library
+incompatible-libtasn1-library
+openpgp-keyring-error
+x509-unsupported-oid
+random-failed
+base64-unexpected-header-error
+openpgp-subkey-error
+crypto-already-registered
+already-registered
+handshake-too-large
+cryptodev-ioctl-error
+cryptodev-device-error
+channel-binding-not-available
+bad-cookie
+openpgp-preferred-key-error
+incompat-dsa-key-with-tls-protocol
+insufficient-security
+heartbeat-pong-received
+heartbeat-ping-received
+unrecognized-name
+pkcs11-error
+pkcs11-load-error
+parsing-error
+pkcs11-pin-error
+pkcs11-slot-error
+locking-error
+pkcs11-attribute-error
+pkcs11-device-error
+pkcs11-data-error
+pkcs11-unsupported-feature-error
+pkcs11-key-error
+pkcs11-pin-expired
+pkcs11-pin-locked
+pkcs11-session-error
+pkcs11-signature-error
+pkcs11-token-error
+pkcs11-user-error
+crypto-init-failed
+timedout
+user-error
+ecc-no-supported-curves
+ecc-unsupported-curve
+pkcs11-requested-object-not-availble
+certificate-list-unsorted
+illegal-parameter
+no-priorities-were-set
+x509-unsupported-extension
+session-eof
+tpm-error
+tpm-key-password-error
+tpm-srk-password-error
+tpm-session-error
+tpm-key-not-found
+tpm-uninitialized
+tpm-no-lib
+no-certificate-status
+ocsp-response-error
+random-device-error
+auth-error
+no-application-protocol
+sockets-init-error
+key-import-failed
+inappropriate-fallback
+certificate-verification-error
+privkey-verification-error
+unexpected-extensions-length
+asn1-embedded-null-in-string
+self-test-error
+no-self-test
+lib-in-error-state
+pk-generation-error
+idna-error
+need-fallback
+session-user-id-changed
+handshake-during-false-start
+unavailable-during-handshake
+pk-invalid-pubkey
+pk-invalid-privkey
+not-yet-activated
+invalid-utf8-string
+no-embedded-data
+invalid-utf8-email
+invalid-password-string
+certificate-time-error
+record-overflow
+asn1-time-error
+incompatible-sig-with-key
+pk-invalid-pubkey-params
+pk-no-validation-params
+ocsp-mismatch-with-certs
+no-common-key-share
+reauth-request
+too-many-matches
+crl-verification-error
+missing-extension
+db-entry-exists
+early-data-rejected
+unimplemented-feature
+int-ret-0
+int-check-again
+application-error-max
+application-error-min
+)
+ "gnutls_strerror"
+ "GNUTLS_E_"))
+
+
+(define %openpgp-certificate-format-enum
+ (make-enum-type 'openpgp-certificate-format "gnutls_openpgp_crt_fmt_t"
+ '(raw base64)
+ #f
+ "GNUTLS_OPENPGP_FMT_"))
+
+(define %server-name-type-enum
+ (make-enum-type 'server-name-type "gnutls_server_name_type_t"
+ '(dns)
+ #f
+ "GNUTLS_NAME_"))
+
+(define %gnutls-enums
+ ;; All enums.
+ (list %cipher-enum %kx-enum %params-enum %credentials-enum %mac-enum
+ %digest-enum %compression-method-enum
+ %connection-end-enum %connection-flag-enum
+ %alert-level-enum %alert-description-enum %handshake-description-enum
+ %certificate-status-enum %certificate-request-enum
+ %close-request-enum %protocol-enum %certificate-type-enum
+ %x509-certificate-format-enum %x509-subject-alternative-name-enum
+ %pk-algorithm-enum %sign-algorithm-enum %server-name-type-enum
+ %psk-key-format-enum %key-usage-enum %certificate-verify-enum
+ %error-enum
+
+ %openpgp-certificate-format-enum))
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
+
+;;; arch-tag: 9e3eb6bb-61a5-4e85-861f-1914ab9677b0
diff --git a/guile/modules/gnutls/build/smobs.scm b/guile/modules/gnutls/build/smobs.scm
new file mode 100644
index 0000000..9612922
--- /dev/null
+++ b/guile/modules/gnutls/build/smobs.scm
@@ -0,0 +1,231 @@
+;;; Help produce Guile wrappers for GnuTLS types.
+;;;
+;;; GnuTLS --- Guile bindings for GnuTLS.
+;;; Copyright (C) 2007-2012, 2014 Free Software Foundation, Inc.
+;;;
+;;; GnuTLS 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.1 of the License, or (at your option) any later version.
+;;;
+;;; GnuTLS 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 GnuTLS; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+;;; Written by Ludovic Courtès <ludo@chbouib.org>
+
+(define-module (gnutls build smobs)
+ :use-module (srfi srfi-9)
+ :use-module (srfi srfi-13)
+ :use-module (gnutls build utils)
+ :export (make-smob-type smob-type-tag smob-free-function
+ smob-type-predicate-scheme-name
+ smob-type-from-c-function smob-type-to-c-function
+
+ output-smob-type-definition output-smob-type-declaration
+ output-smob-type-predicate
+ output-c->smob-converter output-smob->c-converter
+
+ %gnutls-smobs))
+
+
+;;;
+;;; SMOB types.
+;;;
+
+(define-record-type <smob-type>
+ (%make-smob-type c-name scm-name free-function)
+ smob-type?
+ (c-name smob-type-c-name)
+ (scm-name smob-type-scheme-name)
+ (free-function smob-type-free-function))
+
+(define (make-smob-type c-name scm-name . free-function)
+ (%make-smob-type c-name scm-name
+ (if (null? free-function)
+ (string-append "gnutls_"
+ (scheme-symbol->c-name scm-name)
+ "_deinit")
+ (car free-function))))
+
+(define (smob-type-tag type)
+ ;; Return the name of the C variable holding the type tag for TYPE.
+ (string-append "scm_tc16_gnutls_"
+ (scheme-symbol->c-name (smob-type-scheme-name type))))
+
+(define (smob-type-predicate-scheme-name type)
+ ;; Return a string denoting the Scheme name of TYPE's type predicate.
+ (string-append (symbol->string (smob-type-scheme-name type)) "?"))
+
+(define (smob-type-to-c-function type)
+ ;; Return the name of the C `scm_to_' function for SMOB.
+ (string-append "scm_to_gnutls_"
+ (scheme-symbol->c-name (smob-type-scheme-name type))))
+
+(define (smob-type-from-c-function type)
+ ;; Return the name of the C `scm_from_' function for SMOB.
+ (string-append "scm_from_gnutls_"
+ (scheme-symbol->c-name (smob-type-scheme-name type))))
+
+
+;;;
+;;; C code generation.
+;;;
+
+(define (output-smob-type-definition type port)
+ (format port "SCM_GLOBAL_SMOB (~a, \"~a\", 0);~%"
+ (smob-type-tag type)
+ (smob-type-scheme-name type))
+
+ (format port "SCM_SMOB_FREE (~a, ~a_free, obj)~%{~%"
+ (smob-type-tag type)
+ (scheme-symbol->c-name (smob-type-scheme-name type)))
+ (format port " ~a c_obj;~%"
+ (smob-type-c-name type))
+ (format port " c_obj = (~a) SCM_SMOB_DATA (obj);~%"
+ (smob-type-c-name type))
+ (format port " ~a (c_obj);~%"
+ (smob-type-free-function type))
+ (format port " return 0;~%")
+ (format port "}~%"))
+
+(define (output-smob-type-declaration type port)
+ ;; Issue a header file declaration for the SMOB type tag of TYPE.
+ (format port "SCM_API scm_t_bits ~a;~%"
+ (smob-type-tag type)))
+
+(define (output-smob-type-predicate type port)
+ (define (texi-doc-string)
+ (string-append "Return true if @var{obj} is of type @code{"
+ (symbol->string (smob-type-scheme-name type))
+ "}."))
+
+ (let ((c-name (string-append "scm_gnutls_"
+ (string-map (lambda (chr)
+ (if (char=? chr #\-)
+ #\_
+ chr))
+ (symbol->string
+ (smob-type-scheme-name type)))
+ "_p")))
+ (format port "SCM_DEFINE (~a, \"~a\", 1, 0, 0,~%"
+ c-name (smob-type-predicate-scheme-name type))
+ (format port " (SCM obj),~%")
+ (format port " \"~a\")~%"
+ (texi-doc-string))
+ (format port "#define FUNC_NAME s_~a~%"
+ c-name)
+ (format port "{~%")
+ (format port " return (scm_from_bool (SCM_SMOB_PREDICATE (~a, obj)));~%"
+ (smob-type-tag type))
+ (format port "}~%#undef FUNC_NAME~%")))
+
+(define (output-c->smob-converter type port)
+ (format port "static inline SCM~%~a (~a c_obj)~%{~%"
+ (smob-type-from-c-function type)
+ (smob-type-c-name type))
+ (format port " SCM_RETURN_NEWSMOB (~a, (scm_t_bits) c_obj);~%"
+ (smob-type-tag type))
+ (format port "}~%"))
+
+(define (output-smob->c-converter type port)
+ (format port "static inline ~a~%~a (SCM obj, "
+ (smob-type-c-name type)
+ (smob-type-to-c-function type))
+ (format port "unsigned pos, const char *func)~%")
+ (format port "#define FUNC_NAME func~%")
+ (format port "{~%")
+ (format port " SCM_VALIDATE_SMOB (pos, obj, ~a);~%"
+ (string-append "gnutls_"
+ (scheme-symbol->c-name (smob-type-scheme-name type))))
+ (format port " return ((~a) SCM_SMOB_DATA (obj));~%"
+ (smob-type-c-name type))
+ (format port "}~%")
+ (format port "#undef FUNC_NAME~%"))
+
+
+;;;
+;;; Actual SMOB types.
+;;;
+
+(define %session-smob
+ (make-smob-type "gnutls_session_t" 'session
+ "gnutls_deinit"))
+
+(define %anonymous-client-credentials-smob
+ (make-smob-type "gnutls_anon_client_credentials_t" 'anonymous-client-credentials
+ "gnutls_anon_free_client_credentials"))
+
+(define %anonymous-server-credentials-smob
+ (make-smob-type "gnutls_anon_server_credentials_t" 'anonymous-server-credentials
+ "gnutls_anon_free_server_credentials"))
+
+(define %dh-parameters-smob
+ (make-smob-type "gnutls_dh_params_t" 'dh-parameters
+ "gnutls_dh_params_deinit"))
+
+(define %certificate-credentials-smob
+ (make-smob-type "gnutls_certificate_credentials_t" 'certificate-credentials
+ "gnutls_certificate_free_credentials"))
+
+(define %srp-server-credentials-smob
+ (make-smob-type "gnutls_srp_server_credentials_t" 'srp-server-credentials
+ "gnutls_srp_free_server_credentials"))
+
+(define %srp-client-credentials-smob
+ (make-smob-type "gnutls_srp_client_credentials_t" 'srp-client-credentials
+ "gnutls_srp_free_client_credentials"))
+
+(define %psk-server-credentials-smob
+ (make-smob-type "gnutls_psk_server_credentials_t" 'psk-server-credentials
+ "gnutls_psk_free_server_credentials"))
+
+(define %psk-client-credentials-smob
+ (make-smob-type "gnutls_psk_client_credentials_t" 'psk-client-credentials
+ "gnutls_psk_free_client_credentials"))
+
+(define %x509-certificate-smob
+ (make-smob-type "gnutls_x509_crt_t" 'x509-certificate
+ "gnutls_x509_crt_deinit"))
+
+(define %x509-private-key-smob
+ (make-smob-type "gnutls_x509_privkey_t" 'x509-private-key
+ "gnutls_x509_privkey_deinit"))
+
+(define %openpgp-certificate-smob
+ (make-smob-type "gnutls_openpgp_crt_t" 'openpgp-certificate
+ "gnutls_openpgp_crt_deinit"))
+
+(define %openpgp-private-key-smob
+ (make-smob-type "gnutls_openpgp_privkey_t" 'openpgp-private-key
+ "gnutls_openpgp_privkey_deinit"))
+
+(define %openpgp-keyring-smob
+ (make-smob-type "gnutls_openpgp_keyring_t" 'openpgp-keyring
+ "gnutls_openpgp_keyring_deinit"))
+
+
+(define %gnutls-smobs
+ ;; All SMOB types.
+ (list %session-smob %anonymous-client-credentials-smob
+ %anonymous-server-credentials-smob %dh-parameters-smob
+ %certificate-credentials-smob
+ %srp-server-credentials-smob %srp-client-credentials-smob
+ %psk-server-credentials-smob %psk-client-credentials-smob
+ %x509-certificate-smob %x509-private-key-smob
+
+ %openpgp-certificate-smob %openpgp-private-key-smob
+ %openpgp-keyring-smob))
+
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
+
+;;; arch-tag: 26bf79ef-6dee-45f2-9e9d-2d209c518278
diff --git a/guile/modules/gnutls/build/tests.scm b/guile/modules/gnutls/build/tests.scm
new file mode 100644
index 0000000..7dd7991
--- /dev/null
+++ b/guile/modules/gnutls/build/tests.scm
@@ -0,0 +1,93 @@
+;;; GnuTLS --- Guile bindings for GnuTLS.
+;;; Copyright (C) 2011-2012, 2016, 2021-2022 Free Software Foundation, Inc.
+;;;
+;;; GnuTLS 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.1 of the License, or (at your option) any later version.
+;;;
+;;; GnuTLS 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 GnuTLS; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+;;; Written by Ludovic Courtès <ludo@gnu.org>.
+
+(define-module (gnutls build tests)
+ #:export (run-test
+ with-child-process))
+
+(define (run-test thunk)
+ "Call `(exit (THUNK))'. If THUNK raises an exception, then call `(exit 1)' and
+display a backtrace. Otherwise, return THUNK's return value."
+ (exit
+ (catch #t
+ thunk
+ (lambda (key . args)
+ ;; Never reached.
+ (exit 1))
+ (lambda (key . args)
+ (dynamic-wind ;; to be on the safe side
+ (lambda () #t)
+ (lambda ()
+ (format (current-error-port)
+ "~%throw to `~a' with args ~s [PID ~a]~%"
+ key args (getpid))
+ (display-backtrace (make-stack #t) (current-output-port)))
+ (lambda ()
+ (exit 1)))
+ (exit 1)))))
+
+(define (call-with-child-process child parent)
+ "Run thunk CHILD in a child process and invoke PARENT from the parent
+process, passing it the PID of the child process. Make sure the child
+process exits upon failure."
+ (let ((pid (primitive-fork)))
+ (if (zero? pid)
+ (dynamic-wind
+ (const #t)
+ (lambda ()
+ (primitive-exit (if (child) 0 1)))
+ (lambda ()
+ (primitive-exit 2)))
+ (parent pid))))
+
+(use-modules (rnrs io ports)
+ (rnrs bytevectors)
+ (ice-9 match))
+
+(define-syntax-rule (define-replacement (name args ...) body ...)
+ ;; Define a compatibility replacement for NAME, if needed.
+ (define-public name
+ (if (module-defined? the-scm-module 'name)
+ (module-ref the-scm-module 'name)
+ (lambda (args ...)
+ body ...))))
+
+;; 'uniform-vector-read!' and 'uniform-vector-write' are deprecated in 2.0
+;; and absent in 2.2.
+;; TODO: Switch to the R6RS bytevector and I/O interface.
+
+(define-replacement (uniform-vector-read! buf port)
+ (match (get-bytevector-n! port buf
+ 0 (bytevector-length buf))
+ ((? eof-object?) 0)
+ ((? integer? n) n)))
+
+(define-replacement (uniform-vector-write buf port)
+ (put-bytevector port buf))
+
+(define-syntax-rule (with-child-process pid parent child)
+ "Fork and evaluate expression PARENT in the current process, with PID bound
+to the PID of its child process; the child process evaluated CHILD."
+ (call-with-child-process
+ (lambda () child)
+ (lambda (pid) parent)))
+
+;;; Local Variables:
+;;; eval: (put 'define-replacement 'scheme-indent-function 1)
+;;; End:
diff --git a/guile/modules/gnutls/build/utils.scm b/guile/modules/gnutls/build/utils.scm
new file mode 100644
index 0000000..b547aa8
--- /dev/null
+++ b/guile/modules/gnutls/build/utils.scm
@@ -0,0 +1,46 @@
+;;; GnuTLS --- Guile bindings for GnuTLS.
+;;; Copyright (C) 2007-2012 Free Software Foundation, Inc.
+;;;
+;;; GnuTLS 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.1 of the License, or (at your option) any later version.
+;;;
+;;; GnuTLS 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 GnuTLS; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+;;; Written by Ludovic Courtès <ludo@chbouib.org>
+
+(define-module (gnutls build utils)
+ :use-module (srfi srfi-13)
+ :export (scheme-symbol->c-name))
+
+;;;
+;;; Common utilities for the binding generation code.
+;;;
+
+
+;;;
+;;; Utilities.
+;;;
+
+(define (scheme-symbol->c-name sym)
+ ;; Turn SYM, a symbol denoting a Scheme name, into a string denoting a C
+ ;; name.
+ (string-map (lambda (chr)
+ (if (eq? chr #\-) #\_ chr))
+ (symbol->string sym)))
+
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
+
+;;; arch-tag: 56919ee1-7cce-46b9-b90f-ae6fbcfe4159
diff --git a/guile/modules/gnutls/extra.scm b/guile/modules/gnutls/extra.scm
new file mode 100644
index 0000000..4191c5a
--- /dev/null
+++ b/guile/modules/gnutls/extra.scm
@@ -0,0 +1,83 @@
+;;; GnuTLS-extra --- Guile bindings for GnuTLS-EXTRA.
+;;; Copyright (C) 2007-2012 Free Software Foundation, Inc.
+;;;
+;;; GnuTLS-extra is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 3 of the License, or
+;;; (at your option) any later version.
+;;;
+;;; GnuTLS-extra is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with GnuTLS-EXTRA; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+;;; USA.
+
+;;; Written by Ludovic Courtès <ludo@gnu.org>
+
+(define-module (gnutls extra)
+
+ :use-module (gnutls)
+
+ :re-export (;; OpenPGP keys
+ openpgp-certificate? openpgp-private-key?
+ import-openpgp-certificate import-openpgp-private-key
+ openpgp-certificate-id openpgp-certificate-id!
+ openpgp-certificate-fingerprint openpgp-certificate-fingerprint!
+ openpgp-certificate-name openpgp-certificate-names
+ openpgp-certificate-algorithm openpgp-certificate-version
+ openpgp-certificate-usage
+
+ ;; OpenPGP keyrings
+ openpgp-keyring? import-openpgp-keyring
+ openpgp-keyring-contains-key-id?
+
+ ;; certificate credentials
+ set-certificate-credentials-openpgp-keys!
+
+ ;; enum->string functions
+ openpgp-certificate-format->string
+
+ ;; enum values
+ openpgp-certificate-format/raw
+ openpgp-certificate-format/base64))
+
+
+
+;;;
+;;; This module will be removed in a future version.
+;;;
+
+(issue-deprecation-warning
+ "The (gnutls extra) module is deprecated; use (gnutls) instead")
+
+
+;;;
+;;; Aliases kept for backward compatibility with GnuTLS 2.0.x. These aliases
+;;; are deprecated in 2.2 and should be removed in 2.4.x.
+;;;
+
+(define-public openpgp-public-key? openpgp-certificate?)
+(define-public import-openpgp-public-key import-openpgp-certificate)
+(define-public openpgp-public-key-id openpgp-certificate-id)
+(define-public openpgp-public-key-id! openpgp-certificate-id!)
+(define-public openpgp-public-key-fingerprint openpgp-certificate-fingerprint)
+(define-public openpgp-public-key-fingerprint! openpgp-certificate-fingerprint!)
+(define-public openpgp-public-key-name openpgp-certificate-name)
+(define-public openpgp-public-key-names openpgp-certificate-names)
+(define-public openpgp-public-key-algorithm openpgp-certificate-algorithm)
+(define-public openpgp-public-key-version openpgp-certificate-version)
+(define-public openpgp-public-key-usage openpgp-certificate-usage)
+
+(define-public openpgp-key-format->string openpgp-certificate-format->string)
+(define-public openpgp-key-format/raw openpgp-certificate-format/raw)
+(define-public openpgp-key-format/base64 openpgp-certificate-format/base64)
+
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
diff --git a/guile/modules/system/documentation/README b/guile/modules/system/documentation/README
new file mode 100644
index 0000000..d8dba12
--- /dev/null
+++ b/guile/modules/system/documentation/README
@@ -0,0 +1,15 @@
+C Documentation Snarfing Modules
+--------------------------------
+
+This modules provide allow the extraction of Texinfo documentation
+strings from C files---this is usually referred to as ``doc snarfing''
+in Guile terms.
+
+They were stolen from Guile-Reader 0.3:
+
+ https://www.nongnu.org/guile-reader/
+
+It was only slightly modified.
+
+
+Ludovic Courtès <ludo@chbouib.org>.
diff --git a/guile/modules/system/documentation/c-snarf.scm b/guile/modules/system/documentation/c-snarf.scm
new file mode 100644
index 0000000..5e54da3
--- /dev/null
+++ b/guile/modules/system/documentation/c-snarf.scm
@@ -0,0 +1,210 @@
+;;; c-snarf.scm -- Parsing documentation "snarffed" from C files.
+;;;
+;;; Copyright 2006-2012 Free Software Foundation, Inc.
+;;;
+;;;
+;;; This program is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; 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 General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+(define-module (system documentation c-snarf)
+ :use-module (ice-9 popen)
+ :use-module (ice-9 rdelim)
+
+ :use-module (srfi srfi-13)
+ :use-module (srfi srfi-14)
+ :use-module (srfi srfi-39)
+
+ :export (run-cpp-and-extract-snarfing
+ parse-snarfing
+ parse-snarfed-line))
+
+;;; Author: Ludovic Courtès
+;;;
+;;; Commentary:
+;;;
+;;; This module provides tools to parse and otherwise manipulate
+;;; documentation "snarffed" from C files, i.e., information obtained by
+;;; running the C preprocessor with the @code{-DSCM_MAGIC_SNARF_DOCS} flag.
+;;;
+;;; Code:
+
+
+
+;;;
+;;; High-level API.
+;;;
+
+(define (run-cpp-and-extract-snarfing file cpp cpp-flags)
+ (let ((pipe (apply open-pipe* OPEN_READ
+ (cons cpp (append cpp-flags (list file))))))
+ (parse-snarfing pipe)))
+
+
+;;;
+;;; Parsing magic-snarffed CPP output.
+;;;
+
+(define (parse-c-argument-list arg-string)
+ "Parse @var{arg-string} (a string representing a ANSI C argument list,
+e.g., @var{(const SCM first, SCM second_arg)}) and return a list of strings
+denoting the argument names."
+ (define %c-symbol-char-set
+ (char-set-adjoin char-set:letter+digit #\_))
+
+ (let loop ((args (string-tokenize (string-trim-both arg-string #\space)
+ %c-symbol-char-set))
+ (type? #t)
+ (result '()))
+ (if (null? args)
+ (reverse! result)
+ (let ((the-arg (car args)))
+ (cond ((and type? (string=? the-arg "const"))
+ (loop (cdr args) type? result))
+ ((and type? (string=? the-arg "SCM"))
+ (loop (cdr args) (not type?) result))
+ (type? ;; any other type, e.g., `void'
+ (loop (cdr args) (not type?) result))
+ (else
+ (loop (cdr args) (not type?) (cons the-arg result))))))))
+
+(define (parse-documentation-item item)
+ "Parse @var{item} (a string), a single function string produced by the C
+preprocessor. The result is an alist whose keys represent specific aspects
+of a procedure's documentation: @code{c-name}, @code{scheme-name},
+ @code{documentation} (a Texinfo documentation string), etc."
+
+ (define (read-strings)
+ ;; Read several subsequent strings and return their concatenation.
+ (let loop ((str (read))
+ (result '()))
+ (if (or (eof-object? str)
+ (not (string? str)))
+ (string-concatenate (reverse! result))
+ (loop (read) (cons str result)))))
+
+ (let* ((item (string-trim-both item #\space))
+ (space (string-index item #\space)))
+ (if (not space)
+ (error "invalid documentation item" item)
+ (let ((kind (substring item 0 space))
+ (rest (substring item space (string-length item))))
+ (cond ((string=? kind "cname")
+ (cons 'c-name (string-trim-both rest #\space)))
+ ((string=? kind "fname")
+ (cons 'scheme-name
+ (with-input-from-string rest read-strings)))
+ ((string=? kind "type")
+ (cons 'type (with-input-from-string rest read)))
+ ((string=? kind "location")
+ (cons 'location
+ (with-input-from-string rest
+ (lambda ()
+ (let loop ((str (read))
+ (result '()))
+ (if (eof-object? str)
+ (reverse! result)
+ (loop (read) (cons str result))))))))
+ ((string=? kind "arglist")
+ (cons 'arguments
+ (parse-c-argument-list rest)))
+ ((string=? kind "argsig")
+ (cons 'signature
+ (with-input-from-string rest
+ (lambda ()
+ (let ((req (read)) (opt (read)) (rst? (read)))
+ (list (cons 'required req)
+ (cons 'optional opt)
+ (cons 'rest? (= 1 rst?))))))))
+ (else
+ ;; docstring (may consist of several C strings which we
+ ;; assume to be equivalent to Scheme strings)
+ (cons 'documentation
+ (with-input-from-string item read-strings))))))))
+
+(define (parse-snarfed-line line)
+ "Parse @var{line}, a string that contains documentation returned for a
+single function by the C preprocessor with the @code{-DSCM_MAGIC_SNARF_DOCS}
+option. @var{line} is assumed to be a complete \"^^ { ... ^^ }\" sequence."
+ (define (caret-split str)
+ (let loop ((str str)
+ (result '()))
+ (if (string=? str "")
+ (reverse! result)
+ (let ((caret (string-index str #\^))
+ (len (string-length str)))
+ (if caret
+ (if (and (> (- len caret) 0)
+ (eq? (string-ref str (+ caret 1)) #\^))
+ (loop (substring str (+ 2 caret) len)
+ (cons (string-take str (- caret 1)) result))
+ (error "single caret not allowed" str))
+ (loop "" (cons str result)))))))
+
+ (let ((items (caret-split (substring line 4
+ (- (string-length line) 4)))))
+ (map parse-documentation-item items)))
+
+
+(define (parse-snarfing port)
+ "Read C preprocessor (where the @code{SCM_MAGIC_SNARF_DOCS} macro is
+defined) output from @var{port} a return a list of alist, each of which
+contains information about a specific function described in the C
+preprocessor output."
+ (define start-marker "^^ {")
+ (define end-marker "^^ }")
+
+ (define (read-snarf-lines start)
+ ;; Read the snarf lines that follow START until and end marker is found.
+ (let loop ((line start)
+ (result '()))
+ (cond ((eof-object? line)
+ ;; EOF in the middle of a "^^ { ... ^^ }" sequence; shouldn't
+ ;; happen.
+ line)
+ ((string-contains line end-marker)
+ =>
+ (lambda (end)
+ (let ((result (cons (string-take line (+ 3 end))
+ result)))
+ (string-concatenate-reverse result))))
+ ((string-prefix? "#" line)
+ ;; Presumably a "# LINENUM" directive; skip it.
+ (loop (read-line port) result))
+ (else
+ (loop (read-line port)
+ (cons line result))))))
+
+ (let loop ((line (read-line port))
+ (result '()))
+ (cond ((eof-object? line)
+ result)
+ ((string-contains line start-marker)
+ =>
+ (lambda (start)
+ (let ((line
+ (read-snarf-lines (string-drop line start))))
+ (loop (read-line port)
+ (cons (parse-snarfed-line line) result)))))
+ (else
+ (loop (read-line port) result)))))
+
+
+;;; c-snarf.scm ends here
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
+
+;;; arch-tag: dcba2446-ee43-46d8-a47e-e6e12f121988
diff --git a/guile/modules/system/documentation/output.scm b/guile/modules/system/documentation/output.scm
new file mode 100644
index 0000000..d60fe44
--- /dev/null
+++ b/guile/modules/system/documentation/output.scm
@@ -0,0 +1,176 @@
+;;; output.scm -- Output documentation "snarffed" from C files in Texi/GDF.
+;;;
+;;; Copyright 2006-2012 Free Software Foundation, Inc.
+;;;
+;;;
+;;; This program is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; 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 General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this program; if not, write to the Free Software
+;;; Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+(define-module (system documentation output)
+ :use-module (srfi srfi-1)
+ :use-module (srfi srfi-13)
+ :use-module (srfi srfi-39)
+ :autoload (system documentation c-snarf) (run-cpp-and-extract-snarfing)
+
+ :export (schemify-name scheme-procedure-texi-line
+ procedure-gdf-string procedure-texi-documentation
+ output-procedure-texi-documentation-from-c-file
+ *document-c-functions?*))
+
+;;; Author: Ludovic Courtès
+;;;
+;;; Commentary:
+;;;
+;;; This module provides support function to issue Texinfo or GDF (Guile
+;;; Documentation Format) documentation from "snarffed" C files.
+;;;
+;;; Code:
+
+
+;;;
+;;; Utility.
+;;;
+
+(define (schemify-name str)
+ "Turn @var{str}, a C variable or function name, into a more ``Schemey''
+form, e.g., one with dashed instead of underscores, etc."
+ (string-map (lambda (chr)
+ (if (eq? chr #\_)
+ #\-
+ chr))
+ (if (string-suffix? "_p" str)
+ (string-append (substring str 0
+ (- (string-length str) 2))
+ "?")
+ str)))
+
+
+;;;
+;;; Issuing Texinfo and GDF-formatted doc (i.e., `guile-procedures.texi').
+;;; GDF = Guile Documentation Format
+;;;
+
+(define *document-c-functions?*
+ ;; Whether to mention C function names along with Scheme procedure names.
+ (make-parameter #t))
+
+(define (scheme-procedure-texi-line proc-name args
+ required-args optional-args
+ rest-arg?)
+ "Return a Texinfo string describing the Scheme procedure named
+@var{proc-name}, whose arguments are listed in @var{args} (a list of strings)
+and whose signature is defined by @var{required-args}, @var{optional-args}
+and @var{rest-arg?}."
+ (string-append "@deffn {Scheme Procedure} " proc-name " "
+ (string-join (take args required-args) " ")
+ (string-join (take (drop args required-args)
+ (+ optional-args
+ (if rest-arg? 1 0)))
+ " [" 'prefix)
+ (if rest-arg? "...]" "")
+ (make-string optional-args #\])))
+
+(define (procedure-gdf-string proc-doc)
+ "Issue a Texinfo/GDF docstring corresponding to @var{proc-doc}, a
+documentation alist as returned by @code{parse-snarfed-line}. To produce
+actual GDF-formatted doc, the resulting string must be processed by
+@code{makeinfo}."
+ (let* ((proc-name (assq-ref proc-doc 'scheme-name))
+ (args (assq-ref proc-doc 'arguments))
+ (signature (assq-ref proc-doc 'signature))
+ (required-args (assq-ref signature 'required))
+ (optional-args (assq-ref signature 'optional))
+ (rest-arg? (assq-ref signature 'rest?))
+ (location (assq-ref proc-doc 'location))
+ (file-name (car location))
+ (line (cadr location))
+ (documentation (assq-ref proc-doc 'documentation)))
+ (string-append " " ;; form feed
+ proc-name (string #\newline)
+ (format #f "@c snarfed from ~a:~a~%"
+ file-name line)
+
+ (scheme-procedure-texi-line proc-name
+ (map schemify-name args)
+ required-args optional-args
+ rest-arg?)
+
+ (string #\newline)
+ documentation (string #\newline)
+ "@end deffn" (string #\newline))))
+
+(define (procedure-texi-documentation proc-doc)
+ "Issue a Texinfo docstring corresponding to @var{proc-doc}, a documentation
+alist as returned by @var{parse-snarfed-line}. The resulting Texinfo string
+is meant for use in a manual since it also documents the corresponding C
+function."
+ (let* ((proc-name (assq-ref proc-doc 'scheme-name))
+ (c-name (assq-ref proc-doc 'c-name))
+ (args (assq-ref proc-doc 'arguments))
+ (signature (assq-ref proc-doc 'signature))
+ (required-args (assq-ref signature 'required))
+ (optional-args (assq-ref signature 'optional))
+ (rest-arg? (assq-ref signature 'rest?))
+ (location (assq-ref proc-doc 'location))
+ (file-name (car location))
+ (line (cadr location))
+ (documentation (assq-ref proc-doc 'documentation)))
+ (string-append (string #\newline)
+ (format #f "@c snarfed from ~a:~a~%"
+ file-name line)
+
+ ;; document the Scheme procedure
+ (scheme-procedure-texi-line proc-name
+ (map schemify-name args)
+ required-args optional-args
+ rest-arg?)
+ (string #\newline)
+
+ (if (*document-c-functions?*)
+ (string-append
+ ;; document the C function
+ "@deffnx {C Function} " c-name " ("
+ (if (null? args)
+ "void"
+ (string-join (map (lambda (arg)
+ (string-append "SCM " arg))
+ args)
+ ", "))
+ ")" (string #\newline))
+ "")
+
+ documentation (string #\newline)
+ "@end deffn" (string #\newline))))
+
+
+;;;
+;;; Very high-level interface.
+;;;
+
+(define (output-procedure-texi-documentation-from-c-file c-file cpp cflags
+ port)
+ (for-each (lambda (texi-string)
+ (display texi-string port))
+ (map procedure-texi-documentation
+ (run-cpp-and-extract-snarfing c-file cpp cflags))))
+
+
+;;; output.scm ends here
+
+;;; Local Variables:
+;;; mode: scheme
+;;; coding: latin-1
+;;; End:
+
+;;; arch-tag: 20ca493a-6f1a-4d7f-9d24-ccce0d32df49