Introduction. Patterns. Subroutine Groups. Conditional Skeletons. Iterative Skeletons. The "Same" Skeleton <=>. Data Transfer and I/O. Pattern-directed read. Memory buffer operations. Disk system, display and return to CP/M functions. Null pseudofile. Arithmetic Skeletons. Character "Arithmetic". Overlays. "Exclude" feature. Miscellaneous features. :Introduction. This Help file describes advanced CNVRT features as well as additions and changes made to CNVRT after CNVPRG.HLP was prepared. Among the most noteworthy changes the following may be mentioned: - the patterns (OR,...) and (AND,...) are now fully functional [refer to the discussion in Section G (Boolean Patterns) of file CNVRT.HLP]. - The conditional and iterative skeletons if, nf, while and until may contain more than one triple ([s,p,st] in the case of if and nf; [p,sl,sr] in the case of while and until). - Evaluation of general arithmetic expressions whose operands are constants (including floating point) is now possible. - A function reference or a conditional or iterative skeleton may appear as a pattern; it gives a match if the skeleton's value matches the text under examination. :Patterns The Boolean patterns (OR,...) and (AND,...) now have the full functionality expected of them, so that programs of the kind illustrated by the following example are now possible: [Exclude ALL] (( ((OR,[<:e:>],<(><:e:><)>,[<0>],<(><0><)>)) e )()(0)( (<>,); (<:e:><0>,(%t, yes)(%R)): (,(%t, no)(%R)): )) [end] This programs answers yes if it finds the same string inside and to the right of a nest of possibly alternated parentheses and brackets and types no otherwise. For example, ([[([(ab)])]])ab produces "yes", (b)c gives "no". Making this program work requires that the defined pattern e "know" what follows it at the place where it is referenced; this issue has been resolved, so that if pattern <0> in the second rule fails, the next alternative in the OR is tried out. - The effect of having defined patterns check the patterns that follow references to them on compiled programs is a slightly inflated object file (about 10%), so that two compilers are now provided: CNVRT and CNVSM. CNVRT provides the full generality of the language, whereas CNVSM produces less code at the price of less generality in the use of defined patterns. CNVSM should be used only when the program doesn't require that defined patterns check patterns to the right of references to them; our experience is that this covers a fairly large class of programs, so that maintaining the two compilers is justified. Another issue that has now been resolved is that of unbinding variables when backtracking is required. Consider the pattern in the rule (<0>(and,<[3]>,<1>)<--><1><2>, ... ) This should match a string that contains two instances of the same triplet of characters anywhere, such as abcdefbcdgh. In the previous version however, this didn't work because variable 1 became bound after the first trial string (the null string) was assigned to variable 0. If the match didn't succeed in the very first trial, <1> would stay bound during each subsequent trial for variable 0. With the above example, <1> would bind the string abc initially and would then fail to match for each new trial string assigned to <0>: a, ab, abc, abcd, abcde, etc. - This difficulty is now resolved by having each variable unbind other variables whenever a new trial string is required for it; unbinding occurs only for those variables which became bound AFTER the previous trial string was assigned to the variable doing the unbinding. For example, in the pattern <2>:<0>(and,<[3]>,<1>)<--><1><3> if variables 2, 0 and 1 have been bound but a mismatch occurs when the second instance of <1> is sought, in assigning a new trial value for <0> variable 1 will become unbound, but variable 2 will not. The patterns (AND,...) and (and,...) differ in that "AND" unbinds, upon failure, any variables it may have bound, whereas "and" doesn't. "and" suffices in any application in which it is the very first pattern or when there is a variable anywhere to its left (even if hidden away within a defined pattern). "AND" is called for when it is preceded by an (OR,...) or a defined pattern containing an (OR,...), but is not preceded by any variables. (AND,...) should only be used where strictly necessary, as it produces more code and consumes more time during execution. - The length pattern <[n]> admits in place of n any skeleton. The pattern will fail to match if the skeleton doesn't evaluate to a string of ASCII decimal digits, or if the skeleton does evaluate to such a string but there aren't that many characters in the text under scrutiny. Some posibilities now allowed by this pattern are: <[128]> A constant skeleton: its original definition. <[<0>]> A variable, which should be already bound to a string of ASCII digits. <[(&!,<0>)]> The length of the value of a variable. <[(#f,2*<0>+1)]> Twice the value of a variable plus one (the value of the variable here could be a string of ASCII digits or an arithmetic expression whose operands are integer constants). Assuming <0> is bound to the two-digit string "32", the second pattern will match a 32-byte string, the third pattern will match a 2-byte string and the last pattern will match a string of 65 characters. If the value of <0> is abc, of the three examples involving <0> the first and the third will fail, while the second one will match a 3-byte string. - Any functional, conditional or iterative skeleton may appear wherever a pattern is allowed. A skeleton such as (a,<0>:k), (%R), (if,<0>,(^Z),<1>) or (until,(%R),(^Z),<=>,(%R),), when appearing on the pattern side of a rule or within a defined pattern, will have the same effect as if a constant pattern equal to the value of the skeleton were present in its place. Variables used within such skeletons must have been previously bound. :Subroutine Groups. Since CNVRT inherits REC's features as regards the grouping of subroutines, groups of defined patterns, defined skeletons and whole programs may be built. The following example shows a defined pattern group: { ((IVL,0,9)) d (<:d:>(ITR,<:d:>)) i ((or,+,-,)<:i:>) I ((or,<:i:>.<:i:>,.<:i:>,<:i:>.)) r ((or,<:i:>E<:I:>,<:r:>(or,E<:I:>,))) R (<:@:>) } K Notice that the main routine of the group MUST consist only of <:@:>. In this example, d matches a decimal digit, i a decimal integer, I an optionally signed integer, r a decimal number with explicit point and R a general real constant in the fashion of FORTRAN. External references to these patterns are accomplished by writing <:Kd:>, <:Ki:>, <:KI:>, <:Kr:>, and <:KR:>, respectively. A reference to the main routine by itself (e.g., <:K:>) is meaningless and therefore not to be used, and references from within the group to definitions in the same group need not have the group name, as illustrated in the example. - The next example shows a defined skeleton group: { ((%V,MEM:ll,<=>)) G ((%V,MEM:sy,<=>)) Y ((@)) } F The main routine of the group MUST consist only of a reference to the "skeleton" @. Outside references to G and Y may take any of the following forms: (FG,s), (FG), (FY,s) or (FY), where s is a skeleton whose value will be passed as an argument to the corresponding skeleton in group F. (FG) and (FY) deliver a null argument to G and Y, respectively. Finally, program groups may also be formed: { (()()()()) a (()()()()) b (()()()()) } A In this case, subroutines a and b are not directly available from outside the braces, but can only be called by each other and by A; any CNVRT subroutine may be included in a braced group in the fashion shown, and each braced group MUST be a subroutine, the final main program of a CNVRT program file may not be a part of a braced group. :Conditional skeletons. Four conditional skeletons are provided: IF, NF, if and nf. IF and NF require a variable list to be given, if and nf do not. Their general forms are the following: (IF,(v),s1,p1,s1t,s2,p2,s2t,...,sk,pk,skt,sf) (if,s1,p1,s1t,s2,p2,s2t,...,sk,pk,skt,sf) (NF,(v),s1,p1,s1t,s2,p2,s2t,...,sk,pk,skt,sf) (nf,s1,p1,s1t,s2,p2,s2t,...,sk,pk,skt,sf) In skeletons IF and NF, v is list of variables (zero or more integers between 0 and 30 with one space between each pair of variables). Variables appearing in v supersede variables of the same names defined outside the IF or NF during the execution of the conditional skeleton; otherwise, IF and NF operate the same as if and nf, respectively. Each s represents a skeleton and each p represents a pattern. One or more triplets [si,pi,sit] may appear; the last skeleton sf may be omitted (together with the comma which precedes it). The next panels describe the operation of if and nf; we repeat the form of the corresponding skeleton for ease of reference. - (if,s1,p1,s1t,s2,p2,s2t,...,sk,pk,skt,sf) Skeleton s1 is evaluated and matched to pattern p1. If the match succeeds, s1t is evaluated and its value becomes the value of the entire skeleton; if the match fails s2 is evaluated and matched to p2. This continues until a match obtains or there are no more comparisons to be made, in which case the last skeleton sf is left as the result. If no sf appears (which means that the comma following skt is also absent) and all matches fail, the value of the skeleton will be the last skeleton failing to match the pattern which followed it. An example follows: (if,(%R),(^Z),<=>(%t,End of file encountered),(%T,<=>)) This will read a line from the default file; if it finds and end-of-file marker (control-Z), it leaves it but types the message "End of file encountered" (the value of %t is the null string); otherwise, it leaves the line read by (%R) after typing it. The use of more than one s,p,s triplet allows constructs of the "elseif" type within a single (if,...). - (nf,s1,p1,s1t,s2,p2,s2t,...,sk,pk,skt,sf) NF and nf are the negative forms of IF and if, repectively; that is, if s1 does NOT match p1, s1t is substituted, else if s2 does not match p2, s2t is substituted, etc. The last skeleton, sf, is substituted only if all si match the corresponding pi. Alternatively, "nf" may be read as "unless": Unless s1 matches p1, s1t is evaluated and delivered as the result, else unless s2 matches p2, s2t is given as the result, etc. Sf (and the comma preceding it) may be absent, in which case the result will be sk when all si match the corresponding pi. A useful example follows: (nf,(%Or),Not Found,(a,(%R))) This skeleton will call function a, with argument equal to the first line of the default file only if it is possible to open the default file for reading. Variants of this example include giving arguments to the %Or and %R functions. Notice that if the value of (%Or) is "Not Found", this string will be left as the value of the nf skeleton since no "sf" is given. :Iterative skeletons. Four iterative skeletons are provided: WHILE, UNTIL, while and until. WHILE and UNTIL require a variable list to be given, while and until do not. Their general forms are the following: (WHILE,(v),si,p1,s1,s1r,p2,s2,s2r,...,pn,sn,snr,sf) (while,si,p1,s1,s1r,p2,s2,s2r,...,pn,sn,snr,sf) (UNTIL,(v),si,p1,s1,s1r,p2,s2,s2r,...,pn,sn,snr,sf) (until,si,p1,s1,s1r,p2,s2,s2r,...,pn,sn,snr,sf) In skeletons WHILE and UNTIL, v is list of variables (zero or more integers between 0 and 30 with one space between each pair of variables). Variables appearing in v supersede variables of the same names defined outside the WHILE or UNTIL during the execution of the conditional skeleton; otherwise, WHILE and UNTIL perform as while and until, respectively. Each s represents a skeleton and each p represents a pattern. One or more triplets [pk,sk,skr] may appear; the last skeleton sf may be omitted (together with the comma which precedes it). The next panels describe the operation of while and until; we repeat the form of the skeleton for ease of reference. - (while,si,p1,s1,s1r,p2,s2,s2r,...,pn,sn,snr,sf) 1. The initial skeleton si is placed on the workspace. 2. If the pattern p1 matches the text, the skeleton s1 replaces it and a new text to match with p1 is given by the repetition skeleton s1r. This step is repeated until p1 no longer matches the text presented to it. 3. The last text s1r from step 2 (or si if p1 did not match on the very first try) is used as initial text to match with pattern p2, and a similar iteration to that of step 2 takes place on the triple p2,s2,s2r. 4. Similar iterations are performed for each triple pk,sk,pkr; when the last pattern pn fails to match its text, its last residue pnr is left on the workspace, unless the optional final skeleton sf is present, in which case it replaces the text which last failed to match pn. The text produced by "while" will thus be a concatenation of 0 or more instances of s1, s2, ... sn and either of the last of snr or sf; the number of instances of sa, sb, ..., sn will depend on how many iterations of each triple took place. "Until" performs in a similar manner, except that iteration occurs as long as the pattern does NOT match. Examples follow in the next panel. - The following WHILE reads the default file, leaving on the workspace its contents up to but not including the end-of-file marker. (WHILE,(0),(%R),(and,<[128]>,(NOT,<-->(^Z))),<=>,(%R),<< >><=>,<0>(^Z),<0>,) The symbol <=> is the "same" skeleton, whose value is the text used in the last matching attempt (regardless of the outcome); this skeleton is described in the next section of this file. The first triple in the above example leaves on the workspace, one by one, all full disk sectors of the file which do not contain ^Z. The iteration ends when either no more sectors remain in the file or a sector is read which contains a control-Z. The last text (which is either a single ^Z or a sector containing it) is given to the next triple, in which the text match the pattern <0>(^Z), so that <0> will be a null string or the rest of the file up to but not including the ^Z. A null string is given as the repeat text, which will not match <0>(^Z), and the last action of the WHILE will be to "append" this null text to the right of the contents of the workspace. An example of UNTIL follows. - (UNTIL,(0),0,(and,<0>,13),(,(%Ow,MEM:<0>)),(#p,<0>),) This skeleton creates 13 memory buffers, named MEM:0 through MEM:12. Notice that <0> is the first pattern in the "and", so that the variable will be bound to the text even if the whole "and" fails (which will happen 13 times). The skeleton (#p,...) increments by one a number expressed as a decimal number in ASCII; for instance, (#p,12) yields the string "13". The skeleton which would close these buffers and release the memory associated with them would be the following: (UNTIL,(0),12,(and,<0>,-1),(%C,MEM:<0>),(#m,<0>),) (#m,...) decrements its argument; notice that closing is performed in the order opposite to the one followed when opening: since memory buffers are assigned space on the pushdown list, space must be released in order opposite to that of arrival. :The "Same" Skeleton <=>. The skeleton <=> may be used wherever a pattern match has taken place and the workspace hasn't been disturbed (which includes the start of any of the skeletons in ifs, nfs, whiles, untils, etc.); the value of <=> is the whole text in the workspace. For instance, the rule (,<=><=>) leaves two copies of the text to which it is applied. Any concatenation of one or more <=>'s may also be included as the argument of a function or nest of functions, as long as it appears where a single <=> would be allowed. All of the following examples of CNVRT rules (where ... denotes the pattern) are allowed: (...,<=>); (...,<=>(a,(b,<=>))): (...,(a,<=>)): (...,<=><=>(%W,FILE.OUT,<=>)); (...,(%W,(x,<=>),(^Z))); (...,(if,<=>,(^Z),,<=><=>)); (...,(WHILE,(0),(%R),(and,<[128]>,(NOT,<-->(^Z))),<=>,(%R),<< >><=>,<0>(^Z),<0>,)); On the other hand, (...,(%R)<=>) or (...,(a,<=>)<=>) are not allowed because the original text is no longer available at the point where the last <=> is found in each example. :Data Transfer and I/O. In this section we describe additions, extensions and changes to the data transfer and I/O part of the CNVRT library of functions. A listing of functions and options that have not been previously discussed follows: (%R,s,p,st,sf) Read with then/else options (%Or,MEM:n,s) Open memory buffer for reading (%Ow,MEM:n,s) Open memory buffer for writing (%R,MEM:n,...) Read from a memory buffer (%W,MEM:n,s) Write into a memory buffer (%Lr) Get ID of logged disk (%Lw,x) Log in disk x (%t,s) Type and erase argument (%P,s) Print argument ant leave it (%p,s) Print and erase argument (%Q) Type logon message (formerly (%L)) (%M) Return to CP/M NUL: Null pseudofile (%|) no longer exists since (^MJ) performs the same function. The above skeletons are described in detail in the following sections. :Pattern-directed read. (%R,s,p,st,sf) A read is performed on the file or pseudofile described by skeleton s. If the text read matches p, the value of the whole skeleton will be that of st, otherwise sf will be evaluated and delivered to the workspace. Possible alternatives are as follows: (%R,s,,st,sf) The default pattern provided in the library is used. (%R,s,p,,sf) The null string is left if p matches the text read. (%R,s,p,st) st is left if p matches, else the text read is left. (%R,s,p,st,) The null string is left if p does not match the text. If the skeleton s starts with the four-character constant CTR:, no code is generated for pattern matching and all portions of the %R skeleton following s will be ignored if present. A pattern-directed read from a CTR: pseudofile may be accomplished by hiding the CTR: away elsewhere in a defined skeleton, e.g., (() ( (CTR:x) X ) () ( ... ( ... , (%R,(X),...)...); )) where ellipses indicate omitted portions of the program. :Memory buffer operations. Open operations on MEM:-type pseudo files may have an additional skeleton whose value should be a string of decimal digits indicating the size in bytes of the buffer desired. This number is effective only at the time the buffer is actually created; it is ignored if the buffer already exists. If omitted at the time of the initial open, 1024 is assumed. Associated with a memory buffer pseudofile there are two pointers: a read pointer and a write pointer. When the buffer is first created, both pointers reflect an empty buffer. Write operations start writing into a buffer at the location indicated by the write pointer, update the pointer to the next available location when done and remove the written argument from the workspace, however, if the argument doesn't fit in what's left of the buffer, nothing is written, the argument remains in the workspace and the write pointer remains unaltered. Read operations will read all characters between the read pointer and the write pointer and the default pattern or the pattern given explicitly in the read will be tested on this text. If there is a match, the portion of the text which matched will remain in the workspace and the read pointer will be updated to reflect that text has been read out. If no match is possible, the text between the pointers is returned with a ^Z at the end, and the read pointer moves up to the write pointer. - When a read is attempted on a MEM: pseudo file in which both read and write pointers have the same value (either because the buffer is empty or it has been read out entirely), a single ^Z is returned. The final text returned by %R from a memory buffer will of course depend on the presence or absence of the optional skeletons possible in the (%R,...) skeleton. Open operations may be performed on an open buffer, with the following effects: (%Or,MEM:...) moves the read pointer to the beginning of the buffer, thus making available all of its contents. (%Ow,MEM:...) moves both pointers to the beginning of the buffer, effectively leaving it empty. Both open operations on a MEM: pseudofile return the address of the buffer as a four-digit ASCII hexadecimal number; this is provided for use with the %B direct BIOS call available with CP/M-86. For most purposes, %O skeletons involving MEM: buffers should be nested inside the null skeleton (,...) which erases its argument from the workspace. :Disk system, display and return to CP/M functions. (%Lr) returns a single letter (A, B, ...) corresponding to the identifier of the currently logged-in disk. (%Lw,x) logs in the disk sppecified by the first letter of skeleton x; if x is omitte or is null, A is assumed. (%t,s) types and erases the value of skeleton s; it essentially replaces (,(%T,s)); %T retains its function (type and leave). (%P,s) prints on the list device and leaves on the workspace the value of skeleton s. (%p,s) prints on the list device and erases from the workspace the value of its argument, it is equivalent to (,(%P,s)). (%Q) displays the logon message; this is a function previously performed by (%L) [refer to the section on "Program file" in CNVRT.HLP]. (%M) returns to CP/M after closing all files (panic button). :Null pseudofile. The pseudofile NUL: may appear in skeletons %Or, %Ow, %R, %W and %C. When found by %O and %C, no action is taken; reading from the null file always returns a ^Z and writing to the null file has the sole effect of erasing the argument. This feature is useful in compiler and assembler construction, where for test purposes one may not want, say, an object file to be produced. One could then bind a variable near the beginning of the compiler's execution to either of NUL: or an actual file name, and use this variable in all references to the output file. :Arithmetic Skeletons. Arithmetic skeletons have the form (#x,s) where x may be a string of one or more of the arithmetic functions and s is the argument to which the functions given by x are applied. In the listing of arithmetic functions which follows, the term "constant" means a string of ASCII characters representing an integer when the program is run with rec80 or rec86, or an integer, long integer, single precision real or double precision real when the program is run with rec80f or rec86f. CNVRT inherits REC8xF's default of promoting smaller-sized arguments to the size and type of the larger argument in operations involving arguments of different sizes. f evaluates a formula. Its argument must be an arithmetic expression in which the operands are constants. Parentheses are allowed (and must be balanced if present); the operators recognized are ** or ^ for raising to a power, * for product / for division, % for remainder, + for addition or unary plus and - for subtraction or unary minus. - The usual rules for operator precedence and association are followed: ** or ^ precede *, / and %, all of which precede + and -. Unary +'s are removed and unary -'s are replaced by 0-. *, /, %, + and - associate from left to right and ** or ^ associate from right to left. Thus, (#f,2^3^2) yields 512, (#f,(QUO\(2^3)^2\)) yields 64, (#f,2/4*6) gives 0 and (#f,6*2/4) gives 3. Exponents MUST be of integer type; a floating point exponent causes an "Expt err" diagnostic and a return to CP/M. + Takes an argument of the form a+b, where a and b are constants and returns their sum. The argument is unchanged if it doesn't have the required form. - Takes an argument of the form a-b, where a and b are constants and returns the indicated difference. No change is made in the argument if its form isn't a-b. * Returns the product if the argument has the form a*b, with a and b constant; otherwise the original argument remains. - / Returns the quotient given an argument a/b in which a and b are constants; no change is effected if the argument does not have the specified form. ^ Given an argument of the form a^b, where a is any constant and b is an integer, returns a raised to the power b. The argument is returned intact if it does not have the indicated form % Returns the remainder of the division a/b if the argument has the form a%b; otherwise the argument is left unchanged. If either operand is a floating point number, the result returned will be a-(b*int(a/b)), where int(x) is the integer part of x. [e.g., int(3.5)=3; int(-4.8)=-4.] | If its argument has the form a|b, where a and b are integer constants, it returns the greatest common divisor of the pair. No change occurs if the argument lacks the prescribed form and no check is made to ensure that a and b are integers; results are unpredictable in the latter case. | may not be used as an operand in arithmetic expressions to be evaluated by f. - p Accepts a single constant as argument and returns that constant plus one, in a string of the same numeric type as the original argument. It will not alter its argument if it isn't a constant. m If its argument is a constant, it returns that constant minus one, in a string of the same type; otherwise it leaves its argument unchanged. = > These three skeletons take arguments in either of two < forms: a single number or two numbers separated by a comma. In the case of a single number, say a, they return the letter t if a=0, a>0 or a<0, respectively, and the letter f otherwise. In the two-argument case of the form "a,b", t is returned if a=b, a>b or a-1) yields 4 consecutive bytes whose hex values are 0D, 0A, FF and FF; (&D,ab) yields 6 zero bytes: a and b delimit 3 null strings. - H Converts a string of one or more hexadecimal ASCII numbers into binary (modulo 2**16), a pair of bytes for each number. For instance, (&H,F) yields two bytes whose values are, in hex, 0F and 00; (&H,ABCDEf0123) produces 4 bytes whose values expressed in hex are DE, BC, 23 and 01, in that order. The inversion of high and low order bytes is due to the Intel convention for binary data storage. Notice also that lowercase f is not considered a hex digit. d Converts a string by pairs of bytes into ASCII decimal strings separated by commas; if the argument has an odd number of bytes the rightmost byte is converted assuming a zero high order byte. Examples: (#d,(^MJZ)) produces the string 2573,26 (#Hd,FFFE) produces the string -2 h Converts a string by pairs of bytes into strings of 4 ASCII hexadecimal digits separated by commas; the rightmost byte of a string of odd length gets converted to two hex digits. Examples: (#h,(^ABMJZ)) produces the string 0201,0A0D,1A (#Dh,32767) produces the string 7FFF - u Shifts all lowercase letters (a-z) in its argument to uppercase, e.g., (&u,Hello) yields HELLO. l Shifts all uppercase letters (A-Z) in its argument to lowercase, e.g., (&u,What IS it?) results in what is it? a Turns off the sign bit of each byte in its argument. For instance (&Dah,-1) results in the string 7F7F. s Turns on the sign bit of each byte in its argument. For instance (&sh,(^MJZ)) gives 8A8D,9A p Substitutes a period for each byte in its argument whose value is not a printable ASCII character. Example: (&p,abc(^MJ)de) results in abc..de n Converts each byte in its argument into two ASCII hexadecimal digits. For example (&n,ABCDEF) produces 414243444546. b Inverts the effect of n: converts pairs of ASCII hex digits into bytes of the corresponding binary value. Results are unpredictable for odd-numbered arguments or non-hex digits. - i Converts a string of bytes into 3-digit ASCII octal numbers (one for each byte) separated by commas; a null argument produces 000. Example: (&i,Zz) produces 132,172 I Converts a string of ASCII octal numbers separated by commas to binary, a byte for each ASCII number. For example, (&I,116<,>117<,>77) yields the 3-byte ASCII string NO? 8 Converts a string of bytes into 8-bit ASCII binary numbers (one for each byte) separated by commas; an isolated null string produces 00000000. Example: (&8,Zz) produces 01011010,01111010 B Converts a string of ASCII binary numbers separated by commas to binary, a byte to each ASCII number; a single null string produces a single zero byte. For example, (&HB,01011010<,>01111010) yields 7A5A. = Yields the letter f if its argument is the null string or at least one of its bytes is non-null; leaves the letter t if all of the argument's bytes are binary 0. - > Yields the letter f if its argument is the null string or if the sign bit of its rightmost byte is on; t if this byte's sign bit is off. < Yields the letter f if its argument is the null string or if the sign bit of the rightmost byte is off; the letter t is returned if the rightmost byte's sign bit is on. ! Returns the length of its argument as an ASCII decimal number. For example, (&!,What<,> me worry?) returns 15. # Returns the hash function of its argument as an ASCII decimal number, always between 0 and 12. The hash function is defined here as the remainder modulo 13 of the exclusive or of all the bytes in the argument. The entire section of the CNVRT library dealing with chracter arithmetic may be excluded from the compiled program file by the presence of CHR in the [Exclude ...] comment at the beginning of the source program file. Selected portions of the character arithmetic section may be excluded by other three-letter keywords listed in this Help file under "Exclude feature". :Overlays. Overlays are an extremely useful feature which allow the running of programs whose overall size is much larger than REC's compilation area. Overlays may be used when a program can be divided into three or more segments such that two or more of them are not needed simultaneously in memory. For instance, suppose program A calls subroutines B and C, but neither B calls C nor C calls B. Then program A could constitute a main overlay which loads B or C when either of them is required. Thus B and C share the same memory area and the memory requirements for the entire program are smaller by the length of the smaller of B and C than the requirements for the non-overlaid A-B-C combination. An overlay may load other overlays, and this way a very large program may be organized in a tree-like structure of overlays. Since each overlay is a REC program compiled when loaded, no relocatability issue arises so that a given overlay may be loaded at different levels of an overlay tree. For the purpose of discussion, in what follows the main overlay will be called "driver" and the rest of the overlays will be called "secondaries". - A driver is compiled with either CNVSM or CNVRT and should include in its library all functions needed by it and its secondaries. Secondaries may be compiled by CNVSM or CNVRT, in which case they MUST have a directive [Exclude LIB] before their first procedure. Alternatively, CCNVSM and CCNVRT may be used to compile secondaries, in which case no "Exclude" is necessary, since CCNVRT and CCNVSM are counterparts of CNVRT and CNVSM which have no provisions for library insertion; additionally, CCNVRT and CCNVSM may be invoked as overlays by any CNVRT program. Overlays may be read from disk files or memory buffers; the latter case essentially extends the compile area into REC's pushdown list, from which space is procured for memory buffers. Storing overlays in memory buffers also has the advantage that overlay loading from them is substantially faster than loading from a disk file. The following skeleton fragment shows how an overlay in a file called F77SY.REC is read from disk and written into a MEM: pseudofile whose size is computed from the length of the original file itself: >>(IF,(0),(%R,F77SY.REC,<-->(^Z)),<0>,<< >>(%C,F77SY.REC)(,(%Ow,MEM:sy,(&!,<0>)))(%W,MEM:sy,<0>))<< Closing F77SY.REC before opening MEM:sy saves memory by releasing table and buffer space associated with F77SY.REC; the length of MEM:sy is determined by the length of the contents of F77SY.REC; <0> is bound to these contents. - An overlay is loaded and executed by the skeleton (%V,name,arg) where 'name' is the name of the disk file or memory buffer containing the overlay and 'arg' is a skeleton whose value is the argument received by the overlay in the workspace; 'arg' is optional and when omitted, the preceding comma may also be omitted. The last overlay loaded may be reexecuted any number of times without recompiling it (as long as no other overlay is loaded) by calling it with the skeleton ( ,arg) in which a single blank space appears between the left parenthesis and the comma, and 'arg' is the argument to be passed to the overlay; the skeleton ( ) (with a single blank) may be used if no argument is to be passed. Finally, if a program doesn't need the overlay feature, the library code for %V may be excluded by writing OVR in the Exclude directive. :"Exclude" feature Exclusion was already discussed in Section F of CNVRT.HLP, so this section is only an update on the options available, which are the following: DSK Disk system (%Z, %Lr and %Lw) BIO Direct access to BIOS (%B) DIR Directory functions (%S, %A, %D, %N) BOO Return to CP/M (%M) CTR Counter pseudodevice MEM Memory buffer pseudodevice NUL NUL: pseudodevice CLS Close by name (%C) PVR "Print variable" debugging aid pattern PRN Printer skeletons (%P, %p) OVR Overlay feature (%V) INT All of the arithmetic skeletons. Selected portions of this section of the library may be excluded with the following: Keyword Excludes FOR #f FLT Floating point in #f PWR ** or ^ in #f and #^ - Keyword Excludes MOD % in #f and #% GCD #| TWO #+, #-, #*, #/ #|, #%, #^, #=, #> and #< NCM #=, #> and #< IDC #p and #m NCV #l and #s NDH #D, #d, #H and #h CHR All of the character arithmetic skeletons. Selected portions of this section may be excluded as follows: Keyword Excludes CDH &D, &d, &H and &h CSE &u and &l SBT &a and &s DOT &p NIB &n and &b 233 &i and &I BIT &8 and &B BCM &=, &< and &> LEN &! HSH &# - All of the above options may be excluded by the directive [Exclude ALL]; the entire library must be excluded when compiling secondary overlays, this is accomplished by [Exclude LIB]. :Miscellaneous features. - PDL space is recovered when files are closed in the order opposite to that used when opening them. This allows a CNVRT program to process an indefinite number of files without leaving a trail of unused FCB's and buffers on REC's pushdown list. - 'Dir full' and 'Disk full' diagnostics are issued if the respective conditions occur during the compilation of a CNVRT program. - All four compilers (CNVRT, CNVSM, CCNVRT and CCNVSM) may be loaded and executed by the overlay skeleton %V; the second argument of %V must be the name of a disk file containing the CNVRT program whose compilation is desired, e.g., (%V,CCNVSM.REC,FOO) loads CCNVSM, compiles the program in file FOO.CNV, produces the compiled program file FOO.REC and returns to the program invoking %V; since CCNVSM inserts no library, FOO.REC may be then used as an overlay by the same program. :[CNVADV.HLP] [Gerardo Cisneros, 13.8.84] [end]