Munger(1) FreeBSD General Commands Manual Munger(1)
NAME
munger – Text Processing Lisp
SYNOPSIS
munger [⟨script⟩ [⟨args⟩ ...]]
DESCRIPTION
Munger is a lexically scoped lisp interpreter specialized for writing
processors for 8-bit text.
This manual contains an overview of the language followed by a complete
reference.
A variety of example programs are included in the source distribution.
The following are installed in (libdir).
Included Example Programs
cat.munger is a version of the cat utility, the simplest possible
filter.
grep.munger is an egrep-like filter.
options.munger is a module that simplifies the processing of command-
line arguments.
fmt.munger is a version of the fmt utility.
cal.munger prints a calender of the current month to stdout.
filter.munger is a simple filter that expands documents with embedded
munger code in them.
transform.munger performs a set of regular expression based
substitutions destructively over a set of files.
view.munger is a file viewer resembling vi when invoked as view.
mush.munger is a job control shell.
xml2alist.munger is a minimal XML parser that converts a standalone XML
1.0 document into an alist.
xml2buffer.munger
is another XML parser that inserts the alist into the
current buffer.
xmlquery.munger is a module that can be used to extract data from XML
alists.
xml2sqlite.munger
is another XML parser that serializes the XML document
into an SQLite database file.
xmlsqlite.munger is a module providing helper functions to access a
SQLite database containing serialized XML.
rss.munger prints to stdout an RSS feed that has been converted
into a SQLite database.
echo.munger is a TCP echo server.
httpd.munger is a basic HTTP/1.1 server. Note that this server is
inefficient and cannot support significant load.
MINIMUNGER
A subdirectory in the source distribution contains the source for
MiniMunger. MiniMunger is an unoptimized compiler-to-C for a small
functional (in the mathematical sense) variant of Munger. MiniMunger is
specialized for, and limited to, writing filters.
TMSL
A subdirectory in the source distribution contains munger code for
working with TSML documents. TSML is a simple replacement for XML and
SML. The markup language is described in a manual page.
IMPLEMENTATION NOTES
• Munger is an unoptimized lisp and performs best when interpreting
programs written in an imperative style. Any general-purpose
Lisp/Scheme implementation out there will out-perform Munger.
• Munger's strings are 8-bit clean, but some of the intrinsic functions
cannot handle embedded zeroes. This should not be a problem because
it is unlikely you will want to apply these functions to binary
strings. A full list of 8-bit safe intrinsics is specified in the
section below titled STRINGS.
• There is only one namespace.
• The function position of applications is fully-evaluated and must
evaluate to an intrinsic function or a closure. The order of
evaluation of the terms of an application is fixed from left to right
and can be relied upon in computations.
• Munger does not recognize tail-calls, but you can explicitly request
tail-calls with the "tailcall" intrinsic. This mechanism allows even
anonymous functions to be tail-recursive and can be used to turn non-
tail positions into tail positions.
• Munger provides a "dynamic_let" to impose dynamic scope on a single
global at a time.
• All values are considered to be boolean "true" values except for the
empty list, the empty string, and zero. There are no T, NIL, #t or
#f objects.
• All functions return a value.
• Improper lists cannot be formed in Munger. The final "cdr" of all
lists is the empty list.
• The empty list is a list not an atom. The empty list a constant that
evaluates to itself. Every empty list is identical to every other
empty list, which is to say they are "eq" to each other.
• "eq" in Munger behaves similarly to "eql" in Common Lisp. There is
an "equal" that does what you think it does.
• "eval" does not contain the lisp reader. Applying "eval" to a string
will not parse lisp in the string. The original string is returned
because strings are constants. There is an "eval_string" intrinsic.
• Munger's string-manipulation functions return new strings.
• There are no destructive list operations. Munger's "list" and
"append" intrinsics make copies of their arguments.
• Munger's looping constructs are modelled on those of C. The most
efficient way to iterate is to use the "for", "iterate", or "loop"
intrinsics.
• The set of intrinsics is purposefully-limited to a minimal set useful
for text processing.
• Symbol syntax is similar to symbol syntax in C. Symbols are case-
sensitive. For example, "let*" in other dialects is "letn" in Munger.
Hyphens are not valid in symbol names. You have to use underscores.
• Macros and gensyms are provided. A macro definition differs from a
function definition in that the initial "lambda" symbol is replaced
with the "macro" symbol.
• Besides lists, 3 other aggregate types are provided: one-dimensional
arrays called, "records", one-dimensional dynamically resized arrays
called, "stacks", and associative arrays called, "tables".
• There are no interactive features beyond those provided by the
terminal driver (CTRL-H, CTRL-W, CTRL-U).
STARTUP
The interpreter reads three files at startup. First, the system library
(library.munger) is read from the munger data directory (libdir).
Second, the user's custom custom lisp library (.munger) is read from the
user's home directory. Third, the file specified by the first command-
line argument is read.
Command line arguments can be accessed from lisp programs with the
"current", "rewind", "next", and "prev" intrinsics.
COMMENTS
If the parser encounters a semicolon (;) or an octothorpe (#), outside of
a string token, the rest of the line from that character to the next
newline or carriage return is considered to be a comment and discarded.
Recognizing the octothorpe as well as the traditional semicolon enbles
users to put a "shebang" line at the top of scripts.
#!/usr/local/bin/munger
SYMBOLS
Symbols are case-sensitive and consist of sequences of alphanumeric
characters and the underscore. Symbols cannot start with numerical
characters.
NUMBERS
The interpreter supports only the fixnum. The size of the fixnum is the
word size of the machine the interpreter is running on. Arithmetical
operations that overflow this size are not detected. (maxidx) returns
the value of the largest fixnum the interpreter can represent. There is
an "unsigned" intrinsic that can be used to display the result of
unsigned arithmetic operations that wrap-around to the negative side.
> (setq max (maxidx))
1073741823
> (+ max 1)
-1073741824
When an integer value is read by the lisp reader the integer is
represented internally as a fixnum. If the integer is too large or too
small to be represented in that form, the value is silently truncated to
fit.
STRINGS
Arbitrary strings of character data can be placed between " marks (ASCII
34). Strings are constants and evaluate to themselves. " marks can be
embedded into strings if the " marks are escaped with a backslash:
> "asd\""
"asd""
A backslash occurring at the end of a string is interpreted as escaping
the closing " character. Backslashes are escaped with themselves.
> "asd\\"
"asd\"
A backslash is interpreted as an escape only when the backslash occurs
before another backslash or a " character. Other backslashes are
inserted into the string. The following two strings are therefore
identical.
> "\a"
"\a"
> "\\a"
"\a"
It is only necessary to employ these escapes in strings to be parsed by
the lisp reader. Escape characters can be inserted into strings
programmatically.
> (char 34)
"""
> (char 92)
"\"
Munger's strings are 8-bit clean, but not all of the intrinsics that use
strings tolerate embedded zeroes. The following intrinsics are 8-bit
clean.
getline, getchar, getchars, print, cgi_read, cgi_print, code, substring,
stringify, concat, join, chop, chomp, insert, retrieve, slice, strcmp,
child_read, child_write, getline_ub
The "split" intrinsic works correctly when its first argument is the
empty string and its second argument contains NULs.
STACKS, TABLES, AND RECORDS
Munger supports an associative array type called a table. Associative
arrays are collections of lisp atoms paired with arbitrary lisp objects.
The atom is used to retrieve the other object value from the table.
Tables are implemented internally as hash tables.
Munger supports a dynamically-resizable unidimensional array type called
a stack. Stacks can be treated as push-down stacks or indexed as arrays.
Any lisp object can be stored in a stack. Multi-dimensional arrays can
be simulated using stacks of stacks.
In addition to stacks and tables, an aggregate type called a record is
provided. Records are fixed-size unidimensional arrays. They are more
time-and-space-efficient means of representing fixed-size structures than
lists, tables, or stacks.
Tables, stacks, and records are opaque constant atoms that evaluate to
themselves.
FILES
File I/O can be performed in two ways. The content of files can be read
into text buffers, manipulated, then written out again, or the standard
descriptors can be redirected onto files. Three convenience macros
simplify the process: "with_input_file", "with_output_file", and
"with_error_file".
> (with_input_file "README"
>> (for (a 1 4) (print a (char 9) (getline))))
1 Munger
2 ======
3
4 Munger is a lexically scoped, naive lisp interpreter specialized for
All redirections are undone on return to toplevel. Redirections made
with "redirect" are explicitly undone with the "resume" intrinsic.
Redirections made with the "with_input_file", "with_output_file", and
"with_error_file" macros are undone automatically when those macros
return. Redirections made with these macros are dynamically-scoped.
Nested redirections shadow enclosing redirections.
> (with_input_file "README"
>> (print (getline))
Munger
>> (with_input_file "lisp.h"
>>> (print (getline)))
/*
>> (print (getline)))
======
The "temporary" intrinsic redirects stdout onto a temporary file opened
for writing with mkstemp(2). The intrinsic returns the name of the file.
A convenience macro is provided, "with_temporary_output_file".
> (setq filename (with_temporary_output_file (print "foobar")))
"/tmp/munger2nvIa8D98M"
> (with_input_file filename
>> (print (getline)))
"foobar"
> (unlink filename)
1
Two macros simplify the writing of filters: "foreach_line" and
"foreach_line_callback". Both accept a function to be applied
successively to each line of input. The second macro also accepts an
additional function to be called when the input source changes. Both
macros read data from files specified on the command line or stdin. Here
is "cat" in munger.
(next)
(foreach_line print)
(exit 0)
COMMUNICATING WITH CHILD PROCESSES
The interpreter's standard descriptors can be redirected onto processes
with the "pipe" intrinsic. Successive invocations of "pipe" inherit any
already-made redirections. The "with_input_process" and
"with_output_process" macros simplify the creation of pipes.
> (with_input_process "jot 100"
>> (with_input_process "fmt"
>>> (while (setq l (getline))
>>>> (print l))))
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
92 93 94 95 96 97 98 99 100
On return to toplevel, all redirections are undone. Redirections are
explicitly undone with the "resume" intrinsic. The first argument is
passed to the shell (always /bin/sh). We could let the shell create the
pipeline for us.
> (with_input_process "jot 100 | fmt" ...
The curl(1) utility can be used to redirect standard input onto a remote
file via ftp or http:
> (with_input_process "curl -s 'ftp://www.freebsd.org/pub/FreeBSD/README.TXT'"
>> (for (n 1 10) (print n (char 9) (getline))))
1 Welcome to the FreeBSD archive!
2 -------------------------------
3
4 Here you will find the official releases of FreeBSD, along with
5 the ports and packages collection and other FreeBSD-related
6 material. For those who have World Wide Web access, we encourage
7 you to visit the FreeBSD home page at:
8
9 http://www.FreeBSD.org/
10
The munger code below is the equivalent of the shell command.
# cmd < infile 2> errfile | cmd2 > outfile
(redirect 0 "infile")
(redirect 2 "errfile")
(pipe 0 "cmd")
(redirect 1 "outfile")
(resume 2)
(exec "cmd2")
The "getstring" library function forks a program and accumulates all its
output into a string.
> (getstring "curl -s 'http://www.mammothcheese.ca/robots.txt'")
"User-Agent: *
Disallow: /cgi-bin/"
A full duplex socket is connected to a child process or a network server
with "child_open".
> (child_open "www.mammothcheese.ca" 80)
1
> (child_write "GET /robots.txt HTTP/1.0" (char 13) (char 10) (char 13) (char 10))
1
> (while (stringp (setq line (child_read)))
>> (print line))
HTTP/1.0 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 24
Last-Modified: Tue, 12 Jun 2007 16:10:51 GMT
Server: Drood/1.14 (FreeBSD/6.1/i386)
Date: Sun, 02 Sep 2007 01:27:20 GMT
User-agent: *
Disallow:
Only one full-duplex connection can be active at any time, but the
connection exists independently of whatever source the standard
descriptors are connected to. With a port argument of 0, "child_open"
attempts to connect to another process listening on a UNIX domain socket.
Without a port number, "child_open" forks a local program.
> (child_open "munger")
1
> (child_write "(setq foobar 43)")
1
> (chomp (child_read))
"43"
> (child_close)
1
TEXT BUFFERS
Munger provides line-oriented buffers for storing large amounts of text.
Only one buffer out of those currently open can be active at any time.
Each call to "open" creates a new buffer and makes the new buffer the
current buffer. The buffer number of an open buffer is passed as the
argument to the "switch" intrinsic to make that buffer the current
buffer.
A number of intrinsics are provided that act upon the current buffer.
Lines can be retrieved whole or in slices with tabs expanded. A range of
buffer lines is filtered through an external program with the "filter"
intrinsic. The "find" intrinsic is used to find non-overlapping matches
of regular expressions. A range of lines can be copied from one buffer
to another with the "transfer" intrinsic. There are intrinsics to set
and find bookmarks in buffers.
; Loading a buffer from a file:
> (open)
0
> (read 0 "README")
38 ; Number of lines read.
> (for (a 1 5) (print (retrieve a)))
Munger
======
Munger is a simple, statically-scoped, interpreted lisp that has
line-editor-like access to multiple text buffers, for use on the FreeBSD
; Loading a buffer from a process:
> (empty)
1
> (input 0 "ls")
20
> (for (a 1 (lastline)) (print (retrieve a)))
LICENSE
Makefile
README
cat.munger
client.munger
err.munger
cgi.munger
fmt.munger
grep.munger
intrinsics.c
library.munger
lisp.c
lisp.h
options.munger
munger.man
transform.munger
; Filtering buffer content through a process:
> (filter 1 (lastline) "fmt")
3 ; Number of lines received back from filter.
> (for (a 1 (lastline)) (print (retrieve a)))
LICENSE Makefile README cat.munger client.munger err.munger cgi.munger
fmt.munger grep.munger intrinsics.c library.munger lisp.c lisp.h options.munger
munger.man transform.munger
; Loading a buffer from a remote file using curl(1):
> (empty)
1
> (input 0 "curl -s 'http://www.mammothcheese.ca/index.html'")
296 ; Number of lines read.
; Finding the location of a match on a regular expression:
> (setq rx (regcomp "
]*>"))
> (find 1 1 0 rx 0)
(27 3 6)
> (slice 27 3 6 1 0)
""
; Filtering a buffer through an HTTP server:
> (empty)
1
> (insert 1 (concat "GET /Slashdot/slashdot HTTP/1.0" (char 13) (char 10)) 0)
1
> (insert 2 (concat (char 13) (char 10)) 0)
1
> (filter_server 1 2 "rss.slashdot.org" 80)
272
; Get rid of the HTTP header and condense a possibly chunked response body:
> (remove_http_stuff)
0
; Filter the XML document left in the buffer through the xml2alist example
; program:
> (filter 1 (lastline) (join "/" (libdir) "xml2alist.munger"))
264
; The buffer now contains a lisp representation of the XML we can use
; the xmlquery.munger example module with:
> (load (join "/" (libdir) "xmlquery.munger"))
; Evaluate the buffer content as lisp:
> (eval_buffer)
[ Converted document scrolls by dramatically! ]
; Make a query. Let's see the cdata content of the title elements of the
; RSS feed:
> (dynamic_let (document (get_elements "item" "document" 1 "rdf:RDF" 1))
>> (while document
>>> (println (get_cdata "item" 1 "title" 1))
>>> (setq document (cdr document))))
Unrefined "Musician" Gains a Global Audience
Open Source Laser Business Opens In New York
OpenOffice.org 2.1 Released With New Templates
Texas Lawmaker Wants To Let the Blind Hunt
Designer Glasses With Microdisplay Unveiled
Arctic Ice May Melt By 2040
DIY Service Pack For Windows 2000/XP/2003
Sea Snail Toxin Offers Promise For Pain
A Press Junket To Redmond
The Dutch Kill Analog TV Nationwide
Google Web Toolkit Now 100% Open Source
Novell and Microsoft Claim Customer Support
Wikipedia Founder to Give Away Web Hosting
How Craigslist is Keeping up Internet Ideals
Norman & Spolsky - Simplicity is Out
REGULAR EXPRESSIONS
Munger provides intrinsic functions for working with extended regular
expressions. Regular expressions are compiled with the "regcomp"
intrinsic. The "match" intrinsic returns a list of two character indices
describing a match. The "matches" intrinsic returns a list of
subexpression matches. The "substitute" performs regular-expression-
based substitutions. The "replace" library function enables dynamically
generated replacement text. The "find" intrinsic finds the location of
matches in the current buffer.
> (set 'rx (regcomp "munger"))
> (set 's "/usr/local/share/munger/library.munger")
> (match rx s)
(17 23)
; Text before match:
> (substring s 0 17)
"/usr/local/share/"
; Text of match:
> (substring s 17 (- 23 17))
"munger"
; Text after match:
> (substring s 23 0)
"/library.munger"
> (set 'rx (regcomp "^/?([^/]+/)*([^/]+)"))
; Full match and matched subexpressions:
> (matches rx s)
("/usr/local/share/munger/library.munger" "munger/" "library.munger"
"" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "")
; Ex-like substitution:
> (substitute rx "\U\2" "/usr/local/bin/munger" 1)
"MUNGER"
; Dynamically-generated replacement strings for each match:
(let ((r0 (regcomp "%([0-9A-Fa-f][0-9A-Fa-f])"))
(r1 (regcomp "\+")))
(defun decode (str)
(replace r0
(char (hex2dec m1))
(substitute r1 " " str 0))))
> (decode "foobar+tooley%7Efunbag%24%25%26")
"foobar tooley~funbag$%&"
FUNCTIONS
The arguments of functions and macros are evaluated from left to right
with the function position being evaluated in the same environment as the
succeeding positions. The function position must be occupied by an
expression that evaluates to a an intrinsic or a closure.
> (let ((a 10))
>> (defun booger () a))
> (booger)
10
Functions can accept variable-length argument lists. To specify that a
function accepts a varying number of arguments, pass a final parameter to
enclosed in parentheses.
(lambda ((a)) (print a))
The previous code defines a function that accepts zero or more arguments.
Upon invocation, all arguments passed to the function are collected into
a list and bound to "a" inside the function body. If no arguments are
passed to the function, "a" is bound to the empty list.
The following function accepts 2 or more mandatory arguments followed by
optional arguments.
(lambda (a b (c)) (print a b c))
The "labels" intrinsic creates locally visible function bindings. Each
function in the function list is visible to the other functions.
>(labels ((even (lambda (n) (or (eq n 0) (tailcall odd (- n 1)))))
>>> (odd (lambda (n) (and (not (eq n 0)) (tailcall even (- n 1))))))
>> (print (even 11))
>> (newline)
>> (print (even 12))
>> (newline))
0
1
1 ; this is the return value of the last (newline).
There are "let", "letn", and "letf" macros to facilitate the creation of
new lexical bindings. "letn" corresponds to let* in other lisp dialects.
"letf" corresponds to a named let in Scheme or flet in lisp.
Inside a lexical environment, new bindings can be dynamically created
with the "extend" intrinsic. These bindings have unlimited extent just
as all lexical bindings do.
> (defun (a)
>> (extend 'b (* a a))
>> (lambda () b))
You can limit the extent of a new binding with "dynamic_extent".
> (lambda (a)
>> (extend 'f (lambda () b))
>> (dynamic_extent
>>> (extend 'b (* a a))
>>> (print (f))) ; Works here inside "dynamic_extent"
; even though f was closed before "extend" was invoked.
; b suddenly "pops-up" into the lexical environment.
>> (f)) ; ERROR: b is no longer extant here.
Tail recursion is not recognized by the interpreter. The "tailcall"
intrinsic turns its continuation into tail position. This mechanism
allows even anonymous functions to perform tail recursion.
> (let ((n 10)
>>> (a 1))
>> (if (< n 2)
>>> a
>>> (tailcall 0 (- n 1) (* a n))))
3628800
MACROS
Macros to define syntactic transformations. A macro is a function that
receives its arguments unevaluated and has its return expression
evaluated.
(set 'quit (macro () '(exit 0)))
(set 'with_input_file
(macro (file (code))
(qquote
(when (> (redirect 0 ,file) 0)
(protect ,(cons 'progn code)
(resume 0))))))
The "test" intrinsic displays a macro expansion.
> (test (with_input_file "library.munger" (getline)))
(when (> (redirect 0 "library.munger") 0)
(protect (progn (getline))
(resume 0)))
The "defmac" macro make macro definitions simpler.
(defmac with_input_file (file (code))
(qquote
(when (> (redirect 0 ,file) 0)
(protect ,(cons 'progn code)
(resume 0)))))
PROGRAMMING STYLE
Programs written in an imperative style will always out-perform programs
written in a functional style because munger is an unoptimized
interpreter.
(defun fact (n)
(extend 'a 1)
(iterate n (setq a (* a n)) (dec n))
a)
RETURN VALUES
Munger exits with 1 on error and 0 on success.
AUTHORS
James Bailie ⟨jimmy@mammothcheese.ca⟩
http://www.mammothcheese.ca
LANGUAGE REFERENCE
library functions or macros defined in library.munger. To find the entry
for a particular item, search this document for the name of the item
followed by a colon.
List Operations:
cons, car, cdr, list, length,
caar, cdar, cadr, cddr, cdddr,
cddddr, caddr, cadddr, caddddr, append,
alist_lookup, alist_remove, alist_replace, reverse, sort,
sortlist, sortcar, mapcar, foreach, remove,
nthcdr, nth, member, map
Predicates and Conditionals:
eq, atomp, if, when, unless,
and, or, not, nullp, boundp,
pairp, equal <, <=, >,
>=, stringp, fixnump, symbolp, regexpp,
tablep, stackp, intrinsicp, closurep,
macrop, recordp,
Assignment:
set, setq, inc, dec, defun
defmac
Evaluation and Control Flow:
progn, throw, while, until, do,
catch, continue, main, eval, quote,
load, gensym, version, test, let,
letn, labels, cond, apply, exit,
quit, interact, fatal, nofatal, extract,
qquote protect, letf, tailcall, prog1
printer, noprinter die, dynamic_let,
extend, gc, for, iterate loop,
dynamic_extent gc_freq, case, eval_string
blind_eval_string, eval_buffer
Fixnum Arithmetic:
+, -, *, /, %,
abs, random, negate, unsigned
Type Conversions:
stringify, digitize, intern, char, code,
hex2dec, dec2hex
Buffer Operations:
open, close, insert, delete, retrieve,
lastline, filter, write, read, empty,
slice, find, input, output, words,
maxidx, buffer, buffers, switch, transfer,
setmark, getmark, with_buffer, filter_server
remove_http_stuff
Regular Expressions:
regcomp, match, matches, substitute, replace,
String Operations:
split, join, expand, substring, concat
chop, chomp, upcase, downcase, length,
reverse, strcmp, split_rx, tokenize, rootname,
suffix, explode base64_encode, base64_decode
form_encode form_decode
Filesystem Operations:
chdir, libdir, directory, unlink, rmdir,
pwd, exists, stat, rename, seek
mkdir, complete, access, truncate,
redirect, resume, chown, chmod, basename,
readlock, writelock, unlock dirname, symlink
Command-Line Arguments:
current, next, prev, rewind
Line-Oriented I/O:
print, println, warn,
with_input_file, with_output_file, with_output_file_appending,
with_input_process, with_output_process, with_error_file,
with_error_file_appending, with_temporary_output_file
foreach_line, foreach_line_callback, pipe
newline, redirect, resume,
stderr2stdout, getline, rescan_path,
stdout2stderr, flush_stdout getline_ub
reset_history, save_history, load_history
Network daemon-related:
listen, listen_unix, stop_listening, accept, daemonize,
syslog, getpeername, receive_descriptors, send_descriptors,
busymap, nobusymap, busy, notbusy,
get_scgi_header busyp,
System Access:
system, getenv, setenv, block, unblock,
suspend, lines, cols, date, time,
beep, checkpass, crypt, setuid, getuid, setgid
geteuid, seteuid, getgid, hostname, gecos,
timediff, timethen, date2days, days2date, date2time,
localtime, utctime, week, weekday, month, getpid,
getppid, setpgid, getpgrp, tcsetpgrp, tcgetpgrp
kill, killpg, fork, glob, wait,
zombies, nozombies, zombiesp, exec, shexec,
forkpipe, command_lookup, unsetenv getstring
datethen, chroot, isatty, sle
Tables:
table, hash, unhash, lookup, keys,
values
Stacks:
stack, push, pop, index, store,
used, topidx, assign, flatten, shift,
clear,
unshift
Records:
record, getfield, setfield,
Communication with a child process:
child_open, child_write, child_read,
child_close, child_running, child_ready,
child_wait, child_eof
SQLite Interface:
sqlite_open, sqlite_close, sqlite_exec, sqlite_prepare, sqlite_step,
sqlite_finalize, sqlite_reset, sqlite_row, sqlite_bind, sqlp,
sqlitep
Character-Oriented I/O
display, clearscreen, pause, clearline,
getchar, goto, scrolldn, scrollup, hide,
show, pushback, insertln, getchars
fg_black, fg_red, fg_green,
fg_yellow, fg_blue, fg_magenta,
fg_cyan, fg_white, bg_black,
bg_red, bg_green, bg_yellow,
bg_blue, bg_magenta, bg_cyan,
bg_white, boldface, normal,
cons: (cons expr1 expr2)
Intrinsic "cons" adds an element to the beginning of a list. Expr2 must
evaluate to a list.
> (cons 'a (b c)
(a b c)
car: (car expr1)
Intrinsic "car" returns the first element of a list. An error is
generated if expr1 does not evaluate to a list.
> (car '(a b c))
a
cdr: (cdr expr1)
Intrinsic "cdr" returns the subset of a list exluding the first object in
the list. An error is generated if expr1 does not evaluate to a list.
> (cdr '(a b c))
(b c)
boundp: (boundp expr1)
The "boundp" intrinsic accepts 1 argument that must evaluate to a symbol.
The function returns 1 if the symbol is bound. Otherwise, "boundp"
returns 0.
caar, cadr, cdar, caddr, cadddr, caddddr, cddr, cdddr, cddddr: (form expr)
These library functions are built out of nested groupings of those
intrinsics.
> (caar '((a) b c)) ; is equivalent to: (car (car '((a) b c)))
a
> (cadr '(a b c)) ; is equivalent to: (car (cdr '(a b c)))
b
> (cdar '((a) b c)) ; is equivalent to: (cdr (car '((a) b c)))
()
> (cddr '(a b c)) ; is equivalent to: (cdr (cdr '(a b c)))
(c)
eq: (eq expr1 expr2)
Intrinsic "eq" returns 1 if expr1 and expr2 evaluate to the same atom.
Intrinsic "eq" returns 1 if expr1 and expr2 evaluate to different atoms
representing the same fixnum. Intrinsic "eq" returns 1 if expr1 and
expr2 evaluate to the exact same list. Otherwise, "eq" returns 0.
> (eq 'a 'a)
1
> (eq '(a b c) '(a b c))
0
> (set 'l '(a b c))
(a b c)
> (eq l l)
1
> (eq 0001 1)
1
equal: (equal expr1 expr2)
Library function "equal" returns 1 in all the situations where "eq"
returns 1. Additionally, "eq" returns 1 if both of its arguments
evaluate to lists having the same structure and content.
> (equal '(a b c) '(a b c))
1
> (set 'l '(a b c))
(a b c)
> (equal l l)
1
> (equal '(00 01 02) '(0 1 2))
1
atomp: (atomp expr)
Intrinsic "atomp" returns 1 if its argument evaluates to an atom.
Otherwise, "atomp" returns 0.
> (atomp 'a)
1
> (atomp '(a b c))
0
set: (set expr1 expr2)
Intrinsic "set" accepts 2 arguments. The result of evaluating the second
argument is bound to the result of evaluating the first argument. The
first argument must evaluate to a symbol. If a local variable with the
syntax of the symbol exists, the variable's binding is modified.
Otherwise, "set" creates or modifies a toplevel binding.
> (set 's '(a b c))
(a b c)
> s
(a b c)
> (set (car '(a b c)) ((lambda (x) (* x x)) 4))
16
> a
16
setq: (setq symbol expr)
The "setq" intrinsic works similarly to the "set" intrinsic except that
the first argument to the function is not evaluated and must be a symbol.
(setq a b)
is equivalent to:
(set 'a b)
eval_buffer: (eval_buffer)
The "eval_buffer" intrinsic evaluates lisp in the current buffer. The
function accepts no arguments. The buffer is evaluated in the current
lexical context. Code in the current buffer cannot invoke "eval_buffer"
while "eval_buffer" is running. The function returns the result of
evaluating the last expression in the buffer. If the buffer is empty, or
a recursive invocation of "eval_buffer" is detected, 0 is returned. Any
errors encountered during evaluation stop evaluation.
The code in the current buffer can open new buffers. The "eval_buffer"
function continues to parse the code in the buffer that was current when
it was invoked.
eval_string: (eval_string expr)
blind_eval_string: (blind_eval_string expr)
The "eval_string" and "blind_eval_string" intrinsics accept 1 argument
that must evaluate to a string. Both functions evaluate the string as
lisp. Error stop evaluation of the string, but the interpreter continues
to interprete the rest of your program. Both functions return the result
of evaluating the last expression successfully evaluated. If no
expressions are successfully evaluated, the original string is returned.
With "eval_string", the code parsed from the string is evaluated in the
current lexical context. With "blind_eval_string", only the global
environment is visible.
eval: (eval expr)
Intrinsic "eval" returns the result of evaluating its argument twice.
Note that "eval" does not contain the lisp reader. Calling "eval" with a
string argument causes the original string to be returned because strings
are constants.
> (set 'a (quote (set 'b 'booger)))
(set (quote b) (quote (booger)))
> b
evaluate: b has no value.
> (eval a)
booger
> b
booger
quote: (quote expr) or 'expr
Intrinsic "quote" returns its argument unevaluated. "quote" can be
replaced with a single apostrophe.
> (quote (a b c))
(a b c)
> '(a b c)
a
protect: (protect expr expr ...)
The "protect" intrinsic accepts 1 or more arguments and evaluates them in
sequence. "protect" returns the value of evaluating the first argument.
The arguments subsequent to the first are evaluated even if the
evaluation of the first is interrupted by an error.
> (catch
>> (protect (throw 0)
>>> (print 'booger)
>>> (newline)))
booger
0
>
qquote: (qquote expr)
The "qquote" macro accepts a list and returns it unchanged except where
sub-expressions have been "escaped" with comma characters. Those escaped
sub-expressions are evaluated and the result of the evaluation inserted
into the template expression.
The commas escaping sub-expressions are separate tokens in Munger unlike
in other lisps. For example ,token is parsed by Munger as two tokens,
"," and "token". This means ',token parses to "(quote ,) token" and not
"(quote ,token)".
if: (if expr1 expr2 [exp3...])
Intrinsic "if" is a conditional. It accepts 2 or 3 arguments. The first
argument is the test condition. If the test condition evaluates to a
true value, the second argument is evaluated, and that evaluation is
returned. If the test condition evaluates to a false value and further
expressions are present after the second, those expressions are evaluated
in order and the evaluation of the last expression is returned. If only
2 expressions are present, and the test condition evaluates to a false
value, the evaluation of the test expression is returned.
> (if (> 3 4) 'yes 'no)
no
> (if (> 3 4) 'yes)
0
and: (and expr1 [expr2 ...])
Intrinsic "and" accepts 1 or more arguments and evaluates them from left
to right until an argument evaluates to a "false" value. The last
evaluation is returned.
> (and 1 'a 0 1)
0
> (and 1 'a "string")
"string"
or: (or expr1 [expr2 ...])
Intrinsic "or" accepts 1 or more arguments and evaluates them from left
to right until an argument evaluates to a true value. The last
evaluation is returned.
> (or 1 0)
1
> (or 0 0)
0
list: (list expr1 [expr2 ...])
Intrinsic "list" accepts 1 or more arguments and gathers them into a
list.
> (list 'a 'b 'c) ; is equivalent to (cons 'a (cons 'b (cons 'c ())))
(a b c)
> (list '(a b c) 4 "hello")
((a b c) 4 "hello")
progn: (progn expr...)
Intrinsic "progn" accepts 1 or more arguments and evaluates them in
order. "progn" returns the evaluation of the last argument.
> (progn
>> (set 'f (lambda (n) (+ n 1)))
>> (set 'x 1)
>> (f x))
2
prog1: (prog1 ...)
Library macro "prog1" accepts zero or more arguments and evaluates them
in order. "prog1" returns the evaluation of the first argument. If no
arguments are passed to the macro, it returns the empty list.
> (prog1
>> (+ 2 2)
>> (+ 3 3))
4
not: (not expr)
Intrinsic "not" returns 1 if its argument is the empty list, the empty
string, or zero. Otherwise, "not" returns 0.
> (not 0)
1
> (not "hello")
0
nullp: (nullp expr)
Library function "nullp" returns 1 if its argument is the empty list.
Otherwise, "nullp" returns 0.
> (nullp ())
1
> (nullp 'a)
0
pairp: (pairp expr)
Library function "pairp" returns 1 if its argument is a non-empty list.
Otherwise, "pairp" returns 0.
> (pairp '(a b c))
1
(pairp ())
0
(pairp 'a)
0
warn: (warn expr [expr...])
The "warn" intrinsic evaluates its arguments and writes each evaluation
to stderr. A newline is written after the arguments are written. The
"warn" intrinsic returns 1.
setenv: (setenv expr1 expr2)
The "setenv" intrinsic sets the value of a named environment variable.
The function accepts 2 arguments that must evaluate to strings. The
first names the environment variable to set, and the second is the value
to bind to the variable. On success, "setenv" returns 1. Errors stop
evaluation.
unsetenv: (unsetenv expr)
The "unsetenv" intrinsic accepts 1 argument that must evaluate to a
string and removes any environment variable named by the string from the
environment. "unsetenv" returns 1.
getenv: (getenv expr)
The "getenv" intrinsic looks up the value of an environment variable.
The intrinsic accepts 1 argument that must evaluate to a string. If the
string names an environment variable, a string is returned representing
the variable's value. Otherwise, "getenv" returns 0.
> (getenv "HOME")
"/usr/home/jbailie"
> (getenv "foobar")
0
directory: (directory expr)
The "directory" intrinsic accepts 1 argument that must evaluate to a
string. If the string names a directory to which the interpreter has
read access, "directory" returns a list of strings naming the files in
the directory. On error, "directory" returns a string describing the
error returned by the opendir() system call. The ".." and "." directory
entries are not included in the returned list.
> (directory "/usr/local")
("man" "bin" "share" "include" "lib" "etc" "info" "libexec" "sbin" "libdata")
> (directory "/foobar")
"No such file or directory"
chomp: (chomp expr)
The "chomp" intrinsic removes all contiguous terminating carriage return
and newline characters from a string. The function accepts 1 argument
that must evaluate to a string and returns a new string.
> (chomp (getline))
hello[return]
"hello"
> (getline)
hello[return]
"hello
"
>
chop: (chop expr)
The "chop" intrinsic accepts 1 argument that must evaluate to a string
and returns a new string with the same characters as the original string
but with its character removed. If the argument string is empty "chop"
does nothing.
> (chop "hello")
"hell"
> (chop "")
""
beep: (beep)
The "beep" intrinsic accepts no arguments and causes the device connected
to standard output to beep if it is capable of doing so. "beep" returns
1.
suspend: (suspend)
The "suspend" intrinsic accepts no arguments and causes the interpreter
to send a SIGSTOP to itself.
stderr2stdout: (stderr2stdout)
stdout2stderr: (stdout2stderr)
The "stderr2stdout" intrinsic connects stderr to stdout. The
"stdout2stderr" intrinsic connects stdout to stderr. Both functions
accept no arguments and return 1.
pipe: (pipe expr1 expr2)
The "pipe" intrinsic forks a process and connects one of the
interpreter's standard descriptors to a standard descriptor of the
process.
The function accepts 2 arguments. The first argument must evaluate to 0,
1, or 2 and specifies the interpreter descriptor to be redirected. 0 is
the interpreter's standard input. 1 is the interpreter's standard
output. 2 is the interpreter's standard error. The second argument must
evaluate to a string specifying a command line to run.
If the descriptor argument is 0, the other end of the pipe is connected
to the other process's stdout. If the descriptor is 1 or 2, the other
end of the pipe is connected to the process's stdin.
The command is passed to the shell (/bin/sh) for execution. Errors stop
evaluation. On success "pipe" returns 1.
Redirection is undone by the "resume" intrinsic. Successive invocations
of "pipe" on the same descriptor create a pipeline. If interpretation
returns to the toplevel, all redirections are undone.
>(progn
>> (pipe 1 "fmt")
>> (pipe 1 "sort -n")
>> (for (a 100 1)
>>> (print a)
>>>> (newline)))
1
> 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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
92 93 94 95 96 97 98 99 100
Note the last line of output from the pipeline is a short line. After
all the data was written to the pipeline, the "fmt" utility blocked,
reading on its stdin, waiting for enough data to fill another line. When
the "progn" returned to toplevel and the interpreter did an implicit
"resume" on descriptor 1, the pipeline processes read EOF on the pipe,
and "fmt" spat out the last line.
The output of the pipeline and the interpreter process are mixed up
because they both have their standard outputs connected to the terminal.
The 1 after the lisp is the return value of the lisp expression. This is
followed by a the lisp prompt >, which is then followed by the output
from the pipeline.
It is necessary to wrap the whole example in a "progn" to prevent the
interpreter from returning to toplevel between subexpressions and undoing
the redirections. The child process spawned by the second invocation of
"pipe" inherited the redirection made by the first invocation of "pipe".
redirect: (redirect expr1 expr2 [expr3 [expr 4]])
The "redirect" intrinsic redirects one of the three standard file
descriptors to a file. The function accepts 2, 3 or 4 arguments. The
first argument must evaluate to one of 0, 1, or 2 and specifies the
descriptor to be redirected. The second argument must evaluate to a
string specifying the filename to be opened. The third is an optional
boolean fixnum flag (0 or 1) that specifies whether the file specified by
the second argument should be opened in append mode. The fourth argument
is an optional boolean fixnum flag specifying whether the file should be
locked. The third argument is ignored unless argument 1 evaluates to 1
or 2. To provide the fourth argument, you must also provided the third
argument.
If "redirect" is successful, the specified file descriptor is redirected
onto the specified file, and 1 is returned. If an attempt is made to
redirect descriptor 0 to a non-existent file, -1 is returned. If an
attempt is made to redirect any descriptor onto a file to which the user
lacks write permission, -2 is returned. If a lock cannot be acquired, -3
is returned. If "redirect" encounters any other error from the open()
system call, a string string describing the error is returned. Errors
from other sources stop the interpreter.
If execution returns to toplevel while, all redirections are undone by
the interpreter.
temporary: (temporary)
The "temporary" intrinsic creates a file in /tmp and redirects stdout
onto the file. The function accepts no arguments and returns the
filename of the file. Invoke (resume 1) when you are finished writing to
the file. Invoke "unlink" when to delete the file.
with_temporary_output_file: (with_temporary_output_file expr...)
The "with_temporary_output_file" invokes "temporary" to redirect stdout
onto a temporary file, evaluates a sequence of expressions, then invokes
"resume" to undo the redirection to the temporary file. The macro
accepts 1 or more arguments to be evaluated when the redirection is in
place, and returns the name of the temporary file, so that further code
in your program can access the temporary file. "unlink" the filename
when you are finished with the file.
resume: (resume expr)
The "resume" intrinsic connects a descriptor to the source the descriptor
was connected to before the last call to "redirect" or "pipe" on the
descriptor. The function accepts 1 argument that must evaluate to 0, 1,
or 2. If the specified descriptor is not redirected, "resume" returns 0.
Otherwise, "resume" returns 1.
with_input_file: (with_input_file expr1 expr2 ...)
The "with_input_file" macro temporarily redirects standard input onto a
file. The macro accepts 2 or more arguments, the first of must evaluate
to a string specifying the file to read from. The succeeding arguments
are expressions to be evaluated while standard input is redirected. The
redirection is undone after all the arguments have been evaluated. On
success, "with_input_file" returns the evaluation of the last argument.
Otherwise "with_input_file" returns what the failed invocation of the
"redirect" intrinsic returned.
> (with_input_file "library.munger"
>> (print (getline)))
; This file contains the lisp library code for the Munger interpreter.
1
Calls to "with_input_file" can be nested.
> (with_input_file "library.munger"
>> (print (getline))
>> (with_input_file "INSTALL"
>>> (print (getline)))
>> (print (getline)))
; This file contains the lisp library code for the Munger interpreter.
Munger Installation
; Copyright (c) 2001, 2002, 2003, James Bailie .
1
>
with_output_file: (with_output_file expr1 expr2 ...)
The "with_output_file" macro behaves similarly to the "with_input_file"
macro except that "with_output_file" redirects standard output instead of
standard input. The specified file is overwritten if it exists.
> (with_output_file "tmp" (print "hello") (newline))
1
> (with_input_file "tmp" (print (getline)))
hello
1
(unlink "tmp")
1
with_output_file_appending: (with_output_file_appending expr1 expr2 ...)
The "with_output_file_appending" macro behaves similarly to the
"with_output_file" macro except that the specified file is opened for
appending.
with_error_file: (with_error_file expr1 expr2 ...)
The "with_error_file" macro behaves similarly to the "with_output_file"
macro except that "with_error_file" redirects standard error instead of
standard output. The specified file is overwritten if it already exists.
with_error_file_appending: (with_error_file_appending expr1 expr2 ...)
The "with_error_file_appending" macro behaves similarly to the
"with_error_file" macro except that the specified file is opened for
appending.
with_input_process:
with_output_process:
These two macros behave similarly to the "with_input_file" and
"with_output_file" macros except that the first argument names a program
instead of a file. The first argument is passed to /bin/sh.
> (with_input_process "ls"
(while (set 'l (getline))
(print l)))
INSTALL
LICENSE
Makefile
README
cat.munger
cgi.munger
cgi.munger
echo.cgi
err.munger
grep.munger
intrinsics.c
library.munger
lisp.c
lisp.h
munger.man
transform.munger
foreach_line: (foreach_line expr)
The "foreach_line" library macro creates filters. The macro accepts 1
argument that must evaluate to a function that accepts 1 or more
arguments. The function is called repeatedly with each line of input.
The input lines are taken from the files specified on the command line or
if no files are specified, from the standard input.
The argument pointer must be positioned so that the next call to (next)
returns the first of the command line arguments. A script would normally
process any option arguments, advancing the argument pointer as it did
so, and then call foreach_line. "foreach_line" returns when it has
processed all the specified files, or when it encounters EOF on stdin.
; Skip over the interpreter name, so that the argument pointer is now
; pointing to the script name. The next invocation of (next)
; returns the next argument or 0.
(next)
(foreach_line (lambda (line) [do something with line] ))
(exit 0)
foreach_line_callback: (foreach_line_callback expr1 expr2 (expr3))
The "foreach_line_callback" macro functions similarly to the
"foreach_line" macro. "foreach_line_callback" calls a function when the
input source changes. The macro accepts 2 or 3 arguments. The second
argument must evaluate to a function that accepts no arguments and is
called at the end of processing each input source. The third argument is
optional, and if present, is treated as a boolean flag that specifies
whether the callback should be invoked after the argument pointer is
advanced. A "true" third argument causes the callback to be invoked
after the argument pointer has been advanced. Omitting the third
argument, or setting it to "false", causes the callback to be invoked
before the argument pointer is advanced. Within the callback function,
invoking (current) returns the command line argument being processed.
The "grep.munger" example program in (libdir) demonstrates using the
third argument. The following script does not supply a third argument,
and simulates wc -l:
(next)
(set 'script (current))
(set 'count 0)
(set 'total 0)
(set 'callback
(lambda ()
(let ((name (if (eq script (current)) "stdin" (current))))
(print count " " name)
(newline)
(set 'total (+ total count))
(set 'count 0))))
(foreach_line_callback (lambda (x) (inc count)) callback)
(print total " total")
(newline)
(exit 0)
unlink: (unlink expr)
The "unlink" intrinsic removes a file from a directory. The intrinsic
accepts 1 argument that must evaluate to a string specifying the filename
to remove. On success, "unlink" returns 1. On error, "unlink" returns a
string describing the error.
access: (access expr1 expr2)
The "access" intrinsic determines whether the interpreter has access to a
specified file. The function accepts 2 arguments. The first argument
must evaluate to a string and names the file. The second argument must
evaluate to 0, 1, or 2. A second argument of 0 specifies read access. A
second argument of 1 specifies write access. A second argument of 2
specifies executable. If access is allowed, "access" returns 1. If
access is denied "access" returns 0.
mkdir: (mkdir expr)
The "mkdir" intrinsic accepts 1 argument that must evaluate to a string.
"mkdir" attempts to create a directory with the name specified by the
string. Upon success, "mkdir" returns 1. On error, "mkdir" returns a
string describing the error. On success, the new directory has
permissions 755 (possibly modified by the current umask).
rmdir: (unlink expr)
The "rmdir" intrinsic removes a directory from the filesystem. "rmdir"
accepts 1 argument that must evaluate to a string specifying the
directory name. On success, "rmdir" returns 1. On error, "rmdir"
returns a string describing the error.
words: (words)
The "words" intrinsic accepts no arguments and returns the number of
words in the buffer.
time: (time)
The "time" intrinsic accepts no arguments and returns a string
representing an integer representing the number of seconds since 00:00
Jan 1, 1970. Use the "digitize" intrinsic to convert the time to a
fixnum.
timediff: (timediff expr1 expr2)
The "timediff" intrinsic accepts 2 arguments that must evaluate to
strings specifying a time value expressed in seconds from 00:00 Jan 1,
1970. "timediff" returns the difference in seconds between the two
times. If the time difference cannot be expressed within the word-size
of the machine, fixnum wrap-around occurs, and the returned value is not
accurate. The "unsigned" intrinsic returns a string representing the
correct time value.
timethen: (timethen expr)
The "timethen" intrinsic accepts 1 argument that must evaluate to a
fixnum specifying a number of seconds. The value of the argument is
subtracted from the current UNIX time value to specify a time in the
past. "timethen" returns a string representing that time in seconds from
00:00 Jan 1, 1970. This function can be used to determine the UNIX time
value for another time. The following code returns the UNIX time value
for a time 1 hour in the past.
> (timethen -3600)
"1124553616"
date2days: (date2days expr1 expr2 expr3)
The "date2days" intrinsic accepts 3 arguments, each of which must
evaluate to a fixnum. The arguments specify a year, month, and a day of
the month. "date2days" returns a fixnum representing the number of days
this date is removed from March 1st, 1 BCE. This value is useful in
performing calendar arithmetic. The first argument indicates the year
and must be greater than or equal to 0, (1 BCE). The second argument
indicates the month and must be in the range 1-12. The third argument
indicates the day of the month and must be in the range 1-31.
days2date: (days2date expr)
The "days2date" intrinsic accepts a day number fixnum returned by
"date2days" and converts that fixnum into a list of three fixnums
representing that date. The first number indicates the year and is
greater than or equal to 0, (1 BCE). The second number indicates the
month and is in the range 1-12. The third number indicates the day of
the month and is in the range 1-31.
week: (week expr)
The "week" intrinsic accepts 1 argument that must evaluate to a fixnum.
The argument is interpreted as a day number returned by "date2days".
"week" returns a two-element list of fixnums representing the year and
the week number in which the specified day occurs.
weekday: (weekday expr)
The "weekday" accepts 1 argument that must evaluate to a fixnum. The
argument is interpreted as a day number returned by "date2days".
"weekday" returns a two-element list describing the day of the week of
the specified day. The first element is a fixnum in the range 0-6. The
second element is a string representing the name of the weekday in
English.
month: (month expr)
The "month" intrinsic accepts 1 argument that must evaluate to a fixnum.
The fixnum is interpreted as the ordinal position of a month in the
calendar. The fixnum must be in the range 1-12. "month" returns a
string representing the name of the month in English.
localtime: (localtime expr)
The "localtime" intrinsic accepts 1 argument that must evaluate to a
string. The string must represent a UNIX time value such as those
returned by the "time" intrinsic. "localtime" returns a six-element list
of fixnums representing the date of the specified time in the local
timezone. The first element is the year. The second element is the
month. The third element is the day of the month. The fourth element is
the hour. The fifth element is the minutes. The sixth element is the
seconds.
utctime: (utctime expr)
The "utctime" intrinsic accepts 1 argument that must evaluate to a
string. The string must represent a UNIX time value such as those
returned by the "time" intrinsic. "utctime" returns a six-element list of
fixnums representing the date of the specified time in Coordinated
Universal Time. The first element is the year. The second element is
the month. The third element is the day of the month. The fourth
element is the hour. The fifth element is the minutes. The sixth
element is the seconds.
date2time: (date2time expr1 expr2 expr3...)
The "date2time" intrinsic accepts 3, 4, 5, or 6 fixnum arguments
describing a date. "date2time" returns the fixnum that represents that
date as the number of seconds from 00:00, January 1st, 1970.
The first 3 arguments represent the year (1970-), the month (1-12), and
the day of the month (1-31). The fourth, fifth, and sixth optional
arguments represent the hour, minute, and seconds. Omitted optional
arguments default to 0. The presence of an optional argument implies the
presence of all preceding optional arguments. This means if you include
a value for minutes, you must include a value for hours as well, and if
you include a value for seconds, you must include values for hours and
minutes as well.
random: (random expr)
The "random" intrinsic accepts 1 argument that must evaluate to a
positive fixnum. "random" returns a random integer where 0 < returned-
value < evaluated-argument.
date: (date [expr [expr ]])
The "date" intrinsic accepts two optional arguments that must evaluate to
fixnums. "date" returns a string representing the current date.
Invoking "date" with no arguments is the same as invoking it with an
first argument of 0. The second argument is only significant when the
first argument is not 0. When invoked with no arguments or 1 argument of
0, "date" returns a representation of the time and date expressed in
terms of the local timezone. When invoked with a non-zero first
argument, "date" returns a representation of the time and date expressed
as universal coordinated time.
A non-zero second argument changes the UTC abbreviation to GMT.
> (date)
"Fri, 04 Oct 2002 12:06:11 EDT"
> (date 1)
"Fri, 04 Oct 2002 16:06:13 UTC"
> (date 1 1)
"Fri, 04 Oct 2002 16:06:16 GMT"
datethen: (datethen expr1 [expr2 [expr3 ]])
The "datethen" intrinsic accepts 1, 2, or 3 arguments. The first
argument must evaluate to a string specifying a UNIX time value such as
those return by the the "time" and "timethen" intrinsics. The optional
second and third arguments must both be either fixnum 0 or fixnum 1.
"datethen" returns a string describing the time argument formatted
identically to the strings produced by the "date" intrinsic. If the
second argument is 1, the returned time string is expressed in UTC.
Otherwise, the time is specified relative to the local time zone. If the
third argument evaluates to 1, then the timzone abbreviation is GMT
instead of UTC.
Invoking (datethen (time)) is equivalent to invoking (date). Invoking
(datethen (time) 1) is equivalent to invoking (date 1).
print: (print expr...)
println: (println expr...)
Intrinsic "print" accepts 1 or more arguments, evaluates them, and prints
each evaluation to stdout. If an argument evaluates to a string, the
string is printed without the surrounding quotes. If an argument
evaluates to a list, then any strings in those lists are printed with
their surrounding quotes. The "print" intrinsic returns 1.
Intrinsic "println" functions similarly to "print", but "println" outputs
a single newline character after printing its arguments.
> (print "hello there")
hello there
1
> (set 'f '(a b c))
(a b c)
1
> (print f)
(a b c)
> (print 'hello)
hello1
> (progn
>> (print 'hello)
>> (newline))
hello
1
The "newline" intrinsic outputs a newline character (ASCII 10) to stdout.
load: (load expr)
Intrinsic "load" accepts 1 argument that must evaluate to a string.
"load" reads lisp from the file name by the string. "load" returns the
evaluation of the last expression in the file. Errors stop evaluation.
getline_ub: (getline_ub [expr])
The "getline_ub" intrinsic accepts 1 optional argument that must evaluate
to a fixnum.
"getline_ub" is an unbuffered version of the "getline" intrinsic.
"getline_ub" allows the user to read lines of text from stdin and
subsequently "fork" or "forkpipe" the interpreter and "exec" or "shexec"
a new program without the child process losing access to data buffered by
the parent. If the child does not call "exec" or "shexec", "getline_ub"
is not necessary because the child has its own copy of the buffered data.
"getline_ub" reads a line from standard input and returns the line as a
string that includes the terminating newline. If "getline_ub" does not
encounter a newline after reading 2048 characters, the 2048 characters
read are returned without a terminating newline. If EOF is encountered
before a newline or 2048 characters is read, the returned string contains
all the remaining data in the input stream. If no characters remain in
the input stream, the intrinsic returns 0. If the read() system call
fails the intrinsic returns 0.
The optional argument is a timeout value. "getline_ub" reads data a
character at a time from stdin. If any invocation of the read() system
call blocks for a longer number of seconds than that specified by the
timeout value, read() is interrupted and "getline_ub" returns any
characters already read. If no characters were read, the empty string is
returned. If invoked without a timeout value, "getline_ub" blocks until
at least one character can be read from stdin or EOF is encountered and
return either a non-empty string or 0 on EOF.
getline: (getline [expr1 [expr2]])
IF STDIN IS NOT A TERMINAL:
"getline" reads a line from stdin and returns it as a string that
includes the terminating newline. If "getline" does not encounter a
newline before reading 2048 characters, the 2048 characters read are
returned without a terminating newline. If EOF is encountered while
searching for the next newline, all the remaining characters in the
stream are returned. If no characters remain in the stream, "getline"
returns 0. Any subsequent invocations of "getline" on the same input
source continues to return 0. "getline" returns 0 when it encounters any
error condition.
IF STDIN IS A TERMINAL:
The terminal is put into raw mode, and the interpreter simulates the UNIX
terminal line discipline (ctrl-h => backspace; ctrl-w => werase; ctrl-u
=> kill). If Control-D (EOF) is encountered as the first character of
input, "getline" returns 0. Otherwise EOF is ignored, and getline
continues to accumulate characters until either a carriage return or a
newline is input.
Carriage returns are converted into newlines. The strings returned by
"getline" invoked on a terminal are always newline-terminated. The
function drops the cursor to the last line of the terminal device and
echoes input there. The echoed input scrolls horizontally if the input
line grows longer than the width of the terminal device.
The function accepts two optional arguments that are ignored if stdin is
not a terminal. The first argument must evaluate to a string and is
printed as a prompt to the user.
The second argument must evaluate to a fixnum and specifies the location
of tabstops in the onscreen echoed string. For example, a value of 4
causes tabstops to appear to the user to be set every four characters.
If the second argument is not present, tabstops default to every 8
characters. Pass the empty string as the first argument if you wish to
submit a second argument to the function, but you do not wish to print a
prompt.
If the second argument is 0, the input of a tab character triggers
filename completion. If the second argument is -1, tab triggers command
and/or filename completion, depending upon the state of the input line
when the tab is received. If the second argument is -2, tab triggers
filename completion, but the filename completion mechanism does not work
recursively. If the second argument is -3, tab triggers command and/or
filename completion, but the filename completion mechanism does not work
recursively. For the cases where the filename completion mechanism does
not work recursively (second argument of -2 -3), "getline" completes one
level of the path. If completion is invoked again at this point,
"getline" completes another level. For the cases where the filename
completion works recursively, "getline" completes as much of the path as
possible.
When command and filename completion have been requested and the text
entered so far consists of only non-whitespace characters, then command
completion is attempted. Otherwise, filename completion is attempted
upon the last contiguous segment of non-whitespace characters. If the
first character input is either '/' or '.' then filename completion is
attempted in the initial position instead of command completion.
Completions work with a command or filename that contains whitespace only
if the portion before the cursor does not contain whitespace. Quoting
mechanisms are not available. "getline" appends a single space character
to the input string after an unambiguous completion.
When completions are requested, each string created with "getline" is
placed onto a 500-line history list and can be recalled, edited and re-
entered. Pressing Contol-P or Control-N causes the current text to be
replaced with the previous or the next text on the history list. While
in the history list, invoking Control-X restores the original text.
When completions are requested, pressing Control-R or Control-S causes
the interpreter to enter history search mode. The interpreter searches
forward (C-S) or backward (C-R) in the history list for a line containing
the input text. Pressing C-s or C-r again causes the interpreter to
search forward or backward for another matching history line. Both
Control-R and Control-S wraparound the ends of the history list.
Control-H and Backspace erase the last character of the search term.
The history is cleared with the "reset_history" intrinsic.
When completions are requested, these command-line editing commands are
recognized by "getline" in addition to C-h, C-w, and C-u:
M-f - moves the cursor to the beginning of the next word in the line.
M-b - moves the cursor to the beginning of the previous word in the line.
C-k - deletes the text from the cursor location to the end of the line.
C-d - deletes the character the cursor is on.
M-d - deletes the word or word-portion the cursor is before.
C-a - moves the cursor to the beginning of the line.
C-e - moves the cursor to the end of the line.
C-y - pastes the last deletion into the line before the cursor.
Additionally, when completions are active, C-u does not delete the entire
line but only the portion before the cursor.
reset_history (reset_history)
The "reset_history" intrinsic empties the history list the interpreter
maintains for the "getline" intrinsic. The function accepts no arguments
and returns 1.
load_history (load_history expr)
save_history (save_history expr)
The "load_history" intrisic reads the history list from a file. The
"save_history" intrinsic writes the history list to a file. Both
functions accept a single argument that must evaluate to a string naming
the file. On error, the intrinsics return a string describing the error.
On success, the intrinsics return the number of lines read or written.
rescan_path: (rescan_path)
The "rescan_path" intrinsic causes the interpreter to re-build its
internal list of executable files from the directories defined by the
PATH environment variable. This list is used by "getline" and by
"command_lookup". "rescan_path" always returns 1.
stringp: (stringp expr)
Intrinsic "stringp" returns 1 if its argument evaluates to a string.
Otherwise, "stringp" returns 0.
> (stringp "0")
1
> (stringp 0)
0
fixnump: (fixnump expr)
Intrinsic "fixnump" returns 1 if its argument evaluates to a number.
Otherwise, "fixnump" returns 0.
> (fixnump 0)
1
> (fixnump "0")
0
symbolp: (symbolp expr)
Intrinsic "symbolp" returns 1 if its argument evaluates to a symbol.
Otherwise, "symbolp" returns 0.
regexpp: (regexpp expr)
Intrinsic "regexpp" returns 1 if its argument evaluates to a compiled
regular expression. Otherwise, "regexpp" returns 0.
tablep: (tablep expr)
Intrinsic "tablep" returns 1 if its argument evaluates to a table.
Otherwise, "tablep" returns 0.
stackp: (stackp expr)
Intrinsic "stackp" returns 1 if its argument evaluates to a stack.
otherwise, "stackp" returns 0.
intrinsicp: (intrinsicp expr)
Intrinsic "intrinsicp" returns 1 if its argument evaluates to an
intrinsic function. Otherwise, "intrinsicp" returns 0.
closurep: (closurep expr)
Intrinsic "closurep" returns 1 if its argument evaluates to a closure.
Otherwise, "closurep" returns 0.
macrop: (macrop expr)
Intrinsic "macrop" returns 1 if its argument evaluates to a macro
closure. Otherwise, "macrop" returns 0.
recordp: (recordp expr)
Intrinsic "recordp" returns 1 if its argument evaluates to a record.
Otherwise, "recordp" returns 0.
sqlitep: (sqlitep expr)
Intrinsic "sqlitep" returns 1 if its argument evaluates to a sqlite
database object. Otherwise, "sqlitep" returns 0.
regcomp: (regcomp expr1 [expr2 [expr 3]])
The "regcomp" intrinsic accepts 1, 2, or 3arguments. The first argument
must evaluate to a string and is interpreted as a regular expression to
be compiled into a compiled regular expression. "regcomp" returns the
compiled regular expression if compilation is successful. "regcomp"
returns a string describing an error message if compilation fails.
Regular expressions are constants that evaluate to themselves.
If the second optional argument is present, it must evaluate to a fixnum.
If non-zero, the argument causes "regcomp" to produce a compiled regular
expression that matches text case-insensitively. Without the second
argument, "regcomp" defaults to case-sensitive matching. If the third
optional argument is present, it must evaluate to a fixnum. If non-zero,
the argument prevents "regcomp" from recognizing regular expression
operators in the first argument. The resulting compiled expression
matches the literal string value of the first argument.
In the first argument, the escape-sequences \t, \b, \r, and \n represent
the tab, space, carriage return, and newline characters, and the zero
width assertions \< and \> match the null string at the beginning and end
of a word. All escape sequences are ignored if a non-zero third argument
has been passed to "regcomp".
substitute: (substitute expr1 expr2 expr3 [expr4])
Intrinsic "substitute" performs search and replace operations on strings
using regular expressions to specify the matches. The function uses a
template string to specify the replacement text in a manner similar to
that of the substitute command of sed.
The "substitute" function takes 3 or 4 arguments. The first argument
must evaluate to a compiled regular expression. The second and third
arguments must evaluate to strings and are interpreted as the replacement
string and the string to search for matches in. The fourth optional
argument must evaluate to a number that specifies the number of matches
that should be replaced. A value of 0 indicates the substitution should
replace all the matches of the pattern in the text of the third argument.
The absence of the fourth argument is the same as having a fourth
argument of 1. Only the first match is replaced.
The text matched by the first ten subexpressions in the regular
expression is inserted into the replacement string by including an escape
sequence of the form \[0-9] in the replacement text where one wishes the
matched text to appear. The first subexpression is referred to by \1 and
the tenth subexpression is referred to by \0. The text matched by the
entire regular expression is inserted into the replacement text by
inserting \& into the replacement string. In the replacement string,
unrecognized escape sequences are ignored. To escape a backslash, you
must insert a total of four backslashes in the replacement string. A
level of escaping is removed by the lisp string parser leaving two
backslashes for "substitute" to see, the first one escaping the second.
> (substitute (regcomp "string") "booger" "string string string string" 2)
"booger booger string string"
> (substitute (regcomp "[a-z]+") "{\&}" "one two three" 0)
"{one} {two} {three}"
> (substitute (regcomp "([a-zA-Z]+) ([a-zA-Z]+)") "\2 \1"
>> "is This sentence a." 0)
"This is a sentence."
The "substitute" intrinsic interprets the two-character escape-sequences
\t and \b as the tab and space characters. Five other escape sequences
are embedded in the replacement string to control the case of portions of
the returned string. These escape sequences work for strings of ASCII
alphanumeric characters only:
\U Turns on conversion to uppercase.
\u Turns on conversion to uppercase for the next character only.
\L Turns on conversion to lowercase.
\l Turns on conversion to lowercase for the next character only.
\e Turns off \U or \L.
> (substitute (regcomp "foo") "\U\&\e" "foobar")
"FOObar"
The effects of \U and \L extend beyond the replacement string if they are
not terminated:
> (substitute (regcomp "foo") "\U\&" "foobar")
"FOOBAR"
\U and \L override each other:
> (substitute (regcomp "foo") "\U\&\L" "foobar FUNBAG")
"FOObar funbag"
match: (match expr1 expr2)
The "match" intrinsic matches a regular expression against a string and
returns a two element list or the empty list. "match" accepts 2
arguments. The first argument must evaluate to a compiled regular
expression. The second argument must evaluate to the string to match the
regular expression against. On success, a two-element list is returned
consisting of the character indices of the starting and ending locations
of the matched text. The second index is the start of the text following
the match. These two indices can be used in conjunction with the
"substring" intrinsic to extract the text before, after, or containing
the match:
> (set 'rx (regcomp "foobar"))
> (set 's "---foobar---")
"---foobar---"
> (match rx s)
(3 9)
> (substring s 0 3) ; text before the match
"---"
> (substring s 3 (- 9 3)) ; text of the match
"foobar"
> (substring s 9 0) ; text after the match
"---"
In the previous exampe, if the first returned index were 0, the first
invocation of "substring" would have returned the whole string. Passing
a third length argument of 0 to "substring" means "to the end of the
string." The user must check for this situation before invoking
"substring".
matches: (matches expr1 expr2)
The "matches" intrinsic accepts the same arguments as the "match"
intrinsic. "matches" returns a list of matched text.
If no match is found, the list is empty. Otherwise, a list of twenty
strings is returned. The first string is the text matched by the entire
regular expression. The subsequent elements are the text matched by the
first nineteen parenthesized subexpressions in the regular expression.
If nineteen subexpressions are not present in the regular expression,
empty strings are returned for the missing subexpressions. If a
subexpression fails to match, an empty string is returned in the
corresponding list position.
> (matches (regcomp "[0-9]+") "I have 22 figurines.")
("22" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "")
> (matches (regcomp "([0-9])+") "12345")
("12345" "5" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "")
> (matches (regcomp "([0-9]+)") "12345")
("12345" "12345" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" ")
split: (split expr1 expr2 [expr3])
The "split" intrinsic breaks up a string into substrings at delimiters.
"split" accepts 2 or 3 arguments. The first 2 arguments must evaluate to
strings. The first string is interpreted as a set of delimiter
characters that specify where the second argument should be split. Where
a character from the delimiter string occurs in the second argument, the
character is consumed and the string is broken at that place. The pieces
are returned as a list of strings. The original string is unchanged.
The optional third argument must evaluate to a number and specifies a
limit on the number of pieces. If the first argument is the empty
string, the second argument is split up into individual characters. The
"split" intrinsic returns empty strings for empty fields in the original
string. If none of the delimiter characters can be found in the string,
the returned list contains only the original string.
> (split " " "one two three four")
("one" "two" "three" "four")
> (split " " "one two three four" 3)
("one" "two" "three four")
> (split "" "one two three four" 3)
("o" "n" "e two three four")
> (split ":" ":a:b:c:")
("" "a" "b" "c" "")
split_rx: (split_rx expr1 expr2 [expr3])
The "split_rx" library function breaks up a string into substrings using
a regular expression. "split_rx" accepts 2 or 3 arguments. The first
argument must evaluate to a compiled regular expression. The second
argument must evaluate to a string. The third optional argument must
evaluate to a fixnum. The third argument limits the number pieces the
second argument is broken into. The first argument is matched against
the second argument. The text of matches is consumed to split the second
argument into pieces that are returned in a list. If the regular
expression does not match, "split_rx" returns a list containing the
second argument.
> (setq rx (regcomp "[\b\t]+"))
> (split_rx rx "foobar tooley marzipan loopy ")
("foobar" "tooley" "marzipan" "loopy")
rootname: (rootname expr)
The "rootname" library function accepts 1 argument that must evaluate to
a string. "rootname" returns the string without the last trailing dotted
suffix. If the argument does not have a suffix, the original string is
returned.
> (rootname "foobar.tar.gz")
"foobar.tar"
> (rootname (rootname "foobar.tar.gz"))
"foobar"
suffix: (suffix expr)
The "suffix" library function accepts 1 argument that must evaluate to a
string. "suffix" returns the last dotted suffix in the string. If the
string does not end with a suffix, the original string is returned.
> (suffix "foobar.tar.gz")
".gz"
> (suffix (rootname "foobar.tar.gz"))
".tar"
tokenize: (tokenize expr)
The "tokenize" library function accepts 1 argument that must evaluate to
a string. "tokenzie" returns a list of all the tokens embedded in the
string. If the argument contains no whitespace, "tokenize" returns a
list containing only the original argument.
> (tokenize " foobar tooley hot-cha-cha!")
("foobar" "tooley" "hot-cha-cha!")
replace: (replace expr1 expr2 expr3 [expr4])
The "replace" library macro behaves similarly to the "substitute"
intrinsic except that the replacement expression is evaluated once for
every match in the string.
The macro accepts 3 or 4 arguments. The first argument must evaluate to
a compiled regular expression. The second argument is evaluated in a
lexical context where the symbols m0...m19 are bound to the text of the
full match and the text matched by the first nineteen parenthesized
subexpressions.
The string produceshd by this argument undergoes escape-processing when
it is ultimately used as the replacement pattern for a call to the
"substitute" intrinsic. You can pass a string as the second argument,
but it is much more efficient to use "substitute" with a string argument.
The third argument must evaluate to the string the regular expression is
to be matched against. The fourth optional argument must evaluate to a
fixnum specifying a repeat count. The count limits the number of
replacements made in the string. Unlike "substitute", "replace"
interprets a repeat count of 0 as a request to inhibit all substitutions.
If the repeat count is not present, all matches in the string undergo
replacement. If the regular expression matches the second argument,
"replace" returns a new string containing the specified substitutions.
If no match is found, "replace" returns the original string.
The following example uses "replace" to decode x-www-form-url-encoded
characters in a specified string.
> (setq str "foobar+tooley%7Efunbag%24%25%26")
"foobar+tooley%7Efunbag%24%25%26"
> (setq r0 (regcomp "%([0-9A-Fa-f][0-9A-Fa-f])"))
> (setq r1 (regcomp "\+"))
; Decode encoded spaces.
> (setq str (substitute r1 " " str 0))
"foobar tooley%7Efunbag%24%25%26"
; Decoded hex encodings.
>(setq str
>> (replace r0
>>> (char (hex2dec m1))
>>> str))
"foobar tooley~funbag$%&"
concat: (concat expr ...)
The "concat" macro concatenates strings. The macro accepts 1 or more
arguments that must all evaluate to strings or to arbitrarily nested
lists containing only strings. "concat" returns a single string
consisting of all the argument strings concatenated.
> (concat "foo" "bar")
"foobar"
> (concat '("foo" "bar"))
"foobar"
explode: (explode expr)
The "explode" macro accepts 1 argument that must evaluate to a string.
"explode" returns a list of one-character strings derived from the
characters of the argument.
> (explode "foobar")
("f" "o" "o" "b" "a" "r")
join: (join expr1 expr2 expr3...)
The "join" intrinsic concatenates strings with delimiters. "join"
accepts 3 or more arguments that must all evaluate to strings or to
arbitrarily-nested lists containing only strings. The first argument is
sandwiched between the strings of the remaining arguments to make a new
string. The new string is returned.
> (join " " "This" "will" "be" "a" "sentence.")
"This will be a sentence."
> (join "" "this" "will" "be" "run" "together")
"thiswillberuntogether"
> (join ":" '("a" ("b" ("c") "d") "e"))
"a:b:c:d:e"
length: (length expr)
The "length" intrinsic accepts 1 argument that must evaluate to a string,
a record, a stack, a table, or a list. "length" returns the number of
characters in a string, the number of key/value pairs in a table, or the
number of elements in a list.
> (length "fiver")
5
> (length '(a b c))
3
sort: (sort [expr...])
The "sort" intrinsic accepts 0 or more number of arguments that must all
evaluate to numbers or must all evaluate to strings. "sort" returns a
sorted list of its arguments in ascending order. Invoking "sort" without
arguments returns the empty list. When sorting strings, case is ignored.
> (sort "D" "c" "B" "a")
("a" "B" "c" "D")
> (sort 3 2 1)
(3 2 1)
sortlist: (sort expr)
The "sortlist" intrinsic accepts 1 argument that must evaluate to a list
whose elements must be either all numbers or all strings. "sortlist"
returns a new list whose members are the members of the argument list
sorted into ascending order. When sorting strings, case is ignored.
> (sortlist '("c" "b" "a"))
("a" "b" "c")
> (sortlist '(0 -23 1))
(-23 0 1)
sortcar: (sortcar expr)
The "sortcar" intrinsic accepts 1 argument that must evaluate to a list
whose elements must all be lists. The first elements of the interior
lists must either be all strings or all numbers. "sortcar" returns a new
list containing the interior lists sorted in ascending order by the
interior lists' first elements.
The following example sorts a stack-of-stacks, using the second element
of each substack as the sort key.
> (set 's (stack 3))
> (store s 0 (assign (stack) '(f 2 f)))
> (store s 1 (assign (stack) '(f 1 f)))
> (store s 2 (assign (stack) '(f 0 f)))
> (flatten s)
( )
> (assign s (mapcar (lambda (x) (cadr x))
(sortcar (mapcar (lambda (x) (list (index x 1) x))
(flatten s)))))
> (flatten s)
( )
until: (until expr1 [expr2 ...])
while: (while expr1 [expr2 ...])
The "while" and "until" intrinsics are looping constructs. "while"
accepts 1 or more arguments, the first of which is the test condition.
If the test evaluates to a true value, the rest of the arguments are
evaluated in order. This process is repeated until the test no longer
evaluates to a true value. "while" returns the final evaluation of the
test, which is a false value.
"until" behaves similarly "while", but the logic of the test is inverted.
The body of an "until" loop is executed when the test condition evaluates
to a false value. "until" returns the final evaluation of the test,
which is a true value.
> (setq n 10)
10
> (while n
>>> (print n)
>>> (newline)
>>> (setq n (- n 1)))
10 9 8 7 6 5 4 3 2 1
1
> (setq n 0)
0
> (setq l ())
()
> (until (eq n 10)
>> (setq l (cons (inc n) l)))
1
> l
(10 9 8 7 6 5 4 3 2 1)
do: (do expr1 [expr2 ...])
The "do" intrinsic is another looping construct. "do" accepts 1 or more
arguments. All the arguments are evaluated in order. If the last
argument evaluates to a true value, all the arguments are evaluated
again. This process repeats until the last expression evaluates to a
false value. "do" returns the value of the final test expression, which
is a false value.
> (set 'n 0)
0
> (do
>> (print n)
>> (newline)
>> (set 'n (+ n 1)))
> (< n 10))
0 1 2 3 4 5 6 7 8 9
1
>
fatal: (fatal)
nofatal: (nofatal)
The "fatal" and "nofatal" intrinsics accept no arguments. After "fatal"
is invoked, all errors that stop evaluation cause the interpreter to exit
after it has returned to toplevel. After "nofatal" is invoked, the
interpreter does not exit on return to toplevel.
die: (die [expr...])
Intrinsic "die" forces the interpreter to return to the toplevel. The
optional arguments are passed to the "warn" intrinsic. Invoking "die"
when "fatal" has been invoked causes the interpreter to exit upon return
to toplevel.
throw: (throw expr)
catch: (catch [expr1]...)
The "catch" and "throw" intrinsics provide non-local exits. "catch"
accepts 1 or mor arguments. "throw" accepts 1 argument. The arguments
to catch are evaluated in an implicit "progn", and the result of
evaluating the last expression is returned. If a "throw" is evaluated in
the arguments to "catch", the thread of execution returns to the catch
expression. The "catch" form catches the argument provided to "throw",
and "catch" returns the argument. "throw" evaluates its argument before
throwing it to "catch".
If "throw" is invoked outside of a "catch", the interpreter returns to
toplevel.
> (catch
>> (print (catch 0 (throw 'hello) 2 3 4))
>> (newline)
>> (throw 'goodbye)
>> (print 'not_reached))
hello
goodbye
>
stringify: (stringify expr...)
The "stringify" intrinsic accepts 1 or more arguments that must evaluate
to atoms. "stringify" converts each atom's print syntax into a string.
All the strings are concatenated into one string, which is returned.
> (stringify 12 "," 43)
"12,43"
> (stringify 'hello " " 'there)
"hello there"
digitize: (digitize expr)
The "digitize" Intrinsic accepts 1 argument that must evaluate to a
string or a symbol and converts the argument to a number.
> (digitize '42)
42
> (digitize "-3")
-3
> (digitize "abc")
0
mapcar: (mapcar expr1 expr2)
The "mapcar" library function accepts 2 arguments. The first argument
must evaluate to a closure or an intrinsic function that accepts 1 or
more arguments. The second argument must evaluate to a list. "mapcar"
applies the function to each element of the list. "mapcar" returns a new
list containing each evaluation.
> (set 'l '(a b c))
(a b c)
> (set 'f (lambda (n) (list n n n)))
> (mapcar f l)
((a a a) (b b b) (c c c))
map: (map expr1 expr2 ...)
The "map" library function is a generalized version of "mapcar". "map"
accepts 2 or more arguments. The first argument must evaluate to a
closure or an intrinsic function. The remaining arguments must all
evaluate to lists of the same length. The function passed as the first
argument must accept as many arguments as there are list arguments.
"map" returns a new list containing the result of successively applying
the function to a grouping of elements from each list. The function is
applied to first elements of each list. Then the function is applied to
the second elements of each list and so on.
> (map (lambda (x y z) (+ x y z)) '(1 2 3) '(4 5 6) '(7 8 9))
(12 15 18)
remove: (remove expr1 expr2)
Library function "remove" accepts 2 arguments. The first argument can
evaluate to any type. The second argument must evaluate to a list.
"remove" returns a new list that is a copy of the argument list with all
occurrences of the first argument removed. "remove" uses library
function "equal" to test for equivalency.
> (remove 'a '(a a a b))
(b)
> (remove '(a b) '((a b) c (a b) (a b) d e f g))
(c d e f g)
nthcdr: (nthcdr expr1 expr2)
The "nthcdr" intrinsic returns the "nth" cdr of a list. "nthcdr" accepts
2 arguments. The first argument must evaluate to a list. The second
argument must evaluate to a positive fixnum. If the argument list has
insufficient elements to complete the request, "nthcdr" returns the empty
list.
> (nthcdr '(a b c) 1)
(b c)
> (nthcdr '(a b c) 2)
(c)
> (nthcdr '(a b c) 3)
()
nth: (nth expr1 expr2)
The "nth" intrinsic returns the "nth" car of a list. elements are
numbered from from zero. "nth" accepts 2 arguments. The first argument
must evaluate to a list. The second argument must evaluate to a positive
fixnum specifying the index position of the desired element. "nth"
returns the specified element. If the list has insufficient elements to
satisfy the request, "nth" returns the empty list.
> (setq l '(a b c))
(a b c)
> (for (n (length l) 0)
>> (println (nth l n)))
()
c
b
a
0 ; This is the return value of "while"
member: (member expr1 expr2)
Library function "member" accepts 2 arguments. The first argument can
evaluate to any lisp object. The second argument must evaluate to a
list. If the first argument is "equal" to any element of the list,
"member" returns 1. Otherwise, "member" returns 0.
> (member 'a '(a b c))
1
reverse: (reverse expr1)
Library function "reverse" accepts 1 argument that must evaluate to a
list or a string. If the argument is a list, "reverse" returns a new
list containing the same elements as the original list but in reverse
order. If the argument is a string, "reverse" returns a new string
consisting of the same characters as the original but in reverse order.
> (reverse '(a b c))
(c b a)
> (reverse "hello")
"olleh"
append: (append expr1 ...)
The "append" intrinsic accepts 1 or more arguments that all must evaluate
to lists. "append" returns a new list consisting of the elements of the
argument lists.
(append '(a b c) '(d e f))
(a b c d e f)
loop: (loop expr1 ...)
The "loop" intrinsic implements an infinite loop. The function accepts 1
or more arguments. "loop" evaluates its arguments in order, repeatedly.
The evaluation of each argument is discarded. The only way to exit a
"loop" loop is to wrap it in a "catch" and invoke "throw" in the loop:
> (catch
>> (loop
>>> (if (setq line (getline))
>>>> (print line)
>>>> (throw line))))
iterate: (iterate expr1 ...)
The "iterate" intrinsic evaluates expressions a specified number of
times. "iterate" accepts 1 or more arguments. The first argument must
evaluate to a number that specifies the number of times the loop
executes. If the repeat count is negative, the absolute value of the
repeat count is used. The arguments after the repeat count are optional.
Each argument is evaluated in order and the repeat count is decremented
by 1. When the repeat count is 0, evaluation stop. The evaluation of
the last argument on the last iteration is returned. If no arguments are
provided after the repeat count, the repeat count is returned. The
"iterate" intrinsic is the fastest means of iteration available in the
Munger interpreter.
> (iterate 10 (print "A"))
AAAAAAAAAA1
The 1 is the return value of the "print" intrinsic, which is in turn the
return value of "iterate".
for: (for (symbol expr1 expr2 [expr3]) expr ...)
for: (for (([expr...]) (expr [...]) ([expr...])) expr ...)
The "for" intrinsic provides a looping facility similar to the C "for"
keyword. There are two forms of this intrinsic.
FIRST FORM.
The first form implements loops with an index variable. "iterate" is the
most efficient means of iterating a fixed number of times. "iterate"
accepts 2 or more arguments. The first argument must be a three or four
element list. The first 3 arguments must be a symbol to be used for the
loop index variable, an expression evaluating to the initial fixnum value
for the index variable, and an expression evaluating to the fixnum value
the index variable should have on the last iteration of the loop. The
fourth optional element is an increment value.
If the start value is less than or equal to the stop value, the index
variable is incremented on each iteration. Otherwise, the index variable
is decremented on each iteration. Each of the remaining arguments is
evaluated in each iteration of the loop. "for" returns the evaluation of
the last argument evaluated on the last iteration.
The optional fourth element in the first argument list must evaluate to a
fixnum specifying the increment or decrement value. The absolute value
of the argument is added if the first element is less than or equal to
the second element. The absolute value of the argument is subtracted
from the index variable if the first element is greater than the second
element. If the fourth element is not present, the increment value
defaults to 1. If incrementing or decrementing the index variable
results in values that do not become the stop value, the index on the
last iteration of the loop is the last value that was within the
inclusive range specified by the start and stop values.
A "for" loop introduces a new environment for the loop's index variable.
If a closure is formed in the body of a "for" loop, the closure captures
the new environment. Any invocations of "extend" or "dynamic_extent"
inside of a "for" loop body affect the environment of the loop and not
the environment in which the loop is embedded.
> (for (n 0 10 2)
>> (println n))
0
2
4
6
8
10
1 ; return value of "println"
> (set 'a 5)
5
> (for (a a 1)
>> (for (a a (+ a a))
>>> (print a " "))
>> (newline))
5 6 7 8 9 10
4 5 6 7 8
3 4 5 6
2 3 4
1 2
1 ; return value of inner "newline"
>
It is possible to invoke "continue" inside a for loop such that no return
value is ever generated by any of the contained expressions. In that
case, "for" returns 0.
SECOND FORM
The second form of the "for" intrinsic provides a more generic looping
facility. With this form, the first argument must also be a three-
element list, and the subsequent arguments are the loop's body
expressions, but each sublist of the first argument list must also be a
list. The first sublist is a list of expressions to be evaluated in
order before any other part of the loop is evaluated. The first sublist
can be empty. The second sublist consists of 1 or more expressions. The
first expression is the test condition, and is evaluated before every
entry into the loop body. The remaining elements are the final
expressions that are evaluated as the last act of the loop. The elements
after the test expression can be omitted. The third sublist contains the
update expressions to be evaluated after evaluation of the loop body
expressions. The third sublit can be empty.
Evaluation of the loop proceeds as follows. The initialization
expressions are evaluated.
LABEL: REPEAT
The test condition is evaluated. If the evaluation of the test condition
results in a false value, the elements after the test condition are
evaluated in order. "for" returns the last evaluation. If there are no
expressions after the test expression, the evaluation of the failed test
expression is the return value of the loop. The loop is finished.
If the evaluation of the test condition results in a true value, each of
the body expressions are evaluated in order, and then each of the
elements of the update sublist are evaluated. Goto REPEAT.
(defun fact (n)
(for (((extend 'a 1)) ((> n 1) a) ((dec n)))
(setq a (* n a))))
downcase: (downcase expr1 expr2)
upcase: (upcase expr1 expr2)
The "upcase" library function accepts 2 arguments. The first argument
must evaluate to a string. The second argument is treated as a logical
true or false value after evaluation. If the second argument evaluates
to a true value, then "upcase" returns a new string consisting of the
characters of the first argument with any lowercase characters replaced
with their corresponding uppercase characters. If the second argument
evaluates to a false value, then only the first lowercase character
encountered is converted to uppercase. If no lowercase alphabetic
characters are present in the first argument, "upcase" returns a copy of
the first argument.
The "downcase" library function behaves similarly to "upcase" except that
"downcase" converts lowercase characters to uppercase.
alist_lookup: (alist_lookup expr1 expr2)
The "alist_lookup" library function accepts 2 arguments. The evaluation
of the first argument is treated as a key of the alist. The second
argument must evaluate to an alist. "alist_lookup" returns the cdr of
the first sublist of the alist whose car is equal to the key.
> (set 'y '((a b) (b c)))
((a b) (b c))
> (alist_lookup 'b y)
(c)
>
alist_remove: (alist_remove expr1 expr2)
The "alist_remove" library function accepts 2 arguments. The evaluation
of the first argument is treated as a key of the alist. The second
argument must evaluate to an alist. "alist_remove" returns a copy of the
alist with the first sublist whose car is the key, removed.
> (set 'y '((a b) (b c)))
((a b) (b c))
> (alist_remove 'b y)
((a b))
> y
((a b) (b c))
>
alist_replace: (alist_replace expr1 expr2 expr3)
The "alist_replace" library function accepts 3 arguments. The evaluation
of the first argument is treated as a key of the alist. The second
argument must evaluate to an alist. The third argument must evaluate to
a list. "alist_replace" returns a copy of the second argument with the
first sublist whose car is the key replaced with a new sublist consisting
of the key and the elements of the third argument. The new sublist is
added to the front of the alist copy.
> (set 'y '((a b) (b c)))
((a b) (b c))
> (alist_replace 'b y '(d e f))
((b d e f) (a b))
> (set 'y ())
()
> (alist_replace 'b y '(d e f))
((b d e f))
>
when: (when expr1 expr2...)
The "when" intrinsic is a conditional. "when" accepts 1 or more
arguments. The first argument is the test condition. The test condition
is evaluated, and if the evaluation is a true value, the succeeding
arguments are evaluated. "when" returns the evaluation of the last
argument. If the test condition evaluation is a false value, that value
is returned.
> (when (eq 1 1)
>> (print 'hello)
>> (newline))
hello
1
>
unless: (unless expr1 expr2...)
The "unless" intrinsic is a conditional. "unless" accepts 1 or more
arguments. The first argument is the test condition. The test condition
is evaluated, and if the evaluation is a false value, the succeeding
arguments are evaluated. "when" returns the evaluation of the last
argument. If the test condition evaluation is a true value, that value
is returned.
> (unless (eq 1 1)
>> (print 'hello)
>> (newline))
1
>
apply: (apply expr1 expr2)
The "apply" macro accepts 2 arguments. The first argument must evaluate
to a closure or intrinsic. "apply" conses its first element onto its
second and evaluate the result.
> (apply 'set '('q 2))
2
inc: (inc symbol [expr])
dec: (dec symbol [expr])
The "inc" and "dec" intrinsics increment and decrement a fixnum bound to
a symbol. Both functions accept 1 or 2 arguments. The first argument is
not evaluated and must be a symbol bound to a fixnum. The second
optional argument must evaluate to a number. The value bound to the
symbol is incremented or decremented by the value specified by the second
argument. If the second argument is not present, the value is
incremented or decremented by 1. The new value is returned.
> (set 'a 1)
1
> (inc a)
2
> (dec a)
1
> (inc a 10)
11
test: (test expr1)
The "test" intrinsic tests macro expansion. "test" accepts 1 argument
that is not evaluated. The argument must be a list consisting of a macro
application. "test" returns the result of expanding the macro.
> (test (quit))
(exit 0)
continue: (continue)
The "continue" intrinsic short ciruits the evaluation of loops. When
invoked in a loop, "continue" causes the loop to skip any subsequent
expressions in the loop body and jump to the top of the loop to continue
with the next iteration. Invoking "continue" inside of a "do" loop
prevents the evaluation of the test condition. An infinite loop can
result.
If "continue" is invoked outside of the body of a loop, the interpreter
returns to toplevel.
> (set 'n 10)
10
> (while n
>> (print n)
>> (newline)
>> (set 'n (- n 1))
>> (continue)
>> (set 'n 0))
10
9
8
7
6
5
4
3
2
1
0
>
The last 0 is the return value of the "while" intrinsic.
block: (block)
unblock: (unblock)
The "block" and "unblock" intrinsics accept no arguments. These
intrinsics determine whether SIGINT, SIGQUIT, and SIGHUP kill the
interpreter and whether SIGTSTP, SIGTTIN, and SIGTTOU are ignored by the
interpreter.
The interpreter starts out in the unblocked state. When in the unblocked
state, the interpreter is killed upon receipt of SIGINT, SIGQUIT, and
SIGHUP. The interpreter generates a core dump upon receipt of SIGQUIT.
When in the unblocked state, the interpreter is stopped upon receipt of
SIGTSTP, SIGTTIN, or SIGTTOU. Invoking "block" renders all of these
signals impotent. Both of these intrinsics always return 1.
SIGTERM is caught by the interprepter. The "sigtermp" intrinsic can be
used to detect the occurrence of SIGTERM.
sigtermp: (sigtermp)
The "sigtermp" intrinsic accepts no arguments and returns 0 or 1
indicating whether the interpreter has received a SIGTERM since the last
invocation of "sigtermp".
exists: (exists expr)
The "exists" intrinsic accepts 1 argument that must evaluate to a string
that names an entity in the file system. "exists" calls the stat()
system call with the filename. "exists" returns a fixnum.
If stat() succeeds, "exists" returns a value in the range of 1 to 8. If
stat() fails, "exists" returns 0 or -1. If the file does not exist,
"exists" returns 0. If the interpreter lacks permission to search one of
the directories in the filename, "exists" returns -1. The interpreter
does not need permission to read the file itself in order to stat() it.
Successful return values are as follows.
1 == regular file
2 == directory
3 == character device
4 == block device
5 == fifo
6 == symbolic link
7 == socket
8 == unknown type
stat: (stat expr)
The "stat" intrinsic accepts 1 argument that must evaluate to a string
that names a file system entity. The filename is passed to the stat()
system call. "stat" returns a list. If the specified entity does not
exist in the file system, or the interpreter does not have search
permission for one a directory, the returned list is empty. For other
errors, "stat" returns a string describing the error.
Upon successful return of stat(), "stat" returns a 5-element list. The
first element is a string describing the user name of the file. If the
uid does not map to a user on the system, the first element is the uid as
a fixnum. The second element is a string describing the group name of
the file. If the gid does not map to a group on the system, the first
element is the gid as a fixnum. The third element is the time of the
last access of the file as a string. The fourth element is the time of
the last modification of the file as a string. The fifth element is the
size of the file. The time values are expressed in seconds elapsed since
the UNIX Epoch (00:00:00 January 1, 1970 UTC).
> (stat (current))
("root" "wheel" "1097210850" "1097210836" 417214)
rename: (rename expr1 expr2)
The "rename" intrinsic renames entries in the filesystem. "rename"
accepts 2 arguments that must evaluate to strings. The first argument
names a filesystem entity. The second argument is the new name it for
the first argument. "rename" returns 1 on success. On error, "rename"
returns a string describing the error.
current: (current)
The interpreter maintains a pointer to an element of the command line
argument list. The "current" intrinsic accepts no arguments and returns
the command line argument to which the pointer points. At startup,
"current" returns the name of the interpreter.
prev: (prev)
The "prev" intrinsic accepts no arguments and steps the argument pointer
back to the previous command line argument. If no previous argument
exists, "prev" returns 0. If a prevous argument exists, the previous
argument is made the current argument and is returned as a string.
next: (next)
The "next" intrinsic steps the argument pointer forward to the next
command line argument. If no next argument exists, "next" returns 0. If
a next argument exists, the next argument is made the current argument
and is returned as a string.
rewind: (rewind)
The "rewind" intrinsic accepts no arguments and sets the interpreter's
command line argument pointer to point to the first command line
argument. "rewind" returns the first command line argument as a string.
The first argument is always the name of the interpreter.
interact: (interact)
The "interact" intrinsic accepts no arguments and causes the interpreter
to stop evaluating the current program to work interactively with the
user. "interact" is for programs that need to make the interpreter
toplevel temporarily available to the user.
Control-D or "_" input causes the program that invoked "interact" to
resume. "interact" returns 1. Recursive invocations of "interact" cause
a string to be returned with an error message, but evalution at the
prompt of the original invocation continues normally. Note that the
"fatal" intrinisic has no effect when lisp errors are generated inside
"interact". The interpreter does not exit when an error is generated by
the user working at the "interact" prompt.
The current local environment is hidden from "interact".
pwd: (pwd)
The "pwd" intrinsic accepts no arguments and returns the current working
directory as a string.
let: (let [list] expr2 ...)
The "let" intrinsic introduces new local lexical bindings and evaluates a
list of expressions with the new bindings in place. The bindings are
removed when "let" returns.
"let" accepts 2 or more arguments. The first argument is not evaluated
and must be a parameter list of the form: ((symbol1 expr1) (symbol2
expr2)...). The result of evaluating each exprN in the current scope
gets bound to its paired symbolN in the new scope. The remaining
arguments are evaluated in the new scope. "let" returns last evaluation.
> (let ((a 1) (b 2))
>> (print "a: " a " b: " b)
>> (newline))
a: 1
b: 2
1 ; This is the return value of (newline)
> (set 'a 2)
2
> (let ((a (* a a)))
>> (while a
>>>> (print "a: " a)
>>>> (newline)
>>>> (set 'a (- a 1))))
a: 4
a: 3
a: 2
a: 1
0
> a
2
letn: (letn [list] expr2 ...)
Intrinsic "letn" introduces new local lexical bindings and evaluates a
list of expressions with those new bindings in place. The bindings are
removed when "letn" returns.
"letn" accepts 2 or more arguments. The first argument is not evaluated
and must be a parameter list of the form: ((symbol1 expr1) (symbol2
expr2)...). The result of evaluating each exprN in the current scope
gets bound to its paired symbolN in the new scope. The remaining
arguments are evaluated in the new scope. "letn" returns the last
evaluation.
Intrinsic "letn" is different from intrinsic "let" in that each binding
made to symbolN is visible in exprN+1, exprN+2, etc. This form is called
"let*" in Scheme and Common Lisp.
> (letn ((a 1)
>>> (b (+ a 1)))
>> (print "b: " b)
>> (newline))
b: 2
1
>
letf: (letf [list] expr2 ...)
Macro "letf" is the equivalent to a named let in Scheme. "letf" provides
a means of creating and applying a temporary function capable of
recursing on its name. The macro accepts 3 or more arguments. The first
argument is not evaluated and must be a symbol. The second argument must
be a list of the form: ((symbol1 expr1) (symbol2 expr2) ...). The result
of evaluating each exprN in the current scope gets bound to its paired
symbolN in a new local lexical environment. The symbol passed as the
first argument is visible in the new environment. The remaining
arguments are then evaluated in the new environment. "letf" returns the
last evaluation.
> (setq a 10)
10
> (letf fact ((n a))
>> (if (< n 2)
>>> n
>>> (* n (fact (- n 1)))))
3628800
>
tailcall: (tailcall expr1 ...)
The "tailcall" intrinsic accepts 1 or more arguments. The first argument
must evaluate to a closure or 0. The remaining arguments are the
arguments to be passed to the closure. A first argument of 0 indicates
the tail-call is a recursive call of the function in which "tailcall" has
been invoked. This allows anonymous functions to call themselves tail-
recursively. Using tail-calls to implement iteration is inefficient in
Munger.
Note that invoking "tailcall" from a non-tail position, results in that
position becoming a tail position. Any pending computation in the
function is abandoned.
labels: (labels [list] expr2 ...)
The "labels" intrinsic temporarily binds a set of functions to a set of
symbols such that each binding is visible in each function. This allows
recursive and mutually-recursive local functions to be defined in a new
environment. "labels" accepts 1 or more arguments. The first argument
must be a list of lists where each sublist consists of a symbol paired
with a lambda or macro expression. The remaining arguments are evaluated
in the new environment. "labels" returns the last evaluation.
> (labels ((even (lambda (n) (or (eq n 0) (tailcall odd (- n 1)))))
>>> (odd (lambda (n) (and (not (eq n 0)) (tailcall even (- n 1))))))
>> (print (even 11))
>> (newline))
0
1 ; This is the return value of the "newline".
extract: (extract expr)
The "extract" intrinsic extracts the lambda-expression from a function
closure. "extract" accepts 1 argument that must evaluate to a closure.
"extract" returns the closure's lambda-expression.
> mapcar
> (extract mapcar)
(lambda (f l) (if (pairp l) (cons (f (car l)) (mapcar f (cdr l))) ()))
cond: (cond [list] ...)
Intrinsic "cond" is a multiple choice conditional. "cond" accepts 1 or
more lists as arguments. Each list must consist of at least 2 elements.
"cond" evaluates the first element of each argument list until an
evaluation returns a true value. At that point, the rest of that
argument list is evaluated. "cond" returns the value of the last
evaluation. If none of the first elements of the argument lists evaluate
to a true value, "cond" returns the false value returned by the first
element of the last argument list. By placing a first element of 1 in
the final sublist, a catch-all else clause is created.
> (set 'a 10)
10
> (cond ((eq a 12) 'no)
>> ((eq a 10) 'yes))
yes
>
case: (case expr expr2 ...)
The "case" macro is a multiple choice conditional. "case" accepts two or
more arguments. The first argument can be any expression. The
succeeding elements must be lists. The first argument is evaluated, and
then the evaluation is compared against the result of evaluating the
first elements of each argument list using "eq". If "eq" returns 1, then
the succeeding elements of the list are evaluated. "case" returns the
evaluation of the last list element.
If the first element of any of the argument lists is a question mark, the
elements of that list are evaluated if none of the preceding lists are
evaluated.
> (setq n 3)
3
> (case n
>> (1 'one)
>> (2 'two)
>> (3 'three)
>> (4 'four)
>> (5 'five))
three
(setq n 11)
> (case n
>> (6 'six)
>> (7 'seven)
>> (8 'eight)
>> (9 'nine)
>> (10 'ten)
>> (? "no match"))
"no match"
foreach: (foreach expr1 expr2)
The "foreach" library function applies a function to every item in a
list. The result of each application is discarded. "foreach" returns the
empty list.
> (set 'print_each
>> (lambda (x) (print x) (newline)))
> (foreach print_each '(a b c d))
a
b
c
d
()
>
+: (+ expr...)
Intrinsic "+" accepts any number of arguments that must evaluate to
fixnums. "+" returns their sum.
> (+ 1 1 1 1)
4
> (+ 1 "hello")
+: argument 2 did not evaluate to a number.
-: (- expr1 expr2)
Intrinsic "-" accepts 2 arguments that must evaluate to fixnums. "-"
returns their difference. The second argument is subtracted from the
first.
> (- 1 2)
-1
> (- (+ 1 1) 2)
0
*: (* expr...)
Intrinsic "*" accepts 1 or more arguments that must all evaluate to
fixnums. "*" returns their product.
> (* 1 12 2)
24
> (* (+ 23 3) 4)
104
/: (/ expr1 expr2)
Intrinsic "/" accepts 2 arguments that must evaluate to fixnums. "/"
returns the quotient that results from dividing the second argument into
the first.
> (/ 4 3)
1
%: (% expr1 expr2)
Intrinsic "%" accepts 2 arguments that must evaluate to fixnums. "%"
returns the remainder that results from dividing the second argument into
the first.
> (% 4 3)
1
>: (> expr1 expr2)
Intrinsic ">" accepts 2 arguments that must evaluate to numbers. ">"
returns 1 if the first argument is larger than the second. ">" returns 0
otherwise.
> (> 4 3)
1
> (> -4 3)
0
>=: (>= expr1 expr2)
Intrinsic ">=" accepts 2 arguments that must evaluate to numbers. ">="
returns 1 if the first argument is greater than or equal to the second.
">=" returns 0 otherwise.
> (>= 4 3)
1
<: (< expr1 expr2)
Intrinsic "<" accepts 2 arguments thatmust evaluate to numbers. "<"
returns 1 if the first argument is less than the second. "<" returns 0
otherwise.
> (< 4 3)
0
<=: (<= expr1 expr2)
Intrinsic "<=" accepts 2 arguments that must evaluate to numbers. "<="
returns 1 if the first argument is less than or equal to the second.
"<=" returns 0 otherwise.
> (<= 3 4)
0
negate: (negate expr)
The "negate" intrinsic accepts 1 argument that must evaluate to a fixnum.
"negate" returns the fixnum negated.
> (negate 3)
-3
> (negate -3)
3
abs: (abs expr)
Intrinsic "abs" accepts 1 argument that must evaluate to a fixnum. "abs"
returns the absolute value of the fixnum.
intern: (intern expr1)
The "intern" intrinsic accepts 1 argument that must evaluate to a string.
"intern" converts the string into a symbol.
> (set 'hello 4)
4 (eval (intern "hello"))
4
char: (char expr1)
The "char" intrinsic accepts 1 argument that must evaluate to a fixnum
between 1 and 255. "char" returns a string consisting of the character
represented by the ASCII code specified by the argument.
code: (code expr1)
The "code" intrinsic accepts 1 argument that must evaluate to a string.
"code" returns a fixnum representing the ASCII code of the first
character of the argument.
open: (open)
The "open" intrinsic accepts no arguments. "open" creates a new text
buffer and makes the new buffer the active buffer. The buffer number of
the new text buffer is returned on success. Errors stop evaluation.
close: (close)
The "close" intrinsic accepts no arguments. "close" closes the active
text buffer and makes the most-recently opened buffer that has not been
closed the active buffer. "close" returns 1 on success. Errors stop
evaluation.
insert: (insert expr1 expr2 expr3)
The "insert" intrinsic inserts a line into the active buffer. "insert"
accepts 3 arguments. The first argument must evaluate to a positive
fixnum specifying a line number in the buffer. The second argument must
evaluate to a string containing data to be inserted into the buffer. The
third argument must evaluate to a fixnum. A value of 0 indicates that
the line corrresponding to the line number position is to be overwritten.
A positive value indicates that the new line should be inserted after the
numbered line. A negative value indicates that the data is to be
inserted before the numbered line. If the specified line number does not
exist, a line with that number is created. All the lines preceding it in
the buffer are created and initialized to the empty string.
"insert" returns 1, 0 on failure.
> (open)
1
> (insert 1 "This is the first line." 0)
1
delete: (remove expr1)
The "delete" intrinsic removes a line from the active buffer. "delete"
accepts 1 argument that must evaluate to a positive fixnum specifying the
line number of the line to be deleted. "delete" returns 1 on success, 0
on failure.
retrieve: (retrieve expr1)
The "retrieve" intrinsic returns a string containing the content of a
specified line in the active buffer. "retrieve" accepts 1 argument that
must evaluate to a positive fixnum specifying the line number of the
desired line. If the specified line number does not exist, evaluation
stops.
lastline: (lastline)
The "lastline" intrinsic accepts no arguments and returns the line number
of the last line in the active buffer. Errors stop evaluation.
filter: (filter expr1 expr2 expr3)
The "filter" intrinsic sends a range of lines from the active buffer to
an external filter program then replaces the lines in the buffer with the
output from the filter program. "filter" accepts 3 arguments. The first
2 arguments must evaluate to fixnums. The two numbers inclusively
specify the range of lines to be sent to the filter program. The first
index does not have to be less than the second index. The lines are
always processed in ascending order regardless of how the range was
specified. If any of the lines in the specified range do not exist,
evaluation stops. The third argument must evaluate to a string
containing the command to launch the filter. The command is passed to
/bin/sh for interpretation.
Upon success, "filter" returns the number of lines read from the stdout
of the child process. Errors stop evaluation.
filter_server: (filter_server expr1 expr2 expr3 expr4)
The "filter_server" library function sends a range of lines in the active
buffer to a TCP or UNIX domain server and replaces the lines in the
buffer with the server's response. "filter_server" accepts 4 arguments.
The first 2 arguments must evaluate to fixnums that inclusively specify
the range of buffer lines to be sent to the server. If the first
argument is greater than the second, the lines are sent to the server in
reverse order.
The third and fourth arguments are passed to the "child_open" intrinsic.
See the entry in this manual for that function for what these 2 arguments
can be. "filter_server" returns the number of lines read back from the
server.
> (open)
0
> (insert 1 (concat "GET / HTTP/1.0" (char 10)) 0)
1
> (insert 2 (char 10) 0)
1
> (filter_server 1 2 "www.mammothcheese.ca" 80)
306
remove_http_stuff: (remove_http_stuff)
The "remove_http_stuff" library function accepts no arguments. If the
current buffer contains an HTTP response, "remove_http_stuff" removes the
http header and merges a chunked response body.
write: (write expr1 expr2 expr3 expr4 [expr5])
The "write" intrinsic writes lines from the active buffer to a file.
"write" accepts 4 or 5 arguments. The first 2 arguments must evaluate to
positive fixnums that inclusively specify a range of lines to be written.
The third argument must evaluate to a string naming the file to be
written to. The fourth argument must evaluate to a fixnum. A non-zero
value instructs "write" to lock the file. A value of 0 instructs "write"
to not lock the file. The optional fifth argument must evaluate to a
fixnum. A non-zero value instructs "write" to append lines to the file
if it exists. A value of 0 instructs "write" to overwrite an existing
file. In both cases, if the file does not exist, a new file is created.
If the fifth argument is not present, an implicit fifth argument of 0 is
assumed. Empty files can be created by passing 0 for both the first and
second arguments. "write" creates files with mode 644.
The first line number argument does not have to be less than the second
line number argument, but the lines in the region are written to the file
in ascending order regardless of how the region was specified.
Whitespace in the filename can either be literally present or represented
with the \t and \b escapes. If you wish to use a literal \b or \t in
the filename, escape the backslash itself and use \\\\b or \\\\t instead.
On success, "write" returns the number of lines written. If an error
occurs when opening the file, "write" returns a string describing the
error. Other errors stop evaluation.
read: (read expr1 expr2)
The "read" intrinsic inserts all the lines from a file into the active
buffer. "read" accepts 2 arguments. The first argument must evaluate to
a fixnum specifying the line number of the line after which to insert the
new lines. If the buffer is empty, the first argument must be 0, or an
error is generated. To insert lines at the beginning of the buffer, the
first argument must be 0. On success, "read" returns the number of lines
read. If the file doesn't exist, "read" returns -1. If access is is
denied, "read" returns -2 . On other errors of the read() system call,
"read" returns a string describing the error. Other errors stop
evaluation.
Whitespace in the filename can either be literally present or represented
with the \t and \b escapes to represent the tab and the space character,
respectively. If you wish to use a literal \b or \t in the filename,
escape the backslash itself and use \\\\b or \\\\t instead.
empty: (empty)
The "empty" intrinsic accepts no arguments and removes all data from the
active buffer.
slice: (slice expr1 expr2 expr3 expr4 expr5)
The "slice" intrinsic returns part of a line in the active buffer or a
description of part of a line. "slice" accepts 5 arguments that must
evaluate to numbers. The first argument specifies the index value of the
line to be sliced in the buffer. The second argument specifies the
character index where the slice starts. The third argument specifies the
length of the slice in characters. If the length argument is 0, it is
interpreted as meaning, "to the end of the line." The fourth argument
specifies how tabs are expanded. For example, a fourth argument of 3
indicates that tabstops are considered to occur every three columns.
The fifth argument specifies what "slice" returns. A value of 0
indicates that the caller wishes to receive the specified slice as a
string. A value of 1 indicates that the caller wishes to receive a two-
element list describing the specified slice. The first element of this
list is the length of the slice in characters, which can be less than the
specified length if the specified length extended past the end of the
line. The first element describes the actual length of the slice in the
buffer before tab expansion. The second element is the number of extra
characters that would be added to the line during tab expansion from the
beginning of the line to the end of the specified slice.
find: (find expr1 expr2 expr3 expr4 expr5)
The "find" intrinsic searches a specified range of lines in the active
buffer for a match of a regular expression. "find" accepts 5 arguments.
The first 3 arguments and the 3 argument must evaluate to fixnums. The
fourth argument must evaluate to a compiled regular expression. The
first argument specifies the direction of the search. A positive value
causes the search to proceed forward in the buffer. A negative value
causes the search to proceed backwards in the buffer. The second
argument is the line number at which to start the search. The third
argument is the character position within the line at which to start the
search. Lines in the buffer are numbered from 1. Characters positions
are numbered from 0. The fifth argument specifies if the search should
"wraparound". A non-zero value enables wraparound. 0 disables
wraparound.
The fourth argument is the compiled regular expression to search with. A
match starting exactly at the specified starting place is ignored, and
the position of the next non-overlapping match is sought. Newlines are
temporarily removed from the end of buffer lines before matching. ^$
matches empty lines.
"find" returns a list of 3 numbers. If a match was found, the first
element is the index of the line containing the match. The second
element is the character position of the start of the matched text. The
third element is the length in characters of the match. If no match is
found, all three values are zero.
> (open)
0
> (insert 1 "this is the first line in the buffer." 0)
1
> (set 'f (find 1 1 0 (regcomp "buffer") 0)
(1 30 7)
> (substring (retrieve (car f)) (cadr f) (car (cddr f)))
"buffer"
The following function counts the number of blank lines in the buffer.
(set 'blank
(lambda ()
(let ((idx 1)
(regexp (regcomp "^[\b\t]*$"))
(count 0))
(while (setq idx (car (find 1 idx 0 regexp 0)))
(inc count))
count)))
buffer: (buffer)
The "buffer" intrinsic accepts no arguments and returns the buffer number
of the active text buffer. "buffer" returns -1 if no buffers are open.
buffers: (buffers)
The "buffers" intrinsic accepts no arguments and returns a list of the
buffer numbers of all open buffers. If no buffers are open, "buffers"
returns the empty list.
switch: (switch expr)
The "switch" intrinsic makes a specified buffer the active buffer.
"switch" accepts 1 argument that must evaluate to a fixnum specifying the
buffer number of an open buffer. "switch" makes that buffer the active
buffer. Errors stop evaluation.
setmark: (setmark expr1 expr2)
The "setmark" intrinsic bookmarks a line in the active buffer. "setmark"
accepts 2 arguments. The first argument must evaluate to an atom. The
atom names the bookmark. The second argument must evaluate to a fixnum
that is a valid line number line in the active buffer. On success,
"setmark" returns 1. The mark is adjusted after insertions and deletions
in to track the marked line. If the marked line is subsequently deleted,
bookmarks pointing to that line are set to -1.
getmark: (getmark expr1)
The "getmark" intrinsic is used to retrieve the line number of a marked
line in the active buffer. "getmark" accepts 1 argument that must
evaluate to an atom that names the bookmark. "getmark" returns the line
number of the marked line. If the specified mark has not been set,
"getmark" returns 0. If the marked line has been deleted, "getmark"
returns -1.
transfer: (transfer b1 f1 t1 b2 t2)
The "transfer" intrinsic copies a contiguous range of lines from one
buffer into another. "transfer" accepts 5 arguments that must evaluate
to fixnums. The first argument is the buffer number of the source
buffer. The second and third arguments inclusively specify the starting
and ending lines of the range to be copied. If the second argument is
greater than the third, the lines are copied in reversed order. The
fourth argument is the buffer number of the destination buffer. The
fifth argument is the line number in the destination buffer after which
the copied lines are inserted. To copy lines to the front of the
destination buffer, pass a fifth value of 0. "transfer" returns 1 on
success. Errors stop evaluation.
with_buffer: (with_buffer expr1 expr2 ...)
The "with_buffer" macro temporarily changes the active buffer. The macro
accepts 2 or more arguments. The first argument must evaluate to a
fixnum specifying the buffer number of an open buffer. This buffer is
made the active buffer, and the arguments subsequent to the first are
evaluated. When the last argument has been evaluated, the buffer that
was active prior to the invocation of the macro is made the active buffer
again. "with_buffer" returns the evaluation of the last argument.
version: (version)
The "version" intrinsic accepts no arguments and returns a list of two
fixnums. The first number is the major version number of the
interpreter. The second number is the minor version number.
gensym: (gensym)
The "gensym" intrinsic creates and returns a unique anonymous symbol.
Gensyms cannot be named in code because the lisp reader does not
recognize the print syntax for a gensym. Gensyms are useful when it is
necessary for a macro to create a working variable in its returned
expression. The variable name must not shadow other variable names in
the calling context.
(let ((buff (gensym)))
(set 'with_buffer
(macro (x (y))
(qquote
(let ((,buff (buffer)))
(switch ,x)
(protect ,(cons 'progn y)
(switch ,buff)))))))
libdir: (libdir)
The "libdir" intrinsic accepts no arguments and returns a string
specifying the location of the interpreter's library files. The location
is a fully-qualified directory name.
> (libdir)
"/usr/local/share/munger"
>
strcmp: (strcmp expr1 expr2)
The "strcmp" intrinsic lexigraphically compares two strings. "strcmp"
accepts 2 arguments that must evaluate to strings. "strcmp" returns an
integer greater than, equal to, or lesser than zero indicating that the
first string sorts after, is equivalent to, or sorts before the second
string.
> (strcmp "a" "b")
-1
> (strcmp "b" "a")
1
> (strcmp "a" "a")
0
> (strcmp "A" "a")
-32
substring: (substring expr1 expr2 expr3)
The "substring" intrinsic extracts substrings from strings. "substring"
accepts 3 arguments. The first argument must evaluate to a string. The
second and third arguments must evaluate to fixnums. The second argument
specifies the character position where the desired substring begins. The
third argument is the number of characters to include in the substring.
"substring" returns the specified substring as a new string. The second
index can be zero, which is interpreted to mean "to the end of the
string.
> (substring "foobar" 0 0)
"foobar"
> (substring "foobar" 3 0)
"bar"
> (substring "foobar" 0 3)
"foo"
> (substring "foobar" 0 10)
"foobar"
expand: (expand expr1 expr2)
The "expand" intrinsic performs tab expansion on strings. "expand"
accepts 2 arguments. The first argument must evaluate to a positive
fixnum. The second argument must evaluate to a string. The first value
specifies the periodicity of tabstops. "expand" returns a new string
that has the same content as the original second argument but with tab
characters expanded into an appropriate number of spaces. The number of
spaces that result from each expansion depend upon the position of the
tab character in a line. An expansion always contains at least one space
character but can contain up to expr1 space characters. The expansion of
tabs occurring earlier in expr2 influences the expansion of tabs
occurring later in expr2.
lines: (line)
The "lines" intrinsic accepts no arguments and returns the number of
lines on the terminal device. If the interpreter is not running on a
terminal device, a meaningless value is returned.
cols: (cols)
The "cols" intrinsic accepts no arguments and returns the number of
columns on the terminal device. If the interpreter is not running on a
terminal device, a meaningless value is returned.
exit: (exit)
The "exit" interpreter accepts 1 argument that must evaluate to a fixnum.
"exit" causes the interpreter to exit with its argument as the exit
status.
complete: (complete expr)
The "complete" intrinsic performs filename completion. "complete"
accepts 1 argument that must evaluate to a string that partially names an
entity in the file system. "complete" returns a list of 1 or more
strings. The first element of the list is the same as the argument if
the completion algorithm cannot add more characters to it. If more than
1 element is present in the list, more characters can be added to the
argument, but it did not unambiguously name a file. In this case, the
subsequent list elements are preformatted lines of text containing all
the possible completions for the first element organized into a table the
width of the terminal device.
> (complete "/usr/share/pe")
("/usr/share/perl/man/" "./ ../ man3/ whatis cat3/
")
A leading ~ in the argument to "complete" triggers home directory
abbreviation expansion. "complete" does not complete an incompletely
named home directory.
input: (input expr1 expr2)
The "input" intrinsic reads data from a process into the active buffer.
"input" accepts 2 arguments. The first argument must evaluate to a
fixnum that specifies the line number to insert the new data after. The
second argument must evaluate to a string specifying the command line to
pass to the shell. On success, "input" returns the number of lines read.
If the child shell cannot find the specified program or the process exits
prematurely, "input" returns 0. Other errors stop evaluation.
Whitespace in the filename can either be present literally or represented
with the \t and \b escapes. If you wish to use a literal \b or \t in the
filename, you must escape the backslash itself and use \\b or \\t
instead.
output: (output expr1 expr2 expr3)
The "output" intrinsic writes content from the active buffer to a
process. "output" accepts 3 arguments. The first 2 arguments must
evaluate to positive fixnums that inclusively specify the range of lines
to be written. The first line number does not have to be less than the
second, but the range of lines are written to the child process in
ascending order regardless of how the range was specified. The third
argument must evaluate to a string that contains the command line to be
passed to the shell. on success, "output" returns the number of lines
written. If the child shell cannot find the specified program or the
process exits prematurely, "output" returns 0. Other errors stop
evaluation.
Whitespace in the filename can either be present literally or represented
with the \t and \b escapes. If you wish to use a literal \b or \t in the
filename, you must escape the backslash itself and use \\b or \\t
instead.
system: (system expr1)
The "system" intrinsic passes a command to the shell for execution.
"system" accepts 1 argument that must evaluate to a string containing the
shell command. "system" returns the exit status of the shell. The exit
status is 127 if execution of the shell fails. The exit status is -1 if
fork() or waitpid() fails.
maxidx: (maxidx)
The "maxidx" intrinsic accepts no arguments and returns the highest
possible buffer line number that the interpreter can use.
chdir: (chdir expr1)
The "chdir" intrinsic changes the current working directory. "chdir"
accepts 1 argument that must evaluate to a string that names the new
current working directory. On success, "chdir" returns 1. On error,
"chdir" returns a string describing the error.
table: (table)
The "table" intrinsic returns a new associative array. Errors stop
evaluation.
hash: (hash expr1 expr2 expr3)
The "hash" intrinsic inserts a key/value mapping into a table. "hash"
accepts 3 arguments. The first argument must evaluate to the table to be
modified. The second argument must evaluate to the atom that is the key.
The third argument can evaluate to any object that is the value. "hash"
returns the result of evaluating the third argument.
> (set 't (table))
> (hash 'zero "zero")
"zero"
keys: (keys expr1)
The "keys" intrinsic accepts 1 argument that must evaluate to a table and
returns a list of all the objects used as keys in the table. If the
table is empty, "keys" returns the empty list.
> (set 't (table))
> (hash t "0" "zero")
"zero"
> (hash t "1" "one")
"one"
> (keys t)
("1" "0")
values: (values expr1)
The "values" intrinsic accepts 1 argument that must evaluate to a table
and returns a list of all of the values stored in the table. If the
specified table is empty, "values" returns the empty list.
> (set 't (table))
> (hash t "0" "zero")
"zero"
> (hash t "1" "one")
"one"
> (hash t "2" "two")
"two"
> (values t)
("two" "zero" "one")
unhash: (unhash expr1 expr2)
The "unhash" intrinsic removes a key/value mapping from a table.
"unhash" accepts 2 arguments. the first argumentmust evaluate to the
table. The second argument must evaluate to the key of the pair to be
removed. "unhash" returns the result of evaluating the second argument.
> (set 't (table))
> (hash t "0" "zero")
"zero"
> (unhash t "0")
0
> (keys t)
()
lookup: (lookup expr1 expr2)
The "lookup" intrinsic retrieves an object associated with an atom from a
table. "lookup" accepts 2 arguments. The first argument must evaluate
to the table. The second argument must evaluate to the atom that is the
key. If an object is associated with the key in the specified table,
"looup" returns object. Otherwise, "lookup" returns the empty list.
There is no way to tell the difference between a key with no association
and a key associated with the empty list.
> (set 't (table))
> (hash t "1" "one")
"one"
> (hash t "0" "zero")
"zero"
> (lookup t "1")
"one"
> (lookup t "0")
"zero"
> (lookup t "2")
()
sqlite_open: (sqlite_open expr)
The "sqlite_open" intrinsic opens a SQLite database file. "sqlite_open"
accepts 1 argument that must evaluate to a string nameing the file for
the database. The database is created if it does not exist. On success,
"sqlite_open" returns the opened database object. On error,
"sqlite_open" returns a string describing the error. Database objects
are constants that evaluate to themselves.
sqlite_close: (sqlite_close expr)
The "sqlite_close" intrinsic closes an open SQLite database.
"sqlite_close" accepts 1 argument that must evaluate to an open database.
"sqlite_close" returns 1 if the database was open. Otherwise,
"sqlite_close" returns 0.
sqlite_exec: (sqlite_exec expr1 expr2)
The "sqlite_exec" function executes SQL commands on an SQLite database.
"sqlite_exec" accepts 2 arguments. The first argument must evaluate to
the database. The second argument must evaluate to a string specifying
the SQL query. On success, "sqlite_exec" returns a list. If the SQL
does not return data, "sqlite_exec" returns the empty list. Otherwise,
"sqlite_exec" returns a list of lists of strings. The first sublist
contains the column keys. Each subsequent sublist contains 1 row of
returned data. A null database value is represented by an empty string.
On error, "sqlite_exec" returns a string describing the error.
sqlite_prepare: (sqlite_prepare db sql)
The "sqlite_prepare" intrinsic compiles a SQL statement.
"sqlite_prepare" accepts 2 arguments. The first argument must evaluate
to database object. The second argument must evaluate to a string
containing the SQL query. On success, "sqlite_prepare" returns a
compiled SQL object. On error, "sqlite_prepare" returns a string
describing the error. Compiled sql objecta opaque constant atoms.
> (setq db (sqlite_open "document.db"))
> (setq sql (sqlite_prepare "SELECT path FROM document WHERE parent = 0"))
sqlite_bind: (sqlite_bind sql index text)
SQL queries compiled by "sqlite_prepare" can contain parameter references
of the forms ? and ?NNN where NNN is a number. "sqlite_bind" sets or
changes the values bound to parameters. Only strings and fixnums can be
parameterized. "sqlite_bind" accepts 3 arguments. The first argument
must evaluate to a compiled SQL statement. The second argument must
evaluate to the position of the parameter to be substituted. Parameter
positions are number from 1. The third argument must evaluate to a
string containing the text to be bound. Upon success, "sqlite_bind"
returns 1. On error, "sqlite_bind" returns a string describing the
error.
Note that "sqlite_bind" must be invoked on a SQL statement after a call
to "sqlite_prepare" or "sqlite_reset", and before any call to
"sqlite_step".
> (setq db (sqlite_open "example.db"))
> (setq sql (sqlite_prepare db "SELECT name FROM employees WHERE job = ?"))
> (sqlite_bind sql 1 "supervisor")
1
> (for (((setq more (sqlite_step sql)))
(more)
((setq more (sqlite_step sql))))
>> (print (sqlite_row sql))
>> (newline))
("Bob")
> (sqlite_reset sql)
1
> (sqlite_bind sql 1 "technician")
1
> (for (((setq more (sqlite_step sql)))
(more)
((setq more (sqlite_step sql))))
>> (print (sqlite_row))
>> (newline)
("Sally")
("Jeffrey")
("Boodles the cat")
("George")
sqlite_step: (sqlite_step sql)
The "sqlite_step" intrinsic queries a database with a compiled SQL
object. "sqlite_step" generates 1 row of the result set. "sqlite_step"
accepts 1 argument that must evaluate to a compiled SQL object. If a row
of data has been generate, "sqlite_step" returns 1. If the data in the
result set has been exhausted, "sqlite_step" returns 0. On error,
"sqlite_step" returns a string describing the error. If "sqlite_step"
returns 1, then "sqlite_row" can be invoked on the compiled SQL object to
retrieve the generated data. Further invocations of "sqlite_step"
generate data for successive rows of the result set, until the result set
has been exhausted.
sqlite_row: (sqlite_row sql)
The "sqlite_row" intrinsic is called after a successful invocation of
"sqlite_step" to retrieve a row of data from the result set. "sqlite_row"
accepts 1 argument that must evaluate to a compiled SQL object that has
had "sqlite_step" invoked on it. On success, "sqlite_row" returns a list
of strings. The strings are the column data for a row of the result set.
On error, "sqlite_row" returns a string describing the error.
> (setq db (sqlite_open "document.db"))
> (setq sql (sqlite_prepare "SELECT * FROM table1"))
> (for (((setq more (sqlite_step sql))) (more) ((setq more (sqlite_step sql))))
>> (print (sqlite_row sql))
>> (newline))
("first column first row" "second_column first row")
("first column second row" "second_column second row")
sqlite_reset: (sqlite_reset sql)
The "sqlite_reset" intrinsic resets a compiled SQL object after
"sqlite_step" has returned 0. "sqlite_rest" accepts 1 argument that must
evaluate to a compiled SQL object. On success, "sqlite_reset" returns 1.
On error, "sqlite_step" returns a string describing the error. After a
successful invocation of "sqlite_reset", "sqlite_step" and "sqlite_row"
can be invoked on the compiled SQL object to re-generate the previous
result set again.
sqlite_finalize: (sqlite_finalize sql)
The "sqlite_finalize" intrinsic frees the resources associated with a
compiled SQL object. "sqlite_finalize" accepts 1 argument that must
evaluate to a compiled SQL object. On success, "sqlite_finalize" returns
1. On error, "sqlite_finalize" returns a string describing the error.
"sqlite_finalize" must be called on every compiled sql object associated
with a database before that database is closed by "sqlite_close".
Failure to finalize all compiled statements can cause updates to be
rolled back. The garbage collector calls "sqlite_finalize" on compiled
SQL objects, but implicit deallocation should not be relied upon because
the database object can be garbage collected before its SQL statements.
sqlp: (sqlp expr)
The "sqlp" intrinsic accepts 1 argument that can evaluate to any type of
object. "sqlp" returns 1 if its argument is a compiled SQL object.
Otherwise, "sqlp" returns 0.
stack: (stack [expr])
The "stack" intrinsic creates a new stack object. "stack" accepts 1
optional argument that must evaluate to a positive fixnum specifying a
number of elements to preallocate on the stack. Each element is set to
the empty list. Omitting the argument is the same as invoking (stack 0).
"stack" returns the newly-created stack object.
> (set 's (stack))
> (used s)
0
> (set 's (stack 10))
> (used s)
10
push: (push expr1 expr2)
The "push" intrinsic pushes an object onto the top of a stack. "push"
accepts 2 arguments. The first argument must evaluate to the stack to be
affected. The second argument can evaluate to any lisp object. The
second argument is pushed onto the first. "push" returns the result of
evaluating the second argument.
> (set 's (stack))
> (push s 'foo)
foo
> (index s 0)
foo
pop: (pop expr)
The "pop" intrinsic accepts no arguments and pops an object off the top
of a stack. "pop" accepts 1 argument that must evaluate to the stack to
be affected. The removed object is returned. When the stack is empty,
"pop" returns the empty list. The only way to tell the difference
between an empty stack and one that has the empty list stored in its top
element, is to invoke the "used" intrinsic.
> (set 's (stack))
> (push s 'foo)
foo
> (push s 'bar)
bar
> (pop s)
bar
> (pop s)
foo
> (pop s)
()
> (used s)
0
unshift: (unshift expr1 expr2)
The "unshift" intrinsic adds a new element to the bottom of a stack.
"unshift" accepts 2 arguments. The first argument must evaluate to the
stack to be affected. The second can evaluate to any lisp object. The
second argument is placed at the bottom of the stack. "unshift" returns
the evaluation of the second argument.
> (set 's (assign (stack) '(1 2 3 4)))
> (flatten s)
(1 2 3 4)
> (unshift s 0)
0
> (flatten s)
(0 1 2 3 4)
shift: (shift expr)
The "shift" library function accepts no arguments and removes an element
from the bottom of a stack. "shift" accepts 1 argument that must
evaluate to the stack to be affected. If the stack is empty, "shift"
returns the empty list. Otherwise, "shift" returns the removed element.
> (set 's (assign (stack) '(0 1 2 3 4)))
> (flatten s)
(0 1 2 3 4)
> (shift s)
0
> (shift s)
1
> (flatten s)
(2 3 4)
index: (index expr1 expr2)]
The "index" intrinsic fetches the object stored at a specified index in a
stack. "index" accepts 2 arguments. The first argument must evaluate to
the stack to be accessed. The second must evaluate to a fixnum
specifying the index of the desired element on the stack. The bottom
location on a stack has an index value of 0. The index value of the
object on the top of the stack is 1 less than the number of elements on
the stack. Specifying an out of range index, stops evaluation.
> (set 's (assign (stack) '(a b c)))
> (index s 0)
a
> (index s 2)
c
> (index s 3)
: index 3 out of range.
>
topidx: (topidx expr)
The "topidx" intrinsic accepts 1 argument that must evaluate to a stack.
If the stack is not empty, "topidx" returns the index value of the top
element on the stack. If the stack is empty, "topidx" returns -1.
> (topidx (stack 1))
0
used: (used expr)
The "used" intrinsic accepts 1 argument that must evaluate to a stack.
"used" returns a the number of elements on the stack.
> (used (stack 10))
10
store: (store expr1 expr2 expr3)
The "store" intrinsic places an object into a specified position of a
stack. "store" accepts 3 arguments. The first argument must evaluate to
the stack to be affected. The second argument must evaluate to a fixnum
specifying the element of the stack to overwrite. The third argument can
evaluate to any lisp object. "store" inserts the evaluation of the third
argument into the specified position of the stack. "store" returns the
evaluation of the third argument. Specifying an out of range index
value, stops evaluation.
> (set 's (stack 3))
> (store s 0 'foo)
foo
> (store s 1 'bar)
bar
> (store s 2 'wumpus)
wumpus
> (flatten s)
(foo bar wumpus)
> (store s 3 'error)
: index 3 out of range.
>
clear: (clear expr1 expr2)
The "clear" intrinsic removes elements from the top of a stack. "clear"
accepts 2 arguments. The first argument must evaluate to a stack. The
second must evaluate to a fixum. The second argument specifies the
number of objects to remove from the top of the stack. "clear" discards
the removed elements and always returns 1.
> (setq s (assign (stack) '(1 2 3 4 5)))
> (clear s 4)
1
> (flatten s)
(1)
> (assign s '(1 2 3 4 5))
> (clear s (used s))
1
> (flatten s)
()
assign: (assign expr1 expr2)
The "assign" library function allows the user to load the elements of a
list into a stack starting at the position 0. "assign" returns the
stack.
> (set 's (assign (stack) '(a b c d e)))
> (used s)
5
flatten: (flatten expr)
The "flatten" library function returns the elements of a stack as a list.
"flatten" accepts 1 argument that must evaluate to the stack to be
queried.
> (flatten (assign (stack) '(a b c d e)))
(a b c d e)
child_open: (child_open expr [expr])
The "child_open" intrinsic opens a full-duplex connection to another
process. Only one child process can be running at any one time.
"child_open" accepts 1 or 2 arguments.
With 1 argument, the argument must evaluate to a string specifying a
command to pass to the shell. On success, "child_open" returns 1. On
error, "child_open" returns a string describing the error. If the child
process cannot run the specified program, the child process prints an
error to stderr and exits. The user can invoke "child_running" to verify
the successful launch of the program.
With 2 arguments, "child_open" opens a full-duplex stream with another
process over a TCP or UNIX socket. For TCP connections, the first
argument must evaluate to a string that specifies the remote hostname or
IP address. For UNIX connections, the first argument must evaluate to a
string that names the socket file. For TCP connections, the second
argument must evaluate to a string specifying a service defined in
/etc/services or to a fixnum specifying a port number. For UNIX
connections, the second argument must be 0.
On success "child_open" returns 1. On error "child_open" returns a
string describing the error.
child_running: (child_running)
The "child_running" intrinsic accepts no arguments and returns 1 if a
child process is running or 0 if no child process is running.
child_ready: (child_ready)
The "child_ready" intrinsic accepts no arguments and returns 1 if data is
waiting to be read from a child process or 0 if no data is waiting.
child_wait: (child_wait)
The "child_wait" intrinsic accepts no arguments and blocks until data is
ready to read from a child process. "child_wait" returns 1 when data is
ready to be read. If no child process is running, "child_wait" returns
0.
child_close: (child_close)
The "child_close" intrinsic terminates a child process. "child_close"
accepts no arguments and always returns 1. If there is no child process
running, "child_close" does nothing.
child_eof: (child_eof)
The "child_eof" intrinsic accepts no arguments and closes the writable
half of the connection to a child process. On success, "child_eof"
returns 1. On error, "child_eof" returns an string describing the error.
subsequent attempt to write to the child with "child_write" stops
evaluation. A connection that has had its writable half closed with
"child_eof" still needs to be fully closed by invoking "child_close" on
it.
child_write: (child_write expr1 ...)
The "child_write" intrinsic writes a list of strings to a child process.
"child_write" accepts 1 or more arguments that must evaluate to strings.
"child_write" writes its arguments to the child process. On success,
"child_write" function returns 1. Errors stop evaluation.
> (child_open "/usr/local/bin/munger")
1
> (for (a 1 10)
>> (child_write a (char 10)))
1 ; this is the return value of the "child_write"
>> (print (child_read)))
1
2
3
4
5
6
7
8
9
10
child_read: (child_read)
The "child_read" intrinsic accepts no arguments and reads up to 1024
characters of data emitted by a child process. "child_read" returns the
data as a string. Invoking "child_read" when no child process is
running, stops evaluation. If no data can be read after 30 seconds,
"child_read" returns the empty string. "child_read" returns 0 when EOF
is read from the child process.
> (child_open "munger")
1
> (child_write "(set 'foo 'bar)" (char 10))
1
> (child_read)
"bar
"
1
clearscreen: (clearscreen)
The "clearscreen" intrinsic accepts no arguments. If stdout is connected
to a terminal device, "clearscreen" clears the screen. On success, 1 is
returned. Errors stop evaluation.
clearline: (clearline expr1 expr2)
The "clearline" intrinsic accepts 2 arguments that must evaluate to
fixnums. If stdout is connected to a cursor-addressable terminal device,
"clearline" clears the line specified by the first argument starting at
the column specified by the second argument to the end of the line. The
coordinates for screen lines and columns start at 0. The position 0,0 is
the top leftmost position on the screen. The maximum values for the
terminal device can be ascertained with the "lines" and "cols"
intrinsics. "clearscreen" returns 1 on success. Errors stop evaluation.
goto: (goto expr1 expr2)
The "goto" intrinsic accepts 2 arguments that must evaluate to fixnums
that specify screen coordinates. The first argument is the line. The
second argument is the column. If stdout is connected to a cursor-
addressable terminal device, "goto" places the cursor at the screen
coordinates. On success, "goto" returns 1. Errors stop evaluation.
getchar: (getchar)
The "getchar" intrinsic accepts no arguments. "getchar" does a blocking
read on stdin. "getchar" returns a fixnum in the range of 0-255
representing the character code of the character read. If stdin is a
terminal device, it is taken out of canonical mode so that unbuffered,
uninterpreted data can be read.
"getchar" returns -1 when EOF is read. "getchar" returns -2 if a
SIGWINCH is received by the interpreter. On Error, "getchar" returns a
string describing the error.
pushback: (pushback expr1)
The "pushback" intrinsic accepts 1 argument that evaluate to a fixnum in
the range 0-255. "pushback" causes the next subsequent invocation of
"getchar" to return the argument to "pushback". After returning this
value, subsequent invocations of "getchar" read from the terminal again.
On success, "pushback" returns 1. Errors stop evaluation. Note that
"pushback" does not work with "getchars", only "getchar".
display: (display expr1 expr2 expr3)
The "display" accepts 3 arguments that must evaluate to fixnums. If
stdout is connected to a cursor-addressable terminal device, "display"
prints buffer lines, one per screenline, starting with the buffer line is
specified by the first argument and continuing with subsequent buffer
lines. "display" stops printing after it has reached that last line on
the screen but 1 or or until it runs out of buffer lines. If "display"
runs out of lines, it prints single tilde characters on each of the
remaining screenlines except for the last. If the first argument is 0,
"display" prints a full screen of tildes and returns. On success,
display returns 1. Errors stop evaluation.
The second argument specifies a buffer column to start printing at. If
non-zero, only the portions of the lines from the specified column onward
is printed. The second argument does not specify a screen column but a
buffer column. Tab expansion is performed before the slice is taken.
Slices are printed starting at screen column 0. Lines longer than the
terminal width are truncated to the terminal width.
The third argument specifies the tabstop periodicity. Any tabs found in
the specified lines is expanded according to this value before truncation
and printing.
boldface: (boldface)
The "boldface" intrinsic turns on boldface mode of the terminal connected
to stdout. "boldface" accepts no arguments and always returns 1.
normal: (normal)
The "normal" intrinsic turns off boldface mode and resets the colors of
the terminal connected to stdout to their default values. "normal"
accepts no arguments and always returns 1.
fg_black:
fg_red:
fg_green:
fg_yellow:
fg_blue:
fg_magenta:
fg_cyan:
fg_white:
bg_black:
bg_red:
bg_green:
bg_yellow:
bg_blue:
bg_magenta:
bg_cyan:
bg_white:
These sixteen intrinsics set the foreground or background color of the
terminal connected to stdout to the specified color. These intrinsics
accept no arguments and always return 1.
hide: (hide)
The "hide" intrinsic accepts no arguments. If stdout is connected to a
terminal device capable of having its cursor made invisible, "hide" hides
the cursor. "hide" returns 1.
show: (show)
The "show" intrinsic accepts no arguments. If stdout is connected to a
terminal device capable of having its cursor made invisible, "show" shows
the cursor. "show" returns 1.
pause: (pause expr1)
The "pause" intrinsic accepts 1 argument that must evaluate to a fixnum
no larger than 999999. This value specifies a span of microseconds for
the interpreter to sleep. The interpreter wakes when data is waiting on
stdin or when the time value has expired. "pause" returns 1.
scrollup: (scrollup)
The "scrollup" intrinsic accepts no arguments. If the device connected
to stdin is cursor-addressable, "scrollup" scrolls the screen lines
upward by one line. The top line is lost. The bottom line becomes
blank. "scrollup" returns 1
scrolldn: (scrolldn)
The "scrolldn" intrinsic accepts no arguments. If the device connected
to stdin is cursor-addressable, "scrolldn" scrolls the screen lines
downward by one line. The bottom line is lost. The top line becomes
blank. "scrolldn" returns 1
insertln: (insertln)
The "insertln" intrinsic accepts no arguments. If the device connected
to stdin in cursor-addressable, "insertln" scrolls the lines on the
screen from the line the cursor is on to the bottom line on the screen,
inclusive, downward by one line. The line the cursor is on is cleared.
The bottom line on the screen is lost. "insertln" returns 1.
printer: (printer)
The "printer" intrinsic accepts no arguments and turns on the lisp
printer. The result of evaluating an expression at toplevel is discarded
unless the printer is turned on. The printer is turned on by default.
"printer" returns 1.
noprinter: (noprinter)
The "noprinter" intrinsic accepts no arguments and turns off the lisp
printer. "noprinter" return 1.
shexec: (shexec expr)
The "shexec" intrinsic load a new process image. "shexec" accepts 1
argument that must evaluate to a string containing a command to pass to
the shell. "shexec" calls the execv() system call to run the shell
(/bin/sh -c) with the command. On success, the interpreter process is
abandoned, and the shell process runs with the same process id. The
shell replaces the interpreter. If the new process image cannot be exec-
ed, "shexec" returns a string describing the error.
exec: (exec expr ...)
The "exec" intrinsic loads a new process image. The function accepts 1
or more arguments that must evaluate to strings. The arguments are
interpreted as the lexical components of a command line. "exec" calls
the execv() system call with the command. On success, the interpreter
process is abandoned, and the new process runs with the same process id.
If the new process image cannot be exec-ed, then "exec" returns a string
describing the error.
truncate: (truncate expr)
The "truncate" intrinsic alters the length of a file connected to the
standard output of the interpreter. "truncate" accepts 1 argument that
must evaluate to a an integer that specifies the new length of the file.
If the length is greater than the length of the file, the file is
extended and the extended portion filled with zeros. On success,
"truncate" returns 1. On error, "truncate" returns a string describing
the error.
> (with_output_file_appending "HOW_TO_EXTEND_IT"
>> (when (writelock)
>>> (truncate 100)))
1
> (with_input_file "HOW_TO_EXTEND_IT"
>> (setq line (getchars 1000)))
"ADDING INTRINSICS TO THE INTERPRETER
------------------------------------
Under the hood, Munger is"
> (length line)
100
dynamic_let: (dynamic_let (symbol expr) expr1 [expr2...])
Intrinsic "dynamic_let" creates bindings with dynamic scope. The
bindings created by "dynamic_let" cannot be captured by closures. A
lexical binding of the same name as a dynamic binding shadows the dynamic
binding. A binding in an exterior "let" expression can shadow the
binding in an interior "dynamic_let". The intrinsic accepts 2 or more
arguments. The first argument is not evaluated and must be a two-element
list consisting of a symbol followed by any expression. The expression
is evaluated in the current scope and the result is bound to the symbol
for the duration of the "dynamic_let". The remaining arguments are then
evaluated. When the expression terminates the dynamic binding is
removed. "dynamic_let" returns the last evaluation.
> (defun f () a)
> (dynamic_let (a 10)
>> (f))
10
> (f)
evaluate: symbol a not bound.
f: error evaluating body expression 1.
> (defun a (x) 'foobar)
> (defun g (x) (a x))
> (dynamic_let (a (lambda (x) x))
>> (g 23))
23
> (g 23)
foobar
; Exterior "let" is shadowing interior "dynamic_let":
> (let ((a 12))
>> (dynamic_let (a 10)
>>> (print a)
>>> (newline)))
12
1 ; return value of "newline"
basename: (basename expr)
The "basename" intrinsic returns the last portion of a path in the file
system. "basename" accepts 1 argument that must evaluate to a string and
returns a string. The path specified by the argument string does not
have to exist in the filesystem. "basename" is a string manipulation
function only.
(basename "/usr/local/bin/munger")
"munger"
dirname: (dirname expr)
The "dirname" intrinsic returns the directory portion of a path in the
file system. "dirname" accepts 1 argument that must evaluate to a string
and returns a string. The path specified by the argument string does not
have to exists in the filesystem. This is a string manipulation function
only.
(dirname "/usr/local/bin/munger")
"/usr/local/bin"
chmod: (chmod expr1 expr2)
The "chmod" intrinsic changes the permissions of a file. "chmod" accepts
2 arguments that must evaluate to strings. The first argument must be a
new mode specification of the form accepted by chmod(1). The second
argument must evaluate to the filename of the file. On success, "chmod"
returns 1. On error, "chmod" returns a string describing the error.
chown: (chown expr1 expr2 expr3)
The "chown" intrinsic changes the owner and group of a file. "chown"
accepts 3 arguments that must evaluate to strings. The first argument is
be the name of the new owner or the empty string if the owner is not to
be changed. The second argument is the name of the new group or the
empty string if the group is not to be changed. The third argument is
the name of the file. On success, "chown" returns 1. On error, "chown"
returns a string describing the error. Only the superuser can change the
ownership of files.
crypt: (crypt expr)
The "crypt" intrinsic is a frontend to the crypt(3) library function.
"crypt" accepts 1 argument that must evaluate to a string. "crypt"
encrypts the argument using the default scheme used to encrypt passwords
in the user database. "crypt" returns the encrypted string. Errors stop
evaluation.
checkpass: (checkpass expr1 expr2)
The "checkpass" intrinsic verifies a user and password pair are correct.
"checkpass" accepts 2 arguments that must evaluate to strings. The first
argument specifies the user name. The second argument specifies the
password of the user. The function always returns 0 unless the euid of
the interpreter is 0 (the superuser). When the euid is 0, "checkpass"
returns 1 if the user name and password are correct or 0 if they are not.
setuid: (setuid expr)
The "setuid" intrinsic changes the uid and euid of the interpreter
process. "setuid" accepts 1 argument that must evaluate to a string
specifying the user. Unless the euid of the interpreter is 0 (the
superuser), "setuid" returns a string describing an error. If the euid
is 0 and the requested user exists, "setuid" changes the interpreter to
the specified user and returns 1. It is not possible to switch back to
the superuser after invoking "setuid" to become a non-privileged user.
seteuid: (seteuid expr)
The "seteuid" intrinsic changes the euid of the interpreter process.
"seteuid" accepts 1 argument that must evaluate to a string specifying
the user. On success, "seteuid" returns 1. On error, "seteuid" returns
a string describing the error. The euid can be switched between the real
uid and the set-user-id of a set-user-id interpreter. If the interpreter
is not running setuid, then the uid, the euid, and the saved set-user-id
are the same and it is not possible to change the euid.
getuid: (getuid)
The "getuid" intrinsic accepts no arguments and returns a two element
list consisting of the name of the real user of the interpreter followed
by the numerical uid of the user. On error, "getuid" returns the empty
list.
setgid: (setgid expr)
The "setgid" intrinsic is changes the gid of the interpreter process.
"setgid" accepts 1 argument that must evaluate to a string specifying the
group. On success, "setgid" returns 1. On error, "setgid" returns a
string describing the error.
setegid: (setgid expr)
The "setegid" intrinsic changes the effective gid of the interpreter
process. "setegid" accepts 1 argument that must evaluate to a string
specifying the group. On success, "setegid" returns 1. On error,
"setegid" returns a string describing the error. The egid can be
switched between the real gid and the saved set-group-id of a set-group-
id interpreter. If the interpreter is not running set-group-id, both the
saved set-group-id and the real gid are the same.
geteuid: (geteuid)
The "geteuid" intrinsic accepts no arguments and returns a two element
list consisting of the name of the effective user of the interpreter
followed by the numerical uid of that user. On error, "geteuid" returns
the empty list.
getgid: (getgid)
The "getgid" intrinsic accepts no arguments and returns a two element
list consisting of the name of the primary group of the user of the
interpreter followed by the numerical gid of that group. On error,
"getgid" returns the empty list.
seek: (seek expr1 expr2 expr3)
The "seek" intrinsic moves the file pointer of a file connected to one of
the standard descriptors. "seek" accepts 3 arguments. The first
argument must evaluate to a standard descriptor: 0, 1, or 2. The second
argument must evaluate to a fixnum specifying the number of characters by
which the file pointer should be adjusted. The third argument must
evaluate to one of the following three strings: "SEEK_SET", "SEEK_CUR",
or "SEEK_END". "SEEK_SET" indicates the seek operation should seek from
the beginning of the file. "SEEK_CUR" indicates the seek operation
should seek from the current position of the file pointer. "SEEK_END"
indicates the seek operation should seek from the end of the file. On
success, "seek" returns the number of characters from the beginning of
the file corresponding to the new location of the file pointer. Errors
stop evaluation. Seeking past the end of a file connected to stdout
causes the file to be extended with the new portion filled with zeroes.
getchars: (getchars expr [expr])
The "getchars" intrinsic reads a number of characters from the stream
connected to stdin. "getchars" accepts 1 or 2 arguments that must
evaluate to fixnums. The first argument specifies the number of
characters to read. The second argument specifies a timeout value in
seconds. On success, "getchars" returns the characters read a string.
Errors stop evaluation. If "getchars" reads EOF or a timeout occurs,
less than the desired amount of characters can be returned. If EOF is
encountered, any successive invocation of the "getchars" returns fixnum
0. Invoking "getchars" with a first argument of 0 causes it to
immediately return the empty string without reading from stdin.
Mixing calls to "getline" and "getchars" results in unexpected results,
as "getline" performs its own input buffering. You can mix calls to
"getchars" with calls to "getline_ub".
The presence of a timeout value causes "getchars" to operate as follows.
The function calls the read() system call to read a character a time
until the desired number of characters or EOF has been read. If any
invocation of read() takes longer than the number of seconds specified by
the timeout value, read() is interrupted, and "getchars" returns all the
characters read so far. If no characters have been read, "getchars"
returns the empty string. When invoked without a timeout value but with
a positive first argument, "getchar" blocks indefinitely until it can
read at least one character or EOF. "getchars" then returns a non-empty
string or 0 on EOF.
When reading from a terminal device in canonical mode, when a timeout
value has been specified, the empty string can be returned even though
the user has typed some characters, because the terminal driver does not
return any character data to the interpreter in canonical mode until a
carriage return or a newline is input.
readlock: (readlock)
The "readlock" intrinsic obtains a shared lock on a file connected to
stdin. "readlock" accepts no arguments. On success, "readlock" returns
1. If the file is already locked, "readlock" returns 0. If the lock
cannot be obtained for another reason, "readlock" returns a string
describing the error.
writelock: (writelock)
The "writelock" intrinsic obtains an exclusive lock on a file connected
to stdout. "writelock" accepts no arguments. On success, "writelock"
returns 1. If the file is already locked, "writelock" returns 0. If the
lock cannot be obtained for any other reason, "writelock" returns a
string describing the error.
unlock: (unlock expr)
The "unlock" intrinsic releases a lock obtained by the "readlock" or
"writelock" intrinsics. "unlock" accepts 1 argument that must evaluate
to either 0 or 1 specifying the descriptor on which the lock is held.
hostname: (hostname)
The "hostname" intrinsic accepts no arguments. On success, "hostname"
returns the name of host as a string. On error, "hostname" returns a
string describing the error.
symlink: (symlink expr1 expr2)
The "symlink" intrinsic creates a symbolic link to a filesystem entity.
"symlink" accepts 2 arguments that must evaluate to strings. The first
argument names the filesystem entity. The second argument names the
symbolic link. On success, "symlink" returns 1. On error, "symlink"
returns a string describing the error.
gecos: (gecos expr)
The "gecos" intrinsic queries the user database for the value of the
gecos field for a specified account. "gecos" accepts 1 argument that
must evaluate to a string that names a user. If the user exists, "gecos"
returns the gecos field as a string. If the user does not exist, "gecos"
returns the empty string. The gecos field is used to store personal
information about the user. Traditionally, the field held 4 comma-
separated fields containing the user's full name, office location, work
phone number, and home phone number, but the system does not care what
goes into the gecos field. Most administrators nowadays place the user's
full name in the gecos field.
record: (record expr)
The "record" intrinsic creates a fixed-size unidimensional array.
"record" accepts 1 argument that must evaluate to fixnum specifying the
size of the array. "record" returns the new record. The items of the
record are set to the empty list. Errors stop evaluation.
getfield: (getfield expr1 expr2)
The "getfield" intrinsic retrieves an item from a record. "getfield"
accepts 2 arguments. The first argument must evaluate to a record. The
second argument must evaluate to a fixnum specifying the index of the
desired item. On success, "getfield" returns the object at the index in
the record. An out of range index stops evaluation.
setfield: (setfield expr1 expr2 expr3)
The "setfield" intrinsic inserts an object into a record. "setfield"
accepts 3 arguments. The first argument must evaluate to the record to
be affected. The second argument must evaluate to a fixnum specifying
the index location to overwrite. The third argument can evaluate to any
lisp object and is inserted into the first argument at the location
specified by the second argument. The evaluated third argument is
returned. An out of range index stops evaluation.
extend: (extend expr1 expr2)
The "extend" intrinsic adds a new binding to the currently-active lexical
environment. "extend" accepts 2 arguments. The first argument must
evaluate to a symbol. The second argument can evaluate to any lisp
object. The symbol is added to the lexical environment and bound to the
evaluation of the second argument. If the symbol exists in the current
lexical environment, the binding is shadowed not replaced. "extend"
returns the evaluation of the second argument.
> (defun fact (n)
>> (extend 'a 1)
>> (while (> n 1)
>>> (setq a (* n a))
>>> (dec n))
>> a)
> (fact 10)
3628800
gc: (gc)
The "gc" intrinsic accepts no arguments and sets the garbage collector to
run on the next evaluation.
dynamic_extent: (dynamic_extent ...)
The "dynamic_extent" intrinsic limits the extent of additions to the
current lexical environment made with the "extend" intrinsic.
"dynamic_extent" accepts 0 or more arguments. If no arguments are
supplied, "dynamic_extent" does nothing and returns 1. If arguments are
supplied, they are evaluated in order, and the evaluation of the last
expression is returned. Evaluation is stopped if no lexical environment
exists at the time of invocation. When "dynamic_extent" finishes, any
additions made to the current lexical environment by the expressions in
the body body are removed.
> (let ((a 10))
>> (extend 'b (* a a))
>> (dynamic_extent
>>> (extend 'c (* b b))
>>> (print c)
>>> (newline))
>> (print (boundp 'c))
>> (newline))
10000 ; first "print"
0 ; second "print"
gc_freq: (gc_freq expr)
The "gc_freq" intrinsic accepts no arguments and changes the rate at
which garbage collection occurs. "gc_freq" accepts 1 argument that must
evaluate to a fixnum specifying a new value for the GC frequency.
Increasing GC frequency causes the interpreter to run faster but consume
more memory. Decreasing GC frequency causes the interpreter to run more
slowly but consume less memory. The default value is 1048576. This
number is the number of internal object allocations permitted between
collections. "gc_freq" returns a fixnum specifying the GC frequency
before "gc_freq" was called. Setting GC frequency to 0 disables garbage
collection.
getpid: (getpid)
getppid: (getppid)
getpgrp: (getpgrp)
tcgetpgrp: (tcgetpgrp)
The "getpid", "getppid", "getpgrp", "tcgetpgrp" intrinsics accept no
arguments. "getpid" returns a fixnum representing the process id of the
interpreter. "getppid" returns a fixnum representing the process id of
the parent process of the interpreter. "getpgrp" returns a fixnum
representing the process group id of the the interpreter's process group.
"tcgetpgrp" returns a fixnum representing the process group that is
currently the foreground process.
"tcgetpgrp" returns 0 if the interpreter is not associated with a
terminal device. On error, "tcgetpgrp" returns a string describing the
error.
setpgid: (setpgid expr1 expr2)
The "setpgrp" intrinsic accepts 2 arguments that must evaluate to
fixnums. The first argument is a process id of a running process. The
second is the process group id of a running process group, or the second
argument is the same as the first argument. "setpgrp" puts the process
specified by the first argument into the process group specified by the
second argument. Upon success, "setpgrp" returns 1. On error, "setpgrp"
returns a string describing the error.
If the first argument is zero, the pid of the interpreter process is used
as the first argument. If the second argument is zero, the first
argument is used for the second argument. New process groups are created
by setting both arguments to the same value. If the affected process is
not already a process group leader, the process becomes the process group
leader of a new process group, and the process group id is the same as
the process id.
tcsetpgrp: (tcsetpgrp expr)
The "tcsetpgrp" intrinsic accepts 1 argument that must evaluate to a
fixnum specifying a process group id. "tcsetpgrp" makes the process
group the foreground process associated with the terminal. On success,
"tcsetpgrp" returns 1. If the interpreter has no associated controlling
terminal, "tcsetpgrp" returns 0. On error, "tcsetpgrp" returns a string
describing the error. You cannot call "tcsetpgrp" when the interpreter
process is a background process unless you block SIGTTOU by invoking
"block".
kill: (kill expr1 expr2)
The "kill" intrinsic accepts 2 arguments. The first argument must
evaluate to a fixnum representing the process id of a running process.
The second argument must evaluate to a fixnum representing a signal
number. "kill" sends the signal specified by the second argument to the
process specified by the first argument. On success, "kill" returns 1.
On error, "kill" returns a string describing the error.
killpg: (killpg expr1 expr2)
The "killpg" intrinsic accepts 2 arguments. The first argument must
evaluate to a fixnum representing the process group id of a running
process group. The second argument must evaluate to a fixnum
representing a signal number. "killpg" sends the signal specified by the
second argument to every process in the process group specified by the
first argument. On success, "killpg" returns 1. On error, "killpg"
returns a string describing the error.
fork: (fork)
The "fork" intrinsic is a wrapper for the "fork" system call. "fork"
accepts no arguments and forks a new interpreter process. "fork" returns
0 to the child interpreter and the process id of the child interpreter to
the parent interpreter. On error, -1 is returned. The interpreter reaps
any child processes that exit unless the "zombies" intrinsic has been
invoked.
forkpipe: (forkpipe expr)
The "forkpipe" intrinsic behaves similarly to the "fork" intrinsic, but
"forkpipe" creates a pipe between the two interpreters. "forkpipe"
accepts 1 argument that must evaluate to a fixnum specifying one of the
standard descriptors: 0, 1, or 2. The argument determines which of the
child interpreter's descriptors is attached to the pipe. If descriptor 1
or 2 is specified, the child interpreter stdin is connected to the pipe.
If descriptor 0 is specified, the child stdout is connected to the pipe.
"forkpipe" returns 0 in the child interpreter and the process id of the
child process in the parent interpreter. If the fork() system call
fails, "forkpipe" returns -1. Errors stop evaluation.
The interpreter reaps any child processes that exit unless the "zombies"
intrinsic has been invoked.
wait: (wait expr1 [expr2])
The "wait" intrinsic reaps a zombie process. When the interpreter
starts-up it is in the nozombies state, which means the interpreter reaps
any zombies of terminated child processes. "wait" is used after
"zombies" has been invoked.
"wait" accepts 1 or 2 arguments. The first argument must evaluate to a
fixnum specifying a process id, 0, -1, or a process group id negated.
This argument is passed as the first argument to the waitpid() system
call. If the argument is a process id, "wait" reaps that process. If
the argument is -1, "wait" reaps any zombie process. If the argument is
0, "wait" reaps any zombie process that belongs to the interpreter's
process group. If the argument is a process group id negated, then
"wait" reaps any zombie child whose process group id is equal to the
absolute value of the argument.
If the second argument is present, it can evaluate to any value. It is a
boolean flag that determines if "wait" blocks. If the second argument is
not present or if it evaluates to a boolean "false" value, AND there are
no stopped or zombie processes that satisfy the "wait" request, BUT there
is at least one running process that satisfies the "wait" request in the
future, THEN "wait" blocks until it can reap a process. Otherwise "wait"
returns immediately.
"wait" returns a 2 or 3 element list.
If "wait" cannot reap a process, "wait" returns a list containing 0 or -1
and the symbol ECHILD. If no second argument was supplied to "wait" or
if the second argument evaluated to a boolean "false" value, the first
element of the list is -1. This means there is no running or zombie
process that can satisfy the "wait" now or in the future. If a "true"
second argument is supplied to "wait", the first element of the returned
list can be either -1 or 0. A value of 0 indicates that there are
processes that can satisfy the "wait" that are still running.
Otherwise, "wait" returns a list containing a fixnum representing the
process id of the reaped process followed by a symbol describing how the
process exited: EXITED, KILLED, or STOPPED. If the second element is
EXITED, the process terminated by calling the "exit" or "_exit" system
calls, and a third element is present in the list that is a fixnum
representing the child's exit status. If the second element is KILLED,
the process was terminated by a signal, and a third element is present
that is a fixnum representing the signal number of the signal that
terminated the process. If the second element is STOPPED, the process
was stopped by a signal and can be started again, and a third element is
present that is a fixnum representing the signal number that stopped the
process.
To ensure that all zombies are reaped, invoke "wait" with an argument of
-1, until it returns (-1 ECHILD).
> (until (eq -1 (car (wait -1)))
zombies: (zombies)
The "zombies" intrinsic accepts no arguments and causes the interpreter
to stop reaping zombie processes. They must be manually reaped with the
"wait" intrinsic. After invocation of "zombies", each invocation of
"fork", "child_open", "with_input_process", "with_output_process", and
"pipe" generates a new process that can be reaped with the "wait"
intrinsic. "input", "output", and "filter" reap their own zombies,
regardless of the setting of zombies state. "zombies" always returns 1.
nozombies: (nozombies)
The "nozombies" intrinsic accepts no arguments and causes the interpreter
to reap zombie child processes. The interpreter starts-up in the
"nozombies" state. "nozombies" always returns 1.
zombiesp: (zombiesp)
The "zombiesp" intrinsic accepts no arguments and returns the value of
the zombies state. It returns 1 if the interpreter is in the "zombies"
state, and 0 otherwise.
glob: (glob)
The "glob" intrinsic accepts 1 argument that must evaluate to a string.
"glob" interprets the string as a shell glob pattern and searches for
matches on the pattern. If matches are found, "glob" returns the matches
in a list of strings. If no matches are found, "glob" returns the empty
list. Errors stop evaluation.
command_lookup: (command_lookup expr)
The "command_lookup" intrinsic accepts 1 argument that must evaluate to a
string. "command_lookup" attempts to find a file that is executable by
the interpreter in the directories specified by the PATH environment
variable. On success, "command_lookup" returns the fully-qualified
filename of the executable. On failure, "command_lookup" returns the
empty string.
> (command_lookup "munger")
"/usr/local/bin/munger"
getstring: (getstring expr)
The "getstring" library function returns the output of an external
process as a string. "getstring" accepts 1 argument that must evaluate
to a command to be passed to the shell. "getstring" returns a string
containing the data that appears on the shell's standard output.
If the interpreter cannot "forkpipe", "getstring" returns -1. If the
"forkpipe" is successful but the "shexec" is not, then "getstring"
returns the empty string.
dec2hex: (dec2hex expr)
The "dec2hex" intrinsic converts a fixnum into a string representing the
number in hexadecimal notation. "dec2hex" accepts 1 argument that must
evaluate to a non-negative value. Negative values stop evaluation.
> (dec2hex 65535)
"FFFF"
hex2dec: (hex2dec expr)
The "hex2dec" intrinsic converts a string representing a number in
hexadecimal notation to a fixnum. The letter characters used in
hexadecimal notation can be in lowercase or uppercase.
> (hex2dec "FfFf")
65535
listen: (listen expr [expr])
The "listen" intrinsic causes the kernel to accept incoming TCP
connections on a specified port. Both IPv4 and IPv6 connections are
accepted. "listen" accepts 1 or 2 arguments. The first argument must
evaluate to either a fixnum specifying the local port or a string naming
a service in /etc/services. If the port is 0, the kernel chooses a port
from the ephemeral ports. The second optional argument must evaluate to
a string specifying the IP address of the local interface. If the second
argument is not present, "listen" accepts connections on all interfaces
of both protocol families.
On success, "listen" returns the port number of the listening socket. On
error, "listen" returns a string describing the error. Only one
listening socket can be active at any time. The listening socket is
closed with the "stop_listening" intrinsic.
listen_unix: (listen_unix expr)
The "listen_unix" intrinsic causes the kernel to accept incoming
connections on a UNIX socket. "listen_unix" accepts 1 argument that must
evaluate to a string specifying the filename of the socket. If the
socket already exists, it is unlinked. On success, "listen_unix" returns
1. On error, "listen_unix" returns a string describing the error.
stop_listening: (stop_listening)
The "stop_listening" intrinsic closes a listening socket opened by
"listen" or "listen_unix". "stop_listening" accepts no arguments.
"stop_listening" returns 1 if a listening socket was open, 0 otherwise.
accept: (accept)
The "accept" intrinsic accepts an incoming TCP connection. "accept" can
only be invoked after "listen" or "listen_unix" has been invoked.
"accept" accepts no arguments and blocks until an incoming connection is
ready. On success, "accept" returns 1. If the interpreter receives a
SIGTERM, "accept" returns -1. On error, "accept" returns a string
describing the error.
When "accept" returns, the stdin and stdout of the interpreter are
redirected onto the incoming connection. Any of the intrinsics that read
and write from those descriptors ("print", "println", "newline",
"getchar", getchars", and "getline") can be used to communicate with the
client. Keep in mind that "accept" works like "pipe" or "redirect" in
that the new streams connected to the affected descriptors "shadow" the
previously connected streams, but the previously-connected streams are
still open in the interpreter. This means you must invoke both (resume
0) and (resume 1) before calling "accept" again, unless you intend to
come back to the previously-accepted connection in the future.
(fatal)
; Echo Server 1
(daemonize "echo1.munger")
(defun service_client ()
(while (setq line (getline))
(print line)
(flush_stdout)))
(when (fixnump (setq err (listen 7)))
(setuid "nobody")
(while (fixnump (setq err (accept)))
(if (not (fork))
(progn
(stop_listening)
(service_client)
(exit 0))
(resume 0)
(resume 1))))
(syslog 'CRITICAL err)
(exit 1)
; Echo Server 2
(fatal)
(daemonize "echo2.munger")
(defun service_client ()
(while (setq line (getline))
(print line)
(flush_stdout)))
(defun process_clients ()
(while (fixnump (setq err (accept)))
(service_client)
(resume 0)
(resume 1)))
(when (fixnump (setq err (listen 7)))
(setuid "nobody")
(catch
(iterate 9
(unless (fork)
(throw 0)))))
(process_clients)
(syslog 'CRITICAL err)
(exit 1)
get_scgi_header: (get_scgi_header)
The "get_scgi_header" intrinsic parses an SCGI header netstring from
standard input. On success, "get_scgi_header" return returns a list of
strings. On error, "get_scgi_header" returns 0. On success, and each
pair of strings in the returned list is a name of an SCGI environment
variable and its value.
send_descriptors: (send_descriptors);
The "send_descriptors" intrinsic accepts no arguments and passes copies
of the interpreter's stdin and stdout descriptors to another interpreter
over a UNIX socket opened by "child_open". On success,
"send_descriptors" returns 1. After "send_descriptors" returns, the UNIX
socket can be closed with (resume 0) and (resume 1). On error,
"send_descriptors" returns a string describing the error.
receive_descriptors: (receive_descriptors)
The "receive_descriptors" intrinsic accepts no arguments and receives
copies of another interpreter's stdin and stdout descriptors over a UNIX
socket opened by "accept". On success, "receive_descriptors" returns 1.
On success, the interpreter's stdin and stdout are connected to the same
sources as the other interpreter's stdin and stdout. After
"receive_descriptors" returns, the UNIX socket can be closed with (resume
0) (resume 1) (stop_listening). On error, "receive_descriptors" returns
a string describing the error.
busymap: (busymap expr)
The "busymap" intrinsic creates a byte array of shared memory for use
with parent and child server processes. "busymap" accepts 1 argument
that must evaluate to a fixnum specifying the length of the array. Only
1 busymap can exist at any time. If a busymap already exists, "busymap"
returns -1. On success, "busymap" returns 1. On error, "busymap"
returns a string describing the error.
See the httpd.munger example web server for usage.
Master server processes request that their children exit by sending them
a SIGTERM with the "kill" intrinsic. If this signal is received by an
interpreter, the next invocation of "accept" causes the interpreter to
exit. If the interpreter is blocked in "accept" at the time of the
arrival of the signal, the interpreter exits immediately. This allows
the slave server to continue processing any established client connection
to completion before exiting.
nobusymap: (nobusymap)
The "nobusymap" intrinsic accepts no arguments and frees a busymap that
was created with "busymap". If no busymap exists, "nobusymap" returns
-1. if the busymap was successfully unmapped, "busymap" returns 1. On
error, "busymap" returns a string describing the error. Each process
that has access to the busymap must call "nobusymap" to completely remove
the shared mapping.
busy: (busy expr)
The "busy" intrinsic sets a byte in a busymap to 1. "busy" accepts 1
argument that must evaluate to a fixnum specifying a position in the
busymap. On success, "busymap" returns 1. If no busymap exists, "busy"
returns -1. An out of range index stops evaluation.
notbusy: (notbusy expr)
The "notbusy" intrinsic sets a byte in a busymap to 0. "notbusy" accepts
1 argument that must evaluate to a fixnum specifying a position in the
busymap. On success, "notbusy" returns 1. If no busymap exists,
"notbusy" returns -1. An out of range index stops evaluation.
busyp: (busyp expr)
The "busyp" intrinsic returns the value of a byte in the busymap.
"busyp" accepts 1 argument that must evaluate to a fixnum specifying an
position in the busymap. On success, "busyp" returns either 0 or 1. 0
indicates the "not busy" state, and 1 indicates the "busy" state. If no
busymap exists, "busyp" returns -1. An out of range index stops
evaluation.
chroot: (chroot expr)
The "chroot" intrinsic accepts 1 argument that must evaluate to a string
and calls the chroot(2) system call with the string as argument. On
success, the initial slash (/) in all pathnames refers to the specified
directory. See the chroot(2) manual page for more details. Upon success
"chroot" returns 1. On error, "chorot" returns a string describing the
error.
daemonize: (daemonize expr)
The "daemonize" intrinsic turns the interpreter into a daemon process.
"daemonize" accepts 1 argument that must evaluate to the name for the
program to use for itself in the system logfile. On success, "daemonize"
returns 1. Errors stop evaluation. If "daemonize" encounters an error
after the standard descriptors are closed, the interpreter writes an
error message to the system log and exits with an exit status of 1.
syslog: (syslog expr expr)
The "syslog" intrinsic sends a message to the system logfile. "syslog"
can only be used after "daemonize" has been invoked. "syslog" accepts 2
arguments. The first argument must evaluate to one of the following set
of symbols indicating the priority of the event being logged: ALERT,
CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG. The /etc/syslog.conf that
ships with FreeBSD at the time this entry in the manual page is being
edited, prevents any message with priority lower than NOTICE of being
logged. The second argument must evaluate to a string containing the log
message. Any % occurring in the message string is escaped with another
%. On success, "syslog" returns 1. On error, an error message is sent
to the system log and the interpreter exits. There is no point in
returning to toplevel in response to an error event because after
"daemonize" has been invoked, the interpreter is no longer capable of
performing terminal I/O.
flush_stdout: (flush_stdout)
The "flush_stdout" intrinsic accepts no arguments and calls fflush() on
the standard output stream. On success, "flush_stdout" returns 0. On
error, "flush_stdout" returns -1. Any buffered data that has not yet
been written to stdout is written to the stream.
getpeername: (getpeername)
The "getpeername" intrinsic accepts no arguments and returns a string
representing the IP address of the host on the other end of the TCP
socket connected to stdin and stdout. On error, "getpeername" returns 0.
base64_encode (base64_encode expr)
The "base64_encode" intrinsic accepts 1 argument that must evaluate to a
string and returns a new string of the argument encoded in base64
encoding.
> (with_input_file "binary.file"
>> (with_output_file "binary.file.base64"
>>> (println "begin-base64 644 binary.file")
>>> (while (setq line (getchars 57))
>>>> (println (base64_encode line)))
>>> (println "====")))
produces the same output as the b64encode system utility invoked as:
b64encode -o binary.file.base64 binary.file binary.file
Base 64 encoding represents 3 bytes of data as 4 printable characters, so
using a line size of 57 causes those lines to expand to 76 characters
after encoding, which is less than the once-customary 80 character limit
on line lengths in an email message.
A more efficient method is to read a larger amount of text and cut up the
lines with "substring":
> (with_input_file "binary.file"
>> (with_output_file "binary.file.base64"
>>> (println "begin-base64 644 binary.file")
>>> (setq line "")
>>> (while (setq segment (getchars 100000))
>>>> (setq line (concat line segment))
>>>> (while (> (length line) 57)
>>>>> (println (base64_encode (substring line 0 57)))
>>>>> (setq line (substring line 57 0))))
>>> (when line (println (base64_encode line)))
>>> (println "====")))
base64_decode (base64_decode expr)
The "base64_decode" intrinsic accepts 1 argument that must evaluate to a
string containing base64-encoded data and returns a new string consisting
of the unencoded data. On error, "base64_encode" returns 0. The
"isatty" intrinsic accepts 1 argument that must evaluate to fixnum
specifying a standard descriptor: 0, 1, or 2. If the specified
descriptor is not connected to a terminal device, "isatty" returns 0. If
the specified descriptor is connected to a terminal device, "isatty"
returns a non-zero fixnum.
sleep: (sleep expr)
The "sleep" intrinsic accepts 1 argument that must evaluate to a fixnum
specifying a number of seconds for the interpreter to sleep. "sleep"
returns when the specified number of seconds has elapsed or a signal is
received by the interpreter. If the specified number of seconds elapses,
"sleep" returns 0. If "sleep" is interrupted by a signal, "sleep"
returns the remaining, unslept number of seconds.
unsigned: (unsigned expr)
The "unsigned" intrinsic accepts 1 argument that must evaluate to a
fixnum and returns a string representing the value of the fixnum
expressed as an unsigned value. This is not the same as the absolute
value of the fixnum. It is analogous to casting an int to an unsigned
int in C.
form_encode: (form_encode expr)
form_decode: (form_decode expr)
The "form_encode" intrinsic accepts 1 argument that must evaluate to a
string and returns a new string containing the argument data x-www-form-
url-encoded. The "form_decode" intrinsic accepts 1 argument that must
evaluate to a string of x-www-form-urlencoded data. "form_decode" returns
a string containing the decoded data.
Fri, Dec 02 2022