home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
zcpr33
/
tcj
/
tcj33.mzg
/
TCJ33.WS
Wrap
Text File
|
1989-03-13
|
51KB
|
1,031 lines
The ZCPR Corner
TCJ Issue 33
For my column this time I plan to cover two subjects, both of which Iì
have dealt with somewhat at length in the past. Nevertheless, there justì
seems to be a lot more to say on these subjects. The first is ARUNZ; theì
second is shells in general, and the way WordStar 4 behaves (or ratherì
misbehaves) in particular.
I was quite surprised and pleased by the enthusiastic response to myì
detailed treatment of ARUNZ in issue 31. Apparently, there were many, manyì
people who were unaware of what ARUNZ was and who are now quite eager to putì
it to use. There are two specific reasons for taking up the subject ofì
ARUNZ here again so soon.
First of all, I think that readers will benefit from a discussion ofì
some additional concrete examples. Since my own uses are the ones I knowì
best, I plan to take the ALIAS.CMD file from my own system as an example andì
discuss a number of interesting scripts. My first cut at doing that forì
this column came out much too long, so I will cover half of the file thisì
time. The other half will be covered in the next column.
The second reason is that I have just gone through a major upgrade toì
ARUNZ. It is now at version 0.9J. Several aspects of its operation asì
described in my previous column have been changed, and quite a few newì
parameters have been added.
The changes in ARUNZ were stimulated by two factors. One is the twoì
new dynamic Z Systems that will have been released by the time you readì
this: NZCOM for Z80 computers running CP/M 2.2 and Z3PLUS for Z80 computersì
running CP/M-Plus. These two products represent a tremendous advance in theì
concept of an operating system, and everyone interested in experimentingì
with or using Z System -- even if he already has a manually installed ZCPR3ì
running now -- should get the one that is appropriate to his computer.
With these new Z System implementations, if your level of computerì
skill is high enough to run a wordprocessor or menu program, then you canì
have a Z System designed to your specifications in a matter of minutes. Youì
can change the design of your Z System at any time, even betweenì
applications. As described later, ARUNZ now has some parameters to returnì
addresses of system components so that aliases can work properly even whenì
those system components move around, as they may do under these dynamicì
systems.
My New Computer System
The second impetus came from my finally building for myself a state-of¡
the-art computer! For most of my work in the past I have used a BigBoard Iì
with four 8" floppy disk drives and an SB180 with four 5" disk drives. ì
Neither machine had a hard disk.
The SB180, my main system for the past year and a half, had beenì
sitting on the floor in the study. The pc board was mounted in a makeshiftì
chassis with two power supplies, just as I got it from someone who bought itì
at the Software Arts liquidation auction and after they had stripped out theì
disk drives (at $25 I could hardly complain!). I added my own drives, whichì
sat in the open air (for cooling among other reasons) in two separate driveì
cabinets elsewhere on the floor. All in all not very pretty and not asì
functional as it could have been.
The sad part of it is that during all this time I had everything neededì
to turn the SB180 into an enjoyable and productive system. A high-speed 35ì
Mb hard disk was collecting dust on a shelf; an attractive surplus Televideoì
PC-clone chassis adorned the work bench in the basement; the XBIOS softwareì
disks sat ignored in one of my many diskette boxes.
Finally one weekend I decided that it would be more efficient in theì
long run to take some time off from my programming and writing work toì
reconstruct the system. Indeed, it has been! The SB180 is now attractivelyì
mounted in the Televideo chassis with one 96-tpi floppy and one 48-tpiì
floppy. The hard disk is configured as four 8 Mb partitions and runs veryì
nicely with the fast Adaptec 4000 controller.
With the hardware upgraded, I then did the same to the software. ì
Installing XBIOS on the SB180 took so little time that I really had to kickì
myself for not doing it sooner. Richard Jacobson was quite right in hisì
description of it in issue 31. Thank you, Malcom Kemp, for a really niceì
product.
Once I was fixing things up, I decided I should really do it up right,ì
so I also purchased the ETS180IO+ board from Ken Taschner of Electronicì
Technical Services -- this despite the fact that a Micromint COMM180 boardì
was also a part of my longstanding inventory of unused equipment. I cannotì
compare the ETS board to the COMM180, never having used the latter, but Iì
certainly am highly pleased with it. XBIOS includes complete support forì
the ETS board, so configuring the system to make use of the extra ETS180IO+ì
features, like the additional parallel and serial ports and the battery¡
backed clock, was very easy.
I have been so pleased with the new system that I even went out andì
bought a real computer table for it to sit on. For the past years, theì
terminal's CRT unit had been sitting on one of those flimsy folding dining¡
room utility tables, with a yellow-pages phone book under it to jack it upì
to the right height. The keyboard sat on a second folding table, and theì
whole thing was always in imminent danger of toppling over. What a pleasureì
it is to sit at the new system.
While I'm waxing enthusiastic, let me mention one other thing I did toì
reduce the disarray in the study. I bought four Wilson-Jones media drawersì
to house my vast collection of floppies. These diskette cabinets resembleì
professional letter filing cabinets. A drawer, which can hold more than 100ì
floppies, pulls out on a full suspension track so that one can easily reachì
all the way to the back. Since there is no top to flip open, units can beì
stacked on top of each other to save a great deal of table space. Clips areì
provided to secure the units to their neighbors both horizontally andì
vertically.
The only drawback to these disk drawers has been their cost. Inmac andì
the other major commercial supply houses want more than $60 each! Butì
Lyben, which sends its catalogs out to many computer hobbyists, offers themì
for only $35. Extra dividers, which I recommend, are just under $6 perì
package of five. Lyben can be reached at 313-589-3440 (Michigan). [Noteì
added at last moment -- I am sorry to say that I just received the new Lybenì
catalog, and the price has now gone up to $45. Although this is still aì
bargain when compared to other vendors' prices, I'm glad I put in my orderì
when I did.]
ARUNZ VERSION 0.9J
Now that I have had my chance to show my excitement over the new stateì
of my computer and computer room, let's get on with the discussion of ARUNZ. ì
First we will discuss the changes introduced since version 0.9G, both theì
old features that have changed and the new features that have beenì
introduced.
Changes in Old Features
-----------------------
Because, as noted in my last column, ZCPR34 can pass commandsì
containing explicit file types or wildcard characters ('?' and '*'), theì
characters used to define special matching conditions in the alias names inì
ALIAS.CMD had to be changed. The period, which had been used to indicateì
the beginning of optional characters in the alias name, has been replaced byì
the comma. The question mark had been used to indicate a wild-characterì
match in the alias name. Since it can now be an actual character to beì
matched, the underscore has replaced it.
Since the command verb can now include an explicit file type (notì
necessarily COM) and/or a directory prefix, several changes have been madeì
to the parameters that parse the command verb. In general, all of theì
command line tokens are now treated in the same way; all four token parsingì
parameters ('D', 'U', ':', and '.') now work with digits from 0 to 9 and notì
just 1 to 9. Thus the command line
C3:TEST>arunz b12:test.z80 commandtail
or, with ARUNZ running as the extended command processor (ECP), the command
C3:TEST>b12:test.z80 commandtail
will have the following parameter values for token 0, the command verb:
$D0 B
$U0 12
$:0 TEST
$.0 Z80
THIS IS A SIGNIFICANT CHANGE. PLEASE TAKE CAREFUL NOTE OF IT. Theì
parameters $D0 and $U0 no longer necessarily return the logged in drive andì
user. For the standard configuration of ZCPR33 (and 34) a verb of the formì
B12:TEST cannot be passed to the extended command processor; the presence ofì
an explicit directory specification results in the immediate invocation ofì
the error handler (skipping the ECP) if the file cannot be found in theì
specified directory. However, if a file type is included, the 'bad' commandì
will be passed to the ECP.
New Features
There are now three new parameters that do return information about theì
directory that was current (logged in) when ARUNZ was invoked. Theseì
parameters are shown below with their meaning and the values they would haveì
with the example command above:
parameter meaning value
--------- ------- -----
$HD Home Drive (D) C
$HU Home User (U) 3
$HB Home Both (i.e., DU) C3
There is also a new parameter to denote the entire command line,ì
including both the command verb and the command tail. Many people in theì
past confused "command line" with "command tail" and attempted to use theì
parameter $* for the former. The new parameter is '$!'. It is roughlyì
equivalent to '$0 $*', but there is one important difference. The latterì
parameter expression always includes a space after the command verb, even ifì
there was no tail ('$*' was null). This space caused problems with someì
commands. For example, when the SLR assembler SLR180 is invoked withì
nothing after it, it enters interactive mode and allows the user to enter aì
series of assembly requests. Unfortunately, the code is not smart enough toì
distinguish a completely nonexistent command tail from one with only spaces. ì
When the command "SLR180_" is entered, where '_' represents a blank space,ì
the assembler looks for a source file with a null name. Not finding it, itì
returns with an error message.
I used to deal with this problem by writing a complex alias of theì
form:
SLR180 if nu $*;asm:slr180;else;asm:slr180 $*;fi
With the new parameter, all this complication can be avoided. The script isì
simply:
SLR180 asm:$!
If you are wondering why one would want an alias like this, just wait aì
while. It will be explained later.
There is also a whole set of new parameters that generate the addressesì
of almost all of the Z System modules. This capability will becomeì
important with the dynamic Z Systems now being introduced (NZCOM andì
Z3PLUS). With those systems, the addresses of the RCP, FCP, CCP, and so onì
can all change during system operation. The new parameters permit one toì
make reference to the addresses of those modules even when they move around. ì
My ALIAS.CMD file described below will have some examples of how theseì
parameters are used.
These parameters begin with $A ('A' for address) and are followed by anì
additional letter as follows:
B BIOS L MCL (command Line)
C CCP M MSG (message buffer)
D DOS N NDR
E ENV P PATH
F FCP R RCP
I IOP S STK (shell stack)
X XFCB (external FCB)
Amazingly enough, these names are all mnemonic except for the conflict overì
'M' between the multiple command line buffer (MCL) and message buffer (MSG). ì
I resolved this by using 'L' (think of LINE) for the MCL.
Finally, there is a new symbol that can be used to make a special kindì
of alias name specification in ALIAS.CMD. If a name element begins with aì
'>', then only the file type of the command verb is used in the comparison. ì
Without this feature one had to use very complex forms to recognize a fileì
type. For example, suppose you want to be able to enter the name of aì
library file as LBRNAME.LBR as a command and have VLU invoked on it. Theì
following script used to be required:
?.LBR=??.LBR=???.LBR=????.LBR=?????.LBR=??????.LBR=
???????.LBR=????????.LBR vlu $0
Every possible number of characters in the library name had to be dealt withì
explicitly. With the new symbol and the other ARUNZ09J features, one canì
define this script more simply as follows:
>LBR vlu $:0
Example ALIAS.CMD File
Now that we have described the new resources available in ARUNZ09J, weì
will begin our look at part of the ALIAS.CMD file that I am using right nowì
on the SB180. It will be the second half of the file, because that partì
contains some items of immediate relevance.
First some words of philosophy. There are many ways in which Z Systemì
can be used effectively, and I am always amazed and impressed at theì
different styles developed by different users. What I will now describe isì
my approach. As they say, yours may differ! In any case, I hope theseì
comments will stimulate some good ideas, and, as always, I eagerly awaitì
your comments and suggestions.
I am a strong believer in short search paths. When I make a mistake inì
typing a command, I do not want to have to twiddle my thumbs while theì
command processor thrashes through a lot of directories searching for theì
nonexistent command. I want the error handler to take care of it as quicklyì
as possible. As a result, the search path on my SB180 includes only oneì
directory, A0, the RAM disk. (With XBIOS, the RAM disk can be mapped to theì
A drive.)
When I enter a command, it is searched for only in A0. If it is notì
found there, then ARUNZ (renamed to CMDRUN.COM) is loaded from A0, and itì
looks for a script in ALIAS.CMD, also in A0. If ARUNZ cannot resolve theì
command, then the error handler, EASE in my case, is invoked (you guessedì
it, also on A0). Thus no directory other than the RAM disk is accessedì
except by an explicit directory reference generated either by an aliasì
script or by a manually entered command. Everything appears to operateì
instantaneously.
Aliases to Provide Explicit Directory Prefixes
Obviously, I cannot keep all the COM files that I use in directory A0. ì
In fact, with the tiny RAM disk on the SB180 (and allowing about 100K for aì
BGii swap file), there is barely enough room for CMDRUN.COM (ARUNZ),ì
ALIAS.CMD, EASE.COM, EASE.VAR, IF.COM, ZF.COM (ZFILER), ZFILER.CMD,ì
SAVSTAMP.COM, ZEX.COM, ZEX.RSX, and a few directory programs. Fortunately,ì
this is all that really needs to be there.
So what do I do about all the other COM files that I want to use? ì
There are two possibilities. I could invoke them manually with explicitì
directory references, as in "B0:CRC FILESPEC", but this would clearly be aì
nuisance (and contrary to the spirit of Z System!). The other alternativeì
is to provide alias definitions in ALIAS.CMD for all the commands in otherì
directories that I want to use.
A second half of my ALIAS.CMD file is shown in Listing 1. The group ofì
aliases at the very end comprises several sets of definitions that do justì
what I have described for several of the directories on the hard disk. As Iì
use programs in other directories, I add them to the ALIAS.CMD file.
These aliases are included at the end, by the way, so that otherì
definitions can preempt them as desired. If you look carefully, you willì
see some aliases defined here that are also defined earlier in the ALIAS.CMDì
file. The earliest definition always takes precedence, because ARUNZ scansì
ALIAS.CMD from the beginning and stops as soon as it encounters a matchingì
name specification.
Directory B0, named SYS, contains most of my system utilities. ì
Directory B1, named ASM, contains my assembly language utilities. A fewì
commonly used files are in other directories. The aliases defined in theseì
sections do nothing more than add an explicit directory prefix to theì
command entered. For example, the script definition
AFIND b0:$!
would take my command line "AFIND TAIL..." and turn it into "B0:AFINDì
TAIL...". Note how compact the definitions can be. You do not need aì
separate line for each command. Similar scripts could be constructed, byì
the way, for COM files kept in COMMAND.LBR and extracted and executed by LX. ì
I do not use LX, so I have no examples to show.
There are several fairly easy ways to automate the construction ofì
these entries in the ALIAS.CMD file. If you use PMATE or VEDIT as your textì
editor, you can write macros that will perform the entire process. That isì
how I generated the aliases you see. With the PMATE macro, I can easilyì
repeat the process from time to time to make sure that all my COM files areì
represented by aliases. So far I have run my PMATE macro on user areas 0,ì
1, 2, 3, and 4 of hard disk partition B.
Lacking these tools, you can run "SD *.COM /FX" to get a file DISK.DIRì
containing a horizontally sorted listing of all the COM files in a directoryì
(without going to a lot of trouble, I do not get a sorted listing fromì
PMATE). Then use your favorite editor, whatever it is, to add carriageì
returns so that each file is on its own line and to delete all of the textì
after the file name (i.e., the dot, file type, and file size). If there areì
any commands for which you want to have special aliases (we'll see someì
examples shortly), you may delete their names from the list (or you canì
leave them -- they do no harm). Then close up the list, inserting equalì
signs and, when the line is wide enough, add the command script. Finally,ì
merge this with the rest of your ALIAS.CMD file.
Aliases for Special Command Redefinitions
Just before the simple redefinition aliases there are six commands thatì
have been separated out for special treatment. Consider the first of them:
ZP,ATCH b0:zpatch $*
I find that my fingers have some difficulty typing the full ZPATCHì
correctly, and this alias permits me to enter simply ZP. Note that in thisì
case we cannot use "b0:$!" for the script because the alias name allows forì
forms other than an exact ZPATCH. If the script used the $! parameter andì
the command was entered as ZP, then the expanded script would become "B0:ZPì
...", which would not work.
The alias for crunching is similar in some respects but more elaborate. ì
The letter combination CH must give me trouble, because I often type CRUNCHì
wrong, too, unless I work very carefully. This alias not only lets me useì
the short form CR; it also allows the command to work with namedì
directories.
CR,UNCH b0:crunch $d1$u1:$:1.$.1 $d2$u2:
By expanding the first and second parameters explicitly, named directoryì
references can be converted to the DU: form that CRUNCH can deal with.
The alias for DATSWEEP goes a little further than the other two insofarì
as alternative forms are concerned.
DATSW,EEP=DS=SWEEP b0:datsweep $*
It allows abbreviated forms as short as DATSW, but it additionally allowsì
alternative nicknames for the command, such as DS or the more familiarì
SWEEP, which it replaces on my system.
The next example in this section shows how a program that does not knowì
about Z System file specifications at all can be made to work with themì
anyway.
LDIR $d1$u1:;b0:ldir $:1;$hb:
For LDIR I just started to use LDIR-B, which displays date stamp informationì
about files in the library. Unfortunately, it does not know about namedì
directories; in fact, it does not even know anything about user numbers. Ifì
he is true to form, Bruce Morgen, the Intrepid Patcher, will soon have aì
ZLDIR-B or an LDRZ-B that will accept full Z System file specs, and I willì
be able to retire this alias.
At present, however, LDIR-B accepts only the standard CP/M syntax forì
files. As a result, it is not enough simply to pick apart the token, as itì
would be if LDIR would accept the form DU:NAME.TYP. Instead, the directoryì
specified for the library is logged into, then the LDIR command is run onì
the library name, and finally the original directory is relogged. This willì
work very nicely unless the user number specified is higher than 15 (andì
your Z33/Z34 is not configured for logging into high user numbers).
The last two examples in this series illustrate still another way toì
make aliases lighten the typing burden. With XBIOS, alternative versions ofì
the operating system are described in model files. These typically have aì
file type of MDL, but that type is not required or the default. ì
Consequently, the SYSBLD system-defining utility and the XBOOT system¡
loading utility must be given an explicit file type. Since I always use MDLì
for the type, I created these aliases to add the file type for me so that Iì
can enter the commands simply as "SYSBLD TEST" or "XBOOT BIGSYS".
SYSBLD b0:;b0:$0 $1.mdl;$hb:
BOOT=XBOOT b0:;b0:xboot $1.mdl
The XBOOT alias lets me save a little typing by omitting the leading 'X' ifì
I wish. The SYSBLD alias returns to the original directory when it isì
finished. Since XBOOT coldboots a new operating system, any trailingì
commands are lost anyway. The XBOOT command will soon support a warmbootì
mode, in which, like NZCOM and Z3PLUS, the new system is created withoutì
affecting the multiple command line, shell stack, or other loaded systemì
modules that have not changed their address or size. I might then add anì
alias REBOOT or WBOOT (warmboot) that will load a new system and return toì
the original directory.
Memory Display Aliases
In my system development work I often have occasion to examine variousì
parts of memory. I might want to look at the beginning of the BIOS to checkì
the hooks into an RSX (resident system extension), or I might want to seeì
the contents of the ZCPR3 message buffer to see how some flags are beingì
used.
I used to have a set of aliases like these with explicit addresses inì
the script ("P FE00" to look at the ENV, for example). This relieved myì
mind of the task of remembering the addresses where these modules wereì
located in memory. With the new dynamic systems, even a good memory willì
not suffice, since the modules can move around, and one can not easily beì
sure just where they are at any given time.
By using the new parameters that I described earlier, the scriptsì
always have the correct addresses. [Actually, they can still be fooled ifì
these parameters are used in multiple-command-line scripts that include theì
loading of a new dynamic system. As I warned in my earlier article onì
ARUNZ, all parameters are expanded at the time the alias is invoked. If theì
system is changed after that, the parameter values may no longer be correctì
when that part of the script actually runs.]
=============================================================================
; Memory display aliases
PBIOS=BIOS p $ab
PCCP=CCP=CPR p $ac
PDOS=DOS p $ad
PENV=ENV p $ae
PFCP=FCP p $af
PIOP=IOP p $ai
PMCL=MCL p $al
PMSG=MSG p $am
PNDR=NDR p $an
PPATH p $ap
PRCP=RCP p $ar
PSHL=PSHELL=SHL=SHELL p $as
PXFCB=XFCB=PFCB=FCB p $ax
; Special equivalents
ZP,ATCH b0:zpatch $*
CR,UNCH b0:crunch $d1$u1:$:1.$.1 $d2$u2:
DATSW,EEP=DS=SWEEP b0:datsweep $*
LDIR $d1$u1:;b0:ldir $:1;$hb:
SYSBLD b0:;b0:$0 $1.mdl;$hb:
XBOOT=BOOT b0:;b0:xboot $1.mdl
; Complete set of direct equivalents
CMDRUN=LPUT=EDIT0=ERA=IF=REN=SD=SDD=XD=ZEX=ZF=VLU=W=ZPATCH=COPY=ECHO b0:$!
FF=GOTO=JF=JETLDR87=NULU=PWD=SAVE=SP=UNCR=VTYPE=XDIR=AFIND=SALIAS=AREA b0:$!
BD=CRUNCH=DFA=DIFF=DISKRST=DOSERR=DU=EDITNDR=ERRSET=HSH=ALIAS b0:$!
LLF=LGET=LOADNDR=LPUT14=LT23=LUSH=LX=MOVE=MU3=PATH=PAUSE=PIP=PROT b0:$!
PROTCCP=PUBLIC=PUTDS=Q=SAP=SAVENDR=SAVSTAMP=SFA=SHCTRL=SHOW=SQ=STAT b0:$!
SUB=SYSGEN=UF=UNERASE=XSUB=DATE=DATSWEEP=MKDIR=SHSET=TPA=Z3INS=Z3LOC b0:$!
ZRIP=ASSGN=BSX=FVCD=HDINIT=HDUTIL=MDINIT=MPTEST=SETDFLT=STARTHD4=SWX b0:$!
SYSBLD=XSYSGEN=TIME=XBOOT0=XVERS=MCOPY=LZED=PUTBG=STARTHD=STARTHD1 b0:$!
STRTFULL=LDR=JETLDR=LHC=SSTAT=XBOOT=MAP=STARTBIG=LT=LDIR=QL=SETD=CRC b0:$!
4ERA=4MU3=4REN=4SAVE=T4MAKE=DOSVER=DRO=LOGGED=SRO=SRW=LBREXT b0:$!
SLR180+=SLRNK=SLRNK+=Z80ASM=DDT=DSDZ=FORM7=MAKESYM=MLOAD=SLRMAC=XIZ b1:$!
ZAS=ZLINK=ZXLATE=SLR180=180FIG32=180FIG+=LNKFIG+=SLRIB=ZLIB=ZREF b1:$!
ZZCNFG=LNKFIG=180FIG b1:$!
BGSERIAL=LOADBG=STARTBG=BGPRINT=BGPRNCFG=DSCONFIG=Q=REMOVE=SECURE b2:$!
SETBG=SPOOLER=DATSWEEP=SDD=SETTERM b2:$!
INSTALL=MEX b3:$!
WSCHANGE=WS=WINSTALL=MOVEPRN b4:$!
Listing 1. The second half of the ALIAS.CMD file from my SB180 with XBIOS,ì
slightly shortened and rearranged.
=============================================================================
Shells and WordStar Release 4
As I noted in an earlier column, WordStar Release 4 was a very excitingì
event for the CP/M world in general and the Z-System world in particular. ì
It was the first major commercial program to recognize Z System and to makeì
use of its features. Unfortunately, the Z System code in WS4 was notì
adequately tested, and many errors, some quite serious, slipped through. ì
Some of the most significant errors concern WS4's operation as a ZCPR3ì
shell.
Let's begin with a little background on the concept of a shell in ZCPR. ì
Normally, during Z System operation the user is prompted for command lineì
input. This input may consist of a string of commands separated byì
semicolons. When the entire sequence of commands has been completed and theì
command line buffer is again empty, the user would be prompted again forì
input.
This prompting is performed by the ZCPR command processor, which,ì
because it is limited in size to 2K, is correspondingly limited in itsì
power. Richard Conn, creator of ZCPR, had the brilliant idea of including aì
facility in ZCPR3 for, in effect, replacing -- or, perhaps better said,ì
augmenting -- the command processor as a source of commands for the system. ì
This is the shell facility.
Under ZCPR3, when the command processor finds that there are no moreì
commands in the command line buffer for it to perform, before it prompts theì
user for input, it first checks a memory buffer called the shell stack. Ifì
it finds a command line there, it executes that command immediately, withoutì
prompting the user for input. The program run in that way is called aì
shell, because it is like a shell around the command processor kernel. Theì
shell is what the user sees instead of the command processor, and the shellì
will normally get commands from the user and pass them to the commandì
processor. In effect, the outward appearance of the operating system can beì
changed completely when a shell is selected.
A perfect example of a shell is the EASE history shell. To the user itì
looks rather like the command processor. But there are two very importantì
differences. First of all, the command line editing facilities are greatlyì
augmented. One can move the cursor left or right by characters, words, orì
commands; one can insert new characters or enter new characters on top ofì
existing characters; characters or words can be deleted. One has, in a way,ì
a wordprocessor at one's disposal in creating the command line.
The second feature is the ability to record and recall commands in aì
history file. Many users find that they execute the same or similarì
commands repeatedly. The history feature of EASE makes this veryì
convenient. These two command generation features require far too much codeì
to include in the command processor itself, so it is very convenient to haveì
the shell capability.
Programs designed to run as shells have to include special code toì
distinguish when they have been invoked by the user and when they have beenì
invoked by the command processor. ZCPR3 makes this information available toì
such programs. When invoked by the user, they simply write the appropriateì
command line into the shell stack so that the next time the commandì
processor is ready for new input, the shell will be called on. After that,ì
the user sees only the shell. Shells normally have a command that the userì
can enter to turn the shell off.
ZCPR3 goes beyond having just a single shell; it has a stack of shells. ì
A typical configuration allows four shell commands in the stack. When theì
user invokes a command designed to run as a shell, it pushes its name ontoì
the stack. When the user cancels that shell, any shell that had beenì
running previously comes back into force. Only when the last shell commandì
has been cancelled (popped from the shell stack) does the user see theì
command processor again.
Let's look at some of the shells that are available under Z System. Weì
have already mentioned the EASE history shell. There is also the HSHì
history shell, which offers similar capabilities. It was written in C andì
cannot be updated to take advantage of innovations like type-3 and type-4ì
commands. I would say that EASE is the history shell of choice today. Thisì
is especially true because EASE can do double service as an error handler asì
well, with the identical command line editing interface.
Then there are the menu shells, programs that allow the user with justì
a few keystrokes to initiate desired command sequences. They come inì
several flavors. MENU stresses the on-screen menu of command choicesì
associated with single keystrokes. VFILER and ZFILER stress the on-screenì
display of the files on which commands will operate; the commands associatedì
with keys are not normally visible. Z/VFILER offer many internal fileì
maintenance commands (copy, erase, rename, move, archive). VMENU andì
FMANAGER are inbetween. Both the files in the directory and the menu ofì
possible commands are shown on the screen.
What Kind of Programs Should be Shells?
Not all programs should be shells. From a strict conceptual viewpoint,ì
only programs that are intended to take over the command input function fromì
the command processor on a semipermanent basis should be shells. Theì
history shells and the MENU and VMENU type shells clearly qualify. Oneì
generally enters those environments for the long haul, not just for a quickì
command or two.
ZFILER and VFILER are marginal from this viewpoint. One generallyì
enters them to perform some short-term file maintenance operations, afterì
which one exits to resume normal operations. It is rare, I believe, toì
reside inside ZFILER or VFILER for extended periods of time, though I amì
sure there are some users who do so.
Many people (I believe mistakenly) try to set up as shells any programì
from which they would like to run other tasks and automatically return. ì
This is the situation with WordStar. No one will claim that the mainì
function of WordStar is to generate command lines! Clearly it is intendedì
to be a file editor. Why, then, was it made into a ZCPR3 shell in the firstì
place? I'm really not sure.
WordStar's 'R' command really does not offer very much. In neither theì
ZCPR nor the CP/M configuration does any information about the operatingì
environment seem to be retained. For example, one might expect on return toì
WordStar that the control-r function would be able to recall the mostì
recently specified file name. But this does not seem to be the case,ì
although it could easily have been done. In the ZCPR version, the nameì
could be assigned to one of the four system file names in the environmentì
descriptor; in the CP/M version it could be kept in the RSX code at the topì
of the TPA that enables WordStar to be reinvoked after a command isì
executed.
The WordStar 'R' command does not save any time, either. Essentiallyì
no part of WordStar remains in memory. The user could just as well use theì
'X' command to leave WordStar, run whatever other programs he wished, andì
then reinvoke WS. Nevertheless, I can understand why users would enjoy theì
convenience of a command like the 'R' command that automatically brings oneì
back to WordStar. Shells, however, are not the way to do this, at least notì
shells in the ZCPR3 sense.
ZCPR2-Style Shells
In ZCPR2 Richard Conn had already implemented an earlier version of theì
shell concept which, interestingly enough, would be the appropriate way forì
WordStar and perhaps even ZFILER/VFILER to operate. He did not have a shellì
stack, but he did have programs like MENU that, when they generatedì
commands, always appended their own invocation to the end of the commandì
line. Thus if the menu command script associated with the 'W' key was "WSì
fn2", where fn2 represents system file name #2, then the actual commandì
placed into the command line buffer would be "WS fn2;MENU". In this way,ì
after the user's command ran, the MENU program would come back.
Let's compare how the two shell schemes would have worked withì
WordStar. Suppose we want to edit the file MYTEXT.DOC and then copy it toì
our archive disk with the command "PPIP ARCHIVE:=MYTEXT.DOC". We might haveì
created the following alias script for such operations:
WSWORK ws $1;ppip archive:=$1
Then we just enter the command "WSWORK MYTEXT.DOC" when we want to work on theì
file and have it backed up automatically when we are done.
Here is what WS4 does as a ZCPR3-type shell. The command line starts outì
as:
WSWORK MYTEXT.DOC
When the alias WSWORK is expanded the command line becomes:
WS MYTEXT.DOC;PPIP ARCHIVE:=MYTEXT.DOC
When WordStar runs, it pushes its name onto the shell stack so that it will beì
invoked the next time the command line is empty. Noting that the command lineì
is not empty, it returns control to the command processor. Then the PPIPì
command is executed, backing up our unmodified file (horrors!!!) Finally theì
command line is empty and WS, as the current shell, starts running. Since itì
was invoked as a shell, it prompts the user to press any key before it clearsì
the screen to start editing. By this time it has forgotten all about the fileì
we designated and it presents us with the main menu. All in all, a ratherì
foolish and useless way to go about things.
You might think that the problem would be solved if WS did not check forì
pending commands but went ahead immediately with its work. Indeed, this wouldì
work fine until the 'R' command was used. Then either the pending PPIP commandì
would be lost (replaced by the command generated by the 'R' operation) orì
executed (if the 'R' command appended it to the command it generated). Inì
either case we have disaster!
Now suppose WS4 had used the ZCPR2-style shell concept. After the aliasì
had been expanded, the "WS MYTEXT.DOC" command would run, and we would edit ourì
file. While in WS4, suppose we want to find where on our disks we have filesì
with names starting with OLDTEXT. We use the 'R' command to enter the commandì
line "FF OLDTEXT". The 'R' command would append ";WS" to the end the commandì
we entered and insert it into the command line buffer before the currentì
pointer, leaving the following string in the buffer:
FF OLDTEXT;WS;PPIP ARCHIVE:=MYTEXT.DOC
After the FF command was finished, WordStar would be executed again. Just whatì
we wanted.
In fact, under ZCPR3 WS could be much cleverer than this. First of all,ì
it could determine from the external file control block the name (and under Z33ì
the directory) used to invoke WordStar in the first place. There would be noì
need, as there is now, to configure WS to know its own name and to make sureì
that the directory with WS is on the command search path. The 'R' commandì
could have appended "B4:WSNEW" if WSNEW had been its name and it had beenì
loaded from directory B4.
There is one problem, however. We would really like WS to wait beforeì
clearing the screen and obliterating the results of the FF command. With theì
ZCPR3-type shell, WS can determine from a flag in the ZCPR3 message bufferì
whether it was invoked as a shell. For the ZCPR2-style shell we would have toì
include an option on the command line. WS could, for example, recognize theì
command form "WS /S" as a signal that WS was running as a shell. It would thenì
wait for a key to be pressed before resuming, just as under a ZCPR3-styleì
shell. Of course, you would not be able to specify an edit file with the nameì
"/S" from the command line in this case, but that is not much of a sacrifice orì
restriction.
We could continue to work this way as long as we liked. Only when weì
finally exited WS with the 'X' command would the PPIP command run. This, ofì
course, is just the right way to operate!
ZCPR2 vs ZCPR3 Shell Tradeoffs
Once I started thinking about the old ZCPR2-type shells, I began to wonderì
why one would ever want a ZCPR3-type shell. At first I thought that Z2-styleì
shells could not be nested, but that does not seem to be the case. Suppose weì
run MENU and select the 'V' option to run VFILER. The command line at thatì
point would be
VFILER;MENU /S
where we have assumed that a "/S" option is used to indicate invocation as aì
shell. While in VFILER we might run a macro to crunch the file we are pointingì
to. The macro could spawn the command line "CRUNCH FN.FT". The command lineì
buffer would then contain
CRUNCH FN.FT;VFILER /S;MENU /S
After the crunch is complete, VFILER would be reentered. On exit from VFILERì
with the 'X' command, MENU would start to run. Thus nesting is not onlyì
possible with Z2-type shelling, it is not limited by a fixed number of elementsì
in the shell stack as in ZCPR3 (the standard limit is 4). Only the size of theì
command line buffer would set a limit.
What disadvantages are there to the Z2-style shell? Well, I'm afraid thatì
I cannot come up with much in the way of substantial reasons. The shell stackì
provides a very convenient place to keep status information for a program. Iì
do that in ZFILER so that it can remember option settings made with the 'O'ì
command. On the other hand, this information could be kept as additional flagsì
on the command line, as with the "/S" option flag. There is no reason why theì
information could not be stored even in binary format, except that the nullì
byte (00 hex) would have to be avoided.
If the 128 bytes currently set aside for the shell stack were added to theì
multiple command line buffer, the use of memory would be more efficient than itì
is now with Z3-style shells. Z3 shells use shell stack memory in fixed blocks;ì
with Z2 shells the space would be used only as needed. I rarely have more thanì
one shell running, which means that most of the time 96 bytes of shell stackì
space are totally wasted. Of course, with the present setup of ZCPR3, theì
multiple command line buffer cannot be longer than 255 bytes, because the sizeì
value is stored in the environment descriptor as a byte rather than as a word. ì
The command line pointer, however, is a full word, and so extension to longerì
command lines would be quite possible (I'll keep that in mind for Z35!).
Following this line of reasoning, I am coming to the conclusion that onlyì
programs like history shells and true menu shells should be implemented asì
ZCPR3-style shells. Other programs, like ZFILER and WordStar should use theì
ZCPR2 style. If I am missing some important point here, I hope that readersì
will write in to enlighten me.
Forming a Synthesis
So long as the command line buffer is fixed at its present length and soì
long as 128 bytes are set aside as a shell stack, one should make the best ofì
the situation. Rob Wood has come up with a fascinating concept that does justì
that.
Rob was working on Steve Cohen's W (wildcard) shell. He recognized thatì
on many occasions one wants to perform a wildcarded operation followed by someì
additional commands (just as with the WordStar example followed by PPIP). As aì
ZCPR3-type shell, W could not do this. It always executed what it was supposedì
to do after the wild operation before the wild operation!
Rob came up with a brilliant way to combine the ZCPR2 and ZCPR3 shellì
concepts. When his version of W is invoked manually by the user, it pushes itsì
name, as a good ZCPR3 shell does, onto the shell stack. But it does not thenì
return to the command processor to execute commands pending in the commandì
line. It starts running immediately, doing the thing it was asked to do andì
using the shell stack entry to maintain needed data.
In the course of operation, however, it does one unusual thing. Afterì
each command that it generates and passes to the command line buffer, itì
appends its own name, as a good ZCPR2 shell does. This command serves as aì
separator between the shell-generated commands and those that were on theì
original command line after the W command. After the shell-generated commandsì
have run, W starts to run. It checks the top of the shell stack, and if itì
finds its own name there, it says "Aha, I'm a shell," and proceeds to use theì
information in the shell stack to generate the next set of commands. Thisì
process continues until W has no more work to do. Then it pops its name offì
the shell stack and returns to the command processor. The commands originallyì
included after the W command are still there and now execute exactly asì
intended. Beautiful!
WordStar Shell Bugs
It is bad enough that WordStar's conceptual implementation as a shell isì
flawed. On top of that, the shell code was not even written correctly. Theì
person who wrote the code (not MicroPro's fault, I would like to add) tried toì
take a short cut and flubbed it. When a shell installs itself, it shouldì
always -- I repeat, always -- push itself onto the stack. WordStar tries toì
take the following shortcut. If it sees that the shell stack is currentlyì
empty, it just writes its name into the first entry, leaving the other entriesì
as they were.
When WordStar terminates, however, it pops the stack. At this pointì
whatever junk was in the second shell stack entry becomes the currently runningì
shell. The coding shortcut (which I would think took extra code rather thanì
less code, but that is beside the point) assumed that if the current shellì
stack entry was null, all the others would be, too. But this need not be theì
case at all. And in many cases it has not in fact been the case, and veryì
strange behavior has been observed with WordStar. Some users have reportedì
that WordStar works on their computers only if invoked from a shell! That isì
because WordStar properly pushes itself onto the stack in that case.
There are basically two strategies one can take for dealing with the shellì
problems in WordStar. One is to fix the above problem and live with the otherì
anomalies (just don't ever put commands after WS in a multiple command line). ì
The other is to disable the shell feature entirely.
To fix the bug described above, Rick Charnes wrote a program calledì
SHELLINI to initialize the shell stack before using WordStar. On bulletinì
boards in the past both Rick and I presented aliases that one can use toì
disable the shell stack while WS is running and to reenable it after WS hasì
finished. I will now describe patches that can be made directly to WordStarì
itself. First I will explain what the patches do; later I will discuss how toì
install them.
Listing 2 shows a patch I call WSSHLFIX that will fix the bug justì
described. The code assumes that you do not already have any initialization orì
termination patches installed. If you do, you will have to add the routinesì
here to the ones you are already using.
The patch works as follows. When WS starts running, the initializationì
routine is called. It extracts the shell stack address from the ENV descriptorì
and goes there to see if a shell command is on the stack. If there is, noì
further action is required, since WS already works correctly in this case. If,ì
on the other hand, the first shell entry is null, then the routine calculatesì
the address of the beginning of the second shell entry and places a zero byteì
there. When this stack entry is popped later, it will be inactive.
Listing 3 shows a patch I call WSSHLOFF that will completely disable theì
shell feature of ZCPR3 while WS is running. It works as follows. When WSì
starts running, the initialization routine is called. It gets the number ofì
shell stacks defined for the user's system in the ENV descriptor and saves itì
away in the termination code for later restoration. Then it sets the value toì
0. WordStar later checks this value to see if the shell feature is enabled inì
ZCPR3. Since WordStar thinks that there is no shell facility, it operates theì
'R' command as it would under CP/M. Later, on exit from WS, the terminationì
routine restores the shell-stack-number so that normal shell operation willì
continue upon exit from WS.
The easiest way to install these patches is to assemble them to HEX filesì
and use the following MLOAD command (MLOAD is a very useful program availableì
from remote access systems such as Z Nodes):
MLOAD WS=WS.COM,WSSHLxxx
Substitute the name you use for your version of WordStar and the name of theì
patch you want to install. That's it; you're all done.
If you do not have MLOAD, you can install the patches using the patchingì
feature in WSCHANGE. From the main menu select item C (Computer), and fromì
that menu select item F (Computer Patches). From that menu, work through itemsì
C (initialization subroutine), D (un-initialization subroutine), and E (generalì
patch area), installing the appropriate bytes listed in Table 1.
Summary
We have covered a lot of material this time. The issue of shells is aì
very tricky one, and I hope to hear from readers with their comments. I wouldì
also enjoy learning about interesting ARUNZ aliases that you have created.
=============================================================================
; Program: WSSHLFIX
; Author: Jay Sage
; Date: March 26, 1988
; This code is a configuration overlay to correct a problem in the shell
; handling code in WordStar Release 4.
;
; Problem: WS takes a mistaken shortcut when installing its name on the shell
; stack. If the stack is currently empty, it does not bother to push the
; entries up. However, when it exits, it does pop the stack, at which point
; any garbage that had been in the stack becomes the active shell. This patch
; makes sure that the second stack entry is null in that case.
;---- Addresses
initsub equ 03bbh
exitsub equ 03b3h
morpat equ 045bh
;---- Patch code
org initsub ; Initialization subroutine patch
init: jp initpatch
;----
org morpat ; General patch area
initpatch: ; Initialization patch
ld hl,(109h) ; Get ENV address
ld de,1eh ; Offset to shell stack address
add hl,de ; Pointer th shell stack address in HL
ld e,(hl) ; Address to DE
inc hl
ld d,(hl)
ld a,(de) ; See if first entry is null
or a
ret nz ; If not, we have no problem
inc hl ; Advance to ENV pointer to
inc hl ; ..size of stack entry
ld l,(hl) ; Get size into HL
ld h,0
add hl,de ; Address of 2nd entry in HL
ld (hl),0 ; Make sure that entry is null
ret
end
Listing 2. Source code for a patch to fix the bug in the coding of shell
stack pushing and popping in WordStar Release 4.
=============================================================================
; Program: WSSHLOFF
; Author: Jay Sage
; Date: March 26, 1988
; This code is a configuration overlay to correct a problem in the shell
; handling code in WordStar Release 4.
;
; Problem: Because WordStar runs as a ZCPR3 shell, it is impossible to use
; WS in a multiple command line with commands intended to execute after WS is
; finished. One can disable this by patching the ZCPR3 environment to show
; zero entries in the shell stack while WS is running. This effectively
; disables WS4's shell capability. Unfortunately, it means that the extended
; features of the 'R' command under ZCPR3 are also lost.
;---- Addresses
initsub equ 03bbh
exitsub equ 03beh
morpat equ 045bh
;---- Patch code
org initsub ; Initialization subroutine
init: jp initpatch
;----
org exitsub ; Un-initialization subroutine
exit: jp exitpatch
;----
org morpat ; General patch area
initpatch: ; Initialization patch
call getshls ; Get pointer to shell stack number
ld a,(hl) ; Get number
ld (shstks),a ; Save it for later restoration
ld (hl),0 ; Set it to zero to disable shells
ret
exitpatch: ; Termination patch
call getshls ; Get pointer to shell stack number
shstks equ $+1 ; Pointer for code modification
ld (hl),0 ; Value supplied by INITPATCH code
ret
getshls:
ld hl,(109h) ; Get ENV address
ld de,20h ; Offset to number of shell entries
add hl,de ; HL points to number of shell entries
ret
end
Listing 3. Source code for a patch that disables the shell feature of
ZCPR3 while WordStar 4 is running and reenables it on exit.
=============================================================================
WSSHLFIX patch bytes:
initialization subroutine: C3 5B 04
un-initialization subroutine: 00 00 C9 (should be this way already)
general patch area: 2A 09 01 11 1E 00 19 5E 23 56 1A
B7 C0 23 23 6E 26 00 19 36 00 C9
WSSHLOFF patch bytes
initialization subroutine: C3 5B 04
un-initialization subroutine: C3 65 04
general patch area: CD 6B 04 7E 32 69 04 36 00 C9 CD 6B
04 36 00 C9 2A 09 01 11 20 00 19 C9
Table 1. List of HEX bytes for installing either of the patches into
WordStar Release 4 to deal with the problems in the shell code.