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

  1. Newsgroups: comp.sources.unix
  2. From: ross@spam.adelaide.edu.au (Ross Williams)
  3. Subject: v26i135: funnelweb - a tool for literate programming in C, Part15/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 135
  9. Archive-Name: funnelweb/part15
  10.  
  11. [ several files in this archive will unpack with the wrong size, due to
  12.   length restrictions in NNTP.  --vix ]
  13.  
  14. #! /bin/sh
  15. # This is a shell archive.  Remove anything before this line, then unpack
  16. # it by saving it into a file and typing "sh file".  To overwrite existing
  17. # files, type "sh file -c".  You can also feed this as standard input via
  18. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  19. # will see the following message at the end:
  20. #        "End of archive 15 (of 20)."
  21. # Contents:  answers/pr08.lis sources/parser.c
  22. # Wrapped by vixie@gw.home.vix.com on Sun Apr 11 11:00:31 1993
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. if test -f 'answers/pr08.lis' -a "${1}" != "-c" ; then 
  25.   echo shar: Will not clobber existing file \"'answers/pr08.lis'\"
  26. else
  27. echo shar: Extracting \"'answers/pr08.lis'\" \(48225 characters\)
  28. sed "s/^X//" >'answers/pr08.lis' <<'END_OF_FILE'
  29. XFUNNELWEB LISTING FILE
  30. X======================
  31. X
  32. Dump of mapped file "<<Suppressed>>".
  33. X
  34. MEMORY DUMP OF MAPPED FILE
  35. X==========================
  36. X
  37. X+-------------------------------------------------+------------------+
  38. X| 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF |
  39. X+-------------------------------------------------+------------------+
  40. X| 50 52 30 38 3A 20 54 65 73 74 20 73 65 6D 61 6E | PR08: Test seman |
  41. X| 74 69 63 20 63 68 65 63 6B 69 6E 67 20 6F 66 20 | tic checking of  |
  42. X| 6D 61 63 72 6F 20 64 65 66 69 6E 69 74 69 6F 6E | macro definition |
  43. X| 73 2E 0A 0A 54 72 69 70 20 70 61 72 73 65 72 20 | s...Trip parser  |
  44. X| 74 6F 20 62 65 20 73 75 72 65 20 74 68 61 74 20 | to be sure that  |
  45. X| 77 65 20 77 6F 6E 27 74 20 67 65 74 20 61 6E 79 | we won't get any |
  46. X| 20 6F 75 74 70 75 74 20 66 69 6C 65 73 21 0A 40 |  output files!.@ |
  47. X| 3E 0A 0A 31 2E 20 46 69 6C 65 20 6D 61 63 72 6F | >..1. File macro |
  48. X| 20 68 61 73 20 70 61 72 61 6D 65 74 65 72 73 2E |  has parameters. |
  49. X| 20 45 72 72 6F 72 2E 0A 40 4F 40 3C 53 6C 6F 74 |  Error..@O@<Slot |
  50. X| 68 20 31 40 3E 40 28 40 33 40 29 40 7B 57 61 6C | h 1@>@(@3@)@{Wal |
  51. X| 72 75 73 40 7D 0A 40 41 40 3C 45 72 72 6F 72 20 | rus@}.@A@<Error  |
  52. X| 72 65 63 6F 76 65 72 79 20 70 6F 69 6E 74 40 3E | recovery point@> |
  53. X| 0A 0A 32 2E 20 46 69 6C 65 20 6D 61 63 72 6F 20 | ..2. File macro  |
  54. X| 69 73 20 61 64 64 69 74 69 76 65 2E 20 45 72 72 | is additive. Err |
  55. X| 6F 72 2E 0A 40 4F 40 3C 53 6C 6F 74 68 20 32 40 | or..@O@<Sloth 2@ |
  56. X| 3E 2B 3D 40 7B 57 61 6C 72 75 73 40 7D 0A 40 41 | >+=@{Walrus@}.@A |
  57. X| 40 3C 45 72 72 6F 72 20 72 65 63 6F 76 65 72 79 | @<Error recovery |
  58. X| 20 70 6F 69 6E 74 40 3E 0A 0A 33 2E 20 46 69 6C |  point@>..3. Fil |
  59. X| 65 20 6D 61 63 72 6F 20 68 61 73 20 74 6F 6F 20 | e macro has too  |
  60. X| 6C 6F 6E 67 20 61 20 6E 61 6D 65 2E 20 54 68 65 | long a name. The |
  61. X| 20 74 65 73 74 20 6E 61 6D 65 20 68 61 73 20 31 |  test name has 1 |
  62. X| 32 30 30 20 63 68 61 72 61 63 74 65 72 73 2E 20 | 200 characters.  |
  63. X| 45 72 72 2E 0A 4E 6F 74 65 3A 20 54 68 69 73 20 | Err..Note: This  |
  64. X| 74 65 73 74 20 63 61 6E 27 74 20 74 65 73 74 20 | test can't test  |
  65. X| 74 68 65 20 65 72 72 6F 72 20 6D 65 73 73 61 67 | the error messag |
  66. X| 65 20 69 66 20 74 68 65 20 6D 61 78 69 6D 75 6D | e if the maximum |
  67. X| 20 6C 65 6E 67 74 68 20 6F 66 20 61 0A 6D 61 63 |  length of a.mac |
  68. X| 72 6F 20 6E 61 6D 65 20 69 73 20 6C 65 73 73 20 | ro name is less  |
  69. X| 74 68 61 6E 20 74 68 65 20 6D 61 78 69 6D 75 6D | than the maximum |
  70. X| 20 6C 65 6E 67 74 68 20 6F 66 20 61 20 66 69 6C |  length of a fil |
  71. X| 65 20 6E 61 6D 65 20 61 73 20 74 68 65 20 6E 61 | e name as the na |
  72. X| 6D 65 0A 65 72 72 6F 72 20 69 73 20 63 61 75 67 | me.error is caug |
  73. X| 68 74 20 66 69 72 73 74 2E 0A 40 70 20 6D 61 78 | ht first..@p max |
  74. X| 69 6D 75 6D 5F 69 6E 70 75 74 5F 6C 69 6E 65 5F | imum_input_line_ |
  75. X| 6C 65 6E 67 74 68 20 3D 20 69 6E 66 69 6E 69 74 | length = infinit |
  76. X| 79 0A 40 4F 40 3C 31 32 33 34 35 36 37 38 39 30 | y.@O@<1234567890 |
  77. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  78. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  79. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  80. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  81. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  82. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  83. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  84. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  85. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  86. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  87. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  88. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  89. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  90. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  91. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  92. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  93. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  94. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  95. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  96. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  97. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  98. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  99. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  100. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  101. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  102. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  103. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  104. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  105. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  106. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  107. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  108. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  109. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  110. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  111. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  112. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  113. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  114. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  115. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  116. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  117. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  118. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  119. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  120. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  121. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  122. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  123. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  124. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  125. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  126. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  127. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  128. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  129. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  130. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  131. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  132. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  133. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  134. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  135. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  136. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  137. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  138. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  139. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  140. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  141. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  142. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  143. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  144. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  145. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  146. X| 35 36 37 38 39 30 31 32 33 34 35 36 37 38 39 30 | 5678901234567890 |
  147. X| 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 | 1234567890123456 |
  148. X| 37 38 39 30 31 32 33 34 35 36 37 38 39 30 31 32 | 7890123456789012 |
  149. X| 33 34 35 36 37 38 39 30 31 32 33 34 35 36 37 38 | 3456789012345678 |
  150. X| 39 30 31 32 33 34 35 36 37 38 39 30 31 32 33 34 | 9012345678901234 |
  151. X| 35 36 37 38 39 30 40 3E 40 7B 40 7D 0A 40 41 40 | 567890@>@{@}.@A@ |
  152. X| 3C 45 72 72 6F 72 20 72 65 63 6F 76 65 72 79 20 | <Error recovery  |
  153. X| 70 6F 69 6E 74 40 3E 0A 0A 34 2E 20 46 69 6C 65 | point@>..4. File |
  154. X| 20 6D 61 63 72 6F 20 68 61 73 20 7A 65 72 6F 20 |  macro has zero  |
  155. X| 6F 72 20 6D 61 6E 79 20 61 74 74 72 69 62 75 74 | or many attribut |
  156. X| 65 73 2E 20 45 72 72 6F 72 2E 0A 40 4F 40 3C 53 | es. Error..@O@<S |
  157. X| 6C 6F 74 68 20 33 40 3E 40 5A 40 7B 57 61 6C 72 | loth 3@>@Z@{Walr |
  158. X| 75 73 40 7D 0A 40 41 40 3C 45 72 72 6F 72 20 72 | us@}.@A@<Error r |
  159. X| 65 63 6F 76 65 72 79 20 70 6F 69 6E 74 40 3E 0A | ecovery point@>. |
  160. X| 0A 40 4F 40 3C 53 6C 6F 74 68 20 34 40 3E 40 4D | .@O@<Sloth 4@>@M |
  161. X| 40 7B 57 61 6C 72 75 73 40 7D 0A 40 41 40 3C 45 | @{Walrus@}.@A@<E |
  162. X| 72 72 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F | rror recovery po |
  163. X| 69 6E 74 40 3E 0A 0A 40 4F 40 3C 53 6C 6F 74 68 | int@>..@O@<Sloth |
  164. X| 20 35 40 3E 40 5A 40 4D 40 7B 57 61 6C 72 75 73 |  5@>@Z@M@{Walrus |
  165. X| 40 7D 0A 40 41 40 3C 45 72 72 6F 72 20 72 65 63 | @}.@A@<Error rec |
  166. X| 6F 76 65 72 79 20 70 6F 69 6E 74 40 3E 0A 0A 35 | overy point@>..5 |
  167. X| 2E 20 50 72 65 76 69 6F 75 73 20 64 65 66 69 6E | . Previous defin |
  168. X| 69 74 69 6F 6E 20 69 73 20 66 75 6C 6C 2C 20 63 | ition is full, c |
  169. X| 75 72 72 65 6E 74 20 69 73 20 61 64 64 69 74 69 | urrent is additi |
  170. X| 76 65 2E 0A 40 24 40 3C 57 61 6C 72 75 73 20 31 | ve..@$@<Walrus 1 |
  171. X| 40 3E 3D 3D 40 7B 53 6C 6F 74 68 40 7D 0A 40 24 | @>==@{Sloth@}.@$ |
  172. X| 40 3C 57 61 6C 72 75 73 20 31 40 3E 2B 3D 40 7B | @<Walrus 1@>+=@{ |
  173. X| 41 61 72 64 76 61 72 6B 40 7D 0A 40 41 40 3C 45 | Aardvark@}.@A@<E |
  174. X| 72 72 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F | rror recovery po |
  175. X| 69 6E 74 40 3E 0A 0A 36 2E 20 50 72 65 76 69 6F | int@>..6. Previo |
  176. X| 75 73 20 64 65 66 69 6E 69 74 69 6F 6E 20 69 73 | us definition is |
  177. X| 20 61 64 64 69 74 69 76 65 2C 20 63 75 72 72 65 |  additive, curre |
  178. X| 6E 74 20 69 73 20 66 75 6C 6C 2E 0A 40 24 40 3C | nt is full..@$@< |
  179. X| 57 61 6C 72 75 73 20 32 40 3E 2B 3D 40 7B 53 6C | Walrus 2@>+=@{Sl |
  180. X| 6F 74 68 40 7D 0A 40 24 40 3C 57 61 6C 72 75 73 | oth@}.@$@<Walrus |
  181. X| 20 32 40 3E 3D 3D 40 7B 41 61 72 64 76 61 72 6B |  2@>==@{Aardvark |
  182. X| 40 7D 0A 40 41 40 3C 45 72 72 6F 72 20 72 65 63 | @}.@A@<Error rec |
  183. X| 6F 76 65 72 79 20 70 6F 69 6E 74 40 3E 0A 0A 37 | overy point@>..7 |
  184. X| 2E 20 4E 6F 6E 2D 66 69 72 73 74 20 62 6F 64 79 | . Non-first body |
  185. X| 20 70 61 72 74 20 6F 66 20 70 61 72 74 69 61 6C |  part of partial |
  186. X| 20 68 61 73 20 70 61 72 61 6D 65 74 65 72 2E 0A |  has parameter.. |
  187. X| 40 24 40 3C 55 6E 69 63 6F 72 6E 40 3E 40 28 40 | @$@<Unicorn@>@(@ |
  188. X| 33 40 29 2B 3D 40 7B 54 75 72 6B 65 79 40 7D 0A | 3@)+=@{Turkey@}. |
  189. X| 40 24 40 3C 55 6E 69 63 6F 72 6E 40 3E 40 28 40 | @$@<Unicorn@>@(@ |
  190. X| 33 40 29 2B 3D 40 7B 54 75 72 6B 65 79 40 7D 0A | 3@)+=@{Turkey@}. |
  191. X| 40 41 40 3C 45 72 72 6F 72 20 72 65 63 6F 76 65 | @A@<Error recove |
  192. X| 72 79 20 70 6F 69 6E 74 40 3E 0A 0A 38 2E 20 5A | ry point@>..8. Z |
  193. X| 65 72 6F 20 6F 72 20 6D 61 6E 79 20 61 74 74 72 | ero or many attr |
  194. X| 69 62 75 74 65 73 20 6F 6E 20 6E 6F 6E 2D 66 69 | ibutes on non-fi |
  195. X| 72 73 74 20 62 6F 64 79 20 70 61 72 74 20 6F 66 | rst body part of |
  196. X| 20 61 64 64 69 74 69 76 65 2E 0A 40 24 40 3C 45 |  additive..@$@<E |
  197. X| 6C 65 70 68 61 6E 74 40 3E 40 5A 40 4D 2B 3D 40 | lephant@>@Z@M+=@ |
  198. X| 7B 54 75 72 6B 65 79 40 7D 0A 40 24 40 3C 45 6C | {Turkey@}.@$@<El |
  199. X| 65 70 68 61 6E 74 40 3E 40 5A 40 4D 2B 3D 40 7B | ephant@>@Z@M+=@{ |
  200. X| 54 75 72 6B 65 79 40 7D 0A 40 41 40 3C 45 72 72 | Turkey@}.@A@<Err |
  201. X| 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E | or recovery poin |
  202. X| 74 40 3E 0A 0A 39 2E 20 43 68 65 63 6B 20 74 68 | t@>..9. Check th |
  203. X| 61 74 20 6E 6F 6E 2D 65 78 69 73 74 65 6E 74 20 | at non-existent  |
  204. X| 66 6F 72 6D 61 6C 20 70 61 72 61 6D 65 74 65 72 | formal parameter |
  205. X| 73 20 61 72 65 20 63 61 75 67 68 74 2E 0A 0A 40 | s are caught...@ |
  206. X| 24 40 3C 5A 65 72 6F 40 3E 40 5A 40 7B 53 6C 6F | $@<Zero@>@Z@{Slo |
  207. X| 74 68 40 31 57 61 6C 72 75 73 40 7D 0A 40 41 40 | th@1Walrus@}.@A@ |
  208. X| 3C 45 72 72 6F 72 20 72 65 63 6F 76 65 72 79 20 | <Error recovery  |
  209. X| 70 6F 69 6E 74 40 3E 0A 0A 40 24 40 3C 4F 6E 65 | point@>..@$@<One |
  210. X| 40 3E 40 28 40 31 40 29 40 5A 40 7B 53 6C 6F 74 | @>@(@1@)@Z@{Slot |
  211. X| 68 40 32 57 61 6C 72 75 73 40 7D 0A 40 41 40 3C | h@2Walrus@}.@A@< |
  212. X| 45 72 72 6F 72 20 72 65 63 6F 76 65 72 79 20 70 | Error recovery p |
  213. X| 6F 69 6E 74 40 3E 0A 0A 40 24 40 3C 4D 61 6E 79 | oint@>..@$@<Many |
  214. X| 40 3E 40 28 40 37 40 29 40 5A 40 7B 53 6C 6F 74 | @>@(@7@)@Z@{Slot |
  215. X| 68 40 38 57 61 6C 72 75 73 40 7D 0A 40 41 40 3C | h@8Walrus@}.@A@< |
  216. X| 45 72 72 6F 72 20 72 65 63 6F 76 65 72 79 20 70 | Error recovery p |
  217. X| 6F 69 6E 74 40 3E 0A                            | oint@>.          |
  218. X+-------------------------------------------------+------------------+
  219. X
  220. X
  221. X=========================== Start of LINE LIST DUMP ============================
  222. X
  223. Globl Local| Text
  224. X-----------+--------------------------------------------------------------------
  225. X00001 00001| PR08: Test semantic checking of macro definitions.<010>
  226. X00002 00002| <010>
  227. X00003 00003| Trip parser to be sure that we won't get any output files!<010>
  228. X00004 00004| @><010>
  229. X00005 00005| <010>
  230. X00006 00006| 1. File macro has parameters. Error.<010>
  231. X00007 00007| @O@<Sloth 1@>@(@3@)@{Walrus@}<010>
  232. X00008 00008| @A@<Error recovery point@><010>
  233. X00009 00009| <010>
  234. X00010 00010| 2. File macro is additive. Error.<010>
  235. X00011 00011| @O@<Sloth 2@>+=@{Walrus@}<010>
  236. X00012 00012| @A@<Error recovery point@><010>
  237. X00013 00013| <010>
  238. X00014 00014| 3. File macro has too long a name. The test name has 1200 characters. Err.<010>
  239. X00015 00015| Note: This test can't test the error message if the maximum length of a<010>
  240. X00016 00016| macro name is less than the maximum length of a file name as the name<010>
  241. X00017 00017| error is caught first.<010>
  242. X00018 00018| @p maximum_input_line_length = infinity<010>
  243. X00019 00019| @O@<1234567890(elided by comp.sources.unix moderator)1234567890@>@{@}<010>
  244. X00020 00020| @A@<Error recovery point@><010>
  245. X00021 00021| <010>
  246. X00022 00022| 4. File macro has zero or many attributes. Error.<010>
  247. X00023 00023| @O@<Sloth 3@>@Z@{Walrus@}<010>
  248. X00024 00024| @A@<Error recovery point@><010>
  249. X00025 00025| <010>
  250. X00026 00026| @O@<Sloth 4@>@M@{Walrus@}<010>
  251. X00027 00027| @A@<Error recovery point@><010>
  252. X00028 00028| <010>
  253. X00029 00029| @O@<Sloth 5@>@Z@M@{Walrus@}<010>
  254. X00030 00030| @A@<Error recovery point@><010>
  255. X00031 00031| <010>
  256. X00032 00032| 5. Previous definition is full, current is additive.<010>
  257. X00033 00033| @$@<Walrus 1@>==@{Sloth@}<010>
  258. X00034 00034| @$@<Walrus 1@>+=@{Aardvark@}<010>
  259. X00035 00035| @A@<Error recovery point@><010>
  260. X00036 00036| <010>
  261. X00037 00037| 6. Previous definition is additive, current is full.<010>
  262. X00038 00038| @$@<Walrus 2@>+=@{Sloth@}<010>
  263. X00039 00039| @$@<Walrus 2@>==@{Aardvark@}<010>
  264. X00040 00040| @A@<Error recovery point@><010>
  265. X00041 00041| <010>
  266. X00042 00042| 7. Non-first body part of partial has parameter.<010>
  267. X00043 00043| @$@<Unicorn@>@(@3@)+=@{Turkey@}<010>
  268. X00044 00044| @$@<Unicorn@>@(@3@)+=@{Turkey@}<010>
  269. X00045 00045| @A@<Error recovery point@><010>
  270. X00046 00046| <010>
  271. X00047 00047| 8. Zero or many attributes on non-first body part of additive.<010>
  272. X00048 00048| @$@<Elephant@>@Z@M+=@{Turkey@}<010>
  273. X00049 00049| @$@<Elephant@>@Z@M+=@{Turkey@}<010>
  274. X00050 00050| @A@<Error recovery point@><010>
  275. X00051 00051| <010>
  276. X00052 00052| 9. Check that non-existent formal parameters are caught.<010>
  277. X00053 00053| <010>
  278. X00054 00054| @$@<Zero@>@Z@{Sloth@1Walrus@}<010>
  279. X00055 00055| @A@<Error recovery point@><010>
  280. X00056 00056| <010>
  281. X00057 00057| @$@<One@>@(@1@)@Z@{Sloth@2Walrus@}<010>
  282. X00058 00058| @A@<Error recovery point@><010>
  283. X00059 00059| <010>
  284. X00060 00060| @$@<Many@>@(@7@)@Z@{Sloth@8Walrus@}<010>
  285. X00061 00061| @A@<Error recovery point@><010>
  286. X00062 00062| <End-Of-File><010>
  287. X-----------+--------------------------------------------------------------------
  288. Globl Local| Text
  289. X
  290. X============================ End of LINE LIST DUMP =============================
  291. X
  292. X
  293. X=========================== Start of TOKEN LIST DUMP ===========================
  294. X
  295. Summary: There are 245 tokens in the token list.
  296. X
  297. Line[Column]: Token Description
  298. X-------------------------------
  299. X
  300. X0001[01]: Text. Text scrap[Grey]="PR08: Test semantic checking of macro definitions.<010>
  301. X<010>
  302. Trip parser to be sure that we won't get any output files!<010>
  303. X"
  304. X0004[01]: @> Close name. 
  305. X0004[03]: Text. Text scrap[Grey]="<010>
  306. X<010>
  307. X1. File macro has parameters. Error.<010>
  308. X"
  309. X0007[01]: @F File defn. 
  310. X0007[03]: @< Open name. 
  311. X0007[05]: Text. Text scrap[Grey]="Sloth 1"
  312. X0007[12]: @> Close name. 
  313. X0007[14]: @( Open param. 
  314. X0007[16]: @n Parameter. Parameterno=3.
  315. X0007[18]: @} Close param. 
  316. X0007[20]: @{ Open defn. 
  317. X0007[22]: Text. Text scrap[Grey]="Walrus"
  318. X0007[28]: @} Close defn. 
  319. X0007[30]: Text. Text scrap[White]="<010>
  320. X"
  321. X0008[01]: @A New section (Level 1). 
  322. X0008[03]: @< Open name. 
  323. X0008[05]: Text. Text scrap[Grey]="Error recovery point"
  324. X0008[25]: @> Close name. 
  325. X0008[27]: Text. Text scrap[Grey]="<010>
  326. X<010>
  327. X2. File macro is additive. Error.<010>
  328. X"
  329. X0011[01]: @F File defn. 
  330. X0011[03]: @< Open name. 
  331. X0011[05]: Text. Text scrap[Grey]="Sloth 2"
  332. X0011[12]: @> Close name. 
  333. X0011[14]: Text. Text scrap[Grey]="+="
  334. X0011[16]: @{ Open defn. 
  335. X0011[18]: Text. Text scrap[Grey]="Walrus"
  336. X0011[24]: @} Close defn. 
  337. X0011[26]: Text. Text scrap[White]="<010>
  338. X"
  339. X0012[01]: @A New section (Level 1). 
  340. X0012[03]: @< Open name. 
  341. X0012[05]: Text. Text scrap[Grey]="Error recovery point"
  342. X0012[25]: @> Close name. 
  343. X0012[27]: Text. Text scrap[Grey]="<010>
  344. X<010>
  345. X3. File macro has too long a name. The test name has 1200 characters. Err.<010>
  346. Note: This test can't test the error message if the maximum length of a<010>
  347. macro name is less than the maximum length of a file name as the name<010>
  348. error is caught first.<010>
  349. X"
  350. X0019[01]: @F File defn. 
  351. X0019[03]: @< Open name. 
  352. X0019[05]: Text. Text scrap[Grey]="1234567890(elided by comp.sources.unix moderator)1234567890"
  353. X0019[1205]: @> Close name. 
  354. X0019[1207]: @{ Open defn. 
  355. X0019[1209]: @} Close defn. 
  356. X0019[1211]: Text. Text scrap[White]="<010>
  357. X"
  358. X0020[01]: @A New section (Level 1). 
  359. X0020[03]: @< Open name. 
  360. X0020[05]: Text. Text scrap[Grey]="Error recovery point"
  361. X0020[25]: @> Close name. 
  362. X0020[27]: Text. Text scrap[Grey]="<010>
  363. X<010>
  364. X4. File macro has zero or many attributes. Error.<010>
  365. X"
  366. X0023[01]: @F File defn. 
  367. X0023[03]: @< Open name. 
  368. X0023[05]: Text. Text scrap[Grey]="Sloth 3"
  369. X0023[12]: @> Close name. 
  370. X0023[14]: @Z Zero calls. 
  371. X0023[16]: @{ Open defn. 
  372. X0023[18]: Text. Text scrap[Grey]="Walrus"
  373. X0023[24]: @} Close defn. 
  374. X0023[26]: Text. Text scrap[White]="<010>
  375. X"
  376. X0024[01]: @A New section (Level 1). 
  377. X0024[03]: @< Open name. 
  378. X0024[05]: Text. Text scrap[Grey]="Error recovery point"
  379. X0024[25]: @> Close name. 
  380. X0024[27]: Text. Text scrap[White]="<010>
  381. X<010>
  382. X"
  383. X0026[01]: @F File defn. 
  384. X0026[03]: @< Open name. 
  385. X0026[05]: Text. Text scrap[Grey]="Sloth 4"
  386. X0026[12]: @> Close name. 
  387. X0026[14]: @M Many calls. 
  388. X0026[16]: @{ Open defn. 
  389. X0026[18]: Text. Text scrap[Grey]="Walrus"
  390. X0026[24]: @} Close defn. 
  391. X0026[26]: Text. Text scrap[White]="<010>
  392. X"
  393. X0027[01]: @A New section (Level 1). 
  394. X0027[03]: @< Open name. 
  395. X0027[05]: Text. Text scrap[Grey]="Error recovery point"
  396. X0027[25]: @> Close name. 
  397. X0027[27]: Text. Text scrap[White]="<010>
  398. X<010>
  399. X"
  400. X0029[01]: @F File defn. 
  401. X0029[03]: @< Open name. 
  402. X0029[05]: Text. Text scrap[Grey]="Sloth 5"
  403. X0029[12]: @> Close name. 
  404. X0029[14]: @Z Zero calls. 
  405. X0029[16]: @M Many calls. 
  406. X0029[18]: @{ Open defn. 
  407. X0029[20]: Text. Text scrap[Grey]="Walrus"
  408. X0029[26]: @} Close defn. 
  409. X0029[28]: Text. Text scrap[White]="<010>
  410. X"
  411. X0030[01]: @A New section (Level 1). 
  412. X0030[03]: @< Open name. 
  413. X0030[05]: Text. Text scrap[Grey]="Error recovery point"
  414. X0030[25]: @> Close name. 
  415. X0030[27]: Text. Text scrap[Grey]="<010>
  416. X<010>
  417. X5. Previous definition is full, current is additive.<010>
  418. X"
  419. X0033[01]: @$ Macro defn. 
  420. X0033[03]: @< Open name. 
  421. X0033[05]: Text. Text scrap[Grey]="Walrus 1"
  422. X0033[13]: @> Close name. 
  423. X0033[15]: Text. Text scrap[Grey]="=="
  424. X0033[17]: @{ Open defn. 
  425. X0033[19]: Text. Text scrap[Grey]="Sloth"
  426. X0033[24]: @} Close defn. 
  427. X0033[26]: Text. Text scrap[White]="<010>
  428. X"
  429. X0034[01]: @$ Macro defn. 
  430. X0034[03]: @< Open name. 
  431. X0034[05]: Text. Text scrap[Grey]="Walrus 1"
  432. X0034[13]: @> Close name. 
  433. X0034[15]: Text. Text scrap[Grey]="+="
  434. X0034[17]: @{ Open defn. 
  435. X0034[19]: Text. Text scrap[Grey]="Aardvark"
  436. X0034[27]: @} Close defn. 
  437. X0034[29]: Text. Text scrap[White]="<010>
  438. X"
  439. X0035[01]: @A New section (Level 1). 
  440. X0035[03]: @< Open name. 
  441. X0035[05]: Text. Text scrap[Grey]="Error recovery point"
  442. X0035[25]: @> Close name. 
  443. X0035[27]: Text. Text scrap[Grey]="<010>
  444. X<010>
  445. X6. Previous definition is additive, current is full.<010>
  446. X"
  447. X0038[01]: @$ Macro defn. 
  448. X0038[03]: @< Open name. 
  449. X0038[05]: Text. Text scrap[Grey]="Walrus 2"
  450. X0038[13]: @> Close name. 
  451. X0038[15]: Text. Text scrap[Grey]="+="
  452. X0038[17]: @{ Open defn. 
  453. X0038[19]: Text. Text scrap[Grey]="Sloth"
  454. X0038[24]: @} Close defn. 
  455. X0038[26]: Text. Text scrap[White]="<010>
  456. X"
  457. X0039[01]: @$ Macro defn. 
  458. X0039[03]: @< Open name. 
  459. X0039[05]: Text. Text scrap[Grey]="Walrus 2"
  460. X0039[13]: @> Close name. 
  461. X0039[15]: Text. Text scrap[Grey]="=="
  462. X0039[17]: @{ Open defn. 
  463. X0039[19]: Text. Text scrap[Grey]="Aardvark"
  464. X0039[27]: @} Close defn. 
  465. X0039[29]: Text. Text scrap[White]="<010>
  466. X"
  467. X0040[01]: @A New section (Level 1). 
  468. X0040[03]: @< Open name. 
  469. X0040[05]: Text. Text scrap[Grey]="Error recovery point"
  470. X0040[25]: @> Close name. 
  471. X0040[27]: Text. Text scrap[Grey]="<010>
  472. X<010>
  473. X7. Non-first body part of partial has parameter.<010>
  474. X"
  475. X0043[01]: @$ Macro defn. 
  476. X0043[03]: @< Open name. 
  477. X0043[05]: Text. Text scrap[Grey]="Unicorn"
  478. X0043[12]: @> Close name. 
  479. X0043[14]: @( Open param. 
  480. X0043[16]: @n Parameter. Parameterno=3.
  481. X0043[18]: @} Close param. 
  482. X0043[20]: Text. Text scrap[Grey]="+="
  483. X0043[22]: @{ Open defn. 
  484. X0043[24]: Text. Text scrap[Grey]="Turkey"
  485. X0043[30]: @} Close defn. 
  486. X0043[32]: Text. Text scrap[White]="<010>
  487. X"
  488. X0044[01]: @$ Macro defn. 
  489. X0044[03]: @< Open name. 
  490. X0044[05]: Text. Text scrap[Grey]="Unicorn"
  491. X0044[12]: @> Close name. 
  492. X0044[14]: @( Open param. 
  493. X0044[16]: @n Parameter. Parameterno=3.
  494. X0044[18]: @} Close param. 
  495. X0044[20]: Text. Text scrap[Grey]="+="
  496. X0044[22]: @{ Open defn. 
  497. X0044[24]: Text. Text scrap[Grey]="Turkey"
  498. X0044[30]: @} Close defn. 
  499. X0044[32]: Text. Text scrap[White]="<010>
  500. X"
  501. X0045[01]: @A New section (Level 1). 
  502. X0045[03]: @< Open name. 
  503. X0045[05]: Text. Text scrap[Grey]="Error recovery point"
  504. X0045[25]: @> Close name. 
  505. X0045[27]: Text. Text scrap[Grey]="<010>
  506. X<010>
  507. X8. Zero or many attributes on non-first body part of additive.<010>
  508. X"
  509. X0048[01]: @$ Macro defn. 
  510. X0048[03]: @< Open name. 
  511. X0048[05]: Text. Text scrap[Grey]="Elephant"
  512. X0048[13]: @> Close name. 
  513. X0048[15]: @Z Zero calls. 
  514. X0048[17]: @M Many calls. 
  515. X0048[19]: Text. Text scrap[Grey]="+="
  516. X0048[21]: @{ Open defn. 
  517. X0048[23]: Text. Text scrap[Grey]="Turkey"
  518. X0048[29]: @} Close defn. 
  519. X0048[31]: Text. Text scrap[White]="<010>
  520. X"
  521. X0049[01]: @$ Macro defn. 
  522. X0049[03]: @< Open name. 
  523. X0049[05]: Text. Text scrap[Grey]="Elephant"
  524. X0049[13]: @> Close name. 
  525. X0049[15]: @Z Zero calls. 
  526. X0049[17]: @M Many calls. 
  527. X0049[19]: Text. Text scrap[Grey]="+="
  528. X0049[21]: @{ Open defn. 
  529. X0049[23]: Text. Text scrap[Grey]="Turkey"
  530. X0049[29]: @} Close defn. 
  531. X0049[31]: Text. Text scrap[White]="<010>
  532. X"
  533. X0050[01]: @A New section (Level 1). 
  534. X0050[03]: @< Open name. 
  535. X0050[05]: Text. Text scrap[Grey]="Error recovery point"
  536. X0050[25]: @> Close name. 
  537. X0050[27]: Text. Text scrap[Grey]="<010>
  538. X<010>
  539. X9. Check that non-existent formal parameters are caught.<010>
  540. X<010>
  541. X"
  542. X0054[01]: @$ Macro defn. 
  543. X0054[03]: @< Open name. 
  544. X0054[05]: Text. Text scrap[Grey]="Zero"
  545. X0054[09]: @> Close name. 
  546. X0054[11]: @Z Zero calls. 
  547. X0054[13]: @{ Open defn. 
  548. X0054[15]: Text. Text scrap[Grey]="Sloth"
  549. X0054[20]: @n Parameter. Parameterno=1.
  550. X0054[22]: Text. Text scrap[Grey]="Walrus"
  551. X0054[28]: @} Close defn. 
  552. X0054[30]: Text. Text scrap[White]="<010>
  553. X"
  554. X0055[01]: @A New section (Level 1). 
  555. X0055[03]: @< Open name. 
  556. X0055[05]: Text. Text scrap[Grey]="Error recovery point"
  557. X0055[25]: @> Close name. 
  558. X0055[27]: Text. Text scrap[White]="<010>
  559. X<010>
  560. X"
  561. X0057[01]: @$ Macro defn. 
  562. X0057[03]: @< Open name. 
  563. X0057[05]: Text. Text scrap[Grey]="One"
  564. X0057[08]: @> Close name. 
  565. X0057[10]: @( Open param. 
  566. X0057[12]: @n Parameter. Parameterno=1.
  567. X0057[14]: @} Close param. 
  568. X0057[16]: @Z Zero calls. 
  569. X0057[18]: @{ Open defn. 
  570. X0057[20]: Text. Text scrap[Grey]="Sloth"
  571. X0057[25]: @n Parameter. Parameterno=2.
  572. X0057[27]: Text. Text scrap[Grey]="Walrus"
  573. X0057[33]: @} Close defn. 
  574. X0057[35]: Text. Text scrap[White]="<010>
  575. X"
  576. X0058[01]: @A New section (Level 1). 
  577. X0058[03]: @< Open name. 
  578. X0058[05]: Text. Text scrap[Grey]="Error recovery point"
  579. X0058[25]: @> Close name. 
  580. X0058[27]: Text. Text scrap[White]="<010>
  581. X<010>
  582. X"
  583. X0060[01]: @$ Macro defn. 
  584. X0060[03]: @< Open name. 
  585. X0060[05]: Text. Text scrap[Grey]="Many"
  586. X0060[09]: @> Close name. 
  587. X0060[11]: @( Open param. 
  588. X0060[13]: @n Parameter. Parameterno=7.
  589. X0060[15]: @} Close param. 
  590. X0060[17]: @Z Zero calls. 
  591. X0060[19]: @{ Open defn. 
  592. X0060[21]: Text. Text scrap[Grey]="Sloth"
  593. X0060[26]: @n Parameter. Parameterno=8.
  594. X0060[28]: Text. Text scrap[Grey]="Walrus"
  595. X0060[34]: @} Close defn. 
  596. X0060[36]: Text. Text scrap[White]="<010>
  597. X"
  598. X0061[01]: @A New section (Level 1). 
  599. X0061[03]: @< Open name. 
  600. X0061[05]: Text. Text scrap[Grey]="Error recovery point"
  601. X0061[25]: @> Close name. 
  602. X0061[27]: Text. Text scrap[White]="<010>
  603. X"
  604. X0062[01]: End Of File. 
  605. X============================ End of TOKEN LIST DUMP ============================
  606. X
  607. X
  608. X========================== Start of MACRO TABLE DUMP ===========================
  609. X
  610. X
  611. X------------------- Start of Macro Dump --------------------
  612. Macro Name  : "Elephant"
  613. Defined?    : Yes.
  614. Parameters  : 0
  615. Additive?   : Yes.
  616. Zero Calls? : Yes.
  617. Many Calls? : Yes.
  618. Output File?: No.
  619. Call list   :
  620. Macro body  :
  621. X
  622. X--Start of List of Body Parts--
  623. This macro has 1 body part.
  624. Body part 1: Seqnum=4, Pos(L,C)=(48,3), Expression follows:
  625. X
  626. X---- Start of Expression ----
  627. X
  628. X----- Start Text Element -----
  629. Text scrap[Grey]="Turkey"
  630. X------ End Text Element ------
  631. X
  632. X----- End of Expression -----
  633. X
  634. X---End of List of Body Parts---
  635. X
  636. X-------------------- End of Macro Dump ---------------------
  637. X
  638. X
  639. X
  640. X------------------- Start of Macro Dump --------------------
  641. Macro Name  : "Many"
  642. Defined?    : Yes.
  643. Parameters  : 7
  644. Additive?   : No.
  645. Zero Calls? : Yes.
  646. Many Calls? : No.
  647. Output File?: No.
  648. Call list   :
  649. Macro body  :
  650. X
  651. X--Start of List of Body Parts--
  652. This macro has 1 body part.
  653. Body part 1: Seqnum=7, Pos(L,C)=(60,3), Expression follows:
  654. X
  655. X---- Start of Expression ----
  656. X
  657. X----- Start Text Element -----
  658. Text scrap[Grey]="Sloth"
  659. X------ End Text Element ------
  660. X
  661. X
  662. X-- Start Parameter Element --
  663. Parameter number=8.
  664. Parameter is of macro "Many".
  665. X--- End Parameter Element ---
  666. X
  667. X
  668. X----- Start Text Element -----
  669. Text scrap[Grey]="Walrus"
  670. X------ End Text Element ------
  671. X
  672. X----- End of Expression -----
  673. X
  674. X---End of List of Body Parts---
  675. X
  676. X-------------------- End of Macro Dump ---------------------
  677. X
  678. X
  679. X
  680. X------------------- Start of Macro Dump --------------------
  681. Macro Name  : "One"
  682. Defined?    : Yes.
  683. Parameters  : 1
  684. Additive?   : No.
  685. Zero Calls? : Yes.
  686. Many Calls? : No.
  687. Output File?: No.
  688. Call list   :
  689. Macro body  :
  690. X
  691. X--Start of List of Body Parts--
  692. This macro has 1 body part.
  693. Body part 1: Seqnum=6, Pos(L,C)=(57,3), Expression follows:
  694. X
  695. X---- Start of Expression ----
  696. X
  697. X----- Start Text Element -----
  698. Text scrap[Grey]="Sloth"
  699. X------ End Text Element ------
  700. X
  701. X
  702. X-- Start Parameter Element --
  703. Parameter number=2.
  704. Parameter is of macro "One".
  705. X--- End Parameter Element ---
  706. X
  707. X
  708. X----- Start Text Element -----
  709. Text scrap[Grey]="Walrus"
  710. X------ End Text Element ------
  711. X
  712. X----- End of Expression -----
  713. X
  714. X---End of List of Body Parts---
  715. X
  716. X-------------------- End of Macro Dump ---------------------
  717. X
  718. X
  719. X
  720. X------------------- Start of Macro Dump --------------------
  721. Macro Name  : "Sloth 1"
  722. Defined?    : No.
  723. X-------------------- End of Macro Dump ---------------------
  724. X
  725. X
  726. X
  727. X------------------- Start of Macro Dump --------------------
  728. Macro Name  : "Sloth 2"
  729. Defined?    : No.
  730. X-------------------- End of Macro Dump ---------------------
  731. X
  732. X
  733. X
  734. X------------------- Start of Macro Dump --------------------
  735. Macro Name  : "Sloth 3"
  736. Defined?    : No.
  737. X-------------------- End of Macro Dump ---------------------
  738. X
  739. X
  740. X
  741. X------------------- Start of Macro Dump --------------------
  742. Macro Name  : "Sloth 4"
  743. Defined?    : No.
  744. X-------------------- End of Macro Dump ---------------------
  745. X
  746. X
  747. X
  748. X------------------- Start of Macro Dump --------------------
  749. Macro Name  : "Sloth 5"
  750. Defined?    : No.
  751. X-------------------- End of Macro Dump ---------------------
  752. X
  753. X
  754. X
  755. X------------------- Start of Macro Dump --------------------
  756. Macro Name  : "Unicorn"
  757. Defined?    : Yes.
  758. Parameters  : 3
  759. Additive?   : Yes.
  760. Zero Calls? : No.
  761. Many Calls? : No.
  762. Output File?: No.
  763. Call list   :
  764. Macro body  :
  765. X
  766. X--Start of List of Body Parts--
  767. This macro has 1 body part.
  768. Body part 1: Seqnum=3, Pos(L,C)=(43,3), Expression follows:
  769. X
  770. X---- Start of Expression ----
  771. X
  772. X----- Start Text Element -----
  773. Text scrap[Grey]="Turkey"
  774. X------ End Text Element ------
  775. X
  776. X----- End of Expression -----
  777. X
  778. X---End of List of Body Parts---
  779. X
  780. X-------------------- End of Macro Dump ---------------------
  781. X
  782. X
  783. X
  784. X------------------- Start of Macro Dump --------------------
  785. Macro Name  : "Walrus 1"
  786. Defined?    : Yes.
  787. Parameters  : 0
  788. Additive?   : No.
  789. Zero Calls? : No.
  790. Many Calls? : No.
  791. Output File?: No.
  792. Call list   :
  793. Macro body  :
  794. X
  795. X--Start of List of Body Parts--
  796. This macro has 1 body part.
  797. Body part 1: Seqnum=1, Pos(L,C)=(33,3), Expression follows:
  798. X
  799. X---- Start of Expression ----
  800. X
  801. X----- Start Text Element -----
  802. Text scrap[Grey]="Sloth"
  803. X------ End Text Element ------
  804. X
  805. X----- End of Expression -----
  806. X
  807. X---End of List of Body Parts---
  808. X
  809. X-------------------- End of Macro Dump ---------------------
  810. X
  811. X
  812. X
  813. X------------------- Start of Macro Dump --------------------
  814. Macro Name  : "Walrus 2"
  815. Defined?    : Yes.
  816. Parameters  : 0
  817. Additive?   : Yes.
  818. Zero Calls? : No.
  819. Many Calls? : No.
  820. Output File?: No.
  821. Call list   :
  822. Macro body  :
  823. X
  824. X--Start of List of Body Parts--
  825. This macro has 1 body part.
  826. Body part 1: Seqnum=2, Pos(L,C)=(38,3), Expression follows:
  827. X
  828. X---- Start of Expression ----
  829. X
  830. X----- Start Text Element -----
  831. Text scrap[Grey]="Sloth"
  832. X------ End Text Element ------
  833. X
  834. X----- End of Expression -----
  835. X
  836. X---End of List of Body Parts---
  837. X
  838. X-------------------- End of Macro Dump ---------------------
  839. X
  840. X
  841. X
  842. X------------------- Start of Macro Dump --------------------
  843. Macro Name  : "Zero"
  844. Defined?    : Yes.
  845. Parameters  : 0
  846. Additive?   : No.
  847. Zero Calls? : Yes.
  848. Many Calls? : No.
  849. Output File?: No.
  850. Call list   :
  851. Macro body  :
  852. X
  853. X--Start of List of Body Parts--
  854. This macro has 1 body part.
  855. Body part 1: Seqnum=5, Pos(L,C)=(54,3), Expression follows:
  856. X
  857. X---- Start of Expression ----
  858. X
  859. X----- Start Text Element -----
  860. Text scrap[Grey]="Sloth"
  861. X------ End Text Element ------
  862. X
  863. X
  864. X-- Start Parameter Element --
  865. Parameter number=1.
  866. Parameter is of macro "Zero".
  867. X--- End Parameter Element ---
  868. X
  869. X
  870. X----- Start Text Element -----
  871. Text scrap[Grey]="Walrus"
  872. X------ End Text Element ------
  873. X
  874. X----- End of Expression -----
  875. X
  876. X---End of List of Body Parts---
  877. X
  878. X-------------------- End of Macro Dump ---------------------
  879. X
  880. X
  881. X
  882. X=========================== End of MACRO TABLE DUMP ============================
  883. X
  884. X
  885. X========================= Start of DOCUMENT LIST DUMP ==========================
  886. X
  887. X
  888. TEXT COMPONENT: Pos(L,C)=(1,1). 
  889. X
  890. X-- Start of Text Scrap List --
  891. Text scrap[Grey]="PR08: Test semantic checking of macro definitions.<010>
  892. X<010>
  893. Trip parser to be sure that we won't get any output files!<010>
  894. X"
  895. X--- End of Text Scrap List ---
  896. X
  897. X
  898. TEXT COMPONENT: Pos(L,C)=(4,3). 
  899. X
  900. X-- Start of Text Scrap List --
  901. Text scrap[Grey]="<010>
  902. X<010>
  903. X1. File macro has parameters. Error.<010>
  904. X"
  905. X--- End of Text Scrap List ---
  906. X
  907. X
  908. TYPESETTER DIRECTIVE COMPONENT: 
  909. X   Section "1", Section name="Error recovery point".
  910. X
  911. TEXT COMPONENT: Pos(L,C)=(8,27). 
  912. X
  913. X-- Start of Text Scrap List --
  914. Text scrap[Grey]="<010>
  915. X<010>
  916. X2. File macro is additive. Error.<010>
  917. X"
  918. X--- End of Text Scrap List ---
  919. X
  920. X
  921. TYPESETTER DIRECTIVE COMPONENT: 
  922. X   Section "2", Section name="Error recovery point".
  923. X
  924. TEXT COMPONENT: Pos(L,C)=(12,27). 
  925. X
  926. X-- Start of Text Scrap List --
  927. Text scrap[Grey]="<010>
  928. X<010>
  929. X3. File macro has too long a name. The test name has 1200 characters. Err.<010>
  930. Note: This test can't test the error message if the maximum length of a<010>
  931. macro name is less than the maximum length of a file name as the name<010>
  932. error is caught first.<010>
  933. X"
  934. X--- End of Text Scrap List ---
  935. X
  936. X
  937. TYPESETTER DIRECTIVE COMPONENT: 
  938. X   Section "3", Section name="Error recovery point".
  939. X
  940. TEXT COMPONENT: Pos(L,C)=(20,27). 
  941. X
  942. X-- Start of Text Scrap List --
  943. Text scrap[Grey]="<010>
  944. X<010>
  945. X4. File macro has zero or many attributes. Error.<010>
  946. X"
  947. X--- End of Text Scrap List ---
  948. X
  949. X
  950. TYPESETTER DIRECTIVE COMPONENT: 
  951. X   Section "4", Section name="Error recovery point".
  952. X
  953. TEXT COMPONENT: Pos(L,C)=(24,27). 
  954. X
  955. X-- Start of Text Scrap List --
  956. Text scrap[White]="<010>
  957. X<010>
  958. X"
  959. X--- End of Text Scrap List ---
  960. X
  961. X
  962. TYPESETTER DIRECTIVE COMPONENT: 
  963. X   Section "5", Section name="Error recovery point".
  964. X
  965. TEXT COMPONENT: Pos(L,C)=(27,27). 
  966. X
  967. X-- Start of Text Scrap List --
  968. Text scrap[White]="<010>
  969. X<010>
  970. X"
  971. X--- End of Text Scrap List ---
  972. X
  973. X
  974. TYPESETTER DIRECTIVE COMPONENT: 
  975. X   Section "6", Section name="Error recovery point".
  976. X
  977. TEXT COMPONENT: Pos(L,C)=(30,27). 
  978. X
  979. X-- Start of Text Scrap List --
  980. Text scrap[Grey]="<010>
  981. X<010>
  982. X5. Previous definition is full, current is additive.<010>
  983. X"
  984. X--- End of Text Scrap List ---
  985. X
  986. X
  987. MACRO DEFINITION COMPONENT: Pos(L,C)=(33,1). 
  988. Part 1 of macro @<Walrus 1@>.
  989. X
  990. TEXT COMPONENT: Pos(L,C)=(33,26). 
  991. X
  992. X-- Start of Text Scrap List --
  993. Text scrap[White]="<010>
  994. X"
  995. X--- End of Text Scrap List ---
  996. X
  997. X
  998. TYPESETTER DIRECTIVE COMPONENT: 
  999. X   Section "7", Section name="Error recovery point".
  1000. X
  1001. TEXT COMPONENT: Pos(L,C)=(35,27). 
  1002. X
  1003. X-- Start of Text Scrap List --
  1004. Text scrap[Grey]="<010>
  1005. X<010>
  1006. X6. Previous definition is additive, current is full.<010>
  1007. X"
  1008. X--- End of Text Scrap List ---
  1009. X
  1010. X
  1011. MACRO DEFINITION COMPONENT: Pos(L,C)=(38,1). 
  1012. Part 1 of macro @<Walrus 2@>.
  1013. X
  1014. TEXT COMPONENT: Pos(L,C)=(38,26). 
  1015. X
  1016. X-- Start of Text Scrap List --
  1017. Text scrap[White]="<010>
  1018. X"
  1019. X--- End of Text Scrap List ---
  1020. X
  1021. X
  1022. TYPESETTER DIRECTIVE COMPONENT: 
  1023. X   Section "8", Section name="Error recovery point".
  1024. X
  1025. TEXT COMPONENT: Pos(L,C)=(40,27). 
  1026. X
  1027. X-- Start of Text Scrap List --
  1028. Text scrap[Grey]="<010>
  1029. X<010>
  1030. X7. Non-first body part of partial has parameter.<010>
  1031. X"
  1032. X--- End of Text Scrap List ---
  1033. X
  1034. X
  1035. MACRO DEFINITION COMPONENT: Pos(L,C)=(43,1). 
  1036. Part 1 of macro @<Unicorn@>.
  1037. X
  1038. TEXT COMPONENT: Pos(L,C)=(43,32). 
  1039. X
  1040. X-- Start of Text Scrap List --
  1041. Text scrap[White]="<010>
  1042. X"
  1043. X--- End of Text Scrap List ---
  1044. X
  1045. X
  1046. TYPESETTER DIRECTIVE COMPONENT: 
  1047. X   Section "9", Section name="Error recovery point".
  1048. X
  1049. TEXT COMPONENT: Pos(L,C)=(45,27). 
  1050. X
  1051. X-- Start of Text Scrap List --
  1052. Text scrap[Grey]="<010>
  1053. X<010>
  1054. X8. Zero or many attributes on non-first body part of additive.<010>
  1055. X"
  1056. X--- End of Text Scrap List ---
  1057. X
  1058. X
  1059. MACRO DEFINITION COMPONENT: Pos(L,C)=(48,1). 
  1060. Part 1 of macro @<Elephant@>.
  1061. X
  1062. TEXT COMPONENT: Pos(L,C)=(48,31). 
  1063. X
  1064. X-- Start of Text Scrap List --
  1065. Text scrap[White]="<010>
  1066. X"
  1067. X--- End of Text Scrap List ---
  1068. X
  1069. X
  1070. TYPESETTER DIRECTIVE COMPONENT: 
  1071. X   Section "10", Section name="Error recovery point".
  1072. X
  1073. TEXT COMPONENT: Pos(L,C)=(50,27). 
  1074. X
  1075. X-- Start of Text Scrap List --
  1076. Text scrap[Grey]="<010>
  1077. X<010>
  1078. X9. Check that non-existent formal parameters are caught.<010>
  1079. X<010>
  1080. X"
  1081. X--- End of Text Scrap List ---
  1082. X
  1083. X
  1084. MACRO DEFINITION COMPONENT: Pos(L,C)=(54,1). 
  1085. Part 1 of macro @<Zero@>.
  1086. X
  1087. TEXT COMPONENT: Pos(L,C)=(54,30). 
  1088. X
  1089. X-- Start of Text Scrap List --
  1090. Text scrap[White]="<010>
  1091. X"
  1092. X--- End of Text Scrap List ---
  1093. X
  1094. X
  1095. TYPESETTER DIRECTIVE COMPONENT: 
  1096. X   Section "11", Section name="Error recovery point".
  1097. X
  1098. TEXT COMPONENT: Pos(L,C)=(55,27). 
  1099. X
  1100. X-- Start of Text Scrap List --
  1101. Text scrap[White]="<010>
  1102. X<010>
  1103. X"
  1104. X--- End of Text Scrap List ---
  1105. X
  1106. X
  1107. MACRO DEFINITION COMPONENT: Pos(L,C)=(57,1). 
  1108. Part 1 of macro @<One@>.
  1109. X
  1110. TEXT COMPONENT: Pos(L,C)=(57,35). 
  1111. X
  1112. X-- Start of Text Scrap List --
  1113. Text scrap[White]="<010>
  1114. X"
  1115. X--- End of Text Scrap List ---
  1116. X
  1117. X
  1118. TYPESETTER DIRECTIVE COMPONENT: 
  1119. X   Section "12", Section name="Error recovery point".
  1120. X
  1121. TEXT COMPONENT: Pos(L,C)=(58,27). 
  1122. X
  1123. X-- Start of Text Scrap List --
  1124. Text scrap[White]="<010>
  1125. X<010>
  1126. X"
  1127. X--- End of Text Scrap List ---
  1128. X
  1129. X
  1130. MACRO DEFINITION COMPONENT: Pos(L,C)=(60,1). 
  1131. Part 1 of macro @<Many@>.
  1132. X
  1133. TEXT COMPONENT: Pos(L,C)=(60,36). 
  1134. X
  1135. X-- Start of Text Scrap List --
  1136. Text scrap[White]="<010>
  1137. X"
  1138. X--- End of Text Scrap List ---
  1139. X
  1140. X
  1141. TYPESETTER DIRECTIVE COMPONENT: 
  1142. X   Section "13", Section name="Error recovery point".
  1143. X
  1144. TEXT COMPONENT: Pos(L,C)=(61,27). 
  1145. X
  1146. X-- Start of Text Scrap List --
  1147. Text scrap[White]="<010>
  1148. X"
  1149. X--- End of Text Scrap List ---
  1150. X
  1151. X
  1152. X========================== End of DOCUMENT LIST DUMP ===========================
  1153. X
  1154. X
  1155. Global Local| Input File
  1156. X------------+-------------------------------------------------------------------
  1157. X     1     1| PR08: Test semantic checking of macro definitions.
  1158. X     2     2| 
  1159. X     3     3| Trip parser to be sure that we won't get any output files!
  1160. X     4     4| @>
  1161. X       Error|.^The parser was at the top level and was expecting
  1162. X            |.^one of: {Directive, Text, Macro definition, EOF}.
  1163. X     5     5| 
  1164. X     6     6| 1. File macro has parameters. Error.
  1165. X     7     7| @O@<Sloth 1@>@(@3@)@{Walrus@}
  1166. X            |...^Macro definition ignored.
  1167. X       Error|................^Macros attached to output files cannot be parameterized.
  1168. X            |................^Reason: No actual parameters would be available during
  1169. X            |................^        output file generation.
  1170. X            |....................^Skipping after error to the next major construct...
  1171. X     8     8| @A@<Error recovery point@>
  1172. X            |.^...skipped to here after the error.
  1173. X     9     9| 
  1174. X    10    10| 2. File macro is additive. Error.
  1175. X    11    11| @O@<Sloth 2@>+=@{Walrus@}
  1176. X            |...^Macro definition ignored.
  1177. X       Error|..............^Macros attached to output files cannot be additive.
  1178. X            |..............^Reason: Preventing this makes it easy to find output
  1179. X            |..............^file macros later, because there will be exactly one
  1180. X            |..............^@O declaration in the input file for each output file.
  1181. X            |..............^To do what you are trying to do, just create an additive
  1182. X            |..............^bridging macro, like this:
  1183. X            |..............^   @O@<prog.c@>@{@<Bridge@>@}
  1184. X            |..............^   @$@<Bridge@>+=@{void stringhack()...@}
  1185. X            |..............^   @$@<Bridge@>+=@{main()...@}
  1186. X            |................^Skipping after error to the next major construct...
  1187. X    12    12| @A@<Error recovery point@>
  1188. X            |.^...skipped to here after the error.
  1189. X    13    13| 
  1190. X    14    14| 3. File macro has too long a name. The test name has 1200 characters. Err.
  1191. X    15    15| Note: This test can't test the error message if the maximum length of a
  1192. X    16    16| macro name is less than the maximum length of a file name as the name
  1193. X    17    17| error is caught first.
  1194. X    18    18| @p maximum_input_line_length = infinity
  1195. X    19    19| @O@<1234567890(elided by comp.sources.unix moderator)1234567890@>@{@}
  1196. X       Error|.....^Name is too long.
  1197. X            |.....^The maximum length of a legal name is 80 characters.
  1198. X            |.....^Skipping after error to the next major construct...
  1199. X    20    20| @A@<Error recovery point@>
  1200. X            |.^...skipped to here after the error.
  1201. X    21    21| 
  1202. X    22    22| 4. File macro has zero or many attributes. Error.
  1203. X    23    23| @O@<Sloth 3@>@Z@{Walrus@}
  1204. X            |...^Macro definition ignored.
  1205. X       Error|..............^Macros attached to output files cannot have @Z or @M.
  1206. X            |..............^Reason: They are always called once to generate their
  1207. X            |..............^output file and they cannot be called from other macros.
  1208. X            |..............^Hence they are always called exactly once and so there
  1209. X            |..............^can be no need for @Z or @M in their declarations.
  1210. X            |................^Skipping after error to the next major construct...
  1211. X    24    24| @A@<Error recovery point@>
  1212. X            |.^...skipped to here after the error.
  1213. X    25    25| 
  1214. X    26    26| @O@<Sloth 4@>@M@{Walrus@}
  1215. X            |...^Macro definition ignored.
  1216. X       Error|..............^Macros attached to output files cannot have @Z or @M.
  1217. X            |..............^Reason: They are always called once to generate their
  1218. X            |..............^output file and they cannot be called from other macros.
  1219. X            |..............^Hence they are always called exactly once and so there
  1220. X            |..............^can be no need for @Z or @M in their declarations.
  1221. X            |................^Skipping after error to the next major construct...
  1222. X    27    27| @A@<Error recovery point@>
  1223. X            |.^...skipped to here after the error.
  1224. X    28    28| 
  1225. X    29    29| @O@<Sloth 5@>@Z@M@{Walrus@}
  1226. X            |...^Macro definition ignored.
  1227. X       Error|..............^Macros attached to output files cannot have @Z or @M.
  1228. X            |..............^Reason: They are always called once to generate their
  1229. X            |..............^output file and they cannot be called from other macros.
  1230. X            |..............^Hence they are always called exactly once and so there
  1231. X            |..............^can be no need for @Z or @M in their declarations.
  1232. X            |..................^Skipping after error to the next major construct...
  1233. X    30    30| @A@<Error recovery point@>
  1234. X            |.^...skipped to here after the error.
  1235. X    31    31| 
  1236. X    32    32| 5. Previous definition is full, current is additive.
  1237. X    33    33| @$@<Walrus 1@>==@{Sloth@}
  1238. X    34    34| @$@<Walrus 1@>+=@{Aardvark@}
  1239. X       Error|...^A full definition of this macro appears at line 33.
  1240. X            |...^Full and additive definitions of the same macro cannot coexist.
  1241. X            |...^Macro definition ignored.
  1242. X            |.................^Skipping after error to the next major construct...
  1243. X    35    35| @A@<Error recovery point@>
  1244. X            |.^...skipped to here after the error.
  1245. X    36    36| 
  1246. X    37    37| 6. Previous definition is additive, current is full.
  1247. X    38    38| @$@<Walrus 2@>+=@{Sloth@}
  1248. X    39    39| @$@<Walrus 2@>==@{Aardvark@}
  1249. X       Error|...^An additive definition of this macro appears at line 38.
  1250. X            |...^Full and additive definitions of the same macro cannot coexist.
  1251. X            |...^Macro definition ignored.
  1252. X            |.................^Skipping after error to the next major construct...
  1253. X    40    40| @A@<Error recovery point@>
  1254. X            |.^...skipped to here after the error.
  1255. X    41    41| 
  1256. X    42    42| 7. Non-first body part of partial has parameter.
  1257. X    43    43| @$@<Unicorn@>@(@3@)+=@{Turkey@}
  1258. X    44    44| @$@<Unicorn@>@(@3@)+=@{Turkey@}
  1259. X            |...^Macro definition ignored.
  1260. X       Error|................^The formal parameter list of an additive macro
  1261. X            |................^must be placed only in the first definition part.
  1262. X            |................^The first part of this macro appears at line 43.
  1263. X            |......................^Skipping after error to the next major construct...
  1264. X    45    45| @A@<Error recovery point@>
  1265. X            |.^...skipped to here after the error.
  1266. X    46    46| 
  1267. X    47    47| 8. Zero or many attributes on non-first body part of additive.
  1268. X    48    48| @$@<Elephant@>@Z@M+=@{Turkey@}
  1269. X    49    49| @$@<Elephant@>@Z@M+=@{Turkey@}
  1270. X            |...^Macro definition ignored.
  1271. X       Error|...............^@Z and @M modifiers for additive macros must
  1272. X            |...............^be placed only in the first definition part.
  1273. X            |...............^The first part of this macro appears at line 48.
  1274. X            |.....................^Skipping after error to the next major construct...
  1275. X    50    50| @A@<Error recovery point@>
  1276. X            |.^...skipped to here after the error.
  1277. X    51    51| 
  1278. X    52    52| 9. Check that non-existent formal parameters are caught.
  1279. X    53    53| 
  1280. X    54    54| @$@<Zero@>@Z@{Sloth@1Walrus@}
  1281. X       Error|....................^Macro being defined has only 0 parameters.
  1282. X    55    55| @A@<Error recovery point@>
  1283. X    56    56| 
  1284. X    57    57| @$@<One@>@(@1@)@Z@{Sloth@2Walrus@}
  1285. X       Error|.........................^Macro being defined has only 1 parameter.
  1286. X    58    58| @A@<Error recovery point@>
  1287. X    59    59| 
  1288. X    60    60| @$@<Many@>@(@7@)@Z@{Sloth@8Walrus@}
  1289. X       Error|..........................^Macro being defined has only 7 parameters.
  1290. X    61    61| @A@<Error recovery point@>
  1291. X            | <End-Of-File>
  1292. X------------+-------------------------------------------------------------------
  1293. X
  1294. There were 14 Errors.
  1295. END_OF_FILE
  1296. if test 48225 -ne `wc -c <'answers/pr08.lis'`; then
  1297.     echo shar: \"'answers/pr08.lis'\" unpacked with wrong size!
  1298. fi
  1299. # end of 'answers/pr08.lis'
  1300. fi
  1301. if test -f 'sources/parser.c' -a "${1}" != "-c" ; then 
  1302.   echo shar: Will not clobber existing file \"'sources/parser.c'\"
  1303. else
  1304. echo shar: Extracting \"'sources/parser.c'\" \(47198 characters\)
  1305. sed "s/^X//" >'sources/parser.c' <<'END_OF_FILE'
  1306. X/*##############################################################################
  1307. X
  1308. XFUNNNELWEB COPYRIGHT
  1309. X====================
  1310. XFunnelWeb is a literate-programming macro preprocessor.
  1311. X
  1312. Copyright (C) 1992 Ross N. Williams.
  1313. X
  1314. X   Ross N. Williams
  1315. X   ross@spam.adelaide.edu.au
  1316. X   16 Lerwick Avenue, Hazelwood Park 5066, Australia.
  1317. X
  1318. This program is free software; you can redistribute it and/or modify
  1319. it under the terms of Version 2 of the GNU General Public License as
  1320. published by the Free Software Foundation.
  1321. X
  1322. This program is distributed WITHOUT ANY WARRANTY; without even the implied
  1323. warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  1324. See Version 2 of the GNU General Public License for more details.
  1325. X
  1326. You should have received a copy of Version 2 of the GNU General Public
  1327. License along with this program. If not, you can FTP the license from
  1328. prep.ai.mit.edu/pub/gnu/COPYING-2 or write to the Free Software
  1329. XFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  1330. X
  1331. Section 2a of the license requires that all changes to this file be
  1332. recorded prominently in this file. Please record all changes here.
  1333. X
  1334. Programmers:
  1335. X   RNW  Ross N. Williams  ross@spam.adelaide.edu.au
  1336. X
  1337. Changes:
  1338. X   07-May-1992  RNW  Program prepared for release under GNU GPL V2.
  1339. X
  1340. X##############################################################################*/
  1341. X
  1342. X
  1343. X/******************************************************************************/
  1344. X/*                                    PARSER.C                                */
  1345. X/******************************************************************************/
  1346. X
  1347. X#include <setjmp.h>
  1348. X#include "style.h"
  1349. X
  1350. X#include "as.h"
  1351. X#include "data.h"
  1352. X#include "lister.h"
  1353. X#include "machin.h"
  1354. X#include "mapper.h"
  1355. X#include "memory.h"
  1356. X#include "misc.h"
  1357. X#include "parser.h"
  1358. X#include "section.h"
  1359. X#include "table.h"
  1360. X
  1361. X/******************************************************************************/
  1362. X
  1363. X#define DUMMYINT 0                 /* It doesn't matter what this value is!!! */
  1364. X#define TKPS &(p_tk->tk_ps)        /* A commonly used construct.              */
  1365. X
  1366. X/******************************************************************************/
  1367. X
  1368. X/* The following variables look after sections. */
  1369. LOCVAR sn_t     last_sn;   /* Hierarchical section number of last section.    */
  1370. LOCVAR ps_t     pssection; /* Position of last section.                       */
  1371. LOCVAR p_dc_t   p_secdc;   /* Pointer to current section document component.  */
  1372. LOCVAR tk_t    *p_tk;      /* Pointer to the current token (a structure).     */
  1373. LOCVAR ulong    sequence;  /* Current sequence number.                        */
  1374. LOCVAR jmp_buf  jmp_pos;   /* Setjmp() position of main parsing loop.         */
  1375. X
  1376. X/******************************************************************************/
  1377. X/*                             Comparison Functions                           */
  1378. X/******************************************************************************/
  1379. X
  1380. LOCAL sign cm_name P_((name_t *,name_t *));
  1381. LOCAL sign cm_name(name1,name2)
  1382. X/* Compares two names and returns:               */
  1383. X/*    -1 if name1 < name2                        */
  1384. X/*     0 if name1 = name2                        */
  1385. X/*     1 if name1 > name2                        */
  1386. X/* Provides a full ordering on the set of names. */
  1387. name_t *name1;
  1388. name_t *name2;
  1389. X{
  1390. X return signof(strcmp(&(*name1)[0],&(*name2)[0]));
  1391. X}
  1392. X
  1393. X/******************************************************************************/
  1394. X
  1395. LOCAL sign eq_txst P_((p_scls_t,char *));
  1396. LOCAL sign eq_txst(p_scls,p_str)
  1397. X/* The first argument is a list of text scraps.             */
  1398. X/* The second argument is an ordinary string.               */
  1399. X/* Returns TRUE iff the two are identical. Otherwise FALSE. */
  1400. p_scls_t  p_scls;
  1401. char     *p_str;
  1402. X{
  1403. X /* To compare the scrap list with the string, we run through the scrap list */
  1404. X /* comparing the bytes its scraps yield progressively with the string.      */
  1405. X /* The two scanning groups are (p_scls,p_sc,p_ch) and p_str.                */
  1406. X sc_t *p_sc;
  1407. X
  1408. X ls_fir(p_scls);
  1409. X ls_nxt(p_scls,PPV &p_sc);
  1410. X while (p_sc!=NULL)
  1411. X   {
  1412. X    /* The loop body compares a single scrap pointed to by p_sc. */
  1413. X    char *p_ch;
  1414. X    for (p_ch=p_sc->sc_first; p_ch<=p_sc->sc_last; p_ch++)
  1415. X      {
  1416. X       if (*p_str==EOS || *p_str != *p_ch) return FALSE;
  1417. X       p_str++;
  1418. X      }
  1419. X    ls_nxt(p_scls,PPV &p_sc);
  1420. X   }
  1421. X return *p_str==EOS;
  1422. X}
  1423. X
  1424. X/******************************************************************************/
  1425. X/*                               Parsing Primitives                           */
  1426. X/******************************************************************************/
  1427. X/* The following functions provide the basic parsing primitives used by the   */
  1428. X/* main parsing routines.                                                     */
  1429. X/******************************************************************************/
  1430. X
  1431. LOCAL void next_tk P_((bool));
  1432. LOCAL void next_tk(iseoferr)
  1433. X/* This function reads the next token from the token list and places a        */
  1434. X/* pointer to the token (structure) in the global variable "token".           */
  1435. X/* The "iseoferr" determines whether a fuss should be made if the next token  */
  1436. X/* fetched is TK_EOF. If iseoferr==TRUE and the next token is TK_EOF, next_tk */
  1437. X/* jumps to the main parsing loop.                                            */
  1438. bool iseoferr;
  1439. X{
  1440. X ls_nxt(token_list,PPV &p_tk);
  1441. X as_cold(p_tk!=NULL,"next_tk: Attempted to read next token at EOF.");
  1442. X if (iseoferr && p_tk->tk_kind==TK_EOF)
  1443. X   {
  1444. X    lr_err(TKPS,"Ouch! High velocity encounter with end of file.");
  1445. X    lr_mes(TKPS,"FunnelWeb expected something else when it hit the EOF.");
  1446. X    longjmp(jmp_pos,DUMMYINT);    /* Jump up to the main parsing loop. */
  1447. X   }
  1448. X}
  1449. X
  1450. X/******************************************************************************/
  1451. X
  1452. LOCAL void recover P_((void));
  1453. LOCAL void recover()
  1454. X/* Parsing functions call this function at points where a syntax error has    */
  1455. X/* has occurred that it is unlikely that the particular parsing function will */
  1456. X/* be able to recover from on its own. In these situations, the parser        */
  1457. X/* resorts to a course grained syntactic error-recovery implemented by this   */
  1458. X/* function. The goal of the error recovery system is to skip tokens until    */
  1459. X/* the next major outer-level-syntax structure is encountered. These are:     */
  1460. X/*    - A new section (@A etc.).                                              */
  1461. X/*    - A macro definition (@$ or @O).                                        */
  1462. X/*    - End of file.                                                          */
  1463. X/* Once one of these three is found, "recover" raises the syntax exception    */
  1464. X/* which sends control to the main parsing loop which is the correct place    */
  1465. X/* to deal with a new, major syntactic construct.                             */
  1466. X{
  1467. X lr_mes(TKPS,"Skipping after error to the next major construct...");
  1468. X
  1469. X /* Skip to one of TK_NSEC,... */
  1470. X while (TRUE)
  1471. X   {
  1472. X    tk_k_t k = p_tk->tk_kind;
  1473. X    if (k==TK_NSEC || k==TK_MDEF || k==TK_FDEF || k==TK_EOF) break;
  1474. X    next_tk(FALSE);
  1475. X   }
  1476. X
  1477. X /* Keep the user informed. */
  1478. X lr_mes(TKPS,"...skipped to here after the error.");
  1479. X
  1480. X /* Jump up to the main parsing loop. */
  1481. X longjmp(jmp_pos,DUMMYINT);
  1482. X}
  1483. X
  1484. X/******************************************************************************/
  1485. X
  1486. LOCAL void genexerr P_((tk_k_t));
  1487. LOCAL void genexerr(tk_kind)
  1488. X/* Genexerr stands for GENerate EXpecting ERRor.                              */
  1489. X/* Given a token kind, genexerr issues an error saying that the specified     */
  1490. X/* kind of token was expected. It then invokes recover() for error recovery.  */
  1491. tk_k_t tk_kind;
  1492. X{
  1493. X switch (tk_kind)
  1494. X   {
  1495. X    /* Note: Not all token kinds are listed here. Only those token kinds that */
  1496. X    /* are passed to pr_token and check_tk by the main parsing routines are   */
  1497. X    /* included here. There are some tokens that one never expects!           */
  1498. X    case TK_NSEC: lr_err(TKPS,"Expecting '@*'."); break;
  1499. X    case TK_ONAM: lr_err(TKPS,"Expecting '@<'."); break;
  1500. X    case TK_ODEF: lr_err(TKPS,"Expecting '@{'."); break;
  1501. X    case TK_CDEF: lr_err(TKPS,"Expecting '@}'."); break;
  1502. X    case TK_EMPH: lr_err(TKPS,"Expecting '@/'."); break;
  1503. X    case TK_CPAR: lr_err(TKPS,"Expecting '@)'."); break;
  1504. X    case TK_QUOT: lr_err(TKPS,"Expecting '@\"'."); break;
  1505. X    case TK_PARM: lr_err(TKPS,"Expecting one of [@1..@9]." ); break;
  1506. X    case TK_TEXT: lr_err(TKPS,"Expecting a text character."); break;
  1507. X    default: as_bomb("genexerr: Case defaulted.");
  1508. X   }
  1509. X recover();
  1510. X}
  1511. X
  1512. X/******************************************************************************/
  1513. X
  1514. LOCAL void pr_token P_((tk_k_t));
  1515. LOCAL void pr_token(tk_kind)
  1516. X/* Parses a single token of the specified kind.                               */
  1517. X/* If the token is of the specified kind, gets the next token.                */
  1518. X/* If the token is not of the specified kind, generates an "expecting" error. */
  1519. tk_k_t tk_kind;
  1520. X{
  1521. X if (p_tk->tk_kind != tk_kind)
  1522. X    genexerr(tk_kind);
  1523. X next_tk(TRUE);
  1524. X}
  1525. X
  1526. X/******************************************************************************/
  1527. X
  1528. LOCAL void check_tk P_((tk_k_t));
  1529. LOCAL void check_tk(tk_kind)
  1530. X/* Same as pr_token, but only checks that the token is OK. Does not move on.  */
  1531. tk_k_t tk_kind;
  1532. X{
  1533. X if (p_tk->tk_kind != tk_kind)
  1534. X    genexerr(tk_kind);
  1535. X}
  1536. X
  1537. X/******************************************************************************/
  1538. X
  1539. LOCAL void ass_tk P_((tk_k_t));
  1540. LOCAL void ass_tk(tk_kind)
  1541. X/* Aborts the program if the current token is not of the specified kind.      */
  1542. X/* This function is intended to perform internal consistency checks, and      */
  1543. X/* should not be considered to be part of the parsing operation.              */
  1544. tk_k_t tk_kind;
  1545. X{
  1546. X as_cold(p_tk->tk_kind==tk_kind,"Parser.ass_tk: Incorrect token.");
  1547. X}
  1548. X
  1549. X/******************************************************************************/
  1550. X
  1551. LOCAL void ass_tks P_((tk_k_t,tk_k_t));
  1552. LOCAL void ass_tks(tk_kind1,tk_kind2)
  1553. X/* Same as ass_tk except it allows a choice of two token kinds. */
  1554. tk_k_t tk_kind1;
  1555. tk_k_t tk_kind2;
  1556. X{
  1557. X as_cold((p_tk->tk_kind == tk_kind1) || (p_tk->tk_kind == tk_kind2),
  1558. X         "Parser.ass_tks: Token is neither of two allowables.");
  1559. X}
  1560. X
  1561. X/******************************************************************************/
  1562. X/*                            Main Parsing Functions                          */
  1563. X/******************************************************************************/
  1564. X
  1565. X/* The parse expression procedure is the only procedure for which a forward   */
  1566. X/* declaration is required. This is a product of the recursive definition of  */
  1567. X/* a FunnelWeb expression.                                                    */
  1568. LOCAL void pr_exp P_((p_ells_t *,p_ma_t));
  1569. X
  1570. X/******************************************************************************/
  1571. X
  1572. LOCAL void pr_text P_((p_scls_t *,bool *));
  1573. LOCAL void pr_text(pp_scls,p_white)
  1574. X/* This function parses a sequence of zero or more text tokens (until it runs */
  1575. X/* into a non-text token) and constructs a list of scraps containing the text */
  1576. X/* pointed to by the tokens. In addition the function writes TRUE to its      */
  1577. X/* second argument iff all of the text scraps are whitespace.                 */
  1578. p_scls_t *pp_scls;
  1579. bool     *p_white;
  1580. X{
  1581. X *pp_scls=ls_cre(sizeof(sc_t));
  1582. X *p_white=TRUE;
  1583. X
  1584. X while (p_tk->tk_kind==TK_TEXT)
  1585. X   {
  1586. X    *p_white = *p_white && p_tk->tk_sc.sc_white;
  1587. X    ls_add(*pp_scls,PV &p_tk->tk_sc);
  1588. X    next_tk(FALSE);
  1589. X   }
  1590. X}
  1591. X
  1592. X/******************************************************************************/
  1593. X
  1594. LOCAL void pr_white P_((p_scls_t *));
  1595. LOCAL void pr_white(pp_scls)
  1596. X/* Same as pr_text, but generates an error if the text is non-white. */
  1597. p_scls_t *pp_scls;
  1598. X{
  1599. X bool iswhite;
  1600. X ps_t ps;
  1601. X ASSIGN(ps,p_tk->tk_ps);
  1602. X pr_text(pp_scls,&iswhite);
  1603. X if (!iswhite)
  1604. X    lr_err(&ps,"Expecting whitespace text.");
  1605. X}
  1606. X
  1607. X/******************************************************************************/
  1608. X
  1609. LOCAL void pr_name P_((char *));
  1610. LOCAL void pr_name(p_name)
  1611. X/* Parses a single FunnelWeb name (e.g. "@<Sloth@>" and "@#K"). */
  1612. char *p_name;   /* Really should be of type p_name_t but this caused trouble. */
  1613. X{
  1614. X uword namelen = 0;
  1615. X
  1616. X /* Deal with the special case of a token name. */
  1617. X if (p_tk->tk_kind==TK_NAME)
  1618. X   {
  1619. X    p_name[0]=p_tk->tk_gen;
  1620. X    p_name[1]=EOS;
  1621. X    next_tk(TRUE);
  1622. X    return;
  1623. X   }
  1624. X
  1625. X ass_tk(TK_ONAM);
  1626. X next_tk(TRUE);
  1627. X
  1628. X while (TRUE)
  1629. X    switch (p_tk->tk_kind)
  1630. X      {
  1631. X       case TK_TEXT:
  1632. X         {
  1633. X          /* Copy the text token to the name array, checking all the time. */
  1634. X          char  *p;
  1635. X          for (p=p_tk->tk_sc.sc_first; p<=p_tk->tk_sc.sc_last; p++)
  1636. X            {
  1637. X             if (*p==EOL)
  1638. X               {
  1639. X                lr_err(TKPS,"Names cannot cross lines.");
  1640. X                recover();
  1641. X               }
  1642. X             namelen++;
  1643. X             if (namelen>NAME_MAX)
  1644. X               {
  1645. X                lr_err(TKPS,"Name is too long.");
  1646. X                sprintf(linet1,
  1647. X                   "The maximum length of a legal name is %lu characters.",
  1648. X                   (unsigned long) NAME_MAX);
  1649. X                lr_mes(TKPS,linet1);
  1650. X                recover();
  1651. X               }
  1652. X             p_name[namelen-1] = *p;
  1653. X            }
  1654. X          next_tk(TRUE);
  1655. X          break;
  1656. X         }
  1657. X       case TK_CNAM:
  1658. X          /* We finish successfully if we hit a close name token "@>". */
  1659. X          p_name[namelen]=EOS;
  1660. X          next_tk(TRUE);
  1661. X          return;
  1662. X       default:
  1663. X          lr_err(TKPS,"Illegal character or symbol in name.");
  1664. X          recover();
  1665. X      } /* End switch */
  1666. X}
  1667. X
  1668. X/******************************************************************************/
  1669. X
  1670. LOCAL void pr_dctxt P_((void));
  1671. LOCAL void pr_dctxt()
  1672. X/* Parse a major text chunk. */
  1673. X{
  1674. X dc_t  dc;
  1675. X bool  dummybool;
  1676. X ps_t  pstext;
  1677. X
  1678. X ass_tk(TK_TEXT);
  1679. X
  1680. X ASSIGN(pstext,p_tk->tk_ps);
  1681. X pr_text(&dc.dc_text,&dummybool);
  1682. X ASSIGN(dc.dc_ps,pstext);
  1683. X dc.dc_kind=DC_TEXT;
  1684. X ls_add(document_list,PV &dc);
  1685. X}
  1686. X
  1687. X/******************************************************************************/
  1688. X
  1689. LOCAL void sendtype P_((ty_k_t));
  1690. LOCAL void sendtype(ty_kind)
  1691. X/* Send a document component of kind typesetter directive with no attributes. */
  1692. ty_k_t ty_kind;
  1693. X{
  1694. X dc_t dc;
  1695. X ASSIGN(dc.dc_ps,p_tk->tk_ps);
  1696. X dc.dc_kind = DC_TYPE;
  1697. X dc.dc_ty.ty_kind=ty_kind;
  1698. X ls_add(document_list,PV &dc);
  1699. X}
  1700. X
  1701. X/******************************************************************************/
  1702. X
  1703. LOCAL void pr_lit P_((void));
  1704. LOCAL void pr_lit()
  1705. X/* Parse a string delimited by literal typeset directives e.g. @{sloth@}.     */
  1706. X{
  1707. X /* Check and get past opening directive. */
  1708. X ass_tk(TK_ODEF);
  1709. X sendtype(TY_OLIT);
  1710. X
  1711. X /* Move past the opening directive and parse the sandwich text. */
  1712. X next_tk(TRUE);
  1713. X if (p_tk->tk_kind!=TK_TEXT)
  1714. X   {
  1715. X    lr_err(TKPS,"Text expected after open literal token \"@{\".");
  1716. X    if (p_tk->tk_kind==TK_CDEF)
  1717. X       lr_mes(TKPS,"Sorry, empty literal strings are not allowed.");
  1718. X    recover();
  1719. X   }
  1720. X pr_dctxt();
  1721. X
  1722. X /* Check and parse the closing directive. */
  1723. X pr_token(TK_CDEF);
  1724. X sendtype(TY_CLIT);
  1725. X}
  1726. X
  1727. X/******************************************************************************/
  1728. X
  1729. LOCAL void pr_emp P_((void));
  1730. LOCAL void pr_emp()
  1731. X/* Parse a string delimited by emphasis typeset directives e.g. @/sloth@/.    */
  1732. X{
  1733. X /* Check and get past opening directive. */
  1734. X ass_tk(TK_EMPH);
  1735. X sendtype(TY_OEMP);
  1736. X
  1737. X /* Move past the opening directive and parse the sandwich text. */
  1738. X next_tk(TRUE);
  1739. X if (p_tk->tk_kind!=TK_TEXT)
  1740. X   {
  1741. X    lr_err(TKPS,"Text expected after open emphasise token \"@/\".");
  1742. X    if (p_tk->tk_kind==TK_EMPH)
  1743. X       lr_mes(TKPS,"Sorry, empty emphasised strings are not allowed.");
  1744. X    recover();
  1745. X   }
  1746. X pr_dctxt();
  1747. X
  1748. X /* Check and parse the closing directive. */
  1749. X pr_token(TK_EMPH);
  1750. X sendtype(TY_CEMP);
  1751. X}
  1752. X
  1753. X/******************************************************************************/
  1754. X
  1755. LOCAL void pr_npag P_((void));
  1756. LOCAL void pr_npag()
  1757. X/* Parse a newpage token. */
  1758. X{
  1759. X ass_tk(TK_NPAG);
  1760. X sendtype(TY_NPAG);
  1761. X pr_token(TK_NPAG);
  1762. X}
  1763. X
  1764. X/******************************************************************************/
  1765. X
  1766. LOCAL void pr_tocs P_((void));
  1767. LOCAL void pr_tocs()
  1768. X/* Parse a table of contents token. */
  1769. X{
  1770. X ass_tk(TK_TOCS);
  1771. X sendtype(TY_TOCS);
  1772. X pr_token(TK_TOCS);
  1773. X}
  1774. X
  1775. X/******************************************************************************/
  1776. X
  1777. LOCAL void pr_skip P_((void));
  1778. LOCAL void pr_skip()
  1779. X/* Parse a skip token. */
  1780. X{
  1781. X dc_t dc;
  1782. X ass_tk(TK_SKIP);
  1783. X ASSIGN(dc.dc_ps,p_tk->tk_ps);
  1784. X dc.dc_kind = DC_TYPE;
  1785. X dc.dc_ty.ty_kind=TY_SKIP;
  1786. X dc.dc_ty.ty_mm=p_tk->tk_gen;
  1787. X ls_add(document_list,PV &dc);
  1788. X pr_token(TK_SKIP);
  1789. X}
  1790. X
  1791. X/******************************************************************************/
  1792. X
  1793. LOCAL void pr_titl P_((void));
  1794. LOCAL void pr_titl()
  1795. X/* Parse a title token. Bascially moving bones from one grave to another.     */
  1796. X{
  1797. X dc_t dc;
  1798. X ass_tk(TK_TITL);
  1799. X ASSIGN(dc.dc_ps,p_tk->tk_ps);
  1800. X dc.dc_kind        = DC_TYPE;
  1801. X dc.dc_ty.ty_kind  = TY_TITL;
  1802. X dc.dc_ty.ty_font  = p_tk->tk_gen / LRFT_PACK;
  1803. X dc.dc_ty.ty_align = p_tk->tk_gen % LRFT_PACK;
  1804. X ASSIGN(dc.dc_ty.ty_sc,p_tk->tk_sc);
  1805. X ls_add(document_list,PV &dc);
  1806. X pr_token(TK_TITL);
  1807. X}
  1808. X
  1809. X/******************************************************************************/
  1810. X
  1811. LOCAL void pr_sec P_((void));
  1812. LOCAL void pr_sec()
  1813. X/* Parse a new section marker ("@A.. and @*") and its optional name.          */
  1814. X{
  1815. X ps_t   secps;     /* Position of this new section.                           */
  1816. X ubyte  level;     /* Level number of new section.                            */
  1817. X bool   has_name;  /* Set to TRUE iff the section has a name.                 */
  1818. X name_t name;      /* Name of the section (if it has a name).                 */
  1819. X
  1820. X /* If called, a new section marker must have been seen. */
  1821. X ass_tk(TK_NSEC);
  1822. X
  1823. X /* Grab a copy of the position of the start of the section. */
  1824. X ASSIGN(secps,p_tk->tk_ps);
  1825. X
  1826. X /* Grab the level number of the section marker. Move to the next token. */
  1827. X level=p_tk->tk_gen;
  1828. X next_tk(TRUE);
  1829. X
  1830. X /* Check for a discontinuity in level. */
  1831. X if (level>sn_lev(&last_sn)+1)
  1832. X   {
  1833. X    if (sn_lev(&last_sn)==0)
  1834. X       lr_err(&secps,"The first section in a document must be an @A section.");
  1835. X    else
  1836. X      {
  1837. X       sprintf(linet1,"The next section (at line %lu) is too deep.",
  1838. X                   (unsigned long) secps.ps_line);
  1839. X       lr_mes(&pssection,linet1);
  1840. X       lr_err(&secps,"This section is more than one level deeper than the last");
  1841. X       sprintf(linet1,"section (at line %lu). Example: @B followed by @D is not allowed.",
  1842. X                   (unsigned long) pssection.ps_line);
  1843. X       lr_mes(&secps,linet1);
  1844. X      }
  1845. X    /* At this point we know that the section structure of the document is    */
  1846. X    /* faulty and that the weaver will never be invoked. As such the          */
  1847. X    /* principal concern becomes that of error recovery. The best we can do   */
  1848. X    /* there is to set to the specified level regardless of how silly it is.  */
  1849. X    /* This ensures that we generate section errors only relative to the      */
  1850. X    /* previous section. Thus, we avoid cascades of errors, if, for example   */
  1851. X    /* the user mistypes an @A at the beginning of a FunnelWeb document.      */
  1852. X    /* Once an error has occurred we don't care about the actual numbers.     */
  1853. X    sn_set(&last_sn,level);
  1854. X   }
  1855. X
  1856. X /* Actually increment the section number at the specified level. */
  1857. X sn_inc(&last_sn,level);
  1858. X
  1859. X /* Record the position. */
  1860. X ASSIGN(pssection,secps);
  1861. X
  1862. X /* Parse optional name (e.g. "@<Sloth@>"). */
  1863. X if (p_tk->tk_kind==TK_ONAM || p_tk->tk_kind==TK_NAME)
  1864. X   {
  1865. X    pr_name(name);
  1866. X    has_name=TRUE;
  1867. X   }
  1868. X else
  1869. X   {
  1870. X    strcpy(name,"No name given");
  1871. X    has_name=FALSE;
  1872. X   }
  1873. X
  1874. X /* Place all the information we have into a document component structure     */
  1875. X /* and add it to the document list.                                          */
  1876. X {
  1877. X  dc_t dc;
  1878. X  ASSIGN(dc.dc_ps,secps);
  1879. X  dc.dc_kind = DC_TYPE;
  1880. X  dc.dc_ty.ty_kind=TY_NSEC;
  1881. X  ASSIGN(dc.dc_ty.ty_sn,last_sn);
  1882. X  dc.dc_ty.ty_isnam = has_name;
  1883. X  strcpy(&dc.dc_ty.ty_name[0],&name[0]);
  1884. X  ls_add(document_list,PV &dc);
  1885. X  ls_tai(document_list,PPV &p_secdc);
  1886. X }
  1887. X}
  1888. X
  1889. X/******************************************************************************/
  1890. X
  1891. LOCAL void rem_name P_((char *));
  1892. LOCAL void rem_name(p_name)
  1893. X/* rem_name stands for REMember NAME. rem_name accepts a pointer to a name.   */
  1894. X/* It looks up the name in the global macro table, and if the name is in the  */
  1895. X/* table performs no action. If the name isn't in the table, it creates a new */
  1896. X/* entry for the name, filling the entry's fields with "blank" values.        */
  1897. X/* The rem_name function should not be seen as recording the definition of a  */
  1898. X/* macro. This is handled by the md_isdef field. Instead the rem_name macro   */
  1899. X/* should be viewed as just creating the space in the table for the info.     */
  1900. char * p_name;  /* Really should be of type p_name_t but this caused trouble. */
  1901. X{
  1902. X if (!tb_itb(macro_table,PV p_name))
  1903. X   {
  1904. X    p_ma_t p_macro=(p_ma_t) mm_temp(sizeof(ma_t));
  1905. X    strcpy(&p_macro->ma_name[0],&p_name[0]);
  1906. X    p_macro->ma_calls         = ls_cre(sizeof(mc_t));
  1907. X    p_macro->ma_defn.md_isdef = FALSE;
  1908. X    p_macro->ma_actn          = ls_cre(sizeof(p_elll_t));
  1909. X    tb_ins(macro_table,PV p_name,PV &p_macro);
  1910. X   }
  1911. X}
  1912. X
  1913. X/******************************************************************************/
  1914. X
  1915. LOCAL void chk_whex P_((p_ps_t,p_ells_t,p_scls_t *));
  1916. LOCAL void chk_whex(p_ps,p_ex,pp_white)
  1917. X/* This function should really be a subfunction of pr_plist. However, C       */
  1918. X/* doesn't allow nested functions so we have to put it here. This function is */
  1919. X/* called after pr_plist has just parsed an opening expression followed by    */
  1920. X/* @". This means that the expression should consist of whitespace crud. Our  */
  1921. X/* mission here is to check that it really does contain only whitespace crud  */
  1922. X/* and return a text list containing the crud. If, on the other hand, it      */
  1923. X/* contains meatier items, we have to call recover().                         */
  1924. p_ps_t   p_ps;       /* Position of the start of the expression.              */
  1925. p_ells_t p_ex;       /* The expression that we have to check out.             */
  1926. p_scls_t *pp_white;  /* The place to put the resultant whitespace list.       */
  1927. X{
  1928. X p_el_t p_el;
  1929. X
  1930. X /* If the expression is empty, we can return an empty list. */
  1931. X if (ls_len(p_ex)==0)
  1932. X   {
  1933. X    *pp_white=ls_cre(sizeof(sc_t));
  1934. X    return;
  1935. X   }
  1936. X
  1937. X /* If there is more than one element, there is ...trouble. */
  1938. X if (ls_len(p_ex) > 1) goto trouble;
  1939. X
  1940. X /* Extract the first element of the list. */
  1941. X ls_fir(p_ex); ls_nxt(p_ex,PPV &p_el);
  1942. X
  1943. X /* If it's not text, there is ...trouble. */
  1944. X if (p_el->el_kind != EL_TEXT) goto trouble;
  1945. X
  1946. X /* If the text isn't lilly white, there is ...trouble. */
  1947. X {
  1948. X  p_scls_t p_scls = p_el->el_text;
  1949. X  p_sc_t   p_sc;
  1950. X  ls_fir(p_scls);
  1951. X  while (TRUE)
  1952. X    {
  1953. X     ls_nxt(p_scls,PPV &p_sc);
  1954. X     if (p_sc==NULL) break;
  1955. X     if (!p_sc->sc_white) goto trouble;
  1956. X    }
  1957. X  /* If we got this far, we know that the expression contains a single */
  1958. X  /* element and that that element is a text list and that that text   */
  1959. X  /* list consists entirely of whitespace. We can now return it.       */
  1960. X  *pp_white=p_scls;
  1961. X  return;
  1962. X }
  1963. X
  1964. X /* We COULD start dissecting the expression and issuing detailed specific    */
  1965. X /* error messages. However, the general approach is cleaner and so a general */
  1966. X /* error message is used.                                                    */
  1967. X trouble:
  1968. X lr_err(       p_ps,"Everything from here...");
  1969. X lr_mes(TKPS,"...to here should be whitespace.");
  1970. X lr_mes(TKPS,"Use of @\" to delimit macro parameters is optional, but");
  1971. X lr_mes(TKPS,"if they are used, any surrounding text must be white.");
  1972. X recover();
  1973. X}
  1974. X
  1975. X/******************************************************************************/
  1976. X
  1977. LOCAL void pr_plist P_((p_elll_t *, p_scll_t *, p_scll_t *,p_ma_t));
  1978. LOCAL void pr_plist(pp_plist,p_before,p_after,p_curmac)
  1979. X/* This function parses an optional parameter list. If the current token is   */
  1980. X/* not TK_OPAR, then it is assumed that no list is present and no tokens are  */
  1981. X/* consumed and empty lists are returned.                                     */
  1982. X/* The three lists returned are:                                              */
  1983. X/*    A list of parameters each being a pointer to a list of elements.        */
  1984. X/*    A list of whitespace blocks being the space before each parameter.      */
  1985. X/*    A list of whitespace blocks being the space after  each parameter.      */
  1986. X/* The last parameter p_curmac should be supplied by the caller and should    */
  1987. X/* contain a pointer to the macro currently being parsed.                     */
  1988. p_elll_t *pp_plist;
  1989. p_scll_t *p_before;
  1990. p_scll_t *p_after;
  1991. p_ma_t   p_curmac;
  1992. X{
  1993. X /* Initialize all the result lists to empty. */
  1994. X *pp_plist = ls_cre(sizeof(p_ells_t));
  1995. X *p_before = ls_cre(sizeof(p_scls_t));
  1996. X *p_after  = ls_cre(sizeof(p_scls_t));
  1997. X
  1998. X /* The parameter list is optional. If it isn't there we assume a null one.   */
  1999. X if (p_tk->tk_kind!=TK_OPAR)
  2000. X    return;
  2001. X next_tk(TRUE);
  2002. X
  2003. X /* Now parse the parameter list, one parameter during each iteration. */
  2004. X while (TRUE)
  2005. X   {
  2006. X    ps_t     exp_ps;
  2007. X    p_ells_t p_ex;
  2008. X    p_scls_t p_white;
  2009. X
  2010. X    /* Things get a little tricky here because the double quotes around       */
  2011. X    /* parameters are optional (per parameter). Thus the following calls are  */
  2012. X    /* all legal (and functionally identical):                                */
  2013. X    /*    @<Sloth@>@( @"walrus@" @, @"aardvark@" @)                           */
  2014. X    /*    @<Sloth@>@(walrus@,       @"aardvark@" @)                           */
  2015. X    /*    @<Sloth@>@(walrus@,aardvark@)                                       */
  2016. X
  2017. X    /* Note the position of the start of this parameter slot. */
  2018. X    ASSIGN(exp_ps,p_tk->tk_ps);
  2019. X
  2020. X    /* Because we face either crud text or an expression, we parse an exp.    */
  2021. X    pr_exp(&p_ex,p_curmac);
  2022. X
  2023. X    /* Now take a look at the next token. If it is @" we know that we have    */
  2024. X    /* been parsing whitespace crud. If it is @, or @) we know that we have   */
  2025. X    /* been parsing the parameter expression itself.                          */
  2026. X    if (p_tk->tk_kind==TK_COMA || p_tk->tk_kind==TK_CPAR)
  2027. X      {
  2028. X       p_scls_t p_scls = ls_cre(sizeof(sc_t));
  2029. X       ls_add(*p_before,PV &p_scls);  /* Add empty whitespace to crud list.   */
  2030. X       ls_add(*pp_plist,PV &p_ex);    /* Add expression to parameter list.    */
  2031. X       ls_add(*p_after ,PV &p_scls);  /* Add empty whitespace to crud list.   */
  2032. X      }
  2033. X    else
  2034. X       if (p_tk->tk_kind==TK_QUOT)
  2035. X         {
  2036. X          /* After parsing the expression we hit a @". This means that the    */
  2037. X          /* expression just parsed SHOULD turn out to contain a single       */
  2038. X          /* element consisting of a white space text list.                   */
  2039. X          chk_whex(&exp_ps,p_ex,&p_white);
  2040. X          ls_add(*p_before,PV &p_white);
  2041. X
  2042. X          /* Get past the quote. */
  2043. X          next_tk(TRUE);
  2044. X
  2045. X          /* Parse the expression and add it to the parameter list. */
  2046. X          pr_exp(&p_ex,p_curmac); ls_add(*pp_plist,PV &p_ex);
  2047. X
  2048. X          /* Parse the quote to move onto the whitespace. */
  2049. X          pr_token(TK_QUOT);
  2050. X
  2051. X          /* Parse the whitespace after the parameter. */
  2052. X          {p_scls_t p_white; pr_white(&p_white); ls_add(*p_after,PV &p_white);}
  2053. X         }
  2054. X       else
  2055. X          {lr_err(TKPS,"Expecting @\" or @, or @)."); recover();}
  2056. X
  2057. X    /* The parameter list can now end (TK_CPAR) or continue (TK_COMA). */
  2058. X    if (p_tk->tk_kind==TK_COMA)
  2059. X       next_tk(TRUE);
  2060. X    else
  2061. X       if (p_tk->tk_kind==TK_CPAR)
  2062. X          {next_tk(TRUE);return;}
  2063. X       else
  2064. X          {lr_err(TKPS,"Expecting @, or @)."); recover();}
  2065. X   } /* End while */
  2066. X}
  2067. X
  2068. X/******************************************************************************/
  2069. X
  2070. LOCAL void pr_invelt P_((p_el_t,p_ma_t));
  2071. LOCAL void pr_invelt(p_el,p_curmac)
  2072. X/* Parses an "invocation element" which is just FunnelWebSpeak for "macro     */
  2073. X/* call". Upon entry the current token must be TK_ONAM or TK_NAME which       */
  2074. X/* presumably is the start of a macro call. Returns a pointer to an element   */
  2075. X/* object describing the call. Does some other macro table stuff too.         */
  2076. X/* p_curmac should be supplied by the caller and should be a pointer to the   */
  2077. X/* macro currently being parsed.                                              */
  2078. p_el_t p_el;
  2079. p_ma_t p_curmac;
  2080. X{
  2081. X name_t   name;      /* Name of the macro being invoked.                      */
  2082. X ps_t     mc_ps;     /* Position of the start of the macro invocation.        */
  2083. X mc_t     mc;        /* Macro call object that describes the invocation.      */
  2084. X p_ma_t   p_callee;  /* Pointer to the macro object of the target macro.      */
  2085. X p_elll_t parlist;   /* The parameter list of the invocation.                 */
  2086. X p_scll_t before;    /* Whitespace before each parameter in the param list.   */
  2087. X p_scll_t after;     /* Whitespace after  each parameter in the param list.   */
  2088. X
  2089. X /* We shouldn't have been called unless we have seen the start of a name. */
  2090. X ass_tks(TK_ONAM,TK_NAME);
  2091. X
  2092. X /* Note the position of the start of the invocation. */
  2093. X mc_ps=p_tk->tk_ps;
  2094. X
  2095. X /* Parse the invocation (name and optional parameter list). */
  2096. X pr_name(name); pr_plist(&parlist,&before,&after,p_curmac);
  2097. X
  2098. X /* Ensure that there is an entry for this macro name in the macro table. */
  2099. X rem_name(name);
  2100. X
  2101. X /* Construct a macro call object describing the call and add it to the */
  2102. X /* callee macro's call list.                                           */
  2103. X /* Note: The +1 in sequence+1 is because the sequence number is incremented  */
  2104. X /* at the end of each macro definition and we are only halfway here.         */
  2105. X mc.mc_seq  = sequence+1;
  2106. X mc.mc_ps   = mc_ps;
  2107. X mc.mc_npar = ls_len(parlist);
  2108. X tb_loo(macro_table,PV name,PV &p_callee);
  2109. X ls_add(p_callee->ma_calls,PV &mc);
  2110. X
  2111. X /* Write an invocation element describing the call to the parameter. */
  2112. X p_el->el_kind  = EL_INVC;
  2113. X p_el->el_p_mac = p_callee;
  2114. X p_el->el_parls = parlist;
  2115. X p_el->el_pretx = before;
  2116. X p_el->el_postx = after;
  2117. X}
  2118. X
  2119. X/******************************************************************************/
  2120. X
  2121. LOCAL void pr_txtelt P_((p_el_t));
  2122. LOCAL void pr_txtelt(p_el)
  2123. X/* Parses a text element. Upon entry, the current token must be of type       */
  2124. X/* TK_TEXT. Writes a text element into its parameter.                         */
  2125. p_el_t p_el;
  2126. X{
  2127. X p_scls_t p_scls;
  2128. X bool     dummy;
  2129. X ass_tk(TK_TEXT);
  2130. X pr_text(&p_scls,&dummy);
  2131. X p_el->el_kind = EL_TEXT;
  2132. X p_el->el_text = p_scls;
  2133. X}
  2134. X
  2135. X/******************************************************************************/
  2136. X
  2137. LOCAL void pr_parelt P_((p_el_t,p_ma_t));
  2138. LOCAL void pr_parelt(p_el,p_curmac)
  2139. X/* Parses a parameter element (e.g. @5). Writes the resultant parameter       */
  2140. X/* element object to the first parameter. The second parameter should be      */
  2141. X/* supplied by the caller and should be a pointer to the macro being parsed.  */
  2142. p_el_t p_el;
  2143. p_ma_t p_curmac;
  2144. X{
  2145. X /* We have to be sitting on a parameter token. */
  2146. X ass_tk(TK_PARM);
  2147. X
  2148. X /* Complain if the parameter does not exist. */
  2149. X if (p_tk->tk_gen > p_curmac->ma_defn.md_npar)
  2150. X   {
  2151. X    sprintf(linet1,"Macro being defined has only %lu parameter%s.",
  2152. X            (unsigned long) p_curmac->ma_defn.md_npar,
  2153. X            p_curmac->ma_defn.md_npar==1 ? "" : "s");
  2154. X    lr_err(TKPS,linet1);
  2155. X   }
  2156. X
  2157. X /* Write a parameter element to the function parameter. */
  2158. X p_el->el_kind  = EL_PARM;
  2159. X p_el->el_parno = p_tk->tk_gen;
  2160. X p_el->el_which = p_curmac;
  2161. X
  2162. X /* Move on to the token following the parameter token. */
  2163. X next_tk(TRUE);
  2164. X}
  2165. X
  2166. X/******************************************************************************/
  2167. X
  2168. LOCAL void pr_exp(p_ex,p_curmac)
  2169. X/* Parses an expression and writes an expression list to the first parameter. */
  2170. X/* The second parameter should be supplied by the user and should be a        */
  2171. X/* pointer to the macro currently being parsed.                               */
  2172. p_ells_t *p_ex;
  2173. p_ma_t   p_curmac;
  2174. X{
  2175. X p_ells_t ex = ls_cre(sizeof(el_t));
  2176. X
  2177. X while (TRUE)
  2178. X   {
  2179. X    el_t el;
  2180. X    switch (p_tk->tk_kind)
  2181. X      {
  2182. X       case TK_TEXT: pr_txtelt(&el);          break;
  2183. X       case TK_NAME:
  2184. X       case TK_ONAM: pr_invelt(&el,p_curmac); break;
  2185. X       case TK_PARM: pr_parelt(&el,p_curmac); break;
  2186. X       default     : *p_ex=ex;                return;
  2187. X      }
  2188. X    ls_add(ex,PV &el);
  2189. X   }
  2190. X}
  2191. X
  2192. X/******************************************************************************/
  2193. X
  2194. LOCAL void pr_formal P_((uword *,p_ps_t));
  2195. LOCAL void pr_formal(p_numpar,p_ps)
  2196. X/* A FunnelWeb formal parameter list looks something like this: "@(@5@)".     */
  2197. X/* This function parses a parameter list if present and returns the number of */
  2198. X/* parameters in the formal parameter list. The function also returns the     */
  2199. X/* position the parameter list.                                               */
  2200. uword  *p_numpar;
  2201. p_ps_t  p_ps;
  2202. X{
  2203. X /* If the parameter list is absent, we default to having zero parameters and */
  2204. X /* making the position of the parameter list the position of the next token. */
  2205. X *p_numpar = 0;
  2206. X *p_ps     = p_tk->tk_ps;
  2207. X
  2208. X /* Parse the parameter list only if one is present. */
  2209. X if (p_tk->tk_kind==TK_OPAR)
  2210. X   {
  2211. X    /* Move to the parameter token and get its number and position. */
  2212. X    next_tk(TRUE);
  2213. X    check_tk(TK_PARM);
  2214. X    *p_numpar=p_tk->tk_gen;
  2215. X    *p_ps=p_tk->tk_ps;
  2216. X
  2217. X    /* Parse the end of the formal parameter list. */
  2218. X    next_tk(TRUE);
  2219. X    pr_token(TK_CPAR);
  2220. X   }
  2221. X}
  2222. X
  2223. X/******************************************************************************/
  2224. X
  2225. LOCAL void pr_number P_((bool *,bool *));
  2226. LOCAL void pr_number(p_iszer,p_isman)
  2227. X/* Parses optional @Z@M after parameter list. */
  2228. bool *p_iszer;
  2229. bool *p_isman;
  2230. X{
  2231. X *p_iszer=FALSE;
  2232. X *p_isman=FALSE;
  2233. X
  2234. X /* The following parse allows zero, one or both of @Z@M, but in order. */
  2235. X
  2236. X /* Grab an @Z if it is there. */
  2237. X if (p_tk->tk_kind==TK_ZERO)
  2238. X   {
  2239. X    next_tk(TRUE);
  2240. X    *p_iszer=TRUE;
  2241. X   }
  2242. X
  2243. X /* Grab an @M too if it is there. */
  2244. X if (p_tk->tk_kind==TK_MANY)
  2245. X   {
  2246. X    next_tk(TRUE);
  2247. X    *p_isman=TRUE;
  2248. X   }
  2249. X}
  2250. X
  2251. X/******************************************************************************/
  2252. X
  2253. LOCAL void pr_equals P_((bool *,p_ps_t));
  2254. LOCAL void pr_equals(isadd,p_ps)
  2255. X/* Parses optional "==" or "+=". Sets *isadd==TRUE iff "+=" parsed else FALSE.*/
  2256. X/* Sets *p_ps to the position of the equals.                                  */
  2257. bool   *isadd;
  2258. p_ps_t p_ps;
  2259. X{
  2260. X p_scls_t p_scls;
  2261. X bool     dummy;
  2262. X
  2263. X /* Grab a copy of the position of the equals (even if it is not there)    . */
  2264. X ASSIGN(*p_ps,p_tk->tk_ps);
  2265. X
  2266. X /* If the equals isn't there, we default to FALSE. */
  2267. X *isadd=FALSE;
  2268. X if (p_tk->tk_kind!=TK_TEXT) return;
  2269. X
  2270. X /* Parse text tokens producing a text list. */
  2271. X pr_text(&p_scls,&dummy);
  2272. X
  2273. X /* Compare the text list with the assignment constant strings. */
  2274. X if (eq_txst(p_scls,"==")) {*isadd=FALSE; ls_des(p_scls); return;}
  2275. X if (eq_txst(p_scls,"+=")) {*isadd=TRUE;  ls_des(p_scls); return;}
  2276. X
  2277. X lr_err(p_ps,"Expecting \"==@{\" or \"+=@{\" or just \"@{\".");
  2278. X lr_mes(p_ps,"(or @Z or @M if they have not already appeared).");
  2279. X lr_mes(p_ps,"Note: FunnelWeb is intolerant of spaces at this point.");
  2280. X ls_des(p_scls);
  2281. X recover();
  2282. X}
  2283. X
  2284. X/******************************************************************************/
  2285. X
  2286. LOCAL bool checkdef P_((p_ma_t,bool,ulong,bool,bool,bool,
  2287. X                        p_ps_t,p_ps_t,p_ps_t,p_ps_t));
  2288. LOCAL bool checkdef (p_ma,is_file,numpar,iszer,isman,isadd,
  2289. X                        p_psnam,p_psfor,p_pseql,p_psnum)
  2290. X/* This function performs all sorts of checks on a macro definition.          */
  2291. X/* If there is anything wrong, it generates and error and calls recover().    */
  2292. X/* This would be best as a local function but because C doesn't have local    */
  2293. X/* functions we have to use millions of parameters instead.                   */
  2294. p_ma_t p_ma;
  2295. bool   is_file;
  2296. ulong  numpar;
  2297. bool   iszer;
  2298. bool   isman;
  2299. bool   isadd;
  2300. p_ps_t p_psnam;
  2301. p_ps_t p_psfor;
  2302. p_ps_t p_pseql;
  2303. p_ps_t p_psnum;
  2304. X{
  2305. X bool semerr = FALSE;
  2306. X
  2307. X /* CHECK INTERNAL INCONSISTENCIES */
  2308. X /* ------------------------------ */
  2309. X /* Complain if a file macro has a parameter list. */
  2310. X if (is_file && numpar>0)
  2311. X   {
  2312. X    lr_err(p_psfor,"Macros attached to output files cannot be parameterized.");
  2313. X    lr_mes(p_psfor,"Reason: No actual parameters would be available during");
  2314. X    lr_mes(p_psfor,"        output file generation.");
  2315. X    semerr=TRUE;
  2316. X   }
  2317. X
  2318. X /* Complain if a file macro is declared additive. */
  2319. X if (is_file && isadd)
  2320. X   {
  2321. X    lr_err(p_pseql,"Macros attached to output files cannot be additive.");
  2322. X    lr_mes(p_pseql,"Reason: Preventing this makes it easy to find output");
  2323. X    lr_mes(p_pseql,"file macros later, because there will be exactly one");
  2324. X    lr_mes(p_pseql,"@O declaration in the input file for each output file.");
  2325. X    lr_mes(p_pseql,"To do what you are trying to do, just create an additive");
  2326. X    lr_mes(p_pseql,"bridging macro, like this:");
  2327. X    lr_mes(p_pseql,"   @O@<prog.c@>@{@<Bridge@>@}");
  2328. X    lr_mes(p_pseql,"   @$@<Bridge@>+=@{void stringhack()...@}");
  2329. X    lr_mes(p_pseql,"   @$@<Bridge@>+=@{main()...@}");
  2330. X    semerr=TRUE;
  2331. X   }
  2332. X
  2333. X /* Complain if a file macro has a name that is too long. */
  2334. X if (is_file && strlen(&p_ma->ma_name[0])>FILENAME_MAX)
  2335. X   {
  2336. X    lr_err(p_psnam,
  2337. X    "File macro's name is longer than the maximum permissible filename length.");
  2338. X    sprintf(linet1,"Maximum filename length is %lu characters.",
  2339. X                   (unsigned long) FILENAME_MAX);
  2340. X    lr_mes(p_psnam,linet1);
  2341. X    semerr=TRUE;
  2342. X   }
  2343. X
  2344. X /* Complain if a file macro has "zero" or "many" attributes. */
  2345. X if (is_file && (iszer || isman))
  2346. X   {
  2347. X    lr_err(p_psnum,"Macros attached to output files cannot have @Z or @M.");
  2348. X    lr_mes(p_psnum,"Reason: They are always called once to generate their");
  2349. X    lr_mes(p_psnum,"output file and they cannot be called from other macros.");
  2350. X    lr_mes(p_psnum,"Hence they are always called exactly once and so there");
  2351. X    lr_mes(p_psnum,"can be no need for @Z or @M in their declarations.");
  2352. X    semerr=TRUE;
  2353. X   }
  2354. X
  2355. X /* COMPARE WITH EARLIER DEFINITIONS */
  2356. X /* -------------------------------- */
  2357. X /* Don't do this section if no previous definition exists. */
  2358. X if (!p_ma->ma_defn.md_isdef) goto finish;
  2359. X
  2360. X /* Assert: An earlier definition of this macro exists. */
  2361. X
  2362. X /* Old definition is a full definition, not admitting partial ones now. */
  2363. X if (!p_ma->ma_defn.md_isadd)
  2364. X   {
  2365. X    if (isadd)
  2366. X      {
  2367. X       sprintf(linet1,"A full definition of this macro appears at line %lu.",
  2368. X                      (ulong) p_ma->ma_defn.md_ps.ps_line);
  2369. X       lr_err(p_psnam,linet1);
  2370. X       lr_mes(p_psnam,"Full and additive definitions of the same macro cannot coexist.");
  2371. X      }
  2372. X    else
  2373. X      {
  2374. X       sprintf(linet1,"This macro is already fully defined (at line %lu).",
  2375. X                      (ulong) p_ma->ma_defn.md_ps.ps_line);
  2376. X       lr_err(p_psnam,linet1);
  2377. X      }
  2378. X    semerr=TRUE;
  2379. X   }
  2380. X
  2381. X /* Old definition is partial but new definition is full. */
  2382. X if (p_ma->ma_defn.md_isadd && !isadd)
  2383. X   {
  2384. X    sprintf(linet1,"An additive definition of this macro appears at line %lu.",
  2385. X                   (ulong) p_ma->ma_defn.md_ps.ps_line);
  2386. X    lr_err(p_psnam,linet1);
  2387. X    lr_mes(p_psnam,"Full and additive definitions of the same macro cannot coexist.");
  2388. X     semerr=TRUE;
  2389. X   }
  2390. X
  2391. X /* Make sure that non-first body parts of additive macros do not have params.*/
  2392. X if (isadd && (numpar>0))
  2393. X   {
  2394. X    lr_err(p_psfor,"The formal parameter list of an additive macro");
  2395. X    lr_mes(p_psfor,"must be placed only in the first definition part.");
  2396. X    sprintf(linet1,"The first part of this macro appears at line %lu.",
  2397. X                   (ulong) p_ma->ma_defn.md_ps.ps_line);
  2398. X    lr_mes(p_psfor,linet1);
  2399. X    semerr=TRUE;
  2400. X   }
  2401. X
  2402. X /* Complain if number attributes are being attached to an additive. */
  2403. X if (isadd && (iszer || isman))
  2404. X   {
  2405. X    lr_err(p_psnum,"@Z and @M modifiers for additive macros must");
  2406. X    lr_mes(p_psnum,"be placed only in the first definition part.");
  2407. X    sprintf(linet1,"The first part of this macro appears at line %lu.",
  2408. X                   (ulong) p_ma->ma_defn.md_ps.ps_line);
  2409. X    lr_mes(p_psnum,linet1);
  2410. X    semerr=TRUE;
  2411. X   }
  2412. X
  2413. X finish:
  2414. X if (semerr)
  2415. X   {
  2416. X    lr_mes(p_psnam,"Macro definition ignored.");
  2417. X    recover();
  2418. X   }
  2419. X return TRUE;
  2420. X}
  2421. X
  2422. X/******************************************************************************/
  2423. X
  2424. LOCAL void pr_macro P_((void));
  2425. LOCAL void pr_macro()
  2426. X/* This function parses a single macro definition. Upon entry, the current    */
  2427. X/* token must be either TK_MDEF or TK_FDEF.                                   */
  2428. X{
  2429. X ps_t     ps_mac;   /* Position of start of the macro definition.             */
  2430. X bool     is_file;  /* TRUE iff definition starts with @O instead of @$.      */
  2431. X name_t   name;     /* The macro name appearing in this definition.           */
  2432. X p_ma_t   p_ma;     /* Pointer to the macro record corresponding to 'name'.   */
  2433. X ps_t     ps_name;  /* Position of the macro name.                            */
  2434. X ps_t     ps_form;  /* Position of the formal parameter list.                 */
  2435. X ps_t     ps_equal; /* Position of the equals.                                */
  2436. X ps_t     ps_num;   /* Position of number attributes.                         */
  2437. X uword    numpar;   /* Number of parameters in formal parameter list.         */
  2438. X bool     iszer;    /* TRUE iff macro is allowed to be called zero times.     */
  2439. X bool     isman;    /* TRUE iff macro is allowed to be called more than once. */
  2440. X bool     isadd;    /* TRUE iff equals parsed here is "+=" not "==".          */
  2441. X p_ells_t ex;       /* Expression constituting this macro body part.          */
  2442. X bool     hasname;  /* TRUE iff current section already has a name.           */
  2443. X
  2444. X /* We should not have got in here without seeing a definition token. */
  2445. X ass_tks(TK_MDEF,TK_FDEF);
  2446. X
  2447. X /* Grab a copy of the position of the start of the macro. */
  2448. X ASSIGN(ps_mac,p_tk->tk_ps);
  2449. X
  2450. X /* If we have seen a macro definition token then it means that the user is   */
  2451. X /* TRYING to define a macro. The macro may or may not provoke errors. In     */
  2452. X /* either case though we do not want to hassle the user with errors about    */
  2453. X /* nameless sections not containing macros if it is obvious that an attempt  */
  2454. X /* to define a macro has been made. So here we set the name flag after       */
  2455. X /* having a look at it so we can use its value later.                        */
  2456. X if (sn_lev(&last_sn)>0)
  2457. X   {
  2458. X    as_cold(p_secdc->dc_kind==DC_TYPE,"pr_macro: section processing error (1).");
  2459. X    as_cold(p_secdc->dc_ty.ty_kind==TY_NSEC,"pr_macro: section processing error (2).");
  2460. X    hasname=p_secdc->dc_ty.ty_isnam;
  2461. X    p_secdc->dc_ty.ty_isnam=TRUE;
  2462. X   }
  2463. X
  2464. X /* Record whether the macro is attached to an product file. */
  2465. X is_file= (p_tk->tk_kind==TK_FDEF);
  2466. X
  2467. X /* Parse the macro name. Record its position. Ensure that there is an entry  */
  2468. X /* in the macro table for this macro name (i.e. create one if not there).    */
  2469. X next_tk(TRUE);
  2470. X if (p_tk->tk_kind!=TK_ONAM && p_tk->tk_kind!=TK_NAME)
  2471. X   {
  2472. X    lr_err(TKPS,"Macro name expected (@<...@> or @#c).");
  2473. X    recover();
  2474. X   }
  2475. X ps_name=p_tk->tk_ps;
  2476. X pr_name (name);
  2477. X rem_name(name);
  2478. X tb_loo(macro_table,PV name,PV &p_ma);
  2479. X
  2480. X /* Parse the optional formal parameter list and the equals. */
  2481. X /* Extract positioning and other information.               */
  2482. X pr_formal(&numpar,&ps_form );
  2483. X ASSIGN(ps_num,p_tk->tk_ps);
  2484. X pr_number(&iszer, &isman);
  2485. X pr_equals(&isadd ,&ps_equal);
  2486. X
  2487. X /* Perform semantic checks on whether this definition is valid.              */
  2488. X checkdef(p_ma,is_file,numpar,iszer,isman,isadd,
  2489. X               &ps_name,&ps_form,&ps_equal,&ps_num);
  2490. X
  2491. X /* If we have got this far, we know that we have parsed a valid macro        */
  2492. X /* definition except possibly for the actual expression body.                */
  2493. X /* If this is the first definition of this macro, establish its definition.  */
  2494. X if (!p_ma->ma_defn.md_isdef)
  2495. X   {
  2496. X    p_ma->ma_defn.md_isdef = TRUE;
  2497. X    ASSIGN(p_ma->ma_defn.md_ps,ps_mac);
  2498. X    p_ma->ma_defn.md_npar  = numpar;
  2499. X    p_ma->ma_defn.md_isadd = isadd;
  2500. X    p_ma->ma_defn.md_iszer = iszer;
  2501. X    p_ma->ma_defn.md_isman = isman;
  2502. X    p_ma->ma_defn.md_isfil = is_file;
  2503. X    p_ma->ma_defn.md_body  = ls_cre(sizeof(bp_t));
  2504. X    if (is_file) tb_ins(file_table,PV name,PV &p_ma);
  2505. X   }
  2506. X
  2507. X /* Parse the body of this macro definition. */
  2508. X pr_token(TK_ODEF); pr_exp(&ex,p_ma); pr_token(TK_CDEF);
  2509. X
  2510. X /* We are now clear to execute the effects of the macro on our tables.       */
  2511. X /* First we bump up the sequence number.                                     */
  2512. X sequence++;
  2513. X
  2514. X {
  2515. X  /* Construct a body part object containing the information in this          */
  2516. X  /* definition and append it to the list of body parts in the macro record.  */
  2517. X  bp_t bp;
  2518. X  bp.bp_ex  = ex;
  2519. X  bp.bp_seq = sequence;
  2520. X  bp.bp_ps  = ps_name;
  2521. X  ls_add(p_ma->ma_defn.md_body,PV &bp);
  2522. X }
  2523. X
  2524. X {
  2525. X  /* Construct a document component object for this definition and append it  */
  2526. X  /* to the global document component list.                                   */
  2527. X  dc_t dc;
  2528. X  ASSIGN(dc.dc_ps,ps_mac);
  2529. X  dc.dc_kind = DC_MACR;
  2530. X  dc.dc_p_ma = p_ma;
  2531. X  dc.dc_part = ls_len(p_ma->ma_defn.md_body);
  2532. X  ls_add(document_list,PV &dc);
  2533. X }
  2534. X
  2535. X /* Sections without names inherit the name of their first macro. */
  2536. X if (sn_lev(&last_sn)>0 && !hasname)
  2537. X    strcpy(&p_secdc->dc_ty.ty_name[0],name);
  2538. X}
  2539. X
  2540. X/******************************************************************************/
  2541. X
  2542. XEXPORT void parser()
  2543. X/* This is the main parser function. This function contains parser            */
  2544. X/* initialization as well as the main parsing loop to which control is        */
  2545. X/* returned (by recover()) when an error occurs.                              */
  2546. X{
  2547. X /* Create the lists and tables generated by the parser. */
  2548. X macro_table  = tb_cre (sizeof(name_t),sizeof(p_ma_t),(p_kycm_t) cm_name);
  2549. X file_table   = tb_cre (sizeof(name_t),sizeof(p_ma_t),(p_kycm_t) cm_name);
  2550. X document_list= ls_cre (sizeof(dc_t));
  2551. X
  2552. X /* Initialize the section number counter. */
  2553. X sequence = 0;
  2554. X sn_ini(&last_sn);
  2555. X p_secdc  = NULL;
  2556. X
  2557. X /* Prime the scanning of the token list. */
  2558. X ls_fir(token_list);
  2559. X next_tk(FALSE);
  2560. X
  2561. X /* This is where we longjmp back to after hitting a nasty syntax error.  */
  2562. X /* We don't actually have to test dummyint, as our control state is no   */
  2563. X /* different after a syntax error has occurred. Example: We try to parse */
  2564. X /* a macro but there is a syntax error. So we skip to the start of the   */
  2565. X /* next macro and then longjmp back to here ready to parse the next      */
  2566. X /* macro. Thus, there is no need to a fork test.                         */
  2567. X (void) setjmp(jmp_pos);
  2568. X
  2569. X /* This is the main parser loop which parses major syntactic chunks. */
  2570. X while (p_tk->tk_kind != TK_EOF)
  2571. X    switch (p_tk->tk_kind)
  2572. X      {
  2573. X       case TK_NSEC: pr_sec  (); break;
  2574. X       case TK_TEXT: pr_dctxt(); break;
  2575. X       case TK_MDEF: pr_macro(); break;
  2576. X       case TK_FDEF: pr_macro(); break;
  2577. X       case TK_ODEF: pr_lit  (); break;
  2578. X       case TK_EMPH: pr_emp  (); break;
  2579. X       case TK_NPAG: pr_npag (); break;
  2580. X       case TK_TOCS: pr_tocs (); break;
  2581. X       case TK_SKIP: pr_skip (); break;
  2582. X       case TK_TITL: pr_titl (); break;
  2583. X       default:
  2584. X          lr_err(TKPS,"The parser was at the top level and was expecting");
  2585. X          lr_mes(TKPS,"one of: {Directive, Text, Macro definition, EOF}.");
  2586. X          next_tk(FALSE);
  2587. X          break;
  2588. X      }
  2589. X
  2590. X}
  2591. X
  2592. X/******************************************************************************/
  2593. X/*                              End of PARSER.C                               */
  2594. X/******************************************************************************/
  2595. END_OF_FILE
  2596. if test 47198 -ne `wc -c <'sources/parser.c'`; then
  2597.     echo shar: \"'sources/parser.c'\" unpacked with wrong size!
  2598. fi
  2599. # end of 'sources/parser.c'
  2600. fi
  2601. echo shar: End of archive 15 \(of 20\).
  2602. cp /dev/null ark15isdone
  2603. MISSING=""
  2604. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  2605.     if test ! -f ark${I}isdone ; then
  2606.     MISSING="${MISSING} ${I}"
  2607.     fi
  2608. done
  2609. if test "${MISSING}" = "" ; then
  2610.     echo You have unpacked all 20 archives.
  2611.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2612. else
  2613.     echo You still need to unpack the following archives:
  2614.     echo "        " ${MISSING}
  2615. fi
  2616. ##  End of shell archive.
  2617. exit 0
  2618.