home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
ZCPR33
/
A-R
/
PLF10.LBR
/
ALIAS.NZT
/
ALIAS.NOT
Wrap
Text File
|
2000-06-30
|
38KB
|
727 lines
PLF CHIT CHAT 'N' MISCELLANEA
-----------------------------
I have had the idea for writing this for maybe six months. A year or so
after the introduction of the LZW crunching algorithm we in the CP/M-
compatible world still have no all-purpose library utility with a
"sweep" mode (NULU's superb advance over LU) that can read crunched
files the way NULU does for squeezed files. When we get such a utility
PLF will self-destruct; there will be no need for it. I have been
especially surprised we have nothing that will extract crunched text
files directly to the list device; in PLF I try to deal with this
problem, admittedly in a roundabout (but rather enjoyable, for me!) way.
This whole series of aliases that Frank Gaude' and I have been writing --
GLF, TLF and now PLF -- are all attempts to deal with this fundamental
deficiency in our library toolset.
When I use NULU -- to operate inside libraries containing no crunched
members -- I ALWAYS use it in its F)ilesweep mode, which gives the user
the highest degree of facility and flexibility in various library
operations. Its fundamental advantage is the ability to VIEW the
library directory, perform a library operation and then once again be
presented with the library directory once the operation terminates. The
fundamental advance made initially by Frank's GLF retained this feature
of NULU; it incorporated LLF and LGET so that you were first presented
with a directory and then BASED ON THAT could make a decision as to what
file to extract. With PLF I have retained this advantage of NULU. A
listing of the library directory returns to you after ANY operation,
waiting again for your input.
It is because of this feature that even when John Poplett produced the
excellent ZLBR.COM I was still unsatisfied. I am always unsure of
exactly what operation I wish to perform on what file unless I have the
library directory in front of me, and with ZLBR one has to constantly do
a 'DIR' command to attain this. PLF solves this problem.
PLF not only combines the functions of the previous two aliases Get
Library Files and Type Library Files but adds a third function as well,
that of printing. It operates through a series of nine (PLF.CMD) or
eleven (PLF-RAMD) separate nested aliases to be placed in one's
ALIAS.CMD file.
I have deviated here, however, from the fundamental toolset that Frank
and I had been using in our previous aliases. Rather than using GETVAR
as we had previously to "get" and then carry the name of the library
member, I have here taken advantage of the extraordinary file parsing
ability of ARUNZ. Using the "user prompt" technique available through
ARUNZ's $" and $' symbols and then carrying the response in parameters
to a new alias, one may simulate what GETVAR does in actuality. As will
be seen in the technique I use for printing compressed files, ARUNZ's
ability to return the file type of a parameter is of tremendous value.
I might add that I began writing this alias before Dreas Nielsen
produced GETVAR12 which has the ability to abort with CTL-C. It was
precisely for the PLF alias on which I was then working that I had asked
him to write it. The only way the user had at the time to abort from
the GETVAR prompt was through the very time-consuming technique of
invoking a separate 'EXIT' alias. With GETVAR12 this problem is
eliminated.
I enjoyed developing the technique I've implemented to print compressed
files in the RAM- and hard-disk version of PLF, (PLF-RAMD.CMD). (The
following discussion applies only to this version. Since it involves
several re-loads of nested aliases I thought it better to leave out of
the floppy version which should execute more quickly.) I thought about
it for days: how can I print a compressed file the real name of which I
don't as of yet know? (I have only the name of its compressed form,
"*.?z?" or "*.?q?" still in the library.) The solution I came up with
uses one of those many lovely "first generation" shell utilities that so
few people seem to use besides shell stalwarts like Dreas Nielsen and
myself, SHVAR. (The others being of course SH, SHDEFINE, and SHFILE.)
If the filetype equals, for instance, 'ZZ0' or 'ZQ0' ('IF EQ $.2 Z?0')
then we define the shell variable 'P' -- again kept as short as possible
-- to be 'Z80', and print accordingly. I took a sampling of as many
"standard" crunched filetypes as was reasonably possible, and made shell
variables out of their uncrunched counterparts. We save space by simply
defining the filetype variable for these possibles, and THEN and only
then execute our PRINT XXXXXX command. Note that this saves a
tremendous amount of command line buffer space over any method not using
shell variables. The last several lines, already long as they are,
would be totally infeasible without it. If I had tried:
if eq $.2 Z?0;print $:2.Z80;else;if eq $.2 d?c;print $:2.DOC...etc...
it would have overflowed faster than you can say Jackie Robinson.
I like to use this technique whenever possible in aliases.
Note, by the way, my use here of RESOLVE (RS) in front of both the PRINT
and ERA commands to resolve the 'P' shell variable, thus completing our
adventure into the shell world.
Of course there are always going to be many crunched and squeezed
filetypes which I have not been able to include in this "table." I have
included: L?B (LIB), M?C (MAC), D?C (DOC), I?F (INF), Z?0 (Z80), U?D
(UPD), N?T (NOT), M?G (MSG), H?S (HIS) and ZZZ (no filetype), but you
will undoubtedly come across others not in this list. If as noted above
LT is patched to ignore all popular binary file types, our rather
primitive PRINT.COM is most certainly not. (It is so primitive in fact
that it does not even provide a "FILE NOT FOUND" error message if it
cannot find the filename parameter!) Hence we have to provide some way
of ensuring that we don't give a .COM or .REL file to PRINT for
printing! So I try as best as I can to provide accurate filetypes to
it. I have made provision for filetypes not included in our table in a
very nice way, I feel.
Any time PLF _does_ find the provided filetype in its table, it will set
register 1 to a non- zero value. When we have exhausted the filetype
table but before getting to the 'RESOLVE/PRINT/ERA' command, register 1
is tested. If it is a non-zero value, variable P has the value found in
the table. If register 1 is 0, SHVAR then defines P as the string '*
I'. Why this string? Well, we have a problem. Actually, since PLF
prints and then erases our file, we have two problems. If we don't have
the exact name of the file, we can rely on the ability of PRINT.COM and
ERA.COM to accept unambiguous/wildcarded filename parameters. We can do
'PRINT Z80DOS.*' and often get quite decent and reasonable results. So
we can get SHVAR to send a '*' in place of any specific, known filetype.
But what if, as is often the case, the file we're printing has the same
name as the library (.LBR file) from which it came? Or suppose there is
a .REL file or .COM file or any other, non-printable files of the same
fileNAME as the file in question? We certainly don't want PRINT.COM to
be trying to print Z80DOS.LBR!! So --- we get SHVAR to store an 'I' for
"Inspect mode" along with the '*' in the variable. It just so happens
that PRINT and ERA both use this "I" as an option switch, which works
absolutely wonderfully, since we certainly don't want to erase anything
unnecessarily either! Our variable becomes '* I' and our full command
line becomes:
print z80dos.* i;era z80dos.* i
(ARUNZ resolves '$$|' into '$' which RESOLVE.COM then resolves into a
semicolon, ';'.)
Well, take a look at the resultant command line. Suppose our file was
'Z80DOS.BZD', and therefore our unknown filetype would be 'BZD'.
rs print $:2.%p$$|era $:2.%p
would therefore resolve into:
print z80dos.* i;era z80dos.* i
This works perfectly. In case we have picked up some unwanted
Z80DOS.??? files we are put into inspect mode for PRINT, and we next can
decide if we indeed want to erase whatever file(s) we are presented.
In P8 we use the Z33 flow control (IF COmpressed) to test if the user's
file is indeed crunched or squeezed. I create a 'dummy' filename of 'x'
since there's no reason to waste precious buffer space with the real
filename! If it is not crunched, we have no problem and PRINT.COM will
take care of it no sweat. Only if it is will it pass it on to P7 for
further processing.
The 'IF GT $2 ??' in the P3 alias is my ingenious way of distinguishing
whether the user entered a file name, in which case I want PLF to run
LT, or a '/E' or '/P' in which case he wants to extract or print and PLF
uses LEX. It tests specifically for whether the string entered as the
first token (to later become $2) at the PLF prompt has more than two
characters. Since virtually all genuine file names meet this condition,
we can assume that any entered string NOT meeting this condition is
either a '/E' or '/P'.
You'll notice a large number of aliases. After much experimenting I
realized this was the only way to deal with the situation of a
potentially very large command line. If the user is processing
three files the command line will push the buffer to the limit. You
want to be really careful about overflowing your buffer here, and I
think I've made some pretty good, well-reasoned and necessary
compromises between speed (sacrificed with multi-aliases) and space.
You might find some places where you'll be tempted to wonder, "Why
didn't he combine this with the previous alias?" You can rest assured
that I did consider that and was paid a visit by our good friend 'Ovfl'
after a long user input string.
I additionally had to contend with the fact that we surprisingly don't
have a utility for typing crunched files from libraries, with all the
standard Z features such as DIR: and a possible file list.
I don't know if all the '$zzif' (buffer-flushing and 'zif') at the
beginning and 'zif' at the end of EVERY alias is really necessary. When
you're in the process of writing aliases like these, however, and upon
exit you're always finding your IF state set to some damn level or
another, your tendency is to pull out your heavy ammo and go for broke;
these guarantee to smash any IF level that dares to rear its wooly head.
I have noticed a bug in BackGrounder ii v1.13 with the IF EXIST test.
When that option is not enabled in the resident FCP so the testing is
automatically passed by the FCP to COMIF (IF.COM), then IF EXIST does
not operate properly if no DU: or DIR: specification precedes the
filename. Aliases that I had on my system with the traditional Z-System
opening syntax:
IF EX $1; ... [commands] ....;ELSE;echo $1 doesn't exist
would always seem to return "$1 doesn't exist"!! I couldn't figure out
why until I brought it to the attention of Jay Sage who tested and
confirmed the bug. He noticed that if a DU: or DIR: is given it works
properly and that if IF.COM is invoked directly it works fine as well!
The way I have solved this problem -- and I have incorporated this
solution into PLF -- is by changing all my alias beginnings from
'IF EX $1' to 'IF EX $D1$U1:$.1.$.1 or whatever is appropriate. The
latter form ensures that when the alias is expanded and sent to the
command line buffer the current DU: is included in the parameter. If in
PLF if I had used only 'IF EX $1.LBR', then if the user was logged on to
the same directory as the library in question and therefore did not
include a DU: or DIR: spec, what would be sent to the command would not
have a DU:/DIR: reference and would be tested incorrectly by BGii1.13.
Using the form 'IF EX $D1$U1:$:1.LBR' instead forces the logged drive to
to be appended to the beginning of the expansion.
You will notice, by the way, that throughout the various PLF aliases I
have often used this '$d1$u1:.....' form rather than the seemingly
shorter and more simple '$1'. This is actually to save space in the
command line buffer, though a visual impression of the alias gives the
complete opposite impression! Suppose we have a 'LETTERS' directory
associated with C4: If a user has entered
'LETTERS:MICROPRO.LTR'
in response the PLF prompt, and our aliases uses the '$1' form, the full
20-character token will be sent to the buffer. If however, we use
'$d1$u1:$:1.$.1', what is sent to the buffer will only be
'C4:MICROPRO.LTR'
thus saving 4 bytes, which should always be a consideration for us -- in
Jay Sage's words -- "super-alias hackers."
* * *
Creation of this alias would have been easier if:
(1) LBREXT could accept parameters separated by spaces rather than only
a file list separated by commas; or,
(2) We had a Z-System version of LT that would accept a NDR: reference.
I think/hope these are soon to come.
Thoughts on Aliases and Other ZCPR33 Miscellanea
------------------------------------------------
I have spent a lot of time developing a satisfactory technique to loop
back and forth between two different commands one of which is an alias.
One of the major purposes for which I want this is for ongoing
development of my ALIAS.CMD. One's ALIAS.CMD file is one's most
precious possession. It is the most concrete and personal expression of
one's creativity in Z-System, the purified essence of our love of Z, the
shining gemstone of our OS. What I find myself often doing is looping
between editing (usually with VDE) an alias I'm developing in ALIAS.CMD,
and EXECUTING it. For instance, as I was developing PLF, I must have
performed the two sequences:
PLF DIR:TESTLIB ; VDE A15:ALIAS.CMD
2 1/2 million times. How nice it would be for software to automate this
loop. I would run PLF, test it out in all its hundreds of permutations,
then immediately upon exit VDE would automatically load ALIAS.CMD. Upon
VDE exit, I would be queried as to whether I wish to repeat the loop,
and the system would respond accordingly.
Note, of course, that 'PLF DIR:TESTLIB' is itself a VERY long and
complex sequence of multiple command lines, so we are not talking here
about "two commands."
Sure, you one can use HSH or whatever and simply recall the previous
line. But the whole purpose of computers is to automate operations. It
is much cleaner, more elegant, and fun -- of course the most important
REAL use of computers -- to have the computer automatically execute the
next operation in the loop.
In private conversation Jay Sage and others have suggested making the
sequence "PLF DIR:LIBNAME;VDE A15:ALIAS.CMD" an alias in itself, called
say, "PLF-LOOP". I would then have a separate 'RECURSE' alias (actually
a two-alias sequence) like those Jay has put into his ALIAS.CMD or
illustrated in his The Computer Journal #28 article (to which magazine,
by the way, all Z-System users should subscribe at $16 per year to 190
Sullivan Crossroad, Columbia, Montana 59912):
RECURSE recurse2 $*
fi
RECURSE2 fi
$*
echo run "$1" again?
if in
$0 $*
This would run my alias "LOOP" consisting of my two command sequences,
then ask me if I want to run "LOOP" again, and respond accordingly.
There are two faults I find with this technique. First and foremost,
it's inconvenient and inelegant to have to make a separate alias each
time you do something like this. If I had to make either a standalone
alias with V/B/SALIAS or an alias entry in ALIAS.CMD each time I was
doing this looping I'd go crazy. This is/should be a spontaneous,
automated process.
The second problem cuts a bit deeper and more philosophical: it cannot
be used, as I most often wish to do, if either of the command sequences
in question is a nested alias using the '$z' symbol. Once the 'RECURSE'
alias encounters a single '$z' in any alias that is running inside of
it, the command line buffer is completely flushed and all processing is
halted. Any nesting that any of my PLF aliases want to do is prevented
and we are returned to the command line.
I realized that I almost always was using these looping techniques
with a single and "fixed" first command line: "VDE A15:ALIAS.CMD", so I
set up developing them based on this. There are three methods I came up
with, the first two of which I have found not fully satisfactory and the
last of which pretty much does the trick but needs some work. From the
beginning:
(1) An alias similar to Jay's RECURSE, simply:
LOOP vde a15:alias.cmd;$*;if in repeat loop?; LOOP $*;fi
Very simple and very useful for me --- except under one
circumstance, my most common one, the same as that under which
Jay's RECURSE will not work: if the command sequence in question
is itself a recursive alias using the '$z' symbol. In other words:
no PLF again.
(2) Actually my favorite: using SHSET and CMD. That is:
SHSET VDE A15:ALIAS.CMD;new sequence;CMD
This is great to use, and a lot of fun. There are two problems
with it. Number one, your entire command line above cannot exceed
32 characters, the size of a single shell stack entry. I
temporarily dealt with this problem in an interesting way: I
changed my shell stack system to having 2 entries of 64 bytes each
rather than 4 of 32. Easy to do. Either load a new SYS.ENV
configured thusly or even more simply, just POKE FE20 02 40. FE20
on MOST systems holds the number of shell stack entries and FE21
the size of each. Now it's 2 of 64 and the above command line
works fine. Except for problems number two and three. Yeah, you
guessed number two: no aliases with '$z' allowed. So much for
that. But the third is most interesting.
Read Jay's description of the SHELLIF option in the Z33 Users Guide
to get a taste of the whole issue. I use the shell utilities
(SH.COM, SHVAR.COM, RESOLVE.COM, GETVAR.COM, etc.) frequently and
disagree with Jay regarding the value of using flow control in
custom-created shells; I think it's a great idea and would like to
do it more, but of course mine is a user's perspective and I have
no idea of the coding involved. With the Z30 command processor
doing so was impossible. With Z33 it's discouraged and difficult.
Jay has explained that you can have flow control inside of custom
shells or you can have flow control in your regular commands, but
not both.
A true solution will require two different flow control systems,
one for shells and one for regular command-line use. Turning
SHELLIF on in Z33 allows it in shells and therefore disallows it
generally, so forget that solution.
Dreas Nielsen has come up with a solution, however, in the form of
a straightforward little program CLRCST.COM, contained in his
FORNXT2.LBR. It simply clears the console status flag, about which
I unfortunately know very little. It seems to do something similar
to what turning on SHELLIF does, but manually, only on a per-alias
basis. Simply put CLRCST as the very first command in an alias
containing flow control, and it will run properly under SHSET or
other shells.
But this technique's inability to process '$z'-fied aliases rules
in out for me.
It's interesting, by the way,
So what does that leave us with? The biggie:
3) ZEX. "Have more sex with ZEX!" How's that for an advertising
slogan for this wonderful but misaligned, misunderstood and
generally feared ZCPR3 utility? ZEX has a '^:' control directive
that lends it perfectly to this kind of looping. It has no problem
with '$z' aliases. It runs quickly, as the entire command sequence
is placed in memory, unlike with ALIAS.CMD aliases where ARUNZ has
to re-run each time the looping is performed. An easy patch,
provided by Jay, is made to VDE that turns off ZEX processing once
VDE loads, then the simple ZEX file is executed:
vde a15:alias.cmd
$1 $2 $3
^"
SAK /p3
^:
and you're home free. The ^: tells ZEX to rerun its command stream
from the beginning; just what we want. I guess because it operates
in its own area of memory outside the regular ZCPR3 command line
buffer area (in very highest TPA just below the CP, completely
separate from the other ZCPR3 buffers), ZEX doesn't seem to be
bothered by ARUNZ's '$z' COMMAND-LINE BUFFER-flushing. I'm quite
pleased with how this is working. Additionally, the major
complaint I have had with ZEX for a year or so -- that before
running each command it displays the command line prompt which
clutters up the screen and gives the whole operation an unaesthetic
and overly busy appearance -- can be fixed with judicious and
accurate use of the new control directives in Jay's superb NZEX-C.
The complete LOOP.ZEX I use, of which the above is only a skeleton,
is included in this library, but is reproduced below:
^-^< *=&:)(Going to source script...)( ^>
^.vde a15:alias.cmd
^-^< *=&0)(Now running cmdline: ($1 $2 $3... ))(^|^|^>
^.$1 $2 $3
^"
sak /p2
^:
The ^- directive turns off all console output so the command prompt
doesn't display (looks nice and clean). The ^<..display text...^>
directive turns on ZEX's 'echo' mode. The strange escape sequences
you see inside the display text are standard ADM-3A cursor control
commands to place the text in a visually pleasing location on the
screen. Then with the ^. directive we change the "console display
state" to "display console output but don't echo commands" just
before running our commands.
The only part that's a little awkward is the ^" directive that we
need to turn off ZEX while inside our "$1 $2 $3" command line.
(The extra '$3' is just in case we have more than three tokens in
our command; in 'PLF DIR:TESTLIB' I only have two. Jay is working
on a cleaner solution to this. The way ZEX is set up now, if any
of the programs included in the alias do NOT have code in them to
turn off ZEX, then we must include the ^" directive in our ZEX file
to do it manually for us. Otherwise, we could be in the middle of
any of our programs and right in front of our eyes ZEX will start
spewing out the remaining ZEX commands right into our program. I
have actually had problems with MU312 loaded at 8000h inside my
alias; for some reason, even with the ^" ZEX still pokes its nose
and its command stream into MU3 and halts the alias. I don't know
why this particular program gave me problems. (Conflicts with the
ZEX monitor in high TPA? I don't know.) Jay has developed a patch
that can be applied to any program internally to turn off ZEX while
it's loaded thus making an explicit ^" directive in the ZEX file
unnecessary, but until all programs have this it's best to include
it in each ZEX file.
For instance after I patched VDE I thought, "Oh, great, now I don't
have to include ^" in the ZEX file. I pleasantly loaded up PLF and
started viewing a file. LT started to do the job nicely for me and
displayed the first screen's worth of my file. Hit CTL-C and
waited to get back to the PLF prompt. Surprise! There I was
unceremoniously exited out of PLF and looking at a ZCPR3 prompt.
Why? Because since LT wasn't turning ZEX off, my CTL-C that was
intended for LT got intercepted by ZEX as an "abort-ZEX" command.
This used to happen to VDE until I patched it.
Jay is intending, I believe with NZEX-D, to solve this problem with
a technique that WITHIN ZEX will automatically turn off ZEX
redirection inside ALL programs. This will be especially nice since
a ^" directive complicates ZEX scripts in that after the ^" is
reached in the command stream all ZEX processing appears to halt.
The user's screen is dead. At this point if one hits a <CR>
everything resumes again, but this shouldn't be necessary and
detracts from the smoothness and "feel" of the whole operation.
So that's how I've solved my "looping" problem -- for now. NZEX-C as
Jay has implemented it is a beautiful, very powerful program. There's
no reason for anyone to shy away from it. Just take out your manual,
and as Frank says, study, study, study, study, study, study, study.
However, one crucial part of this discussion remains -- how to best
implement recursive and nested aliases. Is there no way we can do
looping methods numbers (1) and (2) above with very long alias
sequences, considering that the flushing of the command line with the
'$z' symbol seems to prohibit this?
I hope everyone subscribes to The Computer Journal, because Jay Sage's Z-
SIG column in there is immensely useful and chock full of information
not available elsewhere. One of the most intriguing columns for me was
in issue #28 in which Jay brings to the readers' attention a letter sent
the magazine by Dreas Nielsen in regard to techniques for alias
recursion. Jay implemented his method originally in VALIAS and carried
the same technique over to ARUNZ with the '$z' symbol. Dreas wrote in
and suggested another way to deal with one specific aspect of creating
recursive aliases -- a way OTHER THAN flushing the command line buffer
as Jay's technique does: their tendency to pile up 'FI's at the end.
Without any intervention here an alias will then incorrectly exit with
an IF level set. While the buffer-flushing technique deals with this by
simply clearing out the 'FI's (along with everything else) from the
command line, Dreas' technique takes a different tack and deliberately
enters the alias in question from a second alias, an IF level therefore
already in effect. Our main alias begins with a 'FI' and therefore
returns us to a zero IF level.
But I have been confused by this discussion, because it seems to only
deal with the issue of IF level overflow, and not common line overflow.
Unless I am misunderstanding something (and I hope I am) Dreas'
technique doesn't seem to offer a solution to this latter problem. The
only answer to this seems to still be the '$z' symbol. I hope this is
not the case because I would like my two looping techniques described
above, as well as Jay's RECURSE and RECURSE2 aliases printed in the TCJ
article, to work with recursive aliases themselves.
SHELL TALK
----------
I've always been surprised at how few people use shell variables and the
"non-menu" shell utilities -- SHVAR.COM, RESOLVE, GETVAR, FOR and PERFORM
-- inside aliases. I understand there's a general reluctance on the
grounds that "theoretically" shells and aliases don't mix. Though an
admitted hard-core theoretician in several fields of human endeavor,
that doesn't seem to bother me. Frank Gaude' first hit upon the idea of
using the by-now famous GETVAR/RESOLVE combination in his GLF alias, but
besides Dreas Nielsen's superb work I've been surprised at how little
public discussion (use?) there is of these utilities.
I've found combinations of SHVAR, RESOLVE and shell variables to be of
inestimable value inside aliases. I think my use inside PLF is a
perfect example. I've also found it very interesting to use them to
save command line buffer space in aliases that would otherwise overflow.
For instance, suppose we have an alias segment:
mu3 ; to 'peek' inside the alias before it runs
if eq $1 $2
echo running: cmd1 $2 $3 $4
cmd1 $2 $3 $4
else
if eq $1 $3
echo running: cmd2 $2 $3 $4
cmd2 $2 $3 $4
else
if eq $1 $4
echo running: cmd3 $2 $3 $4
cmd3 $2 $3 $4
zif
If our four parameters are of any significant size, such as long
filenames with DIR: specs, this alias will overflow so quickly it
wouldn't even be funny. We might hope that the parameters would only
expand in those parameter symbols occupying the portions of the alias
where the flow state is true at any given execution of the alias, but
this is not the case. If you use the trick of beginning every alias
that you want to really peer inside of with a 'MU3;', it'll give you a
window through which you can analyze exactly what's going on. In an
alias like the above, which is an only slightly exaggerated version of
what most of us do -- or would do -- frequently, you'll be amazed at how
much space is wasted by parameters expanding where they don't really
need to --- when the flow state is false. Of course, they have no other
way to work! It's just too bad because they take up precious buffer
space that we need for the flow-state-is-true part of our command line,
the area where the alias is working for us. The many parameters in the
two flow-state-is-false sections of the above alias would expand and
take up so much space the alias would overflow instantly. What to do
about this?
Shell variables to the rescue. A simple command line at the beginning
of the alias:
shvar f $2 $3 $4
would take care of it. The assigns the entire string with our 3
parameters to the shell variable "f". Rename RESOLVE permanently to RS
as I have done, and our alias can now be:
mu3
shvar f $2 $3 $4
if eq $1 $2
rs echo running: cmd1 %f
rs cmd1 %f
else
if eq $1 $3
rs echo running: cmd2 %f
rs cmd2 %f
else
if eq $1 $4
rs echo running: cmd3 %f
rs cmd3 %f
zif
This can fit into our 200-character limit with no problem. If you look
inside with MU3 you will see that the '%f''s do not expand until RESOLVE
gets at them. I'm a little confused about this because I know that
shells such as RESOLVE ultimately do place their product into the
command line buffer (of course), but what I think happens is that all
commands preceding any particular invocation of RESOLVE have already
started moving out of the buffer, so they're not competing for the same
space at the same time. This is the opposite of what happens when
parameters expand, which they do all at the same time, at the very
initial invocation of the command line, thereby all taking up the same
space.
As an experiment, I defined six shell variables, the letters 'a', 'b',
'c', 'd', 'e' and 'f' to definitions of approximately 50 characters in
length. Any string of text will do. You can use GETVAR, SHVAR or that
wonderful but utterly neglected program SHDEFINE. Then try an alias
such as:
echo this is a test of shell variables in the cmdline.
rs echo %a
rs echo %b
echo well, how did the partial test come out?
rs echo %c$$|echo %d
rs echo %e$$|echo %e
echo the end!
You will be utterly surprised at the results. This will NOT produce an
overflow. You will produce a text display of perhaps 400 characters on
the screen --- all with a single alias! Who said we only have a 200-
character buffer? What is the trick? Again, at the time the alias is
invoked we've fit quite well into our 200 characters, as above, with
nothing expanded. As the shell variables expand, the preceding commands
have already emptied out and there is no problem.
By the way, for those puzzled by the '$$|' you are seeing up there,
RESOLVE can resolve two variables in a pass without having to reload
itself. This is done by separating the two commands with a '$|' symbol,
which acts as RESOLVE's own internal multiple-command-line separator.
When RESOLVE does its work, it transforms this symbol into ZCPR3's ';'
semicolon.
And ARUNZ, of course, requires that a single '$' be produced with two
'$'s, hence '$$|' in ALIAS.CMD equals RESOLVE's '$|'.
Postscript: I lied above when I said you won't get a command line
overflow. Once or twice you might. But it won't be an command
processor/ARUNZ overflow; it'll be a RESOLVE overflow. According to
what I read in the RESOLVE documentation, programs can not be passed a
command line tail of greater than 128 characters. (Is this true still
in Z33? I just tested ECHO and it seems to be true) I'm a bit confused
about this, but I know I did occasionally get a message:
Command line overflow
once or twice while playing around with these shell variable aliases,
and this message is distinct from the standard command processor 'Ovfl'
message to which we're all by now so accustomed. I'm not quite sure
under what conditions this RESOLVE overflow occurs. I have never had it
overflow on me in my regular use of it, only when I am experimenting and
testing its limits. Experiment and find out. (One more thing to ask
Dreas.)
Another thought came to me as I was creating PLF. I noticed how often I
was using the string 'LLF $1; P2 $1' in the various nested aliases.
This of course Lists Library Files of the command line parameter and
then sends control back to the beginning of the alias, a procedure that
PLF performs after every operation. So naturally it would be used a
lot. But it took up so much buffer space! How to deal with this?
I experimented with the obvious. First I put a
shvar x $1
command at the very beginning of the alias. If on the command line I
had entered:
plf letters:joeltr
then the string 'LETTERS:JOELTR' would be stored to the shell variable
'x'. Then instead of 'LLF $1; P2 $1', which expands to 37 characters
(count 'em) I could then save space with simply:
rs llf %x$$| p2 %x
which takes up 17 bytes of space.
But I thought some more. The utility to do what I want doesn't yet
exist, but it seems straightforward enough. A shell utility that can
accept and store a multiple-command line FROM THE COMMAND LINE. It's a
pretty obvious and simple concept. In this way I could assign the
entire string 'LLF $1; P2 $1' to a single variable. Why not?
GETVAR and SHDEFINE can both do it, manually, which are of no use from
an alias. With both of these programs a user can assign the above
command line to a single variable, but it must be done as conscious user
input; no alias or even ZEX file can do it. If one cares to do it in
this manner, however, before running the alias, the above sequence,
occupying 37 bytes if done in the 'normal' manner, would be reduced to 4
characters! Hmmm...maybe I can get Dreas to write something...
REGISTERS
---------
Another way I saved command line buffer space in PLF is through the use
of the ZCPR3 registers. They also seem to be an underutilized feature
of Z-System, at least in what I see publically. They are excellent in
CREATING FILENAMES. What? Registers creating filenames? Sure, why
not? If the filename contains -- or could be created to contain --
digits, they're perfect for this use.
I had an example in PLF very much like the above alias with all the
parameters. I solved it differently. Let's look at it again. I'll lay
the solution side by side with the problem; 'BEFORE' on the left,
'AFTER' on the right.
BEFORE AFTER
mu3 mu3
if eq $1 $2 if eq $1 $2
echo running: cmd1 $2 $3 $4 reg s0 1
cmd1 $2 $3 $4 else
else if eq $1 $3
if eq $1 $3 reg s0 2
echo running: cmd2 $2 $3 $4 else
cmd2 $2 $3 $4 if eq $1 $4
else reg s0 3
if eq $1 $4 zif
echo running: cmd3 $2 $3 $4 rs echo running: cmd$$r0 $2 $3 $4
cmd3 $2 $3 $4 rs cmd$$r0 $2 $3 $4
zif
The string 'cmd$$r0' above actually resolves to 'cmd1' if register 0 is
set to 1. It resolves to 'cmd2' if register 0 is set to 2, and to
'cmd3' if set to 3. Again, note the double '$$' in 'cmd$$r0' which is
so RESOLVE can properly be sent the parameter '$r0' by ARUNZ so the
former can return to us the value of register 0.
Works beautifully!
-----------
Using registers and shell variables in this way greatly enhances the
possibilities for aliases, adding much to the pleasure, enjoyment and
variety we experience in this most wonderful operating environment of
ZCPR3. We have infinite oceans to explore, many deep seas and
multicolored coral reefs in which to dive for our beautiful Z-System
pearls. Exploration is the order of the day!
- Rick Charnes, San Francisco