home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / funnlweb / part16 < prev    next >
Encoding:
Text File  |  1993-04-10  |  127.7 KB  |  3,779 lines

  1. Newsgroups: comp.sources.unix
  2. From: ross@spam.adelaide.edu.au (Ross Williams)
  3. Subject: v26i136: funnelweb - a tool for literate programming in C, Part16/20
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: ross@spam.adelaide.edu.au (Ross Williams)
  8. Posting-Number: Volume 26, Issue 136
  9. Archive-Name: funnelweb/part16
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 16 (of 20)."
  18. # Contents:  answers/pr09.lis userman/u_ch2.tex
  19. # Wrapped by vixie@gw.home.vix.com on Sun Apr 11 11:00:32 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'answers/pr09.lis' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'answers/pr09.lis'\"
  23. else
  24. echo shar: Extracting \"'answers/pr09.lis'\" \(59230 characters\)
  25. sed "s/^X//" >'answers/pr09.lis' <<'END_OF_FILE'
  26. XFUNNELWEB LISTING FILE
  27. X======================
  28. X
  29. Dump of mapped file "<<Suppressed>>".
  30. X
  31. MEMORY DUMP OF MAPPED FILE
  32. X==========================
  33. X
  34. X+-------------------------------------------------+------------------+
  35. X| 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF |
  36. X+-------------------------------------------------+------------------+
  37. X| 50 52 30 39 3A 20 54 65 73 74 20 63 61 6C 6C 73 | PR09: Test calls |
  38. X| 20 61 6E 64 20 61 63 74 75 61 6C 20 70 61 72 61 |  and actual para |
  39. X| 6D 65 74 65 72 20 6C 69 73 74 73 2E 0A 0A 46 69 | meter lists...Fi |
  40. X| 72 73 74 20 74 72 69 70 20 75 70 20 74 68 65 20 | rst trip up the  |
  41. X| 70 61 72 73 65 72 20 73 6F 20 77 65 20 64 6F 6E | parser so we don |
  42. X| 27 74 20 67 65 74 20 61 6E 79 20 66 75 72 74 68 | 't get any furth |
  43. X| 65 72 2E 0A 40 3E 0A 0A 4E 6F 77 20 64 65 66 69 | er..@>..Now defi |
  44. X| 6E 65 20 73 6F 6D 65 20 6D 61 63 72 6F 73 20 74 | ne some macros t |
  45. X| 6F 20 63 61 6C 6C 2E 20 4E 6F 20 65 72 72 6F 72 | o call. No error |
  46. X| 2E 0A 0A 40 24 40 3C 5A 65 72 6F 40 3E 40 7B 40 | ...@$@<Zero@>@{@ |
  47. X| 7D 0A 40 24 40 3C 4F 6E 65 40 3E 40 28 40 31 40 | }.@$@<One@>@(@1@ |
  48. X| 29 40 7B 40 7D 0A 40 24 40 3C 54 77 6F 40 3E 40 | )@{@}.@$@<Two@>@ |
  49. X| 28 40 32 40 29 40 7B 40 7D 0A 40 24 40 3C 54 68 | (@2@)@{@}.@$@<Th |
  50. X| 72 65 65 40 3E 40 28 40 33 40 29 40 7B 40 7D 0A | ree@>@(@3@)@{@}. |
  51. X| 40 24 40 3C 4E 69 6E 65 40 3E 40 28 40 39 40 29 | @$@<Nine@>@(@9@) |
  52. X| 40 7B 40 7D 0A 40 24 40 23 22 40 7B 40 7D 0A 0A | @{@}.@$@#"@{@}.. |
  53. X| 54 68 65 20 66 6F 6C 6C 6F 77 69 6E 67 20 74 65 | The following te |
  54. X| 73 74 20 63 61 6C 6C 73 20 73 68 6F 75 6C 64 20 | st calls should  |
  55. X| 4E 4F 54 20 67 65 6E 65 72 61 74 65 20 61 6E 79 | NOT generate any |
  56. X| 20 65 72 72 6F 72 73 2E 0A 0A 40 24 40 3C 4D 61 |  errors...@$@<Ma |
  57. X| 63 72 6F 20 63 6F 6E 74 61 69 6E 69 6E 67 20 74 | cro containing t |
  58. X| 68 65 20 74 65 73 74 20 6D 61 63 72 6F 20 63 61 | he test macro ca |
  59. X| 6C 6C 73 2E 40 3E 3D 3D 40 7B 0A 31 2E 20 54 65 | lls.@>==@{.1. Te |
  60. X| 73 74 20 6D 61 63 72 6F 20 63 61 6C 6C 20 77 69 | st macro call wi |
  61. X| 74 68 20 6E 6F 20 70 61 72 61 6D 65 74 65 72 20 | th no parameter  |
  62. X| 6C 69 73 74 2E 0A 40 3C 5A 65 72 6F 40 3E 0A 0A | list..@<Zero@>.. |
  63. X| 32 2E 20 54 65 73 74 20 6D 61 63 72 6F 20 63 61 | 2. Test macro ca |
  64. X| 6C 6C 20 77 69 74 68 20 71 75 69 63 6B 20 6E 61 | ll with quick na |
  65. X| 6D 65 2E 0A 40 23 22 0A 0A 33 2E 20 54 65 73 74 | me..@#"..3. Test |
  66. X| 20 6D 61 63 72 6F 20 63 61 6C 6C 20 77 69 74 68 |  macro call with |
  67. X| 20 6F 6E 65 20 70 61 72 61 6D 65 74 65 72 2E 0A |  one parameter.. |
  68. X| 40 3C 4F 6E 65 40 3E 40 28 54 6F 75 63 61 6E 40 | @<One@>@(Toucan@ |
  69. X| 29 0A 0A 34 2E 20 54 65 73 74 20 6D 61 63 72 6F | )..4. Test macro |
  70. X| 20 63 61 6C 6C 20 77 69 74 68 20 6D 61 6E 79 20 |  call with many  |
  71. X| 70 61 72 61 6D 65 74 65 72 73 2E 0A 40 3C 54 77 | parameters..@<Tw |
  72. X| 6F 40 3E 40 28 54 6F 75 63 61 6E 40 2C 54 65 61 | o@>@(Toucan@,Tea |
  73. X| 70 6F 74 40 29 0A 40 3C 54 68 72 65 65 40 3E 40 | pot@).@<Three@>@ |
  74. X| 28 54 6F 75 63 61 6E 40 2C 54 65 61 70 6F 74 40 | (Toucan@,Teapot@ |
  75. X| 2C 57 61 6C 72 75 73 40 29 0A 40 3C 4E 69 6E 65 | ,Walrus@).@<Nine |
  76. X| 40 3E 40 28 54 6F 75 63 61 6E 40 2C 54 65 61 70 | @>@(Toucan@,Teap |
  77. X| 6F 74 40 2C 57 61 6C 72 75 73 40 2C 0A 20 20 20 | ot@,Walrus@,.    |
  78. X| 20 20 20 20 20 20 20 54 6F 75 63 61 6E 40 2C 54 |        Toucan@,T |
  79. X| 65 61 70 6F 74 40 2C 57 61 6C 72 75 73 40 2C 0A | eapot@,Walrus@,. |
  80. X| 20 20 20 20 20 20 20 20 20 20 54 6F 75 63 61 6E |           Toucan |
  81. X| 40 2C 54 65 61 70 6F 74 40 2C 57 61 6C 72 75 73 | @,Teapot@,Walrus |
  82. X| 40 29 0A 0A 35 2E 20 54 65 73 74 20 6D 61 63 72 | @)..5. Test macr |
  83. X| 6F 20 63 61 6C 6C 73 20 77 69 74 68 20 64 6F 75 | o calls with dou |
  84. X| 62 6C 65 20 71 75 6F 74 65 73 20 6F 6E 20 70 61 | ble quotes on pa |
  85. X| 72 61 6D 65 74 65 72 73 2E 0A 40 3C 4F 6E 65 40 | rameters..@<One@ |
  86. X| 3E 40 28 20 40 22 54 6F 75 63 61 6E 40 22 40 29 | >@( @"Toucan@"@) |
  87. X| 0A 40 3C 54 77 6F 40 3E 40 28 40 22 54 6F 75 63 | .@<Two@>@(@"Touc |
  88. X| 61 6E 40 22 20 20 20 40 2C 20 20 20 40 22 54 65 | an@"   @,   @"Te |
  89. X| 61 70 6F 74 40 22 40 29 0A 40 3C 54 68 72 65 65 | apot@"@).@<Three |
  90. X| 40 3E 40 28 40 22 54 6F 75 63 61 6E 40 22 20 40 | @>@(@"Toucan@" @ |
  91. X| 2C 0A 20 20 20 20 20 20 20 20 20 20 20 40 22 54 | ,.           @"T |
  92. X| 65 61 70 6F 74 40 22 20 40 2C 0A 20 20 20 20 20 | eapot@" @,.      |
  93. X| 20 20 20 20 20 20 40 22 57 61 6C 72 75 73 40 22 |       @"Walrus@" |
  94. X| 20 40 29 0A 40 3C 4E 69 6E 65 40 3E 40 28 20 40 |  @).@<Nine@>@( @ |
  95. X| 22 54 6F 75 63 61 6E 40 22 20 40 2C 20 40 22 54 | "Toucan@" @, @"T |
  96. X| 65 61 70 6F 74 40 22 20 40 2C 20 40 22 57 61 6C | eapot@" @, @"Wal |
  97. X| 72 75 73 40 22 20 40 2C 0A 20 20 20 20 20 20 20 | rus@" @,.        |
  98. X| 20 20 20 20 40 22 54 6F 75 63 61 6E 40 22 20 40 |     @"Toucan@" @ |
  99. X| 2C 20 40 22 54 65 61 70 6F 74 40 22 20 40 2C 20 | , @"Teapot@" @,  |
  100. X| 40 22 57 61 6C 72 75 73 40 22 20 40 2C 0A 20 20 | @"Walrus@" @,.   |
  101. X| 20 20 20 20 20 20 20 20 20 40 22 54 6F 75 63 61 |          @"Touca |
  102. X| 6E 40 22 20 40 2C 20 40 22 54 65 61 70 6F 74 40 | n@" @, @"Teapot@ |
  103. X| 22 20 40 2C 20 40 22 57 61 6C 72 75 73 40 22 20 | " @, @"Walrus@"  |
  104. X| 40 29 0A 0A 37 2E 20 54 65 73 74 20 6D 61 63 72 | @)..7. Test macr |
  105. X| 6F 20 63 61 6C 6C 73 20 77 69 74 68 20 6D 69 78 | o calls with mix |
  106. X| 65 64 20 64 6F 75 62 6C 65 20 71 75 6F 74 65 73 | ed double quotes |
  107. X| 20 6F 6E 20 70 61 72 61 6D 65 74 65 72 73 2E 0A |  on parameters.. |
  108. X| 40 3C 54 77 6F 40 3E 40 28 40 22 54 6F 75 63 61 | @<Two@>@(@"Touca |
  109. X| 6E 40 22 20 20 20 40 2C 54 65 61 70 6F 74 40 29 | n@"   @,Teapot@) |
  110. X| 0A 40 3C 54 68 72 65 65 40 3E 40 28 40 22 54 6F | .@<Three@>@(@"To |
  111. X| 75 63 61 6E 40 22 20 40 2C 0A 20 20 20 20 20 20 | ucan@" @,.       |
  112. X| 20 20 20 20 20 40 22 54 65 61 70 6F 74 40 22 20 |      @"Teapot@"  |
  113. X| 40 2C 57 61 6C 72 75 73 40 29 0A 40 3C 4E 69 6E | @,Walrus@).@<Nin |
  114. X| 65 40 3E 40 28 20 40 22 54 6F 75 63 61 6E 40 22 | e@>@( @"Toucan@" |
  115. X| 20 40 2C 20 40 22 54 65 61 70 6F 74 40 22 20 40 |  @, @"Teapot@" @ |
  116. X| 2C 20 20 20 57 61 6C 72 75 73 20 20 20 40 2C 0A | ,   Walrus   @,. |
  117. X| 20 20 20 20 20 20 20 20 20 20 20 40 22 54 6F 75 |            @"Tou |
  118. X| 63 61 6E 40 22 20 40 2C 20 20 20 54 65 61 70 6F | can@" @,   Teapo |
  119. X| 74 20 20 20 40 2C 20 40 22 57 61 6C 72 75 73 40 | t   @, @"Walrus@ |
  120. X| 22 20 40 2C 0A 20 20 20 20 20 20 20 20 20 20 20 | " @,.            |
  121. X| 40 22 54 6F 75 63 61 6E 40 22 20 40 2C 20 40 22 | @"Toucan@" @, @" |
  122. X| 54 65 61 70 6F 74 40 22 20 40 2C 20 40 22 57 61 | Teapot@" @, @"Wa |
  123. X| 6C 72 75 73 40 22 20 40 29 0A 0A 40 7D 20 40 21 | lrus@" @)..@} @! |
  124. X| 20 45 6E 64 20 6F 66 20 6D 61 63 72 6F 20 64 65 |  End of macro de |
  125. X| 66 69 6E 69 74 69 6F 6E 20 65 6E 63 6C 6F 73 69 | finition enclosi |
  126. X| 6E 67 20 61 6C 6C 20 74 68 65 73 65 20 6C 65 67 | ng all these leg |
  127. X| 61 6C 20 74 65 73 74 73 2E 0A 0A 38 2E 20 54 65 | al tests...8. Te |
  128. X| 73 74 20 6D 61 63 72 6F 20 63 61 6C 6C 73 20 77 | st macro calls w |
  129. X| 69 74 68 20 61 20 76 61 72 69 65 74 79 20 6F 66 | ith a variety of |
  130. X| 20 73 79 6E 74 61 78 20 65 72 72 6F 72 73 20 69 |  syntax errors i |
  131. X| 6E 20 70 61 72 61 6D 65 74 65 72 20 6C 69 73 74 | n parameter list |
  132. X| 2E 0A 40 24 40 3C 45 72 72 6F 72 31 40 3E 40 7B | ..@$@<Error1@>@{ |
  133. X| 0A 40 3C 5A 65 72 6F 40 3E 40 28 0A 40 7D 0A 40 | .@<Zero@>@(.@}.@ |
  134. X| 41 40 3C 45 72 72 6F 72 20 72 65 63 6F 76 65 72 | A@<Error recover |
  135. X| 79 20 70 6F 69 6E 74 40 3E 0A 0A 40 24 40 3C 45 | y point@>..@$@<E |
  136. X| 72 72 6F 72 32 40 3E 40 7B 0A 40 3C 5A 65 72 6F | rror2@>@{.@<Zero |
  137. X| 40 3E 40 29 0A 40 7D 0A 40 41 40 3C 45 72 72 6F | @>@).@}.@A@<Erro |
  138. X| 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E 74 | r recovery point |
  139. X| 40 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 33 40 3E | @>..@$@<Error3@> |
  140. X| 40 7B 0A 40 3C 4F 6E 65 40 3E 40 28 40 22 54 6F | @{.@<One@>@(@"To |
  141. X| 75 63 61 6E 40 29 0A 40 7D 0A 40 41 40 3C 45 72 | ucan@).@}.@A@<Er |
  142. X| 72 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 | ror recovery poi |
  143. X| 6E 74 40 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 34 | nt@>..@$@<Error4 |
  144. X| 40 3E 40 7B 0A 40 3C 4F 6E 65 40 3E 40 28 40 22 | @>@{.@<One@>@(@" |
  145. X| 54 6F 75 63 61 6E 40 22 40 22 53 6C 6F 74 68 40 | Toucan@"@"Sloth@ |
  146. X| 22 40 29 0A 40 7D 0A 40 41 40 3C 45 72 72 6F 72 | "@).@}.@A@<Error |
  147. X| 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E 74 40 |  recovery point@ |
  148. X| 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 35 40 3E 40 | >..@$@<Error5@>@ |
  149. X| 7B 0A 40 3C 54 77 6F 40 3E 40 28 40 22 54 6F 75 | {.@<Two@>@(@"Tou |
  150. X| 63 61 6E 40 22 54 65 61 70 6F 74 40 29 0A 40 7D | can@"Teapot@).@} |
  151. X| 0A 40 41 40 3C 45 72 72 6F 72 20 72 65 63 6F 76 | .@A@<Error recov |
  152. X| 65 72 79 20 70 6F 69 6E 74 40 3E 0A 0A 40 24 40 | ery point@>..@$@ |
  153. X| 3C 45 72 72 6F 72 36 40 3E 40 7B 0A 40 3C 54 77 | <Error6@>@{.@<Tw |
  154. X| 6F 40 3E 40 28 40 22 54 6F 75 63 61 6E 40 22 54 | o@>@(@"Toucan@"T |
  155. X| 65 61 70 6F 74 0A 40 7D 0A 40 41 40 3C 45 72 72 | eapot.@}.@A@<Err |
  156. X| 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E | or recovery poin |
  157. X| 74 40 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 37 40 | t@>..@$@<Error7@ |
  158. X| 3E 40 7B 0A 40 3C 54 77 6F 40 3E 40 28 40 22 54 | >@{.@<Two@>@(@"T |
  159. X| 6F 75 63 61 6E 40 22 54 65 61 70 6F 74 0A 40 3C | oucan@"Teapot.@< |
  160. X| 54 68 72 65 65 40 3E 40 28 54 6F 75 63 61 6E 40 | Three@>@(Toucan@ |
  161. X| 2C 0A 20 20 20 20 20 20 20 20 20 20 20 40 22 54 | ,.           @"T |
  162. X| 65 61 70 6F 74 40 2C 57 61 6C 72 75 73 0A 0A 40 | eapot@,Walrus..@ |
  163. X| 7D 0A 40 41 40 3C 45 72 72 6F 72 20 72 65 63 6F | }.@A@<Error reco |
  164. X| 76 65 72 79 20 70 6F 69 6E 74 40 3E 0A 0A       | very point@>..   |
  165. X+-------------------------------------------------+------------------+
  166. X
  167. X
  168. X=========================== Start of LINE LIST DUMP ============================
  169. X
  170. Globl Local| Text
  171. X-----------+--------------------------------------------------------------------
  172. X00001 00001| PR09: Test calls and actual parameter lists.<010>
  173. X00002 00002| <010>
  174. X00003 00003| First trip up the parser so we don't get any further.<010>
  175. X00004 00004| @><010>
  176. X00005 00005| <010>
  177. X00006 00006| Now define some macros to call. No error.<010>
  178. X00007 00007| <010>
  179. X00008 00008| @$@<Zero@>@{@}<010>
  180. X00009 00009| @$@<One@>@(@1@)@{@}<010>
  181. X00010 00010| @$@<Two@>@(@2@)@{@}<010>
  182. X00011 00011| @$@<Three@>@(@3@)@{@}<010>
  183. X00012 00012| @$@<Nine@>@(@9@)@{@}<010>
  184. X00013 00013| @$@#"@{@}<010>
  185. X00014 00014| <010>
  186. X00015 00015| The following test calls should NOT generate any errors.<010>
  187. X00016 00016| <010>
  188. X00017 00017| @$@<Macro containing the test macro calls.@>==@{<010>
  189. X00018 00018| 1. Test macro call with no parameter list.<010>
  190. X00019 00019| @<Zero@><010>
  191. X00020 00020| <010>
  192. X00021 00021| 2. Test macro call with quick name.<010>
  193. X00022 00022| @#"<010>
  194. X00023 00023| <010>
  195. X00024 00024| 3. Test macro call with one parameter.<010>
  196. X00025 00025| @<One@>@(Toucan@)<010>
  197. X00026 00026| <010>
  198. X00027 00027| 4. Test macro call with many parameters.<010>
  199. X00028 00028| @<Two@>@(Toucan@,Teapot@)<010>
  200. X00029 00029| @<Three@>@(Toucan@,Teapot@,Walrus@)<010>
  201. X00030 00030| @<Nine@>@(Toucan@,Teapot@,Walrus@,<010>
  202. X00031 00031|           Toucan@,Teapot@,Walrus@,<010>
  203. X00032 00032|           Toucan@,Teapot@,Walrus@)<010>
  204. X00033 00033| <010>
  205. X00034 00034| 5. Test macro calls with double quotes on parameters.<010>
  206. X00035 00035| @<One@>@( @"Toucan@"@)<010>
  207. X00036 00036| @<Two@>@(@"Toucan@"   @,   @"Teapot@"@)<010>
  208. X00037 00037| @<Three@>@(@"Toucan@" @,<010>
  209. X00038 00038|            @"Teapot@" @,<010>
  210. X00039 00039|            @"Walrus@" @)<010>
  211. X00040 00040| @<Nine@>@( @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,<010>
  212. X00041 00041|            @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,<010>
  213. X00042 00042|            @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)<010>
  214. X00043 00043| <010>
  215. X00044 00044| 7. Test macro calls with mixed double quotes on parameters.<010>
  216. X00045 00045| @<Two@>@(@"Toucan@"   @,Teapot@)<010>
  217. X00046 00046| @<Three@>@(@"Toucan@" @,<010>
  218. X00047 00047|            @"Teapot@" @,Walrus@)<010>
  219. X00048 00048| @<Nine@>@( @"Toucan@" @, @"Teapot@" @,   Walrus   @,<010>
  220. X00049 00049|            @"Toucan@" @,   Teapot   @, @"Walrus@" @,<010>
  221. X00050 00050|            @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)<010>
  222. X00051 00051| <010>
  223. X00052 00052| @} @! End of macro definition enclosing all these legal tests.<010>
  224. X00053 00053| <010>
  225. X00054 00054| 8. Test macro calls with a variety of syntax errors in parameter list.<010>
  226. X00055 00055| @$@<Error1@>@{<010>
  227. X00056 00056| @<Zero@>@(<010>
  228. X00057 00057| @}<010>
  229. X00058 00058| @A@<Error recovery point@><010>
  230. X00059 00059| <010>
  231. X00060 00060| @$@<Error2@>@{<010>
  232. X00061 00061| @<Zero@>@)<010>
  233. X00062 00062| @}<010>
  234. X00063 00063| @A@<Error recovery point@><010>
  235. X00064 00064| <010>
  236. X00065 00065| @$@<Error3@>@{<010>
  237. X00066 00066| @<One@>@(@"Toucan@)<010>
  238. X00067 00067| @}<010>
  239. X00068 00068| @A@<Error recovery point@><010>
  240. X00069 00069| <010>
  241. X00070 00070| @$@<Error4@>@{<010>
  242. X00071 00071| @<One@>@(@"Toucan@"@"Sloth@"@)<010>
  243. X00072 00072| @}<010>
  244. X00073 00073| @A@<Error recovery point@><010>
  245. X00074 00074| <010>
  246. X00075 00075| @$@<Error5@>@{<010>
  247. X00076 00076| @<Two@>@(@"Toucan@"Teapot@)<010>
  248. X00077 00077| @}<010>
  249. X00078 00078| @A@<Error recovery point@><010>
  250. X00079 00079| <010>
  251. X00080 00080| @$@<Error6@>@{<010>
  252. X00081 00081| @<Two@>@(@"Toucan@"Teapot<010>
  253. X00082 00082| @}<010>
  254. X00083 00083| @A@<Error recovery point@><010>
  255. X00084 00084| <010>
  256. X00085 00085| @$@<Error7@>@{<010>
  257. X00086 00086| @<Two@>@(@"Toucan@"Teapot<010>
  258. X00087 00087| @<Three@>@(Toucan@,<010>
  259. X00088 00088|            @"Teapot@,Walrus<010>
  260. X00089 00089| <010>
  261. X00090 00090| @}<010>
  262. X00091 00091| @A@<Error recovery point@><010>
  263. X00092 00092| <010>
  264. X00093 00093| <End-Of-File><010>
  265. X-----------+--------------------------------------------------------------------
  266. Globl Local| Text
  267. X
  268. X============================ End of LINE LIST DUMP =============================
  269. X
  270. X
  271. X=========================== Start of TOKEN LIST DUMP ===========================
  272. X
  273. Summary: There are 467 tokens in the token list.
  274. X
  275. Line[Column]: Token Description
  276. X-------------------------------
  277. X
  278. X0001[01]: Text. Text scrap[Grey]="PR09: Test calls and actual parameter lists.<010>
  279. X<010>
  280. XFirst trip up the parser so we don't get any further.<010>
  281. X"
  282. X0004[01]: @> Close name. 
  283. X0004[03]: Text. Text scrap[Grey]="<010>
  284. X<010>
  285. Now define some macros to call. No error.<010>
  286. X<010>
  287. X"
  288. X0008[01]: @$ Macro defn. 
  289. X0008[03]: @< Open name. 
  290. X0008[05]: Text. Text scrap[Grey]="Zero"
  291. X0008[09]: @> Close name. 
  292. X0008[11]: @{ Open defn. 
  293. X0008[13]: @} Close defn. 
  294. X0008[15]: Text. Text scrap[White]="<010>
  295. X"
  296. X0009[01]: @$ Macro defn. 
  297. X0009[03]: @< Open name. 
  298. X0009[05]: Text. Text scrap[Grey]="One"
  299. X0009[08]: @> Close name. 
  300. X0009[10]: @( Open param. 
  301. X0009[12]: @n Parameter. Parameterno=1.
  302. X0009[14]: @} Close param. 
  303. X0009[16]: @{ Open defn. 
  304. X0009[18]: @} Close defn. 
  305. X0009[20]: Text. Text scrap[White]="<010>
  306. X"
  307. X0010[01]: @$ Macro defn. 
  308. X0010[03]: @< Open name. 
  309. X0010[05]: Text. Text scrap[Grey]="Two"
  310. X0010[08]: @> Close name. 
  311. X0010[10]: @( Open param. 
  312. X0010[12]: @n Parameter. Parameterno=2.
  313. X0010[14]: @} Close param. 
  314. X0010[16]: @{ Open defn. 
  315. X0010[18]: @} Close defn. 
  316. X0010[20]: Text. Text scrap[White]="<010>
  317. X"
  318. X0011[01]: @$ Macro defn. 
  319. X0011[03]: @< Open name. 
  320. X0011[05]: Text. Text scrap[Grey]="Three"
  321. X0011[10]: @> Close name. 
  322. X0011[12]: @( Open param. 
  323. X0011[14]: @n Parameter. Parameterno=3.
  324. X0011[16]: @} Close param. 
  325. X0011[18]: @{ Open defn. 
  326. X0011[20]: @} Close defn. 
  327. X0011[22]: Text. Text scrap[White]="<010>
  328. X"
  329. X0012[01]: @$ Macro defn. 
  330. X0012[03]: @< Open name. 
  331. X0012[05]: Text. Text scrap[Grey]="Nine"
  332. X0012[09]: @> Close name. 
  333. X0012[11]: @( Open param. 
  334. X0012[13]: @n Parameter. Parameterno=9.
  335. X0012[15]: @} Close param. 
  336. X0012[17]: @{ Open defn. 
  337. X0012[19]: @} Close defn. 
  338. X0012[21]: Text. Text scrap[White]="<010>
  339. X"
  340. X0013[01]: @$ Macro defn. 
  341. X0013[03]: @# Name. Character='"'.
  342. X0013[06]: @{ Open defn. 
  343. X0013[08]: @} Close defn. 
  344. X0013[10]: Text. Text scrap[Grey]="<010>
  345. X<010>
  346. The following test calls should NOT generate any errors.<010>
  347. X<010>
  348. X"
  349. X0017[01]: @$ Macro defn. 
  350. X0017[03]: @< Open name. 
  351. X0017[05]: Text. Text scrap[Grey]="Macro containing the test macro calls."
  352. X0017[43]: @> Close name. 
  353. X0017[45]: Text. Text scrap[Grey]="=="
  354. X0017[47]: @{ Open defn. 
  355. X0017[49]: Text. Text scrap[Grey]="<010>
  356. X1. Test macro call with no parameter list.<010>
  357. X"
  358. X0019[01]: @< Open name. 
  359. X0019[03]: Text. Text scrap[Grey]="Zero"
  360. X0019[07]: @> Close name. 
  361. X0019[09]: Text. Text scrap[Grey]="<010>
  362. X<010>
  363. X2. Test macro call with quick name.<010>
  364. X"
  365. X0022[01]: @# Name. Character='"'.
  366. X0022[04]: Text. Text scrap[Grey]="<010>
  367. X<010>
  368. X3. Test macro call with one parameter.<010>
  369. X"
  370. X0025[01]: @< Open name. 
  371. X0025[03]: Text. Text scrap[Grey]="One"
  372. X0025[06]: @> Close name. 
  373. X0025[08]: @( Open param. 
  374. X0025[10]: Text. Text scrap[Grey]="Toucan"
  375. X0025[16]: @} Close param. 
  376. X0025[18]: Text. Text scrap[Grey]="<010>
  377. X<010>
  378. X4. Test macro call with many parameters.<010>
  379. X"
  380. X0028[01]: @< Open name. 
  381. X0028[03]: Text. Text scrap[Grey]="Two"
  382. X0028[06]: @> Close name. 
  383. X0028[08]: @( Open param. 
  384. X0028[10]: Text. Text scrap[Grey]="Toucan"
  385. X0028[16]: @, Comma. 
  386. X0028[18]: Text. Text scrap[Grey]="Teapot"
  387. X0028[24]: @} Close param. 
  388. X0028[26]: Text. Text scrap[White]="<010>
  389. X"
  390. X0029[01]: @< Open name. 
  391. X0029[03]: Text. Text scrap[Grey]="Three"
  392. X0029[08]: @> Close name. 
  393. X0029[10]: @( Open param. 
  394. X0029[12]: Text. Text scrap[Grey]="Toucan"
  395. X0029[18]: @, Comma. 
  396. X0029[20]: Text. Text scrap[Grey]="Teapot"
  397. X0029[26]: @, Comma. 
  398. X0029[28]: Text. Text scrap[Grey]="Walrus"
  399. X0029[34]: @} Close param. 
  400. X0029[36]: Text. Text scrap[White]="<010>
  401. X"
  402. X0030[01]: @< Open name. 
  403. X0030[03]: Text. Text scrap[Grey]="Nine"
  404. X0030[07]: @> Close name. 
  405. X0030[09]: @( Open param. 
  406. X0030[11]: Text. Text scrap[Grey]="Toucan"
  407. X0030[17]: @, Comma. 
  408. X0030[19]: Text. Text scrap[Grey]="Teapot"
  409. X0030[25]: @, Comma. 
  410. X0030[27]: Text. Text scrap[Grey]="Walrus"
  411. X0030[33]: @, Comma. 
  412. X0030[35]: Text. Text scrap[Grey]="<010>
  413. X          Toucan"
  414. X0031[17]: @, Comma. 
  415. X0031[19]: Text. Text scrap[Grey]="Teapot"
  416. X0031[25]: @, Comma. 
  417. X0031[27]: Text. Text scrap[Grey]="Walrus"
  418. X0031[33]: @, Comma. 
  419. X0031[35]: Text. Text scrap[Grey]="<010>
  420. X          Toucan"
  421. X0032[17]: @, Comma. 
  422. X0032[19]: Text. Text scrap[Grey]="Teapot"
  423. X0032[25]: @, Comma. 
  424. X0032[27]: Text. Text scrap[Grey]="Walrus"
  425. X0032[33]: @} Close param. 
  426. X0032[35]: Text. Text scrap[Grey]="<010>
  427. X<010>
  428. X5. Test macro calls with double quotes on parameters.<010>
  429. X"
  430. X0035[01]: @< Open name. 
  431. X0035[03]: Text. Text scrap[Grey]="One"
  432. X0035[06]: @> Close name. 
  433. X0035[08]: @( Open param. 
  434. X0035[10]: Text. Text scrap[White]=" "
  435. X0035[11]: @" Quote. 
  436. X0035[13]: Text. Text scrap[Grey]="Toucan"
  437. X0035[19]: @" Quote. 
  438. X0035[21]: @} Close param. 
  439. X0035[23]: Text. Text scrap[White]="<010>
  440. X"
  441. X0036[01]: @< Open name. 
  442. X0036[03]: Text. Text scrap[Grey]="Two"
  443. X0036[06]: @> Close name. 
  444. X0036[08]: @( Open param. 
  445. X0036[10]: @" Quote. 
  446. X0036[12]: Text. Text scrap[Grey]="Toucan"
  447. X0036[18]: @" Quote. 
  448. X0036[20]: Text. Text scrap[White]="   "
  449. X0036[23]: @, Comma. 
  450. X0036[25]: Text. Text scrap[White]="   "
  451. X0036[28]: @" Quote. 
  452. X0036[30]: Text. Text scrap[Grey]="Teapot"
  453. X0036[36]: @" Quote. 
  454. X0036[38]: @} Close param. 
  455. X0036[40]: Text. Text scrap[White]="<010>
  456. X"
  457. X0037[01]: @< Open name. 
  458. X0037[03]: Text. Text scrap[Grey]="Three"
  459. X0037[08]: @> Close name. 
  460. X0037[10]: @( Open param. 
  461. X0037[12]: @" Quote. 
  462. X0037[14]: Text. Text scrap[Grey]="Toucan"
  463. X0037[20]: @" Quote. 
  464. X0037[22]: Text. Text scrap[White]=" "
  465. X0037[23]: @, Comma. 
  466. X0037[25]: Text. Text scrap[White]="<010>
  467. X           "
  468. X0038[12]: @" Quote. 
  469. X0038[14]: Text. Text scrap[Grey]="Teapot"
  470. X0038[20]: @" Quote. 
  471. X0038[22]: Text. Text scrap[White]=" "
  472. X0038[23]: @, Comma. 
  473. X0038[25]: Text. Text scrap[White]="<010>
  474. X           "
  475. X0039[12]: @" Quote. 
  476. X0039[14]: Text. Text scrap[Grey]="Walrus"
  477. X0039[20]: @" Quote. 
  478. X0039[22]: Text. Text scrap[White]=" "
  479. X0039[23]: @} Close param. 
  480. X0039[25]: Text. Text scrap[White]="<010>
  481. X"
  482. X0040[01]: @< Open name. 
  483. X0040[03]: Text. Text scrap[Grey]="Nine"
  484. X0040[07]: @> Close name. 
  485. X0040[09]: @( Open param. 
  486. X0040[11]: Text. Text scrap[White]=" "
  487. X0040[12]: @" Quote. 
  488. X0040[14]: Text. Text scrap[Grey]="Toucan"
  489. X0040[20]: @" Quote. 
  490. X0040[22]: Text. Text scrap[White]=" "
  491. X0040[23]: @, Comma. 
  492. X0040[25]: Text. Text scrap[White]=" "
  493. X0040[26]: @" Quote. 
  494. X0040[28]: Text. Text scrap[Grey]="Teapot"
  495. X0040[34]: @" Quote. 
  496. X0040[36]: Text. Text scrap[White]=" "
  497. X0040[37]: @, Comma. 
  498. X0040[39]: Text. Text scrap[White]=" "
  499. X0040[40]: @" Quote. 
  500. X0040[42]: Text. Text scrap[Grey]="Walrus"
  501. X0040[48]: @" Quote. 
  502. X0040[50]: Text. Text scrap[White]=" "
  503. X0040[51]: @, Comma. 
  504. X0040[53]: Text. Text scrap[White]="<010>
  505. X           "
  506. X0041[12]: @" Quote. 
  507. X0041[14]: Text. Text scrap[Grey]="Toucan"
  508. X0041[20]: @" Quote. 
  509. X0041[22]: Text. Text scrap[White]=" "
  510. X0041[23]: @, Comma. 
  511. X0041[25]: Text. Text scrap[White]=" "
  512. X0041[26]: @" Quote. 
  513. X0041[28]: Text. Text scrap[Grey]="Teapot"
  514. X0041[34]: @" Quote. 
  515. X0041[36]: Text. Text scrap[White]=" "
  516. X0041[37]: @, Comma. 
  517. X0041[39]: Text. Text scrap[White]=" "
  518. X0041[40]: @" Quote. 
  519. X0041[42]: Text. Text scrap[Grey]="Walrus"
  520. X0041[48]: @" Quote. 
  521. X0041[50]: Text. Text scrap[White]=" "
  522. X0041[51]: @, Comma. 
  523. X0041[53]: Text. Text scrap[White]="<010>
  524. X           "
  525. X0042[12]: @" Quote. 
  526. X0042[14]: Text. Text scrap[Grey]="Toucan"
  527. X0042[20]: @" Quote. 
  528. X0042[22]: Text. Text scrap[White]=" "
  529. X0042[23]: @, Comma. 
  530. X0042[25]: Text. Text scrap[White]=" "
  531. X0042[26]: @" Quote. 
  532. X0042[28]: Text. Text scrap[Grey]="Teapot"
  533. X0042[34]: @" Quote. 
  534. X0042[36]: Text. Text scrap[White]=" "
  535. X0042[37]: @, Comma. 
  536. X0042[39]: Text. Text scrap[White]=" "
  537. X0042[40]: @" Quote. 
  538. X0042[42]: Text. Text scrap[Grey]="Walrus"
  539. X0042[48]: @" Quote. 
  540. X0042[50]: Text. Text scrap[White]=" "
  541. X0042[51]: @} Close param. 
  542. X0042[53]: Text. Text scrap[Grey]="<010>
  543. X<010>
  544. X7. Test macro calls with mixed double quotes on parameters.<010>
  545. X"
  546. X0045[01]: @< Open name. 
  547. X0045[03]: Text. Text scrap[Grey]="Two"
  548. X0045[06]: @> Close name. 
  549. X0045[08]: @( Open param. 
  550. X0045[10]: @" Quote. 
  551. X0045[12]: Text. Text scrap[Grey]="Toucan"
  552. X0045[18]: @" Quote. 
  553. X0045[20]: Text. Text scrap[White]="   "
  554. X0045[23]: @, Comma. 
  555. X0045[25]: Text. Text scrap[Grey]="Teapot"
  556. X0045[31]: @} Close param. 
  557. X0045[33]: Text. Text scrap[White]="<010>
  558. X"
  559. X0046[01]: @< Open name. 
  560. X0046[03]: Text. Text scrap[Grey]="Three"
  561. X0046[08]: @> Close name. 
  562. X0046[10]: @( Open param. 
  563. X0046[12]: @" Quote. 
  564. X0046[14]: Text. Text scrap[Grey]="Toucan"
  565. X0046[20]: @" Quote. 
  566. X0046[22]: Text. Text scrap[White]=" "
  567. X0046[23]: @, Comma. 
  568. X0046[25]: Text. Text scrap[White]="<010>
  569. X           "
  570. X0047[12]: @" Quote. 
  571. X0047[14]: Text. Text scrap[Grey]="Teapot"
  572. X0047[20]: @" Quote. 
  573. X0047[22]: Text. Text scrap[White]=" "
  574. X0047[23]: @, Comma. 
  575. X0047[25]: Text. Text scrap[Grey]="Walrus"
  576. X0047[31]: @} Close param. 
  577. X0047[33]: Text. Text scrap[White]="<010>
  578. X"
  579. X0048[01]: @< Open name. 
  580. X0048[03]: Text. Text scrap[Grey]="Nine"
  581. X0048[07]: @> Close name. 
  582. X0048[09]: @( Open param. 
  583. X0048[11]: Text. Text scrap[White]=" "
  584. X0048[12]: @" Quote. 
  585. X0048[14]: Text. Text scrap[Grey]="Toucan"
  586. X0048[20]: @" Quote. 
  587. X0048[22]: Text. Text scrap[White]=" "
  588. X0048[23]: @, Comma. 
  589. X0048[25]: Text. Text scrap[White]=" "
  590. X0048[26]: @" Quote. 
  591. X0048[28]: Text. Text scrap[Grey]="Teapot"
  592. X0048[34]: @" Quote. 
  593. X0048[36]: Text. Text scrap[White]=" "
  594. X0048[37]: @, Comma. 
  595. X0048[39]: Text. Text scrap[Grey]="   Walrus   "
  596. X0048[51]: @, Comma. 
  597. X0048[53]: Text. Text scrap[White]="<010>
  598. X           "
  599. X0049[12]: @" Quote. 
  600. X0049[14]: Text. Text scrap[Grey]="Toucan"
  601. X0049[20]: @" Quote. 
  602. X0049[22]: Text. Text scrap[White]=" "
  603. X0049[23]: @, Comma. 
  604. X0049[25]: Text. Text scrap[Grey]="   Teapot   "
  605. X0049[37]: @, Comma. 
  606. X0049[39]: Text. Text scrap[White]=" "
  607. X0049[40]: @" Quote. 
  608. X0049[42]: Text. Text scrap[Grey]="Walrus"
  609. X0049[48]: @" Quote. 
  610. X0049[50]: Text. Text scrap[White]=" "
  611. X0049[51]: @, Comma. 
  612. X0049[53]: Text. Text scrap[White]="<010>
  613. X           "
  614. X0050[12]: @" Quote. 
  615. X0050[14]: Text. Text scrap[Grey]="Toucan"
  616. X0050[20]: @" Quote. 
  617. X0050[22]: Text. Text scrap[White]=" "
  618. X0050[23]: @, Comma. 
  619. X0050[25]: Text. Text scrap[White]=" "
  620. X0050[26]: @" Quote. 
  621. X0050[28]: Text. Text scrap[Grey]="Teapot"
  622. X0050[34]: @" Quote. 
  623. X0050[36]: Text. Text scrap[White]=" "
  624. X0050[37]: @, Comma. 
  625. X0050[39]: Text. Text scrap[White]=" "
  626. X0050[40]: @" Quote. 
  627. X0050[42]: Text. Text scrap[Grey]="Walrus"
  628. X0050[48]: @" Quote. 
  629. X0050[50]: Text. Text scrap[White]=" "
  630. X0050[51]: @} Close param. 
  631. X0050[53]: Text. Text scrap[White]="<010>
  632. X<010>
  633. X"
  634. X0052[01]: @} Close defn. 
  635. X0052[03]: Text. Text scrap[White]=" "
  636. X0053[01]: Text. Text scrap[Grey]="<010>
  637. X8. Test macro calls with a variety of syntax errors in parameter list.<010>
  638. X"
  639. X0055[01]: @$ Macro defn. 
  640. X0055[03]: @< Open name. 
  641. X0055[05]: Text. Text scrap[Grey]="Error1"
  642. X0055[11]: @> Close name. 
  643. X0055[13]: @{ Open defn. 
  644. X0055[15]: Text. Text scrap[White]="<010>
  645. X"
  646. X0056[01]: @< Open name. 
  647. X0056[03]: Text. Text scrap[Grey]="Zero"
  648. X0056[07]: @> Close name. 
  649. X0056[09]: @( Open param. 
  650. X0056[11]: Text. Text scrap[White]="<010>
  651. X"
  652. X0057[01]: @} Close defn. 
  653. X0057[03]: Text. Text scrap[White]="<010>
  654. X"
  655. X0058[01]: @A New section (Level 1). 
  656. X0058[03]: @< Open name. 
  657. X0058[05]: Text. Text scrap[Grey]="Error recovery point"
  658. X0058[25]: @> Close name. 
  659. X0058[27]: Text. Text scrap[White]="<010>
  660. X<010>
  661. X"
  662. X0060[01]: @$ Macro defn. 
  663. X0060[03]: @< Open name. 
  664. X0060[05]: Text. Text scrap[Grey]="Error2"
  665. X0060[11]: @> Close name. 
  666. X0060[13]: @{ Open defn. 
  667. X0060[15]: Text. Text scrap[White]="<010>
  668. X"
  669. X0061[01]: @< Open name. 
  670. X0061[03]: Text. Text scrap[Grey]="Zero"
  671. X0061[07]: @> Close name. 
  672. X0061[09]: @} Close param. 
  673. X0061[11]: Text. Text scrap[White]="<010>
  674. X"
  675. X0062[01]: @} Close defn. 
  676. X0062[03]: Text. Text scrap[White]="<010>
  677. X"
  678. X0063[01]: @A New section (Level 1). 
  679. X0063[03]: @< Open name. 
  680. X0063[05]: Text. Text scrap[Grey]="Error recovery point"
  681. X0063[25]: @> Close name. 
  682. X0063[27]: Text. Text scrap[White]="<010>
  683. X<010>
  684. X"
  685. X0065[01]: @$ Macro defn. 
  686. X0065[03]: @< Open name. 
  687. X0065[05]: Text. Text scrap[Grey]="Error3"
  688. X0065[11]: @> Close name. 
  689. X0065[13]: @{ Open defn. 
  690. X0065[15]: Text. Text scrap[White]="<010>
  691. X"
  692. X0066[01]: @< Open name. 
  693. X0066[03]: Text. Text scrap[Grey]="One"
  694. X0066[06]: @> Close name. 
  695. X0066[08]: @( Open param. 
  696. X0066[10]: @" Quote. 
  697. X0066[12]: Text. Text scrap[Grey]="Toucan"
  698. X0066[18]: @} Close param. 
  699. X0066[20]: Text. Text scrap[White]="<010>
  700. X"
  701. X0067[01]: @} Close defn. 
  702. X0067[03]: Text. Text scrap[White]="<010>
  703. X"
  704. X0068[01]: @A New section (Level 1). 
  705. X0068[03]: @< Open name. 
  706. X0068[05]: Text. Text scrap[Grey]="Error recovery point"
  707. X0068[25]: @> Close name. 
  708. X0068[27]: Text. Text scrap[White]="<010>
  709. X<010>
  710. X"
  711. X0070[01]: @$ Macro defn. 
  712. X0070[03]: @< Open name. 
  713. X0070[05]: Text. Text scrap[Grey]="Error4"
  714. X0070[11]: @> Close name. 
  715. X0070[13]: @{ Open defn. 
  716. X0070[15]: Text. Text scrap[White]="<010>
  717. X"
  718. X0071[01]: @< Open name. 
  719. X0071[03]: Text. Text scrap[Grey]="One"
  720. X0071[06]: @> Close name. 
  721. X0071[08]: @( Open param. 
  722. X0071[10]: @" Quote. 
  723. X0071[12]: Text. Text scrap[Grey]="Toucan"
  724. X0071[18]: @" Quote. 
  725. X0071[20]: @" Quote. 
  726. X0071[22]: Text. Text scrap[Grey]="Sloth"
  727. X0071[27]: @" Quote. 
  728. X0071[29]: @} Close param. 
  729. X0071[31]: Text. Text scrap[White]="<010>
  730. X"
  731. X0072[01]: @} Close defn. 
  732. X0072[03]: Text. Text scrap[White]="<010>
  733. X"
  734. X0073[01]: @A New section (Level 1). 
  735. X0073[03]: @< Open name. 
  736. X0073[05]: Text. Text scrap[Grey]="Error recovery point"
  737. X0073[25]: @> Close name. 
  738. X0073[27]: Text. Text scrap[White]="<010>
  739. X<010>
  740. X"
  741. X0075[01]: @$ Macro defn. 
  742. X0075[03]: @< Open name. 
  743. X0075[05]: Text. Text scrap[Grey]="Error5"
  744. X0075[11]: @> Close name. 
  745. X0075[13]: @{ Open defn. 
  746. X0075[15]: Text. Text scrap[White]="<010>
  747. X"
  748. X0076[01]: @< Open name. 
  749. X0076[03]: Text. Text scrap[Grey]="Two"
  750. X0076[06]: @> Close name. 
  751. X0076[08]: @( Open param. 
  752. X0076[10]: @" Quote. 
  753. X0076[12]: Text. Text scrap[Grey]="Toucan"
  754. X0076[18]: @" Quote. 
  755. X0076[20]: Text. Text scrap[Grey]="Teapot"
  756. X0076[26]: @} Close param. 
  757. X0076[28]: Text. Text scrap[White]="<010>
  758. X"
  759. X0077[01]: @} Close defn. 
  760. X0077[03]: Text. Text scrap[White]="<010>
  761. X"
  762. X0078[01]: @A New section (Level 1). 
  763. X0078[03]: @< Open name. 
  764. X0078[05]: Text. Text scrap[Grey]="Error recovery point"
  765. X0078[25]: @> Close name. 
  766. X0078[27]: Text. Text scrap[White]="<010>
  767. X<010>
  768. X"
  769. X0080[01]: @$ Macro defn. 
  770. X0080[03]: @< Open name. 
  771. X0080[05]: Text. Text scrap[Grey]="Error6"
  772. X0080[11]: @> Close name. 
  773. X0080[13]: @{ Open defn. 
  774. X0080[15]: Text. Text scrap[White]="<010>
  775. X"
  776. X0081[01]: @< Open name. 
  777. X0081[03]: Text. Text scrap[Grey]="Two"
  778. X0081[06]: @> Close name. 
  779. X0081[08]: @( Open param. 
  780. X0081[10]: @" Quote. 
  781. X0081[12]: Text. Text scrap[Grey]="Toucan"
  782. X0081[18]: @" Quote. 
  783. X0081[20]: Text. Text scrap[Grey]="Teapot<010>
  784. X"
  785. X0082[01]: @} Close defn. 
  786. X0082[03]: Text. Text scrap[White]="<010>
  787. X"
  788. X0083[01]: @A New section (Level 1). 
  789. X0083[03]: @< Open name. 
  790. X0083[05]: Text. Text scrap[Grey]="Error recovery point"
  791. X0083[25]: @> Close name. 
  792. X0083[27]: Text. Text scrap[White]="<010>
  793. X<010>
  794. X"
  795. X0085[01]: @$ Macro defn. 
  796. X0085[03]: @< Open name. 
  797. X0085[05]: Text. Text scrap[Grey]="Error7"
  798. X0085[11]: @> Close name. 
  799. X0085[13]: @{ Open defn. 
  800. X0085[15]: Text. Text scrap[White]="<010>
  801. X"
  802. X0086[01]: @< Open name. 
  803. X0086[03]: Text. Text scrap[Grey]="Two"
  804. X0086[06]: @> Close name. 
  805. X0086[08]: @( Open param. 
  806. X0086[10]: @" Quote. 
  807. X0086[12]: Text. Text scrap[Grey]="Toucan"
  808. X0086[18]: @" Quote. 
  809. X0086[20]: Text. Text scrap[Grey]="Teapot<010>
  810. X"
  811. X0087[01]: @< Open name. 
  812. X0087[03]: Text. Text scrap[Grey]="Three"
  813. X0087[08]: @> Close name. 
  814. X0087[10]: @( Open param. 
  815. X0087[12]: Text. Text scrap[Grey]="Toucan"
  816. X0087[18]: @, Comma. 
  817. X0087[20]: Text. Text scrap[White]="<010>
  818. X           "
  819. X0088[12]: @" Quote. 
  820. X0088[14]: Text. Text scrap[Grey]="Teapot"
  821. X0088[20]: @, Comma. 
  822. X0088[22]: Text. Text scrap[Grey]="Walrus<010>
  823. X<010>
  824. X"
  825. X0090[01]: @} Close defn. 
  826. X0090[03]: Text. Text scrap[White]="<010>
  827. X"
  828. X0091[01]: @A New section (Level 1). 
  829. X0091[03]: @< Open name. 
  830. X0091[05]: Text. Text scrap[Grey]="Error recovery point"
  831. X0091[25]: @> Close name. 
  832. X0091[27]: Text. Text scrap[White]="<010>
  833. X<010>
  834. X"
  835. X0093[01]: End Of File. 
  836. X============================ End of TOKEN LIST DUMP ============================
  837. X
  838. X
  839. X========================== Start of MACRO TABLE DUMP ===========================
  840. X
  841. X
  842. X------------------- Start of Macro Dump --------------------
  843. Macro Name  : """
  844. Defined?    : Yes.
  845. Parameters  : 0
  846. Additive?   : No.
  847. Zero Calls? : No.
  848. Many Calls? : No.
  849. Output File?: No.
  850. Call list   :
  851. X   Call 1: Parameters=0, Sequence num=7, Position(L,C)=(22,1).
  852. Macro body  :
  853. X
  854. X--Start of List of Body Parts--
  855. This macro has 1 body part.
  856. Body part 1: Seqnum=6, Pos(L,C)=(13,3), Expression follows:
  857. X
  858. X---- Start of Expression ----
  859. X----- End of Expression -----
  860. X
  861. X---End of List of Body Parts---
  862. X
  863. X-------------------- End of Macro Dump ---------------------
  864. X
  865. X
  866. X
  867. X------------------- Start of Macro Dump --------------------
  868. Macro Name  : "Error1"
  869. Defined?    : Yes.
  870. Parameters  : 0
  871. Additive?   : No.
  872. Zero Calls? : No.
  873. Many Calls? : No.
  874. Output File?: No.
  875. Call list   :
  876. Macro body  :
  877. X
  878. X--Start of List of Body Parts--
  879. This macro has 0 body parts.
  880. X---End of List of Body Parts---
  881. X
  882. X-------------------- End of Macro Dump ---------------------
  883. X
  884. X
  885. X
  886. X------------------- Start of Macro Dump --------------------
  887. Macro Name  : "Error2"
  888. Defined?    : Yes.
  889. Parameters  : 0
  890. Additive?   : No.
  891. Zero Calls? : No.
  892. Many Calls? : No.
  893. Output File?: No.
  894. Call list   :
  895. Macro body  :
  896. X
  897. X--Start of List of Body Parts--
  898. This macro has 0 body parts.
  899. X---End of List of Body Parts---
  900. X
  901. X-------------------- End of Macro Dump ---------------------
  902. X
  903. X
  904. X
  905. X------------------- Start of Macro Dump --------------------
  906. Macro Name  : "Error3"
  907. Defined?    : Yes.
  908. Parameters  : 0
  909. Additive?   : No.
  910. Zero Calls? : No.
  911. Many Calls? : No.
  912. Output File?: No.
  913. Call list   :
  914. Macro body  :
  915. X
  916. X--Start of List of Body Parts--
  917. This macro has 0 body parts.
  918. X---End of List of Body Parts---
  919. X
  920. X-------------------- End of Macro Dump ---------------------
  921. X
  922. X
  923. X
  924. X------------------- Start of Macro Dump --------------------
  925. Macro Name  : "Error4"
  926. Defined?    : Yes.
  927. Parameters  : 0
  928. Additive?   : No.
  929. Zero Calls? : No.
  930. Many Calls? : No.
  931. Output File?: No.
  932. Call list   :
  933. Macro body  :
  934. X
  935. X--Start of List of Body Parts--
  936. This macro has 0 body parts.
  937. X---End of List of Body Parts---
  938. X
  939. X-------------------- End of Macro Dump ---------------------
  940. X
  941. X
  942. X
  943. X------------------- Start of Macro Dump --------------------
  944. Macro Name  : "Error5"
  945. Defined?    : Yes.
  946. Parameters  : 0
  947. Additive?   : No.
  948. Zero Calls? : No.
  949. Many Calls? : No.
  950. Output File?: No.
  951. Call list   :
  952. Macro body  :
  953. X
  954. X--Start of List of Body Parts--
  955. This macro has 1 body part.
  956. Body part 1: Seqnum=8, Pos(L,C)=(75,3), Expression follows:
  957. X
  958. X---- Start of Expression ----
  959. X
  960. X----- Start Text Element -----
  961. Text scrap[White]="<010>
  962. X"
  963. X------ End Text Element ------
  964. X
  965. X
  966. X-- Begin Invocation Element --
  967. Invocation of macro @<Two@>
  968. This invocation has 1 actual parameters.
  969. Actual parameter list follows as a sequence of expressions:
  970. X(Text crud before and after parameter has been omitted).
  971. XExpression for parameter number 1:
  972. X
  973. X---- Start of Expression ----
  974. X
  975. X----- Start Text Element -----
  976. Text scrap[Grey]="Toucan"
  977. X------ End Text Element ------
  978. X
  979. X----- End of Expression -----
  980. X
  981. X--- End Invocation Element ---
  982. X
  983. X
  984. X----- Start Text Element -----
  985. Text scrap[White]="<010>
  986. X"
  987. X------ End Text Element ------
  988. X
  989. X----- End of Expression -----
  990. X
  991. X---End of List of Body Parts---
  992. X
  993. X-------------------- End of Macro Dump ---------------------
  994. X
  995. X
  996. X
  997. X------------------- Start of Macro Dump --------------------
  998. Macro Name  : "Error6"
  999. Defined?    : Yes.
  1000. Parameters  : 0
  1001. Additive?   : No.
  1002. Zero Calls? : No.
  1003. Many Calls? : No.
  1004. Output File?: No.
  1005. Call list   :
  1006. Macro body  :
  1007. X
  1008. X--Start of List of Body Parts--
  1009. This macro has 0 body parts.
  1010. X---End of List of Body Parts---
  1011. X
  1012. X-------------------- End of Macro Dump ---------------------
  1013. X
  1014. X
  1015. X
  1016. X------------------- Start of Macro Dump --------------------
  1017. Macro Name  : "Error7"
  1018. Defined?    : Yes.
  1019. Parameters  : 0
  1020. Additive?   : No.
  1021. Zero Calls? : No.
  1022. Many Calls? : No.
  1023. Output File?: No.
  1024. Call list   :
  1025. Macro body  :
  1026. X
  1027. X--Start of List of Body Parts--
  1028. This macro has 0 body parts.
  1029. X---End of List of Body Parts---
  1030. X
  1031. X-------------------- End of Macro Dump ---------------------
  1032. X
  1033. X
  1034. X
  1035. X------------------- Start of Macro Dump --------------------
  1036. Macro Name  : "Macro containing the test macro calls."
  1037. Defined?    : Yes.
  1038. Parameters  : 0
  1039. Additive?   : No.
  1040. Zero Calls? : No.
  1041. Many Calls? : No.
  1042. Output File?: No.
  1043. Call list   :
  1044. Macro body  :
  1045. X
  1046. X--Start of List of Body Parts--
  1047. This macro has 1 body part.
  1048. Body part 1: Seqnum=7, Pos(L,C)=(17,3), Expression follows:
  1049. X
  1050. X---- Start of Expression ----
  1051. X
  1052. X----- Start Text Element -----
  1053. Text scrap[Grey]="<010>
  1054. X1. Test macro call with no parameter list.<010>
  1055. X"
  1056. X------ End Text Element ------
  1057. X
  1058. X
  1059. X-- Begin Invocation Element --
  1060. Invocation of macro @<Zero@>
  1061. No actual parameters.
  1062. X--- End Invocation Element ---
  1063. X
  1064. X
  1065. X----- Start Text Element -----
  1066. Text scrap[Grey]="<010>
  1067. X<010>
  1068. X2. Test macro call with quick name.<010>
  1069. X"
  1070. X------ End Text Element ------
  1071. X
  1072. X
  1073. X-- Begin Invocation Element --
  1074. Invocation of macro @<"@>
  1075. No actual parameters.
  1076. X--- End Invocation Element ---
  1077. X
  1078. X
  1079. X----- Start Text Element -----
  1080. Text scrap[Grey]="<010>
  1081. X<010>
  1082. X3. Test macro call with one parameter.<010>
  1083. X"
  1084. X------ End Text Element ------
  1085. X
  1086. X
  1087. X-- Begin Invocation Element --
  1088. Invocation of macro @<One@>
  1089. This invocation has 1 actual parameters.
  1090. Actual parameter list follows as a sequence of expressions:
  1091. X(Text crud before and after parameter has been omitted).
  1092. XExpression for parameter number 1:
  1093. X
  1094. X---- Start of Expression ----
  1095. X
  1096. X----- Start Text Element -----
  1097. Text scrap[Grey]="Toucan"
  1098. X------ End Text Element ------
  1099. X
  1100. X----- End of Expression -----
  1101. X
  1102. X--- End Invocation Element ---
  1103. X
  1104. X
  1105. X----- Start Text Element -----
  1106. Text scrap[Grey]="<010>
  1107. X<010>
  1108. X4. Test macro call with many parameters.<010>
  1109. X"
  1110. X------ End Text Element ------
  1111. X
  1112. X
  1113. X-- Begin Invocation Element --
  1114. Invocation of macro @<Two@>
  1115. This invocation has 2 actual parameters.
  1116. Actual parameter list follows as a sequence of expressions:
  1117. X(Text crud before and after parameter has been omitted).
  1118. XExpression for parameter number 1:
  1119. X
  1120. X---- Start of Expression ----
  1121. X
  1122. X----- Start Text Element -----
  1123. Text scrap[Grey]="Toucan"
  1124. X------ End Text Element ------
  1125. X
  1126. X----- End of Expression -----
  1127. X
  1128. XExpression for parameter number 2:
  1129. X
  1130. X---- Start of Expression ----
  1131. X
  1132. X----- Start Text Element -----
  1133. Text scrap[Grey]="Teapot"
  1134. X------ End Text Element ------
  1135. X
  1136. X----- End of Expression -----
  1137. X
  1138. X--- End Invocation Element ---
  1139. X
  1140. X
  1141. X----- Start Text Element -----
  1142. Text scrap[White]="<010>
  1143. X"
  1144. X------ End Text Element ------
  1145. X
  1146. X
  1147. X-- Begin Invocation Element --
  1148. Invocation of macro @<Three@>
  1149. This invocation has 3 actual parameters.
  1150. Actual parameter list follows as a sequence of expressions:
  1151. X(Text crud before and after parameter has been omitted).
  1152. XExpression for parameter number 1:
  1153. X
  1154. X---- Start of Expression ----
  1155. X
  1156. X----- Start Text Element -----
  1157. Text scrap[Grey]="Toucan"
  1158. X------ End Text Element ------
  1159. X
  1160. X----- End of Expression -----
  1161. X
  1162. XExpression for parameter number 2:
  1163. X
  1164. X---- Start of Expression ----
  1165. X
  1166. X----- Start Text Element -----
  1167. Text scrap[Grey]="Teapot"
  1168. X------ End Text Element ------
  1169. X
  1170. X----- End of Expression -----
  1171. X
  1172. XExpression for parameter number 3:
  1173. X
  1174. X---- Start of Expression ----
  1175. X
  1176. X----- Start Text Element -----
  1177. Text scrap[Grey]="Walrus"
  1178. X------ End Text Element ------
  1179. X
  1180. X----- End of Expression -----
  1181. X
  1182. X--- End Invocation Element ---
  1183. X
  1184. X
  1185. X----- Start Text Element -----
  1186. Text scrap[White]="<010>
  1187. X"
  1188. X------ End Text Element ------
  1189. X
  1190. X
  1191. X-- Begin Invocation Element --
  1192. Invocation of macro @<Nine@>
  1193. This invocation has 9 actual parameters.
  1194. Actual parameter list follows as a sequence of expressions:
  1195. X(Text crud before and after parameter has been omitted).
  1196. XExpression for parameter number 1:
  1197. X
  1198. X---- Start of Expression ----
  1199. X
  1200. X----- Start Text Element -----
  1201. Text scrap[Grey]="Toucan"
  1202. X------ End Text Element ------
  1203. X
  1204. X----- End of Expression -----
  1205. X
  1206. XExpression for parameter number 2:
  1207. X
  1208. X---- Start of Expression ----
  1209. X
  1210. X----- Start Text Element -----
  1211. Text scrap[Grey]="Teapot"
  1212. X------ End Text Element ------
  1213. X
  1214. X----- End of Expression -----
  1215. X
  1216. XExpression for parameter number 3:
  1217. X
  1218. X---- Start of Expression ----
  1219. X
  1220. X----- Start Text Element -----
  1221. Text scrap[Grey]="Walrus"
  1222. X------ End Text Element ------
  1223. X
  1224. X----- End of Expression -----
  1225. X
  1226. XExpression for parameter number 4:
  1227. X
  1228. X---- Start of Expression ----
  1229. X
  1230. X----- Start Text Element -----
  1231. Text scrap[Grey]="<010>
  1232. X          Toucan"
  1233. X------ End Text Element ------
  1234. X
  1235. X----- End of Expression -----
  1236. X
  1237. XExpression for parameter number 5:
  1238. X
  1239. X---- Start of Expression ----
  1240. X
  1241. X----- Start Text Element -----
  1242. Text scrap[Grey]="Teapot"
  1243. X------ End Text Element ------
  1244. X
  1245. X----- End of Expression -----
  1246. X
  1247. XExpression for parameter number 6:
  1248. X
  1249. X---- Start of Expression ----
  1250. X
  1251. X----- Start Text Element -----
  1252. Text scrap[Grey]="Walrus"
  1253. X------ End Text Element ------
  1254. X
  1255. X----- End of Expression -----
  1256. X
  1257. XExpression for parameter number 7:
  1258. X
  1259. X---- Start of Expression ----
  1260. X
  1261. X----- Start Text Element -----
  1262. Text scrap[Grey]="<010>
  1263. X          Toucan"
  1264. X------ End Text Element ------
  1265. X
  1266. X----- End of Expression -----
  1267. X
  1268. XExpression for parameter number 8:
  1269. X
  1270. X---- Start of Expression ----
  1271. X
  1272. X----- Start Text Element -----
  1273. Text scrap[Grey]="Teapot"
  1274. X------ End Text Element ------
  1275. X
  1276. X----- End of Expression -----
  1277. X
  1278. XExpression for parameter number 9:
  1279. X
  1280. X---- Start of Expression ----
  1281. X
  1282. X----- Start Text Element -----
  1283. Text scrap[Grey]="Walrus"
  1284. X------ End Text Element ------
  1285. X
  1286. X----- End of Expression -----
  1287. X
  1288. X--- End Invocation Element ---
  1289. X
  1290. X
  1291. X----- Start Text Element -----
  1292. Text scrap[Grey]="<010>
  1293. X<010>
  1294. X5. Test macro calls with double quotes on parameters.<010>
  1295. X"
  1296. X------ End Text Element ------
  1297. X
  1298. X
  1299. X-- Begin Invocation Element --
  1300. Invocation of macro @<One@>
  1301. This invocation has 1 actual parameters.
  1302. Actual parameter list follows as a sequence of expressions:
  1303. X(Text crud before and after parameter has been omitted).
  1304. XExpression for parameter number 1:
  1305. X
  1306. X---- Start of Expression ----
  1307. X
  1308. X----- Start Text Element -----
  1309. Text scrap[Grey]="Toucan"
  1310. X------ End Text Element ------
  1311. X
  1312. X----- End of Expression -----
  1313. X
  1314. X--- End Invocation Element ---
  1315. X
  1316. X
  1317. X----- Start Text Element -----
  1318. Text scrap[White]="<010>
  1319. X"
  1320. X------ End Text Element ------
  1321. X
  1322. X
  1323. X-- Begin Invocation Element --
  1324. Invocation of macro @<Two@>
  1325. This invocation has 2 actual parameters.
  1326. Actual parameter list follows as a sequence of expressions:
  1327. X(Text crud before and after parameter has been omitted).
  1328. XExpression for parameter number 1:
  1329. X
  1330. X---- Start of Expression ----
  1331. X
  1332. X----- Start Text Element -----
  1333. Text scrap[Grey]="Toucan"
  1334. X------ End Text Element ------
  1335. X
  1336. X----- End of Expression -----
  1337. X
  1338. XExpression for parameter number 2:
  1339. X
  1340. X---- Start of Expression ----
  1341. X
  1342. X----- Start Text Element -----
  1343. Text scrap[Grey]="Teapot"
  1344. X------ End Text Element ------
  1345. X
  1346. X----- End of Expression -----
  1347. X
  1348. X--- End Invocation Element ---
  1349. X
  1350. X
  1351. X----- Start Text Element -----
  1352. Text scrap[White]="<010>
  1353. X"
  1354. X------ End Text Element ------
  1355. X
  1356. X
  1357. X-- Begin Invocation Element --
  1358. Invocation of macro @<Three@>
  1359. This invocation has 3 actual parameters.
  1360. Actual parameter list follows as a sequence of expressions:
  1361. X(Text crud before and after parameter has been omitted).
  1362. XExpression for parameter number 1:
  1363. X
  1364. X---- Start of Expression ----
  1365. X
  1366. X----- Start Text Element -----
  1367. Text scrap[Grey]="Toucan"
  1368. X------ End Text Element ------
  1369. X
  1370. X----- End of Expression -----
  1371. X
  1372. XExpression for parameter number 2:
  1373. X
  1374. X---- Start of Expression ----
  1375. X
  1376. X----- Start Text Element -----
  1377. Text scrap[Grey]="Teapot"
  1378. X------ End Text Element ------
  1379. X
  1380. X----- End of Expression -----
  1381. X
  1382. XExpression for parameter number 3:
  1383. X
  1384. X---- Start of Expression ----
  1385. X
  1386. X----- Start Text Element -----
  1387. Text scrap[Grey]="Walrus"
  1388. X------ End Text Element ------
  1389. X
  1390. X----- End of Expression -----
  1391. X
  1392. X--- End Invocation Element ---
  1393. X
  1394. X
  1395. X----- Start Text Element -----
  1396. Text scrap[White]="<010>
  1397. X"
  1398. X------ End Text Element ------
  1399. X
  1400. X
  1401. X-- Begin Invocation Element --
  1402. Invocation of macro @<Nine@>
  1403. This invocation has 9 actual parameters.
  1404. Actual parameter list follows as a sequence of expressions:
  1405. X(Text crud before and after parameter has been omitted).
  1406. XExpression for parameter number 1:
  1407. X
  1408. X---- Start of Expression ----
  1409. X
  1410. X----- Start Text Element -----
  1411. Text scrap[Grey]="Toucan"
  1412. X------ End Text Element ------
  1413. X
  1414. X----- End of Expression -----
  1415. X
  1416. XExpression for parameter number 2:
  1417. X
  1418. X---- Start of Expression ----
  1419. X
  1420. X----- Start Text Element -----
  1421. Text scrap[Grey]="Teapot"
  1422. X------ End Text Element ------
  1423. X
  1424. X----- End of Expression -----
  1425. X
  1426. XExpression for parameter number 3:
  1427. X
  1428. X---- Start of Expression ----
  1429. X
  1430. X----- Start Text Element -----
  1431. Text scrap[Grey]="Walrus"
  1432. X------ End Text Element ------
  1433. X
  1434. X----- End of Expression -----
  1435. X
  1436. XExpression for parameter number 4:
  1437. X
  1438. X---- Start of Expression ----
  1439. X
  1440. X----- Start Text Element -----
  1441. Text scrap[Grey]="Toucan"
  1442. X------ End Text Element ------
  1443. X
  1444. X----- End of Expression -----
  1445. X
  1446. XExpression for parameter number 5:
  1447. X
  1448. X---- Start of Expression ----
  1449. X
  1450. X----- Start Text Element -----
  1451. Text scrap[Grey]="Teapot"
  1452. X------ End Text Element ------
  1453. X
  1454. X----- End of Expression -----
  1455. X
  1456. XExpression for parameter number 6:
  1457. X
  1458. X---- Start of Expression ----
  1459. X
  1460. X----- Start Text Element -----
  1461. Text scrap[Grey]="Walrus"
  1462. X------ End Text Element ------
  1463. X
  1464. X----- End of Expression -----
  1465. X
  1466. XExpression for parameter number 7:
  1467. X
  1468. X---- Start of Expression ----
  1469. X
  1470. X----- Start Text Element -----
  1471. Text scrap[Grey]="Toucan"
  1472. X------ End Text Element ------
  1473. X
  1474. X----- End of Expression -----
  1475. X
  1476. XExpression for parameter number 8:
  1477. X
  1478. X---- Start of Expression ----
  1479. X
  1480. X----- Start Text Element -----
  1481. Text scrap[Grey]="Teapot"
  1482. X------ End Text Element ------
  1483. X
  1484. X----- End of Expression -----
  1485. X
  1486. XExpression for parameter number 9:
  1487. X
  1488. X---- Start of Expression ----
  1489. X
  1490. X----- Start Text Element -----
  1491. Text scrap[Grey]="Walrus"
  1492. X------ End Text Element ------
  1493. X
  1494. X----- End of Expression -----
  1495. X
  1496. X--- End Invocation Element ---
  1497. X
  1498. X
  1499. X----- Start Text Element -----
  1500. Text scrap[Grey]="<010>
  1501. X<010>
  1502. X7. Test macro calls with mixed double quotes on parameters.<010>
  1503. X"
  1504. X------ End Text Element ------
  1505. X
  1506. X
  1507. X-- Begin Invocation Element --
  1508. Invocation of macro @<Two@>
  1509. This invocation has 2 actual parameters.
  1510. Actual parameter list follows as a sequence of expressions:
  1511. X(Text crud before and after parameter has been omitted).
  1512. XExpression for parameter number 1:
  1513. X
  1514. X---- Start of Expression ----
  1515. X
  1516. X----- Start Text Element -----
  1517. Text scrap[Grey]="Toucan"
  1518. X------ End Text Element ------
  1519. X
  1520. X----- End of Expression -----
  1521. X
  1522. XExpression for parameter number 2:
  1523. X
  1524. X---- Start of Expression ----
  1525. X
  1526. X----- Start Text Element -----
  1527. Text scrap[Grey]="Teapot"
  1528. X------ End Text Element ------
  1529. X
  1530. X----- End of Expression -----
  1531. X
  1532. X--- End Invocation Element ---
  1533. X
  1534. X
  1535. X----- Start Text Element -----
  1536. Text scrap[White]="<010>
  1537. X"
  1538. X------ End Text Element ------
  1539. X
  1540. X
  1541. X-- Begin Invocation Element --
  1542. Invocation of macro @<Three@>
  1543. This invocation has 3 actual parameters.
  1544. Actual parameter list follows as a sequence of expressions:
  1545. X(Text crud before and after parameter has been omitted).
  1546. XExpression for parameter number 1:
  1547. X
  1548. X---- Start of Expression ----
  1549. X
  1550. X----- Start Text Element -----
  1551. Text scrap[Grey]="Toucan"
  1552. X------ End Text Element ------
  1553. X
  1554. X----- End of Expression -----
  1555. X
  1556. XExpression for parameter number 2:
  1557. X
  1558. X---- Start of Expression ----
  1559. X
  1560. X----- Start Text Element -----
  1561. Text scrap[Grey]="Teapot"
  1562. X------ End Text Element ------
  1563. X
  1564. X----- End of Expression -----
  1565. X
  1566. XExpression for parameter number 3:
  1567. X
  1568. X---- Start of Expression ----
  1569. X
  1570. X----- Start Text Element -----
  1571. Text scrap[Grey]="Walrus"
  1572. X------ End Text Element ------
  1573. X
  1574. X----- End of Expression -----
  1575. X
  1576. X--- End Invocation Element ---
  1577. X
  1578. X
  1579. X----- Start Text Element -----
  1580. Text scrap[White]="<010>
  1581. X"
  1582. X------ End Text Element ------
  1583. X
  1584. X
  1585. X-- Begin Invocation Element --
  1586. Invocation of macro @<Nine@>
  1587. This invocation has 9 actual parameters.
  1588. Actual parameter list follows as a sequence of expressions:
  1589. X(Text crud before and after parameter has been omitted).
  1590. XExpression for parameter number 1:
  1591. X
  1592. X---- Start of Expression ----
  1593. X
  1594. X----- Start Text Element -----
  1595. Text scrap[Grey]="Toucan"
  1596. X------ End Text Element ------
  1597. X
  1598. X----- End of Expression -----
  1599. X
  1600. XExpression for parameter number 2:
  1601. X
  1602. X---- Start of Expression ----
  1603. X
  1604. X----- Start Text Element -----
  1605. Text scrap[Grey]="Teapot"
  1606. X------ End Text Element ------
  1607. X
  1608. X----- End of Expression -----
  1609. X
  1610. XExpression for parameter number 3:
  1611. X
  1612. X---- Start of Expression ----
  1613. X
  1614. X----- Start Text Element -----
  1615. Text scrap[Grey]="   Walrus   "
  1616. X------ End Text Element ------
  1617. X
  1618. X----- End of Expression -----
  1619. X
  1620. XExpression for parameter number 4:
  1621. X
  1622. X---- Start of Expression ----
  1623. X
  1624. X----- Start Text Element -----
  1625. Text scrap[Grey]="Toucan"
  1626. X------ End Text Element ------
  1627. X
  1628. X----- End of Expression -----
  1629. X
  1630. XExpression for parameter number 5:
  1631. X
  1632. X---- Start of Expression ----
  1633. X
  1634. X----- Start Text Element -----
  1635. Text scrap[Grey]="   Teapot   "
  1636. X------ End Text Element ------
  1637. X
  1638. X----- End of Expression -----
  1639. X
  1640. XExpression for parameter number 6:
  1641. X
  1642. X---- Start of Expression ----
  1643. X
  1644. X----- Start Text Element -----
  1645. Text scrap[Grey]="Walrus"
  1646. X------ End Text Element ------
  1647. X
  1648. X----- End of Expression -----
  1649. X
  1650. XExpression for parameter number 7:
  1651. X
  1652. X---- Start of Expression ----
  1653. X
  1654. X----- Start Text Element -----
  1655. Text scrap[Grey]="Toucan"
  1656. X------ End Text Element ------
  1657. X
  1658. X----- End of Expression -----
  1659. X
  1660. XExpression for parameter number 8:
  1661. X
  1662. X---- Start of Expression ----
  1663. X
  1664. X----- Start Text Element -----
  1665. Text scrap[Grey]="Teapot"
  1666. X------ End Text Element ------
  1667. X
  1668. X----- End of Expression -----
  1669. X
  1670. XExpression for parameter number 9:
  1671. X
  1672. X---- Start of Expression ----
  1673. X
  1674. X----- Start Text Element -----
  1675. Text scrap[Grey]="Walrus"
  1676. X------ End Text Element ------
  1677. X
  1678. X----- End of Expression -----
  1679. X
  1680. X--- End Invocation Element ---
  1681. X
  1682. X
  1683. X----- Start Text Element -----
  1684. Text scrap[White]="<010>
  1685. X<010>
  1686. X"
  1687. X------ End Text Element ------
  1688. X
  1689. X----- End of Expression -----
  1690. X
  1691. X---End of List of Body Parts---
  1692. X
  1693. X-------------------- End of Macro Dump ---------------------
  1694. X
  1695. X
  1696. X
  1697. X------------------- Start of Macro Dump --------------------
  1698. Macro Name  : "Nine"
  1699. Defined?    : Yes.
  1700. Parameters  : 9
  1701. Additive?   : No.
  1702. Zero Calls? : No.
  1703. Many Calls? : No.
  1704. Output File?: No.
  1705. Call list   :
  1706. X   Call 1: Parameters=9, Sequence num=7, Position(L,C)=(30,1).
  1707. X   Call 2: Parameters=9, Sequence num=7, Position(L,C)=(40,1).
  1708. X   Call 3: Parameters=9, Sequence num=7, Position(L,C)=(48,1).
  1709. Macro body  :
  1710. X
  1711. X--Start of List of Body Parts--
  1712. This macro has 1 body part.
  1713. Body part 1: Seqnum=5, Pos(L,C)=(12,3), Expression follows:
  1714. X
  1715. X---- Start of Expression ----
  1716. X----- End of Expression -----
  1717. X
  1718. X---End of List of Body Parts---
  1719. X
  1720. X-------------------- End of Macro Dump ---------------------
  1721. X
  1722. X
  1723. X
  1724. X------------------- Start of Macro Dump --------------------
  1725. Macro Name  : "One"
  1726. Defined?    : Yes.
  1727. Parameters  : 1
  1728. Additive?   : No.
  1729. Zero Calls? : No.
  1730. Many Calls? : No.
  1731. Output File?: No.
  1732. Call list   :
  1733. X   Call 1: Parameters=1, Sequence num=7, Position(L,C)=(25,1).
  1734. X   Call 2: Parameters=1, Sequence num=7, Position(L,C)=(35,1).
  1735. Macro body  :
  1736. X
  1737. X--Start of List of Body Parts--
  1738. This macro has 1 body part.
  1739. Body part 1: Seqnum=2, Pos(L,C)=(9,3), Expression follows:
  1740. X
  1741. X---- Start of Expression ----
  1742. X----- End of Expression -----
  1743. X
  1744. X---End of List of Body Parts---
  1745. X
  1746. X-------------------- End of Macro Dump ---------------------
  1747. X
  1748. X
  1749. X
  1750. X------------------- Start of Macro Dump --------------------
  1751. Macro Name  : "Three"
  1752. Defined?    : Yes.
  1753. Parameters  : 3
  1754. Additive?   : No.
  1755. Zero Calls? : No.
  1756. Many Calls? : No.
  1757. Output File?: No.
  1758. Call list   :
  1759. X   Call 1: Parameters=3, Sequence num=7, Position(L,C)=(29,1).
  1760. X   Call 2: Parameters=3, Sequence num=7, Position(L,C)=(37,1).
  1761. X   Call 3: Parameters=3, Sequence num=7, Position(L,C)=(46,1).
  1762. Macro body  :
  1763. X
  1764. X--Start of List of Body Parts--
  1765. This macro has 1 body part.
  1766. Body part 1: Seqnum=4, Pos(L,C)=(11,3), Expression follows:
  1767. X
  1768. X---- Start of Expression ----
  1769. X----- End of Expression -----
  1770. X
  1771. X---End of List of Body Parts---
  1772. X
  1773. X-------------------- End of Macro Dump ---------------------
  1774. X
  1775. X
  1776. X
  1777. X------------------- Start of Macro Dump --------------------
  1778. Macro Name  : "Two"
  1779. Defined?    : Yes.
  1780. Parameters  : 2
  1781. Additive?   : No.
  1782. Zero Calls? : No.
  1783. Many Calls? : No.
  1784. Output File?: No.
  1785. Call list   :
  1786. X   Call 1: Parameters=2, Sequence num=7, Position(L,C)=(28,1).
  1787. X   Call 2: Parameters=2, Sequence num=7, Position(L,C)=(36,1).
  1788. X   Call 3: Parameters=2, Sequence num=7, Position(L,C)=(45,1).
  1789. X   Call 4: Parameters=1, Sequence num=8, Position(L,C)=(76,1).
  1790. Macro body  :
  1791. X
  1792. X--Start of List of Body Parts--
  1793. This macro has 1 body part.
  1794. Body part 1: Seqnum=3, Pos(L,C)=(10,3), Expression follows:
  1795. X
  1796. X---- Start of Expression ----
  1797. X----- End of Expression -----
  1798. X
  1799. X---End of List of Body Parts---
  1800. X
  1801. X-------------------- End of Macro Dump ---------------------
  1802. X
  1803. X
  1804. X
  1805. X------------------- Start of Macro Dump --------------------
  1806. Macro Name  : "Zero"
  1807. Defined?    : Yes.
  1808. Parameters  : 0
  1809. Additive?   : No.
  1810. Zero Calls? : No.
  1811. Many Calls? : No.
  1812. Output File?: No.
  1813. Call list   :
  1814. X   Call 1: Parameters=0, Sequence num=7, Position(L,C)=(19,1).
  1815. X   Call 2: Parameters=0, Sequence num=8, Position(L,C)=(61,1).
  1816. Macro body  :
  1817. X
  1818. X--Start of List of Body Parts--
  1819. This macro has 1 body part.
  1820. Body part 1: Seqnum=1, Pos(L,C)=(8,3), Expression follows:
  1821. X
  1822. X---- Start of Expression ----
  1823. X----- End of Expression -----
  1824. X
  1825. X---End of List of Body Parts---
  1826. X
  1827. X-------------------- End of Macro Dump ---------------------
  1828. X
  1829. X
  1830. X
  1831. X=========================== End of MACRO TABLE DUMP ============================
  1832. X
  1833. X
  1834. X========================= Start of DOCUMENT LIST DUMP ==========================
  1835. X
  1836. X
  1837. TEXT COMPONENT: Pos(L,C)=(1,1). 
  1838. X
  1839. X-- Start of Text Scrap List --
  1840. Text scrap[Grey]="PR09: Test calls and actual parameter lists.<010>
  1841. X<010>
  1842. XFirst trip up the parser so we don't get any further.<010>
  1843. X"
  1844. X--- End of Text Scrap List ---
  1845. X
  1846. X
  1847. TEXT COMPONENT: Pos(L,C)=(4,3). 
  1848. X
  1849. X-- Start of Text Scrap List --
  1850. Text scrap[Grey]="<010>
  1851. X<010>
  1852. Now define some macros to call. No error.<010>
  1853. X<010>
  1854. X"
  1855. X--- End of Text Scrap List ---
  1856. X
  1857. X
  1858. MACRO DEFINITION COMPONENT: Pos(L,C)=(8,1). 
  1859. Part 1 of macro @<Zero@>.
  1860. X
  1861. TEXT COMPONENT: Pos(L,C)=(8,15). 
  1862. X
  1863. X-- Start of Text Scrap List --
  1864. Text scrap[White]="<010>
  1865. X"
  1866. X--- End of Text Scrap List ---
  1867. X
  1868. X
  1869. MACRO DEFINITION COMPONENT: Pos(L,C)=(9,1). 
  1870. Part 1 of macro @<One@>.
  1871. X
  1872. TEXT COMPONENT: Pos(L,C)=(9,20). 
  1873. X
  1874. X-- Start of Text Scrap List --
  1875. Text scrap[White]="<010>
  1876. X"
  1877. X--- End of Text Scrap List ---
  1878. X
  1879. X
  1880. MACRO DEFINITION COMPONENT: Pos(L,C)=(10,1). 
  1881. Part 1 of macro @<Two@>.
  1882. X
  1883. TEXT COMPONENT: Pos(L,C)=(10,20). 
  1884. X
  1885. X-- Start of Text Scrap List --
  1886. Text scrap[White]="<010>
  1887. X"
  1888. X--- End of Text Scrap List ---
  1889. X
  1890. X
  1891. MACRO DEFINITION COMPONENT: Pos(L,C)=(11,1). 
  1892. Part 1 of macro @<Three@>.
  1893. X
  1894. TEXT COMPONENT: Pos(L,C)=(11,22). 
  1895. X
  1896. X-- Start of Text Scrap List --
  1897. Text scrap[White]="<010>
  1898. X"
  1899. X--- End of Text Scrap List ---
  1900. X
  1901. X
  1902. MACRO DEFINITION COMPONENT: Pos(L,C)=(12,1). 
  1903. Part 1 of macro @<Nine@>.
  1904. X
  1905. TEXT COMPONENT: Pos(L,C)=(12,21). 
  1906. X
  1907. X-- Start of Text Scrap List --
  1908. Text scrap[White]="<010>
  1909. X"
  1910. X--- End of Text Scrap List ---
  1911. X
  1912. X
  1913. MACRO DEFINITION COMPONENT: Pos(L,C)=(13,1). 
  1914. Part 1 of macro @<"@>.
  1915. X
  1916. TEXT COMPONENT: Pos(L,C)=(13,10). 
  1917. X
  1918. X-- Start of Text Scrap List --
  1919. Text scrap[Grey]="<010>
  1920. X<010>
  1921. The following test calls should NOT generate any errors.<010>
  1922. X<010>
  1923. X"
  1924. X--- End of Text Scrap List ---
  1925. X
  1926. X
  1927. MACRO DEFINITION COMPONENT: Pos(L,C)=(17,1). 
  1928. Part 1 of macro @<Macro containing the test macro calls.@>.
  1929. X
  1930. TEXT COMPONENT: Pos(L,C)=(52,3). 
  1931. X
  1932. X-- Start of Text Scrap List --
  1933. Text scrap[White]=" "
  1934. Text scrap[Grey]="<010>
  1935. X8. Test macro calls with a variety of syntax errors in parameter list.<010>
  1936. X"
  1937. X--- End of Text Scrap List ---
  1938. X
  1939. X
  1940. TYPESETTER DIRECTIVE COMPONENT: 
  1941. X   Section "1", Section name="Error recovery point".
  1942. X
  1943. TEXT COMPONENT: Pos(L,C)=(58,27). 
  1944. X
  1945. X-- Start of Text Scrap List --
  1946. Text scrap[White]="<010>
  1947. X<010>
  1948. X"
  1949. X--- End of Text Scrap List ---
  1950. X
  1951. X
  1952. TYPESETTER DIRECTIVE COMPONENT: 
  1953. X   Section "2", Section name="Error recovery point".
  1954. X
  1955. TEXT COMPONENT: Pos(L,C)=(63,27). 
  1956. X
  1957. X-- Start of Text Scrap List --
  1958. Text scrap[White]="<010>
  1959. X<010>
  1960. X"
  1961. X--- End of Text Scrap List ---
  1962. X
  1963. X
  1964. TYPESETTER DIRECTIVE COMPONENT: 
  1965. X   Section "3", Section name="Error recovery point".
  1966. X
  1967. TEXT COMPONENT: Pos(L,C)=(68,27). 
  1968. X
  1969. X-- Start of Text Scrap List --
  1970. Text scrap[White]="<010>
  1971. X<010>
  1972. X"
  1973. X--- End of Text Scrap List ---
  1974. X
  1975. X
  1976. TYPESETTER DIRECTIVE COMPONENT: 
  1977. X   Section "4", Section name="Error recovery point".
  1978. X
  1979. TEXT COMPONENT: Pos(L,C)=(73,27). 
  1980. X
  1981. X-- Start of Text Scrap List --
  1982. Text scrap[White]="<010>
  1983. X<010>
  1984. X"
  1985. X--- End of Text Scrap List ---
  1986. X
  1987. X
  1988. MACRO DEFINITION COMPONENT: Pos(L,C)=(75,1). 
  1989. Part 1 of macro @<Error5@>.
  1990. X
  1991. TEXT COMPONENT: Pos(L,C)=(77,3). 
  1992. X
  1993. X-- Start of Text Scrap List --
  1994. Text scrap[White]="<010>
  1995. X"
  1996. X--- End of Text Scrap List ---
  1997. X
  1998. X
  1999. TYPESETTER DIRECTIVE COMPONENT: 
  2000. X   Section "5", Section name="Error recovery point".
  2001. X
  2002. TEXT COMPONENT: Pos(L,C)=(78,27). 
  2003. X
  2004. X-- Start of Text Scrap List --
  2005. Text scrap[White]="<010>
  2006. X<010>
  2007. X"
  2008. X--- End of Text Scrap List ---
  2009. X
  2010. X
  2011. TYPESETTER DIRECTIVE COMPONENT: 
  2012. X   Section "6", Section name="Error recovery point".
  2013. X
  2014. TEXT COMPONENT: Pos(L,C)=(83,27). 
  2015. X
  2016. X-- Start of Text Scrap List --
  2017. Text scrap[White]="<010>
  2018. X<010>
  2019. X"
  2020. X--- End of Text Scrap List ---
  2021. X
  2022. X
  2023. TYPESETTER DIRECTIVE COMPONENT: 
  2024. X   Section "7", Section name="Error recovery point".
  2025. X
  2026. TEXT COMPONENT: Pos(L,C)=(91,27). 
  2027. X
  2028. X-- Start of Text Scrap List --
  2029. Text scrap[White]="<010>
  2030. X<010>
  2031. X"
  2032. X--- End of Text Scrap List ---
  2033. X
  2034. X
  2035. X========================== End of DOCUMENT LIST DUMP ===========================
  2036. X
  2037. X
  2038. Global Local| Input File
  2039. X------------+-------------------------------------------------------------------
  2040. X     1     1| PR09: Test calls and actual parameter lists.
  2041. X     2     2| 
  2042. X     3     3| First trip up the parser so we don't get any further.
  2043. X     4     4| @>
  2044. X       Error|.^The parser was at the top level and was expecting
  2045. X            |.^one of: {Directive, Text, Macro definition, EOF}.
  2046. X     5     5| 
  2047. X     6     6| Now define some macros to call. No error.
  2048. X     7     7| 
  2049. X     8     8| @$@<Zero@>@{@}
  2050. X     9     9| @$@<One@>@(@1@)@{@}
  2051. X    10    10| @$@<Two@>@(@2@)@{@}
  2052. X    11    11| @$@<Three@>@(@3@)@{@}
  2053. X    12    12| @$@<Nine@>@(@9@)@{@}
  2054. X    13    13| @$@#"@{@}
  2055. X    14    14| 
  2056. X    15    15| The following test calls should NOT generate any errors.
  2057. X    16    16| 
  2058. X    17    17| @$@<Macro containing the test macro calls.@>==@{
  2059. X    18    18| 1. Test macro call with no parameter list.
  2060. X    19    19| @<Zero@>
  2061. X    20    20| 
  2062. X    21    21| 2. Test macro call with quick name.
  2063. X    22    22| @#"
  2064. X    23    23| 
  2065. X    24    24| 3. Test macro call with one parameter.
  2066. X    25    25| @<One@>@(Toucan@)
  2067. X    26    26| 
  2068. X    27    27| 4. Test macro call with many parameters.
  2069. X    28    28| @<Two@>@(Toucan@,Teapot@)
  2070. X    29    29| @<Three@>@(Toucan@,Teapot@,Walrus@)
  2071. X    30    30| @<Nine@>@(Toucan@,Teapot@,Walrus@,
  2072. X    31    31|           Toucan@,Teapot@,Walrus@,
  2073. X    32    32|           Toucan@,Teapot@,Walrus@)
  2074. X    33    33| 
  2075. X    34    34| 5. Test macro calls with double quotes on parameters.
  2076. X    35    35| @<One@>@( @"Toucan@"@)
  2077. X    36    36| @<Two@>@(@"Toucan@"   @,   @"Teapot@"@)
  2078. X    37    37| @<Three@>@(@"Toucan@" @,
  2079. X    38    38|            @"Teapot@" @,
  2080. X    39    39|            @"Walrus@" @)
  2081. X    40    40| @<Nine@>@( @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,
  2082. X    41    41|            @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,
  2083. X    42    42|            @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)
  2084. X    43    43| 
  2085. X    44    44| 7. Test macro calls with mixed double quotes on parameters.
  2086. X    45    45| @<Two@>@(@"Toucan@"   @,Teapot@)
  2087. X    46    46| @<Three@>@(@"Toucan@" @,
  2088. X    47    47|            @"Teapot@" @,Walrus@)
  2089. X    48    48| @<Nine@>@( @"Toucan@" @, @"Teapot@" @,   Walrus   @,
  2090. X    49    49|            @"Toucan@" @,   Teapot   @, @"Walrus@" @,
  2091. X    50    50|            @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)
  2092. X    51    51| 
  2093. X    52    52| @} @! End of macro definition enclosing all these legal tests.
  2094. X    53    53| 
  2095. X    54    54| 8. Test macro calls with a variety of syntax errors in parameter list.
  2096. X    55    55| @$@<Error1@>@{
  2097. X    56    56| @<Zero@>@(
  2098. X    57    57| @}
  2099. X       Error|.^Expecting @" or @, or @).
  2100. X            |.^Skipping after error to the next major construct...
  2101. X    58    58| @A@<Error recovery point@>
  2102. X            |.^...skipped to here after the error.
  2103. X    59    59| 
  2104. X    60    60| @$@<Error2@>@{
  2105. X    61    61| @<Zero@>@)
  2106. X       Error|.........^Expecting '@}'.
  2107. X            |.........^Skipping after error to the next major construct...
  2108. X    62    62| @}
  2109. X    63    63| @A@<Error recovery point@>
  2110. X            |.^...skipped to here after the error.
  2111. X    64    64| 
  2112. X    65    65| @$@<Error3@>@{
  2113. X    66    66| @<One@>@(@"Toucan@)
  2114. X       Error|..................^Expecting '@"'.
  2115. X            |..................^Skipping after error to the next major construct...
  2116. X    67    67| @}
  2117. X    68    68| @A@<Error recovery point@>
  2118. X            |.^...skipped to here after the error.
  2119. X    69    69| 
  2120. X    70    70| @$@<Error4@>@{
  2121. X    71    71| @<One@>@(@"Toucan@"@"Sloth@"@)
  2122. X       Error|....................^Expecting @, or @).
  2123. X            |....................^Skipping after error to the next major construct...
  2124. X    72    72| @}
  2125. X    73    73| @A@<Error recovery point@>
  2126. X            |.^...skipped to here after the error.
  2127. X    74    74| 
  2128. X    75    75| @$@<Error5@>@{
  2129. X    76    76| @<Two@>@(@"Toucan@"Teapot@)
  2130. X       Error|....................^Expecting whitespace text.
  2131. X    77    77| @}
  2132. X    78    78| @A@<Error recovery point@>
  2133. X    79    79| 
  2134. X    80    80| @$@<Error6@>@{
  2135. X    81    81| @<Two@>@(@"Toucan@"Teapot
  2136. X       Error|....................^Expecting whitespace text.
  2137. X    82    82| @}
  2138. X       Error|.^Expecting @, or @).
  2139. X            |.^Skipping after error to the next major construct...
  2140. X    83    83| @A@<Error recovery point@>
  2141. X            |.^...skipped to here after the error.
  2142. X    84    84| 
  2143. X    85    85| @$@<Error7@>@{
  2144. X    86    86| @<Two@>@(@"Toucan@"Teapot
  2145. X       Error|....................^Expecting whitespace text.
  2146. X    87    87| @<Three@>@(Toucan@,
  2147. X       Error|.^Expecting @, or @).
  2148. X            |.^Skipping after error to the next major construct...
  2149. X    88    88|            @"Teapot@,Walrus
  2150. X    89    89| 
  2151. X    90    90| @}
  2152. X    91    91| @A@<Error recovery point@>
  2153. X            |.^...skipped to here after the error.
  2154. X    92    92| 
  2155. X            | <End-Of-File>
  2156. X------------+-------------------------------------------------------------------
  2157. X
  2158. There were 10 Errors.
  2159. END_OF_FILE
  2160. if test 59230 -ne `wc -c <'answers/pr09.lis'`; then
  2161.     echo shar: \"'answers/pr09.lis'\" unpacked with wrong size!
  2162. fi
  2163. # end of 'answers/pr09.lis'
  2164. fi
  2165. if test -f 'userman/u_ch2.tex' -a "${1}" != "-c" ; then 
  2166.   echo shar: Will not clobber existing file \"'userman/u_ch2.tex'\"
  2167. else
  2168. echo shar: Extracting \"'userman/u_ch2.tex'\" \(66821 characters\)
  2169. sed "s/^X//" >'userman/u_ch2.tex' <<'END_OF_FILE'
  2170. X%==============================================================================%
  2171. X%                                Start of Ch2.tex                              %
  2172. X%==============================================================================%
  2173. X%
  2174. X% Copyright
  2175. X% ---------
  2176. X% Copyright (C) 1992 Ross N. Williams.
  2177. X% This file contains a chapter of the FunnelWeb User's Manual.
  2178. X% See the main TeX file for this manual for further information.
  2179. X%
  2180. X%==============================================================================%
  2181. X
  2182. X\chapter{FunnelWeb Hints}
  2183. X\label{chapadvanced}\xx{FunnelWeb}{hints}
  2184. X
  2185. Whereas Chapter~\ref{chapintroduction} provides an introduction to
  2186. XFunnelWeb and Chapter~\ref{chapdefinition} a definition, \i{this} chapter
  2187. contains hints about how
  2188. XFunnelWeb can be used. This chapter probably should not be read until
  2189. the reader has already commenced using FunnelWeb, or at the very least,
  2190. tried out some of the examples in Chapter~\ref{chapintroduction}.
  2191. Those who find themselves using FunnelWeb frequently
  2192. should read this chapter at some stage
  2193. so as to ensure that they are getting the most out of it.
  2194. X
  2195. Most of the examples in this chapter have been
  2196. placed in the FunnelWeb regression test suite which should be
  2197. available in a directory called \p{/fwdir/tests/}.
  2198. The files to examine are \p{hi01.fw} through \p{hi10.fw}.
  2199. X
  2200. X\section{Macro Names}
  2201. X\xx{macro}{names}\xx{macro}{identifiers}
  2202. X
  2203. When using FunnelWeb, the choice of macro names can be as
  2204. important to the readability of a program as the choice of program
  2205. identifiers,
  2206. and it is important that the user know the range of options available.
  2207. X
  2208. X\narrowthing{Names are case sensitive and exact matching:}{Macro names are case
  2209. sensitive and are matched exactly. The strings used as a macro name
  2210. at the point of definition and call must be
  2211. X\i{identical} for the connection to be made.}
  2212. X
  2213. X\narrowthing{Names can contain any printable character:}{FunnelWeb is less
  2214. restrictive about its macro names than most programming languages are
  2215. about their identifiers. A FunnelWeb macro name can contain any
  2216. sequence of printable characters, including blanks and punctuation. Names
  2217. can start and end with any character. Names cannot cross line boundaries. The
  2218. following are all legal macro names:}
  2219. X
  2220. X\begin{verbatim}
  2221. X        @<This macro expands to some really bad code@>
  2222. X        @<@>
  2223. X        @<453 #$ %&# --===~~1">>>@>
  2224. X        @<<@>
  2225. X        @<<>@>
  2226. X        @<a b c d e f g@>
  2227. X        @<       !     @>
  2228. X        @<?? ...@>
  2229. X        @<"Who's been hacking MY program" said Father Bear.@>
  2230. X        @<Update the maximum and return for more data@>
  2231. X\end{verbatim}
  2232. X
  2233. X\narrowthing{Names must be no more than a maximum limit in length:}{Names
  2234. can be
  2235. no longer than a predefined maximum length. Currently this length cannot
  2236. be modified.}
  2237. X
  2238. Typically, macro names will consist of a short English phrase or sentence
  2239. that describes the contents of the macro.
  2240. X
  2241. X\section{Quick Names}
  2242. X\xx{quick}{names}
  2243. X
  2244. Sometimes a particular macro must be used extremely often. When this happens
  2245. it is desirable to make the macro's name as short as possible.
  2246. The shortest ordinary FunnelWeb macro name is the empty name\xx{empty}{name}
  2247. X\dqp{@<@>}, which is four characters long. Single-character names are
  2248. five characters long.
  2249. X
  2250. To cater for the cases where really short names are needed, FunnelWeb provides
  2251. a \newterm{quick name} syntax that allows one-character macro names to be
  2252. specified in two less characters. Quick names take the form of the special
  2253. character, followed by a hash (\p{\#}) followed by a single character.
  2254. XExamples:
  2255. X
  2256. X\begin{verbatim}
  2257. X@#A     @#|     @#&     @#m
  2258. X\end{verbatim}
  2259. X
  2260. This form of macro name has the same syntactic functionality as an ordinary
  2261. name and can be substituted wherever an ordinary name can be. In fact
  2262. quick names live in the same namespace as ordinary macro names. For example
  2263. the quickname \p{@\#A} is the \i{same name} (refers to the same macro)
  2264. as the ordinary name \p{@<A@>}.
  2265. X
  2266. Because quick names look syntactically \dq{open} (\ie{}they do not have
  2267. a closing\p{@>} as ordinary names do), it is best to avoid them except
  2268. where a macro must be called very often.
  2269. X
  2270. X\section{FunnelWeb the Martinet}
  2271. X\xx{FunnelWeb}{rules}\xx{FunnelWeb}{martinet}
  2272. X
  2273. There are many ways in which a macro preprocessor can cause unexpected
  2274. difficulties. FunnelWeb seeks to avoid many of these problems by performing
  2275. a number of checks. This section describes some of the checks that
  2276. XFunnelWeb performs.
  2277. X
  2278. X\narrowthing{Trailing blanks in the input file:}{Trailing
  2279. blanks\xx{trailing}{blanks} are usually
  2280. not dangerous, but
  2281. XFunnelWeb disallows them anyway. All trailing blanks in the
  2282. X\i{input} (\p{.fw} file) are flagged as errors by FunnelWeb.
  2283. XFunnelWeb does not flag trailing blanks in any of its output files.}
  2284. X
  2285. X\narrowthing{Input line length:}{FunnelWeb has a maximum input line
  2286. length.\xx{input line}{length}
  2287. If FunnelWeb reads an input line longer than this length, it flags the
  2288. line with an error message. The maximum length can be changed using a
  2289. pragma (see Chapter~\ref{chapdefinition}).}
  2290. X
  2291. X\narrowthing{Product file line length:}{FunnelWeb
  2292. watches the length of output lines\xx{output line}{length}
  2293. and all output lines longer than the limit are flagged with error
  2294. messages.
  2295. The maximum length can be changed using a
  2296. pragma (see Chapter~\ref{chapdefinition}).
  2297. That FunnelWeb polices output lines is very important. Some programs
  2298. can behave very strangely if they get an input line that is too long
  2299. X(\eg{}Fortran compilers\xx{Fortran}{compilers}
  2300. can simply ignore text past a certain column!)
  2301. and once FunnelWeb starts expanding macros using indentation, it is sometimes
  2302. not obvious how wide the product file will be.}
  2303. X
  2304. X\narrowthing{Control characters:}{The presence of control
  2305. characters\xx{control}{characters} in a text file
  2306. can result in some confusing behaviour downstream when the file is
  2307. presented to various programs. Unfortunately, some text
  2308. editors\xx{text}{editors} allow
  2309. control characters to be inserted into the text rather too easily, and it is
  2310. all too easy to be tripped up. FunnelWeb prevents these problems by flagging
  2311. with diagnostics all non-end-of-line control characters detected
  2312. in the input (\p{.fw}) file (even TABs\x{tabs}).
  2313. The result is that the user is
  2314. guaranteed that product files generated from FunnelWeb contain no
  2315. unintentional control characters. This said, FunnelWeb does allow the
  2316. insertion of control characters in the output file by explicitly
  2317. specifying
  2318. them in the text using a \p{@\circumflex{}} control sequence.}
  2319. X
  2320. X\narrowthing{Number of invocations:}{FunnelWeb
  2321. checks the number of times that\xx{invocations}{number}
  2322. each macro is called and issues an error if the total is not one. The
  2323. X\p{@Z} (for zero) and \p{@M} (for many) macro attributes can be used
  2324. to bypass these checks.}
  2325. X
  2326. X\narrowthing{Recursion:}{Because\xx{recursion}{macro}
  2327. XFunnelWeb does not provide any conditional
  2328. constructs, all recursively defined macros must, by
  2329. definition, expand infinitely,\footnote{A special case exists where
  2330. there is recursion but no content. In this case, the expansion is finite
  2331. X(the empty string) even though the operation of expanding is infinite.
  2332. XFunnelWeb does not treat this case specially.} and are therefore
  2333. unacceptable. FunnelWeb performs \i{static} checks to detect recursion,
  2334. detecting it before macro expansion commences. The user need not fear that
  2335. XFunnelWeb will lock up or spew forth
  2336. if a recursive macro is accidentally specified.}
  2337. X
  2338. X\section{Fiddling With End of Lines}
  2339. X\xx{EOL}{fiddling with}\xx{end-of-line}{fiddling with}\x{spacing}
  2340. X
  2341. One of the  fiddly aspects of programming  with FunnelWeb is coping  with end of
  2342. lines. If  you want  your product file to be  well indented without
  2343. multiple blank lines  or code run-ons,  you have to spend a  little time working
  2344. out how the end of line markers get moved around.
  2345. X
  2346. The rule  to remember is that,
  2347. disregarding the  effects of  special sequences
  2348. within a macro body, \i{the body of a macro consists of exactly the text
  2349. between the opening \p{@\{} and the  closing \p{@\}}}. This text includes end of
  2350. line markers.
  2351. X
  2352. If for example you call a macro in a sequence of code$\ldots$
  2353. X
  2354. X\begin{verbatim}
  2355. while the_walrus_is_sleepy do
  2356. X   begin
  2357. X   writeln('zzzzzzz');
  2358. X   @<Wake up the walrus@>
  2359. X   writeln('Umpharumpha...');
  2360. X   end;
  2361. X\end{verbatim}
  2362. X
  2363. where \p{<wake up the walrus>} is defined as follows
  2364. X
  2365. X\begin{verbatim}
  2366. X@$@<Wake up the walrus@>==@{
  2367. wake_up_the_walrus(the_walrus);
  2368. X@}
  2369. X\end{verbatim}
  2370. X
  2371. then when \p{<Wake up the walrus>} is expanded you will get
  2372. X
  2373. X\begin{verbatim}
  2374. while the_walrus_is_sleepy do
  2375. X   begin
  2376. X   writeln("zzzzzzz");
  2377. X
  2378. X   wake_up_the_walrus(the_walrus);
  2379. X
  2380. X   writeln("Umpharumpha...");
  2381. X   end;
  2382. X\end{verbatim}
  2383. X
  2384. The blank  lines were  introduced by  the end  on line  markers included  in the
  2385. definition of \p{<Wake  up the walrus>}. A  good solution to this  problem is to
  2386. suppress the end of line markers by defining the macro as follows
  2387. X
  2388. X\begin{verbatim}
  2389. X@$@<Wake up the walrus@>==@{@-
  2390. wake_up_the_walrus(the_walrus);@}
  2391. X\end{verbatim}
  2392. X
  2393. This is the usual form of macro definitions in FunnelWeb files.
  2394. X
  2395. In additive macros, this format  does not
  2396. work properly because the end of line that is suppressed by the trailing \p{@\}}
  2397. does not get replaced by the end of line at the end of the macro invocation. For
  2398. example the definition
  2399. X
  2400. X\begin{verbatim}
  2401. X@$@<Wake up the walrus@>+=@{@-
  2402. wake_up_the_walrus_once(the_walrus);@}
  2403. X\end{verbatim}
  2404. X
  2405. later followed by
  2406. X
  2407. X\begin{verbatim}
  2408. X@$@<Wake up the walrus@>+=@{@-
  2409. wake_up_the_walrus_again(the_walrus);@}
  2410. X\end{verbatim}
  2411. X
  2412. is equivalent to the single definition
  2413. X
  2414. X\begin{verbatim}
  2415. X@$@<Wake up the walrus@>==@{@-
  2416. wake_up_the_walrus_once(the_walrus);wake_up_the_walrus_again(the_walrus);@}
  2417. X\end{verbatim}
  2418. X
  2419. Putting the trailing \p{@\}}  on a new line at the end of  the macro (except for
  2420. the last definition part) solves the problem.
  2421. X
  2422. X\begin{verbatim}
  2423. X@$@<Wake up the walrus@>+=@{@-
  2424. wake_up_the_walrus_once(the_walrus);
  2425. X@}
  2426. X\end{verbatim}
  2427. X
  2428. later followed by
  2429. X
  2430. X\begin{verbatim}
  2431. X@$@<Wake up the walrus@>+=@{@-
  2432. wake_up_the_walrus_again(the_walrus);@}
  2433. X\end{verbatim}
  2434. X
  2435. is equivalent to the single definition
  2436. X
  2437. X\begin{verbatim}
  2438. X@$@<Wake up the walrus@>==@{@-
  2439. wake_up_the_walrus_once(the_walrus);
  2440. wake_up_the_walrus_again(the_walrus);@}
  2441. X\end{verbatim}
  2442. X
  2443. Managing end of line markers is tricky,
  2444. but once you establish  a convention for coping
  2445. with them, the problem disappears into the background.
  2446. X
  2447. X\section{Fudging Conditionals}
  2448. X\xx{fudging}{conditionals}
  2449. X
  2450. As a macro preprocessor, the facility that FunnelWeb most obviously lacks
  2451. is a conditional facility (such as C's \p{\#ifdef}). It might, therefore,
  2452. come as a surprise to know that the first version  of FunnelWeb
  2453. actually had a built in conditional facility. The facility allowed
  2454. the programmer to specify a construct that would select from one of a number
  2455. of macro expressions depending on the value of a controlling macro expression.
  2456. X
  2457. In three years the construct was never used.
  2458. X
  2459. The reason was that conditional constructs could be fudged nearly
  2460. as easily as they could be used. Because of this, the inbuilt conditional
  2461. feature was removed in the current version of FunnelWeb. Not only did this
  2462. simplify the program, but is also allowed recursive macros to be detected
  2463. through static analysis rather than during macro expansion.
  2464. X
  2465. There are two basic ways to fudge a conditional. First, the comment
  2466. facility of the target programming language may be employed. For example,
  2467. in Ada,\x{Ada}
  2468. comments commence with \dqp{--} and terminate at the end of the line.
  2469. Using this fact, it is easy to construct macros that can be called at the
  2470. start of each target line and which turn on and off the lines so
  2471. marked by defining the macro to be the empty string (ON) or the comment
  2472. symbol (\p{--}) (OFF). For example:
  2473. X
  2474. X\begin{verbatim}
  2475. X@A@<Debug Macro@>
  2476. X
  2477. The following macro determines whether debug code will be included in the
  2478. program. All lines of debug code commence with a call to this macro and so
  2479. we can turn all that code on or off here by defining this macro to be either
  2480. empty or the single-line comment symbol (\p{--}). Note the use of a
  2481. quick macro name.
  2482. X
  2483. X@$@#D@M==@{@}     @! Turns the debug code ON.
  2484. X@! Use this definition to turn the debug code OFF: @$@#D==@{--@}
  2485. X
  2486. X... then later in the file...
  2487. X
  2488. X@$@<Sloth incrementing loop@>==@{@-
  2489. while sloth<walrus loop
  2490. X   @#D assert(sloth<walrus,"AWK! sloth>=walrus!!!!!!!");
  2491. X   @#D assert(timer<timermax,"AWK! timer>=timermax!!!");
  2492. X   inc(sloth);
  2493. end loop@}
  2494. X\end{verbatim}
  2495. X
  2496. The other way to fudge a conditional is to define a macro with a
  2497. single parameter. A call to the macro is then wrapped around all the
  2498. conditional code in the program. The macro can then be defined to
  2499. present or ignore the code of its argument. For example:
  2500. X
  2501. X\begin{verbatim}
  2502. X@A@<Debug Macro@>
  2503. X
  2504. The following macro determines whether debug code will be included in the
  2505. program. All debug code is wrapped by a call to this macro and so
  2506. we can turn all the debug code on or off here by defining this macro to be
  2507. either empty or its parameter.
  2508. X
  2509. X@$@#D@(@1@)@M==@{@1@}     @! Turns the debug code ON.
  2510. X@! Use this definition to turn the debug code OFF: @$@#D@(@1@)==@{@}
  2511. X
  2512. X... then later in the file...
  2513. X
  2514. X@$@<Sloth incrementing loop@>==@{@-
  2515. while sloth<walrus loop
  2516. X   @#D@(assert(sloth<walrus,"AWK! sloth>=walrus!!!!!!!");
  2517. X        assert(timer<timermax,"AWK! timer>=timermax!!!");@)
  2518. X   inc(sloth);
  2519. end loop@}
  2520. X\end{verbatim}
  2521. X
  2522. In languages that allow multi-line comments (\eg{}C with \p{/*} and \p{*/}),
  2523. comments can be used to eliminate the conditioned code rather than
  2524. absence.  For example:
  2525. X
  2526. X\begin{verbatim}
  2527. X@$@#D@(@1@)@M==@{/* @1 */@}    @! Comments out the debug code
  2528. X\end{verbatim}
  2529. X
  2530. X(Note: If this example were ever actually used,
  2531. the programmer would have to be careful not to place comments in
  2532. the argument code. Nested comments in~C are non-portable.)
  2533. X
  2534. The parameterized macro idea can be generalized to support the choice of
  2535. more than one mutually exclusive alternative. For example:
  2536. X
  2537. X\begin{verbatim}
  2538. X@A This module contains non-portable code that must execute on Hewlett
  2539. Packard, Sun, and DEC workstations. The following FunnelWeb macro is
  2540. defined to choose between these three. The first parameter is the HP code,
  2541. the second is the Sun code, and the third is the DEC code. Whichever
  2542. parameter constitutes the body of this macro determines which
  2543. machine the code is being targeted\note{Dictionary says only one t
  2544. in targeted.} for.
  2545. X
  2546. X@$@<Machine specific code@>@(@3@)@M==@{@1@}  @! Configure for HP.
  2547. X
  2548. X...then later in the file...
  2549. X
  2550. X@<Machine specific code@>@(
  2551. X@"get_command_line(comline)@"           @, @! HP.
  2552. X@"scan_command_line(128,comline);@"     @, @! Sun.
  2553. X@"dcl_get_command_line(comline,256);@"  @) @! DEC.
  2554. X\end{verbatim}
  2555. X
  2556. Of course, this could also be performed using three separate macros. The
  2557. main advantage of using a single macro is that the mutual exclusivity is
  2558. enforced. Also, because FunnelWeb ensures that the number of formal and
  2559. actual parameters are the same, this method lessens the chance that a
  2560. machine will be forgotten in some places.
  2561. X
  2562. X
  2563. X\section{Changing the Strength of Headings}
  2564. X\xx{headings}{strength}\xx{typesetting}{strength}%
  2565. X\xx{section}{strength}\xx{font}{size}
  2566. X
  2567. XFunnelWeb provides five heading levels:
  2568. X\p{@A}, \p{@B}, \p{@C}, \p{@D}, and \p{@E} to which it binds five different
  2569. typographical strengths. These bindings are static; a level
  2570. X\p{@A} heading will always be typeset in a particular font size regardless
  2571. of the size of the document. The font
  2572. sizes have been preset to be \dq{reasonable} for a range of document sizes,
  2573. but may be inappropriate for very small or large documents.
  2574. X
  2575. XFunnelWeb does not currently provide an \dq{official}
  2576. way (\eg{}a pragma) to change the typesetting
  2577. strength of headings. This feature might be added in later versions.
  2578. Meanwhile, a hack is available that will do the job, providing that you
  2579. do not mind the hack being \TeX{}-specific and probably FunnelWeb-version
  2580. specific.
  2581. X
  2582. Inside the set of \TeX{} macro definitions
  2583. that FunnelWeb writes at the top of every documentation
  2584. file are five \dq{library}
  2585. definitions \p{fwliba}$\ldots$\p{fwlibe} which
  2586. provide five different typesetting strengths for headings. Near the
  2587. end of the set of definitions, FunnelWeb binds these macros to five
  2588. other macros \p{fwseca}$\ldots$\p{fwsece} which are invoked directly in the
  2589. generated \TeX{} code to typeset the headings.
  2590. X
  2591. X\begin{verbatim}
  2592. X\def\fwseca#1#2{\fwliba{#1}{#2}}
  2593. X\def\fwsecb#1#2{\fwlibb{#1}{#2}}
  2594. X\def\fwsecc#1#2{\fwlibc{#1}{#2}}
  2595. X\def\fwsecd#1#2{\fwlibd{#1}{#2}}
  2596. X\def\fwsece#1#2{\fwlibe{#1}{#2}}
  2597. X\end{verbatim}
  2598. X
  2599. This means that the typesetting strength of the headings in a FunnelWeb
  2600. document can be changed by redefining these macros at the top of a FunnelWeb
  2601. document. For example:
  2602. X
  2603. X\begin{verbatim}
  2604. X@p typesetter = tex
  2605. X\def\fwseca#1#2{\fwlibc{#1}{#2}}
  2606. X\end{verbatim}
  2607. X
  2608. would set \p{@A} headings at the same strength as the default strength of
  2609. X\p{@C} headings. The \p{typesetter} directive is necessary to ensure that the
  2610. X\TeX{} control sequences get through to the documentation file unfiltered.
  2611. X
  2612. The following will tone down all headings by two levels (with the
  2613. X\p{@D} and \p{@E} levels being allocated the default \p{@E} typesetting
  2614. strength because there is nothing weaker).
  2615. X
  2616. X\begin{verbatim}
  2617. X@p typesetter = tex
  2618. X\def\fwseca#1#2{\fwlibc{#1}{#2}}
  2619. X\def\fwsecb#1#2{\fwlibd{#1}{#2}}
  2620. X\def\fwsecc#1#2{\fwlibe{#1}{#2}}
  2621. X\def\fwsecd#1#2{\fwlibe{#1}{#2}}
  2622. X\def\fwsece#1#2{\fwlibe{#1}{#2}}
  2623. X\end{verbatim}
  2624. X
  2625. These definitions affect only the headings that follow them, and so they
  2626. should be placed at the top of the FunnelWeb input file.
  2627. X
  2628. X\section{Efficiency Notes}
  2629. X\xx{FunnelWeb}{efficiency}\xx{efficiency}{notes}
  2630. X
  2631. The following notes are worth keeping in mind when using FunnelWeb.
  2632. X
  2633. X\narrowthing{Memory:}{When\x{memory}\xx{input}{files}
  2634. XFunnelWeb processes an input file, it reads
  2635. the entire input file, and all the included files into memory.\footnote{If a
  2636. file is included $n$ times, FunnelWeb keeps $n$ copies in memory.} This
  2637. organization does not pose a constraint on machines with large memories,
  2638. but could
  2639. present a problem on the smaller machines such as the PC.}
  2640. X
  2641. X\narrowthing{Speed:}{FunnelWeb\x{speed} is not a slow program. However, it is
  2642. not particularly fast either. If the speed at which FunnelWeb runs is
  2643. important to you, then the thing to keep in mind is that FunnelWeb has been
  2644. optimized to deal efficiently with large slabs of text. FunnelWeb treats
  2645. input files as a sequence of text slabs and special sequences (\eg{}\p{@+})
  2646. and whenever it hits a special sequence, it has to stop and think.
  2647. Thus, while a ten megabyte text slab would be manipulated as a single token,
  2648. in a few milliseconds, a similar ten megabyte chunk filled with special
  2649. sequences would take a lot longer.
  2650. If FunnelWeb is running slowly, look to see if the input contains
  2651. a high density of special sequences. This can sometimes happen if FunnelWeb
  2652. is being used as a backend macro processor and its input is being
  2653. generated automatically by some other program.}
  2654. X
  2655. X\narrowthing{Macro expansion:}{When\xx{macro}{expansion}
  2656. tangling (expanding macros), FunnelWeb never
  2657. expands a macro expression into memory; it always writes it to the
  2658. product file
  2659. as it goes. This is a powerful fact, because it means that you can
  2660. write macros containing an unlimited amount of text, and pass such macros
  2661. as parameters to other macros without becoming concerned about overflowing
  2662. some kind of buffer memory. In short, FunnelWeb does not impose any
  2663. limits on the size of macro bodies or their expansions.}
  2664. X
  2665. X\section{Interactive Mode}
  2666. X\x{interactive mode}\x{keyboard mode}
  2667. X
  2668. As well as having a command line interface with lots of options, FunnelWeb
  2669. also provides a command language and a mode (\dq{interactive mode})
  2670. in which commands in the language can be typed interactively. The
  2671. XFunnelWeb command interpreter was created primarily
  2672. to support regression testing,\xx{regression}{testing}
  2673. but can also be useful to FunnelWeb users.
  2674. X
  2675. XFunnelWeb's command interpreter\xx{command}{interpreter}
  2676. reads one command per line and can read
  2677. a stream of commands either from a text file, or from the console. The
  2678. interpreter can understand over twenty commands. See
  2679. Chapter~\ref{chapdefinition} for a full list. However, most of them
  2680. were designed to support regression testing and will not be of use to the
  2681. casual user.
  2682. X
  2683. The commands that are of greatest use to the casual user
  2684. are:\xx{useful}{commands}
  2685. X
  2686. X\begin{verbatim}
  2687. X     !               - Comment. Ignores the whole line.
  2688. X     EXECUTE fn      - Execute the specified file.
  2689. X     FW options      - Invoke FunnelWeb-proper once.
  2690. X     SET options     - Sets options.
  2691. X     SHOW            - Displays currently active options.
  2692. X     TRACE ON        - Turns command tracing ON.
  2693. X     QUIT            - Quits FunnelWeb.
  2694. X\end{verbatim}
  2695. X
  2696. To distinguish here between invocations of the FunnelWeb program
  2697. and FunnelWeb runs inside the shell, we call the latter \newterm{FunnelWeb
  2698. proper}. The \dqp{FW} command invokes FunnelWeb proper with the specified
  2699. options which take the same syntax as they do on the command line. The only
  2700. restriction is that none of the action options can be turned on except
  2701. X\dqp{+F} which must be turned on.
  2702. X
  2703. The \dqp{SET} command\xx{set}{command}
  2704. has the same syntax as the \dqp{FW} command except that it
  2705. does not allow \i{any} action options to be
  2706. specified. It's sole effect is to set default option values for the
  2707. rest of the run.
  2708. X
  2709. The \dqp{SHOW}\xx{show}{command}
  2710. command displays the current default options.
  2711. X
  2712. By default, FunnelWeb does not echo the commands that it processes in a
  2713. script. The \dqp{TRACE ON}\xx{trace on}{command}
  2714. command turns on such tracing.
  2715. X
  2716. These commands can be combined to streamline the use of FunnelWeb.
  2717. XFor example, you might wish to create a script called \p{typeset.fws}
  2718. to process a whole group of files.
  2719. X
  2720. X\begin{verbatim}
  2721. trace on
  2722. X!This script typesets the whole program.
  2723. X! Set no listing file, no product files, but specify a documentation file
  2724. X! and specify the directory into which it should be placed.
  2725. set -L -O +T/usr/ross/typeset/
  2726. fw prog1
  2727. fw prog2
  2728. fw prog3
  2729. fw prog4
  2730. X\end{verbatim}
  2731. X
  2732. There are a few ways in which this script can be run. The simplest is
  2733. simply to specify it in the \dqp{+X} option of a FunnelWeb invocation.
  2734. XFunnelWeb shellscripts default to \dqp{<current\_directory>} and \dqp{.fws}.
  2735. X
  2736. X\begin{verbatim}
  2737. fw +xtypeset
  2738. X\end{verbatim}
  2739. X
  2740. The second alternative is to enter interactive mode.
  2741. X
  2742. X\begin{verbatim}
  2743. fw +k
  2744. X\end{verbatim}
  2745. X
  2746. XFrom there, you can execute the script using:
  2747. X
  2748. X\begin{verbatim}
  2749. execute typeset
  2750. X\end{verbatim}
  2751. X
  2752. Interactive mode could be very useful to those with multiple-window
  2753. workstations.\x{workstations}
  2754. The user could create a window containing an interactive
  2755. session of FunnelWeb, and then switch between windows, editing, and executing
  2756. XFunnelWeb proper and other programs.
  2757. X
  2758. If you find yourself using the command interpreter a lot, be sure to
  2759. read about the other commands that are available in
  2760. Chapter~\ref{chapdefinition}.
  2761. X
  2762. X\section{Setting Up Default Options}
  2763. X\xx{options}{setting defaults}\xx{default}{options}
  2764. X
  2765. If you do not like FunnelWeb's default settings for its command line
  2766. options, there are a number of ways in which you can change them.
  2767. X
  2768. X\narrowthing{Define an \dq{alias}:}{Use your operating system
  2769. X\dqp{alias}\x{alias}
  2770. facility to create an alias for FunnelWeb containing the desired options.
  2771. XFunnelWeb processes options from left to right, so you can override
  2772. these defaults later if you wish.}
  2773. X
  2774. X\narrowthing{Create a script called \dqp{fwinit.fws}:}{When FunnelWeb
  2775. starts up, it executes a script called \dqp{fwinit.fws}\x{fwinit.fws}
  2776. if\xx{startup}{script}\xx{initialization}{script} such a
  2777. script exists in the current directory. You can use this fact to set options
  2778. before the run of FunnelWeb proper by creating such a script and placing
  2779. a single \dqp{set} command in it containing the desired options. The main
  2780. trouble with this approach is that the options in the \p{set} command will
  2781. be processed \i{after} the command line options, which means that you won't
  2782. be able to override them on the command line.}
  2783. X
  2784. XFor example, you might be involved more with presenting programs than with
  2785. running them, and want FunnelWeb to generate a documentation
  2786. file by default, but not to produce
  2787. listing or product files by default. In Unix you could do this with:
  2788. X
  2789. X\begin{verbatim}
  2790. alias fw fw -L -O +T
  2791. X\end{verbatim}
  2792. X
  2793. X\section{FunnelWeb and Make}
  2794. X\x{make utility}\xx{file}{dependencies}
  2795. X
  2796. The Unix \p{Make} program allows a set of dependencies between a set of
  2797. files to be described, and then uses these dependencies to control the way in
  2798. which the files are created and updated. Typically,
  2799. X\p{Make} is used to control the process of transforming a collection of
  2800. source code files to one or more executable files.
  2801. As the use of FunnelWeb implies an extra stage to this process, it is
  2802. natural to include the transformation of \p{.fw} files to source code
  2803. files as part of the \p{Make} process. This is easy to do, but the user
  2804. should be aware of one aspect of FunnelWeb which can cause problems.
  2805. X
  2806. It is often useful, when using FunnelWeb, to create a FunnelWeb \p{.fw}
  2807. file that generates more than one product file.
  2808. That is, a single \p{.fw} file may have many macro definitions connected
  2809. to product files so that when the FunnelWeb \p{.fw} file is processed by
  2810. XFunnelWeb, several files are created. For example, this facility has been
  2811. used to great effect to place the description of an Ada\x{Ada} package's
  2812. package specification file and package body file in the same FunnelWeb
  2813. X\p{.fw} file.
  2814. X
  2815. The use of multiple product files, however, provokes a problem
  2816. with dependencies. Suppose for example that a FunnelWeb \p{prog.fw}
  2817. produces two product files \p{proc.spec} (a package specification)
  2818. and \p{prog.body} (a package body). If the package is accessed in the way
  2819. that packages normally are, it will be quite common for the programmer
  2820. to want to modify the package body without modifying the program specification.
  2821. So the programmer will edit the \p{prog.fw} file to change the package
  2822. body. The result of running this through FunnelWeb will be the desired
  2823. new package body file. However, FunnelWeb will also produce a new package
  2824. specification product file \i{even though it may be identical to the
  2825. previous version!} The result is that the newly created (with a recent
  2826. file date) specification package file could provoke a huge remake of much
  2827. of the program in which it resides.
  2828. X
  2829. To solve the problem, FunnelWeb includes a command line option 
  2830. X(\p{D} for Delete),\xx{D}{option}\xx{delete}{output files}
  2831. which when turned on (using \dqp{+D}) causes
  2832. XFunnelWeb to suppress\xx{suppression}{file}
  2833. product and documentation files that are identical
  2834. to the previously existing versions of the same files. For example,
  2835. if, during a FunnelWeb  run, a macro was connected to a product file called
  2836. X\p{x.dat}, and the macro expanded to \i{exactly} the same text as is
  2837. contained in \p{x.dat} then FunnelWeb would simply \i{never write the product
  2838. file}, the file \p{x.dat} would be untouched and, as a result, no further
  2839. X\p{Make} propagations would take place.
  2840. X
  2841. XFunnelWeb implements this feature by writing each product file to
  2842. a temporary file with a temporary file name. It then compares the temporary
  2843. file with the target file. If the two are identical, it deletes the
  2844. temporary file. If the two are different it deletes the target file and
  2845. renames the temporary file to the target file.
  2846. X
  2847. Use of the \p{D} facility means that the programmer need not be punished
  2848. X(by extra \p{Make} propagations) for describing more than one product file
  2849. in the same FunnelWeb file.
  2850. X
  2851. X
  2852. X\section{The Dangers of FunnelWeb}
  2853. X\xx{FunnelWeb}{dangers}\xx{FunnelWeb}{pitfalls}
  2854. X
  2855. Like many tools that are general and flexible, FunnelWeb can be used in a
  2856. variety of ways, both good and bad. One of the original appeals of the
  2857. literate approach to programming for Knuth,\xn{Donald}{Knuth}
  2858. the inventor of literate
  2859. programming,\xx{literate}{programming}
  2860. was that it allows the programmer to describe the target
  2861. program bottom up, top down, size to side, or chaotically if desired.
  2862. The flexibility that this style of programming leaves much
  2863. room for bad documentation as well as good documentation. Years of
  2864. experience with FunnelWeb has revealed the following stylistic pitfalls
  2865. which the experienced FunnelWeb user should take care to
  2866. avoid.\footnote{The fact that these faults are listed here does not mean
  2867. that the author has eliminated them in his own work. Rather,
  2868. it is mainly the author's own mistakes that have resulted in this list
  2869. being compiled. The author immediately
  2870. confesses to several of the faults listed here, most notably that of
  2871. Pavlov documentation.}
  2872. X
  2873. X\narrowthing{Spaghetti organization:}{By\xx{spaghetti}{organization}
  2874. far the worst problem that arises
  2875. in connection with the literate style occurs where the programmer has
  2876. used the literate tool to completely scramble the program so that the
  2877. program is described and layed out in an unordered, undisciplined
  2878. X\dq{stream of consciousness}.\x{stream of consciousness}
  2879. In such cases the programmer may be using
  2880. the literate style as a crutch to avoid having to
  2881. think about structuring the presentation.}
  2882. X
  2883. X\narrowthing{Boring organization:}{At\xx{boring}{organization}
  2884. the other extreme, a program may be
  2885. organized in such a strict way that it is essentially laid out in the
  2886. order most \dq{desired} by the target programming language. For example,
  2887. each macro might contain a single procedure, with all the macros being
  2888. called by a macro connected to a file at the top. In many cases a boring
  2889. structure may be entirely appropriate, but the programmer should be warned
  2890. that it is easy to slip into such a normative style, largely forgetting the
  2891. descriptive structural power that FunnelWeb provides.}
  2892. X
  2893. X\narrowthing{Poor random access:}{Using\xx{random}{access}
  2894. XFunnelWeb, it is quite possible to write
  2895. programs like novels\x{novels}
  2896. X--- to be read from cover to cover. Sometimes the
  2897. story is very exciting, with data structures making dashing triumphs and
  2898. optimized code bringing the story to a satisfying conclusion. These programs
  2899. can be works of art.
  2900. Unfortunately, without careful construction,
  2901. such \dq{novel-programs} can become very hard to access randomly by (say)
  2902. a maintenance programmer\xx{maintenance}{programmer}
  2903. who wishes only to dive in and fix a specific
  2904. problem. If the entire program is scrambled for sequential exposition, it
  2905. can be hard to find the parts relating to a single function.
  2906. Somehow a balance must be struck in the document between the
  2907. needs of the sequential and of the random-access reader.
  2908. This balance will depend on the intended use of the program.}
  2909. X
  2910. X\narrowthing{Too-interdependent documentation:}{Sometimes,
  2911. when\xx{documentation}{interdependent} editing a 
  2912. program written using FunnelWeb, one knows how to modify the program,
  2913. but one is unsure of how to update the surrounding documentation!
  2914. The documentation may be woven into such a network of facts that it seems that
  2915. changing a small piece of code could invalidate many
  2916. pieces of documentation scattered throughout the document. The documentation
  2917. becomes a big tar pit in which movement is impossible.
  2918. XFor example,
  2919. if you have talked about a particular data structure invariant throughout
  2920. a document, changing that invariant in
  2921. a small way could mean having to update all the documentation without
  2922. touching much
  2923. code. In such cases, the documentation is too interdependent. This could be
  2924. symptomatic of an excessibly interconnected program, or of an
  2925. excessively verbose or redundant documenting style. In any case, a balance
  2926. must be struck between the conversational style that encourages redundancy
  2927. X(by mentioning things many times) and the normalized database approach where
  2928. each fact is given at only one point, and the reader is left to figure
  2929. out the implications throughout the document.}
  2930. X
  2931. X\narrowthing{Pavlov documentation:}{By\xx{pavlov}{documentation}
  2932. placing so much emphasis on the documentation,
  2933. XFunnelWeb naturally provides slots where documentation \dq{should} go. For
  2934. example, a FunnelWeb user may feel that there may be a rather unpleasant
  2935. gap between a \p{@C} marker and the following macro. In many cases \i{no}
  2936. commentary is needed and the zone is better left blank rather than being
  2937. filled with the kind of uninformative waffle one often finds filling the slots
  2938. of structured documentation written according to a military standards
  2939. X(\eg{}MIL-STD-2167A).\x{MIL-STD-2167A}\x{2167A}\footnote{Note:
  2940. This is not a criticism of 2167A,
  2941. only of the way it is sometimes used.} The lesson is to add documentation
  2942. only when it adds something. The lesson in Strunk and White\paper{Strunk79}
  2943. X(p.~23)
  2944. holds for
  2945. program documentation as it does for other writing: \dq{Vigorous writing is
  2946. concise. A sentence should contain no unnecessary words, a paragraph no
  2947. unnecessary sentences, for the same reason that a drawing should have
  2948. no unnecessary lines and a machine no unnecessary parts. This
  2949. requires not that the writer make all his sentences short, or that he avoid
  2950. all detail and treat his subjects only in outline, but that every word
  2951. tell.}.\checked{}}
  2952. X
  2953. X\narrowthing{Duplicate documentation:}{Where\xx{duplicate}{documentation}
  2954. the programmer is generating
  2955. product files that must exist on their own within the entire programming
  2956. environment (\eg{}the case of a programmer in a team who is using FunnelWeb
  2957. for his own benefit but must generate (say) commented Ada\x{Ada}
  2958. specification
  2959. package files) there is a tendency for the comments in the
  2960. target code to duplicate the commentary in the FunnelWeb text. This may or
  2961. may not be a problem, depending on the exact situation. However, if this is
  2962. happening, it is certainly worth the programmer spending some time deciding
  2963. if one or other of the FunnelWeb or inline-comment documentation should be
  2964. discarded.
  2965. In many cases, a mixture can be used, with the FunnelWeb documentation
  2966. referring the reader to the inline comments where they are present.
  2967. XFor example:}
  2968. X
  2969. X\begin{verbatim}
  2970. X@A Here is the header comment for the list package specification.
  2971. The reader should read these comments carefully as they define a list.
  2972. There is no need to duplicate the comments in this text.
  2973. X
  2974. X@$@<Specification package header comments@>==@{@-
  2975. X-- LIST PACKAGE
  2976. X-- ============
  2977. X-- * A LIST consists of zero or more ITEMS.
  2978. X-- * The items are numbered 1 to N where N is the number of items in the list.
  2979. X-- * If the list is non-empty, item 1 is called the HEAD of the list.
  2980. X-- * If the list is non-empty, item N is called the TAIL of the list.
  2981. X-- ...
  2982. X@}
  2983. X\end{verbatim}
  2984. X
  2985. X\narrowthing{Overdocumenting:}{Another\xx{over}{documentation}
  2986. evil that can arise when using FunnelWeb is
  2987. to over-document the target program. In some of Knuth's earlier (\eg{}1984)
  2988. examples of literate programming, each variable is given its own description
  2989. and each piece of code has a detailed explanation. This level of analysis,
  2990. while justified for tricky tracts of code, is probably not warranted
  2991. for most of the code that constitutes most programs. Such over-commenting
  2992. can even have the detrimental affect of obscuring the code, making it hard
  2993. to understand because it is so scattered (see \dq{spaghetti organization}
  2994. earlier). It is up to the user to decide when a stretch of just a few lines of
  2995. code should be pulled to bits and analysed and when it is clearer to leave it
  2996. alone.}
  2997. X
  2998. X\narrowtext{In the case where there
  2999. are a few rather tricky lines of code, a detailed
  3000. explanation may be appropriate. The following example
  3001. contains a solution to a problem outlined in section 16.3 of
  3002. the book \dq{The Science of Programming} by David Gries\paper{Gries81}.}
  3003. X
  3004. X\begin{verbatim}
  3005. X@C@<Calculation of the longest plateau in array b@>
  3006. X
  3007. This section contains a solution to a problem outlined in section 16.3 of
  3008. the book @/The Science of Programming@/ by David Gries[Gries81].
  3009. X
  3010. X@D Given a sorted array @{b[1..N]@} of integers, we wish to determine the
  3011. X@/length@/ of the longest run of identically valued elements in the array.
  3012. This problem is defined by the following precondition and postcondition.
  3013. X
  3014. X@$@<Precondition@>==@{/* Pre: sorted(b). */@}
  3015. X@$@<Postcondition@>==@{@-
  3016. X/* Post: sorted(b) and p is the length of the longest run in b[1..N]. */@}
  3017. X
  3018. X@D We approach a solution to the problem by deciding to try the approach of
  3019. scanning through the array one element at a time maintaining a useful
  3020. invariant through each iteration. A loop variable
  3021. array index @{i@} is created for this purpose. The bound function is
  3022. X@{N-i@}. Here is the invariant.
  3023. X
  3024. X@$@<Invariant@>==@{@-
  3025. X/* Invariant: sorted(b) and 1<=i<=N and           */
  3026. X/*            p is len of longest run in b[1..i]. */@}
  3027. X
  3028. X@D Establishing the invariant above in the initial, degenerate case is easy.
  3029. X
  3030. X@$@<Establish the plateau loop invariant initially@>==@{i=1; p=1;@}
  3031. X
  3032. X@D At this stage, we have the following loop structure. Note that when both
  3033. the invariant and @{i != N@} are true, the postcondition holds and the loop
  3034. can terminate.
  3035. X
  3036. X@$@<Set p to the length of the longest plateau in sorted array b[1..N]@>==@{@-
  3037. X@<Precondition@>
  3038. X@<Establish the plateau loop invariant initially@>
  3039. while (i != N)
  3040. X  {
  3041. X   @<Invariant@>
  3042. X   @<Loop body@>
  3043. X  }
  3044. X@<Postcondition@>
  3045. X@}
  3046. X
  3047. X@D Now there remains only the loop body whose sole task is to increase @{i@}
  3048. X(and so decrease the value of the bound function) while maintaining the
  3049. invariant. If @{p@} is the length of the longest run
  3050. seen so far (i.e. in b[1..i]), then, because the array is sorted,
  3051. the extension of our array range to
  3052. X@{b[1..i+1]@} can only result in an increase in @{p@} if the new element
  3053. terminates a run of length @{p+1@}. The increase can be at most 1. Because
  3054. the array is sorted, we need
  3055. only compare the endpoints of this possible run to see if it exists. This
  3056. is performed as shown below.
  3057. X
  3058. X@$@<Loop body@>==@{i++; if (b[i] != b[i-p]) p++;@}
  3059. X\end{verbatim}
  3060. X
  3061. X\narrowtext{Where the code is more obvious,
  3062. it is often better to let the code speak for itself.}
  3063. X
  3064. X\begin{verbatim}
  3065. X@C The following function compares two C~strings and returns TRUE iff they
  3066. are identical.
  3067. X
  3068. X@$@<Function comp@>==@{@-
  3069. bool comp(p,q)
  3070. char *p,*q;
  3071. X{
  3072. X while (TRUE)
  3073. X   {
  3074. X    if (*p != *q  ) return FALSE;
  3075. X    if (*p == '\0') return TRUE;
  3076. X    p++; q++;
  3077. X   }
  3078. X}
  3079. X@}
  3080. X\end{verbatim}
  3081. X
  3082. X\section{Wholistic Debugging}
  3083. X\xx{wholistic}{debugging}
  3084. X
  3085. Surprising though it may be, FunnelWeb has a key role to play in the
  3086. X\i{debugging} of programs. Long experience in programming has led me to the
  3087. concept of \newterm{wholistic debugging}. When most programmers detect a
  3088. bug, their first reaction seems to be to jump into the debugger\x{debugger}
  3089. where they
  3090. often spend many hours stepping through endless stretches of code and 
  3091. generally wasting a lot of time.
  3092. X
  3093. In contrast, my first reaction when I detect a bug is to realize that
  3094. X\i{the code must not be in good enough shape if such a bug can arise.}
  3095. The presence of the bug is taken as symptomatic of the lack of general
  3096. health of the code. If that bug occurred, why not another?
  3097. In response to this realization, my reaction is not to enter the debugger,
  3098. but rather to return to the original code and tend it like a
  3099. garden,\xx{code}{gardening}
  3100. adding more comments, reworking the grotty bits, adding assertions,
  3101. and looking for faults. In many cases, the search for faults does not
  3102. even centre on the specific bug that arose, but does tend to focus on
  3103. the area of code where the bug is likely to be.
  3104. X
  3105. The result is often that the original bug is located more quickly than it
  3106. would have been had the debugger been involved. But even if it isn't, there
  3107. are other benefits. A programmer who enters the debugger may
  3108. stay there for hours and still not find the bug. The result is
  3109. frustration and no positive gain at all. In contrast, by tending to the
  3110. code, the programmer is making forward progress at all times (the code
  3111. is constantly improving) even if the bug is not immediately found.
  3112. At the end of ten hours, the programmer can at least feel that the code
  3113. is \dq{ten hours better}, whereas the debugger freak will likely feel
  3114. defeated.
  3115. All this makes code tending better psychologically as well as a more
  3116. efficient approach to debugging.
  3117. X
  3118. I call this technique wholistic debugging, for it is like the
  3119. difference between conventional and wholistic medicine.\xx{wholistic}{medicine}
  3120. Go to a
  3121. conventional doctor with a headache and he might send off for head X-rays,
  3122. perform allergy tests and perform many other
  3123. debugging activities. Go to a wholistic doctor with the same problem and
  3124. he might look to see if you are fit, assess your mental health, and ask you
  3125. if your marriage is working. Both approaches are appropriate at different
  3126. times. In programming, the wholistic approach is not used enough.
  3127. X
  3128. X\section{Examples of FunnelWeb Applications}
  3129. X\xx{FunnelWeb}{example applications}\xx{FunnelWeb}{applications}
  3130. X
  3131. Despite (or perhaps because of) its flexibility and simplicity,
  3132. XFunnelWeb can be applied to quite a number of different
  3133. text processing and documenting problems. This section describes some of
  3134. the more interesting real problems that FunnelWeb has solved.
  3135. X
  3136. X\subsection{Analyzing the Monster Postscript Header File}
  3137. X\xx{monster file}{postscript}
  3138. X
  3139. During my Ph.D. candidature, I determined at one point that it would be
  3140. very desirable to automatically insert diagrams from the \i{MacDraw}\x{MacDraw}
  3141. program on my Macintosh into
  3142. X\TeX{}\x{TeX}
  3143. X\p{insert}ions in my thesis.\xx{PhD}{thesis} This would allow diagrams to float
  3144. around with the text and be printed automatically rather than having to be
  3145. printed separately and stuck in with real glue. On the face of it, the
  3146. problem seemed inherently solvable as the Macintosh\x{Macintosh}
  3147. could generate PostScript\x{PostScript}
  3148. for each diagram and this PostScript could presumably be inserted into the
  3149. PostScript generated using \TeX{}.
  3150. X
  3151. The only trouble was that the Macintosh PostScript code for the diagrams
  3152. relied on an Apple PostScript header file.\xx{postscript}{header file}
  3153. This meant that the header file
  3154. had to be included at the start of the \TeX{} PostScript if the inserted
  3155. PostScript for the diagrams was to work.
  3156. Unfortunately, merely including the header file at the top didn't work, and
  3157. it turned out that a rather detailed analysis of some parts of the Apple
  3158. header file was required in order to perform the necessary surgery on the
  3159. header file to make it work. This analysis was severely aggravated by the
  3160. fact that the PostScript header file was virtually unreadable. Basically
  3161. it was about 50K of interwoven
  3162. definitions, that looked as if it had been run through a word processor.
  3163. There was no way that the code could be understood clearly without some
  3164. kind of reformatting. Two other aspects of the problem further complicated
  3165. the analysis:
  3166. X
  3167. X\begin{itemize}
  3168. X
  3169. X\item The definitions of interest (\ie{}the ones causing the problems)
  3170. were scattered throughout the file.
  3171. X
  3172. X\item Many definitions could not be moved. For one or more reasons
  3173. X(\eg{}to keep a definition within the activation of a particular
  3174. dictionary \p{begin} and \p{end}) it would have been unwise to move the
  3175. definitions of interest to the same point in the file.
  3176. X
  3177. X\end{itemize}
  3178. X
  3179. In fact the file was so messy and complicated that, as a rule, it had to
  3180. be handled with kid gloves. It would have been unwise to re-arrange
  3181. the definitions or to insert comments.
  3182. X
  3183. To my surprise, FunnelWeb provided an unexpected solution to
  3184. the problem. First I replaced all occurrences of the \p{@} in the
  3185. header file with \p{@@}. Second, I placed the entire header file
  3186. in a FunnelWeb macro definition connected to a product file. I then
  3187. processed the file and checked to make sure that the product file
  3188. was identical to the original file.
  3189. By doing all this I had placed the
  3190. header file under FunnelWeb control. I then left the
  3191. macro definition largely untouched, but replaced the PostScript
  3192. definitions of
  3193. interest with FunnelWeb macro calls, moving the actual PostScript
  3194. definitions into FunnelWeb macro definitions at the end of the FunnelWeb
  3195. file.
  3196. X
  3197. X\begin{verbatim}
  3198. X@O@<LaserHeader.ps@>==@{@-
  3199. Unreadable Postscript code
  3200. X@<Print routine@>
  3201. Unreadable Postscript code
  3202. X@<Zap routine@>
  3203. Unreadable Postscript code
  3204. X@}
  3205. X
  3206. X@A This routine looks as if it does this, but really is does that,
  3207. blah, blah blah.
  3208. X
  3209. X@$@<Print routine@>==@{@-
  3210. X/print { push pop pop push turn around and jump up and down and print it} def
  3211. X@}
  3212. X
  3213. X@A This routine zaps the...
  3214. X
  3215. X@$@<Zap routine@>==@{@-
  3216. X/zap { push pop pop push turn around and jump up and down and print it} def
  3217. X@}
  3218. X\end{verbatim}
  3219. X
  3220. Use of FunnelWeb meant that I was able to pluck out the definitions of interest
  3221. X(a very small part of the whole file) and collect them as a group at the end
  3222. of the file where they could be studied.
  3223. Because each definition was safely contained in a macro, it was possible to
  3224. write a detailed commentary of each routine without fear of affecting the
  3225. final PostScript code in any way at all. Once this analysis was completed,
  3226. it was possible to perform surgery on the offending PostScript definitions
  3227. in an extremely controlled way. In particular, the FunnelWeb input file
  3228. served as a repository for all the different versions of particular routines
  3229. that were tried in order to get the definitions to work. A new (\b{Z}ero)
  3230. macro was created for each version of each definition, and a commentary of how
  3231. it performed added above it.
  3232. X
  3233. This case demonstrates that
  3234. XFunnelWeb is an extremely powerful tool for dissecting and
  3235. documenting cryptic text files.\xx{cryptic}{text files}
  3236. Through the use of macros, particular
  3237. parts of the file can be isolated and discussed without affecting the
  3238. final product file in any way. In the example above, only a small part of the
  3239. file was analysed, the rest being left as a blob, but in the general case,
  3240. a cryptic text file could be inserted into FunnelWeb and then incrementally
  3241. dissected (and possibly modified) until the result is a fully documented
  3242. literate program. That this can be done without affecting the actual
  3243. product file demonstrates the high degree of descriptive control that
  3244. XFunnelWeb provides.
  3245. X
  3246. X\subsection{Making Ada ADTs more A}
  3247. X\x{Ada}\x{abstract data type}\x{ADT}
  3248. X
  3249. Like many modern programming languages, Ada provides mechanisms for hiding
  3250. information and structure. In particular, Ada provides a \newterm{package}
  3251. facility that allows the programmer to declare objects in a
  3252. package definition and define them in a corresponding package body.
  3253. This works well
  3254. for functions and procedures. However, in the case of types, implementation
  3255. issues (in particular, the need to know the size of exported types) have
  3256. led the designers of Ada to force the placement of
  3257. private type definitions in the definition package rather than the
  3258. implementation package. This means that some implementation details
  3259. are present in the package definition for all to see. While not actually
  3260. dangerous (the user of the package cannot make use of the information
  3261. without recourse to \dq{Chapter~13} of the Ada Language Reference
  3262. Manual\paper{DOD83}), this aspect of Ada is certainly unpleasant.
  3263. X
  3264. During the development of some Ada programs, FunnelWeb was used to solve
  3265. this problem. Instead of creating a separate file for the package
  3266. specification and package body, a single FunnelWeb file was created containing
  3267. two sections, one for the each package part. The \dq{private} part of the
  3268. package specification was then moved (using a FunnelWeb macro definition)
  3269. to the section describing the package body. Readers who wished only to read
  3270. the package specification could read only the first part, which contained
  3271. a fully documented description not containing the private definition.
  3272. X
  3273. X\subsection{Multiple Language Systems}
  3274. X\xx{multiple}{languages}
  3275. X
  3276. With the prevalence of open systems\x{open systems}
  3277. and multi-vendor computing, it is
  3278. often necessary to construct systems consisting of programs written in
  3279. a number of different programming languages for a number of different
  3280. systems. For example, a particular functionality might be implemented by a
  3281. shellscript
  3282. X(invoked by the user) that calls a C~program that makes a network connection
  3283. to a Pascal program that queries a database. Quite often all these programs
  3284. must conspire closely to execute their function. In the normal case, they
  3285. must be written separately. FunnelWeb allows them to be written as a
  3286. whole.
  3287. X
  3288. By creating a single FunnelWeb file that creates many product files in
  3289. different languages, the programmer can describe the interaction between
  3290. the different programs in any manner desired. Furthermore, because
  3291. the different product files  are all created in the same \dq{text space}
  3292. X(\ie{}in a single FunnelWeb file), it is easy for them to share information.
  3293. X
  3294. XFor example, in one real application FunnelWeb was used to create a
  3295. system for printing files\xx{printing}{system}
  3296. on a laser printer\xx{laser}{printer}
  3297. connected to a remote Vax
  3298. Unix machine from a local Vax VMS
  3299. machine. The system consisted of two files: a VMS DCL command procedure
  3300. to run on the local node, and a Unix shellscript to run on the remote
  3301. node. The user, by giving the print command, invoked the local VMS
  3302. command procedure, which in turn fired up the remote Unix shellscript. The
  3303. two scripts then cooperated to transfer the files to be printed and print
  3304. them.
  3305. X
  3306. In addition to its usual documentation powers, FunnelWeb assisted in the
  3307. creation of this system in two special ways. First, it allowed pieces of
  3308. code from the two different command procedures to be partially interwoven in a
  3309. description of their interaction. This is just not possible with comments.
  3310. Second, it facilitated the use of shared information. For example, under
  3311. some conditions, each file to be printed would be renamed and copied to the
  3312. remote system using a particular constant filename (\eg{}\dqp{printfile.tmp}).
  3313. XFunnelWeb allowed this constant filename to be included in a single macro
  3314. definition which was invoked in the definition of each of the scripts. This
  3315. ensured that the two scripts used the same name.
  3316. X
  3317. X\begin{verbatim}
  3318. X@A The following macro contains the temporary file name used to allow the
  3319. two shellscripts to transfer each file to be printed.
  3320. X
  3321. X@$@<printfile@>@M==@{printme.txt@}
  3322. X
  3323. X@A Here are the scripts for the local VMS node and the remote UNIX node.
  3324. X
  3325. X@O@<vmscommandprocedure.com@>==@{@-
  3326. DCL commands
  3327. copy @<printfile@> unixnode::
  3328. DCL commands
  3329. X@}
  3330. X
  3331. X@O@<unixshellscript@>==@{@-
  3332. unix commands
  3333. print @<printfile@>
  3334. unix commands
  3335. X@}
  3336. X\end{verbatim}
  3337. X
  3338. In the case of the printing system, the entire system was described and
  3339. defined in a single FunnelWeb \p{.fw} file. In larger systems containing
  3340. many FunnelWeb \p{.fw} files for many different modules in many different
  3341. languages, the same trick can be pulled by placing FunnelWeb macro
  3342. definitions for shared values into FunnelWeb include files. For example,
  3343. a suite of implementations of network nodes, with each implementation being
  3344. in a different programming language for a different target machine, could
  3345. all share a table of configuration constants defined in macros in a
  3346. XFunnelWeb include file.
  3347. X
  3348. In summary, FunnelWeb's macro and include file mechanisms provide
  3349. a simple way for programs written in different languages to share
  3350. information. This reduces redundancy between the systems and hence the
  3351. chance of inconsistencies arising.\x{sharing information}
  3352. X
  3353. X\subsection{The Case of the Small Function}
  3354. X\xx{small}{functions}
  3355. X
  3356. Often, when programming, there is a need for a
  3357. code abstraction\xx{code}{abstraction} facility
  3358. that operates at the text level. If the statement \dqp{a:=3;} occurs often,
  3359. it may be best simply to repeat it verbatim. If a sequence of one hundred
  3360. statements is repeated often, it is normal to remove the code to a function
  3361. and replace the occurrences by a function call.
  3362. However, in between these two extremes are cases where a particular sequence
  3363. of code is long enough and appears often enough to be troublesome, but which
  3364. is bound so messily to its environment as to make a function call
  3365. cumbersome.
  3366. X
  3367. XFor example, the following line of statements (referring to five variables
  3368. declared \i{local} to a function) might appear ten times in
  3369. a function:
  3370. X
  3371. X\begin{verbatim}
  3372. a=b*3.14159; c=d % 256; e=e+1;
  3373. X\end{verbatim}
  3374. X
  3375. Now the \dq{normal} rule of programming says that these statements should be
  3376. placed in a procedure (also called a \dq{function} in the C programming language
  3377. used in this example),
  3378. but here five local variables are used. Use of a procedure
  3379. X(function) would result in a procedure definition looking something like:
  3380. X
  3381. X\begin{verbatim}
  3382. void frobit(a,b,c,d,e)
  3383. float *a,b;
  3384. int *c,d;
  3385. unsigned *e;
  3386. X{*a=b << 8; *c=d % 256; *e=*e+1;}
  3387. X\end{verbatim}
  3388. X
  3389. and a procedure call something like
  3390. X
  3391. X\begin{verbatim}
  3392. frobit(&a,b,&c,d,&e);
  3393. X\end{verbatim}
  3394. X
  3395. This might be workable in a language that allowed formal parameters to be
  3396. specified to be bound only to particular variables. Similarly, it might
  3397. be possible to avoid the parameter list in languages that support
  3398. local procedures that can access non-local variables (such as
  3399. Pascal\x{Pascal}).
  3400. However, in our example here, in the C programming language, these options
  3401. are not available, and so we must either create a function with five
  3402. parameters,
  3403. or use the C macro preprocessor\xx{preprocessor}{C}
  3404. X(the best solution). FunnelWeb provides the
  3405. same macro facility for languages that do not have a built-in
  3406. preprocessor.
  3407. X
  3408. In particularly speed-stressed applications, the programmer may be
  3409. reluctant to remove code to a procedure because of the procedure-call
  3410. overhead.\xx{procedure call}{overhead}
  3411. XFunnelWeb macros can help there too.
  3412. X
  3413. In summary, there sometimes arises in programming situations where the
  3414. cost of defining a procedure is higher than the benefits it will bestow.
  3415. Common reasons for this are the run-time procedure overhead and
  3416. the messy binding problems\xx{binding}{problems}
  3417. caused by removing target code from its target context. FunnelWeb
  3418. can help in these situations by allowing the programmer to define a text
  3419. macro. This avoids all the problems and provides an additional incentive
  3420. for the programmer to describe the piece of code so isolated.
  3421. X
  3422. X\subsection{When Comments are Bad}
  3423. X\xx{comments}{abuse}\xx{eliminating}{comments}
  3424. X
  3425. In the \dq{good old days}\x{good old days}
  3426. of small machine memories and interpreted BASIC,\x{BASIC}
  3427. programmers would eliminate the \dqp{REM} statements\xx{REM}{statement}
  3428. X(comments) from their
  3429. BASIC programs so as to save space and increase execution speed. Whilst
  3430. this was obviously an appalling programming practice, the small memories
  3431. and slow microprocessors often made this tempting, if not necessary.
  3432. X
  3433. Thankfully, times have changed since then,
  3434. and most code is now compiled
  3435. rather than interpreted. However, from time to time one still runs into
  3436. an environment or situation, or special-purpose language, where comments
  3437. are either unavailable (no comment feature) or undesirable. Here
  3438. XFunnelWeb can be used to fully document the code without resulting in any
  3439. comments in the final code at all. For example:\xx{header}{files}
  3440. X
  3441. X\begin{itemize}
  3442. X
  3443. X\item Comments in frequently used \p{.h} header files in C
  3444. programs\xx{C}{header} can
  3445. have a significant impact on compilation speed. Often such header files
  3446. are fairly cryptic and really ought to be well commented, but their authors
  3447. are reluctant to.
  3448. X
  3449. X\item Comments are undesirable in PostScript\x{postscript}
  3450. header files that must be
  3451. transferred repeatedly along communications channels (\eg{}the Apple
  3452. Macintosh LaserWriter header file).
  3453. X
  3454. X\item Interpreted programs in embedded systems.
  3455. X
  3456. X\item Hand written machine code in hex dump form could be commented.
  3457. X
  3458. X\item A programmer may wish to annotate a text data file containing lists
  3459. of numbers that is to be fed into a statistical program that does not
  3460. provide any comment facility for its input file.
  3461. X
  3462. X\end{itemize}
  3463. X
  3464. In all these situations, FunnelWeb allows full integrated documentation
  3465. without any impact on the final code.
  3466. X
  3467. X\subsection{Documents That Share Text}
  3468. X\xx{sharing}{text}
  3469. X
  3470. XFunnelWeb is very useful when preparing multiple documents that must
  3471. share large slabs of identical text that are being constantly modified.
  3472. X
  3473. XFor example someone preparing two slightly different user manuals for two
  3474. slightly different audiences might want the manuals to share
  3475. large slabs of text, while still allowing differences between them.
  3476. The following example shows how this can be done. The code is cluttered,
  3477. but this clutter would not be a problem if the lumps of text were moderately
  3478. large.
  3479. X
  3480. X\begin{verbatim}
  3481. X@O@<manual1.txt@>==@{@<M1@>@+@}
  3482. X@O@<manual2.txt@>==@{@<M2@>@+@}
  3483. X
  3484. X@$@<M1@>+=@{@<T1@>@}
  3485. X@$@<M2@>+=@{@<T1@>@}
  3486. X@$@<T1@>@M==@{First lump of text shared by both documents.@+@}
  3487. X
  3488. X@$@<M1@>+=@{Text for first document@+@}
  3489. X@$@<M2@>+=@{Text for second document@+@}
  3490. X
  3491. X@$@<M1@>+=@{@<T2@>@}
  3492. X@$@<M2@>+=@{@<T2@>@}
  3493. X@$@<T2@>@M==@{Second lump of text shared by both documents.@+@}
  3494. X\end{verbatim}
  3495. X
  3496. An alternative approach, which might work better in situations where there
  3497. are many small differences between the two documents rather than a few large
  3498. ones, is to define a macro with two arguments, one for each product
  3499. file document.
  3500. Write the document from top to bottom, but place all stretches that
  3501. differ between the two documents in a macro call.\xx{annual}{report}
  3502. X
  3503. X\begin{verbatim}
  3504. X@! Set the definition of @#D to
  3505. X@!    @1 to create the shareholders report.
  3506. X@!    @2 to create the customers report.
  3507. X@$@#D@(@2@)@M==@{@1@}
  3508. X
  3509. X@O@<report.txt@>==@{@-
  3510. X1992 ANNUAL REPORT TO @#D@(Shareholders@,Customers@)
  3511. X======================@#D@(============@,=========@)
  3512. This has been a very good year for The Very Big Corporation of America.
  3513. With your help, we have been able to successfully
  3514. X@#D@(@"screw the customers for every cent they have@"@,
  3515. X     @"knock the shareholders into submission to bring you lower prices@"@).
  3516. With gross earnings approaching six trillion dollars, we have been able to
  3517. X@#D@(@"increase dividends@"@,
  3518. X     @"lower prices@"@).
  3519. We expect to have an even better year next year.
  3520. X@}
  3521. X\end{verbatim}
  3522. X
  3523. One application where text sharing can be particularly useful is in the
  3524. preparation of computer documentation\xx{examples}{documentation}
  3525. containing examples. For example,
  3526. a book describing a new programming language might be full of examples
  3527. of small programs written in the language which the user might want to try
  3528. without having to type them all in. The \dq{default} approach of keeping
  3529. a copy of the examples in the text of the book and another copy in
  3530. separate files is cumbersome and error prone, because both files have to
  3531. be updated whenever an example is changed. A more sophisticated approach is
  3532. to store each example in a separate file, and then use the \dq{include file}
  3533. facility of the word processor to include each example in the text.
  3534. This is a better solution, but suffers from a few drawbacks. First, when
  3535. editing the book in a word processor, the
  3536. examples in the book will not be directly accessible or visible. To see an
  3537. example, the writer would have to open the file containing the example in
  3538. a separate window. This could become tedious if the text contained many
  3539. examples, as many texts do. Furthermore, there is a risk that some example
  3540. files will be included in the wrong place. Second, because the book is
  3541. dependent on the included files, the book will end up consisting of a
  3542. directory of a hundred or more files instead of just a few.
  3543. X
  3544. An alternative solution is to construct a single FunnelWeb \p{.fw}
  3545. file that, when processed, produces both the book file and the example files.
  3546. This solution assumes that the book consists of a text file containing
  3547. commands for a typesetter such as \TeX{}.
  3548. X
  3549. X\begin{verbatim}
  3550. X@O@<Book.tex@>==@{@#B@}
  3551. X
  3552. X@$@#B+=@{@-
  3553. The first step to learning the object oriented AdaCgol++ language is to examine
  3554. a hello world program.
  3555. X
  3556. X\start{verbatim}
  3557. X@<Ex1@>
  3558. X\finish{verbatim}
  3559. X@}
  3560. X
  3561. X@$@<Ex1@>==@{read iopack@+Enter !World~! !Hello~! ex pr flu X[1]@}
  3562. X@O@<Ex1.c@>==@{@<Ex1@>@}
  3563. X
  3564. X@$@#B+=@{@-
  3565. To understand the program, think of the execution state as a plate of cheese...
  3566. X@}
  3567. X\end{verbatim}
  3568. X
  3569. Most of the file will consist of part definitions of the additive
  3570. macro \p{@\#B}. The definition is \dq{broken} to allow a macro definition,
  3571. wherever an example appears.
  3572. X
  3573. The example above is a little messy because FunnelWeb does not allow
  3574. macros connected to product files to be called, and it does not have
  3575. text expressions that write to an product file as well as evaluating to text.
  3576. Nevertheless, it presents a fairly clean solution to the problem of keeping
  3577. the example programs in a computing text up to date.
  3578. X
  3579. X\subsection{Generics}
  3580. X\xx{generics}{fudging}
  3581. X
  3582. It is well known that generics in programming languages are closely aligned
  3583. with textual substitution. In fact, a good way to understand the generic
  3584. facility of a new programming language is to ask oneself the question
  3585. X\dq{In what way does this generic facility differ from simple text
  3586. substitution?} The differences, if any, typically have to do with
  3587. the difference in scoping between textual and intelligent substitution
  3588. and whether the generic code is shared or copied by the implementation.
  3589. In most cases the differences are quite minor.
  3590. X
  3591. Because generic facilities are so closely aligned with text substitution,
  3592. it is possible to use FunnelWeb's parameterized macros to provide generics
  3593. in programming languages that do not support generics. Simply write a
  3594. XFunnelWeb macro whose parameters are the parameters of the generic and
  3595. whose body is the generic object.
  3596. X
  3597. The following FunnelWeb file gives an example of a fully worked Vax
  3598. Pascal\x{Pascal}
  3599. generic set package implemented using FunnelWeb parameterized macros.
  3600. The package was written by Barry Dwyer\xn{Barry}{Dwyer}
  3601. of the Computer Science Department
  3602. of the University of Adelaide\xx{University}{Adelaide}
  3603. in 1987 and was emailed to me on
  3604. X11~November 1987. The generic package provides a set
  3605. abstraction\xx{set}{abstraction} implemented
  3606. using linked lists. Note the clever use of the instantiation parameters in
  3607. type, function, and procedure names.
  3608. X
  3609. X\begin{verbatim}
  3610. X@$@<Generic Set Module@>@(@2@)==@{@-
  3611. X@! @1 is the base type, @2 is the set type.
  3612. X[inherit ('@1'), environment ('@2')]
  3613. X
  3614. module @2;
  3615. X
  3616. type  @2 = ^@2Record;
  3617. X      @2Record = record
  3618. X         Member: @1;
  3619. X         Next: @2;
  3620. X         end;
  3621. X
  3622. procedure Null@2 (var Result: @2);
  3623. begin new (Result);
  3624. Result^.Member := (- MaxInt)::@1;
  3625. Result^.Next := nil end;
  3626. X
  3627. function IsNull@2 (S: @2): boolean;
  3628. begin IsNull@2 := S^.Member::integer = - MaxInt end;
  3629. X
  3630. procedure ForEach@1 (S: @2; procedure DoIt (i: @1));
  3631. var   ThisS, NextS: @2;
  3632. begin ThisS := S;
  3633. while ThisS^.Member::integer <> - MaxInt do
  3634. X   begin NextS := ThisS^.Next;
  3635. X   DoIt (ThisS^.Member);
  3636. X   ThisS := NextS end;
  3637. end;
  3638. X
  3639. function First@1 (S: @2): @1;
  3640. begin First@1 := S^.Member end;
  3641. X
  3642. function Is@1InSet (i: @1; S: @2): boolean;
  3643. X   procedure TestEquals (j: @1);
  3644. X   begin if Equal@1 (i, j) then Is@1InSet := true; end;
  3645. begin Is@1InSet := false; ForEach@1 (S, TestEquals); end;
  3646. X
  3647. function Includes@2 (S1, S2: @2): boolean;
  3648. var Result: boolean;
  3649. X   procedure TestIfInS1 (i: @1);
  3650. X   begin if Result then if not Is@1InSet (i, S1) then Result := false; end;
  3651. begin Result := true;
  3652. XForEach@1 (S2, TestIfInS1);
  3653. Includes@2 := Result end;
  3654. X
  3655. function Disjoint@2s (S1, S2: @2): boolean;
  3656. var Result: boolean;
  3657. X   procedure TestIfInS1 (i: @1);
  3658. X   begin if Result then if Is@1InSet (i, S1) then Result := false; end;
  3659. begin Result := true;
  3660. XForEach@1 (S2, TestIfInS1);
  3661. Disjoint@2s := Result end;
  3662. X
  3663. function Equal@2 (S1, S2: @2): boolean;
  3664. begin
  3665. XEqual@2 := Includes@2 (S1, S2) and Includes@2 (S2, S1);
  3666. end;
  3667. X
  3668. procedure Insert@1 (i: @1; var S: @2);
  3669. var   This, Pred, Succ: @2;
  3670. begin
  3671. if not Is@1InSet (i, S) then
  3672. X   begin
  3673. X   Pred := nil; Succ := S;
  3674. X   while Succ^.Member::integer > i::integer do begin
  3675. X      Pred := Succ; Succ := Succ^.Next end;
  3676. X   if Succ^.Member::integer < i::integer then begin
  3677. X      new (This); This^.Next := Succ; This^.Member := i;
  3678. X      if Pred <> nil then Pred^.Next := This else S := This;
  3679. X      end;
  3680. X   end;
  3681. end;
  3682. X
  3683. procedure Insert@1s (S1: @2; var S2: @2);
  3684. var   This, Pred, Succ: @2;
  3685. X   procedure Add@1 (i: @1);
  3686. X   begin Insert@1 (i, S2) end;
  3687. begin
  3688. XForEach@1 (S1, Add@1);
  3689. end;
  3690. X
  3691. procedure Remove@1 (i: @1; var S: @2);
  3692. var   Pred, This: @2;
  3693. begin
  3694. Pred := nil; This := S;
  3695. while not Equal@1 (This^.Member, i) do begin
  3696. X   Pred := This; This := This^.Next end;
  3697. if Pred <> nil then Pred^.Next := This^.Next else S := This^.Next;
  3698. Dispose (This);
  3699. end;
  3700. X
  3701. procedure Dispose@2 (var S: @2);
  3702. var   Old: @2;
  3703. begin
  3704. while S <> nil do begin Old := S; S := S^.Next; Dispose (Old) end;
  3705. end;
  3706. X
  3707. end.
  3708. X@}
  3709. X
  3710. X@O@<NaryTreeSet.pas@>==@{@-
  3711. X  @<Generic Set Module@>@(@"NaryTree@"@,@"NaryTreeSet@"@)@}
  3712. X@O@<NaryTreeSetSet.pas@>==@{@-
  3713. X  @<Generic Set Module@>@(@"NaryTreeSet@"@,@"NaryTreeSetSet@"@)@}
  3714. X\end{verbatim}
  3715. X
  3716. A great advantage of the approach reflected in the above example is that
  3717. it allows the programmer to construct a generic object in a language that
  3718. does not supply generics, \i{with complete typesafety.}\xx{typesafe}{generics}
  3719. This contrasts to the
  3720. approach that might be used in a language such as C where the programmer
  3721. might choose to construct a \dq{generic} package by parameterizing a
  3722. package with pointers to \p{void}. The resulting package is
  3723. powerful but extremely untypesafe. Such a generic list package is used in the
  3724. code of FunnelWeb itself and caused no end of problems, as the compiler had
  3725. no way of telling if pointers to the correctly typed object were being
  3726. handed to the correct list-object/function combination.
  3727. X
  3728. The major disadvantage of the text generic approach is that it causes the
  3729. code of the generic object to be duplicated once for each instantiation.
  3730. Depending on the number and size of the instantiations, this may or may not
  3731. be acceptable.
  3732. X
  3733. Where the duplication of code is unacceptable, a hybrid approach may be
  3734. taken. As in the C~example, the programmer could write
  3735. a single generic package
  3736. using pointers to \p{void} or some other untypesafe mechanism.
  3737. Then the programmer
  3738. creates a FunnelWeb generic package whose functions do nothing
  3739. more than call the functions of the untypesafe package, and whose types do
  3740. nothing more than contain the types of the untypesafe package. This solution
  3741. involves the use of untypesafe programming, but this is a one-off
  3742. and if done carefully and correctly, the result can be
  3743. a typesafe generic package involving minimal code duplication.
  3744. X
  3745. X\section{Summary}
  3746. X
  3747. This chapter has described some of the finer aspects of the use of FunnelWeb.
  3748. Throughout, the power and danger of FunnelWeb as a general text-rearranging
  3749. preprocessor has been emphasised. FunnelWeb can be used both to make programs
  3750. more readable or more obscure. It is up to the programmer to ensure that
  3751. XFunnelWeb is used properly.
  3752. X
  3753. X%==============================================================================%
  3754. X%                               End of Ch2.tex                                 %
  3755. X%==============================================================================%
  3756. END_OF_FILE
  3757. if test 66821 -ne `wc -c <'userman/u_ch2.tex'`; then
  3758.     echo shar: \"'userman/u_ch2.tex'\" unpacked with wrong size!
  3759. fi
  3760. # end of 'userman/u_ch2.tex'
  3761. fi
  3762. echo shar: End of archive 16 \(of 20\).
  3763. cp /dev/null ark16isdone
  3764. MISSING=""
  3765. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  3766.     if test ! -f ark${I}isdone ; then
  3767.     MISSING="${MISSING} ${I}"
  3768.     fi
  3769. done
  3770. if test "${MISSING}" = "" ; then
  3771.     echo You have unpacked all 20 archives.
  3772.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3773. else
  3774.     echo You still need to unpack the following archives:
  3775.     echo "        " ${MISSING}
  3776. fi
  3777. ##  End of shell archive.
  3778. exit 0
  3779.