home *** CD-ROM | disk | FTP | other *** search
/ Turbo Toolbox / Turbo_Toolbox.iso / sharew / exoten / rec / rec4.hlp < prev    next >
Encoding:
Text File  |  1990-10-29  |  23.6 KB  |  523 lines

  1. Ch. 4.  The Workspace, Part I (I, Q, F, D, J, Z)
  2. Ch. 4.  The Workspace, Part II (E, U, V, M, j, z, A, B, q, Y)
  3. Ch. 4.  The Workspace, Part III (a, b, e, f, w, <, >)
  4. :            Chapter 4. The Workspace
  5.  
  6. The workspace (WS) is a linear array of bytes of up to 64K, otherwise limited 
  7. by the available memory, with which five pointers are associated: p0, p1, p2, 
  8. p3 and p4.  Given any pair of pointers p[j] and p[k], with j<k, pointer p[j] 
  9. is inclusive and pointer p[k] is exclusive, so that null strings may be 
  10. validly delimited in the workspace: the string delimited by pointers p[j] and 
  11. p[k] starts at p[j] and its length is p[k]-p[j].  The absolute limits of the 
  12. WS are defined by p0 (the lower limit) and p4 (the upper limit); the last 
  13. address of the WS is p4-1 and the workspace length is p4-p0.
  14.  
  15.     The workspace can be used to carry out insertions, searches and 
  16. modifications of character strings.  The text contained by the WS begins at 
  17. p0 and ends at p3-1, so that its total length is p3-p0; clearly p3 may not 
  18. exceed p4.  Pointers p1 and p2 are altered by the text insertion, search and 
  19. modification operations; p1 and p2 always point to the lower and upper ends, 
  20. respectively, of some substring of the text delimited by p0 and p3.
  21.  
  22.     Thus, the five workspace pointers always satisfy the following
  23. relationship:
  24.  
  25.         p0  ≤  p1  ≤  p2  ≤  p3  ≤  p4
  26.  
  27.     In the figure we show a representation of the workspace and its 
  28. pointers; tick marks are intended to denote byte boundaries.  The workspace 
  29. shown contains a 7-byte string (delimited by p0 and p3); pointers p1 and p2 
  30. delimit the single character c.  The marker at p4 is required by the 
  31. operator >, which we describe later on in this chapter.
  32.  
  33.     ┌─┬─┬─┬─┬─┬──┬──┬────────────────────────────────────────┬─┐
  34.     │z a b c d CR LF│                     │▒│
  35.     └─┴─┴─┴─┴─┴──┴──┴────────────────────────────────────────┴─┘
  36.       p0 ┘  p1 ┘ └ p2     └ p3                      └ p4
  37.  
  38.     The initial contents of the workspace depend on the operating system.
  39. If the command line has the form 
  40.  
  41.             recxx X
  42.  
  43. where xx is 80 or 86 depending on the processor used and X is absent or is 
  44. the name of a file containing a REC program to be compiled and executed, the 
  45. workspace will be initially empty in CP/M, while under MS-DOS it will 
  46. contain a CR, a LF, and a copy of the environment strings each terminated by 
  47. the NUL character (a byte whose value is 0).  Each environment string has the 
  48. form VAR=value.  In both cases the workspace pointers satisfy the relationship
  49. p0 = p1 = p2 ≤ p3 < p4.
  50.  
  51. If the command line has the form
  52.  
  53.             recxx Y Z
  54.  
  55. where xx is 80 or 86, Y is the name of a file and Z is a string consisting of 
  56. at least one nonblank character, the initial contents of the workspace under 
  57. CP/M will be the string Z (i.e., the command line tail); while under MS-DOS 
  58. it will be the string Z followed by a CR, a LF and the environment strings as 
  59. above, with the following relationship among the pointers: p0=p1=p2<p3<p4. 
  60.  
  61.     In the MC68000 version of REC, the initial workspace contents are 
  62. about the same as in REC86; the main differences are that argument strings 
  63. are terminated with NULs and the arguments are separated from the environment 
  64. strings by a single LF.
  65.  
  66.     Several of the operators and predicates which perform their main 
  67. function on the workspace require one or more arguments from the PDL.  All of 
  68. them lift from it the arguments they require; some leave a result on the PDL.
  69.  
  70.     Next we describe the first group of predicates and operators which 
  71. act on the workspace.
  72.  
  73. Operator/Predicate        Function performed
  74.  
  75.     I    Operator. Inserts in the workspace the top PDL argument, if 
  76.         it will fit (i.e., if its length is less than p4-p3).  The 
  77.         string is inserted starting at pointer p2, and the text 
  78.         originally delimited by p2 and p3 is shifted towards p4 to 
  79.         make space for the insertion.  Pointers p1 and p2 are set to 
  80.         delimit the inserted text.  If the text won't fit, the error 
  81.         message "WS ovfl" is issued and program execution is 
  82.         terminated.
  83.  
  84.     Q    Operator.  Copies the text delimited by p1 and p2 to the PDL. 
  85.         Both the workspace and its pointers remain unaltered.
  86.  
  87.     F    Predicate, searches for text.  The text in the workspace is 
  88.         examined from left to right beginning at p1 to see if the 
  89.         object of comparison on the PDL can be found.  If so, its 
  90.         replica on the workspace is bracketed by p1 and p2 and F 
  91.         becomes true; otherwise p1 and p2 retain thir original values 
  92.         and F becomes false.  In both cases the top argument is 
  93.         lifted from the PDL.
  94.  
  95.  
  96.     D    Operator which erases from the AT the text delimited by p1 
  97.         and p2.  The text delimited by p2 and p3 is shifted towards 
  98.         p1 to close the gap generated by the deletion; when the 
  99.         operation ends p2=p1 holds.
  100.  
  101.     J    Operator.  Moves p1 to the beginning of the text, that is to 
  102.         say, assigns to p1 the value of p0.
  103.  
  104.     Z    Operator.  Moves p1 to the end of the text, i.e., assigns the 
  105.         value of p3 to p2.
  106.  
  107.     With these operators it becomes possible to write in REC and execute 
  108. Markov Algorithms, which involve a series of modifications to an initially 
  109. given text.  The modifications can be described by a series of substitution 
  110. rules of the form
  111.  
  112.             a1 => b1
  113.             a2 => b2 
  114.             ...
  115.  
  116. where a[i] and b[i] are (possibly null) character strings.
  117.  
  118.  
  119.     In Markov algorithms, text is always searched from the left, and the 
  120. substitution list is always consulted from top to bottom.  If the chain a[i] 
  121. is found, it is replaced by b[i], and the substitution list is consulted once 
  122. again from the beginning.  If a[i] is not found, a[i+1] is sought, until no 
  123. further transformation is possible.  Markov Algorithms also allow one or more 
  124. substitutions to be declared terminal, conventionally by placing a point 
  125. after the substituion arrow.  Many examples and a thorough discussion may be 
  126. found in Markov's book, "Theory of Algorithms".
  127.  
  128.     A Markov Algorithm may be translated directly into REC by writing
  129.  
  130.     J 'a' F D 'b' I :
  131.  
  132. for an ordinary substitution or
  133.  
  134.     J 'a' F D 'b' I ;
  135.  
  136. for a terminal substitution.
  137.  
  138.     To give a specific example, consider the problem of incrementing by 
  139. one a number written out in binary form.  A Markov algorithm to accomplish 
  140. this is shown in the next panel.
  141.  
  142.             *1  =>  1*
  143.             *0  =>  0*
  144.             *   =>  +
  145.             1+  =>  +0
  146.             0+  =>. 1
  147.             +   =>. 1
  148.                 =>  *
  149.  
  150. It operates as follows:  If neither a * nor a + is seen, a * is inserted at 
  151. the front of the word (last substitution).  It will then travel to the end of 
  152. the word (first and second substitutions), changing places with 0's and 1's, 
  153. wherupon it mutates into a + (third substitution).  The + is the actual 
  154. incrementer, traveling backwards generating a carry if it sees a 1, writing a 
  155. 1 in place of a 0 or placing a 1 in front of the whole string.
  156.  
  157.     A REC program which reads in a binary number (as a string of ASCII 0s 
  158. and 1s) and carries out this algorithm follows.
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.     [Markov Algorithm to increment a binary number]
  166.     {(2573 TL;) L                [new line]
  167.      (R 13%= @L; "0"="0"T|: "1"="1"T|:
  168.         TL "< 0, 1 or 'Return'"TL @L:) T    [text]
  169.      (@L "> "TL ""@T I
  170.         (JZ QTL @L "*1" FD "1*" I:
  171.                "*0" FD "0*" I:
  172.                "*"  FD "+"  I:
  173.                "1+" FD "+0" I:
  174.                "0+" FD "1"  I;
  175.                "+"  FD "1"  I;
  176.                ""   FD "*"  I: )
  177.          JZQDT"1"=;L:)}
  178.  
  179.     It is not necessary to include J in each substitution because p1 
  180. remains unchanged when F fails.  Z is required in order to copy with Q the 
  181. entire text to the PDL.  The program stops when a null string or a single 0 
  182. is given in response to the prompt "> " sent to the console at the beginning 
  183. of each iteration in the main program's outer parenthesis level.
  184.  
  185.  
  186.  
  187.  
  188.     When this program is applied to, e.g., the string 1011, the succesive 
  189. steps in the transformation are
  190.  
  191.             1011        [initial word]
  192.             *1011
  193.             1*011
  194.             10*11
  195.             101*1
  196.             1011*
  197.             1011+
  198.             101+0
  199.             10+00
  200.             1100        [final word].
  201.  
  202.     Phrases can be created out of nothing only at the extreme left of the 
  203. text, and must be moved around very laboriously because only one single 
  204. consecutive string can be modified at a time.  For example, to add two binary 
  205. numbers, their digits first have to be intermingled, and then an adder moved 
  206. through them.  For this reason Markov Algorithms are not very practical.  
  207. Their merit lies in their simplicity, and the ease with which theoretical 
  208. results about computing can be established using them.
  209.  
  210. :            The Workspace, Part II
  211.  
  212. Operator/Predicate        Function performed
  213.  
  214.     E    Predicate which becomes true if the WS contains a string 
  215.         which starts at p1 and is identical to the top PDL argument, 
  216.         in which case p2 is modified to delimit the matching text.  
  217.         If E fails, no pointer is moved, but in either case the PDL 
  218.         argument is lifted.
  219.  
  220.     U    Predicate used to delimit an interval, given strings to 
  221.         delimit it.  Given an argument on the PDL, U searches in the 
  222.         WS for a string identical to the argument, beginning at p2. 
  223.         If found, p1 will take the starting value of p2 and p2 will 
  224.         point to the beginning of the string found by U, and the 
  225.         predicate becomes true; otherwise U becomes false and the 
  226.         pointers are not moved.  The top argument is lifted in either 
  227.         case.  U differs from F in that its search starts at p2, and 
  228.         on succeeding the interval defined by p1 and p2 is the one 
  229.         lying between the previous (p1,p2) interval and the text 
  230.         found by U. For instance, if the workspace contains the 
  231.         string AABBCCDDEEFFGG, the program (J'BB'F 'F'U;) will result 
  232.         in pointer p1 and p2 delimiting the substring CCDDEE.
  233.     V    Predicate, similar to U in its operation.  Searches in WS, 
  234.         beginning at p2, for a string matching exactly the top PDL 
  235.         argument (which will be lifted regardless of the outcome of 
  236.         the search).  If found, value of p2 is altered so that it 
  237.         points to the end of the text found by V; p2 does not change 
  238.         otherwise. The difference between U and V is that U excludes 
  239.         the original interval and the text found from the interval 
  240.         defined by p1 and p2, whereas V includes betwwen p1 and p2 
  241.         the original interval and the text found.  Thus, if the WS 
  242.         contains the string AABBCCDDEEFFGG, the program (J'BB'F 
  243.         'F'V;) causes p1 and p2 to delimit the substring BBCCDDEEF.
  244.  
  245.     M    Predicate requiring two arguments from the PDL, which define 
  246.         a lexicographic interval whose lower bound is the lower 
  247.         argument and whose upper bound is the top argument.  M 
  248.         becomes true if the workspace contains a string which starts 
  249.         at p1 and is greater than or equal to the lower bound and 
  250.         smaller than or equal to the upper bound; if such a string 
  251.         exists p1 and p2 will delimit the smallest string lying in 
  252.         the interval; if M becomes false no pointers are moved, but 
  253.         in either case both PDL arguments are lifted.  Lexicographic 
  254.         order is defined in the following panel. 
  255.         
  256.   M (cont.)    An n-byte string is equal to an m-byte string if and only if 
  257.         m=n and both strings consist of the same sequence of bytes; 
  258.         an n-byte string is greater than an m-byte string if there 
  259.         exists an integer k between 1 and the smaller of m and n, 
  260.         such that the strings coincide in the first k-1 bytes and the 
  261.         k-th byte of the first string is greater than the 
  262.         corresponding byte of the second string; an n-byte string is 
  263.         greater than an m-byte string if n>m and the first m 
  264.         characters of the first string are identical to the 
  265.         corresponding bytes of the second string. The ordering 
  266.         relation between bytes containing alphanumeric data is the 
  267.         one defined by the ASCII code, so that 0<1<... 
  268.         <9<...<A<B<...<Z<...<a<b<...<z. Notice that "" "xxx" M is 
  269.         always true regardless of the string xxx and causes p2 to 
  270.         take the value of p1, whereas "xxx" "" M, which would 
  271.         normally be false when xxx is nonnull, is interpreted in such 
  272.         a way that it is true only if the workspace contains a string 
  273.         that starts at p1 and is greater than or equal to xxx, 
  274.         effectively omitting the null string given as top argument 
  275.         from the comparison.
  276.  
  277.  
  278.  
  279.     j    Operator, delimits a null interval at p1, i.e., assigns the 
  280.         value of p1 to p2.
  281.  
  282.     z    Operator, delimits a null string at p2, i.e., it assigns the 
  283.         value of p2 to p1.
  284.  
  285.     A    Predicate, makes p1 advance one byte if it can.  If p1 is at 
  286.         the right end of the text (p1=p3) before the operation, A 
  287.         becomes false; otherwise p1 advances and drags p2 with it if 
  288.         necessary (so that p2<p1 never holds).
  289.  
  290.     B    Predicate, makes p2 back up one byte if possible. If p1 is at 
  291.         the left end of the text (p1=p0), B becomes false; otherwise 
  292.         p1 backs up.
  293.  
  294.     q    Operator which leaves two numbers on the PDL: the value of p1 
  295.         (as lower argument) and the difference p2-p1 (as top 
  296.         argument), i.e., it leaves the origin and length of the 
  297.         interval defined by p1 and p2.  In the 8086 version, the 
  298.         lower argument (p1) consists of 4 bytes, the lower two 
  299.         containing p1 and the upper two containing the base address 
  300.         of the memory segment in which the workspace resides.
  301.  
  302.     Y    Predicate requiring an argument on the PDL previously 
  303.         produced by either of the operator combinations qL or q|.  
  304.         There are several possibilities, depending on the argument 
  305.         provided and the processor used.  On the 8080, if a 2-byte 
  306.         argument is given (generated by qL), Y is always true and 
  307.         assigns a value to p1, depending on the PDL value, say x, as 
  308.         follows: if x<p0, it moves p1 to p0; if x>p3, it moves both 
  309.         p1 and p2 to p3; if x>p2 but within p0 and p3, it assigns x 
  310.         to both p1 and p2, and in the remaining case, x is assigned 
  311.         to p1 and p2 remains unchanged.  On the 8086, given a 4 byte 
  312.         argument (produced by qL), Y is false (and does not alter any 
  313.         of the pointers) if the segment base contained in the PDL 
  314.         argument is different from the base of the segment containing 
  315.         the WS currently in use (which may be changed as will be seen 
  316.         later on), otherwise, Y assigns values to p1 (and possibly 
  317.         p2) as above.  To analyze the case where the PDL argument is 
  318.         the product of q|, call x and y the values of p1 and p2 used 
  319.         by the operator q, respectively.  Then Y will be false (and 
  320.         not alter any pointers) if x<p0 or y>p3 (or if the segment 
  321.         bases are not equal, on the 8086), and true otherwise, in 
  322.         which case x is assigned to p1 and y to p2.
  323.  
  324.  
  325.     We illustrate the use of these operators and predicates with a 
  326. program which carries out the syntactical analysis of an arithmetic 
  327. expression written out in the usual algebraic notation, in which all operands 
  328. are decimal integer constants.  The operators recognized are +, -, * and /; 
  329. no blanks are allowed nor are + or - permitted as unary operators, but 
  330. parenthesis may be used.  (We will later extend this program to include 
  331. constants containing a decimal point and a power of ten factor, and unary + 
  332. and - operators.)
  333.  
  334.     [Arithmetic expression parser]
  335.     {("0""9"Mz;) d                [digit]
  336.      (@d(@d:;);) q                [integer]
  337.      ('+'Ez; '-'Ez; '*'Ez; '/'Ez;) o    [operator]
  338.      (@q; '('Ez @e ')'Ez;) p        [operand]
  339.      (@p (qL @o@p L: Y;) ;) e        [expression]
  340.  
  341.      (R 13%=""; T@J|;) J            [read a line]
  342.  
  343.      (2573TL '> 'TL @J ""=;
  344.         JZD I @e (A) ": yes"TL: ": no"TL:)}
  345.  
  346.  
  347.  
  348.     The main program signals with a ">" that it is ready to receive a 
  349. string, reads a line and inserts it in the workspace after deleting the 
  350. entire previous contents.  If subroutine e recognizes an arithmetic 
  351. expression spanning the entire text, p1 will be at the right end of the text 
  352. so that (A) is true if the WS does contain an expression (p1 cannot advance) 
  353. and false otherwise.  Looking at the definition of an expression given in 
  354. subroutine e, it is seen that an expression is a single operand or an 
  355. alternating succession of operands and operators starting and ending with an 
  356. operand (the REC operators qL and Y are used to guarantee that p1 ends up 
  357. pointing to the first character not stasifying this definition of an 
  358. expression); in turn, an operand may be an integer or an expression enclosed 
  359. in parentheses, and an integer consists of one or more decimal digits 
  360. (subroutines q and d).  Subroutine q is true if there is a digit at p1 
  361. (recognized by subroutine d) and makes p1 advance through all digits 
  362. following the first one, if any; subroutine d is true only if there is a 
  363. digit at the byte pointed to by p1, in which case the operator z cause p1 to 
  364. advance to the next character.  In a similar fashion, subroutine o becomes 
  365. true if p1 points to a byte containing any one of the four symbols +, -, *
  366. or /.
  367.  
  368. :            The Workspace, Part III
  369.  
  370.     The last operators and predicates affecting the workspace and its 
  371. pointers are the following:
  372.  
  373. Operator/Predicate        Function performed
  374.  
  375.     a    Predicate.  Given a two-byte integer n on the PDL, attempts 
  376.         to delimit an n-byte interval between p1 and p2 keeping p1 
  377.         fixed; if it can, it becomes true, lifts its argument and 
  378.         moves p2; if there are fewer than n bytes between p1 and p3, 
  379.         it becomes false, leaves p2 unchanged and replaces its PDL 
  380.         argument with the deficit, i.e., the difference n-(p3-p1). 
  381.  
  382.     b    Predicate.  Given a two-byte integer n on the PDL, attempts 
  383.         to bracket between p1 and p2 an n-byte interval holding p2 
  384.         fixed, if it can, it becomes true and moves p1; if there are 
  385.         fewer than n bytes between p0 and p2, p1 remains unchanged 
  386.         and the predicate becomes false.  The argument n is lifted in 
  387.         either case.
  388.  
  389.  
  390.  
  391.     e    Predicate.  Given a two-byte integer n on the PDL, attempts 
  392.         to extend the text by making p3 advance n bytes.  If it can, 
  393.         e becomes true, p3 advances, p1 and p2 move to delimit the 
  394.         new n-byte extent and n is lifted from the PDL; otherwise no 
  395.         pointers are moved, e becomes false, and n is replaced on the 
  396.         PDL by the deficit, i.e., n-(p4-p3).
  397.  
  398.     f    Predicate; it requires an argument on the PDL whose length we 
  399.         will call l for the sake of discussion.  f replaces the text 
  400.         starting at p1 with the PDL argument if p1+l does not exceed 
  401.         p2, in which case it becomes true, leaves its argument on the 
  402.         PDL and advances p1 to the end of the replaced text.  If the 
  403.         replacement would go beyond p2, f becomes false, no 
  404.         replacement takes place, p1 does not move and the argument is 
  405.         lifted from the PDL.  For example, "a"(f:;) would fill all 
  406.         bytes delimited by p1 and p2 with the letter a.
  407.  
  408.  
  409.  
  410.  
  411.  
  412.  
  413.  
  414.     w    Operator whose operation may take one of three forms,
  415.         depending on the size of the argument it finds on the PDL.  
  416.         If this argument is the null string, it replaces it with a 
  417.         10-byte argument consisting of the concatenated values of the 
  418.         WS pointers, p0 through p4.  If its argument is 10 bytes 
  419.         long, assigns from it values to p0, p1, p2, p3 and p4 (but it 
  420.         does not check that the above-mentioned inequalities hold; 
  421.         the 10-byte argument should have been generated by a previous 
  422.         usage of w).  Finally, if the PDL contains two 2-byte 
  423.         arguments, w assumes the top one to be a length (say l) and 
  424.         the lower one to be an address (say x); it will then replace 
  425.         both arguments with a ten-byte header containing the current 
  426.         values of p0 through p4 and defines a new workspace from x 
  427.         and l as follows: p0=p1=x, p2=p3=p4=x+l. In the 8086 version, 
  428.         the workspace headers are 12 bytes long (the two extra bytes 
  429.         being used to store the base address of the segment in which 
  430.         the WS resides) and the address argument of the third option 
  431.         may be 4 bytes long, the lower two containing an address and 
  432.         the upper two containing the base address of the segment that 
  433.         is to hold the new workspace.
  434.     
  435.  
  436.  
  437.     <    Operator which closes down the workspace.  The WS becomes 
  438.         restricted to the interval between pointers p1 and p2.  The 
  439.         reason for this could be to restrict the editing operations 
  440.         to a smaller range, or it could be to have absolute freedom 
  441.         to work over some material before incorporating it into the 
  442.         rest of the text.  As a practical matter, the text between 
  443.         pointers p2 and p3 is displaced to the upper end of the WS 
  444.         and the original values of p0 and p4 are recorded with it 
  445.         before setting up new values of the pointers, which are set 
  446.         as follows: p1 and p2 remain unchanged, p0 is set to the 
  447.         value of p1, p3 moves to p2 and p4 moves to the left of the 
  448.         string moved to the right end of the original WS.
  449.  
  450.     >    Operator which reopens the WS (which must have been closed 
  451.         previously by <).  The text lying between p0 and p3 takes the 
  452.         place of the text which lay between p1 and p2 before < was 
  453.         used; p0 and p4 are restored to their previous scope, p1 and 
  454.         p2 remain unaltered and p3 moves to the right end of the text 
  455.         brought back from the far end of the WS.  Opening without 
  456.         prior closing causes an error to be noted.
  457.  
  458.  
  459.  
  460.     The program shown next parses arithmetic expressions which may 
  461. contain floating point constants with power-of-ten factors of the form En or 
  462. Dn, where n is an optionally signed integer and E and D denote single and 
  463. double precision, respectively.  The operators recognized by the program 
  464. include ** and ^, which denote exponentiation; + and - are also accepted as 
  465. unary operators.
  466.  
  467.     [Arithmetic expression parser]
  468.     {("0""9"Mz;) d                [digit]
  469.      (@d:;) D                [0 or more digits]
  470.      (qL('E'Ez;'D'Ez;)(@a;;) @d@D L; Yj;) E [power of 10 factor]
  471.      (Z< (@d@D'.'Ez; J'.'Ez@d; J@d; J>)
  472.             >@D@E;) q        [number]
  473.      ('+'Ez; '-'Ez;) a            [additive operator]
  474.      ('*'Ez; '/'Ez;) m            [mult. operator]
  475.      ('**'Ez; '^'Ez;) i            [power operator]
  476.      (@i; @m; @a;) o            [operator]
  477.      (@q; '('Ez @e ')'Ez;) p        [operand]
  478.      (Z<(@p; J@a@p; J>)> (qL @o@p L: Y;) ;) e    [expression]
  479.  
  480.      (R 13%= ""; T@J|;) J            [read a line]
  481.      (2573TL '> 'TL @J ""=; JZD I @e (A) ": yes" TL: ": no" TL:)}
  482.  
  483.     Notice the use of < and > in subroutines q and e.  The purpose of < 
  484. in both cases is to mark the beginning of the substring being parsed when 
  485. several options are possible.  In subroutine e, the fragment Z<(@p;J@a@p;J>)> 
  486. could have been coded as qL(@p;YqL@a@p; Y)L.  The advantage of using < and > 
  487. is that the PDL is not altered in any way since the action of both operators 
  488. is limited exclusively to the workspace.
  489.  
  490.     The next example shows the use of w and f to initialize to 0 all 
  491. bytes in a memory block created on the PDL by the operator c:
  492.  
  493.     [creates a block and fills it with zeros]
  494.     (c m p w 0% (f:;) w n;) 0
  495.  
  496. This subroutine requires an argument on the PDL for c (the length of the 
  497. block to be created); when done, the top PDL argument is the block's starting 
  498. address.  Observe that the operator combination pw turns the top argument 
  499. into a workspace; this is one way to handle multiple workspaces. A very 
  500. important item to note about w is that when used to set up a new workspace 
  501. given an address and a length, the new workspace will appear to be completely 
  502. filled, so that restricting it (with <) or inserting text (with I) will cause 
  503. termination with the  "WS overflow" message, unless some or all of the text 
  504. is deleted with D.  Our example above does not have this problem, since f 
  505. replaces text rather than inserting it.
  506.  
  507.     The last example of the chapter shows how to fill or truncate a 
  508. string to a specified length: it is a subroutine which leaves an 8 byte 
  509. argument starting from the argument provided to it; if this argument is over 
  510. 8 bytes long, it truncates it to the first 8; otherwise the predicates a, e 
  511. and f are used to pad it with blanks on the right:
  512.  
  513.     [truncate or pad with blanks to 8 bytes]
  514.     (I< (8azZD; e ' '(f:;) ;) JQD>;) 8
  515.  
  516.     There is a possibility that on execution this subroutine will become 
  517. false; it will happen when the workspace is so full that predicate e cannot 
  518. extend the text.  The calling program should then take the appropriate action 
  519. to correct the error.
  520.  
  521. :[REC4.HLP]
  522. [(c) G. Cisneros, 1985, 1990]
  523.