Introduction.
Patterns.
Subroutine Groups.
Conditional Skeletons.
Iterative Skeletons.
The "Same" Skeleton <=>.
The (REC/.../) pattern and skeleton.
Memory buffer operations.
Disk system and return to CP/M functions.
Arithmetic Skeletons.
Character "Arithmetic".
Overlays.
Loading of .COM binary files.
Priority Queues (Heaps).
Error messages.
:Introduction.

This Help file describes advanced CNVRT features as well as additions and 
changes made to the compiler after CNVPRG.HLP was prepared.  Among the most
noteworthy changes the following may be mentioned:

	- Full functionality for pattern definitions and the Boolean
	  combinations OR and AND.

	- Generalization of skeletons if, nf, while and until.

	- Generalization of pattern <[n]>.

	- Inclusion of evaluation of general arithmetic expressions whose 
	  operands are constants (including floating point).

	- Acceptance of any functional skeleton as a pattern.

:Patterns

References to defined patterns and the Boolean OR now perform as expected, so
that programs such as the following give results consistent with the formal
definition of Convert:

	((	((OR,[<:e:>],<(><:e:><)>,[<0>],<(><0><)>)) e
	)()(0)(	
		((^Z),);
		(<: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 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 on compiled programs, of having defined patterns check the patterns
that follow references to them (in the example, that "e" take into account <0>
in the concatenation <:e:><0>) is an object file requiring up to about 20%
more space, so that CONVERT.REC allows selection of the type of treatment
desired in the compilation of defined pattern references by a flag appended
to the source file name in the command line tail; if no flag appears or is /s
or /S, the code produced is simpler but less general.  A slash followed by
anything other than an s or S indicates full treatment should be given.  For
example, if the above example is placed in a file TEST.CNV, when compiling it
with the command line

		REC80 CONVERT TEST/L

the program obtained would recognize the string [([ab])][ab], whereas the line

		REC80 CONVERT TEST

would result in a program in which <:e:><0> would not match that string
(although it would match some simpler strings such as [([ab])]ab).

The default is the shorter compilation because most applications to date have
only used simple pattern definitions not requiring the general treatment.
-
The other question now resolved is that of AND.  Consider a concatenation
(AND,p1,...,pn)p, in which it could happen that there is more than one way in
which the concatenation of p1 and p may match the text and that it may not be
necessarily the first alternative (the one that would have p1 matching the
shortest possible text) that for which p2, ..., pn match the same text as p1.
In this case, one requires that if pi fails (i>1), a different way to match p1
and p to the text be sought.  This is necessary even if p is the null pattern,
for consider the following patterns:

		(AND,<0>;,<1>ab;)

		(and,<0>;,<1>ab;)

The first one matches any text containing the substring "ab;"; the second
matches only if no semicolon precedes the first occurrence of "ab;" because <0>
will match the shortest substring left of a semicolon; for instance, the first
pattern maches x;y;ab;z, whereas the second does not.  Notice however that
(and,<1>ab;,<0>;) has the same effect as the AND shown above, illustrating the
convenience of always analyzing the possibility of expressing the desired
pattern in terms of (and,...) and (or,...), which produce less code and are
less time-consuming.

-
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, the second and fourth patterns will fail, while the third 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. If no external access is desired to d, i, I or r, R could be
the main program (removing the last line and placing the right brace before
the R); in this case the only valid external reference would be <:R:>.
-
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.  As with patterns,
groups may be defined in which the main program is not (@), in which case
outside access would only be allowed to the main program of the group.

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 mutually and recursively, from the main
program (A) and from any subroutine called from within this same 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),s0{,pj,sjt,sj}[,pF,sFt])
	(if,s0{,pj,sjt,sj}[,pF,sFt])
	(NF,(v),s0{,pj,sjt,sj}[,pF,sFt])
	(nf,s0{,pj,sjt,sj}[,pF,sFt])

where v is list of variables (zero or more integers between 0 and 30 with one
space between each pair of variables), the s's are skeletons and the p's are
patterns; braces indicate 0 or more instances of the enclosed list and
brackets indicate 0 or 1 instances of their contents. In IF and NF, the (v)
list creates new instances of the listed variables after s0 has been evaluated;
these instances persist during the execution of the IF or NF and disappear
upon termination.  Otherwise, IF and NF execute like if and nf, respectively.

	The next panels describe the operation of if and nf; we repeat 
the form of the corresponding skeleton for ease of reference.

-
	(if,s0{,pj,sjt,sj}[,pF,sFt])

Skeleton s0 is evaluated and matched to the first pattern, p1.  If they match,
s1t is evaluated and its value becomes the value of the entire skeleton; if
the match fails s1 is evaluated and matched to p2.  This continues until a
match obtains between some sk and p(k+1), in which case the result is s(k+1)t,
or there are no more comparisons to be made, in which case the last skeleton
evaluated for a comparison is left as the result.  In particular, if pF and
sFt appear and pF does not match the last sk, the value of if is that of sk.
The conditional skeleton

	(if,(%R),(^Z),<=>(%t,End of file encountered),(%T,<=>))

reads 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 triple [,p,st,s] allows constructs of the "elseif"
type within a single (if,...).


-
	(nf,s0{,pj,sjt,sj}[,pF,sFt])

NF and nf are the negative forms of IF and if, repectively; that is, if s0
does NOT match p1, s1t is substituted, else if s1 does not match p2, s2t is
substituted, etc.  If each sk matches p(k+1), (k=0,...,n and pF=p(n+1)), sn
is left as the result (This includes the case in which pF and sFt are present.)

Alternatively, "nf" may be read as "unless":  Unless s0 matches p1, s1t is 
evaluated and delivered as the result, else unless s1 matches p2, s2t is
given as the result, etc.

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 skeleton follows sFt.

: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{,pk,sk,skr}[,sf])
	(while,sI{,pk,sk,skr}[,sf])
	(UNTIL,(v),sI{,pk,sk,skr}[,sf])
	(until,sI{,pk,sk,skr}[,sf])

where v is list of variables (zero or more integers between 0 and 30 with one
space between each pair of variables), each s represents a skeleton and each p
represents a pattern; braces denote 0 or more instances of their contents and
brackets indicate 0 or 1 instance of the enclosed item.  In WHILE and UNTIL,
the list v generates new instances of the indicated variables after the initial
skeleton sI is evaluated; these instances persist during the execution of the
iterative skeleton and disappear upon termination. Otherwise, WHILE and UNTIL
perform as while and until, respectively.  

	The next panels describe the operation of while and until; we repeat 
the form of the skeleton for ease of reference.
-
	(while,sI{,pk,sk,skr}[,sf])

1.	The initial skeleton sI is evaluated.

2.	If the first pk matches the text, sk is evaluated and put aside and
a new text to match with pk is given by the repetition skeleton skr.  This 
step is repeated until pk no longer matches the text presented to it.  

3.	The last text skr from step 2 (or sI if pk did not match on the very
first try) is used as initial text to match with the next pattern (if any) and
a similar iteration as that of step 2 occurs on the next triple pk,sk,skr.

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.  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 each sk
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 null string or a sector
containing a ^Z) is given to the next triple, in which the pattern is <0>(^Z);
if there is a ^Z, <0> will match the text in the sector up to but not including
the ^Z.  A null string is given as the repeat text (the skeleton skr in the
second triple), which will not match <0>(^Z), so 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,13,(,(%Ow,MEM:<=>)),(#p,<=>),)

This skeleton creates 13 memory buffers, named MEM:0 through MEM:12.  After
each comparison, the value of <=> is the text used in the comparison; since
#p increments by one its argument if it is a number, the value of <=> will
succesively be 0, 1, 2,... up to 12; when #p increments 12 to 13 the pattern
matches and the iteration ends.

The skeleton which would close these buffers and release the memory associated
with them would be the following:

	(until,12,-1,(%C,MEM:<=>),(#m,<=>),)

#m decrements its argument by one; 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 final value of the skeletons in both examples is the null string.

:The "Same" Skeleton <=>.

The skeleton <=> may be used wherever a pattern match has taken place, and in
skeletons appearing in the list of skeleton definitions.  It may not appear
in skeletons used as patterns embedded in pattern definitions.  In particular,
<=> may appear anywhere in the skeleton part of a rule and in any skeleton
within a conditional or iterative skeleton.  Its value is the entirety of the
text used in the latest comparison, except when appearing within a skeleton
definition, in which case its value is the text passed as argument to such a
skeleton.

For example, if the skeleton definition list contains the definition

			((%W,<8>.<9>,<=>(^MJ))) W

and a skeleton (W,abc) is executed at some point, its effect will be to write
five bytes (a, b, c, CR and LF) into the file whose name and extension are
given by variables 8 and 9.

:The (REC/.../) pattern and skeleton.

The (REC/.../) pattern and skeleton allows REC code to be inserted directly
at the point where it appears.  The inserted code is that delimited by "/";
any character may be used as a delimiter as long as it is not contained in
the code to be inserted.  As a pattern, it can make certain searches faster
than if they are left to the normal Convert mechanisms; as a skeleton it can
help to produce more compact code.

The use of this feature requires a thorough knowledge of REC and of the
translation from Convert to REC.  Examples of its use may be found in
RECONVERT.CNV, a Convert compiler for Convert.

:Memory buffer operations.

Open operations on MEM:-type pseudo files may have an additional argument
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 opening, 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 transfer to the workspace
that portion of the text starting at the read pointer and matching the pattern
(implicit or explicit) associated with %R.  If the pattern does not match the
text between the pointers, this whole text is returned with a ^Z appended to
it (which is deleted if %R contains an explicit pattern) and the read pointer
moves up to the write pointer.  When there is a match, the read pointer
advances to the byte following the portion of text which matched.
-
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 or the null string is returned, depending
on whether the implicit pattern or an explicit one is used, respectively.  In
any case, the final text returned by %R from a memory buffer will depend on the
presence or absence of the optional skeletons which %R may include.

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 function (,...) which
erases its argument from the workspace.

:Disk system 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 specified by the first letter of skeleton
		x; if x is omitted or is null, A is assumed.

	(%M)	returns to CP/M after closing all files.

: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. Convert 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.  If the argument is
		not an expression it is left unchanged.
-
		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 is truncated and causes the message
		"Xpterr" to be displayed.
		
	+	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 operator 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<b, respectively, and f if the
		relation doesn't hold.  In this case, if a and b are two-byte
		integers they are compared as unsigned operands, since 
		two-byte integers are more often used in address 
		calculations.  Arguments not having either of the allowed
		forms are left unchanged.

-
	l	Requires a single constant as argument; it converts it to
		a string of the following larger numeric type.  For instance,
		(#l,-1) yields 065535, (#l,010000000) yields 1.E7 and
		(#l,3.14159) gives 3.14159D0.  Double precision constants and
		non-numeric arguments remain unchanged, a null string as
		argument returns the digit 0.

	s	Converts a single constant argument to next smaller numeric
		type before rendering it back to ASCII.  Thus
		(#s,3.141592653589D0) returns 3.14159265, (#s,-45.98) returns
		-045, (#s,0100000) leaves 34464 (because of truncation modulo
		2**16) and (#s,2000) leaves 208 (because of truncation modulo
		256).  Non-numeric arguments remain unchanged; a null string
		returns the digit 0.

	D	Leaves the binary form of a numeric constant in its place;
		this will take the form of 2, 4, 5 or 8 bytes arranged in
		Intel form (least significant byte first); the lengths
		correspond to short integers, long integers, single precision
		reals and double precision reals, respectively.  D is more
		often used together with h to produce the ASCII hexadecimal
		representation of a number.  
-
		No change takes place if the argument is non-numeric. 
		Examples:	(#Dh,1.5) 	produces 	3FC0000000
				(#Dh,-1) 	produces 	FFFF
				(#Dh,01000000) 	produces 	000F4240

	H	Leaves the binary form of a string of ASCII hexadecimal 
		digits (0-9, A-F).  Given a string of n bytes, it produces
		a string of flr((n+1)/2) bytes, where flr(x) is the greatest
		integer not exceeding x.  H is often used together with d
		to convert from ASCII hexadecimal to ASCII decimal.  No
		change is effected if the argument contains characters other
		than hex digits.  Examples:
		(#H,414243)	 gives	CBA 	(when interpreted as ASCII)
		(#Hd,3FC0000000) gives	1.5
		(#Hd,F)		 gives  15

	d	Assumes its argument is the binary representation of a number
		and converts it to an ASCII decimal string.  If the argument 
		length is not 0, 1, 2, 4, 5 or 8 no change takes place.  
		Examples: (#d,(^MJ)) yields 2573 (10*256+13, due to Intel 
		ordering of bytes in binary operands being assumed); 
		(#Hd,FFFE) yields 65534.
-
	h	Assumes its argument to be binary and converts it to a string
		of ASCII hex.  An n-byte argument produces a 2n-byte result.
		Examples: (#Dh,1.) produces 3F80000000;	(#h,jkl) produces 
		6C6B6A (because Intel ordering of binary operands is assumed)

As mentioned near the beginning of this section, in a skeleton of the form
(#x,s), x may be a string.  When x consists of more than one character, each
of the represented functions is applied to the argument from left to right;
thus in (#Hd,FFFF), H is applied first to FFFF and d is then applied to the
result left by H (the two byte binary representation of 65535).

As mentioned in CNVRT.HLP, a program using function #f and requiring handling
of floating point constnats must have the pair #. in an [Include ..] comment;
furthermore, if functions #^ and #% are not invoked explicitly but operators
** or ^ and % are to appear in formulas for #f, the pairs #^ and #% must be
present in the "Include".  [Include #.#^#%] would serve in a program which
only uses #f explicitly but is intended for computation of formulas involving
floating point numbers and exponentiation and remainder operations.

:Character "Arithmetic".

Character arithmetic skeletons have the form

			(&x,s)

where x may be a string of one or more of the character arithmetic functions
and s is the argument to which the functions given by x are applied.  When
x consists of two or more characters, the function represented by each 
character is applied in turn from left to right, the first one to the 
original argument and the rest to the result left by the preceding function
For instance, (&D!,1.5) applies D to the string 1.5 and ! to the resulting
string.

Functions available for character arithmetic are the following:

	D	Converts a string of one or more decimal integer ASCII
		numbers optionally preceded by minus signs and separated by
		commas or other nondecimal characters into binary, a pair
		of bytes for each integer. Examples: (&D,2573<,>-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 (i.e., SP to ~)
		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,
			(&Bh,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.


: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 root program 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 root overlay
will be called "driver" and the rest of the overlays will be called
"segments".

-
The driver is the only program which should contain the initializing code
inserted by the compiler; all segments must be compiled with an [Exclude LIB]
comment in their source files appearing before the first subroutine or program,
preventing thus insertion of the initializing code.

Automatic inclusion of library routines at runtime requires that the root
inform the compiler which routines must be included in addition to those
determined automatically by the compiler during compilation of the root.  This
is accomplished by an [Include ....] comment near the beginning of the root's
source file, where "...." is replaced by the strings inserted by the compiler
(after enclosing them in square brackets) at the end of each segment's object
file (which will always happen if the source file contains [Exclude LIB]).

For example, the quantum chemistry program HAMEL is made up of 9 programs;
the root is HAMELD and the segments are HAMELx, where x is X, F, G1, G2, G3,
G4, G5 and M.  Due to the [Exclude LIB] in the 8 segments, the compiler
produced the following strings, inserted at the end of each file HAMELx.REC:
[T # #*#|#/W 64O OrOwE ], [T W 64O OrOwE ], [W t T 64O OrOw E ],
[T W 64O OrOwE ], [T W 64O OrOwE ], [t T W 64O OrOwE ],
[# #*#|#/T W 64O OrOwE ] and [T W 64# #*#+#-#|#/O OrOwE ]; with these strings
a comment [Include T t W 64# #+#-#*#/#|O OrOwE ] was formed for insertion in
the program file of the root, HAMELD.CNV.
-
The "Include" comment in the example was built gathering all distinct pairs of
characters appearing in the eight final strings generated for the segments;
notice spaces are important because the automatic inclusion mechanism examines
the "Include" string by pairs of characters.

Overlays may be read from disk files or memory buffers; the latter case
essentially extends the compilation 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 FSY.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),(until,(%R,FSY.REC),(^Z),<=>,(%R,FSY.REC),),<0>,<<
		>>(%C,FSY.REC)(,(%Ow,MEM:sy,(&!,<0>)))(%W,MEM:sy,<0>))

Closing FSY.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 (whose extension is assumed to be
.REC if not explicitly given) 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 and the overlay will receive an empty workspace.

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 (i.e., if the null string is to be passed).

The Convert compiler may be loaded as a segment: (%V,CONVERT,arg) compiles the
program contained in the disk file given by 'arg', generating the corresponding
REC file.  If X.CNV, Y.CNV and Z.CNV are to be compiled, the concatenation
(%V,CONVERT,X)( ,Y)( ,Z) will load CONVERT.REC once and compile the three
programs.  The default extension for 'arg' in this case is .CNV.

:Loading of .COM binary files.

Three skeletons permit loading and executing machine code files:

		(%Xl,f)
		(%Xx,f,c)
		(%Xv,f,c)

%Xl loads the file whose name is given by the skeleton f (an extension .COM
is assumed if none is given), using a file of the same name and extension .BIM
(containing a bit map) to relocate the loaded file, which is assumed to be
loadable without relocation at 100H.  The program contained in "f" is loaded
starting at the next available address in REC's compilation area; this address
is updated if the loaded program fits into the available space.  If the
program does not fit or it or its bit map file do not exist, (%Xl,f) evaluates
to the string 'Not Found'; otherwise its value is the null string.

%Xx executes a program previously loaded by %Xl; a program loaded by %Xl stays
resident for the duration of the run, so that %Xx may be used to execute it as
many times as desired.  


-
The argument c in this skeleton is a skeleton whose value is interpreted as
a command line tail from which up to two file names are parsed and placed at
locations 5CH and 6CH; the length of the string resulting from c (or 127,
whichever is less) is stored in location 80H and the string itself (up to the
first 127 characters) is placed in the data area starting at 81H.  If the 
program was not loaded, %Xx returns the string 'Not Found' to the calling
program; otherwise (and assuming program "f" returns to the calling program)
it returns the string starting at 81H and whose length is stored at 80H, as
long as it does not exceed 127 (if it does, the null string is returned).

%Xv loads and executes a file in the manner of %Xl and %Xx, but restores the
compilation area pointer upon return from execution of the loaded program, so
that it executes the named program as an overlay, freeing the compilation area
space after execution.  It returns the string 'Not Found' if either the file
given by f or its .BIM bit map cannot be found or if the program will not fit
into the available space.  %Xv and %Xl must not be used on the same file f in
a given Convert program, that is, a program to be loaded and executed by the
%X skeletons must be either a resident program or an overlay, but not both,
during a given run of a Convert program using it.



-
The bit map is a file containing one byte for each eight bytes of the program
file.  The correspondence starts at the most significant bit; the first byte
of the BIM file corresponds to the first eight bytes of the COM file.  When a
1 bit is present in the bit map, it indicates that the corresponding byte in
the COM file is the higher byte of an address; relocation is effected by
adjusting this address.

To obtain the BIM file, the corresponding program must have been assembled or
compiled with two origins differing by an integer multiple of 0100H (256); the
differences between the resulting files is exploited by GENBIM (program 165.13
in the SIG/M collection) to produce the bit map.

:Priority Queues (Heaps).

The following skeletons handle a MEM: pseudofile as a priority queue (or heap)
of two-byte unsigned integers:

		(%Hi,m,d)		(%Hs,m)
		(%Hr,m)			(%Hh,m)

In all four skeletons, m is a skeleton which must evaluate to a MEM: 
pseudofile name; d in skeleton %Hi must be evaluate to a four byte ASCII 
string representing a hexadecimal number (lower case a-f are not recognized).

%Hi inserts the two-byte binary representation of the ASCII hex number d 
into the pseudofile m, sifting the file to maintain the heap condition.  If
the pseudofile is viewed as an array P with N entries, maintaining the heap
condition means requiring that P(i)>P(2*i) and P(i)>P(2*i+1) for i between
1 and floor(N/2).  After an insertion, the pseudofile read pointer is set to
beginning of the buffer, so that a subsequent read from m will start from the
top of the heap.  %Hi returns the null string.



-
%Hr reads the next two-byte value from m, converting it to a four-byte ASCII
string (hex).  This skeleton is essentially equivalent to (&h,(%R,m,<[2]>)),
and is included for convenience.

%Hs sorts the contents of m, which are assumed to satisfy the heap condition.
It returns the null string and does not affect the value of the pseudofile
read and write pointers.

%Hh sorts the pseudofile m by the heapsort method assuming it to contain
two-byte unsigned values.  The file need not satisfy the heap condition
initially; a file suitable for sorting by %Hh may be produced by writing
values with the skeleton (%W,m,(&H,h)), where h is a four-byte ASCII
hexadecimal string, or with (%W,m,(&D,d)) where d is an ASCII decimal integer
between 0 and 65535.

:Error messages.

CONVERT.REC displays the following messages upon detecting the corresponding
errors:

	Unexpected EOF		End of file encountered in the middle of a
				compilation, for instance, if there are
				subroutines but no main program.

	Unbal {

	Excess }

	WS ovf			Workspace overflow.

	Unbal [

	Expected (, [, {	Spurious characters in the source file.

	Expected )

	Expected ","		Syntax violation in LAM, IF, WHILE, etc.
-
	Ill patt		Illegal pattern.

	Ill skel		Illegal skeleton.

	Ill rule		Rule lacking the comma separating pattern
				from skeleton.

	Ill sep			Colon/semicolon missing after a rule.

	Ill var			Variable number not between 0 and 30.

	Ill var list		Badly formed variable list.

	Ill <=>			Illegal use of skeleton <=>.

	Dir full		Directory full reported by the operating
				system when attempting to write.

	Disk full		Disk full reported by the operating system
				when attempting to write.

	Not Found		Nonexistent source file.
-
	No file given		No source file name given to the compiler.

:[CNVADV.HLP]
[Gerardo Cisneros, 13.8.84]
[Rev.: G. Cisneros, 28.1.86]
[end]
