home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
336.lha
/
Ash
/
TechNotes.doc
< prev
next >
Wrap
Text File
|
1989-12-27
|
5KB
|
199 lines
Technical Notes
ASH
A ksh-like Shell for the Amiga
Version 1.0
(Copyright) 1989
Steve Koren
November 7, 1989
Implementation Notes
Ash is the result of over 3 month's of evening and weekend
work on an Amiga 2000 with a Xetec hard disk controller, 85mb
Seagate drive, and 3mb of ram. The parser, lexical analyzer,
and program architecture were completed very quickly; most of
the time was spent trying to figure out how to do Amiga
specific things (like directories) and working around compiler
bugs.
Ash has a parser that was generated using Amiga yacc and
modified by hand to deal with some special features of Ash
(such as command substitution). The lexical analyzer was
written by hand, since I needed some capabilities not present
in Lex.
Internally, Ash uses hash tables to keep track of variables,
aliases, functions, and keywords. A stack of hash tables is
maintained, and each time a function is called, a new hash
table is pushed onto the stack. Then, when a name is
referenced, it is looked up in the hash table stack starting
with the most recent hash table. When a function exits, the
most recent hash table is popped off the stack and its
contents are freed. Hash table entries have an associated
type (variable, function, etc), and a value, which can be
either a text string (such as an alias definition) or a
pointer to a parse tree (for a function).
Ash was written to be reentrant, so that in the future
interprocess pipes may be used between internal and external
commands. Thus, all evaluation is done using only information
passed around in an "EVAL_PACKET" structure so that no globals
are referenced. Each execution of the command interpreter
generates its own hash table stack, its own pointer to input
and output files, etc. The few parts of Ash which are not
reentrant are written using a semaphore-based locking
mechanism. This locking mechanism is intelligent; it does not
lock out all other tasks from the system (as Forbit() and
Permit() do), but simply allows only a single task to execute
a given section of program code at one time.
All output is done through a single low level routine which,
given an EVAL_PACKET and some text, will route it to either a
file or a string (in the case of command substition). The
length of the space allocated for this string is kept in the
EVAL_PACKET, and if the new text would cause the string to
overflow its allocated space, more space is allocated and the
original is copied into the new space. Thus, command
substition and variables can deal with text of any length
limited only by free memory.
There are no hard-coded branches to routines which execute Ash
builtin commands. A single structure contains all necessary
information for builtin commands, including their name, a
ASH Amiga Shell Page 2 Technical Notes
pointer to their execution routine, and a few other things.
This architecture makes it trivial to add new builtin
commands. Keywords are dealt with in the same way.
A series of test scripts is run whenever Ash is changed.
These scripts test all the Ash commands and syntax. The
output of these tests are compared against known good results
to verify that no previously working commands were broken
inadvertantly. The entire series of 20 test scripts takes
about 10 minutes to run on a stock 7.x mHz Amiga 2000.
Since the entire Ash project was implemented on an Amiga, and
Ash was designed for Amigas, it currently runs only there. It
was, however, designed with machine independence in mind. The
machine specific code is enclosed in #ifdef AMIGA statements,
and could conceivably be replaced with code specific to
another machine.
ASH Amiga Shell Page 3 Technical Notes