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