home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / MISC / REC.ZIP / CNVPRG.HLP < prev    next >
Encoding:
Text File  |  1986-12-01  |  40.0 KB  |  1,030 lines

  1. Introduction.
  2. Index of Demonstration Programs.
  3. A Bare Minimum Program.
  4. Establishing Communication.
  5. Reading and Writing Files.
  6. Families of Files.
  7. Further Examples.
  8. :Introduction.
  9.  
  10.  The purpose of CNVPRG.HLP is to introduce the programming language Convert,
  11. which is a pattern-directed language, whose commands are written as examples,
  12. in a style typified by: "if you see this, then do that..." Nevertheless, this
  13. is not a HELP file from first principles, but slightly more advanced. Another
  14. file, CNVRT.HLP, which outlines the language should be consulted first. This
  15. file shows how to construct programs, beginning with a totally trivial
  16. example showing how to organize a file containing a Convert program. However,
  17. an editor can elaborate even this program into something more useful. It, and
  18. some of the other programs to be taken up are good seed programs.
  19.  
  20. The first step is to consider input and output. Although Convert has a default
  21. exchange between the console and the program, most programs will work with
  22. disk files, and it is necessary to know what facilities are available to
  23. use the disk. But first, we show a program which interacts exclusively with
  24. the console. Even when disk files are involved, console interaction can always
  25. play a part in the program.
  26.  
  27. The next step is simple reading and writing involving just a single file in
  28. each of these two activities.
  29.  
  30. -
  31. Going on from individual files, there is frequent occasion to work with
  32. families of files, using CP/M's wildcard conventions. This gives us an
  33. opportunity to use some of the function skeletons which communicate with
  34. CP/M to execute advanced directory operations. It is also an opportunity to
  35. show how a list of tasks can be built up, which will be attended to one by one.
  36.  
  37. Finally, a few moderately complicated examples are shown, which are quite
  38. convenient utilities in their own right.
  39.  
  40. These programs are all relatively straightforward, in that they do not
  41. involve any but the simplest pattern matching and searching. In one of
  42. the sample programs, SENTEN.CNV, there is an exception when the definition
  43. of a "sentence" in terms of Convert is undertaken. Typesetters and writers
  44. use constructions just slightly beyond the definitions given; but we do not
  45. pursue the matter in any detail.
  46.  
  47.  
  48. :Index of Demonstration Programs.
  49.  
  50.     Program        Section        Panel
  51.     -------        -------        -----
  52.  
  53.     SAMPLE.CNV    C        4
  54.     VOWEL.CNV    D        10
  55.     COPY.CNV    E        1
  56.     SENTEN.CNV    E        4
  57.     PYP.CNV        E        9
  58.     PAK.CNV        F        3,4
  59.     UPAK.CNV    F        7
  60.     BORRA.CNV    F        9
  61.     FIND.CNV    G        2,3,4
  62.     KWIK.CNV    G        6
  63.     BINCOM.CNV    G        8,9
  64.  
  65.  
  66. :A Bare Minimum Program.
  67.  
  68. The simplest possible Convert program is:
  69.  
  70.         (()()()())
  71.  
  72. It defines no patterns.
  73. It defines no skeletons.
  74. It uses no variables.
  75. It does nothing.
  76.  
  77. In spite of the fact that it does nothing, it IS a program, and gives us
  78. a way to get started. We could also write it in the form:
  79.  
  80.         ((
  81.         )(
  82.         )()(
  83.         ))
  84.  
  85. In the second form it is easy to insert more lines, since its structure as a
  86. quadruple is already established. The null list of variables can't contain any
  87. spaces, carriage returns, or line feeds, so it is sandwiched on the third line.
  88. -
  89. To compile and execute a program we must place it in a disk file. From the
  90. the very beginning we should follow good programming habits and document our
  91. program. Its file needs a name, which could be the name of the program itself.
  92. Since we are all forgetful, especially after we have dozens of disks laying
  93. around, it is a good idea to place the name of the file at the very beginning
  94. of the file. That way, it will always show up on listings; we can also peek at
  95. the file with a TYPE in CP/M, and if names, dates, revision numbers, comments
  96. and the like are at the front of the file they can be scanned rapidly.
  97.  
  98. If a program ends with the word "end" it will be evident that something has
  99. happened to the file if this final remark turns up missing.
  100.  
  101. Without being very original, SAMPLE.CNV could be the name of a practice file,
  102. containing the following text:
  103.  
  104.         [SAMPLE.CNV]
  105.         [A. Programmer, 15 March 1984]
  106.         [A sample of Convert programming]
  107.         (()()()())
  108.         [end]
  109.  
  110. The square brackets make the text they enclose into comments for REC.
  111. -
  112. We do not always remember just what a program is for, the exact form of its
  113. parameters, or the options that we may exercise during its execution. Startup
  114. messages can provide this information, although we ought to be careful about
  115. the optimal form and presentation of the message. If it is too long, people
  116. will rapidly tire of seeing it; furthermore it takes up memory space.
  117.  
  118. Convert uses a run-time library of REC subroutines. The library routines which
  119. search for variables, define, store, and retrieve them are essential. Had they
  120. been included in the Convert program as macros, the resulting code would have
  121. been very much longer. Other subroutines correspond to input-output to disk or
  122. console via CP/M. Conversions and arithmetic operations are required by all but
  123. the simplest programs. One of the subroutines in the runtime library displays
  124. the startup message. A programmer can use this subroutine to show the message
  125. at any time. Either way, the message has to be gotten into the library program.
  126.  
  127. The Convert compiler is programmed to look through the source program for the
  128. startup message. To simplify the compiler the message should not be too hard
  129. to find; the solution is to enclose the message in DOUBLE square brackets.
  130.  
  131. The next panel shows the sample program, incorporating all these features.
  132.  
  133.  
  134. -
  135.  
  136. [SAMPLE.CNV]
  137. [A. Programmer, 15 March 1984]
  138. [A sample of Convert programming]
  139.  
  140. [This panel shows a complete program. Comments, such as this one, can be
  141.  used liberally to explain and document a program. Although defaults are
  142.  provided, CONVERT.REC expects to find the following four components of the
  143.  program, in order:
  144.  
  145.     1. file name (as a comment)
  146.     2. startup message
  147.     3. the first subroutine (or the main program)
  148.  
  149.  More blank lines may be present, and any number of additional comments.]
  150.  
  151. [[This is the startup message.]]
  152.  
  153. [main program]
  154. (()()()())
  155.  
  156. [end]
  157.  
  158. -
  159. :Establishing Communication.
  160.  
  161. There might be programs that do not require input or produce output; think of a
  162. program that tests memory, which simply runs until it fails. Otherwise, sources
  163. and destinations must be established; then the program can receive information
  164. and record the results of its computation. If disk files are going to be used,
  165. CP/M places the names of such disk files on the command line. If no files are
  166. specified, it is a natural assumption that the console is to be used.
  167.  
  168. A Convert program will be executed by typing a command line similar to
  169.  
  170.         REC80 SAMPLE D:FILE.EXT
  171.  
  172. because REC allows the command line tail to be passed along to the program
  173. which it is going to load and execute. The information D:FILE.EXT will be
  174. forwarded to the workspace during the initialization which accompanies every
  175. Convert program. If no file is given we do not want to leave the program
  176. without any communication, so a prompt is issued to the console. Whatever
  177. response then results is placed in the workspace for the main program to use.
  178.  
  179. To complete the exchange between the program and its environment, once the
  180. program has finished, anything left in the workspace is typed at the console.
  181. -
  182. To see how this works, suppose that we use the file SAMPLE.CNV containing the
  183. null main program (()()()()). Since it does nothing, it will end up by typing
  184. whatever it finds in its workspace. We can try it with various command lines,
  185. to see what happens.
  186.  
  187. 1)        A>rec80 sample file.ext
  188.         Next: 27CD
  189.         This is the startup message.
  190.         FILE.EXT
  191.         A>
  192.  
  193. 2)        A>rec80 sample
  194.         Next: 27CD
  195.         This is the startup message.
  196.         > file.ext
  197.         file.ext
  198.         A>
  199.  
  200. Note in the first trial that CCP has converted lower case letters to upper
  201. case. The second trial shows Convert's prompt, our reply, and the echo, still
  202. in lower case. Both show the startup message, which could have been an 
  203. instruction line.  "Next:" shows compilation area usage.
  204. -
  205. If the program is to use the file which has been designated, that file has to
  206. be opened, used, and closed; this means that we are going to have to include
  207. some substance in the program. First, the disk and filename can be bound to
  208. variables while ignoring the extension. A suitable program would be:
  209.  
  210.         [main program]
  211.         (()()(8 9)(
  212.             (<8>:<9>(or, ,.,<>),<<
  213.                 >>(%Or,<8>:<9>.OLD)<<
  214.                 >>(%Ow,<8>:<9>.NEW)<<
  215.                 >>(a)<<
  216.                 >>);
  217.             (<9>,@:<9>):
  218.         ))
  219.  
  220. This program uses only one filename, but the input file will be distinguished
  221. from the output file because the former has the extension OLD, the latter the
  222. extension NEW. The as yet undefined function "a" will do the processing of the
  223. file. A detail which should be noted is the way in which we make sure that the
  224. variable <8> has a value to which to bind. Note further that the filename can
  225. terminate with a space, a dot, or the end of the workspace text.
  226.  
  227. -
  228. A slightly more elaborate main program is desirable. Since it is likely that
  229. the input file will be read by many different rules throughout the program,
  230. the single skeleton (R) can be defined once and for all in the main program
  231. to do this reading. We can also prime the function "a" with an initial line.
  232.  
  233.         [main program]
  234.         (()(
  235.             ((%R,<8>:<9>.OLD)) R
  236.             ((%W,<8>:<9>.NEW,<=>(^MJ))) W
  237.           )(8 9)(
  238.             (<8>:<9>(or, ,.,<>),<<
  239.                 >>(%Or,<8>:<9>.OLD)<<
  240.                 >>(%Ow,<8>:<9>.NEW)<<
  241.                 >>(a,(R))<<
  242.                 >>);
  243.             (<9>,@:<9>):
  244.         ))
  245.  
  246. We have also included function W, in which the skeleton <=> represents the
  247. argument given in references to W; for instance, (W,end) writes on the output
  248. file a line consisting of the word "end" and the control characters CR and LF
  249. (^M and ^J).
  250. -
  251. Most programs will make automatic use of disk files whose names are derived
  252. from the command line, so the main program in each case will be similar to
  253. the one shown in the last panel. Typically, it will open the files to be used,
  254. execute an auxiliary program, and then close the files that it opened. Some
  255. general purpose reading and writing skeletons may be defined at this level,
  256. which is also the level at which disk assignments and generic file names can
  257. be bound. The choice of high numbers like 8 and 9 for these variables is simply
  258. a personal choice which leaves the low numbers free for use in other programs
  259. which will occupy the same file.
  260.  
  261. If the program being prepared is to work with a family of files, supposing that
  262. an ambiguous file name were given on the command line, additional programming
  263. will be required to trace down all files in the directory which correspond to
  264. the ambiguous name and save references to them for later use in the program.
  265.  
  266. Occasionally a program will be written which will not use disk files at all,
  267. but this simply means that the initial workspace derived from CP/M's command
  268. line should be ignored. Alternatively, some initial parameters could be passed
  269. to the program in the guise of a file name. If the program is to be interactive
  270. and the initial workspace is blank, the console is already established as the
  271. device which will be used by (%R) and (%W,,...); if the presence of a parameter
  272. were interpreted as a default disk, (%R,TTY:) and (%W,TTY:,...) will serve.
  273. -
  274. To explore the uses of the console as a default "file" consider the following:
  275.  
  276.         [VOWEL.CNV]
  277.         (()()()(
  278.             (stop,goodbye!);
  279.             ((or,A,E,I,O,U),(%t,VOWEL)(%R)):
  280.             (,(%t,other)(%R)):
  281.         ))
  282.  
  283. This program types out a comment according to the initial letter of whatever
  284. is typed in response to the prompt at the console. It requires a lower case
  285. "stop" to terminate the program. In the combination (%t,....)(%R), %t erases
  286. its argument, so it leaves a clean workspace into which is inserted the
  287. response following the next prompt.
  288.  
  289. This program requires no variables because it does not use any portion of the
  290. workspace, as dissected by a variable-containing pattern, in creating the new
  291. contents of the workspace. Generally, variables are not required when all the
  292. rules of a set are of the form (recognition, response). A program which made
  293. substitutions from a table, or classified intervals, would not use variables.
  294.  
  295.  
  296. -
  297. Let us try this same program again, using %W instead of %t. For the sake of
  298. variety, let us also mention the console specifically using (%R,TTY:) for (%R).
  299.  
  300.         [VOWEL.CNV]
  301.         (()()()(
  302.             (stop,goodbye!);
  303.             ((or,a,e,i,o,u),(%W,,vowel)(%R,TTY:)):
  304.             ((or,A,E,I,O,U),(%t,VOWEL)(%R)):
  305.             (,(%W,,other)(%R,)):
  306.         ))
  307.  
  308. Note the following details:
  309.  
  310.    1)    "goodbye!" does not need %T because it is the last thing placed
  311.     in the workspace, to be typed as the program exits to CP/M.
  312.  
  313.    2)    %W is followed by TWO commas because we have to distinguish the
  314.     message it will type from the file name; by definition the default
  315.     is not spelled out by name, but we have to show up its absence somehow.
  316.     somehow. Notice that %W will not add CR,LF, as %t does.
  317.  
  318.    3)    (%R,) works; but is redundant, the same as (%R).
  319. -
  320. Suppose that we make a hasty copy of this program - omitting the startup
  321. message and everything - and give it a trial run. The following (annotated)
  322. transcript might result:
  323.  
  324.         A>rec80 convert vowel    ;first compile VOWEL.CNV
  325.         ...            ;CONVERT.REC will output something here
  326.         A>rec80 vowel        ;now execute VOWEL.REC
  327.         Next: 2A66        ;memory used by the program
  328.         convert/icuap/1985    ;default message
  329.         > a<CR>vowel        ;<CR> won't show, reply on same line
  330.         > A<CR>            ;<CR> denotes the user's CR
  331.         VOWEL            ;reply on new line
  332.         > b<CR>other        ;different response
  333.         > stop<CR>        ;time to quit
  334.         goodbye!        ;acknowledgement
  335.         A>            ;back to CP/M
  336.  
  337. The treatment of a and A was different - %W types what it sees, and if you
  338. want a CR,LF you have to put one in, say as (^MJ). The prompt showed up on a
  339. new line because %R always prefaces the prompt with a CR,LF. %t does the same
  340. because it is intended for debugging or for message transmission direct to the
  341. console, where it is a good idea to start everything off on a new line.
  342. -
  343. When a program is running, one often forgets how to stop it, or even what
  344. kind of data it is expecting. The purpose of the startup message is to supply
  345. this kind of information. At the risk of becoming irritating, it could be
  346. repeated with every %R to make sure that it was always available.
  347.  
  348. A good startup message for this example would be:
  349.  
  350.         [[
  351.         To identify upper and lower case vowels...
  352.         type any character, either shifted or regular.
  353.         type stop to quit
  354.         ]]
  355.  
  356. With practice one begins to pick up little formatting details. For example,
  357. when a reply falls on the same line as a prompt, and knowing that the carriage
  358. return which terminates console input will not be echoed, we might program a
  359. carriage return, line feed; or at least a separating space.
  360.  
  361. The next panel shows a finished version of VOWEL.CNV.
  362.  
  363.  
  364.  
  365. -
  366.     [VOWEL.CNV]
  367.     [Harold V. McIntosh, 16 March 1984]
  368.  
  369.     [[
  370.     To identify upper and lower case vowels...
  371.     type any character, either shifted or regular.
  372.     type stop to quit
  373.     ]]
  374.  
  375.  
  376.  
  377.     [main program]
  378.     (()()()(
  379.         (stop,goodbye!);
  380.         ((or,a,e,i,o,u),(%W,, vowel)(%R,TTY:)):
  381.         ((or,A,E,I,O,U),(%t, VOWEL)(%R)):
  382.         (,(%W,, other)(%R,)):
  383.     ))
  384.  
  385.     [end]
  386.  
  387.  
  388.  
  389. :Reading and Writing Files.
  390.  
  391. Once the basics of transmitting the CP/M command line to a Convert program have
  392. been mastered and one has prepared a seed program, it can be copied via PIP
  393. to start a new program. A good place to begin is with a copying program, which
  394. is not all that useful, but which IS simple.
  395.  
  396.         [COPY.CNV]
  397.         (()()(0)( ((^Z),); (<0>,(W)(R)): )) a
  398.  
  399.         [main program]
  400.         (()(
  401.             ((%R,<8>:<9>.OLD)) R
  402.             ((%W,<8>:<9>.NEW,<0>(^MJ))) W
  403.           )(8 9)(
  404.             (<8>:<9>(or, ,.),<<
  405.                 >>(%Or,<8>:<9>.OLD)<<
  406.                 >>(%Ow,<8>:<9>.NEW)<<
  407.                 >>(a,(R))<<
  408.                 >>);
  409.             (<9>,@:<9>):
  410.         ))
  411. -
  412. There are fine points to be perceived in the program of the preceding panel.
  413.  
  414.    1)    The program "a" is written on one line; it is harder to read but
  415.     since it is quite short, it is nicer to save the space.
  416.  
  417.    2)    %R will read the block of information which corresponds to it, one
  418.     single line - delimited by but not including its CR,LF - unless
  419.     formatted reading has been requested. %R will NEVER deliver a ^Z unless
  420.     it is the first character delivered. (Well, almost NEVER. A formatted
  421.     read could include a ^Z, but that could also be considered poor
  422.     programming practice.)  In non-pattern-directed reads, %R ALWAYS
  423.     returns ^Z upon exhausting the file, and on any further read attempts.
  424.  
  425.    3)    The terminal rule in "a" leaves a null workspace, not one containing
  426.     ^Z. For users of certain brands of terminals, this avoids a
  427.     disconcerting flash on the screen as the final workspace is typed
  428.     on the console prior to returning to CP/M.
  429.  
  430.    4)    The pair (W)(R) in "a" could be (R)(W) instead since each function
  431.     has its private workspace. However, (W)(R) uses less total space.
  432.  
  433.  
  434. -
  435. Since simple copying of a file is easy enough to do with PIP, it might be a
  436. bit more interesting to look at programs which are capable of fancier maneuvers
  437. than that. First of all, when working with written text, the sentence is a much
  438. more natural unit than a line; indeed the discrepancy between the two accounts
  439. for much of the complexity involved in "word processors."
  440.  
  441. What is a sentence? Traditionally, it begins with a capital letter and ends
  442. with a period; the period is the more important of the two. However, there
  443. are a few exceptions - quoted periods, triple dots sometimes used to express
  444. continuation, the period that goes inside the quoted expression which lies at
  445. the end of a sentence. Starting with its beginning, a sentence is recognized by
  446.  
  447.         <-->.
  448.  
  449. but we can incorporate the exceptions by making a series of definitions:
  450.  
  451.   [non-terminal]    ((or,(and,<[1]>,(nor,.,<'>,<">)),..(ITR,.))) q
  452.   [balanced quote]    ((ITR,(or,<:q:>,<"><:r:><">,<'><:r:><'>))) r
  453.   [sentence]        (<:r:>(or,.,<"><:r:>.<">,<'><:r:>.<'>)) s
  454.  
  455. We still have to filter out things like captions and section numbers, but <:s:>
  456. is a certain approximation to a sentence recognizer.
  457. -
  458. The following program ought to read the file named on the command line, and
  459. type it out sentence by sentence on the console.
  460.  
  461.         [SENTENCE.CNV]
  462.         (()()(0 1)(
  463.             (<0>(^Z),<0>);
  464.             ( <0>,<0>):
  465.             (<0>  (ITR, )<1>,<0> <1>):
  466.             (<0>(^MJ)<1>,<0> <1>):
  467.             (<0>,(%t,<0>)(R)):
  468.         )) a
  469.  
  470.         [main program]
  471.         ((
  472.             ((or,(and,<[1]>,(nor,.,<'>,<">)),..(ITR,.))) q
  473.             ((ITR,(or,<:q:>,<"><:r:><">,<'><:r:><'>))) r
  474.             (<:r:>(or,.,<"><:r:>.<">,<'><:r:>.<'>)) s
  475.         )(
  476.             ((%R,,<:s:>)) R
  477.           )()(
  478.             (,(%Or)(a,(R)));
  479.         ))
  480. -
  481. When a file containing the program of the last panel is prepared and compiled,
  482. its execution reveals several oversights.
  483.  
  484.     1) Not all sentences end with a period - exclamation and question
  485.        mark, sometimes three dashes, are also terminators.
  486.  
  487.     2) As written, the provision for singly or doubly quoted expressions
  488.        does not foresee their nesting with alternate parity.
  489.  
  490.     3) What programmers take for a single quote is an ASCII accent; ASCII
  491.        doesn't have an apostrophe, so the accent is used for that too!
  492.  
  493.     4) Abbreviations, especially initials in proper names, are followed
  494.        by periods. Beware the division FILE.EXT in CP/M file names.
  495.  
  496.     5) Tabular material, formulas, and program examples don't show periods.
  497.        Inserts may have periods of their own - decimal points for example.
  498.        Paragraph numbers, captions, and headers are all non-sentences.
  499.  
  500.  
  501.  
  502.  
  503. -
  504. The foregoing sequence, containing an attempt at a sentence recognizer, siows
  505. two contradictory aspects of Convert programming. On the one hand, Convert has the
  506. power to give a quick description of natural characteristics of text. On the
  507. other hand, we see that natural language is subtly beyond any short and simple
  508. analysis. If we strive for perfection, it will elude us; but if we settle for
  509. a cursory solution of a casual problem we will fare much better.
  510.  
  511. In the case of a sentence recognizer, we will do pretty well just picking out
  512. periods, and slightly better with periods followed by spaces or CR,LF's.
  513.  
  514. To continue surveying simple copying programs, consider some frequent tasks
  515. which PIP can perform, and how even more general movements could be achieved.
  516. Convert contains some "character arithmetic" functions which were placed there
  517. to allow certain kinds of copying.
  518.  
  519.         &u - make uppercase
  520.         &l - make lowercase
  521.         &a - zero parity bit (CP/M's convention for ASCII)
  522.         &s - set parity bit  (used by some editors)
  523.  
  524. The functions in the & family process a character string of arbitrary length;
  525. the easiest way to use them is line by line until the end-of-file comes up.
  526. -
  527. There are further functions in the & family; &h would be useful for generating
  528. hexadecimal dumps from binary progam files because it replaces each byte in
  529. its argument string by a two-byte printable ASCII equivalent using hexadecimal
  530. "digits." Individual functions of the & family could be incorporated in the
  531. COPY.CNV example of a previous panel just by modifying the definition of the
  532. skeleton W:
  533.  
  534.         ((%W,<8>:<9>.NEW,(&u,<0>)(^MJ))) U
  535.         ((%W,<8>:<9>.NEW,(&l,<0>)(^MJ))) L
  536.         ((%W,<8>:<9>.NEW,(&a,<0>)(^MJ))) A
  537.         ((%W,<8>:<9>.NEW,(&u,<0>)(^MJ))) H
  538.  
  539. Rather than having five special purpose programs, let us think of how to
  540. incorporate all five options into a single program. The Convert command line
  541. is still restricted by its REC substrate to passing a single argument, so
  542. there are two evident choices:
  543.  
  544.         1. Incorporate the option in the filename.
  545.         2. Solicit the option from the console.
  546.  
  547. The latter is likely to be the more instructive; it also leaves open the
  548. possibility that the command line file would be a sort of SUBMIT file.
  549. -
  550.  
  551. [PYP.CNV]
  552. [Harold V. McIntosh, 16 March 1984]
  553.  
  554. [A Convert program exhibiting some of the characteristics of PIP.COM]
  555. [[
  556. c/copy, u/upper, l/lower, a/zero parity, h/hex dump]]
  557.  
  558. [option]      (()()(0)((X,(^Z)); (<0>,(%t,In file  )(b,(Q))); )) a
  559. [input file]  (()()(1)((<1>,(%t,Out file )(c,(Q))(%C,<1>)); )) b
  560. [output file] (()()(2)((<1>,); (<2>,(%Or,<1>)(%Ow,<2>)(d,<0>)(%C,<2>)); )) c
  561. [choose]      (()( ((%R,<1>)) R)()( (C,(e,(R))); (U,(f,(R))); (L,(g,(R)));
  562.           (A,(h,(%R,<1>,<[128]>))); (H,(i,(%R,<1>,<[16]>))); )) d
  563. [copy]    (()()(0)( ((^Z),); (<0>,(%W,<2>,<0>(^MJ))(R)): )) e
  564. [upper]    (()()(0)( ((^Z),); (<0>,(%W,<2>,(&u,<0>)(^MJ))(R)): )) f
  565. [lower]    (()()(0)( ((^Z),); (<0>,(%W,<2>,(&l,<0>)(^MJ))(R)): )) g
  566. [ascii]    (()()(0)( (<>,); (<0>,(%W,<2>,(&a,<0>))(%R,<1>,<[128]>)): )) h
  567. [dump]    (()()(0)( (<>,); (<0>,(%W,<2>,(&h,<0>)(^MJ))(%R,<1>,<[16]>)): )) i
  568. [loop]  (()()()( ((^Z),); (,(%Q)(%t,Option?)(a,(Q))): )) x
  569. [main]  (()( ((&u,(%R,(&u,<9>)))) Q)(9)( (<9>,(%Or,(&u,<9>))(x)(%E)); ))
  570.  
  571. [end]
  572. -
  573. This program is rather densely packed to make it fit in a single panel, but
  574. its structure is quite straightforward.
  575.  
  576.     main    place SUBMIT file or TTY: in <9>, open if necessary, call x
  577.  
  578.     x    loop: solicit option, call a, quit for ^Z
  579.  
  580.     a    bind option to <0>, solicit input file, call b
  581.         but return immediately for option X
  582.  
  583.     b    bind input file to <1>, solicit output file, call c
  584.  
  585.     c    bind output file to <2>, open input and output, call d
  586.  
  587.     d    call e, f, g, h, i according to option selected
  588.  
  589.     others    repeat the appropriate action until end-of-file
  590.         e - option C - simple copy
  591.         f - option U - make uppercase
  592.         g - option L - make lowercase
  593.         h - option A - remove parity bit
  594.         i - option H - hexadecimal dump
  595. -
  596. Commentary regarding the program PYP.CNV:
  597.  
  598.     1. A null file command line will give us the opportunity to define
  599.        a "SUBMIT" file, or to interact through the keyboard if we give a
  600.        null response. A file given on the command line defines a "SUBMIT"
  601.        file, whose lines should contain the expected keyboard response.
  602.  
  603.     2. The program is illustrative, not fool proof; little is done about
  604.        possible error reports from BDOS unless BDOS itself takes over.
  605.  
  606.     3. Files are closed with %C, this frees space in REC's pushdown list.
  607.  
  608.     4. ASCII oriented processing terminates on a ^Z, but block processing
  609.        ends when %R returns a null string (no more to be read).
  610.  
  611.     5. The startup line contains the option menu, and is repeated by %Q
  612.        for each file processed. A more elegant program would use the
  613.        startup line to explain the "SUBMIT" options, and generate the
  614.        menu listing by a %t before requesting new input.
  615.  
  616.     6. If TTY: is designated as the output device, we can watch the results
  617.        on the console screen.
  618. -
  619. :Families of Files.
  620.  
  621. Programming with a single input file and a single output file requires only the
  622. Convert functions %O, %R, %W, %C, and %E. They open and close files, read and
  623. write data to the files. Based on the analogous CP/M function, their operation
  624. is only slightly different. For example, opening a file for writing will create
  625. a previously nonexistent file, or else erase a previously existing file. When
  626. reading, the nonexistence of the file returns the phrase "Not Found" in the
  627. workspace. %E closes all open files and frees all associated storage.
  628.  
  629. The read function reads one single line unless directed to read another format
  630. by including a pattern in its parameter list. In writing, only the contents of
  631. the workspace is sent to the output file. Naturally, some buffering is needed
  632. by these functions to make them compatible with CP/M.
  633.  
  634. Other file handling functions are available in CP/M, notably those which treat
  635. ambiguous file names, and allow the renaming and deleting of files. The two
  636. search functions, %S for "search" and %A for "search again" may be used to
  637. track down all the instances of an ambiguous file name at the beginning of a
  638. program. Then they may be read out one by one as the files they represent are
  639. processed. It is a good idea to save everything at once at the beginning of a
  640. program; this avoids the inadvertent reprocessing of a file just created.
  641. -
  642. There is a fairly straightforward main program, which is shown in the HELP
  643. file CNVRT.HLP, which can be used to gather up all the files corresponding
  644. to an ambiguous file reference.
  645.  
  646. The following example is slightly more complex, because it derives the name of
  647. an output file from the first reasonable instance of the ambiguous reference
  648. which it encounters. It is another variant on PIP; which has the capacity to
  649. join several files into a single file, as would be done by the command line:
  650.  
  651.         PIP UNION=A,B,C,D
  652.  
  653. The variation consists in joining the files in a way that will preserve their
  654. individuality so that they can later be separated from one another. For binary
  655. files this is hard without prefacing the union with some sort of directory,
  656. but for ASCII files some kind of mark can be used to separate them.
  657.  
  658. If the mark is ASCII text, we have to have some assurance that it will not
  659. occur naturally in the texts that we are going to join. For example it is
  660. risky to use the word end because it is a segment of render, trend, endeavour,
  661. and many others. Quoting it is safer, but to say that "end" was a terminator
  662. wouldn't work in this very file. Non-text, such as ^Z, would be safer but would
  663. confuse PIP or TYPE. ASCII claims that ^\ is a "file separator"; it might do. 
  664. -
  665. [PAK.CNV]
  666. [Harold V. McIntosh, 18 March 1984]
  667.  
  668. [[Make composite file from many individual files.]]
  669.  
  670. [transcribe file]
  671. (()()(2)(     ((^Z),(%W,(P),(^\MJ))); 
  672.         (<2>,(%W,(P),<2>(^MJ))(R)): )) a
  673.  
  674. [main loop - run through files]
  675. (()(
  676.     ((%R,<7>:<8>.<9>)) R
  677. )(0 8 9)(
  678.   [avoid selfreference]    (<[9]>PAK<[20]><0>,<0>):
  679.   [backup files too]    (<[9]>BAK<[20]><0>,<0>):
  680.   [parse filename]    (<[1]>(and,<[8]>,<8>)(and,<[3]>,<9>)<[20]><0>,<<
  681.     [open file]            >>(%Or,<7>:<8>.<9>)<<
  682.     [insert its name]        >>(%W,(P),[<8>.<9>](^MJ))<<
  683.     [copy file]            >>(a,(R))<<
  684.     [close file]        >>(%C,<7>:<8>.<9>)<<
  685.     [go to next]        >><0>):
  686. )) x
  687. [-]
  688.  
  689. [form file list]
  690. (()()(0)( (Not Found<0>,<0>); (<0>,(%A,(&u,<7>:<1>))<0>): )) y
  691.  
  692. [choose and open output file]
  693. (()(
  694.     (<7>:<6>.PAK) P
  695. )(6)(
  696.   [no more files]    (Not Found,);
  697.   [avoid .BAK, .PAK]    (<[9]>(or,BAK,PAK),(%A,(&u,<7>:<1>))):
  698.   [parse filename]    (<[1]>(and,<[8]>,<6>),<<
  699.     [open .PAK file]        >>(%Ow,(%T,(P)))<<
  700.     [now process list]        >>(x,(y,(%S,(&u,<7>:<1>))))<<
  701.     [close .PAK file]        >>(%C,(%T,(P)))<<
  702.                 >>);
  703. )) z
  704.  
  705. [main program]
  706. (()()(1 7)( (<7>:<1>,(z,(%S,(&u,<7>:<1>)))); (<1>,@:<1>): ))
  707.  
  708. [end]
  709.  
  710. -
  711. PAK.CNV is cluttered, but still long enough to require two panels. Even so,
  712. it is a simple succession of nested programs:
  713.  
  714.     main    bind disk unit, file name (which is probably ambiguous)
  715.         locate first instance of the file
  716.  
  717.     z    search for first plausible family name, which with the
  718.         extension .PAK, will become the output file. Set up a loop
  719.         which will open the output file, run through the files to
  720.         be loaded into it, and finally close it.
  721.  
  722.     y    form the list of candidate files to be packed
  723.  
  724.     x    the main loop, which opens each acceptable file (.BAK, and
  725.         .PAK files are rejected), reads it and writes it into the
  726.         .PAK file, then closes it (not necessary for CP/M, but will
  727.         release its FCB and buffer space for Convert).
  728.  
  729.     a    responsible for copying each individual file
  730.  
  731. The packed files are separated by a line containing ^\ (1CH); it is easier
  732. for unpacking if this mark occupies a whole line.
  733. -
  734. There is, of course, a complementary program which restores the original
  735. programs form the packed file. It is somewhat simpler to write because the
  736. file names to be used are predetermined and only have to be read out of the
  737. text, taking advantage of the fact that they follow the separator ^\. About
  738. the only new technique to be found in this example is the cycle of opening,
  739. writing, and closing the files embedded in the master file.
  740.  
  741. The complementary program is shown in the next panel.
  742.  
  743. There are some details concerning file acquisition which are common to all
  744. the programs we are showing.
  745.  
  746. One: we have set up a pattern which requires a disk unit because of the colon.
  747. Were only recognition involved, the pattern (or,<8>:,) would accept the lack
  748. of a unit specification; but then <8> would not get bound, which would cause
  749. trouble later. Since a pattern can only bind by matching, we have to use a
  750. separate rule to get a workspace of acceptable structure.
  751.  
  752. Two: A null command line could result in having the family name input from
  753. the console, but we have taken no precaution to force it into upper case.
  754.  
  755.  
  756. -
  757. [UPAK.CNV]
  758. [Harold V. McIntosh, 18 March 1984]
  759.  
  760. [[make individual files from packed file]]
  761.  
  762. [locate file name]
  763. (()( (<8>:<0>.<1>) V ((%W,(V),<2>(^MJ))) W )(0 1)(
  764.     ((^Z),);
  765.     ([<0>.<1>],(%Ow,(%T,(V)))(b,(P))(%C,(V))(P)):
  766.     (,Bad .PAK file);
  767. )) a
  768.  
  769. [transcribe file]
  770. (()()(2)( ((^\),); (<2>,(W)(P)): )) b
  771.  
  772. [main program]
  773. (()( ((%R,<8>:<9>.PAK)) P )(8 9)(
  774.     (<8>:<9>(or, ,.,<>),(%Or,<8>:<9>.PAK)(a,(P)));
  775.     (<9>,@:<9>):
  776. ))
  777.  
  778. [end]
  779. -
  780. As a final example of a program which can scan a series of files, let us
  781. consider one which makes selective erasures from the directory. Service
  782. programs with this capability are not rare; let us make this one more
  783. instresting by giving it the capability of scanning the file to be erased
  784. to facilitate the decision whether to erase it or not. To do this it employs
  785. the function &p which replaces each non-printable ASCII character by a dot.
  786. It is the function used in DDT.COM and some other programs to permit lisiting
  787. general binary files without risking the untoward action of some of the ASCII
  788. control characters.
  789.  
  790. To check whether a file is null - that is, a directory entry possessing zero
  791. sectors - or just to refresh your memory for a file you have forgotten about,
  792. type slash to have the first 64 bytes of the file placed on the screen, but
  793. filtered by the "dot" function.
  794.  
  795. This program shows the dual use of the startup message - using the function
  796. (%Q) it is repeated after every query keeping the options always visible. This
  797. is an economy for cramped space, albeit an effective one. A useful interactive
  798. program should be as liberal with messages, supplementary advice, and comments
  799. as necessary to make it helpful to the user. There is also an art to tastefully
  800. concealing all the additional information and handholding from the experienced
  801. user who does not want to endure lengthy explanations during every session.
  802. -
  803. [BORRA.CNV]
  804. [G. Cisneros, 2Jan84; HVM, 21Mar84]
  805. [[y/erase, q/quit, x/examine, other/keep.]]
  806.  
  807. [Get next name]
  808. (()( (<8>:<1>.<2>) F )(1 2 3)(
  809.      (<>,); (q:,(%W,TTY:,: Kept; end.));
  810.      (<[1]>(and,<[8]>,<1>)(and,<[3]>,<2>)<[20]><3>,<<
  811.           >>(%t,Erase (F)?)(%Q)<<
  812.           >>(d,(&l,(%R,TTY:)))<3>): )) a
  813.  
  814. [Delete, Quit, Show, or Keep]
  815. (()()()( (y,(%D,(F))); (q,q:);
  816.      (x,(%Or,(F))(%t,(&p,(%R,(F),<[64]>)))(%C,(F))(&l,(%R,TTY:))):
  817.      (,(%W,TTY:,: Kept));   )) d
  818.  
  819. [Assemble directory entries in WS]
  820. (()()(0)( (Not Found<0>,<0>); (<0>,(%A,<8>:<9>)<0>): )) b
  821.  
  822. [Main program: search for first]
  823. (()()(8 9)( (<8>:<9>,(a,(b,(%S,<8>:<9>)))); (<9>,@:<9>): ))
  824. [end]
  825.  
  826. :Further Examples.
  827.  
  828. To round out our presentation of input-output and file handling programs,
  829. we show some service routines. They are presented here in a very abbreviated
  830. form to confine them to a single panel, but having followed the discussion
  831. of how to run through families of disk files, how to add more interactive
  832. console messages to the programs, and so on, anyone could adapt them.
  833.  
  834. One of the useful utility functions which were included in Ward Christensen
  835. and Randy Suess' CBBS (R) programs which were available from them at one time
  836. was a function FIND.COM, which scanned a family of disk files to locate one
  837. or the other of a series of phrases which one could place on the command line.
  838. The evident purpose of this utility was finding lost messages when some mishap
  839. befell the disk which was in the system.
  840.  
  841. This program was generalized to FYNDE.COM, included as number 165.12 in SIG/M
  842. disk #165. For the purpose of comparison, we have used Convert to reproduce the
  843. original FIND.COM. As a binary program it is much longer, much slower; but it
  844. was written and tested during an afternoon and can readily be modified in
  845. several directions as fast as the program can be modified with an editor and
  846. recompiled. To get the full generality of FYNDE.COM, Convert's ability to
  847. compile and execute Convert programs from within Convert programs can be used.
  848. -
  849. [FIND.CNV]
  850. [Harold V. McIntosh, 22 March 1984]
  851.  
  852. [A program which will scan a family of files looking for a keyword.
  853.  
  854.  The control line
  855.  
  856.         REC80 FIND FAMILY.*
  857.  
  858.  will prompt for a key phrase,
  859.  
  860.         > Search phrase?
  861.  
  862.  and  then report all the lines in the search family which contain that
  863.  word or phrase. Tabs may be included in the phrase. The exact case shift
  864.  shown will be used, as well the exact number of spaces. Totals per file
  865.  and a grand total will also be reported.]
  866.  
  867. [[look through files for a reference]]
  868.  
  869.  
  870.  
  871. [-]
  872. [scan file]
  873. (()()(0 1)(
  874.   [end]        ((^Z),);
  875.   [found]    ((and,<--><6>,<0>)<1>,(C)(T)(%W,TTY:,(K): <0><1>(^MJ))(R)):
  876.         (,(,(K))(R)):
  877.   )) a
  878.  
  879. [main loop - run through files]
  880. (()( ((%R,<7>:<8>.<9>)) R ((%R,CTR:LINE)) K
  881.     ((,(%R,CTR:CASE))) C   ((,(%R,CTR:TOTL))) T  )(0 8 9)(
  882.   [avoid .COM files]    (<[9]>COM<[20]><0>,<0>):
  883.   [parse filename]    (<[1]>(and,<[8]>,<8>)(and,<[3]>,<9>)<[20]><0>,<<
  884.     [initialize counter]    >>(%W,CTR:LINE,1,1)<<
  885.     [initialize instance]    >>(%Or,CTR:CASE)<<
  886.     [open file]            >>(%Or,<7>:<8>.<9>)<<
  887.     [type filename]        >>(%t,-----(>) File: <7>:<8>.<9>(^MJ))<<
  888.     [scan file]            >>(a,(R))<<
  889.     [close file]        >>(%C,<7>:<8>.<9>)<<
  890.     [report instances]        >>(%t,Lines Found: (%R,CTR:CASE)(^MJ))<<
  891.     [go to next]        >><0>):
  892.   )) x
  893.  
  894. [-]
  895. [form file list]
  896. (()()(0)( (Not Found<0>,<0>); (<0>,(%A,<7>:<8>)<0>): )) y
  897.  
  898.  
  899. [bind search phrase, look for file]
  900. (()()(6)( (<6>,(x,(y,(%S,<7>:<8>)))); )) z
  901.  
  902.  
  903. [main program]
  904. (()()(7 8)(
  905.     (<7>:<8>,<<
  906.         >>(%Or,CTR:LINE)<<
  907.         >>(%Or,CTR:TOTL)<<
  908.         >>(%t,Search phrase?)<<
  909.         >>(z,(%R,TTY:))<<
  910.         >>(%t,Total Lines Found: (%R,CTR:TOTL))<<
  911.         >>);
  912.     (<8>,@:<8>):
  913.   ))
  914.  
  915. [end]
  916.  
  917. -
  918. One possible variant on the theme of FIND.CNV is to produce the line bearing
  919. the phrase sought in the form of a KWIC index. KWIC means "keyword in context,"
  920. and is a technique deriving from the days of punched cards. Textual material,
  921. for example a bibliography, was scanned for the presence of a certain phrase,
  922. or keyword; cards bearing the designated phrase were listed on the printer. For
  923. the presence of the keyword to be more obvious, the line was rotated, so that
  924. the keyword occupied a central position in the printed line, the same position
  925. for all the lines so that they could be quickly scanned to see how each one of
  926. them used the target word or phrase.
  927.  
  928. KWIC indices can be elaborated to a considerable degree. For example, the
  929. keywords can be derived from the source text itself, listing all possible
  930. words as they occur in all possible sentences, after discarding such trivial
  931. occurrences as a, and, the, and other high-frequency English words.
  932.  
  933. Beware of the program shown in the next panel - it processes only a single
  934. file and not a family of files. However, it is a simple modification to give
  935. this capability, as well as to permit the use of more than one keyword, to
  936. rotate the line rather than just windowing it, and so on.
  937.  
  938.  
  939.  
  940. -
  941. [KWIC.CNV]
  942. [Harold V. McIntosh, 22 March 1984]
  943. [[KWIC Index]]
  944.  
  945. [Bind keyword]
  946. (()( (                         ) S )(8)( (<8>,(b,(e,(%R,<9>)))); )) a
  947. [KWIC line]    (()()(0 1)( ((^Z),);
  948.         (<0><8><1>,(%t,(c,<0>) <8> (d,<1>))(e,(%R,<9>))):
  949.         (,(e,(%R,<9>))): )) b
  950.  
  951. [left segment]  (()()(0)( (<-->(and,<[25]><>,<0>),<0>); (<0>,(S)<0>): )) c
  952.  
  953. [right segment] (()()(0)( ((and,<[25]>,<0>),<0>); (<0>,<0>(S)): )) d
  954.  
  955. [find tabs]     (()()(0 1 2)(
  956.         ((and,<[8]>,<0>(^I)<1>)<2>,(f,<0>)(e,<1><2>));
  957.         ((and,<[8]>,<0>)<2>,<0>(e,<2>));
  958.         (<0>(^I)<1>,(f,<0>)(e,<1>)): )) e
  959. [expand tabs]    (()()(0)( ((and,<[8]>,<0>),<0>); (<0>,<0>        ): )) f
  960.  
  961. [main program]    (()()(9)( (<9>,(%Or,<9>)(%t,Keyword?)(a,(%R,TTY:))); ))
  962. [end]
  963. -
  964. Another of the utilities on the disk SIG/M #165 is BINCOM.COM, which may
  965. be used to compare two binary files to see whether they are identical. Even
  966. though it contains no adjustment to pick up synchronism after encountering
  967. an insertion or deletion, it is still a very useful program. One use consists
  968. in verifying that a dissasembly has been correctly done by comparing the newly
  969. assembled binary program with the original binary source; as discrepancies are
  970. found they can be used to refine the source code.
  971.  
  972. In the next panels we show BINCOM.CNV, which is the same program written with
  973. Convert. The source is quite concise, less than a page of code. The running
  974. speed is somewhat bound by the velocity of transmission to the terminal, but
  975. cannot help being slow in comparison to the assembly language program.
  976.  
  977. Should a modification of BINCOM be attempted, the Convert version is clearly
  978. advantageous; not only was the program set up with about an hour's work, any
  979. modification will require a similar time scale. For example, the bytes examined
  980. could be tested to see whether they were among the 8080 instructions which use
  981. an address. Knowing that two programs were closely similar except for the
  982. widespread occurrence of address shifts caused by insertions or deletions would
  983. make the comparison of two versions of a program much easier.
  984.  
  985.  
  986. -
  987. [BINCOM.CNV]
  988. [Harold V. McIntosh, 22 March 1984]
  989.  
  990. [Convert version of program SIG/M 165.04 which will compare two binary files]
  991. [TTY: output only; for disk replace %t by %W,(&u,<9>)]
  992.  
  993. [[compare two binary files]]
  994.  
  995. [bind <1>] (()()(1)( (<1>,(%t,Second file)(b,(&u,(%R,TTY:)))); )) a
  996. [bind <2>] (()()(2)( (<2>,(%Or,<1>)(%Or,<2>)(c,(1):(2))); )) b
  997. [read two] (()()(3 4)(
  998.     (:<>,);
  999.     (:<[1]><>,(%t,<1> shorter));
  1000.     (<[1]>:<>,(%t,<2> shorter));
  1001.     (<3>:<3><>,(,(%R,CTR:BYTE))(1):(2)):
  1002.     ((and,<[1]>,<3>):<4>,<<
  1003.         >>(%t,Bytes (&Dh,(%R,CTR:BYTE)) different: <<
  1004.             >>(&h,<4><3>)  (&p,<3><4>))<<
  1005.         >>(,(%R,CTR:MISM))<<
  1006.         >>(1):(2)):
  1007.     )) c
  1008.  
  1009. [-]
  1010. [main]  (()(
  1011.         ((%R,<1>,<[1]>)) 1
  1012.         ((%R,<2>,<[1]>)) 2
  1013.     )(9)( (<9>,<<
  1014.         >>(%Ow,(&u,<9>))<<
  1015.         >>(%Or,CTR:BYTE)<<
  1016.         >>(%Or,CTR:MISM)<<
  1017.         >>(%t,First file)<<
  1018.             >>(a,(&u,(%R,TTY:)))<<
  1019.         >>(%t,(%R,CTR:BYTE) bytes read)<<
  1020.         >>(%t,(%R,CTR:MISM) mismatches found)<<
  1021.         >>);
  1022.     ))
  1023.  
  1024. [end]
  1025.  
  1026. :[CNVPRG.HLP]
  1027. [Harold V. McIntosh, 27 March 1984]
  1028. [Rev.: G. Cisneros, 23 January 1986]
  1029. [end]
  1030.