summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpukkamustard <pukkamustard@posteo.net>2021-01-02 18:43:00 +0100
committerpukkamustard <pukkamustard@posteo.net>2021-01-02 18:46:38 +0100
commit9c6711a2af82ab4111bf0e36f332c6a7520f2136 (patch)
treed9dc305d57fcf4c8d4fddf916e783cff465c404c
parent0d2609be270053d33b7a4505a2ffa702243335b8 (diff)
cbor: basic encoder and decoder
-rw-r--r--AUTHORS3
-rw-r--r--ChangeLog1
-rw-r--r--Makefile.am78
-rw-r--r--NEWS14
-rw-r--r--README.org25
-rw-r--r--build-aux/test-driver.scm180
-rw-r--r--cbor.scm15
-rw-r--r--cbor/decode.scm66
-rw-r--r--cbor/encode.scm100
-rw-r--r--cbor/tag.scm23
-rw-r--r--configure.ac35
-rw-r--r--hall.scm4
-rw-r--r--pre-inst-env.in14
13 files changed, 535 insertions, 23 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..9da1c28
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,3 @@
+Contributers to guile-cbor 0.1.0:
+
+ pukkamustard <pukkamustard@posteo.net>
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..92ebfe8
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1 @@
+For a complete log, please see the Git commit log at <https://inqlab.net/git/guile-cbor.git/PATH/TO/LOG>.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..b0c9687
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,78 @@
+
+
+bin_SCRIPTS =
+
+# Handle substitution of fully-expanded Autoconf variables.
+do_subst = $(SED) \
+ -e 's,[@]GUILE[@],$(GUILE),g' \
+ -e 's,[@]guilemoduledir[@],$(guilemoduledir),g' \
+ -e 's,[@]guileobjectdir[@],$(guileobjectdir),g' \
+ -e 's,[@]localedir[@],$(localedir),g'
+
+nodist_noinst_SCRIPTS = pre-inst-env
+
+GOBJECTS = $(SOURCES:%.scm=%.go)
+
+moddir=$(prefix)/share/guile/site/$(GUILE_EFFECTIVE_VERSION)
+godir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache
+ccachedir=$(libdir)/guile/$(GUILE_EFFECTIVE_VERSION)/site-ccache
+
+nobase_mod_DATA = $(SOURCES) $(NOCOMP_SOURCES)
+nobase_go_DATA = $(GOBJECTS)
+
+# Make sure source files are installed first, so that the mtime of
+# installed compiled files is greater than that of installed source
+# files. See
+# <http://lists.gnu.org/archive/html/guile-devel/2010-07/msg00125.html>
+# for details.
+guile_install_go_files = install-nobase_goDATA
+$(guile_install_go_files): install-nobase_modDATA
+
+EXTRA_DIST = $(SOURCES) $(NOCOMP_SOURCES)
+GUILE_WARNINGS = -Wunbound-variable -Warity-mismatch -Wformat
+SUFFIXES = .scm .go
+.scm.go:
+ $(AM_V_GEN)$(top_builddir)/pre-inst-env $(GUILE_TOOLS) compile $(GUILE_WARNINGS) -o "$@" "$<"
+
+SOURCES = cbor.scm \
+ cbor/decode.scm \
+ cbor/encode.scm \
+ cbor/tag.scm
+
+TESTS =
+
+TEST_EXTENSIONS = .scm
+SCM_LOG_DRIVER = \
+ $(top_builddir)/pre-inst-env \
+ $(GUILE) --no-auto-compile -e main \
+ $(top_srcdir)/build-aux/test-driver.scm
+
+# Tell 'build-aux/test-driver.scm' to display only source file names,
+# not indivdual test names.
+AM_SCM_LOG_DRIVER_FLAGS = --brief=yes
+
+AM_SCM_LOG_FLAGS = --no-auto-compile -L "$(top_srcdir)"
+
+AM_TESTS_ENVIRONMENT = abs_top_srcdir="$(abs_top_srcdir)"
+
+info_TEXINFOS = doc/cbor.texi
+dvi: # Don't build dvi docs
+
+EXTRA_DIST += README.org \
+ README \
+ HACKING \
+ COPYING \
+ guix.scm \
+ hall.scm \
+ build-aux/test-driver.scm \
+ $(TESTS)
+
+ACLOCAL_AMFLAGS = -I m4
+
+clean-go:
+ -$(RM) $(GOBJECTS)
+.PHONY: clean-go
+
+CLEANFILES = \
+ $(GOBJECTS) \
+ $(TESTS:tests/%.scm=%.log)
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..0ddeaa9
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,14 @@
+-*- mode: org; coding: utf-8; -*-
+
+#+TITLE: guile-cbor NEWS – history of user-visible changes
+#+STARTUP: content hidestars
+
+Copyright © (2020) pukkamustard <pukkamustard@posteo.net>
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved.
+
+Please send Guile Cbor bug reports to INSERT EMAIL HERE.
+
+* Publication at 0.1
diff --git a/README.org b/README.org
index 601bab8..4f78234 100644
--- a/README.org
+++ b/README.org
@@ -4,6 +4,31 @@
guile-cbor is a Guile implementation of CBOR (Concise Binary Object Representation) as specified by [[https://www.rfc-editor.org/rfc/rfc8949.html][RFC8949]].
+
+* Usage
+
+** Native Scheme Values <-> CBOR data items
+
+| Native Scheme | CBOR | Note |
+|------------------+------------------------------------------------+-----------------------------------------------------------------|
+| positive integer | unsigned integer (major type 0) | |
+| negative integer | negative integer (major type 0) | |
+| bytevector | byte string (major type 2) | |
+| string | text string (major type 3) | |
+| vector | array (major type 4) | See also how [[https://github.com/aconchillo/guile-json#usage][guile-json]] maps arrays |
+| alist | map (major type 5) | |
+| <cbor-tag> | tagged data item (major type 6) | |
+| - | IEEE 754 Half-Precision Float (major type 7) | Can not be parsed (FIXME) |
+| real | IEEE 754 Double-Precision Float (major type 7) | Scheme reals are alwyas encoded as CBOR double precision floats |
+| real | IEEE 754 Single-Precision Float (major type 7) | CBOR single precision floats are parsed as Schme real numbers |
+| #f | false (major type 7, simple value 20) | |
+| #t | true (major type 7, simple value 21) | |
+| #nil | null (major type 7, simple value 22) | |
+
+
+* Todos
+** TODO Tests
+** TODO texinfo documentation
* License
GPL-3.0-or-later see [[./COPYING]].
diff --git a/build-aux/test-driver.scm b/build-aux/test-driver.scm
new file mode 100644
index 0000000..a818968
--- /dev/null
+++ b/build-aux/test-driver.scm
@@ -0,0 +1,180 @@
+
+;;;; test-driver.scm - Guile test driver for Automake testsuite harness
+
+(define script-version "2019-01-15.13") ;UTC
+
+;;; Copyright © 2015, 2016 Mathieu Lirzin <mthl@gnu.org>
+;;; Copyright © 2019 Alex Sassmannshausen <alex@pompo.co>
+;;;
+;;; 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, see <http://www.gnu.org/licenses/>.
+
+;;;; Commentary:
+;;;
+;;; This script provides a Guile test driver using the SRFI-64 Scheme API for
+;;; test suites. SRFI-64 is distributed with Guile since version 2.0.9.
+;;;
+;;; This script is a lightly modified version of the orignal written by
+;;; Matthieu Lirzin. The changes make it suitable for use as part of the
+;;; guile-hall infrastructure.
+;;;
+;;;; Code:
+
+(use-modules (ice-9 getopt-long)
+ (ice-9 pretty-print)
+ (srfi srfi-26)
+ (srfi srfi-64))
+
+(define (show-help)
+ (display "Usage:
+ test-driver --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--brief={yes|no}}] [--]
+ TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS]
+The '--test-name', '--log-file' and '--trs-file' options are mandatory.
+"))
+
+(define %options
+ '((test-name (value #t))
+ (log-file (value #t))
+ (trs-file (value #t))
+ (color-tests (value #t))
+ (expect-failure (value #t)) ;XXX: not implemented yet
+ (enable-hard-errors (value #t)) ;not implemented in SRFI-64
+ (brief (value #t))
+ (help (single-char #\h) (value #f))
+ (version (single-char #\V) (value #f))))
+
+(define (option->boolean options key)
+ "Return #t if the value associated with KEY in OPTIONS is 'yes'."
+ (and=> (option-ref options key #f) (cut string=? <> "yes")))
+
+(define* (test-display field value #:optional (port (current-output-port))
+ #:key pretty?)
+ "Display 'FIELD: VALUE\n' on PORT."
+ (if pretty?
+ (begin
+ (format port "~A:~%" field)
+ (pretty-print value port #:per-line-prefix "+ "))
+ (format port "~A: ~S~%" field value)))
+
+(define* (result->string symbol #:key colorize?)
+ "Return SYMBOL as an upper case string. Use colors when COLORIZE is #t."
+ (let ((result (string-upcase (symbol->string symbol))))
+ (if colorize?
+ (string-append (case symbol
+ ((pass) "") ;green
+ ((xfail) "") ;light green
+ ((skip) "") ;blue
+ ((fail xpass) "") ;red
+ ((error) "")) ;magenta
+ result
+ "") ;no color
+ result)))
+
+(define* (test-runner-gnu test-name #:key color? brief? out-port trs-port)
+ "Return an custom SRFI-64 test runner. TEST-NAME is a string specifying the
+file name of the current the test. COLOR? specifies whether to use colors,
+and BRIEF?, well, you know. OUT-PORT and TRS-PORT must be output ports. The
+current output port is supposed to be redirected to a '.log' file."
+
+ (define (test-on-test-begin-gnu runner)
+ ;; Procedure called at the start of an individual test case, before the
+ ;; test expression (and expected value) are evaluated.
+ (let ((result (cute assq-ref (test-result-alist runner) <>)))
+ (format #t "test-name: ~A~%" (result 'test-name))
+ (format #t "location: ~A~%"
+ (string-append (result 'source-file) ":"
+ (number->string (result 'source-line))))
+ (test-display "source" (result 'source-form) #:pretty? #t)))
+
+ (define (test-on-test-end-gnu runner)
+ ;; Procedure called at the end of an individual test case, when the result
+ ;; of the test is available.
+ (let* ((results (test-result-alist runner))
+ (result? (cut assq <> results))
+ (result (cut assq-ref results <>)))
+ (unless brief?
+ ;; Display the result of each test case on the console.
+ (format out-port "~A: ~A - ~A~%"
+ (result->string (test-result-kind runner) #:colorize? color?)
+ test-name (test-runner-test-name runner)))
+ (when (result? 'expected-value)
+ (test-display "expected-value" (result 'expected-value)))
+ (when (result? 'expected-error)
+ (test-display "expected-error" (result 'expected-error) #:pretty? #t))
+ (when (result? 'actual-value)
+ (test-display "actual-value" (result 'actual-value)))
+ (when (result? 'actual-error)
+ (test-display "actual-error" (result 'actual-error) #:pretty? #t))
+ (format #t "result: ~a~%" (result->string (result 'result-kind)))
+ (newline)
+ (format trs-port ":test-result: ~A ~A~%"
+ (result->string (test-result-kind runner))
+ (test-runner-test-name runner))))
+
+ (define (test-on-group-end-gnu runner)
+ ;; Procedure called by a 'test-end', including at the end of a test-group.
+ (let ((fail (or (positive? (test-runner-fail-count runner))
+ (positive? (test-runner-xpass-count runner))))
+ (skip (or (positive? (test-runner-skip-count runner))
+ (positive? (test-runner-xfail-count runner)))))
+ ;; XXX: The global results need some refinements for XPASS.
+ (format trs-port ":global-test-result: ~A~%"
+ (if fail "FAIL" (if skip "SKIP" "PASS")))
+ (format trs-port ":recheck: ~A~%"
+ (if fail "yes" "no"))
+ (format trs-port ":copy-in-global-log: ~A~%"
+ (if (or fail skip) "yes" "no"))
+ (when brief?
+ ;; Display the global test group result on the console.
+ (format out-port "~A: ~A~%"
+ (result->string (if fail 'fail (if skip 'skip 'pass))
+ #:colorize? color?)
+ test-name))
+ #f))
+
+ (let ((runner (test-runner-null)))
+ (test-runner-on-test-begin! runner test-on-test-begin-gnu)
+ (test-runner-on-test-end! runner test-on-test-end-gnu)
+ (test-runner-on-group-end! runner test-on-group-end-gnu)
+ (test-runner-on-bad-end-name! runner test-on-bad-end-name-simple)
+ runner))
+
+;;;
+;;; Entry point.
+;;;
+
+(define (main . args)
+ (let* ((opts (getopt-long (command-line) %options))
+ (option (cut option-ref opts <> <>)))
+ (cond
+ ((option 'help #f) (show-help))
+ ((option 'version #f) (format #t "test-driver.scm ~A" script-version))
+ (else
+ (let ((log (open-file (option 'log-file "") "w0"))
+ (trs (open-file (option 'trs-file "") "wl"))
+ (out (duplicate-port (current-output-port) "wl")))
+ (redirect-port log (current-output-port))
+ (redirect-port log (current-warning-port))
+ (redirect-port log (current-error-port))
+ (test-with-runner
+ (test-runner-gnu (option 'test-name #f)
+ #:color? (option->boolean opts 'color-tests)
+ #:brief? (option->boolean opts 'brief)
+ #:out-port out #:trs-port trs)
+ (load-from-path (option 'test-name #f)))
+ (close-port log)
+ (close-port trs)
+ (close-port out))))
+ (exit 0)))
diff --git a/cbor.scm b/cbor.scm
index 08a6887..2b35e09 100644
--- a/cbor.scm
+++ b/cbor.scm
@@ -1,8 +1,17 @@
(define-module (cbor)
- #:use-module (rnrs bytevectors))
+ #:use-module (rnrs bytevectors)
+ #:use-module (rnrs io ports)
+
+ #:use-module (cbor encode)
+ #:use-module (cbor decode))
(define (scm->cbor native)
- (make-bytevector 0))
+ (call-with-values open-bytevector-output-port
+ (lambda (port get-bytevector)
+ (put-cbor-data-item port native)
+ (get-bytevector))))
(define (cbor->scm port-or-bv)
- #f)
+ (if (port? port-or-bv)
+ (get-cbor-data-item port-or-bv)
+ (cbor->scm (open-bytevector-input-port port-or-bv))))
diff --git a/cbor/decode.scm b/cbor/decode.scm
index 940e225..f802a9c 100644
--- a/cbor/decode.scm
+++ b/cbor/decode.scm
@@ -1,6 +1,11 @@
(define-module (cbor decode)
+ #:use-module (rnrs bytevectors)
#:use-module (rnrs io ports)
- #:use-module (rnrs bytevectors))
+ #:use-module (srfi srfi-43)
+
+ #:use-module (cbor tag)
+
+ #:export (get-cbor-data-item))
(define (get-uint-network-order port n)
"Read a unsigned integer of size @code{n} in network order (big endian) from
@@ -10,7 +15,6 @@
(define (get-argument port additional-information)
(cond
-
((< additional-information 24)
;; the argument's value is the value of the additional information
additional-information)
@@ -27,6 +31,10 @@
((eqv? additional-information 27)
(get-uint-network-order port 8))
+ ((eqv? additional-information 31)
+ 'indefinite-length)
+
+ ;; TODO: error handling
(else 'not-well-formed)))
(define (get-cbor-data-item port)
@@ -36,7 +44,7 @@
(major-type (bit-extract initial-byte 5 8))
;; additional information is in the lower-order 5 bits
(additional-information (bit-extract initial-byte 0 5))
- ;; read argument value TODO handle the float exception
+ ;; read argument value
(argument (get-argument port additional-information)))
(case major-type
@@ -53,19 +61,39 @@
;; text string
((3) (utf8->string (get-bytevector-n port argument)))
- ;; TODO array of data items
- ((4) #f)
-
- ;; TODO map of pairs of data items
- ((5) #f)
-
- ;; TODO tagged data item
- ((6) #f)
-
- ;; TODO floating-point number
- ((7) #f))))
-
-(get-cbor-data-item
- (open-bytevector-input-port (uint-list->bytevector '(#x38 #x63)
- (endianness big)
- 1)))
+ ;; array of data items
+ ((4) (vector-unfold
+ (lambda (_) (get-cbor-data-item port))
+ argument))
+
+ ;; map of pairs of data items
+ ((5) (map (lambda (_) (cons (get-cbor-data-item port)
+ (get-cbor-data-item port)))
+ (iota argument)))
+
+ ;; tagged data item
+ ((6) (make-cbor-tag argument
+ (get-cbor-data-item port)))
+
+ ;; floating-point number and simple values
+ ((7) (case additional-information
+ ((20) #f)
+ ((21) #t)
+ ((22) #nil)
+
+ ;; TODO error handling
+ ((25) 'not-supported)
+
+ ;; re-encode argument as bytevector and decode as float
+ ;; FIXME this is ineficient
+ ((26) (let ((bv (make-bytevector 4)))
+ (bytevector-u32-set! bv 0 argument (endianness big))
+ (bytevector-ieee-single-ref bv 0 (endianness big))))
+
+ ((27) (let ((bv (make-bytevector 8)))
+ (bytevector-u64-set! bv 0 argument (endianness big))
+ (display bv)
+ (bytevector-ieee-double-ref bv 0 (endianness big))))
+
+ ;; TODO error handling
+ (else 'not-well-formed))))))
diff --git a/cbor/encode.scm b/cbor/encode.scm
new file mode 100644
index 0000000..064926b
--- /dev/null
+++ b/cbor/encode.scm
@@ -0,0 +1,100 @@
+(define-module (cbor encode)
+ #:use-module (rnrs arithmetic bitwise)
+ #:use-module (rnrs base)
+ #:use-module (rnrs bytevectors)
+ #:use-module (rnrs io ports)
+
+ #:use-module (cbor tag)
+
+ #:export (put-cbor-data-item))
+
+(define (put-cbor-initial-byte port major-type additional-info)
+ (put-u8 port
+ (bitwise-ior
+ ;; shift major-type to upper 3 bits
+ (bitwise-arithmetic-shift major-type 5)
+ additional-info)))
+
+(define (put-uint-network-order port uint size)
+ (let ((bv (make-bytevector size)))
+ (bytevector-uint-set! bv 0 uint (endianness big) size)
+ (put-bytevector port bv)))
+
+(define (put-cbor-integer port major-type uint)
+ (let ((arg-length (ceiling-quotient (integer-length uint) 8)))
+ (cond
+ ;; directly encode value in additional info
+ ((< uint 24)
+ (put-cbor-initial-byte port major-type uint))
+
+ ;; fits in one byte
+ ((<= arg-length 1)
+ (put-cbor-initial-byte port major-type 24)
+ (put-uint-network-order port uint 1))
+
+ ((<= arg-length 2)
+ (put-cbor-initial-byte port major-type 25)
+ (put-uint-network-order port uint 2))
+
+ ((<= arg-length 4)
+ (put-cbor-initial-byte port major-type 26)
+ (put-uint-network-order port uint 4))
+
+ ((<= arg-length 8)
+ (put-cbor-initial-byte port major-type 27)
+ (put-uint-network-order port uint 8))
+
+ ;; TODO error integer out of bound
+ (else 'oops))))
+
+(define (put-cbor-data-item port value)
+ (cond
+
+ ;; unsigned integer
+ ((and (integer? value) (<= 0 value))
+ (put-cbor-integer port 0 value))
+
+ ;; negative integer
+ ((and (integer? value) (> 0 value))
+ (put-cbor-integer port 1 (- -1 value)))
+
+ ((bytevector? value)
+ (put-cbor-integer port 2 (bytevector-length value))
+ (put-bytevector port value))
+
+ ((string? value)
+ (let ((as-bytes (string->utf8 value)))
+ (put-cbor-integer port 3 (bytevector-length as-bytes))
+ (put-bytevector port as-bytes)))
+
+ ((vector? value)
+ (put-cbor-integer port 4 (vector-length value))
+ (vector-for-each (lambda (sub-value)
+ (put-cbor-data-item port sub-value))
+ value))
+
+ ((list? value)
+ (put-cbor-integer port 5 (length value))
+ (for-each (lambda (key-value)
+ (put-cbor-data-item port (car key-value))
+ (put-cbor-data-item port (cdr key-value)))
+ value))
+
+ ((cbor-tag? value)
+ (put-cbor-integer port 6 (cbor-tag-number value))
+ (put-cbor-data-item port (cbor-tag-content value)))
+
+ ((real? value)
+ (let ((bv (make-bytevector 8)))
+ (put-cbor-initial-byte port 7 27)
+ (bytevector-ieee-double-set! bv 0 value (endianness big))
+ (put-bytevector port bv)))
+
+ ((equal? value #f)
+ (put-cbor-initial-byte port 7 20))
+
+ ((equal? value #t)
+ (put-cbor-initial-byte port 7 21))
+
+ ((nil? value)
+ (put-cbor-initial-byte port 7 22))))
diff --git a/cbor/tag.scm b/cbor/tag.scm
new file mode 100644
index 0000000..14734af
--- /dev/null
+++ b/cbor/tag.scm
@@ -0,0 +1,23 @@
+(define-module (cbor tag)
+ #:use-module (srfi srfi-9)
+ #:use-module (srfi srfi-9 gnu)
+ #:use-module (ice-9 format)
+
+ #:export (<cbor-tag>
+ make-cbor-tag
+ cbor-tag?
+ cbor-tag-number
+ cbor-tag-content))
+
+(define-record-type <cbor-tag>
+ (make-cbor-tag number content)
+ cbor-tag?
+ (number cbor-tag-number)
+ (content cbor-tag-content))
+
+(set-record-type-printer!
+ <cbor-tag>
+ (lambda (tag port)
+ (format port "~d(~a)"
+ (cbor-tag-number tag)
+ (cbor-tag-content tag))))
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..b2f5ce5
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,35 @@
+
+dnl -*- Autoconf -*-
+
+AC_INIT(guile-cbor, 0.1)
+AC_SUBST(HVERSION, "\"0.1\"")
+AC_SUBST(AUTHOR, "\"pukkamustard\"")
+AC_SUBST(COPYRIGHT, "'(2020)")
+AC_SUBST(LICENSE, gpl3+)
+AC_CONFIG_SRCDIR(cbor.scm)
+AC_CONFIG_AUX_DIR([build-aux])
+AM_INIT_AUTOMAKE([1.12 gnu silent-rules subdir-objects color-tests parallel-tests -Woverride -Wno-portability])
+AM_SILENT_RULES([yes])
+
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([pre-inst-env], [chmod +x pre-inst-env])
+
+dnl Search for 'guile' and 'guild'. This macro defines
+dnl 'GUILE_EFFECTIVE_VERSION'.
+GUILE_PKG([3.0 2.2 2.0])
+GUILE_PROGS
+GUILE_SITE_DIR
+if test "x$GUILD" = "x"; then
+ AC_MSG_ERROR(['guild' binary not found; please check your guile-2.x installation.])
+fi
+
+dnl Hall auto-generated guile-module dependencies
+
+
+dnl Installation directories for .scm and .go files.
+guilemoduledir="${datarootdir}/guile/site/$GUILE_EFFECTIVE_VERSION"
+guileobjectdir="${libdir}/guile/$GUILE_EFFECTIVE_VERSION/site-ccache"
+AC_SUBST([guilemoduledir])
+AC_SUBST([guileobjectdir])
+
+AC_OUTPUT
diff --git a/hall.scm b/hall.scm
index 18524b0..63fbe8a 100644
--- a/hall.scm
+++ b/hall.scm
@@ -13,7 +13,9 @@ Object Representation (CBOR) as defined by RFC 8949.")
(dependencies `())
(files (libraries
((scheme-file "cbor")
- (directory "cbor" ((scheme-file "decode")))))
+ (directory "cbor" ((scheme-file "decode")
+ (scheme-file "encode")
+ (scheme-file "tag")))))
(tests ((directory "tests" ())))
(programs ((directory "scripts" ())))
(documentation
diff --git a/pre-inst-env.in b/pre-inst-env.in
new file mode 100644
index 0000000..1556fcd
--- /dev/null
+++ b/pre-inst-env.in
@@ -0,0 +1,14 @@
+
+#!/bin/sh
+
+abs_top_srcdir="`cd "@abs_top_srcdir@" > /dev/null; pwd`"
+abs_top_builddir="`cd "@abs_top_builddir@" > /dev/null; pwd`"
+
+GUILE_LOAD_COMPILED_PATH="$abs_top_builddir${GUILE_LOAD_COMPILED_PATH:+:}$GUILE_LOAD_COMPILED_PATH"
+GUILE_LOAD_PATH="$abs_top_builddir:$abs_top_srcdir${GUILE_LOAD_PATH:+:}:$GUILE_LOAD_PATH"
+export GUILE_LOAD_COMPILED_PATH GUILE_LOAD_PATH
+
+PATH="$abs_top_builddir/scripts:$PATH"
+export PATH
+
+exec "$@"