aboutsummaryrefslogtreecommitdiff
path: root/doc/ref/general
diff options
context:
space:
mode:
Diffstat (limited to 'doc/ref/general')
-rw-r--r--doc/ref/general/base64.texi22
-rw-r--r--doc/ref/general/bst.texi37
-rw-r--r--doc/ref/general/crypto.texi17
-rw-r--r--doc/ref/general/data-formats.texi25
-rw-r--r--doc/ref/general/data-stores.texi36
-rw-r--r--doc/ref/general/datetime.texi670
-rw-r--r--doc/ref/general/glob.texi37
-rw-r--r--doc/ref/general/graph.texi65
-rw-r--r--doc/ref/general/graphviz.texi10
-rw-r--r--doc/ref/general/io.texi31
-rw-r--r--doc/ref/general/lens.texi47
-rw-r--r--doc/ref/general/options.texi32
-rw-r--r--doc/ref/general/srfi-41.texi100
-rw-r--r--doc/ref/general/sxml.texi100
-rw-r--r--doc/ref/general/util-config.texi93
-rw-r--r--doc/ref/general/util-exceptions.texi40
-rw-r--r--doc/ref/general/util-object.texi86
-rw-r--r--doc/ref/general/util-path.texi73
-rw-r--r--doc/ref/general/util-type.texi62
-rw-r--r--doc/ref/general/util.texi374
-rw-r--r--doc/ref/general/uuid.texi17
-rw-r--r--doc/ref/general/webdav.texi301
-rw-r--r--doc/ref/general/xdg-basedir.texi62
-rw-r--r--doc/ref/general/zic.texi135
24 files changed, 2472 insertions, 0 deletions
diff --git a/doc/ref/general/base64.texi b/doc/ref/general/base64.texi
new file mode 100644
index 00000000..ab6bba81
--- /dev/null
+++ b/doc/ref/general/base64.texi
@@ -0,0 +1,22 @@
+@node Base64
+@section Base64
+
+@defun base64->bytevector bv
+@defunx bytevector->base64 bv
+Base procedure for all Base64 operations.
+Takes and returns bytevectors.
+
+Throws @code{decoding-error} on invalid input.
+@end defun
+
+@defun base64-string->bytevector string
+@defunx bytevector->base64-string bv
+Base64 side is strings, while data is bytevectors.
+@end defun
+
+
+@defun base64encode string [transcoder=(native-transcoder)]
+@defunx base64decode string [transcoder=(native-transcoder)]
+Highest level Base64 procedures. Both encoded and decoded data is
+strings.
+@end defun
diff --git a/doc/ref/general/bst.texi b/doc/ref/general/bst.texi
new file mode 100644
index 00000000..d2bba0ff
--- /dev/null
+++ b/doc/ref/general/bst.texi
@@ -0,0 +1,37 @@
+@node Binary Search Tree
+@section Binary Search Tree
+
+A simple ``read only'' binary search tree.
+
+@defun make-tree pred? lst
+Constructs a new tree. @var{pred?} should be a procedure taking the
+first element of @var{lst}, along with each element, and should return
+a boolean value indicating if the specific element should go in the
+left or right subtree. (left subtree is ``truthy'' values).
+
+This operation is done recursively.
+@end defun
+
+@defun tree-node tree
+Return the value of a tree node.
+@end defun
+
+@defun left-subtree tree
+Return all ``truthy'' children of tree node.
+@end defun
+
+@defun right-subtree tree
+Return all ``falsy children of tree node.
+@end defun
+
+@defun length-of-longest-branch tree
+Get the depth of a tree.
+@end defun
+
+@defun tree-map proc tree
+Apply proc onto the value of every node in tree, keeping the structure
+of the tree.
+
+@b{Note:} this can cause the tree to no longer be a binary search
+tree, but simply a ``formless'' binary tree.
+@end defun
diff --git a/doc/ref/general/crypto.texi b/doc/ref/general/crypto.texi
new file mode 100644
index 00000000..b9e362d3
--- /dev/null
+++ b/doc/ref/general/crypto.texi
@@ -0,0 +1,17 @@
+@node Cryptographic and Hash Procedures
+@section Cryptographic and Hash Procedures
+
+This module links libcrypto, exposing some hash procedures.
+
+@defun sha256 message
+Calculate the sha256-sum of @var{message}. The message can either be a
+bytevector or a string (in which case it will de encoded as UTF-8).
+
+Returns the checksum as a bytevector.
+@end defun
+
+@defun checksum->string message-digest [port]
+Generates a hex digest string from a checksum (generated by
+@code{sha256}). The checksum is written to @var{port} if given, or
+returned as a string otherwise.
+@end defun
diff --git a/doc/ref/general/data-formats.texi b/doc/ref/general/data-formats.texi
new file mode 100644
index 00000000..037d3ae7
--- /dev/null
+++ b/doc/ref/general/data-formats.texi
@@ -0,0 +1,25 @@
+@node Data Formats
+@section Data Formats
+A data format is some way that an individual event may get serialized
+to disk. The default is iCalendar (TODO reference RFC 5545), but
+others might be available (TODO footnote and reference xcal).
+
+Each available format should be included as
+@code{(vcomponent formats @var{format-name})}.
+Which module corresponds to what file type is currently defined out of band.
+
+Each module should expose the following procedures.
+
+@defun serialize component port
+Write a serialized representation of @var{component} to @var{port}.
+@end defun
+
+@defun deserialize port
+Read a serialized representation of a component from @var{port}, and
+return the deserialized instance of this object.
+@end defun
+
+@subsection iCalendar
+RFC 5545
+
+@subsection xCal
diff --git a/doc/ref/general/data-stores.texi b/doc/ref/general/data-stores.texi
new file mode 100644
index 00000000..ec3962da
--- /dev/null
+++ b/doc/ref/general/data-stores.texi
@@ -0,0 +1,36 @@
+@node Data Stores
+@section Data Stores
+Data stores are persistant stores for events, such as databases or the
+file system. Each data store can support any number of data formats,
+but which is an implementation detail of that format and shouldn't be
+needed information from the high level view.
+@footnote{It is however important for interoperability with other programs}.
+
+@c (make <calendar-store> #:path ``hello'')
+
+@defun path store
+@end defun
+
+@deftp {GOOPS method} get-calendar this
+Returns a vcomponent object of type @code{VCALENDAR}. Should contain
+all @code{VEVENT} components of this calendar.
+@end deftp
+
+@deftp {GOOPS method} get-by-uid this uid
+Return the event object with UID equal to the string @var{uid}.
+@end deftp
+
+@deftp {GOOPS method} queue-save this event
+Queue a save event of @var{event} to the store.
+@end deftp
+
+@deftp {GOOPS method} flush this
+Force write of all queued actions.
+@end deftp
+
+@subsection VDir
+[VDIR]: http://vdirsyncer.pimutils.org/en/latest/vdir.html
+
+@subsection File
+
+@subsection SQLite
diff --git a/doc/ref/general/datetime.texi b/doc/ref/general/datetime.texi
new file mode 100644
index 00000000..037ac8d5
--- /dev/null
+++ b/doc/ref/general/datetime.texi
@@ -0,0 +1,670 @@
+@node Datetime
+@section Datetime
+
+My datetime library, with focus on date manipulation in ways sensible
+for humans. So that a date-time plus one day always keep the time of
+day.
+For example, 26 mars 2022 10:00 plus 1 day would give 27 mars 2022
+10:00, even though 25 hours have passed due to summer time starting
+(in Sweden).
+
+Note that while some of these procedures mentions timezones, almost
+nothing is actually done with it.
+
+@subsection Constants
+
+@defvar jan
+@defvarx january
+@defvarx feb
+@defvarx february
+@defvarx mar
+@defvarx mars
+@defvarx apr
+@defvarx april
+@defvarx may
+@defvarx jun
+@defvarx june
+@defvarx jul
+@defvarx july
+@defvarx aug
+@defvarx august
+@defvarx sep
+@defvarx september
+@defvarx oct
+@defvarx october
+@defvarx nov
+@defvarx november
+@defvarx dec
+@defvarx december
+Numeric constants for all months.
+@code{@var{jan} = 1}, @code{@var{dec} = 12}.
+@end defvar
+
+@defvar sun
+@defvarx sunday
+@defvarx mon
+@defvarx monday
+@defvarx tue
+@defvarx tuesday
+@defvarx wed
+@defvarx wednesday
+@defvarx thu
+@defvarx thursday
+@defvarx fri
+@defvarx friday
+@defvarx sat
+@defvarx saturday
+@anchor{sunday}
+Numeric constants for all weekdays.
+@code{@var{sunday} = 0}, @code{@var{saturday} = 6}.
+@end defvar
+
+@subsection Parameters and Configuration
+
+@deftp {parameter} week-start
+@anchor{week-start}
+Which weekday should be considered the first. Used for calculating
+week numbers, the start dates of week, and is available for UI-code
+and the like which wants it.
+@end deftp
+
+@deftp {config} week-start
+Configuration item, updates @xref{week-start}.
+@end deftp
+
+
+@subsection Datatypes
+
+@deftp {Immutable Record} <date> year month day
+Object representing a date, without any timezone information.
+Given the date 2040-03-23 (in ISO-8601 format), @var{year} = 2020,
+@var{month} = 3 and @var{day} = 23.
+
+Values higher than those usually used are possible, but not recommended.
+
+@defun date? x
+Is @var{x} a date object?
+@end defun
+
+@defun date [#:year=0] [#:month=0] [#:day=0]
+Create a new date object.
+@end defun
+
+@defun year <date>
+@defunx month <date>
+@defunx day <date>
+Fetch corresponding field from the date object.
+@end defun
+@end deftp
+
+@deftp {Immutable Record} <time> hour minute second
+Object representing a timestamp in a given day,
+without any timezone information.
+Given the time 10:20:30, @var{hour} = 10,
+@var{minute} = 20 and @var{second} = 30.
+
+Values larger than the ``regular'' are allowed, and useful since this
+type is also used for time offsets.
+
+@defun time? x
+Is @var{x} a time object?
+@end defun
+
+@defun time [#:hour=0] [#:minute=0] [#:second=0]
+Create a new time object.
+@end defun
+
+@defun hour <time>
+@defunx minute <time>
+@defunx second <time>
+Fetch corresponding field from the time object.
+@end defun
+@end deftp
+
+
+@deftp {Immutable Record} <datetime> date time tz
+
+A collation of date and time, along with an optional timezone.
+Set @code{tz = #f} if a timezone is not desired.
+
+@defun datetime? x
+Is @var{x} a datetime object?
+@end defun
+
+@defun datetime [#:date] [#:time] [#:tz] [#:year=0] [#:month=0] [#:day=0] [#:hour=0] [#:minute=0] [#:second=0]
+Creates a new <datetime>. If @var{date} or @var{time} is given, those
+are used. Otherwise, a date object is created from @var{year},
+@var{month} and @var{day}, and time is respectively created from
+@var{hour}, @var{minute} and @var{second}.
+@end defun
+
+@defun get-date
+@defunx get-timezone
+Note that @code{get-time} doesn't exists.
+@end defun
+@end deftp
+
+
+@subsection Reader Extensions
+
+This module registers reader extensions on @code{#0}, @code{#1}, and
+@code{#2}. These read either dates, times, or datetimes; using @code{string->date/-time}.
+
+@c @subsection CTIME
+
+@c These procedures are for interfacing with C's time procedures, see CTIME(3).
+
+@c The datetime<->tm procedures are internal, since they are slightly
+@c unstable (see comments in code).
+@c They are thereby not documented.
+@c @defun datetime->tm datetime
+@c Convert a @code{<datetime>} object to a @code{struct tm}, encoded in a
+@c scheme vector.
+@c @end defun
+@c
+@c @defun tm->datetime tm
+@c Converts a @code{struct tm}, as returned from @code{datetime->tm} back
+@c into a @code{<datetime>} object.
+@c @end defun
+
+@subsection Procedures
+
+@defun datetime->unix-time datetime
+Converts @var{datetime} to an integer representing its unix time.
+@end defun
+
+@defun unix-time->datetime n
+Converts a given unix timestamp to a datetime object.
+Currently forces the timezone to be UTC.
+@end defun
+
+@defun current-datetime
+Return a datetime object of the current date and time.
+Currently always returns it in UTC.
+@end defun
+
+@defun current-date
+Get the date component from a call to @code{current-datetime}.
+@end defun
+
+
+@defun get-datetime datetime
+Takes a datetime in any timezone, and renormalize it to local time (as
+defined by the environment variable TZ). This means that given UTC
+10:00 new years day would return 11:00 new years day if ran in sweden.
+@end defun
+
+
+@defun as-date date/-time
+@defunx as-time date/-time
+Both procedures takes a <date>, <time>, or <datetime>, and return
+respectively a <date> or <time> object.
+
+@code{as-date}, when given a time will return a zeroed date object.
+Vice versa for @code{as-time}.
+@end defun
+
+@defun as-datetime date/-time
+Takes a <date>, <time>, or <datetime>, and returns a <datetime> object
+with the same data, with the (possibly) missing date or time set to
+all zeroes.
+@end defun
+
+
+@defun date-zero? date
+@defunx time-zero? time
+Checks if all components are zero.
+@end defun
+
+
+@defun leap-year? year
+Given an integer @var{year}, return @code{#t} if it's a leap year, and
+@code{#f} otherwise.
+@end defun
+
+@defun days-in-month date
+Returns how many days are in the month specified by the <date> @var{date}.
+Note that the day component is ignored.
+@end defun
+
+@defun days-in-year date
+Returns how many days are in the year pointed to by @var{date}.
+@end defun
+
+@defun start-of-month date
+Returns a <date> object equal to date, but with the day component set
+to 1.
+@end defun
+
+@defun end-of-month date
+Returns a <date> object equal to date, but with the day component set
+to the last day of the month.
+
+@example
+(end-of-month #2020-01-10)
+⇒ #2020-01-31
+(end-of-month #2020-02-01)
+⇒ #2020-02-29
+@end example
+@end defun
+
+
+@defun start-of-year date
+Returns a <date> object equal to date, but with the day and month
+component set to 1.
+@end defun
+
+@defun date-stream date-increment start-day
+Returns an @ref{(guile)SRFI-43} stream of <date> objects, starting at
+@var{start-day} and stepping in increments of @var{date-increment}.
+@end defun
+
+@defun day-stream start-day
+Returns a stream of each day from @var{start-day}.
+@end defun
+
+@defun month-stream start-day
+Returns a stream of each months from @var{start-day}.
+Day component stays the same.
+@end defun
+
+@defun week-stream start-day
+Returns a stream of each week from @var{start-day}
+(increments of 7 days).
+@end defun
+
+@defun time-min a b
+@defunx time-max a b
+@defunx date-min a b
+@defunx date-max a b
+@defunx datetime-min a b
+@defunx datetime-max a b
+Returns the smaller (or larger) of @var{a} or @var{b}.
+@end defun
+
+@defun week-day date
+Returns an integer representing the week day of @var{date}.
+@ref{sunday}
+@end defun
+
+
+@defun week-1-start date [week-start=(week-start)]
+Returns the date which week 1 starts on, according to the (at least)
+Swedish rule of week counting.
+@ref{week-start}
+@end defun
+
+
+@defun week-number date [week-start=(week-start)]
+Returns the week number of @var{date}, according to the (at least)
+Swedish rule of week counting.
+@ref{week-start}
+@end defun
+
+@defun date-starting-week week-number date [week-start=(week-start)]
+Returns the first day of week @var{week-number}, @var{date} is used
+for year information.
+@ref{week-start}
+@end defun
+
+
+@defun week-day-name week-day [truncate-to] [#:key locale]
+Returns the locale dependent name for the given week day.
+
+@var{week-day} is a number per @ref{sunday}.
+@var{truncate-to} may be a number, which limits to the first @var{n}
+letters of the resulting string.
+@end defun
+
+
+@defun timespan-overlaps? s1-begin s1-end s2-begin s2-end
+Check if the interval @var{s1-begin} to @var{s1-end} overlaps with the
+interval @var{s2-begin} to @var{s2-end}.
+@end defun
+
+@defun find-first-week-day week-day date
+Returns the first instance of the given week-day after @var{date}.
+
+@example
+(find-first-week-day mon #2020-04-01)
+⇒ #2020-04-06
+(find-first-week-day mon #2020-04-10)
+⇒ #2020-04-13
+(find-first-week-day mon #2020-04-30)
+⇒ #2020-05-04
+@end example
+@end defun
+
+@defun all-wday-in-month week-day month-date
+Returns instances of the given week-day in month between
+month-date and end of month.
+@example
+(all-wday-in-month mon #2020-06-01)
+⇒ (#2020-06-01 #2020-06-08 #2020-06-15 #2020-06-22 #2020-06-29)
+(all-wday-in-month mon #2020-06-10)
+⇒ (#2020-06-15 #2020-06-22 #2020-06-29)
+@end example
+@end defun
+
+@defun all-wday-in-year week-day year-date
+Returns a list of all instances of @var{week-day} in @var{year-date}.
+@end defun
+
+@defun in-date-range? start-date end-date → date → boolean
+Returns a predicate procedure, which checks if a given date is between
+@var{start-date} and @var{end-date}.
+@end defun
+
+@defun weekday-list [week-start=(week-start)]
+Returns a list of the seven week days, with @var{week-start}
+as the beginning of the week.
+@end defun
+
+
+@defun start-of-week d [week-start=(week-start)]
+@defunx end-of-week d [week-start=(week-start)]
+Returns the date the week containing @var{d} started or ended.
+@end defun
+
+
+@defun month-days date [week-start=(week-start)]
+Given a month and and which day the week starts on,
+returns three lists, which are:
+The days leading up to the current month, but share a week
+The days in the current month
+The days after the current month, but which shares a week.
+
+@example
+ mars 2020
+må ti on to fr lö sö
+ 1
+ 2 3 4 5 6 7 8
+ 9 10 11 12 13 14 15
+16 17 18 19 20 21 22
+23 24 25 26 27 28 29
+30 31
+@end example
+@lisp
+(month-days #2020-03-01 mon)
+; ⇒ (2020-02-24 ... 2020-02-29)
+; ⇒ (2020-03-01 ... 2020-03-31)
+; ⇒ (2020-04-01 ... 2020-04-05)
+@end lisp
+Ignores day component of @var{date}.
+@end defun
+
+
+@defun days-in-interval start-date end-date
+The amount of days in the given interval, including both endpoints.
+@end defun
+
+
+@defun year-day date
+Day from start of the year, so 1 feb would be day 32.
+Also known as Julian day.
+@end defun
+
+
+@defun time->decimal-hour time
+Convert @var{time} to a decimal value, so 10:30 would become 10.5.
+@end defun
+
+@defun datetime->decimal-hour dt [start-date]
+Similar to @code{time->decimal-hour}, but also looks at the date component.
+
+@var{start-date} is required if either the month of year component of
+@var{dt} is non-zero (since months and years have a variable number of hours).
+@end defun
+
+@defun date-range start end [increment=(date day: 1)]
+Returns a list of all dates from start to end.
+Both inclusive
+@end defun
+
+@defun locale-month
+@defunx locale-month-short
+These are direct re-exports from (ice-9 i18n)
+
+@xref{Accessing Locale Information,,,guile}.
+@end defun
+
+@defun date= args ...
+@defunx date=? args ...
+@defunx date< args ...
+@defunx date<? args ...
+@defunx date> args ...
+@defunx date>? args ...
+@defunx date<= args ...
+@defunx date<=? args ...
+@defunx date>= args ...
+@defunx date>=? args ...
+Checks if all date arguments satisfy the predicate.
+@end defun
+
+@defun time= args ...
+@defunx time=? args ...
+@defunx time< a b
+@defunx time<? a b
+@defunx time> a b
+@defunx time>? a b
+@defunx time<= a b
+@defunx time<=? a b
+@defunx time>= a b
+@defunx time>=? a b
+Checks if all time arguments satisfy the predicate.
+@end defun
+
+@defun datetime= args ...
+@defunx datetime=? args ...
+@defunx datetime< a b
+@defunx datetime<? a b
+@defunx datetime> a b
+@defunx datetime>? a b
+@defunx datetime<= a b
+@defunx datetime<=? a b
+@defunx datetime>= a b
+@defunx datetime>=? a b
+Check if all datetime arguments satisfy the predicate.
+The timezone field is ignored.
+@end defun
+
+@defun date/-time< a b
+@defunx date/-time<? a b
+@defunx date/-time> a b
+@defunx date/-time>? a b
+@defunx date/-time<= a b
+@defunx date/-time<=? a b
+@defunx date/-time>= a b
+@defunx date/-time>=? a b
+Equivalent to the @code{datetime*} versions, but wraps its arguments
+in @code{as-datetime}.
+@end defun
+
+@subsection Arithmetic
+
+While only one date (and one time) type is available, it really should
+be seen as two. Absolute dates, such as the fourth of november,
+2022. The other type are intervals, such as 3 years, 4 months and 2 days.
+
+A ``type mismatch'' might therefore lead to some confounding results.
+@example
+(date- #2020-01-01 #2020-01-01)
+⇒ #00-1-11-31
+(date-difference #2020-01-01 #2020-01-01)
+⇒ #0000-00-00
+@end example
+
+@defun date+ base rest ...
+@defunx date- base rest ...
+Add or remove each difference from base.
+@end defun
+
+@defun date-difference end start
+Returns difference between the two dates, in years, months, and days.
+In such a way that
+
+@lisp
+(date= (date+ start (date-difference end start)))
+@end lisp
+@end defun
+
+@defun time+ base rest ...
+@defunx time- base rest ...
+Adds (or subtracts) each difference from the base, and returns two
+values. The sum, and how many midnight's have passed.
+
+@lisp
+(time+ #22:00:00 (time hour: 4))
+⇒ #02:00:00
+⇒ 1
+@end lisp
+@end defun
+
+@defun datetime+ base change
+@defunx datetime- base change
+@end defun
+
+@defun datetime-difference end start
+@end defun
+
+@subsection Parsing and Formatting
+
+@defun datetime->string datetime [fmt=''~Y-~m-~dT~H:~M:~S''] [#:allow-unknown?]
+
+Formats @var{datetime} into a string.
+The function will throw an error when encountering an unknown format
+specifier, unless @var{#:allow-unknown} is true.
+
+@table @samp
+@item ~~
+A literal tilde (~).
+@item ~H
+Hour, left padded with zeroes to length 2.
+@item ~k
+Like @samp{~H}, but padded with spaces.
+@item ~M
+Minute, left padded with zeroes to length 2.
+@item ~S
+Seconds, left padded with zeroes to length 2.
+@item ~Y
+Year, left padded with zeroes to length 4;
+@item ~m
+Month number, left padded with zeroes to length 2.
+@item ~d
+Day in month, left padded with zeroes to length 2.
+@item ~s
+Epoch time, per UNIX.
+@item ~e
+Same as @samp{~d}, but padded with spaces.
+@item ~1
+Shorthand for @samp{~Y-~m-~d}.
+@item ~3
+Shorthand for @samp{~H:~M:~S}.
+@item ~A
+Locale week day name.
+@item ~a
+Locale week day name, truncated to 3 characters.
+@item ~b
+Locale month name, truncated.
+@item ~B
+Locale month name, in full.
+@item ~Z
+@samp{Z} if the timezone is @samp{UTC}. Nothing otherwise.
+@end table
+@end defun
+
+@defun date->string date [fmt=''~Y-~m-~d''] [#:allow-unknown?]
+@defunx time->string date [fmt=''~H:~M:~S''] [#:allow-unknown?]
+Simple wrappers around @code{datetime->string}, which works directly
+on date or time objects.
+@end defun
+
+
+@defun string->datetime str [fmt=''~Y-~m-~dT~H:~M:~S~Z''] [locale=%global-locale]
+Attempts to parse @var{str} as a datetime, according to the ruleset @var{fmt}.
+An invalid or unparsable string will throw an error.
+
+Each token in @var{fmt} informs the parser what the next expected
+token in @var{str} is. If a binding rule is parsed multiple times,
+then the last one is used for the resulting object. For example,
+@example
+(string->datetime "10:20" "~H:~H")
+⇒ (datetime hour: 20)
+@end example
+
+spaces are literal, there is no way to match an arbitrary number of
+whitespace characters
+
+@table @samp
+@item ~~
+Next token is a literal tilde.
+
+@item ~Z
+If next token is a literal @samp{Z} then the resulting timezone is set
+to @samp{UTC}, otherwise does nothing.
+
+@item ~p
+The next token is an AM/PM indicator, matched by the regex
+@code{^([AaPp])[.]?[Mm][.]?}. A valid token will reinterpret the last
+hour indicator as 12-hour time (instead of 24 hour time), regardless
+if its before or after this token.
+
+@item ~b
+@itemx ~B
+@itemx ~h
+Parses a month by name, just as @code{parse-month}.
+
+@item ~H
+@itemx ~M
+@itemx ~S
+@itemx ~m
+@itemx ~d
+Parses up to two digits, but possibly less if a non-digit appears in
+the string. Then stores the resulting value in either the hour,
+minute, second, month, or day slot of the resulting object.
+
+This double function allows both dates without delimiters, such as
+``0102'' to be correctly parsed, but also more free form formats, such
+as ``1 jan''.
+
+@item ~Y
+Equivalent to @samp{~H}, but reads up to 4 digits, and stores the
+result in the year field.
+@end table
+@end defun
+
+
+@defun parse-month str [locale=%global-locale]
+Returns the first month whose name has @var{str} as its prefix.
+The result will be on the interval [1, 12], or -1 if no month matched.
+@end defun
+
+
+@defun string->time str [fmt=''~H:~M:~S''] [locale=%global-locale]
+@defunx string->date str [fmt=''~Y-~m-~d''] [locale=%global-locale]
+Wrappers around @code{string->datetime}, but only returning the time
+or date component.
+@end defun
+
+
+@defun string->date/-time string
+Parses string as an ISO-8601 string. Checks for the existence of
+@code{T}, @code{:}, or @code{-} to determine if it's a datetime, time
+or date.
+@end defun
+
+@defun parse-ics-date str
+@defunx parse-ics-time str
+@defunx parse-ics-datetime str [zone]
+Parses dates per RFC5545.
+@end defun
+
+@defun parse-iso-date str
+@defunx parse-iso-time str
+@defunx parse-iso-datetime str
+Parses (the well known subset) of ISO-compatible dates.
+@end defun
+
+@defun parse-freeform-date str
+Currently an alias for parse-iso-datetime, but should preferably be extended.
+@end defun
diff --git a/doc/ref/general/glob.texi b/doc/ref/general/glob.texi
new file mode 100644
index 00000000..400eb1f7
--- /dev/null
+++ b/doc/ref/general/glob.texi
@@ -0,0 +1,37 @@
+@node Glob
+@section Glob
+
+@defun glob str
+Globs (glob(7)) on @var{str}, returing a list of files, which will be
+on the same form of the glob. E.g. @code{(glob "../*")} will return
+strings all starting with ``../''
+
+If no matches are found, a misc error is thrown.
+@end defun
+
+
+
+@defvar GLOB_NOMAGIC
+@defvarx GLOB_NOCHECK
+@defvarx unix
+@defvarx GLOB_NOSPACE
+@defvarx GLOB_TILDE_CHECK
+@defvarx GLOB_ALTDIRFUNC
+@defvarx GLOB_NOSORT
+@defvarx GLOB_NOMATCH
+@defvarx GLOB_TILDE
+@defvarx GLOB_ERR
+@defvarx GLOB_MAGCHAR
+@defvarx GLOB_BRACE
+@defvarx GLOB_APPEND
+@defvarx GLOB_NOSYS
+@defvarx GLOB_DOOFFS
+@defvarx GLOB_NOESCAPE
+@defvarx GLOB_MARK
+@defvarx GLOB_PERIOD
+@defvarx linux
+@defvarx GLOB_ABORTED
+@defvarx _POSIX_VDISABLE
+@defvarx GLOB_ONLYDIR
+``Symbols'' imported from the C header ``glob.h''. See that documentation.
+@end defvar
diff --git a/doc/ref/general/graph.texi b/doc/ref/general/graph.texi
new file mode 100644
index 00000000..1677b635
--- /dev/null
+++ b/doc/ref/general/graph.texi
@@ -0,0 +1,65 @@
+@node A Graph data structure
+@section A Graph data structure
+
+This is a simple immutable directed graph.
+
+Most operations are O(n), since Scheme lacks a total order betwen
+arbitrary objects.
+
+@defun make-graph [node-key-proc=identity] [node-equal?=eq?]
+Constructs a new graph.
+
+@var{node-key-proc} should be a procedure mapping the actual nodes to
+a value which can be compared. These values are sometimes called
+``node keys''.
+@cindex node keys
+
+@var{node-equal?} should return if two nodes are equal or not.
+@end defun
+
+@defun rebuild-graph [old-graph] [nodes='()] [edges='()]
+@c TODO document me
+@end defun
+
+@defun graph-empty? graph
+Does the graph contaitn
+@end defun
+
+@defun add-node graph node edge-neighbors
+Adds the value @var{node} to @var{graph}. @var{edge-neighbors} should
+be a list of node keys.
+@end defun
+
+@defun get-node graph key
+Retrieve a node from the graph, given its node key.
+
+Returns @code{#f} if no such node exists.
+@end defun
+
+@defun remove-node graph node
+Remvoe @var{node} from @var{graph}, if it exists.
+@end defun
+
+@defun find-dangling-node graph
+Find a node in the graph which no other node ``depends'' on (has an
+edge pointing at it).
+
+NOTE this is O(n^2) (maybe, sort of?)
+Getting it faster would require building an index, which
+is hard since there isn't a total order on symbols.
+@end defun
+
+
+@defun pop-dandling-node graph
+Find a node as per @code{find-dangling-node}, and return two values:
+the node, and a new graph without that node.
+@end defun
+
+@defun resolve-dependency-graph graph
+If each edge is assumed to indicate a nodes dependencies, then this
+procedure will find return a flat list where each dependency is before
+its dependants.
+
+If any link is missing, or a cycle exists, then the result is
+undefined.
+@end defun
diff --git a/doc/ref/general/graphviz.texi b/doc/ref/general/graphviz.texi
new file mode 100644
index 00000000..72817ea8
--- /dev/null
+++ b/doc/ref/general/graphviz.texi
@@ -0,0 +1,10 @@
+@node Graphviz
+@section Graphviz
+
+The graphviz library comes bundled with Guile bindings, but without a
+corresponding .scm file exporting the symbols. The module @code{(guile)} does
+exactly that.
+
+This ``header'' is borrowed from
+@url{https://github.com/roelj/graphviz-guile/blob/master/graphviz.scm},
+under GPL 3.0.
diff --git a/doc/ref/general/io.texi b/doc/ref/general/io.texi
new file mode 100644
index 00000000..3f67700b
--- /dev/null
+++ b/doc/ref/general/io.texi
@@ -0,0 +1,31 @@
+@node IO operations
+@section IO operations
+
+Provided by module @code{(hnh util io)}.
+
+@defun open-input-port path
+@defunx open-output-port path
+Like @code{open-*-file}, but ``-'' gives @code{standard-@{input,output@}}.
+@end defun
+
+@defun read-lines port
+Return a list of all lines read from port.
+@end defun
+
+@defun with-atomic-output-to-file filename thunk
+Same functionality as the regular @var{with-output-to-file}, but
+with the difference that either everything is written, or nothing
+is written, and if anything is written it's all written atomicaly at
+once (the original file will never contain an intermidiate state).
+Does NOT handle race conditions between threads.
+
+propagates the return value of @var{thunk} upon successfully writing
+the file, and @code{#f} otherwise.
+@end defun
+
+@defun call-with-tmpfile proc [#:tmpl ``/tmp/file-XXXXXXX'']
+@end defun
+
+@defun read-file path
+Open file at path, and return its content as a string.
+@end defun
diff --git a/doc/ref/general/lens.texi b/doc/ref/general/lens.texi
new file mode 100644
index 00000000..eeddd6ca
--- /dev/null
+++ b/doc/ref/general/lens.texi
@@ -0,0 +1,47 @@
+@node Lenses
+@section Lenses
+
+Provided by the module @code{(hnh util lens)}
+
+@defun modify object lens f args ...
+@end defun
+
+@defmac modify* object lens
+@defmacx modify* object lens rest ...
+@end defmac
+
+@defmac set object lenses ... value
+@end defmac
+
+@defmac get object lenses ...
+@end defmac
+
+
+@defun make-lens getter setter
+@end defun
+
+@defmac build-lens getter setter
+Where any of getter or setter can either be a single symbol, or a list.
+@end defmac
+
+@deftp {Scheme Lens} identity-lens
+@end deftp
+
+@defun compose-lenses lenses ...
+@defunx lens-compose lenses ...
+Lenses composes left to right, so earlier lenses in @var{lenses} are
+applied earlier.
+@end defun
+
+@deftp {Scheme Lens} ref idx
+Focuses the element at index @var{idx} in a list.
+@end deftp
+
+@deftp {Scheme Lens} car*
+@deftp {Scheme Lens} cdr*
+Focuses the first or second element of a pair.
+@end deftp
+
+@defun each object lens proc
+@end defun
+
diff --git a/doc/ref/general/options.texi b/doc/ref/general/options.texi
new file mode 100644
index 00000000..675e91f3
--- /dev/null
+++ b/doc/ref/general/options.texi
@@ -0,0 +1,32 @@
+@node Getopt-Long Extensions
+@section Getopt-Long extensions
+
+The module @code{(hnh util options)} extend Guile's
+@code{(ice-9 getopt-long)}. The extra keys which can be specified on
+an option are
+
+@table @samp
+@item (description string)
+A propper description of the value. Should be written for human
+consumption.
+
+@item (value value-spec)
+Value is from the core library, but here ...
+@c TODO document me
+@end table
+
+@defun getopt-opt options
+Remove extensions from @var{options}, turning it into a structure
+which can be passed to @code{getopt-long}.
+@end defun
+
+@defun format-arg-help options
+Pretty print an option summary.
+
+Each description will be parsed as XML and then fed through our markup
+system @xref{Markup}.
+@end defun
+
+@defun print-arg-help options [port=(current-error-port)]
+Formats and prints option spec.
+@end defun
diff --git a/doc/ref/general/srfi-41.texi b/doc/ref/general/srfi-41.texi
new file mode 100644
index 00000000..d8020ecc
--- /dev/null
+++ b/doc/ref/general/srfi-41.texi
@@ -0,0 +1,100 @@
+@node SRFI 41 Utilities
+@section SRFI 41 Utilities
+
+Extra utilities for handling streams. Provided by @code{(srfi srfi-41
+util)}.
+
+@defun stream-car+cdr stream
+Returns the car and cdr of stream.
+@end defun
+
+@defun interleave-streams < streams
+Merges a number of totally ordered streams into a single
+totally ordered stream.
+
+((≺, stream)) → (≺, stream)
+@end defun
+
+@defun stream-insert < item stream
+Insert item in the totally ordered stream (≺, stream).
+@end defun
+
+
+@defun filter-sorted-stream pred stream
+@end defun
+
+
+@defun filter-sorted-stream* pred keep-remaining? stream
+@end defun
+
+@defun get-stream-interval start-pred end-pred stream
+Get the substream from stream from the first match of start-pred, to
+the first match of end-pred after start-pred.
+@end defun
+
+
+@defun stream-find pred stream
+Find the first element in stream satisfying the predicate, or #f none
+was found.
+@end defun
+
+
+@defun stream-remove pred stream
+Stream-filter, but with predicate negated.
+@end defun
+
+
+@defun stream->values stream
+Equivalent to list->values. Returns as many objects as the stream is long.
+@end defun
+
+
+@defun repeating-naturals from repeats
+Natural numbers from @var{from} and up, but each repeated @var{repeat}
+times.
+@example
+(stream->list 15 (repeating-naturals 1 3))
+⇒ (1 1 1 2 2 2 3 3 3 4 4 4 5 5 5)
+@end example
+@end defun
+
+
+@defun stream-partition pred stream
+@end defun
+
+@defun stream-split idx stream
+@end defun
+
+@defun stream-paginate stream [page-size=10]
+@end defun
+
+
+@defun eager-stream-cons a b
+stream cons, but eval arguments beforehand.
+@end defun
+
+@defun stream-split-by pred strm
+Chunks the content of @var{strm} into lists, breaking on @var{pred}.
+If the end of the stream is reached, the remaining objects
+are put into a final chunk.
+
+Can for example be used to split a stream of characters into a stream
+of words.
+
+@lisp
+(stream-split-by (lambda (c) (char=? c #\space))
+ (-> "This is a short test"
+ string->list list->stream))
+⇒ #<stream (#\T #\h #\i #\s #\space)
+ (#\i #\s #\space)
+ (#\a #\space)
+ (#\s #\h #\o #\r #\t #\space)
+ (#\t #\e #\s #\t)>
+@end lisp
+@end defun
+
+@defun stream-timeslice-limit stream timeslice
+Wrap a stream in time limits. Each element has at most @var{timeslice}
+seconds to produce a value, otherwise the stream ends. Useful for finding the
+``final'' element matching a predicate in an infinite stream.
+@end defun
diff --git a/doc/ref/general/sxml.texi b/doc/ref/general/sxml.texi
new file mode 100644
index 00000000..dd635b4c
--- /dev/null
+++ b/doc/ref/general/sxml.texi
@@ -0,0 +1,100 @@
+@node sxml namespaced
+@section Namespaced SXML
+
+Namespaces is a variant to ``regular'' SXML. Difference being that
+instead of representing XML-tags as symbols, they are instead actual
+objects.
+
+For example
+@example
+`(a (b "Content"))
+@end example
+
+Would be represented as
+@example
+`(,(xml 'a)
+ (,(xml 'b)
+ "Content"))
+@end example
+
+@defun namespaced-sxml->sxml tree [namespace-prefixes='()]
+Takes a tree of namespaced-sxml, and optionally an assoc list from
+namespace symbols, to prefered prefix.
+
+Returns a sxml tree, with xmlns:<prefix>=namespace attributes
+@end defun
+
+@defun namespaced-sxml->xml tree [namespaces='()] [port='(current-output-port)]
+Serializes the namespaced sxml tree to port. @var{namespaces} should
+be an association list from namespace symbols, to prefered prefixes.
+@end defun
+
+@defun namespaced-sxml->sxml/namespaces tree [namespace-prefixes='()]
+Returns two values:
+@itemize
+@item An SXML tree (which doesn't have namespace attributes)
+@item an association list from namespace symbols, to used prefixes.
+@end itemize
+@end defun
+
+@c xml->namespcaed-sxml and sxml->namespaced-sxml don't share
+@c implementation, despite doing almost the same thing. This is since
+@c xml->namespaced-sxml directly uses the ssax parser, giving us great
+@c controll, while sxml->namespaced-sxml attempt to look at symbols.
+
+@defun xml->namespaced-sxml port-or-string
+Reads xml from port, and return a namespaced SXML tree.
+@end defun
+
+@defun sxml->namespaced-sxml tree namespaces
+Converts a ``regular'' SXML tree into a namespaced sxml tree.
+@var{namespaces} must be an association list which maps each prefix
+used in @var{tree} onto a full XML namespace.
+
+The key @code{#f} can be used to map non-namespaced elements into a
+namespace.
+@end defun
+
+@defun xml tag
+@defunx xml ns tag [attrs]
+@anchor{xml-tag}
+ A single XML element, suitable to go as the car of a list to
+ create a full object.
+
+ @var{xml} is a shorthand to @code{make-xml-element}, which
+ either takes just a tag (for non-namespaced elements), or a
+ namespace, a tag, and a list of attributes.
+
+ @itemize
+ @item @var{tag} should be a symbol.
+ @item @var{ns} should be a symbol.
+ @item @var{attrs} should be a hash table.
+ @end itemize
+
+ @defun make-xml-element tagname namespace attributes
+ @end defun
+
+ @defun xml-element? x
+ @end defun
+
+ @defun xml-element-tagname el
+ @end defun
+
+ @defun xml-element-namespace el
+ @end defun
+
+ @defun xml-element-attributes el
+ @end defun
+@end defun
+
+
+@defun make-pi-element tag body
+ @defun pi-element? x
+ @end defun
+
+ @defun pi-tag pi
+ @end defun
+
+ @defun pi-body pi
+ @end defun
+@end defun
diff --git a/doc/ref/general/util-config.texi b/doc/ref/general/util-config.texi
new file mode 100644
index 00000000..2e197bcc
--- /dev/null
+++ b/doc/ref/general/util-config.texi
@@ -0,0 +1,93 @@
+@node Configuration
+
+@section Configuration
+
+Provided by the module @code{(calp util config)}.
+
+Configuration items are similar to regular defines, but global to the
+entire program, and assignable before they are declared.
+Their primary purpose is to allow a user supplied @file{config.scm},
+without needing all appropriate modules already loaded.
+
+@defmac define-config name default kw-parameters ...
+Declares a new configuration variable named @var{named}, with the
+default value @var{default}. @var{kw-parameters} are given on Guile's
+standard @code{hash: value} form. @pxref{get-property} for available parameters.
+@end defmac
+
+@defun get-property config-name property-key
+@anchor{get-property}
+Returns a metadata-slot value for the given configuration setting.
+
+Each declared configuration item has (at least) the following metadata
+slots:
+
+@table @samp
+@item description
+Short human-readable description of this configuration item.
+
+@item source-module
+Module in which this item was declared. Automatically filled in by @code{define-config}.
+
+@item pre
+Procedure which can pre-process or validate set values. Think about it
+as if @code{(set-config! key value)} expands to
+@code{(true-set-config! key (pre value))},
+with the bonus that if @code{pre value} returns @code{#f} then the
+assignment fail.
+
+@item post
+Procedure to run after the value is set. For example for updating a
+local parameter.
+@example
+(define-public week-start (make-parameter sun))
+(define-config week-start sun
+ description: "First day of week"
+ pre: (ensure (lambda (x) (<= sun x sat)))
+ post: week-start)
+@end example
+@end table
+
+@findex set-property!
+Note that @code{set-property!} doesn't exist, since properties are read-only.
+@end defun
+
+@defun set-config! name value
+Sets the @var{value} of the configuration variable @var{name}.
+@end defun
+
+@defun get-config key [default]
+Retrieve the configured value for @var{key}. Throws an error if key
+isn't set, and @var{default} isn't given (to differentiate it from
+@code{#f} being set.
+@end defun
+
+@defun {(ensure predicate)} value
+Helper procedure for @code{pre} hooks. Curried function which checks
+if @var{value} satisfies @var{predicate}, and if so returns @var{value}.
+
+@example
+(define-public ((ensure predicate) value)
+ (if (predicate value)
+ value #f))
+@end example
+@end defun
+
+@defun get-configuration-documentation
+Collects all variables we know about (both defined and non-defined
+(but set)), and builds a markup-tree with information about them.
+@c TODO document markup format, link it here
+@end defun
+
+@defun format-procedure procedure
+Procedure mainly used by @code{get-configuration-documentation}. Gives
+a simple string representation of the given procedure.
+
+@example
+(format-procedure format-procedure)
+⇒ "format-procedure(proc)"
+
+(format-procedure (lambda* (key: (a 1)) (+ a 3)))
+⇒ "λkey: a"
+@end example
+@end defun
diff --git a/doc/ref/general/util-exceptions.texi b/doc/ref/general/util-exceptions.texi
new file mode 100644
index 00000000..34ba33f9
--- /dev/null
+++ b/doc/ref/general/util-exceptions.texi
@@ -0,0 +1,40 @@
+@node Exception & Warning Utilities
+@section Exception & Warning Utilities
+@anchor{warning}
+
+Warnings are like exceptions, but only fatal when wanted.
+
+@code{(hnh util exceptions)}
+
+@defun warning fmt args ...
+Emit a warning.
+
+If the parameter @var{warnings-are-errors} is true, then an exception
+of type @code{'warning} will be raised, with @var{fmt} and @var{args}
+as arguments.
+
+If that parameter is false, then the procedure in
+@var{warning-handler} will instead be called.
+@end defun
+
+@deftp {parameter} warning-handler
+Parameter containing proceudre which will be called for non-throwing
+warnings. This procedure is assumed by the program to log the warning
+in some way, and continue program flow. But anything goes.
+
+The procedure is given a format specifier (as per Scheme's basic
+@code{format}), along with the correct number of arguments.
+@end deftp
+
+@deftp {parameter} warnings-are-errors
+Boolean parameter, which if set causes warnings to be thrown as exceptions.
+@end deftp
+
+@defun fatal fmt args ...
+Display the message in fmt, populated with args, then raises the UNIX
+signal SIGINT, which kills the program.
+@end defun
+
+@defun filter-stack pred? stack
+@c TODO document me
+@end defun
diff --git a/doc/ref/general/util-object.texi b/doc/ref/general/util-object.texi
new file mode 100644
index 00000000..ceac2f2a
--- /dev/null
+++ b/doc/ref/general/util-object.texi
@@ -0,0 +1,86 @@
+@node define-type
+@section Yet Another Object System
+
+@defmac define-type (name type-parameters ...) fields ...
+Introduce a new type.
+
+Each field is either a symbol, or a list where the first element is a
+symbol, and the remaining elements are alternating keywords and
+values, as per @ref{Field Parameters}. All fields are optional by
+default, but can be made non-optional through its type parameter.
+
+The example below creates a new type called @var{type}, with a custom
+printer which always displays the string ``TYPE''. It has two fields,
+@var{x}, which must be an integer, and @var{y}, which can have any
+type, but gets the value ``Hello'' in none is given.
+@example
+(define-type (type #:printer (lambda (r p) (display "TYPE" p)))
+ (x #:type integer?)
+ (y #:default "Hello"))
+@end example
+@end defmac
+
+@subsection Type Parameters
+
+@deffn {Type Parameter} constructor (λ (primitive-constructor type-validator))
+Use a custom constructor for the type. The given procedure is called
+with two values:
+@itemize
+@item the types primitive (and usually hidden) constructor,
+which takes as many arguments as there are fields, in the order given
+in define-type, and
+@item the type validator procedure, which also takes all arguments,
+but instead either returns an undefined value if everything is fine,
+or throws @code{'wrong-type-arg} otherwise.
+@end itemize
+The procedure should then return a new procedure, which will be bound
+as the constructor for the type. Note that default values are current
+disregarded with custom constructors.
+
+A custom constructor for the type above might look like
+@example
+(lambda (primitive-constructor type-check)
+ (lambda* (#:key x y)
+ (type-check x y)
+ (primitive-constructor x y)))
+@end example
+@end deffn
+
+@deffn {Type Parameter} printer (λ (record port))
+Use a custom printer for the type.
+@end deffn
+
+@subsection Field Parameters
+@anchor{Field Parameters}
+
+@deffn {Field Parameter} default value
+Value the field should get if not given.
+@end deffn
+
+@deffn {Field Parameter} type type-clause
+A type predicate that the field must obey. See @ref{type-clause} for details.
+@end deffn
+
+@subsection Introduced Bindings
+
+Define type introduces a number procedures. (@var{<name>} should be
+replaced with whatever was given as @var{name} to define-type.
+
+@defun @var{<name>} [kv-args ...]
+Type constructor. Takes key-value arguments. Where the keys are the
+names of the fields.
+@end defun
+
+@defun @var{<name>}? x
+Type predicate.
+@end defun
+
+And for each field @var{<field>}:
+
+@defun @var{<field>} object [value]
+Accessor for the given filed.
+Returns the current value if called with only an object, and returns a
+new object with @var{field} set to @var{value} if called with two values.
+
+The updating version checks the type if #:type was given on creation.
+@end defun
diff --git a/doc/ref/general/util-path.texi b/doc/ref/general/util-path.texi
new file mode 100644
index 00000000..ba78a828
--- /dev/null
+++ b/doc/ref/general/util-path.texi
@@ -0,0 +1,73 @@
+@node Path Utilities
+@section Path Utilities
+
+An extended path library for Guile. This library builds upon the path
+utilities provided by @xref{File System,,,guile}, but adds
+manipulation procedures. These procedures should work no matter what
+the systems directory delimiter is, even though this documentation
+uses ``/'' for its examples.
+
+Provided by the module @code{(hnh util path)}.
+
+@defun path-absolute? string
+Alias of @code{absolute-file-name?} from Guile.
+@end defun
+
+@defun path-append path paths ...
+Joins all strings into a path, squeezing duplicated delimiters, but
+ensuring that all delimiters that are needed are there.
+
+Note that delimiters embedded inside the string, which aren't first or
+last in a substring (or are the only thing in a string) are
+kept. Meaning that
+@example
+(path-append "/" "hello") ⇒ "/hello"
+(path-append "/usr/local/bin" "cmd") ⇒ "/usr/local/bin/cmd"
+@end example
+@end defun
+
+
+@defun path-join lst
+@lisp
+(apply path-append lst)
+@end lisp
+@end defun
+
+
+@defun path-split path
+Splits path into a list of components.
+The first component will be @code{""} if path is absolute.
+@end defun
+
+
+@defun filename-extension filename
+Returns the extension of the filename without a leading period, or the
+empty string if none exists.
+
+@example
+(filename-extension "file.tar.gz")
+⇒ "gz"
+@end example
+@end defun
+
+@defun realpath path
+Equivalent of realpath(3). Absolute file names are returned as is,
+while relative filenames gets expanded to absolute filenames.
+@end defun
+
+@defun relative-to base path
+Returns @var{path} as a relative path relative to @var{base}.
+
+base must be non-empty
+@example
+(relative-to "/some" "/some/path")
+;; ⇒ "path"
+
+(relative-to "/some" "/other/path/")
+;; ⇒ "../path"
+
+(relative-to "/a/b/c" "/a/b")
+;; ⇒ "/a/b"
+@end example
+
+@end defun
diff --git a/doc/ref/general/util-type.texi b/doc/ref/general/util-type.texi
new file mode 100644
index 00000000..104b00b3
--- /dev/null
+++ b/doc/ref/general/util-type.texi
@@ -0,0 +1,62 @@
+@node Type utilities
+@section Type utilities
+
+Provided by the module @code{(hnh util type)}
+
+@subsection Type Clauses
+@anchor{type-clause}
+@cindex type-clause
+
+Type clauses are an effective way of writing compound predicates
+without explicitly mentioning the variable at all steps.
+
+The simplest type predicate is a single symbol, which is directly
+called on the object:
+@example
+predicate? ⇒ (predicate? x)
+@end example
+
+Otherwise, if the predicate is a list then the variable is spliced
+into the argument list in the first position:
+@example
+(proc args ...) ⇒ (proc x args ...)
+@end example
+
+The two primitives @code{and} and @code{or} are also available, which
+both take an arbitrary number of predicates, and calls them in order,
+with Scheme's usual short-circuiting rules.
+@footnote{@code{and} and @code{or} doesn't have to be primitives, but
+we would otherwise have one hell of a namespace conflict}
+
+@defmac list-of variable type-clause
+Checks if @var{variable} is a list, and that every element satisfies type-clause.
+@end defmac
+
+@defmac pair-of variable car-type-clause cdr-type-clause
+Check if @var{variable} is a cons-pair, and that the car satisfies
+@var{car-type-clause}, and that the cdr satisfies @var{cdr-type-clause}.
+@end defmac
+
+@subsection Deffinitions
+
+@defmac build-validator-body variable type-clause
+``Entry point'' of type clauses. Inserts variable into the
+type-clause, returning something ready to be passed along the eval (or
+rather, spliced into another macro).
+
+Also used if new ``primitives'' are to be added, such as list-of.
+@end defmac
+
+@defmac typecheck variable type-clause [procedure-name=(current-procedure-name)]
+Checks @var{variable} against @var{type-clause}, and raises
+@code{'wrong-type-argument} if it fails. @var{procedure-name} is used
+as the calling procedure for @code{scm-error}.
+
+Useful at the start of procedures.
+@end defmac
+
+
+@defmac current-procedure-name
+Returns the current procedure name as a symbol, or @code{#f} if not found.
+@end defmac
+
diff --git a/doc/ref/general/util.texi b/doc/ref/general/util.texi
new file mode 100644
index 00000000..1d6a4e7a
--- /dev/null
+++ b/doc/ref/general/util.texi
@@ -0,0 +1,374 @@
+@node Miscellaneous utilities
+@section Miscellaneous utilities
+
+A kitchen sink utility library. Note should be taken that some core
+procedures and forms are replaced, but all in compatible ways.
+
+Provided by the module @code{(hnh util)}.
+
+@defmac define-syntax [stx]
+Extends the default syntax from the default
+@lisp
+(define-syntax @r{<name>} (λ (stx) body ...))
+@end lisp
+To also allow
+@lisp
+(define-syntax (@r{<name>} stx) body ...)
+@end lisp
+@end defmac
+
+
+@defmac when pred body ...
+@defmacx unless pred body ...
+Extends @var{when} and @var{unless} to return @code{'()} on the
+false-case (instead of being undefined).
+@end defmac
+
+
+@defmac aif condition consequent alternate
+@defmacx awhen condition consequent ...
+Equivalent to the standard @var{if} and @var{when}@footnote{Actually
+our extra specialized @var{when}}, but binds the return of
+@var{condition} in the variable @var{it}.
+@end defmac
+
+
+@defmac for key in collection body ...
+@defmacx for (key ...) in collection body ...
+Syntactic sugar over @code{map}.
+@example
+(for x in collection
+ body ...)
+@end example
+expands into
+@example
+(map (lambda (x) body ...) collection)
+@end example
+
+If keys are a list, an match-lambda is used instead.
+@xref{Pattern Matching,,,guile}
+
+@defun break args ...
+Abandon the entire loop. Returing what was given to @code{break}.
+@end defun
+
+@defun continue [arg]
+Abandon the current iteration of the loop. If an argument is given,
+it's used as the result in the resulting list, otherwise @code{#f} is
+used.
+@end defun
+
+@end defmac
+
+
+@defmac print-and-return expr
+Prints @var{expr}, and then returns it.
+Only evaluates @var{expr} once.
+@end defmac
+
+
+@defun swap f
+@math{swap (λ (x y) body ...) ⇔ λ (y x) body ...}
+@end defun
+
+@defmac set! key value ...
+@defmacx set! key = proc ...
+@defmacx set! key = (op args ...) ...
+Extends @var{set!} to allow multiple forms in one, also introduces the
+cases:
+@lisp
+(set! x = f) ⇔ (set! x (f x))
+(set! x = (+ 1) ⇔ (set! x (+ x 1))
+@end lisp
+@end defmac
+
+@defmac set/r! key value ...
+See @var{set!}, but also returns the final value.
+@end defmac
+
+@defmac label name proc
+Equivalent to
+@lisp
+(letrec ((name proc))
+ proc)
+@end lisp
+@end defmac
+
+
+@defun sort* items comperator [get=identity]
+@defunx sort*! items comperator [get=identity]
+A sort more similar to Python's. Applies @var{get} to each item before
+calling @var{comperator} on them.
+
+@var{sort*!} may modify the input list.
+@end defun
+
+
+@defun find-extreme items [<=<] [access=identity]
+Returns 2 values, the most extreme value, as compared by @var{<} after
+calling @var{access} on each element, along with the remaining values
+in an undefined order.
+
+Should be faster than @var{car+cdr} ∘ @var{sort*}.
+@end defun
+
+@defun find-min list [access=identity]
+@defunx find-max list [access=identity]
+See @var{find-extreme}
+@end defun
+
+@defun filter-sorted proc list
+@c TODO document me
+@end defun
+
+@defun != args ...
+@lisp
+(define != (negate =))
+@end lisp
+@end defun
+
+@defun init+last list
+Returns two values: everything except the last element of @var{list},
+and the last element of @var{list}.
+@end defun
+
+@defun take-to lst n
+Equivalent to @var{take}, but return everything (instead of crash) if
+n > (length lst).
+@end defun
+
+@defun string-take-to str n
+Same as @var{take-to}, but for strings
+@end defun
+
+
+@defun string-first
+@defunx string-last
+Returns the first and last character of a string respectivly
+@end defun
+
+
+@defun as-symb s
+Returns @code{(string->symbol s)} if @var{s} is a string, @var{s} otherwise.
+@end defun
+
+@defun enumerate lst
+Returns a list of lists, where the @var{car} is the index in the list,
+and the @var{cadr} is the corresponding element of the original list
+@end defun
+
+
+@defun unval proc [n=0]
+Takes a procedure returning multiple values, and returns a function
+which takes the same arguments as the original procedure, but only
+returns one of the procedures. Which procedure can be sent as an
+additional parameter.
+@end defun
+
+
+@defun flatten lst
+Takes an arbitrarily nested list, and flattens it to a depth 1 list
+@end defun
+
+
+@defmac let-lazy forms body ...
+Syntactically equivalent to a regular @var{let}, but wraps each variable
+in @var{forms} in @var{delay}, while it finds each instance of that
+variable in body and wraps in in @var{force}.
+@end defmac
+
+
+@defun map/dotted proc dotted-list
+Like @var{map}, but also works for improper lists.
+@end defun
+
+
+@defun assq-merge a b
+@c TODO
+@end defun
+
+@defun kvlist->assq
+Given a flat list where each odd element (counting from 1) is a
+keyword, and each even element is any value, return these as a list of
+pairs of symbols and values.
+
+@lisp
+(kvlist->assq '(#:a 1 #:b "Hello"))
+⇒ ((a . 1)
+ (b . "Hello"))
+@end lisp
+@end defun
+
+@defun assq-limit alist [number=1]
+@c TODO document
+@end defun
+
+@defun group-by proc lst
+Calls @var{proc} on each element in @var{lst}, and return a
+association list which @code{(proc e)} as its keys, and all elements
+which mapped to that value.
+
+The values returned by @var{proc} are compared as per @code{equal?}.
+@end defun
+
+@defun split-by lst element
+Split a list into sub-lists on @var{element}
+@lisp
+(split-by '(0 1 2 3 4 2 5 6) 2)
+⇒ ((0 1) (3 4) (5 6))
+@end lisp
+@end defun
+
+
+@defun span-upto count predicate list
+Simar to span from srfi-1, but never takes more than
+@var{count} items. Can however still take less.
+@example
+(span-upto 2 char-numeric? (string->list "123456"))
+⇒ (#\1 #\2)
+⇒ (#\3 #\4 #\5 #\6)
+(span-upto 2 char-numeric? (string->list "H123456"))
+⇒ ()
+⇒ (#\H #\1 #\2 #\3 #\4 #\5 #\6)
+@end example
+@end defun
+
+
+@defun cross-product args ...
+Returns the cross product between all given lists. Each pair will be a
+list, whose indices matches the order of the inputs
+@end defun
+
+@defun string-flatten tree
+Given an arbitary tree, do a pre-order traversal, appending all strings.
+
+Non-strings are converted to strings, and also appended.
+@end defun
+
+@defun intersperse item list
+Inserts @var{item} between each element in @var{list}.
+@end defun
+
+
+@defun insert-ordered item collection [<]
+Inserts @var{item} into @var{collection}, such that collection
+remainins sorted if it was sorted beforehand.
+@end defun
+
+
+@defmac -> item forms ...
+@defmacx ->> item forms ...
+Applies each form onto item, from left to right.
+A form can either by a symbol, which is the applied directly, or a
+list, in which case @var{->} inserts item as the second argument
+(after the operand), and @var{->>} inserts it last.
+@end defmac
+
+
+@defmac set (accessor object) value
+@defmacx set (accessor object) = (operation args ...)
+See @xref{SRFI-9 Records,,,guile}
+@end defmac
+
+@defmac set-> object (accessor value) rest ...
+@defmacx set-> object (accessor = (operator args)) rest ...
+Wrapper around @var{set}, but applies transformations from left to
+right, similar to @var{->}.
+@end defmac
+
+
+@defmac and=>> value procedures ...
+Chained application of @code{and=>}, so applies each procedure from
+left to right, stopping when one return @code{#f}.
+@end defmac
+
+@defun downcase-symbol
+Converts a symbol to lower case.
+@end defun
+
+
+@defun group list chunk-size
+Splits @var{list} into sub-lists of size @var{chunk-size}.
+Requires that @math{chunk-size|(length list)}
+@end defun
+
+
+@defun iterate proc until base
+Repeatedly applies @var{proc} to @var{base}, until @var{until} is
+satisfied.
+@end defun
+
+@defun valued-map proc lists ...
+Applies a procedure which returns multiple values to each element of a
+list, and returns all values returned from all procedure calls.
+@example
+(define (± x) (values x (- x)))
+(valued-map ± '(1 2))
+⇒ 1
+⇒ -1
+⇒ 2
+⇒ -2
+@end example
+@end defun
+
+
+@defun assoc-ref-all alist key
+@defunx assq-ref-all alist key
+@defunx assv-ref-all alist key
+Equivalent to assoc-ref (and family), but works on association lists with
+non-unique keys, returning all mathing records (instead of just the first).
+@lisp
+(assoc-ref-all '((a . 1) (b . 2) (a . 3)) 'a)
+⇒ (1 3)
+@end lisp
+@end defun
+
+
+@defun vector-last v
+Returns the last element of @var{v}.
+@end defun
+
+@defun ->string any
+Converts @var{any} to a string, as per @var{display}.
+@end defun
+
+
+@defmac let-env bindings body ...
+Similar to @var{let}, but sets environment variables for the code in
+body. Restores the old values once we leave.
+
+A variable can also be removed from the environment, by setting its
+value to @code{#f}.
+@end defmac
+
+@defmac with-locale1 category locale thunk
+Run @var{thunk} with the locale @var{category} temporarily set to
+@var{locale}.
+@end defmac
+
+@defmac catch* thunk (symbol proc) ...
+Macro allowing multiple exception types to be caught. Each (symbol
+proc) pair expands to a regular @code{catch}, with the leftmost being
+innermost.
+
+@var{Symbol} can also be on the form @code{(pre-unwind @var{symbol})},
+then @code{with-throw-handler} is used instead of @code{catch}.
+@end defmac
+
+@defun uniq lst
+@defunx univ lst
+@defunx unique lst
+@defunx uniqx comp lst
+Squash repeated equivalent elements in a list into single instances,
+similar to the POSIX command uniq(1). The three variants uses
+@code{eq?}, @code{eqv?}, and @code{equal?} respectively.
+
+@code{uniqx} also takes @var{comp}, which is sholud be a binary
+procedure returning if the elements are equal.
+@end defun
+
+@defmac begin1 forms ...
+Port of Common Lisp's @code{begin1} form. Like @code{begin} runs each
+form in its body in order, but returns the first result instead of the
+last.
+@end defmac
diff --git a/doc/ref/general/uuid.texi b/doc/ref/general/uuid.texi
new file mode 100644
index 00000000..78674763
--- /dev/null
+++ b/doc/ref/general/uuid.texi
@@ -0,0 +1,17 @@
+@node UUIDs
+@section UUID generation
+
+Provided by module @code{(hnh util uuid)}.
+
+@defun uuid-v4
+Generates a UUID-v4 string.
+@end defun
+
+@defun uuid
+Generates an implementation defined (but guaranteed valid) UUID.
+@end defun
+
+@deftp {parameter} seed
+Guile parameter containing the seed used when generating UUID's in
+this module. Only set this when you want non-random randomness.
+@end deftp
diff --git a/doc/ref/general/webdav.texi b/doc/ref/general/webdav.texi
new file mode 100644
index 00000000..a495c945
--- /dev/null
+++ b/doc/ref/general/webdav.texi
@@ -0,0 +1,301 @@
+@node WebDAV
+@section WebDAV
+
+For a complete view of WebDAV, please see @cite{RFC4918 (HTTP
+Extensions for Web Distributed Authoring and Versioning (WebDAV))},
+but in short, and specifc for this implementation.
+
+A DAV tree consists of resources, which are analogous to files and
+directories. A resource is referenced by its href.
+
+Each resources is either a collection and have children, or have
+content. Parts of this implementation allows a collection to also have
+contents, while other does not. The standard doesn't seem to mind
+either way.
+
+Each resource also has a set of properties, modelling metadata and
+extra data about the resource.
+
+@emph{href}'s are internally represented as lists of strings, where the
+root element ``/'' is an empty list, and all other cases are mapped
+like:
+@example
+"/a/b" ⇒ '("a" "b")
+@end example
+
+@emph{resources} are GOOPS objects, which the base class
+@code{<resource>}.
+
+The user (of the library) is assumed to designate one resource
+instance as the root of the resource tree. All other resources are
+then added as (grand-)children to that resource. Each resource has a
+field @var{name}, which is the normative name used when searching by
+name in the tree@footnote{This means that one resource can't easily
+exist at multiple points in the tree}.
+
+@emph{properties} are split into live and dead properties, where live
+properties have extra handling by the server, while dead properties
+are simply carried along after the end-user put them on a resource.
+
+Live properties are handled through GOOPS methods.
+
+Dead properties are (by default) stored directly inside each resource.
+
+@node WebDAV Properties
+@subsection Properties
+
+@itemize
+@item @code{(calp webdav property)}
+@item @code{(calp webdav propfind)}
+@end itemize
+
+@subsubsection Default Live Properties
+
+@deftp {GOOPS method} creationdate
+@end deftp
+
+@deftp {GOOPS method} displayname
+@end deftp
+
+@deftp {GOOPS method} getcontentlanguage
+@end deftp
+
+@deftp {GOOPS method} getcontentlength
+@end deftp
+
+@deftp {GOOPS method} getcontenttype
+@end deftp
+
+@deftp {GOOPS method} getetag
+@end deftp
+
+@deftp {GOOPS method} getlastmodified
+@end deftp
+
+@deftp {GOOPS method} lockdiscovery
+@end deftp
+
+@deftp {GOOPS method} resourcetype
+@end deftp
+
+@deftp {GOOPS method} supportedlock
+@end deftp
+
+
+@node WebDAV Resources
+@subsection Resources
+
+@deftp {GOOPS class} <resource>
+Base type for all WebDAV resources.
+
+The base class shouldn't be directly instanciated.
+
+ @defun resource? x
+ Is the given object a <resource>, or decendant?
+ @end defun
+@end deftp
+
+@deftp {GOOPS method} name resource
+The name of a resource is the local part of a href.
+@end deftp
+
+@deftp {GOOPS method} children resource
+All direct children of a resource, as a list.
+@end deftp
+
+@defun add-child! parent child [#:overwrite?] [#:collection?=(is-collection? child)]
+Adds a resource as a child of another resource.
+
+Before adding the resource to the parents child set,
+@code{(setup-new-resource! child parent)} is called. If
+@var{collection?} is true, then
+@code{(setup-new-collection! child parent)} is also called.
+
+If @var{overwrite?} is present, then the parent will be checked for a
+child which already has that name, and take action accordingly.
+It will return one of: @code{'replaced} if a resource already existed
+with that name, but it has been replaced, @code{'collision}, if the
+old one was kept, and @code{'created} if the new resource was added
+without collisions.
+
+If @var{overwrite?} is absent then the method always returns @var{'created}.
+@end defun
+
+@defun add-resource! resource name content
+Creates a new resource with the given name, and make it a child of
+@var{self}. Setting its initial content to @var{content}.
+
+Calls @code{add-resource!}, so the same book-keeping procedures are called.
+@c TODO Document throw
+@c TODO Document return
+@end defun
+
+@defun add-collection! resource name
+Similar to @code{add-resource!} but the created resource is instead a collection.
+@end defun
+
+@deftp {GOOPS method} setup-new-resource! (self <resource>) (parent <resource>)
+Book-keeping procedure called by @code{add-resource!} on @emph{all}
+added resources.
+
+Base implementation in a no-op.
+@end deftp
+
+@deftp {GOOPS method} setup-new-collection! (self <resource>) (parent <resource>)
+Book-keeping procedure called by @code{add-resource!} if
+@var{collection?} is true.
+
+Base implementation is a no-op.
+@end deftp
+
+@deftp {GOOPS method} is-collection? resource
+Is the given resource a collection.
+
+The base implementation simply checks if the resource has any children.
+@end deftp
+
+@deftp {GOOPS method} content resource
+@deftpx {GOOPS method} set-content! resource content
+Get and set the content of a given resource. @var{content}s type can
+be anything that the given resource type accepts. Overrides of this
+procedure should preferably save its contents properly.
+@end deftp
+
+@c
+
+@defun get-property resource xml-tag
+@defunx get-live-property resource xml-tag
+@defunx get-dead-property resource xml-tag
+@end defun
+
+
+@defun set-property resource xml-el
+@defunx set-property! resource xml-el
+@defunx set-dead-property resource xml-el
+@defunx set-dead-property! resource xml-el
+@defunx set-live-property resource xml-el
+@defunx set-live-property! resource xml-el
+@end defun
+
+
+@defun remove-property resource xml-tag
+@defunx remove-property! resource xml-tag
+@defunx remove-dead-property resource xml-tag
+@defunx remove-dead-property! resource xml-tag
+@defunx remove-live-property resource xml-tag
+@defunx remove-live-property! resource xml-tag
+@end defun
+
+@c
+
+@deftp {GOOPS method} copy-resource (resource <resource>) include-children? [name]
+Create a new resource which looks as similar as possible to the given
+resource. The new resource will have the same (GOOPS) class as the
+source, displayname, contentlanguage and all dead properties are
+transfered, other live properties are currently not explicitly
+transfered (but probably still transfered implicitly).
+
+The new resources name is @var{name} if given, and the name of the
+original resource otherwise.
+
+If @var{include-children?} is true then a deep copy is performed,
+otherwise no children are copied, and the resulting resource will be a
+leaf node.
+
+Content is copied verbatim.
+
+@b{NOTE} currently no helper method is called, which means that extra
+resources held by the resource object can't be copied.
+For example, FILE can't create a copy (but it also shouldn't do that
+here, but rathen when the element is ``mounted'' into the tree).
+@end deftp
+
+@c
+
+@defun lookup-resource root-resource path
+@end defun
+
+
+@defun all-resources-under resource [prefix='()]
+Returns the given resource, and all its children in a flat list.
+
+Currently depth first, but that might change.
+The root resource is however guaranteed to be first.
+@end defun
+
+@c
+
+@c TODO
+ make-live-property
+ live-property?
+ property-getter
+
+ property-setter-generator
+ property-remover-generator
+
+ prepare-update-properties
+
+ live-properties
+ dead-properties
+
+ webdav-properties
+
+
+@node WebDAV Resource Types
+@subsection Resource Types
+
+@subsubsection @code{(calp webdav resource base)}
+
+Implementation of @code{(calp webdav resource)}. Exists to possibly
+avoid dependency loops.
+
+@subsubsection @code{(calp webdav resource calendar)}
+@subsubsection @code{(calp webdav resource file)}
+
+Resources backed by the file system.
+
+@defun file-resource? x
+@end defun
+
+@deftp {GOOPS method} children <file-resource>
+@end deftp
+
+@deftp {GOOPS method} is-collection? <file-resource>
+@end deftp
+
+@deftp {GOOPS method} creationdate <file-resource>
+Retrived directly from the file through @command{stat -c %W $@{filename@}}.
+@end deftp
+
+@deftp {GOOPS method} content <file-resource>
+@deftpx {GOOPS method} set-content! <file-resource> data
+Directly interfaced with the file.
+
+Data can't be retrieved for collections, and will always be
+returned as a bytevector for non-collections.
+
+Data can be set either as a string or a bytevector. When a string is
+used Guile's current encoding will be used.
+@end deftp
+
+@subsubsection @code{(calp webdav resource virtual)}
+
+@node WebDAV Utilities
+@subsection Utilities
+@defun xml-element-hash-key xml-tag
+Given an xml tag object @ref{xml-tag}, return a suitable key for
+@code{hash-ref} and family.
+
+These key objects should preferably not be carried around for
+long. Prefer to keep the @emph{real} xml-tag object, and only call
+this while directly referencing the hash table.
+@end defun
+
+@defun href->string href
+HREF's are represented as lists of strings. The root resource (``/'')
+is the empty list.
+@end defun
+
+@defun string->href string
+Return a href list back into a string. A leading slash will always be added.
+@end defun
diff --git a/doc/ref/general/xdg-basedir.texi b/doc/ref/general/xdg-basedir.texi
new file mode 100644
index 00000000..2d3b2972
--- /dev/null
+++ b/doc/ref/general/xdg-basedir.texi
@@ -0,0 +1,62 @@
+@node XDG Base Directory
+@section XDG Base Directory
+
+Implementation of the XDG Base Directory Specification
+@url{https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html}, v0.8.
+
+It's recommended to include this module with a symbol prefix:
+
+@example
+(use-modules ((xdg basedir) :prefix xdg-)
+
+(xdg-data-dirs)
+⇒ ("/usr/local/share" "/usr/share")
+@end example
+
+The users home directory is fetched from the environment variable @env{HOME}.
+
+
+@defun data-home
+@findex XDG_DATA_HOME
+@env{XDG_DATA_HOME}, usually @file{~/.local/share}.
+@end defun
+
+@defun config-home
+@findex XDG_CONFIG_HOME
+@env{XDG_CONFIG_HOME}, usually @file{~/.config}.
+@end defun
+
+@defun state-home
+@findex XDG_STATE_HOME
+@env{XDG_STATE_HOME}, usually @file{~/.local/state}.
+@end defun
+
+@defun data-dirs
+@findex XDG_DATA_DIRS
+@env{XDG_DATA_DIRS}, split into a list.
+
+Defaults to @code{("/usr/local/share" "/usr/share")}.
+@end defun
+
+@defun config-dirs
+@findex XDG_CONFIG_DIRS
+@env{XDG_CONFIG_DIRS} as a list, usually @code{("/etc/xdg")}.
+
+Defaults to @file{/etc/xdg}.
+@end defun
+
+@defun cache-home
+@findex XDG_CACHE_HOME
+@env{XDG_CACHE_HOME}, usually @file{~/.cache}.
+@end defun
+
+@defun runtime-dir
+@findex XDG_RUNTIME_DIR
+If @env{XDG_RUNTIME_DIR} is set, than that is used. Otherwise a
+warning message is printed to stderr and @file{/tmp} is returned.
+
+The standard also stipulates a few things about permissons for this
+directory. These are currently not checked.
+
+Systemd usually sets this value to @file{/run/user/$(id -u)}.
+@end defun
diff --git a/doc/ref/general/zic.texi b/doc/ref/general/zic.texi
new file mode 100644
index 00000000..5af36fd3
--- /dev/null
+++ b/doc/ref/general/zic.texi
@@ -0,0 +1,135 @@
+@node Timespec
+@section Timespec
+
+Specifiers of times, including their offset from some origin, and what
+kind they are.
+
+Refer to zic(8) and the AT field of rules.
+
+@defun make-timespec time sign type
+
+@defun timespec? x
+@end defun
+
+@defun timspec-time timespec
+Should be a time object.
+@end defun
+
+@defun timspec-sign timespec
+@code{'+} or @code{'-}
+@end defun
+
+@defun timspec-type timespec
+char
+@end defun
+@end defun
+
+@defun timespec-zero
+The ``empty'' timespec.
+@end defun
+
+@defun timespec-add specs ...
+@end defun
+
+@defun parse-time-spec string [suffixes='(#\s #\w #\u #\g #\z)]
+More or less follows the pattern @code{-?[0-9]@{2@}(:[0-9]@{2@})@{0,2@}[swugz]}.
+@end defun
+
+
+@node Zone Info Compiler
+@section Zone Info Compiler
+
+@defun read-zoneinfo ports-or-filenames
+Takes a (possibly mixed) list of ports and filenames, and calls
+@code{parse-zic-file} on each of them.
+@end defun
+
+@c @defun parse-zic-file port
+@c @end defun
+
+@defun zoneinfo?
+@end defun
+
+@defun get-zone zoneinfo name
+Takes a zoneinfo object, and a name as a string (probably something
+like ``Europe/Stockholm''), and returns a list of zone-entries.
+@end defun
+
+@defun get-rule zoneinfo name
+Gets a list of rule objects, sorted in chronological order.
+@var{name} is a symbol.
+@end defun
+
+@defun rule->dtstart rule
+Returns the first time a given rule happens.
+@end defun
+
+@defun rule->rrule rule
+Converts a given zoneinfo rule into a recurrence rule, of all times
+that change occurs.
+@end defun
+
+@defun zone-format fmt-string arg
+A special case of format, which handles the format strings containing
+``%s'' and ``%z''.
+@end defun
+
+
+
+@defun make-rule name from to in on at save letters
+
+See zic(8).
+
+@defun rule?
+@end defun
+
+@defun rule-name
+@end defun
+
+@defun rule-from
+@end defun
+
+@defun rule-to
+@end defun
+
+@c @defun rule-type
+@c @end defun
+
+@defun rule-in
+@end defun
+
+@defun rule-on
+@end defun
+
+@defun rule-at
+@end defun
+
+@defun rule-save
+@end defun
+
+@defun rule-letters
+@end defun
+
+@end defun
+
+
+@defun make-zone-entry stdoff rule format until
+
+See zic(8).
+
+@defun zone-entry?
+@end defun
+
+@defun zone-entry-stdoff
+@end defun
+
+@defun zone-entry-rule
+@end defun
+
+@defun zone-entry-format
+@end defun
+
+@defun zone-entry-until
+@end defun
+@end defun
+