[comp.sys.amiga] SHELL 2.04 PART 2 of 4

dillon@CORY.BERKELEY.EDU (Matt Dillon) (01/03/87)

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	doc.txt
#	examples.txt
# This archive created: Sat Jan  3 00:58:57 1987
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'doc.txt'" '(19307 characters)'
if test -f 'doc.txt'
then
	echo shar: "will not over-write existing file 'doc.txt'"
else
cat << \!Funky!Stuff! > 'doc.txt'

SHELL V2.04. (C)Copyright 1986, Matthew Dillon, All Rights Reserved.
You may distribute this program for non-profit only.


INSTRUCTIONS FOR SHELL V2.04

      (A)   Compiling
      (B)   Overview
      (C)   Quicky tech notes on implimentation.

      (D)   Command pre-processor
      (E)   Command-list
      (F)   special SET variables

      (G)   example .login file.


(A) COMPILING:

   NOTE: An executable is provided as compilation instructions are
   difficult AND because there is a good change this version will not
   compile correctly using Manx.  For you Manx hackers: Beware the
   C/Assembly interface when you convert.  There is also a good chance
   you will not have the latest version of MY.LIB.  Also for you Manx
   hackers, you must use the +l option for 32 bit ints.

   This version of my shell MUST be compiled with Lattice. You must use
   the Provided Startup Module rather than Lstartup.obj or Astartup.obj.
   The startup module is equivalent to Astartup.obj except that I have added
   a little code at the beginning to save the BCPL startup state.

   Link using the provided startup module and the following libraries in
   this order:

      MY.LIB AMIGA.LIB LC.LIB

   MY.LIB is my own library which has been posted (but feel free to ask
   me to send it to you if you haven't got it).

   lc1 -i$incdir/ -i$incdir/lattice/ $y
   lc2 -s -v $y

      where $incdir is the include directory for C, and '$y' stands for
      each .C file.  At this point you have nothing but object modules and
      must now link them together:

      NOTE: you MUST use the LC2 options.


   a/blink c.o+main.o+...+run.o library $libdir/my.lib+$libdir/amiga.lib+$libs+$libdir/lc.lib to ram:shell

      NOTE: c.o is provided, do not use standard startups (I said this
      above)


   Executable Size should be around 34K.


(B) OVERVIEW:

   PROBLEMS

   -You should not redirect the RUN command. to redirect the command the
    RUN command is running, embed a standard CLI redirection in the command
    string:

    RUN ">file" command

   -Append '>>' does NOT work with BCPL programs.  It does work with all
    internal and non-bcpl programs.

   OVERVIEW of the major features:

   -simple history
   -redirection
   -piping
   -command search path 
   -aliases
   -variables & variable handling (embedded variables)
   -file name expansion via '?' and '*'
   -conditionals
   -source files  (w/ gotos and labels)
   -many built in commands to speed things up

   NEW FEATURES IN 2.04:
      - CP command now internal... see instructions.
      - RM command now has '-r' option.
      - \command forces the command parser NOT to look at aliases.  Thus,
       you can alias something like 'cd' and have the alias contain a 'cd'
       which references the internal cd:

       alias cd "stuff...;\\cd $x"

      - "-c" command line option to execute commands and return.
       shell -c "echo a;echo b;echo c".
      -_path default now places RAM: and RAM:C first rather than last.
      -_histnum variable .. current history #
      -expanded filenames are sorted.
      -^search^replace (modify previous command).

   NEW FEATURES IN 2.03.  Thanks to Steve Drew who suggested a '_path'
   variable.  The other difference with this version is that BCPL
   output redirection works properly.  Additionaly, alias loops are
   detected (this is what is known as a hack).

   NEW FEATURES IN 2.02.  I would like to thank Dave Wecker and Steve Drew
   for their numerous comments on the previous version of my shell.

   -Return code and error handling
      (A) retrieve return code
      (B) Manual or Automatic error handling.
   -Control C-F now passed to external commands.
   -can execute shell scripts as if they were normal commands (w/ arguments)
    (see down below)
   -C:RUN no longer required.  ext Command loading is faster
   -BCPL programs which change the CLI state (CD/PATH...) now work with
    the shell.  However, the CLI PATH is not used currently.
   -MV command embellished... can now specify multiple files with a
    directory as the destination.
   -'-l' option for DIR
   -CD re-written, new variable $_cwd. startup directory figured out.
   -wildcard expansion no longer cares about case.
   -Comment character '#'
   -EXIT as an alternate to QUIT

   Additional Commands:
      abortline
      forever

   Additional SET variables (see documentation below)
      _cwd           current directory (see CD below)
      _maxerr        worst return value to date
      _lasterr       return value from last command (internal or external)
      _except        contains error level AND exception code. "nnn;command"
                     (see ABORTLINE, and start of section E)

      _passed        contains passed command line to source files
      _path          contains search path (example:  "c:,df1:c/,df0:c/"


(C) QUICK TECH NOTES:

   PIPES have been implimented using temporary RAM: files.  Thus, you
   should be careful when specifying a 'ram:*' expansion as it might
   include the temp. files.  These files are deleted on completion of
   the pipe segment.

   The file names used are completely unique, even with multiple shell
   running simultaniously.

   My favorite new feature is the fact that you can now redirect to and
   from, and pipe internal commands.  'echo charlie >ram:x', for
   instance.  Another favorite:

      echo "echo mem | shell" | shell

   To accomplish these new features, I completely re-wrote the command
   parser in execom.c

   The BCPL 'RUN' command should not be redirected.. .strange things
   happen.

   NO BCPL program should be output-append redirected (>>).


(D)   Command pre-processor

   preprocessing is done on the command line before it is passed on to
   an internal or external routine:

   ^c       where c is a character is converted to that control character.
            Thus, say '^l' for control-l.

   $name    where name is a variable name.  Variable names can consist of
            0-9, a-z, A-Z, and underscore (_).  The contents of the
            specified variable is used.  If the variable doesn't exist,
            the specifier is used.  That is, if the variable 'i' contains
            'charlie', then '$i' -> 'charlie'.  If the variable 'i' doesn't
            exist, then '$i'->'$i' .

   ;        delimits commands.   echo charlie ; echo ben.

   ' '      (a space). Spaces delimit arguments.

   "string" a quoted string.  For instance, if you want to echo five spaces
            and an 'a':

            echo      a       -> a
            echo "    a"      ->      a

   \c       overide the meaning of special characters.  '\^a' is a
            circumflex and an a rather than control-a.  To get a backslash,
            you must say '\\'.

            also used to overide alias searching for commands.

   >file    specify output redirection.  All output from the command is
            placed in the specified file.

   >>file   specify append redirection (Does not work with BCPL programs).

   <file    specify input redirection.  The command takes input from the
            file rather than the keyboard (note: not all commands require
            input).  It makes no sense to say  'echo <charlie' since
            the 'echo' command only outputs its arguments.

   |        PIPE specifier.  The output from the command on the left becomes
            the input to the command on the right.  The current SHELL
            implimentation uses temporary files to store the data.

   !!       execute the previously executed command.
   !nn      (nn is a number).  Insert the history command numbered n (see
            the HISTORY command)
   !partial search backwards through the history list for a command which
            looks the same as 'partial', and execute it.

   #        Enter comment.  The rest of the line is discarded (note: \#
            will, of course, overide the comment character's special
            meaning)


(E)  COMMAND LIST:

   The first argument is the command-name... if it doesn't exist in the
   list below and isn't an alias, it is assumed to be an external (disk)
   command.

   AUTOMATIC SOURCING may be accomplished by naming shell scripts with a
   .sh suffix.  Thus, if you say 'stuff' and the file 'stuff.sh' exists in
   your current or C: directory, it will be SOURCED with any arguments you
   have placed in the $_passed variable.

   EXCEPTION_PROCESSING:

      if no _except variable exists, any command which fails causes the
      rest of the line to abort as if an ABORTLINE had been executed.  If
      the _except variable exists, it is of the form:

      "nnn;commands..."

      where nnn is some value representing the minimum return code required
      to cause an error.  Whenever a command returns a code which is
      larger or equal to nnn, the commands in _except are executed before
      anything.  WHEN _except EXISTS, THE COMMAND LINE DOES NOT ABORT
      AUTOMATICALLY.  Thus, if you want the current line being executed
      to be aborted, the last command in _except should be an "abortline".

      exception handling is disabled while in the exception handling routine
      (thus you can't get into any infinite loops this way).

      Thus if _except = ";", return codes are completely ignored.

      example:

      set _except "20;abortline"


   ABORTLINE

      or just 'abort'.  Causes the rest of the line to be aborted. Used in
      conjunction with exception handling.

      % echo a;abort;echo b
      a


   HELP

      simply displays all the available commands.  The commands are
      displayed in search-order.  That is, if you give a partial name
      the first command that matches that name in this list is the one
      executed.  Generally, you should specify enough of a command so that
      it is completely unique.

   QUIT
   EXIT
   RETURN [n]

      quit my SHELL (awww!).  End, El-Zappo, Kapow. Done, Finis.  If you
      use RETURN and are on the top source level, the shell exits with the
      optional return code.  (see RETURN below)


   SET
   SET name
   SET name string

      The first method lists all current variable settings.
      The second method lists the setting for that particular variable,
      or creates the variable if it doesn't exist (to "")
      The last method sets a variable to a string.

      see the section on special _ variables down below


   UNSET name name name....

      unset one or more variables.  Deletes them entirely.


   ALIAS
   ALIAS name
   ALIAS name string

      same as SET, but applies to the alias list.  You can alias a single
      name to a set of commands.  For instance:

      alias hi "echo a; echo b"

      then you can simply say 'hi'.  Aliases come in two forms the second
      form allows you to place the arguments after an alias in a variable
      for retrieval:

      alias xxx "%i echo this $i is a test"

      % xxx charlie
      this charlie is a test

      The rest of the command line is placed in the specified variable
      for the duration of the alias.  This is especially useful when used
      in conjunction with the 'FOREACH' command.


   UNALIAS name name name...

      delete aliases..


   ECHO string
   ECHO -n string

      echo the string to the screen.  If '-n' is specified, no newline is
      output.


   STRHEAD  varname breakchar string

      remove everything after and including the breakchar in 'string' and
      place in variable 'varname':

         % strhead j . aaa.bbb
         % echo $j
         aaa
         %


   STRTAIL  varname breakchar string

      remove everything before and including the breakchar in 'string' and
      place in variable 'varname':

         % strtail j . aaa.bbb
         % echo $j
         bbb
         %


   SOURCE file [arguments]

      execute commands from a file.  You can create SHELL programs in
      a file and then execute them with this command.  Source'd files
      have the added advantage that you can have loops in your command
      files (see GOTO and LABEL).  You can pass SOURCE files arguments
      by specifying arguments after the file name.  Arguments are passed
      via the _passed variable (as a single string).

      Automatic 'sourcing' is accomplished by placing a .sh extension on
      the file and executing it as you would a C program:

      --------- file hello.sh ---------
      foreach i ( $_passed ) "echo yo $i"
      ---------------------------------
      % hello a b c
      yo a
      yo b
      yo c


   MV from to
   MV from from from ... from todir

      Allows you to rename a file or move it around within a disk.  Allows
      you to move 1 or more files into a single directory.


   CD
   CD ..
   CD path

      Change your current working directory.  You may specify '..' to go
      back one directory (this is a CD specific feature, and does not
      work with normal path specifications).

      CD without any arguments displays the path of the directory you
      are currently in.


   PWD
      rebuild _cwd by backtracing from your current directory.


   RM [-r] file file file...

      DeleteFile().  Remove the specified files.  Remove always returns
      errorcode 0.  You can remove empty directories.  The '-r' option
      will remove non-empty directories by recursively removing all sub
      directories.


   CP file file
   CP file1 file2...fileN dir
   CP [-r] dir1 dir2...dirN dir

      copy files or directories.  when copying directories, the "-r" option
      must be specified to copy subdirectories as well.  Otherwise, only
      top level files in the source directory are copied.


   MKDIR name name name...

      create the following directories.


   HISTORY [partial_string]

      Displays the enumerated history list.  The size of the list is
      controlled by the _history variable.  If you specify a partial-
      string, only those entries matching that string are displayed.


   MEM

      Display current memory statistics for CHIP and FAST.


   CAT [file file....]

      Type the specified files onto the screen.  If no file is specified,
      STDIN in used.  CAT is meant to output text files only.


   DIR [-l] [path path ... ]

      Get a directory listing of the current directory or specified
      directories.  The -l options causes DIR to display time stamps
      as well.


   DEVINFO [device: device:... ]

      Display Device statistics for the current device (CD base), or
      specified devices.


   FOREACH varname ( strings ) command

      'strings' is broken up into arguments.  Each argument is placed in
      the variable 'varname' in turn and 'command' executed.  To execute
      multiple commands, place them in quotes:

      % foreach i ( a b c d ) "echo -n $i;echo \" ha\""
      a ha
      b ha
      c ha
      d ha

      Foreach is especially useful when interpreting passed arguments in
      an alias or source file.

      NOTE: a GOTO inside will have indeterminate results.


   FOREVER command
   FOREVER "command;command;command..."

      The specified commands are executed over and over again forever.

      -Execution stops if you hit ^C
      -If the commands return with an error code.

      NOTE: a GOTO inside will have indeterminate results.


   RETURN [value]

      return from a source file.  The rest of the source file is
      discarded.  If given, the value becomes the return value for the
      SOURCE command.  If you are on the top level, this value is returned
      as the exit code for the shell.


   IF argument conditional argument ;
   IF argument

      If a single argument is something to another argument.  Conditional
      clauses allowed:

      <, >, =, and combinations (wire or).  Thus <> is not-equal, >=
      larger or equal, etc...

      If the left argument is numeric, both arguments are treated as
      numeric.

      usually the argument is either a constant or a variable ($varname).

      The second form if IF is conditional on the existance of the argument.
      If the argument is a "" string, then false , else TRUE.


   ELSE ;

      else clause.


   ENDIF ;

      the end of an if statement.


   LABEL name

      create a program label right here.


   GOTO label

      goto the specified label name.  You can only use this command from a
      source file.


   DEC var
   INC var

      decrement or increment the numerical equivalent of the variable and
      place the ascii-string result back into that variable.


   INPUT varname

      input from STDIN (or a redirection, or a pipe) to a variable.  The
      next input line is placed in the variable.


   VER

      display my name and the version number.


   SLEEP timeout

      Sleep for 'timeout' seconds.



(F) SPECIAL SET VARIABLES

   _prompt
         This variable is set to the command you wish executed that will
         create your prompt.

   _history
         This variable is set to a numerical value, and specifies how far
         back your history should extend.

   _debug
         Debug mode... use it if you dare.  must be set to some value

   _verbose
         Verbose mode (for source files).  display commands as they are
         executed.

   _maxerr
         The worst (highest) return value to date.  To use this, you usually
         set it to '0', then do some set of commands, then check it.  

   _lasterr
         Return code of last command executed.  This includes internal
         commands as well as external comands, so to use this variables
         you must check it IMMEDIATELY after the command in question.

   _cwd
         Holds a string representing the current directory we are in from
         root.  The SHELL can get confused as to its current directory if
         some external program changes the directory.  Use PWD to rebuild
         the _cwd variable in these cases.

   _passed
         This variable contains the passed arguments when you SOURCE a file
         or execute a .sh file.  For instance:

         test a b c d

         -------- file test.sh ----------
         echo $_passed
         foreach i ( $_passed ) "echo YO $i"
         --------------------------------


   _path
         This variable contains the search path when the shell is looking
         for external commands.  The format is:  DIR,DIR,DIR  Each DIR must
         have a trailing ':' or '/'.  The current directory is always
         searched first.  The entire path will be searched first for the
         <command>, then for <command>.sh (automatic shell script sourcing).

         The default _path is set to  "c:,df1:c/,df0:c/,ram:,ram:c/"



(G) EXAMPLE .login file.

   from a CLI or the startup-script say 'SHELL filename'.  That file
   is sourced first.  thus, 'SHELL .login' will set up your favorite
   aliases:

   ------------------------------ example .login source file ----------

echo "shells, Matt"
alias l     "%var if $var;echo $var;else;echo *;endif"
alias c     "echo ^l"
alias cc    "cd ram:;assign c: cb:c"
alias wb    "cd ram:;assign c: sys:c"
alias ed    "run ED"
set dest ram:a
set temp ram:
set ld cb:clib
set incdir cb:include
set libs +$ld/lc.lib
set ops  ""

   --------------------------------------------------------------------


!Funky!Stuff!
fi  # end of overwriting check
echo shar: "extracting 'examples.txt'" '(1870 characters)'
if test -f 'examples.txt'
then
	echo shar: "will not over-write existing file 'examples.txt'"
else
cat << \!Funky!Stuff! > 'examples.txt'
EXAMPLE FILES

------------------------------------------------------------------------
EXAMPLE INTERNAL COMMAND OVERIDING
------------------------------------------------------------------------

#Make CD not only do it's normal function, but also a PWD.

alias cd "%var \\cd $var;pwd"

------------------------------------------------------------------------
.LOGIN
------------------------------------------------------------------------

echo "shells, Matt"
alias l     "%var if $var;echo $var;else;echo *;endif"
alias c     "echo ^l"
alias cc    "cd ram:;assign c: cb:c"
alias wb    "cd ram:;assign c: sys:c"
alias ed    "run ED"
set dest ram:a
set temp ram:
set ld cb:clib
set incdir cb:include
set libs +$ld/lc.lib
set ops  ""


------------------------------------------------------------------------
RAM.SH
------------------------------------------------------------------------
cp c:run ram:; cp c:assign ram:; cp c:cp ram:; assign c: ram:


------------------------------------------------------------------------
C1.SH
------------------------------------------------------------------------
foreach y ( $_passed ) "echo $y;lc1 -o$temp -i$incdir/ -i$incdir/lattice/ $y";echo DONE


------------------------------------------------------------------------
C2.SH
------------------------------------------------------------------------
foreach y ( $_passed ) "echo $y;lc2 -s -v $temp$y";echo DONE


------------------------------------------------------------------------
LD.SH
------------------------------------------------------------------------
blink $ld/lstartup.obj+$_passed library $ld/lc.lib+$ld/amiga.lib $ops to $dest


------------------------------------------------------------------------
LDALL.SH
------------------------------------------------------------------------
set O "";foreach y ( *.o ) "set O $O+$y";strtail O + $O
ld $O;unset O


!Funky!Stuff!
fi  # end of overwriting check
exit 0
#	End of shell archive