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