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 / JSAGE / ZSUS / TCJ / TCJ41.WZ / TCJ41.WS
Text File  |  2000-06-30  |  24KB  |  460 lines

  1.                                Z-System Corne≥ (c)
  2.                                  by Jay Sage
  3.                         The Computer Journal, Issue 41
  4.                           Reproduced with permission
  5.                            of author and publisher
  6.  
  7.  
  8.    By the time you read this, summer vacation will probably be just a fondì
  9. memory for you, but it is August as I write this, and I have just returnedì
  10. from three weeks in Israel.  This was a total vacation.  I didn't touch orì
  11. even think about computers the whole time I was away, except at the very endì
  12. when my mind started to refocus on the responsibilities that awaited me atì
  13. home, including this TCJ column.  It was so nice to get "computerì
  14. compulsion" out of my system that I have not been all that eager to get backì
  15. immediately to my old routine...but I know it will happen soon enough.
  16.  
  17.    Having not thought about computing for a month, I had to work to recallì
  18. the things I was excited about before I left and planned to discuss in thisì
  19. issue.  Fortunately, I left myself some notes.  One item was theì
  20. continuation of the BYE discussion, this time covering the extended DOSì
  21. functions implemented in BYE.  The truth is I have neither the energy norì
  22. the time to take up that subject now.  Instead, I am going to come back onceì
  23. again to my favorite subject: aliases and ARUNZ.
  24.  
  25.    I think ARUNZ is the one thing that keeps me hooked on Z-System and notì
  26. eager to follow after the MS-DOS crowd.  Although I have looked hard, I haveì
  27. not found anything with the combined simplicity and power of ARUNZ for MS¡
  28. DOS.  The mainframe batch processing language REXX, which has been ported byì
  29. Mansfield Software to DOS machines, is far more powerful, and some day Iì
  30. hope to port a greatly simplified version to Z-System.  The DOS version ofì
  31. REXX, you see, takes over 200K of memory while it is running!  That oftenì
  32. does not leave enough memory, even on a 640K machine, for applicationì
  33. programs to run.  I think I actually have more problems running out of TPAì
  34. on my Compaq 386 than I do on my SB180!
  35.  
  36.    Anyway, for this column I am going to begin with a very brief report on aì
  37. rather dramatic change in the works for ARUNZ and the Z-System as a whole. ì
  38. Then I am going to describe two ARUNZ applications that I recently developedì
  39. for my own use.  I think they illustrate some interesting generalì
  40. principles, and you may even find them useful as they are.
  41.  
  42.  
  43.                      The Extended Multiple Command Line
  44.  
  45.    Most people who use ARUNZ aliases -- or even standard aliases -- soonerì
  46. or later run into a situation where the command line overflows and the wholeì
  47. process comes to a crashing halt (well, not really a crash, but a suddenì
  48. stoppage).  The standard Z-System configuration supports a multiple commandì
  49. line buffer (MCL) that can accommodate 203 characters.  The largest sizeì
  50. possible is 255 characters.  Either way, there comes a time when aliases areì
  51. invoked from command lines that already contain additional commands, and theì
  52. combined command line is too long to fit in the MCL.  People like RickìèCharnes would have this happen constantly if they did not adopt a strategyì
  53. to avoid the problem (more about that in one of our examples later).
  54.  
  55.    I have long been intrigued by the possibility of having a much longerì
  56. command line.  The command processor (CPR) has always used a word-sizeì
  57. (16-bit) pointer into the command line, and so, without any change in theì
  58. ZCPR34 code, the CPR could handle a command line as big as the address spaceì
  59. of the Z80.
  60.  
  61.    To verify this, I performed a simple experiment.  I configured a Z-Systemì
  62. with free memory after the MCL, and then, using the memory utility programì
  63. MU3, I manually filled in the command line with a very long multiple commandì
  64. line sequence terminated, as required, by a null character (binary zero). ì
  65. Sure enough, after exiting from MU3, the huge command line ran without aì
  66. hitch.
  67.  
  68.    The next step was to write a special new version of ARUNZ that could beì
  69. configured to recognize an oversized MCL.  Richard Conn set up theì
  70. environment descriptor (ENV) with a one-byte value for the length of theì
  71. command line that the MCL buffer could contain.  Thus there is presently noì
  72. way to support an extended MCL (XMCL) in a system-invariant way, that is, inì
  73. a way that allows programs to determine at run time how big the MCL is.  Weì
  74. are working on that problem right now, and, by the time you are readingì
  75. this, there will almost certainly be a new ENV type defined (81H) that usesì
  76. one of the remaining spare bytes in the type-80H ENV to report the size ofì
  77. XMCL to programs smart enough to check for it.
  78.  
  79.    The original, single-byte MCL size value in the ENV has to remain as isì
  80. and contain a value no larger (by definition) than 255 (0FFH).  That valueì
  81. is used by the command processor when new user input is being requested. ì
  82. There is no way for the CPR to allow users to type in command lines longerì
  83. than 255 characters without adding a vast amount of code to perform theì
  84. line-input function now so conveniently and efficiently provided by the DOS. ì
  85. A shell could be written that included such code, but I really can't imagineì
  86. anyone typing in such long command lines.  If they do, it probably showsì
  87. that they are not making proper use of aliases.
  88.  
  89.    I have decided to use only one of the spare ENV bytes for the XMCL sizeì
  90. and to let that value represent the size -- in paragraphs -- of the totalì
  91. MCL memory buffer allocated, including the five bytes used by the addressì
  92. pointer, size bytes, and terminating null.  The term 'paragraph' as a unitì
  93. of memory is not often used in the Z80 world.  I believe it was introducedì
  94. with the 8086 processor, where the segment registers represent addressesì
  95. that are shifted four bits right.  Each unit in the segment register is,ì
  96. therefore, 16 bytes and is called a paragraph.  With this system, the XMCLì
  97. buffer can be as large as 255 * 16 = 4080, which allows command lines withì
  98. up to 4075 characters.  Rich Charnes, do you think you can live with thatì
  99. without cramping your style too much?!
  100.  
  101.    Most people will not want to allocate that much memory to the operatingì
  102. system, and I would never have considered this step before the new dynamicì
  103. versions of Z-System were available.  While I might be willing to allocateìè1K to the XMCL most of the time, I certainly would want to be able toì
  104. reclaim that memory when I need it.  I'm not sure whether NZCOM or Z3PLUSì
  105. can be cajoled into handling this kind of flexibility yet; new versions mayì
  106. be needed at some time in the future.
  107.  
  108.    I put the new version of ARUNZ out for beta test, and it worked justì
  109. fine, and one could write very long alias scripts.  Rick Charnes, however,ì
  110. quickly identified a problem.  Suppose a conventional alias appeared in theì
  111. command sequence.  After expanding itself and constructing the new commandì
  112. line, the alias would find that, as far as it knew, there was not enoughì
  113. room for it in the MCL.  In a nutshell, the hard part with going to the XMCLì
  114. is that it is not enough to have an advanced ARUNZ; all programs thatì
  115. operate on the MCL must be upgraded.  We hope to have new versions of theì
  116. library routines in Z3LIB that perform these functions.  Then, if we areì
  117. lucky, most of the utility programs can be upgraded simply by relinking. ì
  118. I'm sure it won't be quite that easy, of course!
  119.  
  120.  
  121.                                 A MEX Alias
  122.  
  123.    For those who are not familiar with it, MEX (Modem EXecutive) is anì
  124. advanced telecommunications program written by Ron Fowler of NightOwlì
  125. Software.  Early versions were released for free to the public (up toì
  126. version 1.14), while the most advanced versions (called MEX-Plus) areì
  127. commercial products.  I use version 1.65, and some of the specifics in myì
  128. example apply to that version.  I am pretty sure that the technique Iì
  129. describe can be applied to the free version as well.
  130.  
  131.    Rather than being a telecommunications program, MEX should probably beì
  132. considered a telecommunications programming language.  It supports a veryì
  133. wide range of internal commands for managing telecommunications tasks, andì
  134. it even has a script language for automating complex sequences ofì
  135. operations.
  136.  
  137.    The MEX command line allows multiple commands to be entered just as in Z¡
  138. System, and a MEX command allows the user to define the command separator. ì
  139. Although I depend on aliases to generate complex Z-System commands and MEXì
  140. script files to automate complex MEX command sequences, I still frequentlyì
  141. make use of simple, manually entered multiple commands.
  142.  
  143.    Being accustomed as I am to entering Z-System commands separated byì
  144. semicolons, I naturally set up my version of MEX to use the semicolon as itsì
  145. separator, too.  Now I can comfortably work in both environments.  However,ì
  146. I also frequently like to invoke MEX with some initial commands, which MEXì
  147. allows one to include in the command tail.  Here's a simple example.
  148.  
  149.     B11:TEMP>mex read mnp on
  150.  
  151. This command invokes MEX and tells it to run the script file MNP.MEX withì
  152. the parameter "ON".  This script causes a string to be sent to my modemì
  153. which engages the MNP error correcting mode (yes, when I purchased my mostì
  154. recent modem -- replacing a USR Password -- I decided to spend the extraìèmoney for MNP, although at the time there weren't many systems thatì
  155. supported it; now I'm glad I did).
  156.  
  157.    That command line works fine.  But often I want to do more, and so Iì
  158. always wanted to enter something like:
  159.  
  160.     B11:TEMP>mex read mnp on;call zitel
  161.  
  162. This would start out by doing what the first example did but would thenì
  163. continue by placing a call to the ZITEL BBS.  [If you can keep a secret,ì
  164. I'll tell you that the ZITEL BBS is the MS-DOS system that I run for theì
  165. ZI/TEL Group of the Boston Computer Society.  ZI/TEL comes from the lettersì
  166. in Zilog and Intel, and it symbolizes the fact that we support the two mainì
  167. operating systems run on chips from those companies: CP/M and MS-DOS.  Theì
  168. BBS machine, a Kaypro 286/16, is sitting in the other room (you don't thinkì
  169. I'd allow it in the same room with the Z-Node, do you?), and it has an HSTì
  170. 9600 bps modem with MNP error correction.  If you want to contact me there,ì
  171. by the way, the number is 617-965-7046.]
  172.  
  173.    An on-the-ball reader already realized that the above command will notì
  174. work, because the semicolon separator before the CALL command, which Iì
  175. intended as the MEX separator, will be interpreted by the CPR as itsì
  176. separator, and it will terminate the MEX command.  What can we do aboutì
  177. this?
  178.  
  179.    Some compromise here is inescapable, and I was willing to accept -- fromì
  180. the CPR command line only -- a MEX separator other than semicolon.  Thus theì
  181. following form would be acceptable
  182.  
  183.     B11:TEMP>mex read mnp on!call zitel
  184.  
  185. with an exclamation point as the separator as in CP/M-Plus.  But for years Iì
  186. could not figure out how to accomplish this.
  187.  
  188.    At first I thought there was a very simple solution.  When MEX starts up,ì
  189. it can be set up to automatically run an initialization script file INI.MEX. ì
  190. So, I created a version of MEX (the MEX "CLONE" command makes it easy toì
  191. create new versions) that used "!" as the separator, and I created anì
  192. INI.MEX file with the command
  193.  
  194.     STAT SEP ";"
  195.  
  196. Thus, as soon as MEX was running, the separator would be set back to aì
  197. semicolon.  Unfortunately, to my chagrin, I learned that MEX invokes theì
  198. INI.MEX script only when no commands are included on the command line.  Withì
  199. the ZITEL command line shown earlier, MEX would be left with the exclamationì
  200. point as the separator.
  201.  
  202.    Here is what I thought of next (at least momentarily).  Rename MEX.COM toì
  203. MEX!.COM and set up a MEX alias in ALIAS.CMD with the definition
  204.  
  205.     MEX    mex:mex! $*!stat sep ";"è
  206. The idea here is that the user's MEX commands from the command lineì
  207. (separated by "!") will be passed in by the $* parameter and will have theì
  208. STAT command added.  Thus our earlier example will turn into the commandì
  209. line
  210.  
  211.     B11:TEMP>mex:mex! read mnp on!call zitel!stat sep ";"
  212.  
  213.    This, of course, fails for the same reason that I could not just enterì
  214. commands with semicolons in the first place.  The trick to get around thisì
  215. is to use a command that for some reason Ron Fowler does not document in theì
  216. MEX manual: POKE.  It works like the Z-System command of the same name andì
  217. places a byte of data into a specified memory address.
  218.  
  219.    I knew the value I wanted to poke: 3BH, the hex value for the semicolonì
  220. character.  The question was, where should it go?  To find out, I took aì
  221. version of MEX set up with semicolon as the separator and the version withì
  222. exclamation point as the separator and ran the utility DIFF on them (inì
  223. verbose mode to show all the differences).  Then I looked for the placeì
  224. where the former has a semicolon and the latter an exclamation point.  Forì
  225. MEX-Plus this turned out to be 0D18H so that the MEX poke command would be
  226.  
  227.     POKE $0D18 $3B
  228.  
  229. Note that MEX uses a dollar sign to designate hex numbers.  The alias nowì
  230. read
  231.  
  232.     MEX    mex:mex! $*!poke $$0d18 $$3b
  233.  
  234. Observe that a double dollar sign is needed to get a single dollar signì
  235. character into a command.  A lot of people forget this and end up withì
  236. scripts that don't do what they're supposed to.
  237.  
  238.    I tested this, and it works splendidly -- but with one possible 'gotcha'. ì
  239. The commands passed to MEX must not invoke any script files that depend onì
  240. the command separator being a semicolon (because it will be exclamationì
  241. point until the final poke command runs); nor may the read files change theì
  242. command separator (because the rest of the command sequence still assumes itì
  243. is the exclamation point).  For this reason, it is prudent to write allì
  244. script files with only one command per line so that no separator is needed. ì
  245. I haven't been doing this, but I will from now on!
  246.  
  247.    One final word on the script.  I actually did not do this exactly as Iì
  248. have described.  Instead, I left my MEX.COM set up with the semicolonì
  249. separator, and I created a distinct ARUNZ alias called MEX! so that I wouldì
  250. be reminded of the separator.  This alias script reads
  251.  
  252.     MEX!    get 100 mex:mex.com;poke d18 "!;go $*!poke $$0d18 $$3b
  253.  
  254. This uses the famous poke&go technique originated by Bruce Morgen.  MEX.COMì
  255. is loaded into memory by the GET command, and then the Z-System POKE commandì
  256. sets "!" as the command separator.  Then the modified loaded code is run byìèthe GO command.  The rest is as described previously.
  257.  
  258.  
  259.                             A Spell-Check Alias
  260.  
  261.    I try to remember to put all my writing through The Word Plus spellingì
  262. checker that came with WordStar Release 4 so that as many typos as possibleì
  263. will be caught.  The procedure for doing that on a Z-System is a bitì
  264. complicated because the text file is generally not in the same user area asì
  265. the spelling check program.  While writing my last TCJ column, I finally gotì
  266. fed up with the complexity and automated the whole process using a set ofì
  267. aliases.
  268.  
  269.    I wanted to support the following syntax:
  270.  
  271.         C1:TCJ>spell filename.typ dictname
  272.  
  273. If just the file name was given, the alias would prompt for the name of theì
  274. special dictionary to use, and if not even a file name was given, then theì
  275. alias would prompt for both names.  A special version of the command,ì
  276. ZSPELL, would take only the file name and would automatically use ZSYSTEM asì
  277. the name of the special dictionary (it knows about mnemonics like ZCPR, MCL,ì
  278. and RCP, and about all those special words like debugger, relocatable, andì
  279. modem).  We'll describe the general alias set first.  In listing theì
  280. aliases, we will write them in multiline format for easy reading;in theì
  281. ALIAS.CMD file the scripts have to be on a single line (though I hope thatì
  282. will change soon).
  283.  
  284.    The user-interface alias, SPELL, deals only with the matter of how manyì
  285. parameters the user has provided.  It reads as follows:
  286.  
  287.     SPELL
  288.         if nu $1;
  289.           /TW0;
  290.         else;
  291.           if nu $2;
  292.             /TW1 $1;
  293.           else;
  294.             /TW2 $1 $2;
  295.           fi;
  296.         fi
  297.  
  298. If no parameters at all are provided (IF NULL $1), then the secondary scriptì
  299. TW0 is run.  The leading slash signals ZCPR34 that the command should beì
  300. directed immediately to the extended command processor.  If a firstì
  301. parameter but no second parameter is present (IF NULL $2), then theì
  302. secondary script TW1 is run.  Finally, if both parameter are provided, thenì
  303. script TW2 is run.
  304.  
  305.    The script TW1 includes a prompt only for the name of the specialì
  306. dictionary file:
  307. è    TW1
  308.         $"Name of special dictionary: "
  309.         /TW2 $1 $'e1
  310.  
  311. The first token in any user response to the first prompt ($'E1 -- whenì
  312. working with ARUNZ you should have a printout of the parameter DOC file) isì
  313. used along with the file name that was already given, and both are passed toì
  314. TW2.
  315.  
  316.    The script TW0 includes prompts for both the file name and the specialì
  317. dictionary:
  318.  
  319.     TW0
  320.         $"Name of file to check: "
  321.         $"Name of special dictionary: "
  322.         if ~nu $'e1
  323.           /TW2 $'e1 $'e2
  324.         fi
  325.  
  326. The first tokens in the responses to the prompts are passed to script TW2. ì
  327. If no file is specified for checking, the alias simply terminates.
  328.  
  329.    Before we look at TW2, which does the real work, let me ask a rhetoricalì
  330. question: why do we break this process up into so many separate aliases. ì
  331. There are two main reasons.  The first is that the command line buffer would overflow if all these smaller scripts were merged into a single big script. ì
  332. The extended MCL we discussed earlier could overcome this problem, but forì
  333. another reason we would still have to use separate aliases.
  334.  
  335.    As I have discussed in past columns, ARUNZ cannot know at the time itì
  336. expands a script what the results of conditional tests will be later whenì
  337. the IF commands are run.  Thus ARUNZ must process all user input promptsì
  338. that appear in the script.  This would mean asking for a file name andì
  339. special dictionary even when the names were given on the command line.  Theì
  340. solution to this problem is to put the prompts in separate scripts that getì
  341. invoked only when the information requested in those prompts is actuallyì
  342. needed.
  343.  
  344.    Now let's look at the script TW2.
  345.  
  346.     TW2
  347.         path /d=tw:;
  348.         $td1$tu1:;
  349.         tw:tw $tf1 $tn2.cmp;
  350.         path /d=;
  351.         /twend $tn2;
  352.         $hb:
  353.  
  354. This is simpler than what you expected, no?  Well, there is still a lot ofì
  355. work imbedded in the subroutine script TWEND, which we will cover later. ì
  356. Here we broke up the script solely to prevent MCL overflow.
  357.  
  358.    The first command makes use of the ZSDOS file search path (see theìèarticles by Hal Bower and Cam Cotrill on ZSDOS in TCJ issues 37 and 38). ì
  359. Although there was an attempt to update WordStar Release 4 to include someì
  360. Z-System support, no such attempt was made with The Word Plus spell checker. ì
  361. In general, the file to be spell-checked will be in one directory and Theì
  362. Word files in another directory.  The main program TW.COM could be locatedì
  363. by the command processor using its search path, but TW.COM needs a number ofì
  364. auxiliary files, such as the dictionary files.  How can the system be madeì
  365. to find all of these files at the same time.  ZSDOS provides the answer.
  366.  
  367.    I have replaced the standard Z-System PATH command with the ZSDOS utilityì
  368. ZPATH (renamed to PATH).  The first command in TW2 defines the DOS searchì
  369. path to include the directory TW:, which is where I keep all the files thatì
  370. are part of The Word Plus spell-checking package.  Once that directory is onì
  371. the DOS path, all files in it will more-or-less appear to be in the currentì
  372. directory.  Very handy!  If you use ZDDOS, the search path is not available. ì
  373. I will not show it here, but you can accomplish the same thing using onlyì
  374. public files.  It's just not quite as neat and straightforward.  I amì
  375. willing to pay the small memory penalty to get the nice extra features ofì
  376. ZSDOS over ZDDOS.
  377.  
  378.    The second command logs us into the directory where the file to beì
  379. checked resides.  If we did not include a DIR: prefix, we were alreadyì
  380. there, but the extra command does not hurt, and it is nice to know that aì
  381. directory can be specified explicitly (in either DU: or DIR: form) for theì
  382. file to be checked.  There could be a problem if the file is in a user areaì
  383. above 15, since you may not be able to log into that area.  My configurationì
  384. of Z34 allows this, but when I run BGii I lose this feature (and I sure missì
  385. it).  If you can't log into those areas, then you should not keep filesì
  386. there that you want to spell-check.
  387.  
  388.    The third line actually runs the spell checker (you knew that had toì
  389. happen some time!).  Notice that even if the user specified a file type forì
  390. the special dictionary, type CMP is used.  Only the name ($TN2) without theì
  391. type is taken from the user.  As the master program TW.COM is run, it willì
  392. find its component program files (e.g., SPELL.COM, LOOKUP.COM, MARKFIX.COM)ì
  393. and the various dictionaries in the TW: directory thanks to ZSDOS, and itì
  394. will find the text file in the current directory.  As it works through theì
  395. text, if there are any questionable words, it will write out a fileì
  396. ERRWORDS.TXT to the current directory.  If any words are added to theì
  397. special or UPDATE dictionaries, then the modified dictionaries will be readì
  398. from TW: but written out to the current directory.  You must understandì
  399. these facts in order to understand the rest of the script.
  400.  
  401.    Once the spell-checking is complete, the ZSDOS path is set back to nullì
  402. (unless I have a special need to have the DOS perform a search, I leave itì
  403. this way to avoid surprises).  Then the ending script TWEND is run, andì
  404. finally the original directory ($HB:) is restored as the current directory.
  405.  
  406.    Now let's look at TWEND.  As it is invoked, the name of the specialì
  407. dictionary is passed to it.  TWEND's job is to clean up scratch files and toì
  408. take care of any updated dictionaries.  It reads
  409. è    TWEND
  410.         if ex errwords.txt;
  411.           era errwords.txt;
  412.         fi;
  413.         /dupd $1;
  414.         /dupd updict
  415.  
  416. For efficiency and to prevent MCL overflow, the dictionary updating isì
  417. performed by yet another subroutine script, DUPD.  It gets called twice,ì
  418. once with the special dictionary (if any) and once with the updateì
  419. dictionary.  It reads as follows:
  420.  
  421.     DUPD
  422.         if ex $tn1.cmp;
  423.           mcopy tw:=$tn1.cmp /ex;
  424.         fi
  425.  
  426. If an updated version of the specified dictionary exists in the currentì
  427. directory, then it is copied to the TW: directory, overwriting any existingì
  428. file of that name (MCOPY option E).  The source file is then erased (MCOPYì
  429. option X).  Oh yes, I almost forgot; the MCOPY here is my renamed version ofì
  430. the COPY program supplied with ZSDOS.
  431.  
  432.    That is it except for showing you the special ZSPELL version of theì
  433. alias.  Notice that I make the "ELL" part of the command optional byì
  434. inserting the comma in front of that part of the alias name.  I also allowì
  435. the script to be invoked under the name ZTW.  The main SPELL script actuallyì
  436. has the name "TW=SP,ELL" on my system.  Since TW: is not on my commandì
  437. search path, the command "TW" will invoke the ARUNZ script unless I am inì
  438. the TW: directory at the time.
  439.  
  440.     ZTW=ZSP,ELL
  441.         if nu $1;
  442.           /ZTW1;
  443.         else;
  444.           /TW2 $1 zsystem.cmp;
  445.         fi
  446.  
  447.     ZTW1
  448.         $"Name fo file to check: "
  449.         if ~nu $'e1
  450.           /TW2 $'e1 zsystem.cmp
  451.         fi
  452.  
  453. I hope you find these alias examples useful and instructive.  That's all forì
  454. this time.  See you again in two months.
  455.  
  456. [This article was originally published in issue 41 of The Computer Journal,
  457. P.O. Box 12, South Plainfield, NJ 07080-0012 and is reproduced with the
  458. permission of the author and the publisher. Further reproduction for non-
  459. commercial purposes is authorized. This copyright notice must be retained.
  460. (c) Copyright 1989, 1991 Socrates Press and respective authors]è