In order to specify the behaviors upon an error and an interrupt(signal), set an appropriate function to each of the special variables *error-handler* and *signal-handler* in advance. There is no correctable or continue-able error. After analyzing errors you must abort the current execution by reset or appropriate throw to upper level catchers. reset is equivalent to (throw 0 NIL), since EusLisp's top-level creates catch frame named 0.
Error handlers should be programmed as functions with three or four arguments: code msg1 form &optional (msg2). Code is the error code which identifies system defined errors, such as 14 for 'mismatch argument' or 13 for 'undefined function'. These mappings are described in "c/eus.h". msg1 and msg1 are messages displayed to the user. form is the S-expression which caused the error.
Signal handlers should be programmed as functions receiving two arguments: sig and code. Sig is the signal number ranging from 1 to 31, and code is the minor signal code defined in signal-number dependent manners.
^
D (end-of-file) at the top-level terminates eus session.
This is useful when eus is programmed as a filter.
Eval-dynamic is the function to find the dynamic value bound to a symbol used as a let or lambda variable. This is useful for debugging.
eval form &optional environment [function]
apply func &rest args [function]
funcall func &rest args [function]
evalhook hookfunc form &optional env [function]
eval-dynamic variable [function]
eval-when situation &rest forms [special]
declare &rest declarations [special]
proclaim proclamation [function]
warn format-string &rest args [function]
error format-string &rest args [function]
In the multithread EusLisp, special variables are shared among threads and the same *error-handler* is referenced by different threads. To avoid this inconvenience, multithread EusLisp provides the install-error-handler function which installs different error handler for each thread.
lisp::install-error-handler handler [function]
EusLisp's standard top-level read-eval-print loop is controlled by eustop. When EusLisp is invoked, eustop tries to load the file named ".eusrc" in your home directory or the file specified by the EUSRC environment variable. It also tries to load a file named ".eusrc" in the current working directory. So, if you are in your home directory, note that .eusrc is loaded twice. Then EusLisp loads files specified in its argument list. After these loading, eustop enters normal interactive session.
When *standard-input* is connected to user's tty, eustop prints prompt generated by the toplevel-prompt function. The default toplevel-prompt prints "eus$ ". The effect of changing the definition of toplevel-prompt appears when eustop is invoked next time. One way to change the prompt from the first time is to define toplevel-prompt in your .eusrc file.
Inputs are read from *terminal-io* stream. If the input is parenthesized, it is taken as a lisp form and is evaluated by eval. Else if the first symbol of the input line has function definition, the line is automatically parenthesized and evaluated. If no function definition is found, then its special value is examined and the value is printed. If the symbol is unbound, the line is regarded as UNIX command and passed to sh (Bourn's shell). If sh cannot find corresponding unix command, “command unrecognized" message is printed. Thus, eustop works both as a lisp interpreter and as a unix shell. If you do not wish to execute the input as UNIX command, you may escape the form by preceeding a comma ',' at the begining of the line. This is also useful to see the dynamic value binding when an error occurred in the interpretive execution. Since EusLisp adopts lexical scope, we cannot examine the value of local variables outside of the scope unless they are declared special.
If the environment variable, USE_TOP_SELECTOR, is defined, the toplevel input is read in an asynchronous manner using the select library call. The input stream (*standard-input*) is registered to the *top-selector*, which is an instance of the port-selector class, together with the read-eval-print function (repsel) Therefore arrival of key inputs invokes the evaluation of the repsel. This feature is particularly useful when EusLisp is to handle multiple events, i.e., key inputs, X window events, and socket connection requests, at the same time. In order to exploit this asynchronous toplevel interaction, users should never write a code that blocks at the read operation. Instead, the input stream should be registered to the *top-selector* with its handler function by using the :add-port method. The handler function is expected to read from the stream, which is already known ready to return the input without blocking.
Note that Xwindow event handlers are defined to use the *top-selector* implicitly when USE_TOP_SELECTOR is defined, and user programs do not have to call x:window-main-loop at all to catch X events.
Using the time-out of the select call, users may define a timer handler. Each time the select call times out, the function bound to *timer-job* is invoked with no argument. The timer interval is defined by *top-selector-interval*, which is defaulted to 10.0 second. Note that the timer function invokation is not precisely periodic when there are inputs to the *top-selector*.
In the toplevel interaction, each line input is remembered in *history* vector with a sequence number. You can recall a specific input by ! function as if you were in csh. The difference from csh's history is, you need at least one white space between the exclamation mark and the sequence number since ! is a function.
^
D (EOF) terminates EusLisp normally.
To return abnormal termination code to upper level (usually a csh),
use exit with an appropriate condition code.
eustop sets a signal handler only for SIGINT and SIGPIPE, and other signals are not caught. Thus, signals such as SIGTERM or SIGQUIT cause EusLisp to terminate. In order to catch these signals to avoid termination, use unix:signal function to set user-defined signal handlers.
sigint-handler sig code [function]
euserror code message &rest arg [function]
exit &optional termination-code [function]
! &optional (seq 0) [function]
EusLisp compiler is used to speed the execution of Lisp programs. You can expect 5 to 30 times faster execution and notable reduction of garbage collection time elapsed by macro expansion.
Euscomp does optimization for arithmetic operation and vector access. Sometimes proper type declarations are needed to inform the compiler applicability of optimization.
Compile-function compiles functions one by one. Compile-file compiles an entire source file. During the execution of Compile-file, each form in a file is read and evaluated. This may change the current EusLisp environment. For examples, defparameter may set a new value to a symbol and defun may substitute the existing compiled function with its non-compiled version. To avoid these unexpected effects, use the eval-when special form without compile time situation, or use euscomp command to run the compiler as a separate process.
Euscomp is a unix command, which is usually a symbolic link to eus. It recognizes several options. -O flag indicates optimization of the C compiler. Each of -O1,-O2, -O3 indicates optimization level of EusLisp compiler, which is equivalent to proclaiming (optimize 1 or 2 or 3). Each of -S0, -S1, -S2, -S3 set 0,1,2 and 3 to compiler:*safety*. If *safety* is less than 2, no code for checking interrupt is emitted, and you will lose control if the program enters an infinite loop. If *safety* is zero, the number of required arguments is not checked. -V flag is used to print function names when they are compiled (verbose). -c flag prevents from forking and exec'ing cc. -D pushes next argument to the *features* list, which can be used for conditional compilation in conjunction with #- and #+ read-macro.
The compiler translates EusLisp source program named as "xxx.l" into the intermediate C program file named "xxx.c" and the header file named "xxx.h". Then the C compiler is run and "xxx.o" is generated. Intermediate files "xxx.c" and "xxx.h" are left for the purpose of cross compilation: usually you only need to compile "xxx.c" files by cc unix command when you wish to use the code on machines of different architecture. Compiled code is loaded to EusLisp by '(load "xxx")'.
Each intermediate file refers to the "eus.h" header file, which is supposed to be located in the *eusdir*/c directory. *eusdir* is copied from the EUSDIR environment variable. If none is set, /usr/local/eus/ is taken as the default directory.
When compiled, intermediate C programs are usually much bigger than the original source code. For example, 1,161 lines of "l/common.l" lisp source expands to 8,194 lines of "l/common.c" and 544 lines of "l/common.h". Compiling 1,000 lines of lisp source is not a hard task, but optimized compililation of nearly 10,000 lines of C program not only takes long time (several minutes), but also consumes much disk space. So if you are compiling relatively big programs, be sure your machine has sufficient /var/tmp disk, otherwise CC may die. Setting the TEMPDIR environment variable to a bigger disk slice may help.
As the linkage is performed at load-time or at run-time, no recompilation is required even the eus kernel is updated. On the other hand, run-time linkage may impose you another inconvenience. Suppose you have two functions A and B in a file "x.l" and A calls B. After compiling "x.l", you load "x.o" and try to call A which internally calles B. Then you find a bug in B, and probably you would redefine B. Here, you have compiled A and non-compiled B. You may call A again, but nothing will change, since A still calls old compiled B which is rigidly linked when A first called B. To avoid this problem, A must be redefined again, or B must be redefined just after "x.o" is loaded and before A is called.
When a compiled-code is loaded, its top level code, which is normally a series of defun, defmethod, etc., is executed. This top level code is defined as the entry function of the load module. The compiler names the entry function, and the loader has to know the exact name of this function. To make the situation simple, both the compiler and the loader assume the entry function name is identical to the basename of the object file. For example, if you compile and load "fib.l", the compiler produces "fib(...)" as the entry function of "fib.c", and the loader looks for "fib" in the "fib.o" object file. Since the final object file is produced by "cc" and "ld" of unix, this entry function name has to satisfy the naming rule of C functions. Therefore, you have to avoid C's reserved keywords such as "int", "struct", "union", "register", "extern", etc., or the private identifiers defined in "c/eus.h" such as "pointer", "cons", "makeint", etc., to be used as the name of the file. If you have to use one of these reserved words as the name of the source file, you specify it as :entry arguments of the compiler and the loader.
A restriction exists for the usage of closure: return-from special form in closures and clean-up forms in unwind-protect is not always correctly compiled.
Disassemble is not implemented. In order to analyze compiled code, see the intermediate C program or use adb.
euscomp &rest filename [unix-command]
compile-file [function]
srcfile &key (verbose nil)
(optimize 2) (c-optimize 1) (safety 1) ; optimization level
(pic t) ; position independent code
(cc t) ; run c compiler
(entry (pathname-name file))
compile-file-if-src-newer srcfile &key compiler-options [function]
compiler:*optimize* [variable]
load [function]
fname &key (verbose *load-verbose*)
(package *package*)
(entry (pathname-name fname))
(symbol-input nil)
(symbol-output "")
(print nil)
(ld-option "")
For example, if *load-path* is ("/user/eus/" "/usr/lisp/"), and "llib/math" is given as fname, load tries to find "/user/eus/llib/math.o", "/usr/lisp/llib/math.o", "/user/eus/llib/math.l" and "/usr/lisp/llib/math.l" in this order. If no appropriate file could be found, an error is reported.
:entry option specifies the entry address to initialize the load module. For example, :entry "_myfunc" option means that the execution begins at _myfunc. Default entry is the basename of the file loaded as described in the section 12.3. Library module names can be specified in :ld-option option string. For example, in order to link a module which uses suncore libraries, :ld-option "-lsuncore -lsunwindow -lpixrect -lm -lc" should be given. On non Solaris systems, ld runs twice when libraries are included; once to determine the size of the linked module, and again to link them actually with a proper memory allocation.
:symbol-input and :symbol-output options are used to solve references from one object module to another or to avoid duplicated loading of libraries. Suppose you have two object modules A and B which has reference to symbols defined in A. You first load the module A specifying :symbol-output = "a.out". Symbol information generated by this linking is written to a.out. In order to load the module B, you have to specify :symbol-input = "a.out" to solve the references from B to A.
On Solaris2 OS, the loading of compiled code is done by calling dlopen in the dynamic loader library. Application of dlopen is restricted to shared objects which are compiled position independently with "-K pic" option. Also, since dlopen cannot open the same file twice, load first does dlclose on the file already loaded.
:print option decides whether load should produce output to *standard-output* for each input expression. This option is provided to find which expression (usually defun, defmethod, etc.) results error in loading.
load-files &rest files [function]
provide module-name &rest version-info [function]
require module-name &rest load-arg [function]
system:binload [function]
opath qpath &optional (entry (pathname-name opath))
(symfile "/usr/local/bin/eus")
(symout "a.out")
(ldopt "")
system::txtload fname [function]
describe obj &optional (stream *standard-output*) [function]
describe-list list &optional (stream *standard-output*) [function]
break &optional (prompt ":: ") [function]
apropos strng &optional pack [function]
apropos-list strng &optional pack [function]
constants &optional (string "") (pkg *package*) [function]
variables &optional (string "") (pkg *package*) [function]
functions &optional (string "") (pkg *package*) [function]
btrace &optional (depth 10) [function]
trace &rest functions [function]
untrace &rest functions [function]
timing count &rest forms [macro]
sys:list-all-catchers [function]
sys:list-all-instances aclass &optional scan-sub [function]
sys:list-all-bindings [function]
sys:list-all-special-bindings [function]
dump-object file &rest objects [function]
dump-structure file &rest objects [function]
dump-loadable-structure file &rest symbols [function]
(setq a (make-cube 1 2 3)) ;; sample for dump-object (dump-object "a-cube.l" a) (with-open-file (f "a-cube.l" :direction :input) (setq a (read f))) (print a) ;; sample for dump-structure (dump-structure "a-cube.l" a) (with-open-file (f "a-cube.l" :direction :input) (setq a (read f))) (print a) ;; sample for dump-loadable-structure (dump-loadable-structure "a-cube.l" a) (load "a-cube.l") (print a)
sys:save path &optional (symbol-file "") starter [function]
The toplevel function should be programmed to accept arbitrary number of arguments. Each argument on the command line is coerced to a string and transfered to the toplevel function. The program below repeatedly reads expressions from the file given by the first argument and pretty-prints them to the second argument file.
(defun pprint-copy (infile outfile) (with-open-file (in infile) (with-open-file (out outfile :direction :output) (let ((eof (cons nil nil)) (exp)) (while (not (eq (setq exp (read in nil eof)) eof)) (pprint exp out)))))) (defun pprint-copy-top (&rest argv) (when (= (length argv) 2) (pprint-copy (first argv) (second argv))))
Once you defined these functions in EusLisp, (save "ppcopy" "" 'pprint-copy-top) creates a unix executable command named ppcopy.
In Solaris based EusLisp, the toplevel evaluator cannot change in this manner, since save is not available. Instead, edit lib/eusrt.l to define the custom toplevel evaluator and set it to *toplevel*. lib/eusrt.l defines initialization procedures evaluated at every invocation of the EusLisp.
lisp-implementation-type [function]
lisp-implementation-version [function]
This document was generated using the LaTeX2HTML translator on Sat Feb 5 14:36:57 JST 2022 from EusLisp version 138fb6ee Merge pull request #482 from k-okada/apply_dfsg_patch