Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

[c13f92]: ref_os.xmlf Maximize Restore History

Download this file

ref_os.xmlf    495 lines (433 with data), 18.2 kB

<?xml version="1.0"?><!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<book lang="en"><reference id="os.dict"><title>OS Reference</title>

 <!-- ====================================================================== -->
 <!-- EXT:*HELP-MESSAGE*                                                     -->
 <!-- ====================================================================== -->

 <refentry id="ref._help-message_">
  <refnamediv>
   <refname><varname>ext:*help-message*</varname></refname>
   <refpurpose>Command line help message</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Variable</title>
   <variablelist>
    <varlistentry>
     <term>Type</term>
     <listitem><para>A string</para></listitem>
    </varlistentry>
    <varlistentry>
     <term>Initial value</term>
     <listitem><para>&ECL; help message</para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This variable contains the help message which is output when &ECL; is
   invoked with the <option>--help</option>.</para>
  </refsect1>

  <refsect1>
   <title>Example</title>
   <para>See <xref linkend="ref.process-command-args"/>.</para>
  </refsect1>
 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:+LISP-INIT-FILES+                                                  -->
 <!-- ====================================================================== -->

 <refentry id="ref._lisp-init-files_">
  <refnamediv>
   <refname><varname>ext:*lisp-init-files*</varname></refname>
   <refpurpose>&ECL; initialization files.</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Constant</title>
   <variablelist>
    <varlistentry>
     <term>Type</term>
     <listitem><para>A list of pathname designators.</para></listitem>
    </varlistentry>
    <varlistentry>
     <term>Initial value</term>
     <listitem><para><literal>'("~/.ecl" "~/.eclrc")</literal></para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This variable contains the names of initialization files that are
   loaded by &ECL; or embedding programs. The loading of initialization files
   happens automatically in &ECL; unless invoked with the option
   <option>-norc</option>. Whether initialization files are loaded or not is
   controlled by the command line options rules, as described in <xref
   linkend="ref.process-command-args"/>.</para>
  </refsect1>

  <refsect1>
   <title>Example</title>
   <para>See <xref linkend="ref.process-command-args"/>.</para>
  </refsect1>
 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:+DEFAULT-COMMAND-ARG-RULES+                                        -->
 <!-- ====================================================================== -->

 <refentry id="ref._default-command-arg-rules_">
  <refnamediv>
   <refname><varname>ext:+default-command-arg-rules+</varname></refname>
   <refpurpose>&ECL; command line options</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Constant</title>
   <variablelist>
    <varlistentry>
     <term>Type</term>
     <listitem><para>A list of lists.</para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This constant contains a list of rules for parsing the command line
   arguments. This list is made of all the options which &ECL; accepts by
   default. It can be passed as first argument to <xref
   linkend="ref.process-command-args"/>, and you can use it as a starting point
   to extend &ECL;.</para>
  </refsect1>

  <refsect1>
   <title>Example</title>
   <para>See <xref linkend="ref.process-command-args"/>.</para>
  </refsect1>
 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:COMMAND-ARGS                                                       -->
 <!-- ====================================================================== -->

 <refentry id="ref.command-args">
  <refnamediv>
   <refname><function>ext:command-args</function></refname>
   <refpurpose>List of command line arguments.</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Function</title>
   <funcsynopsis>
    <funcprototype>
     <funcdef>ext:command-args</funcdef>
     <void></void>
    </funcprototype>
   </funcsynopsis>
   <variablelist>
    <varlistentry>
     <term>returns</term>
     <listitem><para>A list of strings.</para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This function returns the list of command line arguments passed to
   either &ECL; or the program it was embedded in. The output is a list of
   strings and it corresponds to the <varname>argv</varname> vector in a C
   program. Typically, the first argument is the name of the program as it was
   invoked. You should not count on ths filename to be resolved.</para>
  </refsect1>

 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:PROCESS-COMMAND-ARGS                                               -->
 <!-- ====================================================================== -->

 <refentry id="ref.process-command-args">
  <refnamediv>
   <refname><function>ext:process-command-args</function></refname>
   <refpurpose>Process command line arguments.</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Function</title>
   <funcsynopsis>
    <funcprototype>
     <funcdef>ext:process-command-args</funcdef>
     <paramdef><parameter>&key;</parameter></paramdef>
     <paramdef><parameter>args</parameter></paramdef>
     <paramdef><parameter>rules</parameter></paramdef>
    </funcprototype>
   </funcsynopsis>
   <variablelist>
    <varlistentry>
     <term><replaceable>args</replaceable></term>
     <listitem><para>A list of strings. Defaults to the output of <xref
     linkend="ref.command-args"/></para></listitem>
    </varlistentry>
    <varlistentry>
     <term><replaceable>rules</replaceable></term>
     <listitem><para>A list of lists. Defaults to the value of <xref
     linkend="ref._default-command-arg-rules_"/></para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This function processes the command line arguments passed to either
   &ECL; or the program that embeds it. It uses the list of rules
   <replaceable>rules</replaceable>, which has the following syntax:
<synopsis>(option-name nargs template [:stop | :noloadrc | :loadrc]*)</synopsis>
   </para>
   <variablelist>
    <varlistentry>
     <term><replaceable>option-name</replaceable></term>
     <listitem><para>A string with the option prefix as typed by the user. For
     instance <option>--help</option>, <option>-?</option>,
     <option>--compile</option>, etc.</para></listitem>
    </varlistentry>
    <varlistentry>
     <term><replaceable>nargs</replaceable></term>
     <listitem><para>A nonnegative integer denoting the number of arguments
     taken by this option.</para></listitem>
    </varlistentry>
    <varlistentry>
     <term><replaceable>template</replaceable></term>
     <listitem><para>A lisp form, not evaluated, where numbers from 0 to
     <replaceable>nargs</replaceable> will be replaced by the corresponding
     option argument.</para></listitem>
    </varlistentry>
    <varlistentry>
     <term><symbol>:STOP</symbol></term>
     <listitem><para>If present, parsing of arguments stops after this option
     is found and processed.</para></listitem>
    </varlistentry>
    <varlistentry>
     <term><symbol>:NOLOADRC</symbol> and <symbol>:LOADRC</symbol></term>
     <listitem><para>Determine whether the lisp initalization file (<xref
     linkend="ref._lisp-init-file-list_"/>) will be loaded before processing
     all forms.</para></listitem>
    </varlistentry>
   </variablelist>

   <para><function>EXT:PROCESS-COMMAND-ARGS</function> works as follows. First
   of all, it parses all the command line arguments, except for the first one,
   which is assumed to contain the program name. Each of these arguments is
   matched against the rules, sequentially, until one of the patterns
   succeeeds.</para>

   <para>A special name <literal>"*DEFAULT*"</literal>, matches any unknown
   command line option. This template gets a single argument, which is the list
   of remaining unprocessed options.</para>

   <para>If no match is found, an error is signalled. For each rule
   that succeeds, the function constructs a lisp statement using the
   <replaceable>template</replaceable>.</para>

   <para>After all arguments have been processed,
   <function>EXT:PROCESS-COMMAND-ARGS</function>, and there were no occurences
   of <symbol>:NOLOADRC</symbol>, one of the files listed in <xref
   linkend="ref._lisp-init-file-list_"/> will be loaded. Finally, the list of
   lisp statements will be evaluated.</para>
  </refsect1>

  <refsect1>
   <title>Example</title>

   <para>The following piece of code implements the <command>ls</command>
   command using lisp.<footnote><para>Instructions for building this program
   are found under
   <filename>ecl/examples/cmdline/ls.lsp</filename></para></footnote></para>
<!-- When changing, check ecl/examples/cmdline/ls.lsp -->
<programlisting>
(setq ext:*help-message* "
ls [--help | -?] filename*
     Lists the file that match the given patterns.
")

(defun print-directory (pathnames)
 (format t "~{~A~%~}"
  (mapcar #'(lambda (x) (enough-namestring x (si::getcwd)))
	  (mapcan #'directory (or pathnames '("*.*" "*/"))))))

(defconstant +ls-rules+
'(("--help" 0 (progn (princ ext:*help-message* *standard-output*) (ext:quit 0)))
  ("-?" 0 (progn (princ ext:*help-message* *standard-output*) (ext:quit 0)))
  ("*DEFAULT*" 1 (print-directory 1))))

(let ((ext:*lisp-init-file-list* NIL)) ; No initialization files
  (handler-case (ext:process-command-args :rules +ls-rules+)
    (error (c)
       (princ ext:*help-message* *error-output*)
       (ext:quit 1))))
(ext:quit 0)
</programlisting>
  </refsect1>
 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:QUIT                                                               -->
 <!-- ====================================================================== -->

 <refentry id="ref.quit">
  <refnamediv>
   <refname><function>ext:quit</function></refname>
   <refpurpose>Exit &ECL;.</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Function</title>
   <funcsynopsis>
    <funcprototype>
     <funcdef>ext:quit</funcdef>
     <paramdef>&optional;</paramdef>
     <paramdef><parameter>exit-code</parameter></paramdef>
    </funcprototype>
   </funcsynopsis>
   <variablelist>
    <varlistentry>
     <term><replaceable>exit-code</replaceable></term>
     <listitem><para>An integer between 0 and 255</para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This function abruptly stops the execution of the program in which
   &ECL; is embedded. Depending on the platform, several other functions will
   be invoked to free resources, close loaded modules, etc.</para>

   <para>The exit code is the code seen by the parent process that invoked
   this program. Normally a code other than zero denotes an error.</para>
  </refsect1>
 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:RUN-PROGRAM                                                        -->
 <!-- ====================================================================== -->
 <refentry id="ref.run-program">
  <refnamediv>
   <refname><function>ext:run-program</function></refname>
   <refpurpose>Start and communicate with a child process.</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Function</title>
   <funcsynopsis>
    <funcprototype>
     <funcdef>ext:run-program</funcdef>
     <paramdef><parameter>command</parameter></paramdef>
     <paramdef><parameter>argv</parameter></paramdef>
     <paramdef>&key;</paramdef>
     <paramdef>input</paramdef>
     <paramdef>output</paramdef>
     <paramdef>error</paramdef>
    </funcprototype>
   </funcsynopsis>
   <variablelist>
    <varlistentry>
     <term><replaceable>input</replaceable></term>
     <listitem><para>One of <symbol>:STREAM</symbol>, <symbol>T</symbol> or
     <symbol>NIL</symbol>, defaults to
     <symbol>:STREAM</symbol></para></listitem>
    </varlistentry>
    <varlistentry>
     <term><replaceable>output</replaceable></term>
     <listitem><para>One of <symbol>:STREAM</symbol>, <symbol>T</symbol> or
     <symbol>NIL</symbol>, defaults to
     <symbol>:STREAM</symbol></para></listitem>
    </varlistentry>
    <varlistentry>
     <term><replaceable>error</replaceable></term>
     <listitem><para>One of <symbol>:OUTPUT</symbol>, <symbol>T</symbol> or
     <symbol>NIL</symbol>, defaults to
     <symbol>:STREAM</symbol></para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This function creates a external process by launching the program
   <replaceable>command</replaceable> with the arguments from the list
   <replaceable>argv</replaceable>.</para>

   <para>The arguments <replaceable>input</replaceable>,
   <replaceable>output</replaceable> and <replaceable>error</replaceable> are
   used to intercept the standard input, output and error streams of the
   program. A value of <symbol>:STREAM</symbol> means a lisp stream will be
   created to communicate with the child process. A value of
   <symbol>NIL</symbol> means that the data from this pipe will be
   discarded. The vaule of <symbol>T</symbol> means that the child process will
   use the parent's standard input, output or error channels. For instance, if
   &ECL; writes to the console and you pass a value of
   <replaceable>output</replaceable> equal to <symbol>:STREAM</symbol>, the
   child process will also output to the console. Finally, the error messages
   of the child process are redirected to the same pipe as its standard
   output when <replaceable>error</replaceable> takes the value
   <symbol>:OUTPUT</symbol>.</para>

   <para>If the child process was succesfully launched, this function outputs a
   lisp stream to which we one may write, read or do both things, depending on
   the arguments <replaceable>input</replaceable> and
   <replaceable>output</replaceable>. If an error happened during the
   preparation of the child process (for instance the program was not found),
   this function returns <replaceable>NIL</replaceable>.</para>

   <para>The design of this function is inspired by the function of same name
   in &CMUCL; and &SBCL;.</para>
  </refsect1>

  <refsect1>
   <title>Example</title>

   <para>List all users in a Unix system. We use the <command>sed</command>
   command to parse the file with the list of users, removing comments and
   information other than the user names:
<programlisting>(defun all-users (&amp;optional (file "/etc/passwd"))
  (let ((s (ext:run-program "sed"
              (list "-e" "/^#.*$/d;/^[^:]*$/d;s,^\\([^:]*\\).*$,\\1,g"
	            file)
              :input NIL :output :STREAM :error NIL)))
    (unless s
      (error "Unable to parse password file"))
    (loop for x = (read s NIL NIL)
          while x
          collect x)))</programlisting></para>

   <para>Make a directory. Redirect standard error output to the same as the
   output:
<programlisting>(ext:run-program "mkdir" '("./tmp") :output :STREAM :error :OUTPUT)
</programlisting>
</para>

   <para>Same as before, but now both the output and the standard error are
   discarded
<programlisting>(ext:run-program "mkdir" '("./tmp") :output NIL :error :OUTPUT)
</programlisting>
</para>
  </refsect1>
 </refentry>

 <!-- ====================================================================== -->
 <!-- EXT:SYSTEM                                                             -->
 <!-- ====================================================================== -->

 <refentry id="ref.system">
  <refnamediv>
   <refname><function>ext:system</function></refname>
   <refpurpose>Invoke a command using the shell.</refpurpose>
  </refnamediv>

  <refsynopsisdiv>
   <title>Function</title>
   <funcsynopsis>
    <funcprototype>
     <funcdef>ext:system</funcdef>
     <paramdef><parameter>command</parameter></paramdef>
    </funcprototype>
   </funcsynopsis>
   <variablelist>
    <varlistentry>
     <term><replaceable>command</replaceable></term>
     <listitem><para>A string</para></listitem>
    </varlistentry>
    <varlistentry>
     <term>returns</term>
     <listitem><para>An integer (0-255) with the exit code of the
     program</para></listitem>
    </varlistentry>
   </variablelist>
  </refsynopsisdiv>

  <refsect1>
   <title>Description</title>

   <para>This function executes a command in the shell. In Unix systems,
   typically the environment variable <symbol>SHELL</symbol> determines which
   program will be invoked, while in Windows <command>CMD.EXE</command> is
   used. The string may thus be any valid command that the shell accepts and
   in can contain higher level elements such as input/output
   redirection.</para>

   <para>As an example, the following function uses an external editor to
   modify a lisp file and, if successful, loads the changed sources:</para>
   <programlisting>
(defun edit (filename)
  (let* ((editor #+windows "notepad.exe"
                 #-windows "/usr/bin/emacs")
    (command (concatenate 'string editor " " filename)))
    (when (zerop (ext:system command))
    (load filename))))
   </programlisting>
  </refsect1>
 </refentry>

</reference></book>
<!-- Keep this comment at the end of the file
      Local variables:
      mode: nxml
      sgml-parent-document: "ecl.xml"
      sgml-indent-step: 1
      nxml-child-indent: 1
      nxml-outline-child-indent: 1
      fill-column: 79
      End:
 -->