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

  1. Program
  2. Pattern
  3. Skeleton
  4. Comments
  5. Program File
  6. Library and Initialization
  7. Boolean Patterns
  8. Constant Patterns and Skeletons
  9. Input-Output Skeletons
  10. Directory Skeletons
  11. Arithmetic Skeletons
  12. Conditional and Iterative Skeletons
  13. Variables
  14. Intervals
  15. Rule Set
  16. Debugging Aids
  17. Performance
  18. Bibliography
  19. :[Structure of a Convert program]
  20.  [format: ((p)(s)(v) (
  21.      (pattern, skeleton):    [repeating]
  22.   [or]     (pattern, skeleton);    [terminal]
  23.      )) x]
  24. where    (p) is a list of pattern definitions ((P1) p1 (P2) p2 ...)
  25.     (s) is a list of skeleton definitions ((S1) s1 (S2) s2 ...)
  26.     (v) is a list of variables (v1 v2 ...) (each vi between 0 and 30)
  27.     x   is the name of the program
  28.  
  29. Sample programs:
  30.  
  31. [replace two or more spaces by a single space]
  32. (()()()(0 1)(
  33.     (<0>  (ITR, )<1>,<0> <1>):
  34.   )) w
  35.  
  36. [insert tabs for each eight columns]
  37. (()()(0 1)(
  38.     ((and,<[8]>,<0> (ITR, ))<1>,<0>(^I)(x,<1>));
  39.     ((and,<[8]>,<0>)<1>,<0>(x,<1>));
  40.   )) x
  41. -
  42. Two programs can be used together, with one calling the other. In the
  43. second the pattern 0, written as <:0:>, although it is only used once
  44. represents the more complicated composite (and,<[8]>,<0>). This whole
  45. phrase is a pattern, and must be enclosed in parentheses to make a
  46. definition. There is no conflict between variable names and pattern or
  47. skeleton names; here 0 is used in both senses.
  48.  
  49. [replace 8-column tabs by spaces]
  50. (()()(0 1 2)(
  51.     ((and,<[8]>,<0>(^I)<1>)<2>,(z,<0>)(y,<1><2>));
  52.     ((and,<[8]>,<0>)<2>,<0>(y,<2>));
  53.     (<0>(^I)<1>,(z,<0>)<1>):
  54.   )) y
  55.  
  56. [fill out tab space]
  57. ((
  58.   ((and,<[8]>,<0>)) 0
  59.   ()(0)( 
  60.     (<:0:>,<0>);
  61.     (<0>,<0>        ):
  62.   )) z
  63.  
  64. -
  65. Skeletons can also be symbolized by single letters. The following program
  66. copies one file to another, which PIP.COM could do more efficiently. (R)
  67. and (W) are read and write skeletons, respectively; (W) incorporates a
  68. variable that must have been defined by a pattern match.
  69.  
  70. [read word, write word]
  71. (()()(0)(
  72.     (<0>(^Z),(W));
  73.     (<0>,(W)(R)):
  74.   )) a
  75.  
  76. [main program]
  77. (()(
  78.     ((%R,<9>.ONE,(ITR, )<-->(or, ,(^Z)))) R
  79.     ((%W,<9>.TWO,(%T,<0>))) W
  80.   )(9)(
  81.     (<9>(or, ,.,<>),<<
  82.         >>(%Or,<9>.ONE)<<
  83.         >>(%Ow,<9>.TWO)<<
  84.         >>(a,(R)));
  85.   ))
  86.  
  87. -
  88. :Patterns may have one of the forms
  89.     (AND,p1,p2,...,pn)    [matches if all patterns p1,..pn match]
  90.     (and,p1,p2,...,pn)    [simplified version of AND]
  91.     (OR,p1,p2,...,pn)    [first of p1,...pn to match]
  92.     (or,p1,p2,...,pn)    [simplified version of OR]
  93.     (NOT,p)            [pattern does not start w/p]
  94.     (DEF,p1,n1,...,pk,nk,p)    [p defined in terms of pj w/ names nj]
  95.     (ITR,p)            [Repeat p as much as possible]
  96.     (itr,p)            [Repeat p as little as possible]
  97.     (QUO/.../)        [constant ... with delimiters /]
  98.     (DEC,n)            [the decimal byte n (mod 256)]
  99.     (HEX,n)            [the hexadecimal number n]
  100.     (^xxx)            [control characters xxx]
  101.     (IVL,m,n,)        [lexicographic interval [m,n]; m, n constants]
  102.     (ivl,s1,s2,...)        [lexicographic intervals [s1,s2],... ]
  103.     (PWS)            [print remaining workspace]
  104.     (PWS,r)            [print remaining workspace after message r]
  105.     (PVR,n)            [print value of variable n]
  106.     (HLT)            [wait for keystroke]
  107.     (HLT,mssg)        [print mssg, wait]
  108.     (NOP,p)            [null pattern, disables p]
  109.     (<)  (>)        [constants: left and right angle brackets]
  110. -
  111.     <(>  <)>        [constants: left and right parentheses]
  112.     <,>  <'>  <">        [constants: comma, single quote, double quote]
  113.     <()>            [balanced parentheses]
  114.     (LAM,(v),p)        [p with local variables given in list (v)]
  115.     <:a:>            [defined pattern a]
  116.     <[n]>            [interval of length n]
  117.     <[s]>            [interval of length given by skeleton s]
  118.     <-->            [indefinite interval]
  119.     <n>            [variable n]
  120.     s            [matches text identical to value of skel. s]
  121.     xxx            [constant: string of ASCII characters between
  122.                  ! and ~, except parentheses, angle brackets,
  123.                  comma and single and double quotes; it may
  124.                  include SP, CR, LF and HT]
  125.     <>            [no free space left]
  126.     <<...>>            [null pattern]
  127. :Skeletons may take any one of the following forms
  128.     (<)  (>)        [constants: left and right angle brackets]
  129. -
  130.     <(>  <)>        [constants: left and right parentheses]
  131.     <,>  <'>  <">        [constants: comma, single quote, double quote]
  132.     xxx            [constant: string of ASCII characters between
  133.                  ! and ~, except parentheses, angle brackets,
  134.                  comma and single and double quotes; it may
  135.                  include SP, CR, LF and HT]
  136.     (QUO/.../)        [constant ... between delimiters /]
  137.     (^xxx)            [control characters xxx]
  138.     <n>            [variable n]
  139.     (f)            [function (skeleton) f, no argument]
  140.     (f,s)            [function f, argument s (another skeleton)]
  141.     <=>            [text used in the last comparison]
  142.     (LAM,(v),s)        [s with local variables given in list (v)]
  143.     <<...>>            [null skeleton]
  144.     (if,s{,p,s,s}[,p,s])    [conditional]
  145.     (IF,(v),s{,p,s,s}[,p,s]) [conditional with variables]
  146.     (nf,s{,p,s,s}[,p,s])    [negative conditional]
  147.     (NF,(v),s{,p,s,s}[,p,s]) [negative conditional with variables]
  148.     (while,s{,p,s,s}[,s])    [iterative]
  149.     (WHILE,(v),s{,p,s,s}[,p,s]) [iterative with variables]
  150.     (until,s{,p,s,s}[,s])    [iterative, negative form]
  151.     (UNTIL,(v),s{,p,s,s}[,p,s]) [iterative with variables, negative form]
  152.  
  153. :Since all spaces, tabs, and similar characters are taken literally
  154. in patterns and skeletons, the pair <<...>> may be used to format
  155. programs into lines and columns.  Comments in square brackets will
  156. appear in the compiled program; text between angular brackets will
  157. be ignored; for example
  158.  
  159.         (and,<[8]>,<<
  160.             >><0>)
  161.  
  162. is identical to
  163.  
  164.         (and,<[8]>,<0>)
  165.  
  166. :Program file. A Convert program will eventually have to be compiled and
  167. executed if it is to produce any practical results. The program responsible for
  168. first compiling it is CONVERT.REC, which requires a disk file containing the
  169. program, and which will produce a REC program to be executed. Both steps
  170. require having a REC compiler in the system - REC80.COM (for CP/M or CDOS with
  171. an 8080, 8085 or Z80), REC86.CMD (for CP/M-86) or REC86.EXE (for MS-DOS).
  172.  
  173. The disk file bearing a Convert program may have any extension but REC; if
  174. not given, the assumed extension is CNV.
  175.  
  176. The command line
  177.  
  178.         REC80 CONVERT SOURCE
  179.  
  180. will automatically compile the file SOURCE.CNV to produce SOURCE.REC, which
  181. can be executed with the command line
  182.  
  183.         REC80 SOURCE [argument]
  184.  
  185. where [argument] is an optional string received by program SOURCE as initial
  186. text when its execution begins.
  187.  
  188. -
  189. Explicit disk assignments can be made for any of the files mentioned in these
  190. command lines. Explicit extensions can also be given, but their omission has
  191. proved to be extremely convenient.
  192.  
  193. The execution of the compiled program requires the presence of a library,
  194. CNVLIB.REC, in the current disk.  The operation of I/O skeletons varies
  195. depending on the presence or absence of the additional argument in the command
  196. line; the variants are described in the corresponding section.  When execution
  197. terminates, all open files are closed and the last contents of the workspace
  198. are displayed on the console.
  199.  
  200. Since a Convert program will be compiled into a REC program, it is convenient
  201. to require that it be laid out like a REC program:
  202.  
  203.     (subroutine 1) n1 (subroutine 2) n2 ... (main program)
  204.  
  205. wherein subroutine definitions alternate with subroutine names, which are
  206. printing ASCII characters excluding the space and the 11 characters ( ) % &
  207. # ~ < > , @ and }.  CONVERT will insert the appropriate braces to get a REC 
  208. program, as well as a subroutine to initialize and load the required routines
  209. from the library.
  210.  
  211. -
  212. Certain comments enclosed in square brackets are processed by the compiler;
  213. in order for them to be noted the program should be structured according to
  214. the following scheme:
  215.  
  216. [SOURCE.CNV]
  217. [Author, Date]
  218. [comments]
  219. [Exclude LIB]
  220. [Include ..]
  221. [[Logon message at startup.]]
  222.  
  223. [subroutine a descriptor]
  224. (()()()()) a
  225.  
  226. [another subroutine]
  227. (()()()()) b
  228.  
  229. [main program]
  230. (()()()())
  231.  
  232. The comments which are processed are [xx.CNV], [Exclude LIB], [Include ..]
  233. and [[...]].
  234. -
  235. The header [SOURCE.CNV] should be upper case, and will be transformed into
  236. [SOURCE.REC] by the compiler. The header, together with the attribution of
  237. author and date help to identify the program, and with the date, its version.
  238. All this header material should be placed in balanced square brackets.
  239.  
  240. The [Exclude LIB] comment indicates the program should not include the initial-
  241. izing routine; if appearing, it overrides any [Include ..] also present
  242. [Include ..] indicates which routines must be loaded at run time in addition
  243. to those whose inclusion is automatically determined at compile time.  Both
  244. types of comment are optional.
  245.  
  246. The double square brackets may enclose a logon message that will be displayed
  247. at startup. It may be shown again during the program execution by using the
  248. skeleton function (%Q). It should be short and concise, as it will occupy
  249. space at runtime. If none is included in the program, Convert will insert the
  250. message "convert/icuap/1985".
  251.  
  252. The subroutines and main program then follow.  The compiler displays for each
  253. one of them the names of patterns and skeletons they define, the variables they
  254. declare, the punctuation following each rule (: or ;), the name of the subrou-
  255. tine (if it is one), and a series of dots, one for each sector of compiled code
  256. written to the disk.
  257. -
  258. :Library and Initalization.  The library is contained in file CNVLIB.REC, which
  259. is sought and read during the initializing process.  The library should reside
  260. in the currently logged disk unless the command line contains an argument
  261. having one of the following forms:
  262.  
  263.             L/B:
  264.             L/d:filename.ext
  265.  
  266. The first form indicates CNVLIB.REC resides on the specified disk (B in the
  267. example); the second form indicates that the file whose name is given (in
  268. which both the disk identifier and the extension are optional) should be used
  269. as library.  No extension is assumed in the second form if one is not given
  270. explicitly.
  271.  
  272. The argument L/ is transparent to the program, that is, it will neither appear
  273. in the program's initial text nor interfere with other arguments; for instance,
  274.  
  275.         REC80 DSASM L/A: WRTSYS
  276.         REC80 DSASM WRTSYS L/A:
  277.  
  278. both produce the same result, passing the string "WRTSYS" as initial text to
  279. the program being executed (DSASM.REC).
  280. -
  281. The [Include ..] comment is only required by the root program in an overlay
  282. tree, by a program requiring floating point arithmetic, or by a program using
  283. the operators ^ or ** (for exponentiation) or % (for remainder) in arguments
  284. to the formula-evaluating skeleton (#f,s) and not calling explicitly the skele-
  285. tons #^ or #%.  For example, the comment [Include #.#^#%] is required for a
  286. program which would evaluate formulae containing floating point numbers and
  287. exponentiation and remainder operations, and invoking only the library function
  288. #f.
  289.  
  290. The [Exclude LIB] comment is required by the overlaying segments of an overlay
  291. tree.  More about Include and Exclude may be found in CNVADV.HLP.
  292.  
  293. :Boolean patterns.  One of the mechanisms for generating complex patterns
  294. from simpler constituents is to form Boolean combinations of patterns. The
  295. fundamental Boolean connectives AND, OR, and NOT may be used.  In Convert, AND
  296. and OR are not binary operations, but rather may have any number of arguments;
  297. a Boolean function of a variable number of arguments has a standard definition,
  298. which follows the associative law and reduces to the binary function in that
  299. special case. Thus it is not capriciousness which requires that
  300.  
  301.         (AND)        always matches (to the null string)
  302.         (AND,p)        is the same as p (matches if p matches)
  303.         (AND,p1,p2,...)    matches when all of the pj match
  304.         (OR)        never matches
  305.         (OR,p)        is the same as p (matches if p matches)
  306.         (OR,p1,p2,...)    matches if at least one pi matches.
  307.  
  308. As is customary in programming languages, Boolean combinations are executed
  309. progressively, so that no more arguments are evaluated than the minimum
  310. needed to reach a decision. The first failure in an AND, the first match in
  311. OR decides the expression.
  312.  
  313.  
  314.  
  315. -
  316. Convert has an alternative series of Boolean functions, namely (and,...),
  317. (or,...), and (nor,...) [which is equivalent to (NOT,(or,...))]. They exist
  318. only for reasons of efficiency.  The issue is that Convert combines variable
  319. matching with variable generation, rather than separating these two activities.
  320. This is in turn more efficient, but subject to logical paradoxes if not done
  321. correctly. Concretely, if a variable match fails, Convert will back up and
  322. retry the previous variable it identified, or will progress to the next 
  323. alternative of a preceding OR. In using the lower case Boolean operators we
  324. forsake all this jockeying in the interest of speed, but it is forsaken
  325. nevertheless.
  326.  
  327. Thus, lower case Boolean operators are to be used when the decision which
  328. they represent is final - for example if their arguments are constants. In
  329. practice, if the patterns (ITR,xxx) and (itr,xxx) are used, the searching
  330. required by a program can be assigned to them, and the lower case operators
  331. used exclusively. The upper case operators work correctly albeit more slowly.
  332.  
  333. Combining variable generation with variable matching as Convert does restrict
  334. the participation of NOT in patterns; its arguments must not contain unbound
  335. variables.
  336.  
  337.  
  338. -
  339. One of the most common uses of AND is to impose some condition on a variable,
  340. although it could also be used to parse a string in two or more different ways.
  341. For example, consider CP/M's directory entry from which we may wish to extract
  342. the file name and the extension, and ignore the rest of the block. The pattern
  343.  
  344.     (and,<[1]>(and,<[8]>,<1>)(and,<[3]>,<2>)<[20]>,<4>)
  345.  
  346. will bind the whole 32-byte string to the variable <4>, but at the same
  347. time allow us to retrieve the file name as <1>, and the extension as <2>.
  348. Both uses of AND are shown in this example. The pattern
  349.  
  350.     (and,(ITR,(and,<[1]>,(nor, ,(^I))),<0>)
  351.  
  352. will match a string free of spaces or tabs - whitespace as some say - and
  353. associate it with the variable <0>. The inner "and" prevents the null string
  354. from matching the "nor". The first argument of an AND establishes the length
  355. of the string that the remaining arguments must match. Another example would
  356. be to identify a decimal number through
  357.  
  358.     (and,(ITR,(and,<[1]>,(IVL,0,9,))),<0>).
  359.  
  360.  
  361. -
  362. The most apparent use of the Boolean OR is to express alternatives. Taken
  363. together with a mechanism to assign a name to a pattern, OR can be used to
  364. generate recursive patterns.  Given the definition
  365.  
  366.         ((or, <:s:>,)) s
  367.  
  368. we can define a series of spaces - which is either a space followed by the
  369. series, or the null string. This definition also makes use of the property,
  370. that the first viable alternative satisfies an OR.  Alternatively,
  371.  
  372.         ((OR,, <:m:>)) m
  373.  
  374. would be a pattern that rendered the null string unless a reconsideration
  375. were forced upon it. These two alternatives define respectively a maximal
  376. and a minimal string satisfying a condition defined by an OR. Equivalently,
  377.  
  378.         ((ITR, )) s
  379.         ((itr, )) m
  380.  
  381. Many other kinds of recursive definitions can be made with OR, but it is
  382. interesting to note that ITR and itr seem to be sufficient for the
  383. applications that have been encountered.
  384.  
  385. -
  386. An OR with a null terminal argument is a convenient way to express optional
  387. elements of a string. Consider
  388.  
  389.         ((or,+,-,)<:d:>(or,.<:d:>,)) f
  390.  
  391. as a definition of a signed floating point number. The sign is entirely
  392. optional, as is the decimal point. According to whether <:d:> accepts the
  393. null string or not, <:f:> could match or not a single isolated decimal point.
  394. If it does not, we would have to modify the definition to make 1. into an
  395. acceptable number.
  396.  
  397.  
  398. :Constant Patterns and Skeletons.  There are two types of constants: default
  399. constants and distinguished constants.  A default constant is any string
  400. including spaces, tabs, carriage returns, line feeds and printing ASCII
  401. characters (those between ! and ~) except any of the seven characters ( )
  402. < > , " and '. The first five exceptions have been reserved to delimit
  403. patterns and skeletons of diverse kinds; the last two play an exceptional role
  404. in REC and so must be given special treatment; it is the conflict with REC
  405. which keeps them from being used for quoting in Convert.  The distinguished
  406. constants are described in the remainder of this section.
  407.  
  408. The very delimiters themselves have to be quoted; for conciseness and to
  409. avoid reserving yet more symbols, we use them to quote each other:
  410.  
  411.         <(>    left parenthesis
  412.         <)>    right parenthesis
  413.         (<)    left angle
  414.         (>)    right angle
  415.         <,>    comma
  416.         <'>    single quote
  417.         <">    double quote
  418.  
  419.  
  420. -
  421. It is not convenient to incorporate control characters directly into programs,
  422. because they interfere with printing the program for reference. The pattern
  423. (CTL,xxx) proved to be unsightly, so we use the form (^xxx), in analogy to
  424. the common representation ^X for a single control character.  The characters
  425. allowed in the string xxx are those between @ and _; these bounds correspond
  426. to control characters whose values in ASCII are 0 and 31, respectively. Some
  427. useful control characters to remember are:
  428.  
  429.         (^I)    horizontal tab
  430.         (^Z)    end of file
  431.         (^MJ)    carriage return, line feed
  432.         (^[)    escape
  433.  
  434. Provision has been made for quoting a long string, too cumbersome to represent
  435. character by character using the foregoing conventions; we could write
  436.  
  437.         (QUO/.../)
  438.  
  439. wherein / could be any character not occurring in the text ..., and terminates
  440. the string with its second appearance in the pattern.
  441.  
  442.  
  443. -
  444. Two constants have been provided for recognizing (as patterns) or generating
  445. (as skeletons) bytes of binary data:
  446.  
  447.         (DEC,n)        decimal byte n (mod 256)
  448.         (HEX,k)        the shortest byte string needed to represent
  449.                 the hex value k (including leading zeros in k)
  450.  
  451. For example, (DEC,2035) represents a byte whose decimal value is 243, whereas
  452. (HEX,5C) represents a byte whose decimal value is 92.  For hexadecimal strings
  453. with 3 or more digits, the string represented by (HEX,k) is machine-dependent;
  454. in microprocessors following Intel's convention, (HEX,05C) would represent two
  455. bytes, the first of which is 92 (decimal) and the second zero (the least
  456. significant byte in the lowest addressed location); on other microprocessors
  457. like the MC68000, (HEX,05C) would represent two bytes, the first one zero and
  458. the second one 92 (the most significant byte at the lowest address).
  459.  
  460. :Input-Output skeletons exploiting CP/M's BDOS and BIOS:
  461.  
  462.     (%Or,D:FILENAME.EXT)        open file for reading
  463.     (%Ow,D:FILENAME.EXT)        open file for writing
  464.     (%R)                read from default
  465.     (%R,D:FILENAME.EXT)        read file
  466.     (%R,source,pattern)        read until match
  467.     (%R,source,patt,skt)        read, match, substitute
  468.     (%R,source,patt,skt,skf)    read, match, two options
  469.     (%W,D:FILENAME.EXT,xxx)        write file
  470.     (%C,D:FILENAME.EXT)        close file
  471.     (%E)                close all files
  472.     (%Z)                reset disk system
  473.     (%Lr)                get id of currently logged-in disk
  474.     (%Lw,D)                log in the given disk
  475.     (%S,D:FILENAME.EXT)        search
  476.     (%A,D:FILENAME.EXT)        search again
  477.     (%D,D:FILENAME.EXT)        delete
  478.     (%N,D:NEW.NXT,D:OLD.OXT)    rename
  479.     (%T,xxx)            type, preserve
  480.     (%t,xxx)            type, erase
  481.     (%+)                type CR,LF
  482. -
  483.     (%P,xxx)            print, preserve
  484.     (%p,xxx)            print, erase
  485.     (%B,dfc,hcx,hdx)        direct BIOS call (CP/M-86)
  486.  
  487. The pattern-directed READ operation is worthy of attention. There are
  488. several forms of the READ function-skeleton %R,
  489.  
  490.     (%R)                read from default
  491.     (%R,D:FILENAME.EXT)        read file
  492.     (%R,source,pattern)        read until match
  493.     (%R,source,patt,skt)        read, match, substitute
  494.     (%R,source,patt,skt,skf)    read, match, two options
  495.  
  496. which are progressively more complex.  Beginning with the first, a default
  497. input device is assigned, and a single line is delivered to the workspace
  498. with each invocation, without the terminating carriage return or line feed.
  499. The default will be the disk file mentioned on the command line when the
  500. program was loaded for execution, unless the line was blank. In that case
  501. the console is assigned. This form gives a simple means of communication
  502. that can be especially helpful in the initial stages of program development.
  503.  
  504.  
  505. -
  506. The next alternative in the sequence of complexity requires the programmer
  507. to assign a specific disk file. The latter can be a constant, as illustrated
  508. above, or it can be a skeleton which evaluates into the name of the disk file.
  509. An example would be (%R,<7>:<8>.<9>), where the disk, file and extension have
  510. been determined separately and bound to variables 7, 8 and 9, respectively.
  511. (%R,) is the same as (%R).
  512.  
  513. Just as in the default case, a single line, without its terminator, is placed
  514. in the workspace with each execution of the skeleton. If the end of file has
  515. been reached, a control-Z is inserted and will be produced repeatedly each
  516. additional time an attempt is made to read the exhausted file. The file itself
  517. is buffered so that partial contents such as a single line can be read at will.
  518.  
  519. Sometimes data is not divided into lines, or it may be that the program finds
  520. it inconvenient to receive a whole line at a time. A binary file would typify
  521. the former case, the scrutiny of a file word by word or by sentences would
  522. exemplify the second. In these cases the third form of %R is useful.
  523.  
  524. The third variant, to which a pattern has been adjoined, will search the
  525. input stream until the first instance of the pattern is found, which will
  526. then be given to the workspace. Using the skeleton again will locate the
  527. second instance of the pattern, and so on.
  528. -
  529. If the file is exhausted and no match was obtained, all of the material read
  530. remains in the workspace; subsequent reads will leave the null string.
  531.  
  532. The final two forms practically allows the incorporation of a whole pre-
  533. processor into the read command, since it allows any recognition and
  534. transformation that Convert is capable of expressing to be incorporated 
  535. into the act of reading a file; furthermore this processing can be tailored
  536. individually for each file, and even for each instance of reading.
  537.  
  538. In the next to the last case, %R leaves the value of skt if the pattern
  539. does match; otherwise all of the text (to the end of the file) is left.  In
  540. the last case, skf is a skeleton which generates the text left in the
  541. workspace if the pattern does not match the text read.
  542.  
  543. In these skeletons, if the null pattern is given [e.g. (%R,,,skt)], %R reads
  544. up to the next carriage return (or to the end of the file if no CR is found).
  545.  
  546.  
  547.  
  548.  
  549.  
  550.  
  551. -
  552. Skeletons performing writing operations vary as to the result they leave in
  553. the workspace.  Skeletons %T and %P leave the value of their argument; %t and
  554. %p always erase it.  In addition, %T and %t write CR and LF before sending
  555. their argument to the console, whereas %P, %p and %W write no more than the
  556. value of their arguments.
  557.  
  558. If %W is not able to write on the indicated file due to lack of space, it will
  559. leave on the workspace the unwritten portion of its argument.
  560.  
  561. (%Or,D:FILENAME.EXT) leaves the bull string if it was possible to open the
  562. indicated file; it leaves the string "Not Found" if the file could not be
  563. opened.
  564.  
  565. In functions %R, %W, %Or, %Ow and %C the value of the skeleton designating the
  566. file is not restricted to an actual disk file, in conformity with CP/M's PIP
  567. conventions that there may be such devices as TTY: or EOF:. The assortment
  568. is not exactly the same, but it includes
  569.  
  570.         TTY:    console keyboard
  571.         NUL:    the null file
  572.         CTR:X    named counter
  573.         MEM:X    named memory pseudofile
  574. -
  575. The operations of reading via %R and writing via %W may be performed on
  576. these devices just as though they were disk files. They may be opened and
  577. closed by using %O and %C; in fact these operations are a necessity if these
  578. false devices are to be given a meaningful definition, or if they are to be
  579. removed from a program in an orderly fashion when they are no longer required.
  580.  
  581. (%W,TTY:,skel) works like (%t,skel), but without the CR/LF included by %t
  582. in its operation.
  583.  
  584. Every write operation on NUL: simply erases its argument; every read from NUL:
  585. returns control-Z; that is, NUL: functions as a file to which one can "write"
  586. without limit but which is permanently exhausted when read.  This pseudofile
  587. is useful in compiler and assembler construction, where for test purposes one
  588. may not want to produce, say, an object file.  In this case a variable could
  589. be bound at the beginning of the program to NUL: or to a disk file, and this
  590. variable be used in all references to the object file.
  591.  
  592. MEM:X pseudofiles are dealt with in detail in CNVADV.HLP.
  593.  
  594.  
  595.  
  596.  
  597. -
  598. To open and then read a counter requires only a name, of eight or less
  599. ASCII characters. Neither counters nor memory regions use extensions.
  600. To write a counter we have a series of parameters, whose tail may optionally
  601. be discarded at any point after the counter's name. Altogether, we can write
  602.  
  603.         (%Or,CTR:XXXXXXXX)
  604.         (%W,CTR:XXXXXXXX,val,incr)
  605.         (%R,CTR:XXXXXXXX)
  606.  
  607. Argument val is the initial value; its default is 0; incr is the increment,
  608. which may be signed and whose default is +1; the assigned value is any
  609. (sixteen bit) integer which is modified in modulo-16 arithmetic. Both of the
  610. parameters are ASCII strings representing decimal numbers, introduced into
  611. the skeleton as constants or as other skeletons which evaluate into constants
  612. of the required form.  Every time that a counter is read, its present value
  613. is reported, but the increment is added to its stored value so that it will
  614. appear at the next reading.  In the language of "C",it is a postincrementing
  615. counter. When a counter is opened, it is assigned default value 0, increment 1.
  616.  
  617.  
  618. :Directory Skeletons.  It is possible to write a Convert program which will
  619. process a series of files, for example to empack several short files into
  620. a single large file. Later, with another similar program, they can be restored
  621. to their original condition. This process can be used advantageously to build
  622. up a library for Microsoft's F80, for example. Although they offer a library
  623. function which can combine several .REL files, there lacks a way to assemble
  624. hundreds of small .MAC files individually, yet not overflow the directory of
  625. the single disk which could hold them.
  626.  
  627. To realize this sort of operation Convert offers access to the BDOS functions
  628. for directory and disk system access via the operators K and k in REC.
  629.  
  630.     (%S,D:FILENAME.EXT)         initial search for file
  631.     (%A,D:FILENAME.EXT)         subsequent search for file
  632.     (%D,D:FILENAME.EXT)         delete specified files
  633.     (%N,D:NEWFILE.EXT,D:OLDFILE.EXT) rename file
  634.     (%Z)                 reset disk system
  635.     (%Lr)                 get id of currently logged-in disk
  636.     (%Lw,D)                 log in the given disk
  637.  
  638. The %Z and %L functions are required when disk changes are contemplated.
  639.  
  640. -
  641. The following scheme, showing a Main program and satellite, can be used as
  642. the basis of a Convert program which will process a series of files as shown
  643. by a possibly ambiguous file reference in the initial command line.
  644.  
  645. [Program heading, including Name, Excludes, Comments and Logon Message]
  646.  
  647. [the bulk of the program, accessed through a program called "y"]
  648. (()()()()) y
  649. ...
  650.  
  651. [Gather directory entries in WS]
  652. (()()(0)(
  653.     (Not Found<0>,<0>);
  654.     (<0>,(%A,<8>:<9>)<0>):
  655.   )) z
  656.  
  657. [Main program: search for first]
  658. (()()(8 9)(
  659.     (<8>:<9>,(y,(z,(%S,<8>:<9>))));
  660.     (<9>,@:<9>): 
  661.   ))
  662.  
  663. -
  664. On arriving at the execution of "y" the workspace contains all the relevant
  665. directory lines - possibly none - which were found by "z". It is advisable
  666. to gather them up all at once on entering the program, before the directory
  667. begins to change. This avoids the conflict of a new file having the same name
  668. as an old file, avoids the loss of the internal state which is stored in BDOS
  669. between calls, and avoids an error latent in some versions of CP/M.
  670.  
  671. For other programs to use the workspace, this directory extract must be stored
  672. in a variable and parcelled out to the programs as they are required. It will
  673. generally be sufficient to call the following program "y" and interpose it
  674. between the actual program, "x", and the main program, which already calls it.
  675.  
  676. [Get next name]
  677. (()()(1 2 3)(
  678.   [quit if no more]    (<>,);
  679.   [parse dir entry]    (<[1]>(and,<[8]>,<1>)(and,<[3]>,<2>)<[20]><3>,<<
  680.   [process this file]        >>(x,<8>:<1>.<2>)))<<
  681.   [rest of files]        >><3>):
  682.   )) y
  683.  
  684. "x" encounters its file, D:FILENAME.EXT on entry, must leave a null chain when
  685. it finishes; but it could possibly return some additional files for processing.
  686. -
  687. :Arithmetic Skeletons.  Convert provides facilities for integer and floating
  688. point arithmetic (through skeleton #) and for character "arithmetic" (through
  689. skeleton &).  The latter facilitates upper/lower case conversions, hexadecimal
  690. dumps and access to individual bits or groups of bits within bytes.
  691.  
  692. The file CNVADV.HLP contains a detailed description of the operations possible
  693. with these two library skeletons.
  694.  
  695. :Conditional and iterative skeletons. The fundamental skeleton forms in 
  696. Convert are constants, variables and functions. In principle it is sufficient 
  697. to work with this combination because functions are readily defined and 
  698. capable of defining any construction that one wants. Thus the motivation for 
  699. introducing further skeleton forms would have to be to offer some frequently 
  700. used function as an inherent feature of the language. Other motives would be 
  701. to avoid the cumbersome ritual of defining a function if a particularly 
  702. simple action were desired, or to avoid preparing an argument for a function 
  703. and then finding that the argument would not be used after all.
  704.  
  705. Most languages have facilities for the selection of alternatives - an IF
  706. statement, or for an orderly repetition of some activity - a DO or a WHILE
  707. statement. The convenience of these constructs is widely recognized. Convert
  708. offers the conditional skeletons if, IF, nf and NF, and the iterative
  709. skeletons whil, WHILE, until and UNTIL, all of which are described in
  710. detail in CNVADV.HLP.
  711.  
  712. :Variables are numbered decimally in Convert. There is no theoretical limit
  713. to their range, but the practical range is 0-30 with the present structure
  714. of the underlying REC compiler. Few programs go beyond ten variables, many
  715. subsist with one or two, and it is possible to have a program without any
  716. variables at all.
  717.  
  718.  
  719. Even if a program binds no variables, they must be enclosed in parentheses.
  720. The same is true of pattern and skeleton definitions, so that a program
  721. quadruple (()()()()) may contain some null parentheses.
  722.  
  723. A program should not bind a variable which it has not declared - that is,
  724. if a previously undefined variable appears in the pattern of one of the
  725. rules of a program where it may become defined, it must be declared in the
  726. variable list. A program in which this has not been done may work, but the
  727. order in which variables are pushed and popped in the internal dictionary
  728. will be violated, and it can only result that obscure errors will occur.
  729.  
  730. A variable is designated by enclosing its number within angle brackets. <0>,
  731. <8>, or <15> are examples of variables. Variables are defined by patterns and
  732. used by skeletons. Convert combines variable matching and variable generation
  733. so that a variable can be defined and then matched within the same pattern.
  734. -
  735. Generally speaking, variables are defined by the constants which surround
  736. them; thus v<0>e would assign the value ariabl to <0> when matched against
  737. the word variable, or a null value when matched to ve. Since the null string
  738. is accepted throughout Convert, a very common type of error arises from matches
  739. involving a null string in a way that the programmer had not foreseen. Since
  740. Convert uses other pattern forms than constants, a variable need not always be
  741. delimited by a constant. <[9]>(and,<[3]>,<0>)<[20]> could be used to pick the
  742. extension out of a CP/M directory entry, for example.
  743.  
  744. Persons who like long or arbitrary variable names will be disappointed with
  745. Convert.  When CONVERT was built over a LISP substrate, it was possible to make
  746. arbitrary choices of variable names; this was because LISP contained a kind
  747. of preprocessor which parsed individual atoms and replaced them by their own
  748. address in a dictionary. A string parser does not necessarily want to isolate
  749. atoms, so another symbolism must be found.
  750.  
  751. Other persons find that it is much easier to work with a very concise symbolism
  752. even though it means reusing the same few symbols over and over again in each
  753. different context.  Thus one may see a complicated file of Convert programs all
  754. of which use the same series of variables <0>, <1>, ... up to the number that
  755. the given program requires. It is not hard to become accustomed to this way of
  756. thinking.
  757.  
  758. :Intervals.  There is a kind of pattern, which is technically a variable when 
  759. giving a formal definition of the syntax of Convert, but which is not treated 
  760. as a variable in this description because it is not assigned a name, and so 
  761. can't be referred to again, either in the same pattern or in the paired 
  762. skeleton of its rule. Of course, it is not lost entirely; it can be named by 
  763. participating in an AND together with a named variable. We call these unnamed 
  764. variables intervals, of which there are three kinds:
  765.  
  766.         <-->    indefinite interval
  767.         <[n]>    interval of length n
  768.         <>    null interval (no more text in workspace)
  769.  
  770. The indefinite interval simply allows us to skip over uninteresting parts of a
  771. text - for example an end-of-file embedded in a line of whatsoever length can
  772. be detected by <-->(^Z).
  773.  
  774. Tabular information can be broken into columns by specifying an interval of a
  775. determined length. Such a pattern is often paired with a named variable through
  776. an and, as in (and,<[8]>,<0>). In this sense it is a predicate, describing some
  777. property of a string, and it is reasonable that it should be compounded using
  778. the Boolean AND.
  779.  
  780. -
  781. A null pattern will always match a null interval, but the null designator <>
  782. refers to something slightly different; it requires that it be matched to the
  783. entire remainder of the workspace, and that that remainder be null. Thus the
  784. rule
  785.     (<>,there<'>s nothing here)
  786.  
  787. will guarantee that the workspace is empty and say so; the rule
  788.  
  789.     (,goodbye)
  790.  
  791. will ALWAYS succeed. It is a useful final rule to give a function a value.
  792.  
  793. The reason that we have to insist explicitly on a null workspace has to do
  794. with a quirk of the pattern matching process which usually simplifies programs
  795. and makes them run faster. A final VARIABLE, including <-->, will always match
  796. the entire remainder of the workspace. A final CONSTANT, including definite
  797. intervals, will only require corresponding text, but will remain indifferent to
  798. any text or lack thereof which follows it. This is why null text will match
  799. anything, because "anything" always begins with a null character. Historically
  800. CONVERT programs spent far too much time seeking character by character for the
  801. end of the text when it corresponded to a final variable. Likewise, it is
  802. bothersome to append a final <--> to text only whose beginning interests us.
  803. -
  804. There is another context in which the null-seeker <> is implicit. Suppose
  805. that we have defined balanced parentheses using the following two pattern
  806. definitions:
  807.  
  808.   [non-parenthesis]        ((and,<[1]>,(nor,<(>,<)>)) n
  809.   [balanced parenthesis]    (<(>(ITR,(or,<:p:>,<:n:>))<)>) p
  810.  
  811. and that we want to bind the variable <0> to the contents of a parenthesis
  812. pair. We would then define
  813.  
  814.   [parenthesis interior]    ((and,<:p:>,<(><0><)>)) i
  815.  
  816. where the second pattern in the "and" has implicitly the form <(><0><)><>,
  817. which ensures that the right parenthesis following <0> is the final right
  818. parenthesis that <:p:> picked out, not the first one to be found; the
  819. implicit <> is required by the definition of "and".
  820.  
  821. :The working part of a Convert quadruple is its rule set, the fourth member
  822. of the quadruple. There is not much point to a null rule set, but it is
  823. quite possible for a program to depend on a single rule. The set has the
  824. form
  825.         (
  826.         (p1,s1):
  827.         (p2,s2);
  828.         ...
  829.         (pn,sn);
  830.         )
  831.  
  832. The outer parentheses are necessary; they define the set. The inner parentheses
  833. are also necessary, for they define the rule. It is a matter of one's personal
  834. preference as to where the external parentheses are located, but it is good
  835. programming practice to adopt a definite style and follow it, as it makes
  836. errors much easier to spot when reviewing a program.  In contrast, once the
  837. rule has commenced, every space, tab, line feed or what not counts. The comma
  838. which separates the pattern from the skeleton is a prominent part of the rule
  839. and must be placed accurately. Commas which occur within the pattern are also
  840. crucial in their placement. Commas which are really constants and part of the
  841. text must be quoted: <,>.
  842.  
  843. -
  844. The colons or semicolons which immediately follow the rules are essential, and
  845. are an inheritance from REC. They determine whether a rule is to be repeated,
  846. when the colon is used, or whether the program has terminated, signalled by the
  847. semicolon. Rules are tried out in sequence, from top to bottom, left to right
  848. as they are written on paper. Several short rules can occupy the same line if
  849. convenient. If no rule applies, the workspace is left unchanged. This is still
  850. another way that the execution of a program may terminate.
  851.  
  852. There are some fine points to be considered in designing a rule set. Using a
  853. colon to produce an iterative transformation of the workspace supposes that
  854. the whole workspace is available for the transformation. If only a part of
  855. the workspace is to be subject to the transformation, the preservation of the
  856. remainder arises in a way that makes it preferable to exercise a recursive
  857. call even though it is to the same rule set. This makes counting the number
  858. of preserved fragments automatic.
  859.  
  860. Since Convert is a pattern directed language, and the pattern is presented
  861. by example and not in some other way, the rules must be stated precisely.
  862. Outside the rule more freedom is permitted, allowing the rule set to be
  863. formatted according to what the programmer considers attractive. Comments,
  864. enclosed in square brackets, have no effect on the compilation and their
  865. liberal use will enhance the program's quality.
  866.  
  867. :Debugging Aids.  Convert offers several aids to debugging programs. As with
  868. any language, programs that don't contain errors don't have to be debugged.
  869. This may look like redundant advice, but it is sound.  Good programming habits
  870. reduce errors. Although there are free-form aspects to Convert,, it is still
  871. amenable to developing typical program formats and adhering to them. They
  872. promote good programming, and make lapses easier to detect. The patterns
  873.  
  874.         (PWS)        [print remaining workspace]
  875.         (PWS,mssg)    [identify printed workspace with message]
  876.         (HLT)        [stop program, wait for keystroke]
  877.         (HLT,mssg)    [print message, then halt]
  878.         (PVR,n)        [print value of variable n]
  879.         (NOP,p)        [null pattern, disables p]
  880.  
  881. are provided primarily for debugging. The rule
  882.  
  883.         ((PWS,subroutine: )(or),);
  884.  
  885. placed at the beginning of a program allows tracing by showing the workspace as
  886. each subroutine is entered; also the evolution of the workspace as repetitive
  887. rules change it.  If a given rule hangs up a calculation, it can be found
  888. by interspersing this same rule among the normal rules.
  889. -
  890. On the skeleton side of a rule, the only debugging aids are the skeleton
  891. functions %t and %T which display their argument on the console (the former
  892. nulls its argument, the latter returns it unchanged).  %T may be applied to a
  893. problematical skeleton to see what kind of a result it produces when evaluated.
  894. If a function is under suspicion, the combination
  895.  
  896.         (%T,(f,(%T,...)))
  897.  
  898. will show both the argument and the result.  To display messages without their
  899. remaining in the workspace, %t may be used:
  900.  
  901.         (%t,...)
  902.  
  903. Selective printing suffices to find the majority of errors in Convert which
  904. are syntactically correct but the result of a poorly designed or erroneous
  905. program. There are occasional errors which are due to flaws in the support
  906. programs which Convert uses. These are gradually being caught and eliminated,
  907. but the possibility always exists that an error has occurred on this more
  908. fundamental level.
  909.  
  910.  
  911.  
  912. -
  913. There are certain possibilities for error arising out of the resemblance 
  914. between the symbolism of REC and the symbolism of Convert, which are activated 
  915. when a bit of source code passes directly from Convert to REC. For example, the 
  916. notation <:0:> for a defined pattern reference can be miswritten <0:>, 
  917. causing ":" to pass unchanged, this may well provoke an unending loop.
  918.  
  919. Another source of error lies in the use of double angle brackets to generate
  920. continuation lines for patterns or skeletons. Consider the code
  921.  
  922.         (pattern,<<
  923.                 >>skeleton 1<<
  924.                 >>skeleton 2>>
  925.                 >>);
  926.  
  927. The double angle following skeleton 2 is reversed; such errors are common.
  928. Note also that the double angles are effective only within a pattern or within
  929. a skeleton, they cannot bridge across from one to the other. Thus,
  930.  
  931.         <<(pattern, skeleton)>>
  932.  
  933. cannot be used to "comment out" a rule.
  934.  
  935. -
  936. If a program cannot be debugged with judicious use of print statements, and
  937. following it with DDT appears too formidable, it is useful to revise the
  938. intermediate REC code. If sections appear more like Convert code than REC code,
  939. a parenthesis, angle bracket or quote is probably unbalanced. It should be
  940. located and corrected, and the compilation tried anew.
  941.  
  942. It is possible to put much more selective print statements or comments in the
  943. REC intermediate, using the operator T or inserting 'message'TL at appropriate
  944. points. Of course, they will be lost when the intermediate is discarded in
  945. favor of a new one when the Convert source is corrected and recompiled, so one
  946. should not expend the effort to make elaborate insertions unless the problem
  947. is very difficult, the intermediate is renamed to save it, or one is willing
  948. to forego a new compilation until significant progress has been made in 
  949. correcting the difficulties in the program.
  950.  
  951.  
  952. :Performance. As a very rough estimate, a REC program compiles into three times
  953. as many bytes as the source code. This factor is reduced according to the ratio
  954. of comments to program, and when large quantities of text are quoted. Comments
  955. result in no compiled code; quoted material goes over byte for byte plus a tiny
  956. overhead to load it onto the pushdown list at execution time.
  957.  
  958. Convert programs typically produce 30% more REC object code than there was
  959. source code, again modified by the presence of comments and the ratio of
  960. constant patterns and skeletons to the use of variables and Boolean composites.
  961. To this one must add the initializing code inserted by the compiler, occupying
  962. about 1K.  Once loaded and ready to execute, a Convert program takes up about
  963. 3.5 times as many bytes as in the source file, plus 2K of initializing code
  964. and between 2K and 12K of library routines, depending of the program require-
  965. ments determined by its use of library calls.
  966.  
  967. As a practical matter, the maximum size Convert program (in source) that a
  968. REC compiler can execute (without recourse to overlays) is about a quarter
  969. of the compilation area size at REC's disposal, which is about 23 or 24K
  970. for REC80 and up to 60K for REC86.
  971.  
  972.  
  973.  
  974. -
  975. Many of the simple programs that can be written in Convert can also be written
  976. in assembly language, and the amount of resultant code compared. In very
  977. general terms, the factor ranges between ten and twenty, tending to twenty.
  978. A similar inflation is experienced in some other "high level" languages - the
  979. "C" compiler for example. The reason for this inflation is readily found in
  980. the formal expansion of certain structures which have to be fairly intricate
  981. to handle general cases and can be much reduced in particular instances.
  982.  
  983. Programming time in Convert can be extremely short - minutes in some cases. The
  984. inflation in program size is fully recovered when considering development time
  985. for a program.
  986.  
  987. Execution time tends to follow program size. Programs written in Convert to
  988. process files can handle them at the rate of lines per second - slow compared
  989. to good assembly language programming, not unacceptable in an absolute sense,
  990. and vastly faster than doing the same job manually through an editor.
  991.  
  992.  
  993. :Bibliography.
  994.  
  995.     [CNVRT.HLP]
  996.     [Harold V. McIntosh, 11 March 1984]
  997.     [Rev.: G. Cisneros, 23 January 1986]
  998.  
  999. [Convert is a chain oriented adaptation of the LISP based CONVERT in
  1000.  
  1001.         Adolfo Guzman and Harold V. McIntosh
  1002.         CONVERT
  1003.         Communications of the ACM 9 604-615 (1966).]
  1004.  
  1005.  
  1006.  
  1007. :[end]
  1008.