= S-expressions parser and generator library in C\++ (SEXP in C++)

image:https://github.com/rnpgp/sexp/workflows/build-and-test/badge.svg["Build status Ubuntu/macOS/Windows", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test"]
image:https://github.com/rnpgp/sexp/workflows/build-and-test-rh/badge.svg["Build status CentOS/Fedora", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test-rh"]
image:https://github.com/rnpgp/sexp/workflows/build-and-test-deb/badge.svg["Build status Debian", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test-deb"]
image:https://github.com/rnpgp/sexp/workflows/build-and-test-msys/badge.svg["Build status MSys", link="https://github.com/rnpgp/sexp/actions?workflow=build-and-test-msys"]


image:https://codecov.io/gh/rnpgp/sexp/branch/feat/g23/graph/badge.svg["Code coverage", link="https://codecov.io/gh/rnpgp/sexp"]
image:https://github.com/rnpgp/sexp/workflows/CodeQL/badge.svg["CodeQL analysis", link="https://github.com/rnpgp/sexp/actions?workflow=CodeQL"]
image:https://scan.coverity.com/projects/27150/badge.svg["Coverity Scan Build Status", link="https://scan.coverity.com/projects/rnpgp-sexp"]


== Purpose

This is a C++ library for working with S-expressions. This implementation
is derived from the reference SEXP C library developed by Professors Ronald Rivest
and Butler Lampson of MIT LCS (now CSAIL).

This library differs from the original C implementation in the following ways:

* It aims to be reuseable in C++ implementations and is importable via CMake.
* It includes a test suite for correctness testing and tests against malformed
  S-expressions.
* It supports, and is tested against, all major platforms, including:
** Ubuntu, Debian, Fedora, CentOS
** macOS
** Windows
** msys
* It implements additional interface to work with S-expressions wrapped by GnuPG 2.3+ extended format as defined at https://github.com/gpg/gnupg/blob/master/agent/keyformat.txt

The original C library is available at:

* http://people.csail.mit.edu/rivest/sexp.html


== Background

S-expressions are a data structure for representing complex data as a variation
on https://en.wikipedia.org/wiki/Lisp_(programming_language)[LISP] S-expressions.

S-expressions were originally adopted for use in
http://theory.lcs.mit.edu/~cis/sdsi.html[SDSI] and
http://world.std.com/~cme/html/spki.html[SPKI].

SDSI has been developed by Professors
https://people.csail.mit.edu/rivest/index.html[Ronald L. Rivest] and Butler
Lampson of http://www.lcs.mit.edu/[MIT's Laboratory for Computer Science],
members of
http://theory.lcs.mit.edu/~cis[LCS's Cryptography and Information Security]
research group.

NOTE: SDSI research has been supported by DARPA contract DABT63-96-C-0018,
"Security for Distributed Computer Systems".

NOTE: SPKI has been developed by
http://www.clark.net/pub/cme/home.html[Carl Ellison] and others in the IETF SPKI
working group.


== Usage guide for S-expressions

* https://people.csail.mit.edu/rivest/Sexp.txt[SEXP 1.0 guide]


== Code

The library is a deep rework to C++ of the original
https://people.csail.mit.edu/rivest/sexp.html[SEXP library] that maintains full
support of original specification.

While most applications will not need anything but the simple canonical and
transport formats; however, the code here is considerably more complex because
it also supports the advanced format, both for input and for output.


== Building and installation

[source,sh]
----
mkdir build
cd build
cmake ..
cmake --build .
ctest
cmake --install .
----


== CMake script options

`WITH_SEXP_TESTS:BOOL`::
build tests (default: `ON`)

`DOWNLOAD_GTEST`::
if tests are build download googletest from github (default: `ON`)
when this option is set to `OFF` googletest binary package is a prerequisite for SEXP tests

`WITH_SEXP_CLI:BOOL`::
build the `sexp` client application (default: `ON`)

`WITH_SANITIZERS:BOOL`::
build with address and other sanitizers (default: `OFF`)
(requires clang compiler)



== SEXP command-line utility

The `sexp` command-line utility is reference parser and generator of S-expressions.
It can read, parse and print out SEXP in all defined formats.

=== sexp switches:
[options="header"]
|=======================================================================================================
| Switch              | Description                                    | Default
3+| Input
| -i <filename>       | input file name                                | read input from console (stdin)
| -p                  | prompt input if reading from console           | disabled
| -s                  | treat input as a single SEXP string            | disabled, input is treated as S-expression
3+| Output
| -o <filename>       | output file name:                              | write output to console (stdout)
| -a                  | generate advanced transport format             | enabled if no format is specified
| -b                  | generate base-64 transport format              | disabled
| -c                  | generate canonical format                      | disabled
| -l                  | suppress linefeeds after output                | disabled
| -w <width>          | set output line width (0 implies no constraint)| 75
3+| Miscellaneous
| -x                  | execute repeatedly until EOF                   | process single S-expression then exit
| -h                  | print help message and exit                    |
|=======================================================================================================

Running without switches implies: -p -a -b -c -x

=== Usage examples:
Prompt for S-expressions input from console, parse and output it to `certificate.dat` in base64 transport format
[source]
----
sexp -o certificate.dat -p -b

> Input:
> (aa bb (cc dd))
>
> Writing base64 (of canonical) output to 'certificate.dat'
----

Parse all S-expressions from `certificate.dat`, output them to console in advanced transport format with no prompts
[source]
----
sexp -i certificate.dat -x

> (2:aa2:bb(2:cc2:dd))
----

Parse S-expressions from `certificate.dat`, output it to console in canonical, base64 and advanced format with prompts and no width limitation
[source]
----
sexp -i certificate.dat -a -b -c -p -w 0

> Reading input from certificate.dat
>
> Canonical output:
> (2:aa2:bb(2:cc2:dd))
> Base64 (of canonical) output:
> {KDI6YWEyOmJiKDI6Y2MyOmRkKSk=}
> Advanced transport output:
> (aa bb (cc dd))
----

Repeatedly prompt for S-expressions input from console, parse and output it console in advanced, base64 and canonical formats
[source]
----
sexp -p -a -b -c -x
----
or just
----
sexp

> Input:
> (abc def (ghi jkl))
>
> Canonical output:
> (3:abc3:def(3:ghi3:jkl))
> Base64 (of canonical) output:
> {KDM6YWJjMzpkZWYoMzpnaGkzOmprbCkp}
> Advanced transport output:
> (abc def (ghi jkl))
>
> Input:
> ^C
----

== License

The code is made available as open-source software under the MIT License.
