Chapter 2

Operating a CL Development Environment

This chapter covers some of the hands-on techniques used when working with a CL development environment, specifically, the Allegro CL® environment from Franz Inc. If you are completely unfamiliar with any Lisp language, you may wish to reference Chapter 3 as you read this chapter.
 
Ideally, while reading this chapter, you should have access to an actual Common Lisp session and try typing in some of the examples.
 When working with Common Lisp, it helps to think of the environment as its own operating system, sitting on top of whatever operating system you happen to be working with. In fact, people used to build entire
workstations and operating systems in Lisp. The Symbolics Common Lisp environment still runs as an emulated machine on top of the 64-bit Compaq/DEC Alpha CPU, with its own Lisp-based operating system.
  A complete and current listing of available CL systems can be found on the Association of Lisp Users website, at 

http://www.alu.org/table/systems.htm

These systems follow the same basic principles, and most of what you learn and write on one system can be applied and ported over to others. The examples in this guide were prepared using Allegro CL for Linux. Where possible, we will note Allegro CL-specific syntax and extensions.

 

2.1 Installing a CL Environment

Installing a CL environment is generally a straightforward process. For Allegro CL on Linux, this basically involves running a simple shell script which steps you through some licensing information, then proceeds to unpack the distribution, and sets up the CL executable and supporting files.
  The Windows installation involves somewhat less typing and more mouse clicking.

 

2.2 Running CL in a Shell Window

The most primitive and simplest way to run CL is directly from the Unix (Linux) shell from within a terminal window. Most programmers do not work this way on a daily basis because other modes of use provide more power and convenience with fewer keystrokes.
  This mode of working is sometimes useful for logging into a running CL system on a remote host (e.g. a CL process acting as a webserver) when using a slow dial-up connection.

2.2.1 Starting CL from a Terminal Window

To start a CL session from a terminal window, simply type

lisp

from the Unix (or DOS) command line. Assuming your shell execution path is set up properly and CL is installed properly, you will see some introductory information, then will be presented with a Command Prompt which should look very similar to the following:

USER(1):

CL has entered its read-eval-print loop, and is waiting for you to type something which it will then read, evaluate to obtain a return-value, and finally print this resulting return-value.
  The
USER printed before the prompt refers to the current CL package (more on Packages later), and the number (1) simply keeps track of how many commands have been entered at the prompt.

2.2.2 Stopping CL from a Terminal Window

Now that you have learned how to start CL, you should probably know how to stop it. In Allegro CL, one easy way to stop the CL process is to type

(excl:exit)

at the Command Prompt. This should return you to the shell. In very rare cases, a stronger hammer is required to stop the CL process, in which case you can try typing

(excl:exit 0 :no-unwind t)

Try It: Now try starting and stopping CL several times, to get a feel for it. In general, you should notice that CL starts much more quickly on subsequent invocations. This is because the entire executable file has already been read into the computer's memory and does not have to be read from the disk every time.
  A shortcut for the (excl:exit) command is the toplevel command :exit. Toplevel commands are words which are preceded by a colon [:] that you can type at the CL Command Prompt as a shorthand way of making CL do something.
   
Try It: Start the CL environment. Then, using your favorite text editor, create a file /tmp/hello.lisp and place the following text into it (don't worry about understanding the text for now):

(in-package :user)

(defun hello ()
   (write-string "Hello, World!"))

Save the file to disk. Now, at the CL prompt in the shell where you started the CL environment, compile and load this file as follows (text after the "USER" prompt represents what you have to type; everything else is text printed by CL):

USER(3): (compile-file "/tmp/hello")
;;; Compiling file /tmp/hello.lisp
;;; Writing fasl file /tmp/hello.fasl Fasl write complete
#p"/tmp/hello.fasl"
NIL
NIL

USER(4): (load "/tmp/hello")
; Fast loading /tmp/hello.fasl
T

By default, the compile-file command will look for files with the .lisp suffix, and the load command will load the resulting compiled machine-code (binary) file, which by default will have the extension .fasl. The extension ".fasl" stands for "FASt Loading" file.
  Note that, in general, simply loading an uncompiled Lisp file (using
load) will functionally have the same effect as loading a compiled binary (fasl) file. But the fasl file will load faster, and any Functions, Objects, etc. defined in it will perform faster, since they will have been optimized and translated into language which is closer to the actual machine. Unlike Java "class" files, CL fasl files usually represent native machine-specific code. This means that compiled CL programs will generally run much faster than compiled Java programs, but CL programs must be compiled separately for each type of machine on which you want to run them.
  Finally, try executing the newly defined Function hello by typing the following at your command line:

USER(5): (hello)
Hello, World!
"Hello, World!"

You should see the String Hello, World! printed (without double-quotes), then the returned String (with double-quotes) will be printed as well. In the next chapter, The CL Language, we will learn more about exactly what is going on here. For now the main point to understand is the idea of compiling and loading definitions from files, and invoking Functions by typing expressions at the CL command line.

 

2.3 Running CL inside a Text Editor

A more powerful way of developing with CL is by running it from within a Unix (or DOS) shell that is running inside a buffer in a powerful text editor, such as Gnu Emacs1. One advantage of this approach is that the editor (in our example, Emacs) keeps a history of the entire session: both the expressions the programmer has typed, as well as everything that CL has printed. All these items can be easily reviewed or recalled.

2.3.1 A Note on Emacs and Text Editors

To develop using Common Lisp, you can, of course, use any text editor of your choice, although Emacs happens to be especially synergistic for working with CL, for reasons we will discuss later.
With a bit of practice, you will find that the combination of Emacs and Allegro CL provides a more powerful and convenient development environment than any of today's ashy "visual programming" environments. If you are used to working with the "vi" editor, Emacs comes with several "vi" emulation modes which you may want to experiment with on a transitional basis. If you are used to working with a standard Windows-based text editor, you will find a smooth transition to Emacs, and will find many "surprise and delight" features as you progress on your Emacs journey.
  This guide provides examples using Gnu Emacs.
  To work with CL in an Emacs shell buffer, you should be reasonably familiar with the text editor. If you are completely new to Gnu Emacs, go through the Emacs Tutorial, available under the "Help" menu at the top of the Emacs window.

2.3.2 Emacs Terminology

As you will learn in the Emacs Tutorial, when working with Emacs you make frequent use of key chords. Similar to "chords" on a piano, keychords can allow some powerful text processing with relatively few sequential keystrokes.
  They are key combinations involving holding down the
Control key and/or the Meta key, and pressing some other regular key.
  See Appendix B for information on which keys represent Control and Meta on your keyboard, and how you can customize these. To begin, try using the key labeled "Control" for Control and the keys labeled "Alt" (or the diamond-shaped key on Sun keyboards) for Meta. If your keyboard has a "Caps Lock" key to the left of the letter "A," you should consider remapping this to function as Control, as explained in Appendix B.
  This guide uses the following notations to indicate keychords (identical to those referenced in the Emacs Tutorial):

  • M-x means to hold down the Meta key, and press (in this case) the "X" key
  • C-x means to hold down the Control key, and press (in this case) the "X" key
  • C-M-q means to hold down the Control key and the Meta key at the same time , and press (in this case) the "Q" key
  • M-A would mean to hold down the Meta key, and the Shift key (because the "A" is uppercase), and press (in this case) the "A" key.

2.3.3 Starting, Stopping, and Working With CL inside an Emacs Shell

To start Emacs, type

emacs

or

gnuemacs

then start a Unix (or DOS) shell within emacs by typing M-x shell. Now type

lisp

inside this shell's window to start a CL session there. To shut down a session, exit CL exactly as above by typing

(xcl:exit)

Exit from the shell by typing

Exit

and finally exit from Emacs by typing C-x C-c or M-x kill-emacs. Note that it is good practice always to exit from CL before exiting from Emacs. Otherwise the CL process may be left as an "undead" (zombie) process.
  When in the CL process, you can move forward and backward in the "stack" (history) of expressions that you have typed, effectively recalling previous commands with only a few keystrokes. Use
M-p to move backward in the history, and M-n to move forward. You can also use all of the editor's text processing commands, for example to cut, copy, and paste expressions between the command line and other windows and open files ("buffers") you may have open.
 
Try It: try typing the following expressions at the CL prompt. See what return-values are printed, and try recalling previous expressions (commands) using M-p and M-n:

(list 1 2 3)

(+ 1 2 3)

(> 3 4)

(< 3 4)

Now, of course, you can edit, compile, load, and test your hello.lisp file as we did in Section 2.2. But this time you are staying within a single environment (the text editor environment) to achieve all these tasks.

 

2.4 Running CL as a subprocess of Emacs

An even more powerful way of developing with Allegro CL is by running it within Emacs in conjunction with a special Emacs/Lisp interface provided by Franz Inc. This technique provides all the benefits of running in an Emacs shell as outlined above, but is more powerful because the Emacs-CL interface extends Emacs with several special commands. These commands interact with the CL process, making the editor appear to be "Lisp-aware." The combination of Emacs with the Emacs- CL interface results in a development environment whose utility approaches that of the vintage Symbolics Lisp Machines, which many Lisp aficionados still consider to be technology advanced well beyond anything produced today.
  Complete documentation of the Emacs-CL interface can be viewed by pointing your web browser at:
file:/usr/local/acl5/eli/readme.htm (you may have to modify this pathname to point to your actual installed location of Allegro CL (acl5)).

2.4.1 Starting the CL subprocess within Emacs

To enable your Emacs to function in the proper manner, place the following expressions in a file named .emacs in your home directory:

 

Table 2.1: Common Commands of the Emacs-Lisp Interface

(setq load-path
  (cons "/usr/local/acl5/eli" load-path))
(load "fi-site-init")

As above, you may have to modify this pathname to point to your actual installed location of Allegro CL (acl5). Once you have added these lines to your .emacs file, you should be able to restart emacs, then issue the command:

M-x fi:common-lisp

to start CL running and automatically establish a network connection between the Emacs process and the CL process (in theory, the two processes could be running on different machines, but in practice they usually will run on the same machine). Accept all the defaults when prompted.
 
You can also start emacs with the CL subprocess automatically from a terminal window, by invoking emacs with an optional "function" argument, as follows:

emacs -f fi:common-lisp

This will start Emacs, which itself will immediately launch CL.

2.4.2 Working with CL as an Emacs subprocess

Once you have started CL within Emacs, you will be presented with a special buffer named *common-lisp* which in many ways is similar to simply running CL within a shell within Emacs as above. But now you have several more capabilities available to you, as outlined in Table 2.1.
  To summarize, the Lisp-Emacs interface adds capabilities such as the following to your development environment:

  • Start and stop the CL process using Emacs commands
  • Compile and load files into the running CL process, directly from the open Emacs buffer you are editing (no need explicitly to save the file, call the compile-file Function, then call the load Function, as with the "in-a-shell" techniques above)
  • Query the running CL process for information about objects currently defined in it - for example, querying the CL, directly from Emacs, for the argument List of a particular Function
  • Run multiple read-eval-print loops, or listeners, in different threads of CL execution, as Emacs buffers
  • Compile and load specified sections of an open Emacs buffer
  • Locate the source code file corresponding to any defined CL object, such as a Function or parameter, and automatically open it in an Emacs buffer
  • Perform various debugging actions and other general CL help capabilities, directly from within the Emacs session

    In short, Emacs becomes a remarkably powerful, infinitely customizable, CL integrated development environment.

2.4.3 Compiling and Loading a File from an Emacs buffer

Try it: Try starting Emacs with a CL subprocess as outlined above. If you have trouble, consult the URL listed above for complete instructions on running the Lisp-Emacs interface.
  Once you have Emacs running with a CL subprocess, you should have a buffer named *common-lisp*. If your Emacs session is not already visiting this buffer, visit it with the command C-x b *common-lisp*, or select *common-lisp* from the "Buffers" menu in Emacs (see Appendix B for instructions on how to set up a "hot key" for this and other common tasks when working with the Emacs-Lisp interface).
    Now, split your Emacs frame into two windows, with the command
C-x 2. In both windows you should now see *common-lisp*. Now move the point to the other window with C-x o, and open the hello.lisp file you created for the previous exercise. If you don't have that file handy, create it now, with the following contents:

(defun hello ()
   (write-string "Hello, World!"))

Now, compile and load the contents of this Function definition with C-M-x. Finally, switch to the *common-lisp* window again with C-x o, and try invoking the hello Function by calling it in normal Lisp fashion:

USER(5): (hello)
Hello, World!
"Hello, World!"

You should see the results printed into the same *common-lisp* buffer.
  Try it: Now try the following: go back to the hello.lisp buffer, make an edit to the contents (for example, change the String to "Hello, CL World!"). Now compile the buffer with this change (Note that you do not necessarily have to save the file). Finally, return to the *common-lisp* buffer, and try invoking the Function again to confirm that the redefinition has taken effect.
  You have now learned the basic essentials for working with the Emacs-Lisp interface. See Appendix B for more information about Emacs customization and convenient Emacs commands specific to the Lisp editing mode.

 

2.5 Integrated Development Environment

Some CL implementations support or integrate with an IDE, or Integrated Development Environment. Such environments provide visual layout and design capabilities for User Interfaces and other graphical, visual techniques for application development. For example, such a system is available for Allegro CL on the Microsoft platforms. The details of these systems are covered in their own documentation and are beyond the scope of this guide.

 

2.6 The User Init File

When CL begins execution, it usually looks for an initialization file, or "init" file, to load. When CL loads this file, it will read and evaluate all the commands contained in it.
 
The default name and location for this initialization file is

.clinit.cl
 

in the user's home directory on Unix/Linux, and

c:"clinit.cl

on Windows systems.
  For example, the init file can be used to define library Functions and variables that the user employs frequently, or to control other aspects of the CL environment. An example init file is:

(in-package :user)

(defun load-project ()
   (load "~/lisp/part1")
   (load "~/lisp/part2"))

This will have the effect of defining a convenient Function the user can then invoke to load the files for the current project. Note the call to the in-package Function, which tells CL which Package to make "current" when loading this file. As we will see in more detail in Section 3.7, CL Packages allow programs to be separated into different "layers," or "modules." Notice also that in the calls to load we do not specify a file "type" extension, e.g. .lisp or .fasl. We are making use of the fact that the load Function will look first for a binary file (of type fasl), and if this is not found it will then look for a file of type lisp. In this example we assume that our Lisp files will already have been compiled into up-to-date binary fasl files.
    
In Section 2.9 we will look at some techniques for managing larger projects, and automating both the compiling and loading process for the source files making up a project.
    Note: the IDE mentioned in Section 2.5 is also a full-featured and powerful project system. The IDE is described in its own documentation, and is beyond the scope of this document.

 

2.7 Using CL as a scripting language

Although CL is usually used in the interactive mode described above while developing a program, it can be also used as a scripting language in more of a "batch" mode. For example, by running CL as:

lisp -e '(load "~/script")' < datafile1 > datafile2

it will load all of the Function definitions and other expressions in file script.fasl or script.lisp, will process datafile1 on its Standard Input, and will create datafile2 with anything it writes to its Standard Output. Here is an example of a simple script.lisp file:

(in-package :user)

(defun process-data ()
       (let (x j)
           ;;Read a line of input from datafile1
           (setq x (read-line))
           ;;Remove leading spaces from X
           (setq j (dotimes (i (length x))
                       
(when (not (string-equal " " (subseq x i (+ i 1))))
                           
(return i))))
           
(setq x (subseq x j))
           ;;Write the result to datafile2
           (format t "~A~%" x)))

(process-data)

This file defines a Function to process the datafile, then calls this Function to cause the actual processing to occur.
    Note the use of the semicolon ("
;"), which is a reader macro which tells CL to treat everything between it and the end of the line as a comment (to be ignored by the CL Reader).

 

2.8 Debugging in CL

CL provides one of the most advanced debugging and error-handling capabilities of any language or environment. The most obvious consequence of this is that your application will very rarely "crash" in a fatal manner. When an error occurs in a CL program, a break occurs. CL prints an error message, enters the debugger, and presents the user with one or more possible restart actions. This is similar to running inside a debugger, or in "debug mode," in other languages, but in CL this ability comes as a built-in part of the language.
    
For example, if we call the + Function with an alphabetic Symbol instead of a Number, we generate the following error:

USER(95): (+ 'r 4)
Error: `R' is not of the expected type `NUMBER'
     [condition type: TYPE-ERROR]

Restart actions (select using :continue):
   0: Return to Top Level (an "abort" restart)
[1] USER(96):

The number [1] at the front of the prompt indicates that we are in the debugger, at Level 1. The debugger is itself a CL Command Prompt just like the toplevel Command Prompt, but it has some additional functionality. The next section provides a partial list of commands available to be entered directly at the debugger's Command Prompt:

2.8.1 Common debugger commands

  • :reset returns to the toplevel (out of any debug levels)
  • :pop returns up one level
  • :continue continues execution after a break or an error
  • :zoom Views the current Function call stack
  • :up Moves the currency pointer up one frame in the stack
  • :down Moves the currency pointer down one frame in the stack
  • :help Describes all debugger commands

  Franz Inc.'s Allegro Composer product also offers graphical access to these commands, as well as additional functionality.

2.8.2 Interpreted vs Compiled Code

CL works with both compiled and interpreted code. When you type expressions at a Command Prompt, or use CL's load Function to load lisp source files directly, you are introducing interpreted code into the system. This code does not undergo any optimization or translation into a lower-level machine representation - internally to CL it exists in a form very similar to its source code form. CL must do considerable work every time such code is evaluated, since it must be translated into lower-level machine instructions on each use.
    When you create
compiled code, on the other hand, for example by using CL's compile-file command in order to produce a fasl file, the code is optimized and translated into an efficient form.
 
Loading the fasl file will replace any previous interpreted definitions with compiled definitions.
    Interpreted code is the best to use for debugging a program, because the code has not undergone as many transformations, so the debugger can provide the programmer with more recognizable information.
    If you are debugging with compiled code (e.g. after loading a
fasl file), and you feel that not enough information is available from within the debugger, try redefining the Function in interpreted form and running it again. To redefine a Function in interpreted form you can, of course, simply load the lisp source file, rather than the compiled fasl file.

2.8.3 Use of (break) and C-c to interrupt

In order to cause a break in your program interactively, issue the C-c command. When running inside Emacs, you must use a "double" C-c, because the first C-c will be intercepted by Emacs. Depending on what your application is doing, it may take a few moments for it to respond to your break command. Once it responds, you will be given a normal debugger level, as described above.

2.8.4 Profiling

CL has built-in functionality for monitoring its own performance. The most basic and commonly used component is the time Macro. You can "wrap" the time Macro around any expression.
 Functionally,
time will not affect the behavior of the expression, but it will print out information about how long the expression took to be evaluated:

USER(2): (time (dotimes (n 10000) (* n 2))) cpu time (non-gc) 130
; msec user, 20 msec system cpu time (gc) 0 msec user, 0 msec system
; cpu time (total) 130 msec user, 20 msec system real time 147 msec

It is often interesting to look at the difference in time between interpreted and compiled code. The example above is interpreted, since we typed it directly at the Command Line, so CL had no opportunity to optimize the dotimes. In compiled form, the above code consumes only one millisecond as opposed to 147 milliseconds.
    In addition to the basic
time Macro, Allegro CL provides a complete Profiler package, which allows you to monitor exactly what your program is doing, when it is doing it, how much time it takes, and how much memory it uses.

 

2.9 Developing Programs and Applications in CL

For developing a serious application in CL, you will want to have a convenient procedure in place for starting up your development session.

2.9.1 A Layered Approach

The development session consists of your favorite text editor with appropriate customizations, and a running CL process with any standard code loaded into it. While you can certainly develop serious applications on top of base CL, typically you will work in a layered fashion, on top of some standard tools or libraries, such as an embedded language, a webserver, etc.
    
Using one of the techniques outlined below, starting a customized development session with your standard desired tools should become convenient and transparent.

2.9.2 Compiling and Loading your Project

An individual project will generally consist of a tree of directories and files in your computer's filesystem. We will refer to this directory tree as the project's codebase.
    Generally, it does not matter in what
order the files in the codebase are compiled and loaded. Typical CL definitions, such as Functions, Classes, etc., can ordinarily be defined in any order. However, certain constructs, most notably Packages and Macros, do have order dependencies. In general, CL Packages and Macros must be defined before they can be used, or referenced.
    
So one of the requirements of the startup process for a development session is that all files be compiled and/or loaded in the correct order.
    To start a development session on your project, you will generally want CL to do the following:

  1. Go through your project's Codebase, finding source files in the proper order
  2. For each file found, either load the corresponding binary file (if it is up-to-date), or compile the source file to create a new binary file and load it (if the source file has changed since the most recent compilation)

    CL does not dictate one standard way of accomplishing this task, and in fact, several options are available. One option is to use a defsystem package, which will allow you to prepare a special file, similar to a "make" file, which lists out all your project's source files and their required load order. Allegro CL contains its own Defsystem package as an extension to CL, and the open-source MK:Defsystem is available through Sourceforge (http://www.sourceforge.net).
    Using a Defsystem package requires you to maintain a catalog listing of all your project's source files. Especially in the early stages of a project, when you are adding, renaming, and deleting a lot of files and directories, maintaining this catalog listing by hand can become tiresome.
    For this purpose, you may wish to use a lighter-weight utility for compiling and loading your files, at least in the early stages of development. For very small projects, you can use the Allegro CL Function
excl:compile-file-if-needed, an extension to CL, by writing a simple Function which calls this Function repeatedly to compile and load your project's files.
    The Bootstrap package, available at
http://gdl.sourceforge.net, provides the Function cl-lite, which will traverse a codebase, compiling and loading files, and observing simple "ordering directive" files which can be placed throughout the codebase to enforce correct load ordering.
    For a new project, the best option is probably to start with a simple but somewhat manual loading technique, then graduate into more automated techniques as they become necessary and as you become more familiar with the environment.

2.9.3 Creating an Application "Fasl" File

Fasl files in Allegro CL and most other CL systems have the convenient property that they can simply be concatenated, e.g. with the Unix/Linux cat command, to produce a single fasl file. Loading this single file will have the same efiect as loading all the individual files which went into it, in the same order as they were concatenated.
    In certain situations, this can be a convenient mechanism for loading and/or distributing your project. For example, you can prepare a concatenated
fasl file, email it to a colleague, and the colleague needs only to load this file. Thus, there is no chance of confusion about how (e.g. in what order) to load individual files.

2.9.4 Creating an Image File

Loading Lisp source files or compiled binary files into memory at the start of each session can become slow and awkward for large programs.
    An alternative approach is to build an
image file. This entails starting a CL process, loading all application files into the running CL process, then creating a new "CL Image." In Allegro CL, this is done by invoking the Function:

excl:dumplisp

The Image File is typically named with a .dxl extension. Once you have created an Image File, you can start a session simply by starting CL with that Image File, as follows:

lisp -I <image-file-name>.dxl

You must then compile/load any files that have changed since the Image File was created. Starting CL with the Image File has the same effect as starting a base CL and loading all your application files, but is simpler and much faster.

2.9.5 Building Runtime Images

CL Image files built with excl:dumplisp contain the entire CL environment, and may also contain information which is specific to a certain machine or certain site. Allegro CL also provides a mechanism for building runtime images, which contain only the information needed to run an end-user application. These Runtime Images can be packaged and distributed just as with any stand-alone software application.
    Preparing runtime images for different platforms (e.g. Sun Solaris, Linux, Windows, etc.) is usually a simple matter of running a compilation and building a runtime image for the target platform - application source code typically remains identical among different platforms. See your platform-specific documentation for details about creating Runtime Images.

2.9.6 Using an Application Init File

In some cases, for a finished production application, you will want the CL process to execute certain commands upon startup (for example, loading some data from a database). However, you do not want to depend on the end-user having the appropriate .clinit.cl in his or her home directory.  For such cases, you can specify a difierent location for the init file, which can be installed along with the application itself. One way to accomplish this is with the -q command-line argument to the lisp command. This argument will tell CL to look in the current directory, rather than in the default location, for the init file.
    To use this technique, you would set up an "application home" directory, place the application's
.clinit.cl file in this directory, and start the application with a production startup script. This script would first change into the "application home" directory, then start CL with your application's image file, or start a Runtime Image. Such a startup script might look like this:

cd $MYAPPfiHOME
lisp -I image.dxl –q

In this example, both the application's init file and the application's image file would be housed in the directory named by the environment variable $MYAPP_HOME.

 

2.10 Using CL with Other Languages and Environments

One of CL's strong points is its exibility in working with other environments. In this section we will briey mention six different ways in which CL can integrate and/or communicate with other languages and environments.

2.10.1 Interfacing with the Operating System

One of the most basic means of interacting with the outside world is simply to invoke commands at the operating system level, in similar fashion to Perl's "system" command. In Allegro CL, one way to accomplish this is with the Function excl:run-shell-command. This command takes a String which represents a command (possibly with arguments) to be executed through an operating system shell, such as the "C" shell on Unix:

(excl:run-shell-command "ls")

The Standard Output from a shell command invoked in this fashion will be inherited by CL's Standard Output, so you will see it in the normal CL console. Alternatively, you can specify that the output go to another location, such as a file, or a variable defined inside the CL session.
    When using
excl:run-shell-command, you can also specify whether CL should wait for the shell command to complete, or should simply go about its business and let the shell command complete asynchronously.

2.10.2 Foreign Function Interface

Allegro CL's foreign function interface allows you to load compiled libraries and object code from C, C++, Fortran, and other languages, and call functions defined in this code as if they were defined natively in CL. This technique requires a bit more setup work than using simple shell commands with excl:run-shell-command, but it will provide better performance and more transparent operation once it is set up.

2.10.3 Interfacing with Corba

Corba, or the Common Object Request Broker Architecture, is an industry-standard mechanism for connecting applications written in different object-oriented languages.
    To use Corba, you define a standard Interface for your application in a language called Interface Definition Language (Corba IDL), and each application must compile the standard Interface and implement either a Servant or a Client for the interface. In this manner, Servants and Clients can communicate through a common protocol, regardless of what language they are written in.
    In order to use Corba with CL requires a Corba IDL compiler implemented in CL, as well as a run-time ORB, or Object Request Broker, to handle the actual Client/Server communications.
Several such Corba IDL compilers and ORBs are available for CL. An example of such a system is Orblink, which is available as an optional package for Allegro CL. Orblink consists of a complete Corba IDL compiler, and a CL-based ORB, which runs as a CL thread rather than as a separate operating system process.
    Using Orblink to integrate a CL application to a Corba Client/Server environment is a straightforward process. To start, you simply obtain the Corba IDL files for the desired Interface, and compile them in CL with the command
corba:idl. This will automatically define a set of Classes in CL corresponding to all the Classes, Methods, etc. which make up the Interface.
    To use CL as a Client, you can now simply make instances of the desired Classes, and use them to call the desired Methods. The Orblink ORB will take care of communicating these Method calls across the network, where they will be invoked in the actual process where the corresponding Servant is implemented (which could be on a completely different machine written in a completely different language).
    To use CL as a Servant, you must implement the relevant Interfaces. This consists of defining Classes in CL which
inherit from the "stub" Servant Classes automatically defined by the compilation of the Corba IDL, then defining Methods which operate on these Classes, and which perform as advertised in the Interface. Typically, a Corba Interface will only expose a small piece of an entire application, so implementing the Servant Classes would usually represent a small chore relative to the application itself.

2.10.4 Custom Socket Connections

Just about every CL implementation provides a mechanism to program directly with network sockets, in order to implement "listeners" and network client applications. As a practical example, Figure 2.1 shows a Telnet server, written by John Foderaro of Franz Inc., in 22 lines of code in Allegro CL. This Telnet server will allow a running CL process to accept a Telnet login on port 4000 on the

machine on which it is running, and will present the client with a normal CL Command Prompt (for security, it will by default only accept connections from the local machine).

2.10.5 Interfacing with Windows (COM, DLL, DDE)

Most Commercial CL implementations for the Microsoft Windows platform will allow CL applications to use various Microsoft-specific means for integrating with the Microsoft platform. For example, an Allegro CL application can be set up to run as a COM Server, or compiled into a DLL to be used by other applications.

2.10.6 Code Generation into Other Languages

CL excels at reading and generating CL code. It is also a powerful tool for analyzing and generating code in other languages. An example of this can be found in Chapter 5, where we use a convenient CL macro to generate HTML for a web page.
    Another example is MSC's AutoSim product, which uses a CL program to model an automobile, then generates optimized C programs for solving specialized systems of linear equations relating to vehicle dynamics.
    CL also played a crucial role in preventing the Y2K disaster by automatically analyzing and repairing millions of lines of COBOL!