A Lisp implemented in AWK
* v0.6: I tried to use it and didn't get far

** Special forms added

symbolp consp stringp load < > = != >= <= cdar cddr apply
unsafe-system shellquote repr getenv setenv as-number dump-append load
repl

** Macros added

let* prog1 defun defintrinsic and or 

** Library functions added

intercalate string-join system save-lisp-and-die

** Known issues

None yet.

** ~save-lisp-and-die~

This function takes three parameters: (1) the filename of a glotawk
interpreter; (2) a filename to which to write a new interpreter; (3) a
symbol, whose value is a function to run at startup (usually, this is
~'repl~). The AWK code from glotawk is written into the new file, and
then a dump of the current heap. In this way, you can construct a
single-file interpreter containing not only glotawk's base library,
but also definitions of your own, which will be instantly available
without the overhead of parsing and without the need to distribute
more files. In addition, if you define your own main function and pass
its symbol in, the file written will run your function on startup,
instead of the REPL.

** Parsing across lines

The reader is retooled to support forms spanning multiple lines, which
lets the user write Lisp source in the commonly expected fashion.

** ~system~ rehabilitation

The special form ~system~ was previously a direct interface to AWK's
~system~ function, thence to ~system(3)~, which takes a command as a
single string and runs it in a subshell. If that string contains any
untrusted input, you have OS command injection.

The old ~system~ special form has been renamed to ~unsafe-system~, and
replaced with the library function ~system~. This takes any number of
strings, the first for the executable and one for each desired
argument. It uses ~shellquote~ to defang each string, concatenates
them using ~string-join~, and then runs ~unsafe-system~ with that. But
then you can't do redirections using ~system~, so as a workaround,
when there are any symbols among the arguments, their names are
inserted into the shell command without quoting. So you can
src_glotawk{ (system "echo" "hi" '> "/dev/null") } for example.

** Bugs fixed

*** Backslash escapes in strings

Inside strings, the usual backslash escapes act how you would expect
them to. That's ~\a \b \f \n \r \t \v \\ \"~ for the bell, backspace,
formfeed, newline, carriage return, horizontal tab, vertical tab,
backslash and double quotes, respectively. This means when the
characters ~\a~ are found in your string literal, they mean a single
character inside the resultant string: ASCII code 7; when that string
is printed using ~print~, which prints the readable representation of
a thing, it will come back out as the characters ~\a~; when that
string is printed using ~printf~, the ASCII code 7 will be sent to the
output.

*** ~strcat~, ~printf~, ~sprintf~ infinite loops

Evaluation environments were not being passed into these special
forms, causing infinite loops. This is fixed.

*** Strings now ~equal~ by contents

Due to a bug, ~equal~ was comparing strings using their identities
(e.g. is string a /stored at the same place as/ string b?), not their
contents (e.g. would awk consider them ~==~ ?). This is fixed.

*** ~quasiquote~ works

Tested and reimplemented. It may not be the most efficient, but it
doesn't crash anything.

*** Some infinite loops squashed

As well as bugfixes mentioned above to prevent infinite loops, in
several places where infinite loops can possibly happen, they are
checked for, and we print an error and exit instead.

*** match function

The ~match~ special form had a wrong variable name that kept it from
ever working right; this is fixed. In cases where there was no match,
previously this special form would return ~(0 -1)~, hewing closely to
AWK. It has been modified to return ~nil~ if there is no match, so you
can more easily use its results in conditional checks.

** Other changes

*** Library moved to lib.glotawk

~lib-eval.awk~ contained the upper-level parts of glotawk, written in
glotawk. With the ability to parse across lines, and the addition of
the ~load~ function, the library is now moved to ~lib.glotawk~ and
is loaded in by ~lib-eval.awk~.

*** Busybox awk compatibility attempted; failed

Busybox's awk was barfing on the regular expressions used in the
tokenizer. That's fixed, but you can't take the length() of an array
in Busybox awk. POSIX does not specify this behavior, so Busybox is
not in the wrong here; but glotawk takes the length of many arrays.
Perhaps the next version of POSIX will require awk to support the use
of length() on arrays.

*** GC_DEBUG

If you run glotawk like ~awk -v GC_DEBUG=1 -f glotawk~, then upon
every garbage collection, the heap before and after are written to
Graphviz ~dot~ files, as well as the GC marks. You may wish to avoid
using the ~dot~ algorithm to visualize these: with thousands of nodes,
~dot~ thinks for a long time, and makes an inscrutable drawing. ~fdp~
and ~sfdp~ can render an inscrutable drawing much faster.

*** awk flexibility

Three awks are specified in the Makefile now: the one used to build
glotawk (~BUILD_AWK~), the one used to run the tests (~TEST_AWK~), and
the one expected to exist when glotawk is run (~TARGET_AWK_F~). These
all default to the value of ~AWK~, which in turn defaults to
~/usr/bin/awk~.

* v0.5: First public release

** Special forms added (this is all of them)

quote atom eq car cdr cons cond label lambda not null equal
caar cadr memq member assoc setq
caaar caadr cadar caddr cdaar cdadr cddar cdddr
rplaca rplacd nreverse nconc append list-length print progn
macro expand1 eval
only2+ only2* only2- only2/ only2// only2% only2**
atan2 cos sin exp log sqrt rand srand int
system tolower toupper substr index match split sub gsub
printf sprintf string-length strcat getline
with-ors with-rs with-fs with-output-to with-input-from
fflush close
gc-dot gc dump dump-dot

** Macros added (this is all of them)
let quasiquote

** Library functions added (this is all of them)
mapcar foldl reduce mappend + * - / // % **

** Known issues

~system~ probably doesn't even work. This is good because, without
appropriate quoting, it has Common Weakness CWE-78, OS command
injection.

~quasiquote~ doesn't work and may crash awk due to infinite recursion.