home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-10 | 127.7 KB | 3,779 lines |
- Newsgroups: comp.sources.unix
- From: ross@spam.adelaide.edu.au (Ross Williams)
- Subject: v26i136: funnelweb - a tool for literate programming in C, Part16/20
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: ross@spam.adelaide.edu.au (Ross Williams)
- Posting-Number: Volume 26, Issue 136
- Archive-Name: funnelweb/part16
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 16 (of 20)."
- # Contents: answers/pr09.lis userman/u_ch2.tex
- # Wrapped by vixie@gw.home.vix.com on Sun Apr 11 11:00:32 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'answers/pr09.lis' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'answers/pr09.lis'\"
- else
- echo shar: Extracting \"'answers/pr09.lis'\" \(59230 characters\)
- sed "s/^X//" >'answers/pr09.lis' <<'END_OF_FILE'
- XFUNNELWEB LISTING FILE
- X======================
- X
- Dump of mapped file "<<Suppressed>>".
- X
- MEMORY DUMP OF MAPPED FILE
- X==========================
- X
- X+-------------------------------------------------+------------------+
- X| 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF |
- X+-------------------------------------------------+------------------+
- X| 50 52 30 39 3A 20 54 65 73 74 20 63 61 6C 6C 73 | PR09: Test calls |
- X| 20 61 6E 64 20 61 63 74 75 61 6C 20 70 61 72 61 | and actual para |
- X| 6D 65 74 65 72 20 6C 69 73 74 73 2E 0A 0A 46 69 | meter lists...Fi |
- X| 72 73 74 20 74 72 69 70 20 75 70 20 74 68 65 20 | rst trip up the |
- X| 70 61 72 73 65 72 20 73 6F 20 77 65 20 64 6F 6E | parser so we don |
- X| 27 74 20 67 65 74 20 61 6E 79 20 66 75 72 74 68 | 't get any furth |
- X| 65 72 2E 0A 40 3E 0A 0A 4E 6F 77 20 64 65 66 69 | er..@>..Now defi |
- X| 6E 65 20 73 6F 6D 65 20 6D 61 63 72 6F 73 20 74 | ne some macros t |
- X| 6F 20 63 61 6C 6C 2E 20 4E 6F 20 65 72 72 6F 72 | o call. No error |
- X| 2E 0A 0A 40 24 40 3C 5A 65 72 6F 40 3E 40 7B 40 | ...@$@<Zero@>@{@ |
- X| 7D 0A 40 24 40 3C 4F 6E 65 40 3E 40 28 40 31 40 | }.@$@<One@>@(@1@ |
- X| 29 40 7B 40 7D 0A 40 24 40 3C 54 77 6F 40 3E 40 | )@{@}.@$@<Two@>@ |
- X| 28 40 32 40 29 40 7B 40 7D 0A 40 24 40 3C 54 68 | (@2@)@{@}.@$@<Th |
- X| 72 65 65 40 3E 40 28 40 33 40 29 40 7B 40 7D 0A | ree@>@(@3@)@{@}. |
- X| 40 24 40 3C 4E 69 6E 65 40 3E 40 28 40 39 40 29 | @$@<Nine@>@(@9@) |
- X| 40 7B 40 7D 0A 40 24 40 23 22 40 7B 40 7D 0A 0A | @{@}.@$@#"@{@}.. |
- X| 54 68 65 20 66 6F 6C 6C 6F 77 69 6E 67 20 74 65 | The following te |
- X| 73 74 20 63 61 6C 6C 73 20 73 68 6F 75 6C 64 20 | st calls should |
- X| 4E 4F 54 20 67 65 6E 65 72 61 74 65 20 61 6E 79 | NOT generate any |
- X| 20 65 72 72 6F 72 73 2E 0A 0A 40 24 40 3C 4D 61 | errors...@$@<Ma |
- X| 63 72 6F 20 63 6F 6E 74 61 69 6E 69 6E 67 20 74 | cro containing t |
- X| 68 65 20 74 65 73 74 20 6D 61 63 72 6F 20 63 61 | he test macro ca |
- X| 6C 6C 73 2E 40 3E 3D 3D 40 7B 0A 31 2E 20 54 65 | lls.@>==@{.1. Te |
- X| 73 74 20 6D 61 63 72 6F 20 63 61 6C 6C 20 77 69 | st macro call wi |
- X| 74 68 20 6E 6F 20 70 61 72 61 6D 65 74 65 72 20 | th no parameter |
- X| 6C 69 73 74 2E 0A 40 3C 5A 65 72 6F 40 3E 0A 0A | list..@<Zero@>.. |
- X| 32 2E 20 54 65 73 74 20 6D 61 63 72 6F 20 63 61 | 2. Test macro ca |
- X| 6C 6C 20 77 69 74 68 20 71 75 69 63 6B 20 6E 61 | ll with quick na |
- X| 6D 65 2E 0A 40 23 22 0A 0A 33 2E 20 54 65 73 74 | me..@#"..3. Test |
- X| 20 6D 61 63 72 6F 20 63 61 6C 6C 20 77 69 74 68 | macro call with |
- X| 20 6F 6E 65 20 70 61 72 61 6D 65 74 65 72 2E 0A | one parameter.. |
- X| 40 3C 4F 6E 65 40 3E 40 28 54 6F 75 63 61 6E 40 | @<One@>@(Toucan@ |
- X| 29 0A 0A 34 2E 20 54 65 73 74 20 6D 61 63 72 6F | )..4. Test macro |
- X| 20 63 61 6C 6C 20 77 69 74 68 20 6D 61 6E 79 20 | call with many |
- X| 70 61 72 61 6D 65 74 65 72 73 2E 0A 40 3C 54 77 | parameters..@<Tw |
- X| 6F 40 3E 40 28 54 6F 75 63 61 6E 40 2C 54 65 61 | o@>@(Toucan@,Tea |
- X| 70 6F 74 40 29 0A 40 3C 54 68 72 65 65 40 3E 40 | pot@).@<Three@>@ |
- X| 28 54 6F 75 63 61 6E 40 2C 54 65 61 70 6F 74 40 | (Toucan@,Teapot@ |
- X| 2C 57 61 6C 72 75 73 40 29 0A 40 3C 4E 69 6E 65 | ,Walrus@).@<Nine |
- X| 40 3E 40 28 54 6F 75 63 61 6E 40 2C 54 65 61 70 | @>@(Toucan@,Teap |
- X| 6F 74 40 2C 57 61 6C 72 75 73 40 2C 0A 20 20 20 | ot@,Walrus@,. |
- X| 20 20 20 20 20 20 20 54 6F 75 63 61 6E 40 2C 54 | Toucan@,T |
- X| 65 61 70 6F 74 40 2C 57 61 6C 72 75 73 40 2C 0A | eapot@,Walrus@,. |
- X| 20 20 20 20 20 20 20 20 20 20 54 6F 75 63 61 6E | Toucan |
- X| 40 2C 54 65 61 70 6F 74 40 2C 57 61 6C 72 75 73 | @,Teapot@,Walrus |
- X| 40 29 0A 0A 35 2E 20 54 65 73 74 20 6D 61 63 72 | @)..5. Test macr |
- X| 6F 20 63 61 6C 6C 73 20 77 69 74 68 20 64 6F 75 | o calls with dou |
- X| 62 6C 65 20 71 75 6F 74 65 73 20 6F 6E 20 70 61 | ble quotes on pa |
- X| 72 61 6D 65 74 65 72 73 2E 0A 40 3C 4F 6E 65 40 | rameters..@<One@ |
- X| 3E 40 28 20 40 22 54 6F 75 63 61 6E 40 22 40 29 | >@( @"Toucan@"@) |
- X| 0A 40 3C 54 77 6F 40 3E 40 28 40 22 54 6F 75 63 | .@<Two@>@(@"Touc |
- X| 61 6E 40 22 20 20 20 40 2C 20 20 20 40 22 54 65 | an@" @, @"Te |
- X| 61 70 6F 74 40 22 40 29 0A 40 3C 54 68 72 65 65 | apot@"@).@<Three |
- X| 40 3E 40 28 40 22 54 6F 75 63 61 6E 40 22 20 40 | @>@(@"Toucan@" @ |
- X| 2C 0A 20 20 20 20 20 20 20 20 20 20 20 40 22 54 | ,. @"T |
- X| 65 61 70 6F 74 40 22 20 40 2C 0A 20 20 20 20 20 | eapot@" @,. |
- X| 20 20 20 20 20 20 40 22 57 61 6C 72 75 73 40 22 | @"Walrus@" |
- X| 20 40 29 0A 40 3C 4E 69 6E 65 40 3E 40 28 20 40 | @).@<Nine@>@( @ |
- X| 22 54 6F 75 63 61 6E 40 22 20 40 2C 20 40 22 54 | "Toucan@" @, @"T |
- X| 65 61 70 6F 74 40 22 20 40 2C 20 40 22 57 61 6C | eapot@" @, @"Wal |
- X| 72 75 73 40 22 20 40 2C 0A 20 20 20 20 20 20 20 | rus@" @,. |
- X| 20 20 20 20 40 22 54 6F 75 63 61 6E 40 22 20 40 | @"Toucan@" @ |
- X| 2C 20 40 22 54 65 61 70 6F 74 40 22 20 40 2C 20 | , @"Teapot@" @, |
- X| 40 22 57 61 6C 72 75 73 40 22 20 40 2C 0A 20 20 | @"Walrus@" @,. |
- X| 20 20 20 20 20 20 20 20 20 40 22 54 6F 75 63 61 | @"Touca |
- X| 6E 40 22 20 40 2C 20 40 22 54 65 61 70 6F 74 40 | n@" @, @"Teapot@ |
- X| 22 20 40 2C 20 40 22 57 61 6C 72 75 73 40 22 20 | " @, @"Walrus@" |
- X| 40 29 0A 0A 37 2E 20 54 65 73 74 20 6D 61 63 72 | @)..7. Test macr |
- X| 6F 20 63 61 6C 6C 73 20 77 69 74 68 20 6D 69 78 | o calls with mix |
- X| 65 64 20 64 6F 75 62 6C 65 20 71 75 6F 74 65 73 | ed double quotes |
- X| 20 6F 6E 20 70 61 72 61 6D 65 74 65 72 73 2E 0A | on parameters.. |
- X| 40 3C 54 77 6F 40 3E 40 28 40 22 54 6F 75 63 61 | @<Two@>@(@"Touca |
- X| 6E 40 22 20 20 20 40 2C 54 65 61 70 6F 74 40 29 | n@" @,Teapot@) |
- X| 0A 40 3C 54 68 72 65 65 40 3E 40 28 40 22 54 6F | .@<Three@>@(@"To |
- X| 75 63 61 6E 40 22 20 40 2C 0A 20 20 20 20 20 20 | ucan@" @,. |
- X| 20 20 20 20 20 40 22 54 65 61 70 6F 74 40 22 20 | @"Teapot@" |
- X| 40 2C 57 61 6C 72 75 73 40 29 0A 40 3C 4E 69 6E | @,Walrus@).@<Nin |
- X| 65 40 3E 40 28 20 40 22 54 6F 75 63 61 6E 40 22 | e@>@( @"Toucan@" |
- X| 20 40 2C 20 40 22 54 65 61 70 6F 74 40 22 20 40 | @, @"Teapot@" @ |
- X| 2C 20 20 20 57 61 6C 72 75 73 20 20 20 40 2C 0A | , Walrus @,. |
- X| 20 20 20 20 20 20 20 20 20 20 20 40 22 54 6F 75 | @"Tou |
- X| 63 61 6E 40 22 20 40 2C 20 20 20 54 65 61 70 6F | can@" @, Teapo |
- X| 74 20 20 20 40 2C 20 40 22 57 61 6C 72 75 73 40 | t @, @"Walrus@ |
- X| 22 20 40 2C 0A 20 20 20 20 20 20 20 20 20 20 20 | " @,. |
- X| 40 22 54 6F 75 63 61 6E 40 22 20 40 2C 20 40 22 | @"Toucan@" @, @" |
- X| 54 65 61 70 6F 74 40 22 20 40 2C 20 40 22 57 61 | Teapot@" @, @"Wa |
- X| 6C 72 75 73 40 22 20 40 29 0A 0A 40 7D 20 40 21 | lrus@" @)..@} @! |
- X| 20 45 6E 64 20 6F 66 20 6D 61 63 72 6F 20 64 65 | End of macro de |
- X| 66 69 6E 69 74 69 6F 6E 20 65 6E 63 6C 6F 73 69 | finition enclosi |
- X| 6E 67 20 61 6C 6C 20 74 68 65 73 65 20 6C 65 67 | ng all these leg |
- X| 61 6C 20 74 65 73 74 73 2E 0A 0A 38 2E 20 54 65 | al tests...8. Te |
- X| 73 74 20 6D 61 63 72 6F 20 63 61 6C 6C 73 20 77 | st macro calls w |
- X| 69 74 68 20 61 20 76 61 72 69 65 74 79 20 6F 66 | ith a variety of |
- X| 20 73 79 6E 74 61 78 20 65 72 72 6F 72 73 20 69 | syntax errors i |
- X| 6E 20 70 61 72 61 6D 65 74 65 72 20 6C 69 73 74 | n parameter list |
- X| 2E 0A 40 24 40 3C 45 72 72 6F 72 31 40 3E 40 7B | ..@$@<Error1@>@{ |
- X| 0A 40 3C 5A 65 72 6F 40 3E 40 28 0A 40 7D 0A 40 | .@<Zero@>@(.@}.@ |
- X| 41 40 3C 45 72 72 6F 72 20 72 65 63 6F 76 65 72 | A@<Error recover |
- X| 79 20 70 6F 69 6E 74 40 3E 0A 0A 40 24 40 3C 45 | y point@>..@$@<E |
- X| 72 72 6F 72 32 40 3E 40 7B 0A 40 3C 5A 65 72 6F | rror2@>@{.@<Zero |
- X| 40 3E 40 29 0A 40 7D 0A 40 41 40 3C 45 72 72 6F | @>@).@}.@A@<Erro |
- X| 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E 74 | r recovery point |
- X| 40 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 33 40 3E | @>..@$@<Error3@> |
- X| 40 7B 0A 40 3C 4F 6E 65 40 3E 40 28 40 22 54 6F | @{.@<One@>@(@"To |
- X| 75 63 61 6E 40 29 0A 40 7D 0A 40 41 40 3C 45 72 | ucan@).@}.@A@<Er |
- X| 72 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 | ror recovery poi |
- X| 6E 74 40 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 34 | nt@>..@$@<Error4 |
- X| 40 3E 40 7B 0A 40 3C 4F 6E 65 40 3E 40 28 40 22 | @>@{.@<One@>@(@" |
- X| 54 6F 75 63 61 6E 40 22 40 22 53 6C 6F 74 68 40 | Toucan@"@"Sloth@ |
- X| 22 40 29 0A 40 7D 0A 40 41 40 3C 45 72 72 6F 72 | "@).@}.@A@<Error |
- X| 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E 74 40 | recovery point@ |
- X| 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 35 40 3E 40 | >..@$@<Error5@>@ |
- X| 7B 0A 40 3C 54 77 6F 40 3E 40 28 40 22 54 6F 75 | {.@<Two@>@(@"Tou |
- X| 63 61 6E 40 22 54 65 61 70 6F 74 40 29 0A 40 7D | can@"Teapot@).@} |
- X| 0A 40 41 40 3C 45 72 72 6F 72 20 72 65 63 6F 76 | .@A@<Error recov |
- X| 65 72 79 20 70 6F 69 6E 74 40 3E 0A 0A 40 24 40 | ery point@>..@$@ |
- X| 3C 45 72 72 6F 72 36 40 3E 40 7B 0A 40 3C 54 77 | <Error6@>@{.@<Tw |
- X| 6F 40 3E 40 28 40 22 54 6F 75 63 61 6E 40 22 54 | o@>@(@"Toucan@"T |
- X| 65 61 70 6F 74 0A 40 7D 0A 40 41 40 3C 45 72 72 | eapot.@}.@A@<Err |
- X| 6F 72 20 72 65 63 6F 76 65 72 79 20 70 6F 69 6E | or recovery poin |
- X| 74 40 3E 0A 0A 40 24 40 3C 45 72 72 6F 72 37 40 | t@>..@$@<Error7@ |
- X| 3E 40 7B 0A 40 3C 54 77 6F 40 3E 40 28 40 22 54 | >@{.@<Two@>@(@"T |
- X| 6F 75 63 61 6E 40 22 54 65 61 70 6F 74 0A 40 3C | oucan@"Teapot.@< |
- X| 54 68 72 65 65 40 3E 40 28 54 6F 75 63 61 6E 40 | Three@>@(Toucan@ |
- X| 2C 0A 20 20 20 20 20 20 20 20 20 20 20 40 22 54 | ,. @"T |
- X| 65 61 70 6F 74 40 2C 57 61 6C 72 75 73 0A 0A 40 | eapot@,Walrus..@ |
- X| 7D 0A 40 41 40 3C 45 72 72 6F 72 20 72 65 63 6F | }.@A@<Error reco |
- X| 76 65 72 79 20 70 6F 69 6E 74 40 3E 0A 0A | very point@>.. |
- X+-------------------------------------------------+------------------+
- X
- X
- X=========================== Start of LINE LIST DUMP ============================
- X
- Globl Local| Text
- X-----------+--------------------------------------------------------------------
- X00001 00001| PR09: Test calls and actual parameter lists.<010>
- X00002 00002| <010>
- X00003 00003| First trip up the parser so we don't get any further.<010>
- X00004 00004| @><010>
- X00005 00005| <010>
- X00006 00006| Now define some macros to call. No error.<010>
- X00007 00007| <010>
- X00008 00008| @$@<Zero@>@{@}<010>
- X00009 00009| @$@<One@>@(@1@)@{@}<010>
- X00010 00010| @$@<Two@>@(@2@)@{@}<010>
- X00011 00011| @$@<Three@>@(@3@)@{@}<010>
- X00012 00012| @$@<Nine@>@(@9@)@{@}<010>
- X00013 00013| @$@#"@{@}<010>
- X00014 00014| <010>
- X00015 00015| The following test calls should NOT generate any errors.<010>
- X00016 00016| <010>
- X00017 00017| @$@<Macro containing the test macro calls.@>==@{<010>
- X00018 00018| 1. Test macro call with no parameter list.<010>
- X00019 00019| @<Zero@><010>
- X00020 00020| <010>
- X00021 00021| 2. Test macro call with quick name.<010>
- X00022 00022| @#"<010>
- X00023 00023| <010>
- X00024 00024| 3. Test macro call with one parameter.<010>
- X00025 00025| @<One@>@(Toucan@)<010>
- X00026 00026| <010>
- X00027 00027| 4. Test macro call with many parameters.<010>
- X00028 00028| @<Two@>@(Toucan@,Teapot@)<010>
- X00029 00029| @<Three@>@(Toucan@,Teapot@,Walrus@)<010>
- X00030 00030| @<Nine@>@(Toucan@,Teapot@,Walrus@,<010>
- X00031 00031| Toucan@,Teapot@,Walrus@,<010>
- X00032 00032| Toucan@,Teapot@,Walrus@)<010>
- X00033 00033| <010>
- X00034 00034| 5. Test macro calls with double quotes on parameters.<010>
- X00035 00035| @<One@>@( @"Toucan@"@)<010>
- X00036 00036| @<Two@>@(@"Toucan@" @, @"Teapot@"@)<010>
- X00037 00037| @<Three@>@(@"Toucan@" @,<010>
- X00038 00038| @"Teapot@" @,<010>
- X00039 00039| @"Walrus@" @)<010>
- X00040 00040| @<Nine@>@( @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,<010>
- X00041 00041| @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,<010>
- X00042 00042| @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)<010>
- X00043 00043| <010>
- X00044 00044| 7. Test macro calls with mixed double quotes on parameters.<010>
- X00045 00045| @<Two@>@(@"Toucan@" @,Teapot@)<010>
- X00046 00046| @<Three@>@(@"Toucan@" @,<010>
- X00047 00047| @"Teapot@" @,Walrus@)<010>
- X00048 00048| @<Nine@>@( @"Toucan@" @, @"Teapot@" @, Walrus @,<010>
- X00049 00049| @"Toucan@" @, Teapot @, @"Walrus@" @,<010>
- X00050 00050| @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)<010>
- X00051 00051| <010>
- X00052 00052| @} @! End of macro definition enclosing all these legal tests.<010>
- X00053 00053| <010>
- X00054 00054| 8. Test macro calls with a variety of syntax errors in parameter list.<010>
- X00055 00055| @$@<Error1@>@{<010>
- X00056 00056| @<Zero@>@(<010>
- X00057 00057| @}<010>
- X00058 00058| @A@<Error recovery point@><010>
- X00059 00059| <010>
- X00060 00060| @$@<Error2@>@{<010>
- X00061 00061| @<Zero@>@)<010>
- X00062 00062| @}<010>
- X00063 00063| @A@<Error recovery point@><010>
- X00064 00064| <010>
- X00065 00065| @$@<Error3@>@{<010>
- X00066 00066| @<One@>@(@"Toucan@)<010>
- X00067 00067| @}<010>
- X00068 00068| @A@<Error recovery point@><010>
- X00069 00069| <010>
- X00070 00070| @$@<Error4@>@{<010>
- X00071 00071| @<One@>@(@"Toucan@"@"Sloth@"@)<010>
- X00072 00072| @}<010>
- X00073 00073| @A@<Error recovery point@><010>
- X00074 00074| <010>
- X00075 00075| @$@<Error5@>@{<010>
- X00076 00076| @<Two@>@(@"Toucan@"Teapot@)<010>
- X00077 00077| @}<010>
- X00078 00078| @A@<Error recovery point@><010>
- X00079 00079| <010>
- X00080 00080| @$@<Error6@>@{<010>
- X00081 00081| @<Two@>@(@"Toucan@"Teapot<010>
- X00082 00082| @}<010>
- X00083 00083| @A@<Error recovery point@><010>
- X00084 00084| <010>
- X00085 00085| @$@<Error7@>@{<010>
- X00086 00086| @<Two@>@(@"Toucan@"Teapot<010>
- X00087 00087| @<Three@>@(Toucan@,<010>
- X00088 00088| @"Teapot@,Walrus<010>
- X00089 00089| <010>
- X00090 00090| @}<010>
- X00091 00091| @A@<Error recovery point@><010>
- X00092 00092| <010>
- X00093 00093| <End-Of-File><010>
- X-----------+--------------------------------------------------------------------
- Globl Local| Text
- X
- X============================ End of LINE LIST DUMP =============================
- X
- X
- X=========================== Start of TOKEN LIST DUMP ===========================
- X
- Summary: There are 467 tokens in the token list.
- X
- Line[Column]: Token Description
- X-------------------------------
- X
- X0001[01]: Text. Text scrap[Grey]="PR09: Test calls and actual parameter lists.<010>
- X<010>
- XFirst trip up the parser so we don't get any further.<010>
- X"
- X0004[01]: @> Close name.
- X0004[03]: Text. Text scrap[Grey]="<010>
- X<010>
- Now define some macros to call. No error.<010>
- X<010>
- X"
- X0008[01]: @$ Macro defn.
- X0008[03]: @< Open name.
- X0008[05]: Text. Text scrap[Grey]="Zero"
- X0008[09]: @> Close name.
- X0008[11]: @{ Open defn.
- X0008[13]: @} Close defn.
- X0008[15]: Text. Text scrap[White]="<010>
- X"
- X0009[01]: @$ Macro defn.
- X0009[03]: @< Open name.
- X0009[05]: Text. Text scrap[Grey]="One"
- X0009[08]: @> Close name.
- X0009[10]: @( Open param.
- X0009[12]: @n Parameter. Parameterno=1.
- X0009[14]: @} Close param.
- X0009[16]: @{ Open defn.
- X0009[18]: @} Close defn.
- X0009[20]: Text. Text scrap[White]="<010>
- X"
- X0010[01]: @$ Macro defn.
- X0010[03]: @< Open name.
- X0010[05]: Text. Text scrap[Grey]="Two"
- X0010[08]: @> Close name.
- X0010[10]: @( Open param.
- X0010[12]: @n Parameter. Parameterno=2.
- X0010[14]: @} Close param.
- X0010[16]: @{ Open defn.
- X0010[18]: @} Close defn.
- X0010[20]: Text. Text scrap[White]="<010>
- X"
- X0011[01]: @$ Macro defn.
- X0011[03]: @< Open name.
- X0011[05]: Text. Text scrap[Grey]="Three"
- X0011[10]: @> Close name.
- X0011[12]: @( Open param.
- X0011[14]: @n Parameter. Parameterno=3.
- X0011[16]: @} Close param.
- X0011[18]: @{ Open defn.
- X0011[20]: @} Close defn.
- X0011[22]: Text. Text scrap[White]="<010>
- X"
- X0012[01]: @$ Macro defn.
- X0012[03]: @< Open name.
- X0012[05]: Text. Text scrap[Grey]="Nine"
- X0012[09]: @> Close name.
- X0012[11]: @( Open param.
- X0012[13]: @n Parameter. Parameterno=9.
- X0012[15]: @} Close param.
- X0012[17]: @{ Open defn.
- X0012[19]: @} Close defn.
- X0012[21]: Text. Text scrap[White]="<010>
- X"
- X0013[01]: @$ Macro defn.
- X0013[03]: @# Name. Character='"'.
- X0013[06]: @{ Open defn.
- X0013[08]: @} Close defn.
- X0013[10]: Text. Text scrap[Grey]="<010>
- X<010>
- The following test calls should NOT generate any errors.<010>
- X<010>
- X"
- X0017[01]: @$ Macro defn.
- X0017[03]: @< Open name.
- X0017[05]: Text. Text scrap[Grey]="Macro containing the test macro calls."
- X0017[43]: @> Close name.
- X0017[45]: Text. Text scrap[Grey]="=="
- X0017[47]: @{ Open defn.
- X0017[49]: Text. Text scrap[Grey]="<010>
- X1. Test macro call with no parameter list.<010>
- X"
- X0019[01]: @< Open name.
- X0019[03]: Text. Text scrap[Grey]="Zero"
- X0019[07]: @> Close name.
- X0019[09]: Text. Text scrap[Grey]="<010>
- X<010>
- X2. Test macro call with quick name.<010>
- X"
- X0022[01]: @# Name. Character='"'.
- X0022[04]: Text. Text scrap[Grey]="<010>
- X<010>
- X3. Test macro call with one parameter.<010>
- X"
- X0025[01]: @< Open name.
- X0025[03]: Text. Text scrap[Grey]="One"
- X0025[06]: @> Close name.
- X0025[08]: @( Open param.
- X0025[10]: Text. Text scrap[Grey]="Toucan"
- X0025[16]: @} Close param.
- X0025[18]: Text. Text scrap[Grey]="<010>
- X<010>
- X4. Test macro call with many parameters.<010>
- X"
- X0028[01]: @< Open name.
- X0028[03]: Text. Text scrap[Grey]="Two"
- X0028[06]: @> Close name.
- X0028[08]: @( Open param.
- X0028[10]: Text. Text scrap[Grey]="Toucan"
- X0028[16]: @, Comma.
- X0028[18]: Text. Text scrap[Grey]="Teapot"
- X0028[24]: @} Close param.
- X0028[26]: Text. Text scrap[White]="<010>
- X"
- X0029[01]: @< Open name.
- X0029[03]: Text. Text scrap[Grey]="Three"
- X0029[08]: @> Close name.
- X0029[10]: @( Open param.
- X0029[12]: Text. Text scrap[Grey]="Toucan"
- X0029[18]: @, Comma.
- X0029[20]: Text. Text scrap[Grey]="Teapot"
- X0029[26]: @, Comma.
- X0029[28]: Text. Text scrap[Grey]="Walrus"
- X0029[34]: @} Close param.
- X0029[36]: Text. Text scrap[White]="<010>
- X"
- X0030[01]: @< Open name.
- X0030[03]: Text. Text scrap[Grey]="Nine"
- X0030[07]: @> Close name.
- X0030[09]: @( Open param.
- X0030[11]: Text. Text scrap[Grey]="Toucan"
- X0030[17]: @, Comma.
- X0030[19]: Text. Text scrap[Grey]="Teapot"
- X0030[25]: @, Comma.
- X0030[27]: Text. Text scrap[Grey]="Walrus"
- X0030[33]: @, Comma.
- X0030[35]: Text. Text scrap[Grey]="<010>
- X Toucan"
- X0031[17]: @, Comma.
- X0031[19]: Text. Text scrap[Grey]="Teapot"
- X0031[25]: @, Comma.
- X0031[27]: Text. Text scrap[Grey]="Walrus"
- X0031[33]: @, Comma.
- X0031[35]: Text. Text scrap[Grey]="<010>
- X Toucan"
- X0032[17]: @, Comma.
- X0032[19]: Text. Text scrap[Grey]="Teapot"
- X0032[25]: @, Comma.
- X0032[27]: Text. Text scrap[Grey]="Walrus"
- X0032[33]: @} Close param.
- X0032[35]: Text. Text scrap[Grey]="<010>
- X<010>
- X5. Test macro calls with double quotes on parameters.<010>
- X"
- X0035[01]: @< Open name.
- X0035[03]: Text. Text scrap[Grey]="One"
- X0035[06]: @> Close name.
- X0035[08]: @( Open param.
- X0035[10]: Text. Text scrap[White]=" "
- X0035[11]: @" Quote.
- X0035[13]: Text. Text scrap[Grey]="Toucan"
- X0035[19]: @" Quote.
- X0035[21]: @} Close param.
- X0035[23]: Text. Text scrap[White]="<010>
- X"
- X0036[01]: @< Open name.
- X0036[03]: Text. Text scrap[Grey]="Two"
- X0036[06]: @> Close name.
- X0036[08]: @( Open param.
- X0036[10]: @" Quote.
- X0036[12]: Text. Text scrap[Grey]="Toucan"
- X0036[18]: @" Quote.
- X0036[20]: Text. Text scrap[White]=" "
- X0036[23]: @, Comma.
- X0036[25]: Text. Text scrap[White]=" "
- X0036[28]: @" Quote.
- X0036[30]: Text. Text scrap[Grey]="Teapot"
- X0036[36]: @" Quote.
- X0036[38]: @} Close param.
- X0036[40]: Text. Text scrap[White]="<010>
- X"
- X0037[01]: @< Open name.
- X0037[03]: Text. Text scrap[Grey]="Three"
- X0037[08]: @> Close name.
- X0037[10]: @( Open param.
- X0037[12]: @" Quote.
- X0037[14]: Text. Text scrap[Grey]="Toucan"
- X0037[20]: @" Quote.
- X0037[22]: Text. Text scrap[White]=" "
- X0037[23]: @, Comma.
- X0037[25]: Text. Text scrap[White]="<010>
- X "
- X0038[12]: @" Quote.
- X0038[14]: Text. Text scrap[Grey]="Teapot"
- X0038[20]: @" Quote.
- X0038[22]: Text. Text scrap[White]=" "
- X0038[23]: @, Comma.
- X0038[25]: Text. Text scrap[White]="<010>
- X "
- X0039[12]: @" Quote.
- X0039[14]: Text. Text scrap[Grey]="Walrus"
- X0039[20]: @" Quote.
- X0039[22]: Text. Text scrap[White]=" "
- X0039[23]: @} Close param.
- X0039[25]: Text. Text scrap[White]="<010>
- X"
- X0040[01]: @< Open name.
- X0040[03]: Text. Text scrap[Grey]="Nine"
- X0040[07]: @> Close name.
- X0040[09]: @( Open param.
- X0040[11]: Text. Text scrap[White]=" "
- X0040[12]: @" Quote.
- X0040[14]: Text. Text scrap[Grey]="Toucan"
- X0040[20]: @" Quote.
- X0040[22]: Text. Text scrap[White]=" "
- X0040[23]: @, Comma.
- X0040[25]: Text. Text scrap[White]=" "
- X0040[26]: @" Quote.
- X0040[28]: Text. Text scrap[Grey]="Teapot"
- X0040[34]: @" Quote.
- X0040[36]: Text. Text scrap[White]=" "
- X0040[37]: @, Comma.
- X0040[39]: Text. Text scrap[White]=" "
- X0040[40]: @" Quote.
- X0040[42]: Text. Text scrap[Grey]="Walrus"
- X0040[48]: @" Quote.
- X0040[50]: Text. Text scrap[White]=" "
- X0040[51]: @, Comma.
- X0040[53]: Text. Text scrap[White]="<010>
- X "
- X0041[12]: @" Quote.
- X0041[14]: Text. Text scrap[Grey]="Toucan"
- X0041[20]: @" Quote.
- X0041[22]: Text. Text scrap[White]=" "
- X0041[23]: @, Comma.
- X0041[25]: Text. Text scrap[White]=" "
- X0041[26]: @" Quote.
- X0041[28]: Text. Text scrap[Grey]="Teapot"
- X0041[34]: @" Quote.
- X0041[36]: Text. Text scrap[White]=" "
- X0041[37]: @, Comma.
- X0041[39]: Text. Text scrap[White]=" "
- X0041[40]: @" Quote.
- X0041[42]: Text. Text scrap[Grey]="Walrus"
- X0041[48]: @" Quote.
- X0041[50]: Text. Text scrap[White]=" "
- X0041[51]: @, Comma.
- X0041[53]: Text. Text scrap[White]="<010>
- X "
- X0042[12]: @" Quote.
- X0042[14]: Text. Text scrap[Grey]="Toucan"
- X0042[20]: @" Quote.
- X0042[22]: Text. Text scrap[White]=" "
- X0042[23]: @, Comma.
- X0042[25]: Text. Text scrap[White]=" "
- X0042[26]: @" Quote.
- X0042[28]: Text. Text scrap[Grey]="Teapot"
- X0042[34]: @" Quote.
- X0042[36]: Text. Text scrap[White]=" "
- X0042[37]: @, Comma.
- X0042[39]: Text. Text scrap[White]=" "
- X0042[40]: @" Quote.
- X0042[42]: Text. Text scrap[Grey]="Walrus"
- X0042[48]: @" Quote.
- X0042[50]: Text. Text scrap[White]=" "
- X0042[51]: @} Close param.
- X0042[53]: Text. Text scrap[Grey]="<010>
- X<010>
- X7. Test macro calls with mixed double quotes on parameters.<010>
- X"
- X0045[01]: @< Open name.
- X0045[03]: Text. Text scrap[Grey]="Two"
- X0045[06]: @> Close name.
- X0045[08]: @( Open param.
- X0045[10]: @" Quote.
- X0045[12]: Text. Text scrap[Grey]="Toucan"
- X0045[18]: @" Quote.
- X0045[20]: Text. Text scrap[White]=" "
- X0045[23]: @, Comma.
- X0045[25]: Text. Text scrap[Grey]="Teapot"
- X0045[31]: @} Close param.
- X0045[33]: Text. Text scrap[White]="<010>
- X"
- X0046[01]: @< Open name.
- X0046[03]: Text. Text scrap[Grey]="Three"
- X0046[08]: @> Close name.
- X0046[10]: @( Open param.
- X0046[12]: @" Quote.
- X0046[14]: Text. Text scrap[Grey]="Toucan"
- X0046[20]: @" Quote.
- X0046[22]: Text. Text scrap[White]=" "
- X0046[23]: @, Comma.
- X0046[25]: Text. Text scrap[White]="<010>
- X "
- X0047[12]: @" Quote.
- X0047[14]: Text. Text scrap[Grey]="Teapot"
- X0047[20]: @" Quote.
- X0047[22]: Text. Text scrap[White]=" "
- X0047[23]: @, Comma.
- X0047[25]: Text. Text scrap[Grey]="Walrus"
- X0047[31]: @} Close param.
- X0047[33]: Text. Text scrap[White]="<010>
- X"
- X0048[01]: @< Open name.
- X0048[03]: Text. Text scrap[Grey]="Nine"
- X0048[07]: @> Close name.
- X0048[09]: @( Open param.
- X0048[11]: Text. Text scrap[White]=" "
- X0048[12]: @" Quote.
- X0048[14]: Text. Text scrap[Grey]="Toucan"
- X0048[20]: @" Quote.
- X0048[22]: Text. Text scrap[White]=" "
- X0048[23]: @, Comma.
- X0048[25]: Text. Text scrap[White]=" "
- X0048[26]: @" Quote.
- X0048[28]: Text. Text scrap[Grey]="Teapot"
- X0048[34]: @" Quote.
- X0048[36]: Text. Text scrap[White]=" "
- X0048[37]: @, Comma.
- X0048[39]: Text. Text scrap[Grey]=" Walrus "
- X0048[51]: @, Comma.
- X0048[53]: Text. Text scrap[White]="<010>
- X "
- X0049[12]: @" Quote.
- X0049[14]: Text. Text scrap[Grey]="Toucan"
- X0049[20]: @" Quote.
- X0049[22]: Text. Text scrap[White]=" "
- X0049[23]: @, Comma.
- X0049[25]: Text. Text scrap[Grey]=" Teapot "
- X0049[37]: @, Comma.
- X0049[39]: Text. Text scrap[White]=" "
- X0049[40]: @" Quote.
- X0049[42]: Text. Text scrap[Grey]="Walrus"
- X0049[48]: @" Quote.
- X0049[50]: Text. Text scrap[White]=" "
- X0049[51]: @, Comma.
- X0049[53]: Text. Text scrap[White]="<010>
- X "
- X0050[12]: @" Quote.
- X0050[14]: Text. Text scrap[Grey]="Toucan"
- X0050[20]: @" Quote.
- X0050[22]: Text. Text scrap[White]=" "
- X0050[23]: @, Comma.
- X0050[25]: Text. Text scrap[White]=" "
- X0050[26]: @" Quote.
- X0050[28]: Text. Text scrap[Grey]="Teapot"
- X0050[34]: @" Quote.
- X0050[36]: Text. Text scrap[White]=" "
- X0050[37]: @, Comma.
- X0050[39]: Text. Text scrap[White]=" "
- X0050[40]: @" Quote.
- X0050[42]: Text. Text scrap[Grey]="Walrus"
- X0050[48]: @" Quote.
- X0050[50]: Text. Text scrap[White]=" "
- X0050[51]: @} Close param.
- X0050[53]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0052[01]: @} Close defn.
- X0052[03]: Text. Text scrap[White]=" "
- X0053[01]: Text. Text scrap[Grey]="<010>
- X8. Test macro calls with a variety of syntax errors in parameter list.<010>
- X"
- X0055[01]: @$ Macro defn.
- X0055[03]: @< Open name.
- X0055[05]: Text. Text scrap[Grey]="Error1"
- X0055[11]: @> Close name.
- X0055[13]: @{ Open defn.
- X0055[15]: Text. Text scrap[White]="<010>
- X"
- X0056[01]: @< Open name.
- X0056[03]: Text. Text scrap[Grey]="Zero"
- X0056[07]: @> Close name.
- X0056[09]: @( Open param.
- X0056[11]: Text. Text scrap[White]="<010>
- X"
- X0057[01]: @} Close defn.
- X0057[03]: Text. Text scrap[White]="<010>
- X"
- X0058[01]: @A New section (Level 1).
- X0058[03]: @< Open name.
- X0058[05]: Text. Text scrap[Grey]="Error recovery point"
- X0058[25]: @> Close name.
- X0058[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0060[01]: @$ Macro defn.
- X0060[03]: @< Open name.
- X0060[05]: Text. Text scrap[Grey]="Error2"
- X0060[11]: @> Close name.
- X0060[13]: @{ Open defn.
- X0060[15]: Text. Text scrap[White]="<010>
- X"
- X0061[01]: @< Open name.
- X0061[03]: Text. Text scrap[Grey]="Zero"
- X0061[07]: @> Close name.
- X0061[09]: @} Close param.
- X0061[11]: Text. Text scrap[White]="<010>
- X"
- X0062[01]: @} Close defn.
- X0062[03]: Text. Text scrap[White]="<010>
- X"
- X0063[01]: @A New section (Level 1).
- X0063[03]: @< Open name.
- X0063[05]: Text. Text scrap[Grey]="Error recovery point"
- X0063[25]: @> Close name.
- X0063[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0065[01]: @$ Macro defn.
- X0065[03]: @< Open name.
- X0065[05]: Text. Text scrap[Grey]="Error3"
- X0065[11]: @> Close name.
- X0065[13]: @{ Open defn.
- X0065[15]: Text. Text scrap[White]="<010>
- X"
- X0066[01]: @< Open name.
- X0066[03]: Text. Text scrap[Grey]="One"
- X0066[06]: @> Close name.
- X0066[08]: @( Open param.
- X0066[10]: @" Quote.
- X0066[12]: Text. Text scrap[Grey]="Toucan"
- X0066[18]: @} Close param.
- X0066[20]: Text. Text scrap[White]="<010>
- X"
- X0067[01]: @} Close defn.
- X0067[03]: Text. Text scrap[White]="<010>
- X"
- X0068[01]: @A New section (Level 1).
- X0068[03]: @< Open name.
- X0068[05]: Text. Text scrap[Grey]="Error recovery point"
- X0068[25]: @> Close name.
- X0068[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0070[01]: @$ Macro defn.
- X0070[03]: @< Open name.
- X0070[05]: Text. Text scrap[Grey]="Error4"
- X0070[11]: @> Close name.
- X0070[13]: @{ Open defn.
- X0070[15]: Text. Text scrap[White]="<010>
- X"
- X0071[01]: @< Open name.
- X0071[03]: Text. Text scrap[Grey]="One"
- X0071[06]: @> Close name.
- X0071[08]: @( Open param.
- X0071[10]: @" Quote.
- X0071[12]: Text. Text scrap[Grey]="Toucan"
- X0071[18]: @" Quote.
- X0071[20]: @" Quote.
- X0071[22]: Text. Text scrap[Grey]="Sloth"
- X0071[27]: @" Quote.
- X0071[29]: @} Close param.
- X0071[31]: Text. Text scrap[White]="<010>
- X"
- X0072[01]: @} Close defn.
- X0072[03]: Text. Text scrap[White]="<010>
- X"
- X0073[01]: @A New section (Level 1).
- X0073[03]: @< Open name.
- X0073[05]: Text. Text scrap[Grey]="Error recovery point"
- X0073[25]: @> Close name.
- X0073[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0075[01]: @$ Macro defn.
- X0075[03]: @< Open name.
- X0075[05]: Text. Text scrap[Grey]="Error5"
- X0075[11]: @> Close name.
- X0075[13]: @{ Open defn.
- X0075[15]: Text. Text scrap[White]="<010>
- X"
- X0076[01]: @< Open name.
- X0076[03]: Text. Text scrap[Grey]="Two"
- X0076[06]: @> Close name.
- X0076[08]: @( Open param.
- X0076[10]: @" Quote.
- X0076[12]: Text. Text scrap[Grey]="Toucan"
- X0076[18]: @" Quote.
- X0076[20]: Text. Text scrap[Grey]="Teapot"
- X0076[26]: @} Close param.
- X0076[28]: Text. Text scrap[White]="<010>
- X"
- X0077[01]: @} Close defn.
- X0077[03]: Text. Text scrap[White]="<010>
- X"
- X0078[01]: @A New section (Level 1).
- X0078[03]: @< Open name.
- X0078[05]: Text. Text scrap[Grey]="Error recovery point"
- X0078[25]: @> Close name.
- X0078[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0080[01]: @$ Macro defn.
- X0080[03]: @< Open name.
- X0080[05]: Text. Text scrap[Grey]="Error6"
- X0080[11]: @> Close name.
- X0080[13]: @{ Open defn.
- X0080[15]: Text. Text scrap[White]="<010>
- X"
- X0081[01]: @< Open name.
- X0081[03]: Text. Text scrap[Grey]="Two"
- X0081[06]: @> Close name.
- X0081[08]: @( Open param.
- X0081[10]: @" Quote.
- X0081[12]: Text. Text scrap[Grey]="Toucan"
- X0081[18]: @" Quote.
- X0081[20]: Text. Text scrap[Grey]="Teapot<010>
- X"
- X0082[01]: @} Close defn.
- X0082[03]: Text. Text scrap[White]="<010>
- X"
- X0083[01]: @A New section (Level 1).
- X0083[03]: @< Open name.
- X0083[05]: Text. Text scrap[Grey]="Error recovery point"
- X0083[25]: @> Close name.
- X0083[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0085[01]: @$ Macro defn.
- X0085[03]: @< Open name.
- X0085[05]: Text. Text scrap[Grey]="Error7"
- X0085[11]: @> Close name.
- X0085[13]: @{ Open defn.
- X0085[15]: Text. Text scrap[White]="<010>
- X"
- X0086[01]: @< Open name.
- X0086[03]: Text. Text scrap[Grey]="Two"
- X0086[06]: @> Close name.
- X0086[08]: @( Open param.
- X0086[10]: @" Quote.
- X0086[12]: Text. Text scrap[Grey]="Toucan"
- X0086[18]: @" Quote.
- X0086[20]: Text. Text scrap[Grey]="Teapot<010>
- X"
- X0087[01]: @< Open name.
- X0087[03]: Text. Text scrap[Grey]="Three"
- X0087[08]: @> Close name.
- X0087[10]: @( Open param.
- X0087[12]: Text. Text scrap[Grey]="Toucan"
- X0087[18]: @, Comma.
- X0087[20]: Text. Text scrap[White]="<010>
- X "
- X0088[12]: @" Quote.
- X0088[14]: Text. Text scrap[Grey]="Teapot"
- X0088[20]: @, Comma.
- X0088[22]: Text. Text scrap[Grey]="Walrus<010>
- X<010>
- X"
- X0090[01]: @} Close defn.
- X0090[03]: Text. Text scrap[White]="<010>
- X"
- X0091[01]: @A New section (Level 1).
- X0091[03]: @< Open name.
- X0091[05]: Text. Text scrap[Grey]="Error recovery point"
- X0091[25]: @> Close name.
- X0091[27]: Text. Text scrap[White]="<010>
- X<010>
- X"
- X0093[01]: End Of File.
- X============================ End of TOKEN LIST DUMP ============================
- X
- X
- X========================== Start of MACRO TABLE DUMP ===========================
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : """
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- X Call 1: Parameters=0, Sequence num=7, Position(L,C)=(22,1).
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=6, Pos(L,C)=(13,3), Expression follows:
- X
- X---- Start of Expression ----
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error1"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 0 body parts.
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error2"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 0 body parts.
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error3"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 0 body parts.
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error4"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 0 body parts.
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error5"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=8, Pos(L,C)=(75,3), Expression follows:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Two@>
- This invocation has 1 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error6"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 0 body parts.
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Error7"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 0 body parts.
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Macro containing the test macro calls."
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=7, Pos(L,C)=(17,3), Expression follows:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X1. Test macro call with no parameter list.<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Zero@>
- No actual parameters.
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X<010>
- X2. Test macro call with quick name.<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<"@>
- No actual parameters.
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X<010>
- X3. Test macro call with one parameter.<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<One@>
- This invocation has 1 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X<010>
- X4. Test macro call with many parameters.<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Two@>
- This invocation has 2 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Three@>
- This invocation has 3 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 3:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Nine@>
- This invocation has 9 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 3:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 4:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 5:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 6:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 7:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 8:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 9:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X<010>
- X5. Test macro calls with double quotes on parameters.<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<One@>
- This invocation has 1 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Two@>
- This invocation has 2 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Three@>
- This invocation has 3 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 3:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Nine@>
- This invocation has 9 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 3:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 4:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 5:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 6:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 7:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 8:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 9:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[Grey]="<010>
- X<010>
- X7. Test macro calls with mixed double quotes on parameters.<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Two@>
- This invocation has 2 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Three@>
- This invocation has 3 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 3:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X"
- X------ End Text Element ------
- X
- X
- X-- Begin Invocation Element --
- Invocation of macro @<Nine@>
- This invocation has 9 actual parameters.
- Actual parameter list follows as a sequence of expressions:
- X(Text crud before and after parameter has been omitted).
- XExpression for parameter number 1:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 2:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 3:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]=" Walrus "
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 4:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 5:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]=" Teapot "
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 6:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 7:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Toucan"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 8:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Teapot"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- XExpression for parameter number 9:
- X
- X---- Start of Expression ----
- X
- X----- Start Text Element -----
- Text scrap[Grey]="Walrus"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X--- End Invocation Element ---
- X
- X
- X----- Start Text Element -----
- Text scrap[White]="<010>
- X<010>
- X"
- X------ End Text Element ------
- X
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Nine"
- Defined? : Yes.
- Parameters : 9
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- X Call 1: Parameters=9, Sequence num=7, Position(L,C)=(30,1).
- X Call 2: Parameters=9, Sequence num=7, Position(L,C)=(40,1).
- X Call 3: Parameters=9, Sequence num=7, Position(L,C)=(48,1).
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=5, Pos(L,C)=(12,3), Expression follows:
- X
- X---- Start of Expression ----
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "One"
- Defined? : Yes.
- Parameters : 1
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- X Call 1: Parameters=1, Sequence num=7, Position(L,C)=(25,1).
- X Call 2: Parameters=1, Sequence num=7, Position(L,C)=(35,1).
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=2, Pos(L,C)=(9,3), Expression follows:
- X
- X---- Start of Expression ----
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Three"
- Defined? : Yes.
- Parameters : 3
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- X Call 1: Parameters=3, Sequence num=7, Position(L,C)=(29,1).
- X Call 2: Parameters=3, Sequence num=7, Position(L,C)=(37,1).
- X Call 3: Parameters=3, Sequence num=7, Position(L,C)=(46,1).
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=4, Pos(L,C)=(11,3), Expression follows:
- X
- X---- Start of Expression ----
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Two"
- Defined? : Yes.
- Parameters : 2
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- X Call 1: Parameters=2, Sequence num=7, Position(L,C)=(28,1).
- X Call 2: Parameters=2, Sequence num=7, Position(L,C)=(36,1).
- X Call 3: Parameters=2, Sequence num=7, Position(L,C)=(45,1).
- X Call 4: Parameters=1, Sequence num=8, Position(L,C)=(76,1).
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=3, Pos(L,C)=(10,3), Expression follows:
- X
- X---- Start of Expression ----
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X------------------- Start of Macro Dump --------------------
- Macro Name : "Zero"
- Defined? : Yes.
- Parameters : 0
- Additive? : No.
- Zero Calls? : No.
- Many Calls? : No.
- Output File?: No.
- Call list :
- X Call 1: Parameters=0, Sequence num=7, Position(L,C)=(19,1).
- X Call 2: Parameters=0, Sequence num=8, Position(L,C)=(61,1).
- Macro body :
- X
- X--Start of List of Body Parts--
- This macro has 1 body part.
- Body part 1: Seqnum=1, Pos(L,C)=(8,3), Expression follows:
- X
- X---- Start of Expression ----
- X----- End of Expression -----
- X
- X---End of List of Body Parts---
- X
- X-------------------- End of Macro Dump ---------------------
- X
- X
- X
- X=========================== End of MACRO TABLE DUMP ============================
- X
- X
- X========================= Start of DOCUMENT LIST DUMP ==========================
- X
- X
- TEXT COMPONENT: Pos(L,C)=(1,1).
- X
- X-- Start of Text Scrap List --
- Text scrap[Grey]="PR09: Test calls and actual parameter lists.<010>
- X<010>
- XFirst trip up the parser so we don't get any further.<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TEXT COMPONENT: Pos(L,C)=(4,3).
- X
- X-- Start of Text Scrap List --
- Text scrap[Grey]="<010>
- X<010>
- Now define some macros to call. No error.<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(8,1).
- Part 1 of macro @<Zero@>.
- X
- TEXT COMPONENT: Pos(L,C)=(8,15).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(9,1).
- Part 1 of macro @<One@>.
- X
- TEXT COMPONENT: Pos(L,C)=(9,20).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(10,1).
- Part 1 of macro @<Two@>.
- X
- TEXT COMPONENT: Pos(L,C)=(10,20).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(11,1).
- Part 1 of macro @<Three@>.
- X
- TEXT COMPONENT: Pos(L,C)=(11,22).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(12,1).
- Part 1 of macro @<Nine@>.
- X
- TEXT COMPONENT: Pos(L,C)=(12,21).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(13,1).
- Part 1 of macro @<"@>.
- X
- TEXT COMPONENT: Pos(L,C)=(13,10).
- X
- X-- Start of Text Scrap List --
- Text scrap[Grey]="<010>
- X<010>
- The following test calls should NOT generate any errors.<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(17,1).
- Part 1 of macro @<Macro containing the test macro calls.@>.
- X
- TEXT COMPONENT: Pos(L,C)=(52,3).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]=" "
- Text scrap[Grey]="<010>
- X8. Test macro calls with a variety of syntax errors in parameter list.<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "1", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(58,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "2", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(63,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "3", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(68,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "4", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(73,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- MACRO DEFINITION COMPONENT: Pos(L,C)=(75,1).
- Part 1 of macro @<Error5@>.
- X
- TEXT COMPONENT: Pos(L,C)=(77,3).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "5", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(78,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "6", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(83,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- TYPESETTER DIRECTIVE COMPONENT:
- X Section "7", Section name="Error recovery point".
- X
- TEXT COMPONENT: Pos(L,C)=(91,27).
- X
- X-- Start of Text Scrap List --
- Text scrap[White]="<010>
- X<010>
- X"
- X--- End of Text Scrap List ---
- X
- X
- X========================== End of DOCUMENT LIST DUMP ===========================
- X
- X
- Global Local| Input File
- X------------+-------------------------------------------------------------------
- X 1 1| PR09: Test calls and actual parameter lists.
- X 2 2|
- X 3 3| First trip up the parser so we don't get any further.
- X 4 4| @>
- X Error|.^The parser was at the top level and was expecting
- X |.^one of: {Directive, Text, Macro definition, EOF}.
- X 5 5|
- X 6 6| Now define some macros to call. No error.
- X 7 7|
- X 8 8| @$@<Zero@>@{@}
- X 9 9| @$@<One@>@(@1@)@{@}
- X 10 10| @$@<Two@>@(@2@)@{@}
- X 11 11| @$@<Three@>@(@3@)@{@}
- X 12 12| @$@<Nine@>@(@9@)@{@}
- X 13 13| @$@#"@{@}
- X 14 14|
- X 15 15| The following test calls should NOT generate any errors.
- X 16 16|
- X 17 17| @$@<Macro containing the test macro calls.@>==@{
- X 18 18| 1. Test macro call with no parameter list.
- X 19 19| @<Zero@>
- X 20 20|
- X 21 21| 2. Test macro call with quick name.
- X 22 22| @#"
- X 23 23|
- X 24 24| 3. Test macro call with one parameter.
- X 25 25| @<One@>@(Toucan@)
- X 26 26|
- X 27 27| 4. Test macro call with many parameters.
- X 28 28| @<Two@>@(Toucan@,Teapot@)
- X 29 29| @<Three@>@(Toucan@,Teapot@,Walrus@)
- X 30 30| @<Nine@>@(Toucan@,Teapot@,Walrus@,
- X 31 31| Toucan@,Teapot@,Walrus@,
- X 32 32| Toucan@,Teapot@,Walrus@)
- X 33 33|
- X 34 34| 5. Test macro calls with double quotes on parameters.
- X 35 35| @<One@>@( @"Toucan@"@)
- X 36 36| @<Two@>@(@"Toucan@" @, @"Teapot@"@)
- X 37 37| @<Three@>@(@"Toucan@" @,
- X 38 38| @"Teapot@" @,
- X 39 39| @"Walrus@" @)
- X 40 40| @<Nine@>@( @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,
- X 41 41| @"Toucan@" @, @"Teapot@" @, @"Walrus@" @,
- X 42 42| @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)
- X 43 43|
- X 44 44| 7. Test macro calls with mixed double quotes on parameters.
- X 45 45| @<Two@>@(@"Toucan@" @,Teapot@)
- X 46 46| @<Three@>@(@"Toucan@" @,
- X 47 47| @"Teapot@" @,Walrus@)
- X 48 48| @<Nine@>@( @"Toucan@" @, @"Teapot@" @, Walrus @,
- X 49 49| @"Toucan@" @, Teapot @, @"Walrus@" @,
- X 50 50| @"Toucan@" @, @"Teapot@" @, @"Walrus@" @)
- X 51 51|
- X 52 52| @} @! End of macro definition enclosing all these legal tests.
- X 53 53|
- X 54 54| 8. Test macro calls with a variety of syntax errors in parameter list.
- X 55 55| @$@<Error1@>@{
- X 56 56| @<Zero@>@(
- X 57 57| @}
- X Error|.^Expecting @" or @, or @).
- X |.^Skipping after error to the next major construct...
- X 58 58| @A@<Error recovery point@>
- X |.^...skipped to here after the error.
- X 59 59|
- X 60 60| @$@<Error2@>@{
- X 61 61| @<Zero@>@)
- X Error|.........^Expecting '@}'.
- X |.........^Skipping after error to the next major construct...
- X 62 62| @}
- X 63 63| @A@<Error recovery point@>
- X |.^...skipped to here after the error.
- X 64 64|
- X 65 65| @$@<Error3@>@{
- X 66 66| @<One@>@(@"Toucan@)
- X Error|..................^Expecting '@"'.
- X |..................^Skipping after error to the next major construct...
- X 67 67| @}
- X 68 68| @A@<Error recovery point@>
- X |.^...skipped to here after the error.
- X 69 69|
- X 70 70| @$@<Error4@>@{
- X 71 71| @<One@>@(@"Toucan@"@"Sloth@"@)
- X Error|....................^Expecting @, or @).
- X |....................^Skipping after error to the next major construct...
- X 72 72| @}
- X 73 73| @A@<Error recovery point@>
- X |.^...skipped to here after the error.
- X 74 74|
- X 75 75| @$@<Error5@>@{
- X 76 76| @<Two@>@(@"Toucan@"Teapot@)
- X Error|....................^Expecting whitespace text.
- X 77 77| @}
- X 78 78| @A@<Error recovery point@>
- X 79 79|
- X 80 80| @$@<Error6@>@{
- X 81 81| @<Two@>@(@"Toucan@"Teapot
- X Error|....................^Expecting whitespace text.
- X 82 82| @}
- X Error|.^Expecting @, or @).
- X |.^Skipping after error to the next major construct...
- X 83 83| @A@<Error recovery point@>
- X |.^...skipped to here after the error.
- X 84 84|
- X 85 85| @$@<Error7@>@{
- X 86 86| @<Two@>@(@"Toucan@"Teapot
- X Error|....................^Expecting whitespace text.
- X 87 87| @<Three@>@(Toucan@,
- X Error|.^Expecting @, or @).
- X |.^Skipping after error to the next major construct...
- X 88 88| @"Teapot@,Walrus
- X 89 89|
- X 90 90| @}
- X 91 91| @A@<Error recovery point@>
- X |.^...skipped to here after the error.
- X 92 92|
- X | <End-Of-File>
- X------------+-------------------------------------------------------------------
- X
- There were 10 Errors.
- END_OF_FILE
- if test 59230 -ne `wc -c <'answers/pr09.lis'`; then
- echo shar: \"'answers/pr09.lis'\" unpacked with wrong size!
- fi
- # end of 'answers/pr09.lis'
- fi
- if test -f 'userman/u_ch2.tex' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'userman/u_ch2.tex'\"
- else
- echo shar: Extracting \"'userman/u_ch2.tex'\" \(66821 characters\)
- sed "s/^X//" >'userman/u_ch2.tex' <<'END_OF_FILE'
- X%==============================================================================%
- X% Start of Ch2.tex %
- X%==============================================================================%
- X%
- X% Copyright
- X% ---------
- X% Copyright (C) 1992 Ross N. Williams.
- X% This file contains a chapter of the FunnelWeb User's Manual.
- X% See the main TeX file for this manual for further information.
- X%
- X%==============================================================================%
- X
- X\chapter{FunnelWeb Hints}
- X\label{chapadvanced}\xx{FunnelWeb}{hints}
- X
- Whereas Chapter~\ref{chapintroduction} provides an introduction to
- XFunnelWeb and Chapter~\ref{chapdefinition} a definition, \i{this} chapter
- contains hints about how
- XFunnelWeb can be used. This chapter probably should not be read until
- the reader has already commenced using FunnelWeb, or at the very least,
- tried out some of the examples in Chapter~\ref{chapintroduction}.
- Those who find themselves using FunnelWeb frequently
- should read this chapter at some stage
- so as to ensure that they are getting the most out of it.
- X
- Most of the examples in this chapter have been
- placed in the FunnelWeb regression test suite which should be
- available in a directory called \p{/fwdir/tests/}.
- The files to examine are \p{hi01.fw} through \p{hi10.fw}.
- X
- X\section{Macro Names}
- X\xx{macro}{names}\xx{macro}{identifiers}
- X
- When using FunnelWeb, the choice of macro names can be as
- important to the readability of a program as the choice of program
- identifiers,
- and it is important that the user know the range of options available.
- X
- X\narrowthing{Names are case sensitive and exact matching:}{Macro names are case
- sensitive and are matched exactly. The strings used as a macro name
- at the point of definition and call must be
- X\i{identical} for the connection to be made.}
- X
- X\narrowthing{Names can contain any printable character:}{FunnelWeb is less
- restrictive about its macro names than most programming languages are
- about their identifiers. A FunnelWeb macro name can contain any
- sequence of printable characters, including blanks and punctuation. Names
- can start and end with any character. Names cannot cross line boundaries. The
- following are all legal macro names:}
- X
- X\begin{verbatim}
- X @<This macro expands to some really bad code@>
- X @<@>
- X @<453 #$ % --===~~1">>>@>
- X @<<@>
- X @<<>@>
- X @<a b c d e f g@>
- X @< ! @>
- X @<?? ...@>
- X @<"Who's been hacking MY program" said Father Bear.@>
- X @<Update the maximum and return for more data@>
- X\end{verbatim}
- X
- X\narrowthing{Names must be no more than a maximum limit in length:}{Names
- can be
- no longer than a predefined maximum length. Currently this length cannot
- be modified.}
- X
- Typically, macro names will consist of a short English phrase or sentence
- that describes the contents of the macro.
- X
- X\section{Quick Names}
- X\xx{quick}{names}
- X
- Sometimes a particular macro must be used extremely often. When this happens
- it is desirable to make the macro's name as short as possible.
- The shortest ordinary FunnelWeb macro name is the empty name\xx{empty}{name}
- X\dqp{@<@>}, which is four characters long. Single-character names are
- five characters long.
- X
- To cater for the cases where really short names are needed, FunnelWeb provides
- a \newterm{quick name} syntax that allows one-character macro names to be
- specified in two less characters. Quick names take the form of the special
- character, followed by a hash (\p{\#}) followed by a single character.
- XExamples:
- X
- X\begin{verbatim}
- X@#A @#| @#& @#m
- X\end{verbatim}
- X
- This form of macro name has the same syntactic functionality as an ordinary
- name and can be substituted wherever an ordinary name can be. In fact
- quick names live in the same namespace as ordinary macro names. For example
- the quickname \p{@\#A} is the \i{same name} (refers to the same macro)
- as the ordinary name \p{@<A@>}.
- X
- Because quick names look syntactically \dq{open} (\ie{}they do not have
- a closing\p{@>} as ordinary names do), it is best to avoid them except
- where a macro must be called very often.
- X
- X\section{FunnelWeb the Martinet}
- X\xx{FunnelWeb}{rules}\xx{FunnelWeb}{martinet}
- X
- There are many ways in which a macro preprocessor can cause unexpected
- difficulties. FunnelWeb seeks to avoid many of these problems by performing
- a number of checks. This section describes some of the checks that
- XFunnelWeb performs.
- X
- X\narrowthing{Trailing blanks in the input file:}{Trailing
- blanks\xx{trailing}{blanks} are usually
- not dangerous, but
- XFunnelWeb disallows them anyway. All trailing blanks in the
- X\i{input} (\p{.fw} file) are flagged as errors by FunnelWeb.
- XFunnelWeb does not flag trailing blanks in any of its output files.}
- X
- X\narrowthing{Input line length:}{FunnelWeb has a maximum input line
- length.\xx{input line}{length}
- If FunnelWeb reads an input line longer than this length, it flags the
- line with an error message. The maximum length can be changed using a
- pragma (see Chapter~\ref{chapdefinition}).}
- X
- X\narrowthing{Product file line length:}{FunnelWeb
- watches the length of output lines\xx{output line}{length}
- and all output lines longer than the limit are flagged with error
- messages.
- The maximum length can be changed using a
- pragma (see Chapter~\ref{chapdefinition}).
- That FunnelWeb polices output lines is very important. Some programs
- can behave very strangely if they get an input line that is too long
- X(\eg{}Fortran compilers\xx{Fortran}{compilers}
- can simply ignore text past a certain column!)
- and once FunnelWeb starts expanding macros using indentation, it is sometimes
- not obvious how wide the product file will be.}
- X
- X\narrowthing{Control characters:}{The presence of control
- characters\xx{control}{characters} in a text file
- can result in some confusing behaviour downstream when the file is
- presented to various programs. Unfortunately, some text
- editors\xx{text}{editors} allow
- control characters to be inserted into the text rather too easily, and it is
- all too easy to be tripped up. FunnelWeb prevents these problems by flagging
- with diagnostics all non-end-of-line control characters detected
- in the input (\p{.fw}) file (even TABs\x{tabs}).
- The result is that the user is
- guaranteed that product files generated from FunnelWeb contain no
- unintentional control characters. This said, FunnelWeb does allow the
- insertion of control characters in the output file by explicitly
- specifying
- them in the text using a \p{@\circumflex{}} control sequence.}
- X
- X\narrowthing{Number of invocations:}{FunnelWeb
- checks the number of times that\xx{invocations}{number}
- each macro is called and issues an error if the total is not one. The
- X\p{@Z} (for zero) and \p{@M} (for many) macro attributes can be used
- to bypass these checks.}
- X
- X\narrowthing{Recursion:}{Because\xx{recursion}{macro}
- XFunnelWeb does not provide any conditional
- constructs, all recursively defined macros must, by
- definition, expand infinitely,\footnote{A special case exists where
- there is recursion but no content. In this case, the expansion is finite
- X(the empty string) even though the operation of expanding is infinite.
- XFunnelWeb does not treat this case specially.} and are therefore
- unacceptable. FunnelWeb performs \i{static} checks to detect recursion,
- detecting it before macro expansion commences. The user need not fear that
- XFunnelWeb will lock up or spew forth
- if a recursive macro is accidentally specified.}
- X
- X\section{Fiddling With End of Lines}
- X\xx{EOL}{fiddling with}\xx{end-of-line}{fiddling with}\x{spacing}
- X
- One of the fiddly aspects of programming with FunnelWeb is coping with end of
- lines. If you want your product file to be well indented without
- multiple blank lines or code run-ons, you have to spend a little time working
- out how the end of line markers get moved around.
- X
- The rule to remember is that,
- disregarding the effects of special sequences
- within a macro body, \i{the body of a macro consists of exactly the text
- between the opening \p{@\{} and the closing \p{@\}}}. This text includes end of
- line markers.
- X
- If for example you call a macro in a sequence of code$\ldots$
- X
- X\begin{verbatim}
- while the_walrus_is_sleepy do
- X begin
- X writeln('zzzzzzz');
- X @<Wake up the walrus@>
- X writeln('Umpharumpha...');
- X end;
- X\end{verbatim}
- X
- where \p{<wake up the walrus>} is defined as follows
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>==@{
- wake_up_the_walrus(the_walrus);
- X@}
- X\end{verbatim}
- X
- then when \p{<Wake up the walrus>} is expanded you will get
- X
- X\begin{verbatim}
- while the_walrus_is_sleepy do
- X begin
- X writeln("zzzzzzz");
- X
- X wake_up_the_walrus(the_walrus);
- X
- X writeln("Umpharumpha...");
- X end;
- X\end{verbatim}
- X
- The blank lines were introduced by the end on line markers included in the
- definition of \p{<Wake up the walrus>}. A good solution to this problem is to
- suppress the end of line markers by defining the macro as follows
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>==@{@-
- wake_up_the_walrus(the_walrus);@}
- X\end{verbatim}
- X
- This is the usual form of macro definitions in FunnelWeb files.
- X
- In additive macros, this format does not
- work properly because the end of line that is suppressed by the trailing \p{@\}}
- does not get replaced by the end of line at the end of the macro invocation. For
- example the definition
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>+=@{@-
- wake_up_the_walrus_once(the_walrus);@}
- X\end{verbatim}
- X
- later followed by
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>+=@{@-
- wake_up_the_walrus_again(the_walrus);@}
- X\end{verbatim}
- X
- is equivalent to the single definition
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>==@{@-
- wake_up_the_walrus_once(the_walrus);wake_up_the_walrus_again(the_walrus);@}
- X\end{verbatim}
- X
- Putting the trailing \p{@\}} on a new line at the end of the macro (except for
- the last definition part) solves the problem.
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>+=@{@-
- wake_up_the_walrus_once(the_walrus);
- X@}
- X\end{verbatim}
- X
- later followed by
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>+=@{@-
- wake_up_the_walrus_again(the_walrus);@}
- X\end{verbatim}
- X
- is equivalent to the single definition
- X
- X\begin{verbatim}
- X@$@<Wake up the walrus@>==@{@-
- wake_up_the_walrus_once(the_walrus);
- wake_up_the_walrus_again(the_walrus);@}
- X\end{verbatim}
- X
- Managing end of line markers is tricky,
- but once you establish a convention for coping
- with them, the problem disappears into the background.
- X
- X\section{Fudging Conditionals}
- X\xx{fudging}{conditionals}
- X
- As a macro preprocessor, the facility that FunnelWeb most obviously lacks
- is a conditional facility (such as C's \p{\#ifdef}). It might, therefore,
- come as a surprise to know that the first version of FunnelWeb
- actually had a built in conditional facility. The facility allowed
- the programmer to specify a construct that would select from one of a number
- of macro expressions depending on the value of a controlling macro expression.
- X
- In three years the construct was never used.
- X
- The reason was that conditional constructs could be fudged nearly
- as easily as they could be used. Because of this, the inbuilt conditional
- feature was removed in the current version of FunnelWeb. Not only did this
- simplify the program, but is also allowed recursive macros to be detected
- through static analysis rather than during macro expansion.
- X
- There are two basic ways to fudge a conditional. First, the comment
- facility of the target programming language may be employed. For example,
- in Ada,\x{Ada}
- comments commence with \dqp{--} and terminate at the end of the line.
- Using this fact, it is easy to construct macros that can be called at the
- start of each target line and which turn on and off the lines so
- marked by defining the macro to be the empty string (ON) or the comment
- symbol (\p{--}) (OFF). For example:
- X
- X\begin{verbatim}
- X@A@<Debug Macro@>
- X
- The following macro determines whether debug code will be included in the
- program. All lines of debug code commence with a call to this macro and so
- we can turn all that code on or off here by defining this macro to be either
- empty or the single-line comment symbol (\p{--}). Note the use of a
- quick macro name.
- X
- X@$@#D@M==@{@} @! Turns the debug code ON.
- X@! Use this definition to turn the debug code OFF: @$@#D==@{--@}
- X
- X... then later in the file...
- X
- X@$@<Sloth incrementing loop@>==@{@-
- while sloth<walrus loop
- X @#D assert(sloth<walrus,"AWK! sloth>=walrus!!!!!!!");
- X @#D assert(timer<timermax,"AWK! timer>=timermax!!!");
- X inc(sloth);
- end loop@}
- X\end{verbatim}
- X
- The other way to fudge a conditional is to define a macro with a
- single parameter. A call to the macro is then wrapped around all the
- conditional code in the program. The macro can then be defined to
- present or ignore the code of its argument. For example:
- X
- X\begin{verbatim}
- X@A@<Debug Macro@>
- X
- The following macro determines whether debug code will be included in the
- program. All debug code is wrapped by a call to this macro and so
- we can turn all the debug code on or off here by defining this macro to be
- either empty or its parameter.
- X
- X@$@#D@(@1@)@M==@{@1@} @! Turns the debug code ON.
- X@! Use this definition to turn the debug code OFF: @$@#D@(@1@)==@{@}
- X
- X... then later in the file...
- X
- X@$@<Sloth incrementing loop@>==@{@-
- while sloth<walrus loop
- X @#D@(assert(sloth<walrus,"AWK! sloth>=walrus!!!!!!!");
- X assert(timer<timermax,"AWK! timer>=timermax!!!");@)
- X inc(sloth);
- end loop@}
- X\end{verbatim}
- X
- In languages that allow multi-line comments (\eg{}C with \p{/*} and \p{*/}),
- comments can be used to eliminate the conditioned code rather than
- absence. For example:
- X
- X\begin{verbatim}
- X@$@#D@(@1@)@M==@{/* @1 */@} @! Comments out the debug code
- X\end{verbatim}
- X
- X(Note: If this example were ever actually used,
- the programmer would have to be careful not to place comments in
- the argument code. Nested comments in~C are non-portable.)
- X
- The parameterized macro idea can be generalized to support the choice of
- more than one mutually exclusive alternative. For example:
- X
- X\begin{verbatim}
- X@A This module contains non-portable code that must execute on Hewlett
- Packard, Sun, and DEC workstations. The following FunnelWeb macro is
- defined to choose between these three. The first parameter is the HP code,
- the second is the Sun code, and the third is the DEC code. Whichever
- parameter constitutes the body of this macro determines which
- machine the code is being targeted\note{Dictionary says only one t
- in targeted.} for.
- X
- X@$@<Machine specific code@>@(@3@)@M==@{@1@} @! Configure for HP.
- X
- X...then later in the file...
- X
- X@<Machine specific code@>@(
- X@"get_command_line(comline)@" @, @! HP.
- X@"scan_command_line(128,comline);@" @, @! Sun.
- X@"dcl_get_command_line(comline,256);@" @) @! DEC.
- X\end{verbatim}
- X
- Of course, this could also be performed using three separate macros. The
- main advantage of using a single macro is that the mutual exclusivity is
- enforced. Also, because FunnelWeb ensures that the number of formal and
- actual parameters are the same, this method lessens the chance that a
- machine will be forgotten in some places.
- X
- X
- X\section{Changing the Strength of Headings}
- X\xx{headings}{strength}\xx{typesetting}{strength}%
- X\xx{section}{strength}\xx{font}{size}
- X
- XFunnelWeb provides five heading levels:
- X\p{@A}, \p{@B}, \p{@C}, \p{@D}, and \p{@E} to which it binds five different
- typographical strengths. These bindings are static; a level
- X\p{@A} heading will always be typeset in a particular font size regardless
- of the size of the document. The font
- sizes have been preset to be \dq{reasonable} for a range of document sizes,
- but may be inappropriate for very small or large documents.
- X
- XFunnelWeb does not currently provide an \dq{official}
- way (\eg{}a pragma) to change the typesetting
- strength of headings. This feature might be added in later versions.
- Meanwhile, a hack is available that will do the job, providing that you
- do not mind the hack being \TeX{}-specific and probably FunnelWeb-version
- specific.
- X
- Inside the set of \TeX{} macro definitions
- that FunnelWeb writes at the top of every documentation
- file are five \dq{library}
- definitions \p{fwliba}$\ldots$\p{fwlibe} which
- provide five different typesetting strengths for headings. Near the
- end of the set of definitions, FunnelWeb binds these macros to five
- other macros \p{fwseca}$\ldots$\p{fwsece} which are invoked directly in the
- generated \TeX{} code to typeset the headings.
- X
- X\begin{verbatim}
- X\def\fwseca#1#2{\fwliba{#1}{#2}}
- X\def\fwsecb#1#2{\fwlibb{#1}{#2}}
- X\def\fwsecc#1#2{\fwlibc{#1}{#2}}
- X\def\fwsecd#1#2{\fwlibd{#1}{#2}}
- X\def\fwsece#1#2{\fwlibe{#1}{#2}}
- X\end{verbatim}
- X
- This means that the typesetting strength of the headings in a FunnelWeb
- document can be changed by redefining these macros at the top of a FunnelWeb
- document. For example:
- X
- X\begin{verbatim}
- X@p typesetter = tex
- X\def\fwseca#1#2{\fwlibc{#1}{#2}}
- X\end{verbatim}
- X
- would set \p{@A} headings at the same strength as the default strength of
- X\p{@C} headings. The \p{typesetter} directive is necessary to ensure that the
- X\TeX{} control sequences get through to the documentation file unfiltered.
- X
- The following will tone down all headings by two levels (with the
- X\p{@D} and \p{@E} levels being allocated the default \p{@E} typesetting
- strength because there is nothing weaker).
- X
- X\begin{verbatim}
- X@p typesetter = tex
- X\def\fwseca#1#2{\fwlibc{#1}{#2}}
- X\def\fwsecb#1#2{\fwlibd{#1}{#2}}
- X\def\fwsecc#1#2{\fwlibe{#1}{#2}}
- X\def\fwsecd#1#2{\fwlibe{#1}{#2}}
- X\def\fwsece#1#2{\fwlibe{#1}{#2}}
- X\end{verbatim}
- X
- These definitions affect only the headings that follow them, and so they
- should be placed at the top of the FunnelWeb input file.
- X
- X\section{Efficiency Notes}
- X\xx{FunnelWeb}{efficiency}\xx{efficiency}{notes}
- X
- The following notes are worth keeping in mind when using FunnelWeb.
- X
- X\narrowthing{Memory:}{When\x{memory}\xx{input}{files}
- XFunnelWeb processes an input file, it reads
- the entire input file, and all the included files into memory.\footnote{If a
- file is included $n$ times, FunnelWeb keeps $n$ copies in memory.} This
- organization does not pose a constraint on machines with large memories,
- but could
- present a problem on the smaller machines such as the PC.}
- X
- X\narrowthing{Speed:}{FunnelWeb\x{speed} is not a slow program. However, it is
- not particularly fast either. If the speed at which FunnelWeb runs is
- important to you, then the thing to keep in mind is that FunnelWeb has been
- optimized to deal efficiently with large slabs of text. FunnelWeb treats
- input files as a sequence of text slabs and special sequences (\eg{}\p{@+})
- and whenever it hits a special sequence, it has to stop and think.
- Thus, while a ten megabyte text slab would be manipulated as a single token,
- in a few milliseconds, a similar ten megabyte chunk filled with special
- sequences would take a lot longer.
- If FunnelWeb is running slowly, look to see if the input contains
- a high density of special sequences. This can sometimes happen if FunnelWeb
- is being used as a backend macro processor and its input is being
- generated automatically by some other program.}
- X
- X\narrowthing{Macro expansion:}{When\xx{macro}{expansion}
- tangling (expanding macros), FunnelWeb never
- expands a macro expression into memory; it always writes it to the
- product file
- as it goes. This is a powerful fact, because it means that you can
- write macros containing an unlimited amount of text, and pass such macros
- as parameters to other macros without becoming concerned about overflowing
- some kind of buffer memory. In short, FunnelWeb does not impose any
- limits on the size of macro bodies or their expansions.}
- X
- X\section{Interactive Mode}
- X\x{interactive mode}\x{keyboard mode}
- X
- As well as having a command line interface with lots of options, FunnelWeb
- also provides a command language and a mode (\dq{interactive mode})
- in which commands in the language can be typed interactively. The
- XFunnelWeb command interpreter was created primarily
- to support regression testing,\xx{regression}{testing}
- but can also be useful to FunnelWeb users.
- X
- XFunnelWeb's command interpreter\xx{command}{interpreter}
- reads one command per line and can read
- a stream of commands either from a text file, or from the console. The
- interpreter can understand over twenty commands. See
- Chapter~\ref{chapdefinition} for a full list. However, most of them
- were designed to support regression testing and will not be of use to the
- casual user.
- X
- The commands that are of greatest use to the casual user
- are:\xx{useful}{commands}
- X
- X\begin{verbatim}
- X ! - Comment. Ignores the whole line.
- X EXECUTE fn - Execute the specified file.
- X FW options - Invoke FunnelWeb-proper once.
- X SET options - Sets options.
- X SHOW - Displays currently active options.
- X TRACE ON - Turns command tracing ON.
- X QUIT - Quits FunnelWeb.
- X\end{verbatim}
- X
- To distinguish here between invocations of the FunnelWeb program
- and FunnelWeb runs inside the shell, we call the latter \newterm{FunnelWeb
- proper}. The \dqp{FW} command invokes FunnelWeb proper with the specified
- options which take the same syntax as they do on the command line. The only
- restriction is that none of the action options can be turned on except
- X\dqp{+F} which must be turned on.
- X
- The \dqp{SET} command\xx{set}{command}
- has the same syntax as the \dqp{FW} command except that it
- does not allow \i{any} action options to be
- specified. It's sole effect is to set default option values for the
- rest of the run.
- X
- The \dqp{SHOW}\xx{show}{command}
- command displays the current default options.
- X
- By default, FunnelWeb does not echo the commands that it processes in a
- script. The \dqp{TRACE ON}\xx{trace on}{command}
- command turns on such tracing.
- X
- These commands can be combined to streamline the use of FunnelWeb.
- XFor example, you might wish to create a script called \p{typeset.fws}
- to process a whole group of files.
- X
- X\begin{verbatim}
- trace on
- X!This script typesets the whole program.
- X! Set no listing file, no product files, but specify a documentation file
- X! and specify the directory into which it should be placed.
- set -L -O +T/usr/ross/typeset/
- fw prog1
- fw prog2
- fw prog3
- fw prog4
- X\end{verbatim}
- X
- There are a few ways in which this script can be run. The simplest is
- simply to specify it in the \dqp{+X} option of a FunnelWeb invocation.
- XFunnelWeb shellscripts default to \dqp{<current\_directory>} and \dqp{.fws}.
- X
- X\begin{verbatim}
- fw +xtypeset
- X\end{verbatim}
- X
- The second alternative is to enter interactive mode.
- X
- X\begin{verbatim}
- fw +k
- X\end{verbatim}
- X
- XFrom there, you can execute the script using:
- X
- X\begin{verbatim}
- execute typeset
- X\end{verbatim}
- X
- Interactive mode could be very useful to those with multiple-window
- workstations.\x{workstations}
- The user could create a window containing an interactive
- session of FunnelWeb, and then switch between windows, editing, and executing
- XFunnelWeb proper and other programs.
- X
- If you find yourself using the command interpreter a lot, be sure to
- read about the other commands that are available in
- Chapter~\ref{chapdefinition}.
- X
- X\section{Setting Up Default Options}
- X\xx{options}{setting defaults}\xx{default}{options}
- X
- If you do not like FunnelWeb's default settings for its command line
- options, there are a number of ways in which you can change them.
- X
- X\narrowthing{Define an \dq{alias}:}{Use your operating system
- X\dqp{alias}\x{alias}
- facility to create an alias for FunnelWeb containing the desired options.
- XFunnelWeb processes options from left to right, so you can override
- these defaults later if you wish.}
- X
- X\narrowthing{Create a script called \dqp{fwinit.fws}:}{When FunnelWeb
- starts up, it executes a script called \dqp{fwinit.fws}\x{fwinit.fws}
- if\xx{startup}{script}\xx{initialization}{script} such a
- script exists in the current directory. You can use this fact to set options
- before the run of FunnelWeb proper by creating such a script and placing
- a single \dqp{set} command in it containing the desired options. The main
- trouble with this approach is that the options in the \p{set} command will
- be processed \i{after} the command line options, which means that you won't
- be able to override them on the command line.}
- X
- XFor example, you might be involved more with presenting programs than with
- running them, and want FunnelWeb to generate a documentation
- file by default, but not to produce
- listing or product files by default. In Unix you could do this with:
- X
- X\begin{verbatim}
- alias fw fw -L -O +T
- X\end{verbatim}
- X
- X\section{FunnelWeb and Make}
- X\x{make utility}\xx{file}{dependencies}
- X
- The Unix \p{Make} program allows a set of dependencies between a set of
- files to be described, and then uses these dependencies to control the way in
- which the files are created and updated. Typically,
- X\p{Make} is used to control the process of transforming a collection of
- source code files to one or more executable files.
- As the use of FunnelWeb implies an extra stage to this process, it is
- natural to include the transformation of \p{.fw} files to source code
- files as part of the \p{Make} process. This is easy to do, but the user
- should be aware of one aspect of FunnelWeb which can cause problems.
- X
- It is often useful, when using FunnelWeb, to create a FunnelWeb \p{.fw}
- file that generates more than one product file.
- That is, a single \p{.fw} file may have many macro definitions connected
- to product files so that when the FunnelWeb \p{.fw} file is processed by
- XFunnelWeb, several files are created. For example, this facility has been
- used to great effect to place the description of an Ada\x{Ada} package's
- package specification file and package body file in the same FunnelWeb
- X\p{.fw} file.
- X
- The use of multiple product files, however, provokes a problem
- with dependencies. Suppose for example that a FunnelWeb \p{prog.fw}
- produces two product files \p{proc.spec} (a package specification)
- and \p{prog.body} (a package body). If the package is accessed in the way
- that packages normally are, it will be quite common for the programmer
- to want to modify the package body without modifying the program specification.
- So the programmer will edit the \p{prog.fw} file to change the package
- body. The result of running this through FunnelWeb will be the desired
- new package body file. However, FunnelWeb will also produce a new package
- specification product file \i{even though it may be identical to the
- previous version!} The result is that the newly created (with a recent
- file date) specification package file could provoke a huge remake of much
- of the program in which it resides.
- X
- To solve the problem, FunnelWeb includes a command line option
- X(\p{D} for Delete),\xx{D}{option}\xx{delete}{output files}
- which when turned on (using \dqp{+D}) causes
- XFunnelWeb to suppress\xx{suppression}{file}
- product and documentation files that are identical
- to the previously existing versions of the same files. For example,
- if, during a FunnelWeb run, a macro was connected to a product file called
- X\p{x.dat}, and the macro expanded to \i{exactly} the same text as is
- contained in \p{x.dat} then FunnelWeb would simply \i{never write the product
- file}, the file \p{x.dat} would be untouched and, as a result, no further
- X\p{Make} propagations would take place.
- X
- XFunnelWeb implements this feature by writing each product file to
- a temporary file with a temporary file name. It then compares the temporary
- file with the target file. If the two are identical, it deletes the
- temporary file. If the two are different it deletes the target file and
- renames the temporary file to the target file.
- X
- Use of the \p{D} facility means that the programmer need not be punished
- X(by extra \p{Make} propagations) for describing more than one product file
- in the same FunnelWeb file.
- X
- X
- X\section{The Dangers of FunnelWeb}
- X\xx{FunnelWeb}{dangers}\xx{FunnelWeb}{pitfalls}
- X
- Like many tools that are general and flexible, FunnelWeb can be used in a
- variety of ways, both good and bad. One of the original appeals of the
- literate approach to programming for Knuth,\xn{Donald}{Knuth}
- the inventor of literate
- programming,\xx{literate}{programming}
- was that it allows the programmer to describe the target
- program bottom up, top down, size to side, or chaotically if desired.
- The flexibility that this style of programming leaves much
- room for bad documentation as well as good documentation. Years of
- experience with FunnelWeb has revealed the following stylistic pitfalls
- which the experienced FunnelWeb user should take care to
- avoid.\footnote{The fact that these faults are listed here does not mean
- that the author has eliminated them in his own work. Rather,
- it is mainly the author's own mistakes that have resulted in this list
- being compiled. The author immediately
- confesses to several of the faults listed here, most notably that of
- Pavlov documentation.}
- X
- X\narrowthing{Spaghetti organization:}{By\xx{spaghetti}{organization}
- far the worst problem that arises
- in connection with the literate style occurs where the programmer has
- used the literate tool to completely scramble the program so that the
- program is described and layed out in an unordered, undisciplined
- X\dq{stream of consciousness}.\x{stream of consciousness}
- In such cases the programmer may be using
- the literate style as a crutch to avoid having to
- think about structuring the presentation.}
- X
- X\narrowthing{Boring organization:}{At\xx{boring}{organization}
- the other extreme, a program may be
- organized in such a strict way that it is essentially laid out in the
- order most \dq{desired} by the target programming language. For example,
- each macro might contain a single procedure, with all the macros being
- called by a macro connected to a file at the top. In many cases a boring
- structure may be entirely appropriate, but the programmer should be warned
- that it is easy to slip into such a normative style, largely forgetting the
- descriptive structural power that FunnelWeb provides.}
- X
- X\narrowthing{Poor random access:}{Using\xx{random}{access}
- XFunnelWeb, it is quite possible to write
- programs like novels\x{novels}
- X--- to be read from cover to cover. Sometimes the
- story is very exciting, with data structures making dashing triumphs and
- optimized code bringing the story to a satisfying conclusion. These programs
- can be works of art.
- Unfortunately, without careful construction,
- such \dq{novel-programs} can become very hard to access randomly by (say)
- a maintenance programmer\xx{maintenance}{programmer}
- who wishes only to dive in and fix a specific
- problem. If the entire program is scrambled for sequential exposition, it
- can be hard to find the parts relating to a single function.
- Somehow a balance must be struck in the document between the
- needs of the sequential and of the random-access reader.
- This balance will depend on the intended use of the program.}
- X
- X\narrowthing{Too-interdependent documentation:}{Sometimes,
- when\xx{documentation}{interdependent} editing a
- program written using FunnelWeb, one knows how to modify the program,
- but one is unsure of how to update the surrounding documentation!
- The documentation may be woven into such a network of facts that it seems that
- changing a small piece of code could invalidate many
- pieces of documentation scattered throughout the document. The documentation
- becomes a big tar pit in which movement is impossible.
- XFor example,
- if you have talked about a particular data structure invariant throughout
- a document, changing that invariant in
- a small way could mean having to update all the documentation without
- touching much
- code. In such cases, the documentation is too interdependent. This could be
- symptomatic of an excessibly interconnected program, or of an
- excessively verbose or redundant documenting style. In any case, a balance
- must be struck between the conversational style that encourages redundancy
- X(by mentioning things many times) and the normalized database approach where
- each fact is given at only one point, and the reader is left to figure
- out the implications throughout the document.}
- X
- X\narrowthing{Pavlov documentation:}{By\xx{pavlov}{documentation}
- placing so much emphasis on the documentation,
- XFunnelWeb naturally provides slots where documentation \dq{should} go. For
- example, a FunnelWeb user may feel that there may be a rather unpleasant
- gap between a \p{@C} marker and the following macro. In many cases \i{no}
- commentary is needed and the zone is better left blank rather than being
- filled with the kind of uninformative waffle one often finds filling the slots
- of structured documentation written according to a military standards
- X(\eg{}MIL-STD-2167A).\x{MIL-STD-2167A}\x{2167A}\footnote{Note:
- This is not a criticism of 2167A,
- only of the way it is sometimes used.} The lesson is to add documentation
- only when it adds something. The lesson in Strunk and White\paper{Strunk79}
- X(p.~23)
- holds for
- program documentation as it does for other writing: \dq{Vigorous writing is
- concise. A sentence should contain no unnecessary words, a paragraph no
- unnecessary sentences, for the same reason that a drawing should have
- no unnecessary lines and a machine no unnecessary parts. This
- requires not that the writer make all his sentences short, or that he avoid
- all detail and treat his subjects only in outline, but that every word
- tell.}.\checked{}}
- X
- X\narrowthing{Duplicate documentation:}{Where\xx{duplicate}{documentation}
- the programmer is generating
- product files that must exist on their own within the entire programming
- environment (\eg{}the case of a programmer in a team who is using FunnelWeb
- for his own benefit but must generate (say) commented Ada\x{Ada}
- specification
- package files) there is a tendency for the comments in the
- target code to duplicate the commentary in the FunnelWeb text. This may or
- may not be a problem, depending on the exact situation. However, if this is
- happening, it is certainly worth the programmer spending some time deciding
- if one or other of the FunnelWeb or inline-comment documentation should be
- discarded.
- In many cases, a mixture can be used, with the FunnelWeb documentation
- referring the reader to the inline comments where they are present.
- XFor example:}
- X
- X\begin{verbatim}
- X@A Here is the header comment for the list package specification.
- The reader should read these comments carefully as they define a list.
- There is no need to duplicate the comments in this text.
- X
- X@$@<Specification package header comments@>==@{@-
- X-- LIST PACKAGE
- X-- ============
- X-- * A LIST consists of zero or more ITEMS.
- X-- * The items are numbered 1 to N where N is the number of items in the list.
- X-- * If the list is non-empty, item 1 is called the HEAD of the list.
- X-- * If the list is non-empty, item N is called the TAIL of the list.
- X-- ...
- X@}
- X\end{verbatim}
- X
- X\narrowthing{Overdocumenting:}{Another\xx{over}{documentation}
- evil that can arise when using FunnelWeb is
- to over-document the target program. In some of Knuth's earlier (\eg{}1984)
- examples of literate programming, each variable is given its own description
- and each piece of code has a detailed explanation. This level of analysis,
- while justified for tricky tracts of code, is probably not warranted
- for most of the code that constitutes most programs. Such over-commenting
- can even have the detrimental affect of obscuring the code, making it hard
- to understand because it is so scattered (see \dq{spaghetti organization}
- earlier). It is up to the user to decide when a stretch of just a few lines of
- code should be pulled to bits and analysed and when it is clearer to leave it
- alone.}
- X
- X\narrowtext{In the case where there
- are a few rather tricky lines of code, a detailed
- explanation may be appropriate. The following example
- contains a solution to a problem outlined in section 16.3 of
- the book \dq{The Science of Programming} by David Gries\paper{Gries81}.}
- X
- X\begin{verbatim}
- X@C@<Calculation of the longest plateau in array b@>
- X
- This section contains a solution to a problem outlined in section 16.3 of
- the book @/The Science of Programming@/ by David Gries[Gries81].
- X
- X@D Given a sorted array @{b[1..N]@} of integers, we wish to determine the
- X@/length@/ of the longest run of identically valued elements in the array.
- This problem is defined by the following precondition and postcondition.
- X
- X@$@<Precondition@>==@{/* Pre: sorted(b). */@}
- X@$@<Postcondition@>==@{@-
- X/* Post: sorted(b) and p is the length of the longest run in b[1..N]. */@}
- X
- X@D We approach a solution to the problem by deciding to try the approach of
- scanning through the array one element at a time maintaining a useful
- invariant through each iteration. A loop variable
- array index @{i@} is created for this purpose. The bound function is
- X@{N-i@}. Here is the invariant.
- X
- X@$@<Invariant@>==@{@-
- X/* Invariant: sorted(b) and 1<=i<=N and */
- X/* p is len of longest run in b[1..i]. */@}
- X
- X@D Establishing the invariant above in the initial, degenerate case is easy.
- X
- X@$@<Establish the plateau loop invariant initially@>==@{i=1; p=1;@}
- X
- X@D At this stage, we have the following loop structure. Note that when both
- the invariant and @{i != N@} are true, the postcondition holds and the loop
- can terminate.
- X
- X@$@<Set p to the length of the longest plateau in sorted array b[1..N]@>==@{@-
- X@<Precondition@>
- X@<Establish the plateau loop invariant initially@>
- while (i != N)
- X {
- X @<Invariant@>
- X @<Loop body@>
- X }
- X@<Postcondition@>
- X@}
- X
- X@D Now there remains only the loop body whose sole task is to increase @{i@}
- X(and so decrease the value of the bound function) while maintaining the
- invariant. If @{p@} is the length of the longest run
- seen so far (i.e. in b[1..i]), then, because the array is sorted,
- the extension of our array range to
- X@{b[1..i+1]@} can only result in an increase in @{p@} if the new element
- terminates a run of length @{p+1@}. The increase can be at most 1. Because
- the array is sorted, we need
- only compare the endpoints of this possible run to see if it exists. This
- is performed as shown below.
- X
- X@$@<Loop body@>==@{i++; if (b[i] != b[i-p]) p++;@}
- X\end{verbatim}
- X
- X\narrowtext{Where the code is more obvious,
- it is often better to let the code speak for itself.}
- X
- X\begin{verbatim}
- X@C The following function compares two C~strings and returns TRUE iff they
- are identical.
- X
- X@$@<Function comp@>==@{@-
- bool comp(p,q)
- char *p,*q;
- X{
- X while (TRUE)
- X {
- X if (*p != *q ) return FALSE;
- X if (*p == '\0') return TRUE;
- X p++; q++;
- X }
- X}
- X@}
- X\end{verbatim}
- X
- X\section{Wholistic Debugging}
- X\xx{wholistic}{debugging}
- X
- Surprising though it may be, FunnelWeb has a key role to play in the
- X\i{debugging} of programs. Long experience in programming has led me to the
- concept of \newterm{wholistic debugging}. When most programmers detect a
- bug, their first reaction seems to be to jump into the debugger\x{debugger}
- where they
- often spend many hours stepping through endless stretches of code and
- generally wasting a lot of time.
- X
- In contrast, my first reaction when I detect a bug is to realize that
- X\i{the code must not be in good enough shape if such a bug can arise.}
- The presence of the bug is taken as symptomatic of the lack of general
- health of the code. If that bug occurred, why not another?
- In response to this realization, my reaction is not to enter the debugger,
- but rather to return to the original code and tend it like a
- garden,\xx{code}{gardening}
- adding more comments, reworking the grotty bits, adding assertions,
- and looking for faults. In many cases, the search for faults does not
- even centre on the specific bug that arose, but does tend to focus on
- the area of code where the bug is likely to be.
- X
- The result is often that the original bug is located more quickly than it
- would have been had the debugger been involved. But even if it isn't, there
- are other benefits. A programmer who enters the debugger may
- stay there for hours and still not find the bug. The result is
- frustration and no positive gain at all. In contrast, by tending to the
- code, the programmer is making forward progress at all times (the code
- is constantly improving) even if the bug is not immediately found.
- At the end of ten hours, the programmer can at least feel that the code
- is \dq{ten hours better}, whereas the debugger freak will likely feel
- defeated.
- All this makes code tending better psychologically as well as a more
- efficient approach to debugging.
- X
- I call this technique wholistic debugging, for it is like the
- difference between conventional and wholistic medicine.\xx{wholistic}{medicine}
- Go to a
- conventional doctor with a headache and he might send off for head X-rays,
- perform allergy tests and perform many other
- debugging activities. Go to a wholistic doctor with the same problem and
- he might look to see if you are fit, assess your mental health, and ask you
- if your marriage is working. Both approaches are appropriate at different
- times. In programming, the wholistic approach is not used enough.
- X
- X\section{Examples of FunnelWeb Applications}
- X\xx{FunnelWeb}{example applications}\xx{FunnelWeb}{applications}
- X
- Despite (or perhaps because of) its flexibility and simplicity,
- XFunnelWeb can be applied to quite a number of different
- text processing and documenting problems. This section describes some of
- the more interesting real problems that FunnelWeb has solved.
- X
- X\subsection{Analyzing the Monster Postscript Header File}
- X\xx{monster file}{postscript}
- X
- During my Ph.D. candidature, I determined at one point that it would be
- very desirable to automatically insert diagrams from the \i{MacDraw}\x{MacDraw}
- program on my Macintosh into
- X\TeX{}\x{TeX}
- X\p{insert}ions in my thesis.\xx{PhD}{thesis} This would allow diagrams to float
- around with the text and be printed automatically rather than having to be
- printed separately and stuck in with real glue. On the face of it, the
- problem seemed inherently solvable as the Macintosh\x{Macintosh}
- could generate PostScript\x{PostScript}
- for each diagram and this PostScript could presumably be inserted into the
- PostScript generated using \TeX{}.
- X
- The only trouble was that the Macintosh PostScript code for the diagrams
- relied on an Apple PostScript header file.\xx{postscript}{header file}
- This meant that the header file
- had to be included at the start of the \TeX{} PostScript if the inserted
- PostScript for the diagrams was to work.
- Unfortunately, merely including the header file at the top didn't work, and
- it turned out that a rather detailed analysis of some parts of the Apple
- header file was required in order to perform the necessary surgery on the
- header file to make it work. This analysis was severely aggravated by the
- fact that the PostScript header file was virtually unreadable. Basically
- it was about 50K of interwoven
- definitions, that looked as if it had been run through a word processor.
- There was no way that the code could be understood clearly without some
- kind of reformatting. Two other aspects of the problem further complicated
- the analysis:
- X
- X\begin{itemize}
- X
- X\item The definitions of interest (\ie{}the ones causing the problems)
- were scattered throughout the file.
- X
- X\item Many definitions could not be moved. For one or more reasons
- X(\eg{}to keep a definition within the activation of a particular
- dictionary \p{begin} and \p{end}) it would have been unwise to move the
- definitions of interest to the same point in the file.
- X
- X\end{itemize}
- X
- In fact the file was so messy and complicated that, as a rule, it had to
- be handled with kid gloves. It would have been unwise to re-arrange
- the definitions or to insert comments.
- X
- To my surprise, FunnelWeb provided an unexpected solution to
- the problem. First I replaced all occurrences of the \p{@} in the
- header file with \p{@@}. Second, I placed the entire header file
- in a FunnelWeb macro definition connected to a product file. I then
- processed the file and checked to make sure that the product file
- was identical to the original file.
- By doing all this I had placed the
- header file under FunnelWeb control. I then left the
- macro definition largely untouched, but replaced the PostScript
- definitions of
- interest with FunnelWeb macro calls, moving the actual PostScript
- definitions into FunnelWeb macro definitions at the end of the FunnelWeb
- file.
- X
- X\begin{verbatim}
- X@O@<LaserHeader.ps@>==@{@-
- Unreadable Postscript code
- X@<Print routine@>
- Unreadable Postscript code
- X@<Zap routine@>
- Unreadable Postscript code
- X@}
- X
- X@A This routine looks as if it does this, but really is does that,
- blah, blah blah.
- X
- X@$@<Print routine@>==@{@-
- X/print { push pop pop push turn around and jump up and down and print it} def
- X@}
- X
- X@A This routine zaps the...
- X
- X@$@<Zap routine@>==@{@-
- X/zap { push pop pop push turn around and jump up and down and print it} def
- X@}
- X\end{verbatim}
- X
- Use of FunnelWeb meant that I was able to pluck out the definitions of interest
- X(a very small part of the whole file) and collect them as a group at the end
- of the file where they could be studied.
- Because each definition was safely contained in a macro, it was possible to
- write a detailed commentary of each routine without fear of affecting the
- final PostScript code in any way at all. Once this analysis was completed,
- it was possible to perform surgery on the offending PostScript definitions
- in an extremely controlled way. In particular, the FunnelWeb input file
- served as a repository for all the different versions of particular routines
- that were tried in order to get the definitions to work. A new (\b{Z}ero)
- macro was created for each version of each definition, and a commentary of how
- it performed added above it.
- X
- This case demonstrates that
- XFunnelWeb is an extremely powerful tool for dissecting and
- documenting cryptic text files.\xx{cryptic}{text files}
- Through the use of macros, particular
- parts of the file can be isolated and discussed without affecting the
- final product file in any way. In the example above, only a small part of the
- file was analysed, the rest being left as a blob, but in the general case,
- a cryptic text file could be inserted into FunnelWeb and then incrementally
- dissected (and possibly modified) until the result is a fully documented
- literate program. That this can be done without affecting the actual
- product file demonstrates the high degree of descriptive control that
- XFunnelWeb provides.
- X
- X\subsection{Making Ada ADTs more A}
- X\x{Ada}\x{abstract data type}\x{ADT}
- X
- Like many modern programming languages, Ada provides mechanisms for hiding
- information and structure. In particular, Ada provides a \newterm{package}
- facility that allows the programmer to declare objects in a
- package definition and define them in a corresponding package body.
- This works well
- for functions and procedures. However, in the case of types, implementation
- issues (in particular, the need to know the size of exported types) have
- led the designers of Ada to force the placement of
- private type definitions in the definition package rather than the
- implementation package. This means that some implementation details
- are present in the package definition for all to see. While not actually
- dangerous (the user of the package cannot make use of the information
- without recourse to \dq{Chapter~13} of the Ada Language Reference
- Manual\paper{DOD83}), this aspect of Ada is certainly unpleasant.
- X
- During the development of some Ada programs, FunnelWeb was used to solve
- this problem. Instead of creating a separate file for the package
- specification and package body, a single FunnelWeb file was created containing
- two sections, one for the each package part. The \dq{private} part of the
- package specification was then moved (using a FunnelWeb macro definition)
- to the section describing the package body. Readers who wished only to read
- the package specification could read only the first part, which contained
- a fully documented description not containing the private definition.
- X
- X\subsection{Multiple Language Systems}
- X\xx{multiple}{languages}
- X
- With the prevalence of open systems\x{open systems}
- and multi-vendor computing, it is
- often necessary to construct systems consisting of programs written in
- a number of different programming languages for a number of different
- systems. For example, a particular functionality might be implemented by a
- shellscript
- X(invoked by the user) that calls a C~program that makes a network connection
- to a Pascal program that queries a database. Quite often all these programs
- must conspire closely to execute their function. In the normal case, they
- must be written separately. FunnelWeb allows them to be written as a
- whole.
- X
- By creating a single FunnelWeb file that creates many product files in
- different languages, the programmer can describe the interaction between
- the different programs in any manner desired. Furthermore, because
- the different product files are all created in the same \dq{text space}
- X(\ie{}in a single FunnelWeb file), it is easy for them to share information.
- X
- XFor example, in one real application FunnelWeb was used to create a
- system for printing files\xx{printing}{system}
- on a laser printer\xx{laser}{printer}
- connected to a remote Vax
- Unix machine from a local Vax VMS
- machine. The system consisted of two files: a VMS DCL command procedure
- to run on the local node, and a Unix shellscript to run on the remote
- node. The user, by giving the print command, invoked the local VMS
- command procedure, which in turn fired up the remote Unix shellscript. The
- two scripts then cooperated to transfer the files to be printed and print
- them.
- X
- In addition to its usual documentation powers, FunnelWeb assisted in the
- creation of this system in two special ways. First, it allowed pieces of
- code from the two different command procedures to be partially interwoven in a
- description of their interaction. This is just not possible with comments.
- Second, it facilitated the use of shared information. For example, under
- some conditions, each file to be printed would be renamed and copied to the
- remote system using a particular constant filename (\eg{}\dqp{printfile.tmp}).
- XFunnelWeb allowed this constant filename to be included in a single macro
- definition which was invoked in the definition of each of the scripts. This
- ensured that the two scripts used the same name.
- X
- X\begin{verbatim}
- X@A The following macro contains the temporary file name used to allow the
- two shellscripts to transfer each file to be printed.
- X
- X@$@<printfile@>@M==@{printme.txt@}
- X
- X@A Here are the scripts for the local VMS node and the remote UNIX node.
- X
- X@O@<vmscommandprocedure.com@>==@{@-
- DCL commands
- copy @<printfile@> unixnode::
- DCL commands
- X@}
- X
- X@O@<unixshellscript@>==@{@-
- unix commands
- print @<printfile@>
- unix commands
- X@}
- X\end{verbatim}
- X
- In the case of the printing system, the entire system was described and
- defined in a single FunnelWeb \p{.fw} file. In larger systems containing
- many FunnelWeb \p{.fw} files for many different modules in many different
- languages, the same trick can be pulled by placing FunnelWeb macro
- definitions for shared values into FunnelWeb include files. For example,
- a suite of implementations of network nodes, with each implementation being
- in a different programming language for a different target machine, could
- all share a table of configuration constants defined in macros in a
- XFunnelWeb include file.
- X
- In summary, FunnelWeb's macro and include file mechanisms provide
- a simple way for programs written in different languages to share
- information. This reduces redundancy between the systems and hence the
- chance of inconsistencies arising.\x{sharing information}
- X
- X\subsection{The Case of the Small Function}
- X\xx{small}{functions}
- X
- Often, when programming, there is a need for a
- code abstraction\xx{code}{abstraction} facility
- that operates at the text level. If the statement \dqp{a:=3;} occurs often,
- it may be best simply to repeat it verbatim. If a sequence of one hundred
- statements is repeated often, it is normal to remove the code to a function
- and replace the occurrences by a function call.
- However, in between these two extremes are cases where a particular sequence
- of code is long enough and appears often enough to be troublesome, but which
- is bound so messily to its environment as to make a function call
- cumbersome.
- X
- XFor example, the following line of statements (referring to five variables
- declared \i{local} to a function) might appear ten times in
- a function:
- X
- X\begin{verbatim}
- a=b*3.14159; c=d % 256; e=e+1;
- X\end{verbatim}
- X
- Now the \dq{normal} rule of programming says that these statements should be
- placed in a procedure (also called a \dq{function} in the C programming language
- used in this example),
- but here five local variables are used. Use of a procedure
- X(function) would result in a procedure definition looking something like:
- X
- X\begin{verbatim}
- void frobit(a,b,c,d,e)
- float *a,b;
- int *c,d;
- unsigned *e;
- X{*a=b << 8; *c=d % 256; *e=*e+1;}
- X\end{verbatim}
- X
- and a procedure call something like
- X
- X\begin{verbatim}
- frobit(&a,b,&c,d,&e);
- X\end{verbatim}
- X
- This might be workable in a language that allowed formal parameters to be
- specified to be bound only to particular variables. Similarly, it might
- be possible to avoid the parameter list in languages that support
- local procedures that can access non-local variables (such as
- Pascal\x{Pascal}).
- However, in our example here, in the C programming language, these options
- are not available, and so we must either create a function with five
- parameters,
- or use the C macro preprocessor\xx{preprocessor}{C}
- X(the best solution). FunnelWeb provides the
- same macro facility for languages that do not have a built-in
- preprocessor.
- X
- In particularly speed-stressed applications, the programmer may be
- reluctant to remove code to a procedure because of the procedure-call
- overhead.\xx{procedure call}{overhead}
- XFunnelWeb macros can help there too.
- X
- In summary, there sometimes arises in programming situations where the
- cost of defining a procedure is higher than the benefits it will bestow.
- Common reasons for this are the run-time procedure overhead and
- the messy binding problems\xx{binding}{problems}
- caused by removing target code from its target context. FunnelWeb
- can help in these situations by allowing the programmer to define a text
- macro. This avoids all the problems and provides an additional incentive
- for the programmer to describe the piece of code so isolated.
- X
- X\subsection{When Comments are Bad}
- X\xx{comments}{abuse}\xx{eliminating}{comments}
- X
- In the \dq{good old days}\x{good old days}
- of small machine memories and interpreted BASIC,\x{BASIC}
- programmers would eliminate the \dqp{REM} statements\xx{REM}{statement}
- X(comments) from their
- BASIC programs so as to save space and increase execution speed. Whilst
- this was obviously an appalling programming practice, the small memories
- and slow microprocessors often made this tempting, if not necessary.
- X
- Thankfully, times have changed since then,
- and most code is now compiled
- rather than interpreted. However, from time to time one still runs into
- an environment or situation, or special-purpose language, where comments
- are either unavailable (no comment feature) or undesirable. Here
- XFunnelWeb can be used to fully document the code without resulting in any
- comments in the final code at all. For example:\xx{header}{files}
- X
- X\begin{itemize}
- X
- X\item Comments in frequently used \p{.h} header files in C
- programs\xx{C}{header} can
- have a significant impact on compilation speed. Often such header files
- are fairly cryptic and really ought to be well commented, but their authors
- are reluctant to.
- X
- X\item Comments are undesirable in PostScript\x{postscript}
- header files that must be
- transferred repeatedly along communications channels (\eg{}the Apple
- Macintosh LaserWriter header file).
- X
- X\item Interpreted programs in embedded systems.
- X
- X\item Hand written machine code in hex dump form could be commented.
- X
- X\item A programmer may wish to annotate a text data file containing lists
- of numbers that is to be fed into a statistical program that does not
- provide any comment facility for its input file.
- X
- X\end{itemize}
- X
- In all these situations, FunnelWeb allows full integrated documentation
- without any impact on the final code.
- X
- X\subsection{Documents That Share Text}
- X\xx{sharing}{text}
- X
- XFunnelWeb is very useful when preparing multiple documents that must
- share large slabs of identical text that are being constantly modified.
- X
- XFor example someone preparing two slightly different user manuals for two
- slightly different audiences might want the manuals to share
- large slabs of text, while still allowing differences between them.
- The following example shows how this can be done. The code is cluttered,
- but this clutter would not be a problem if the lumps of text were moderately
- large.
- X
- X\begin{verbatim}
- X@O@<manual1.txt@>==@{@<M1@>@+@}
- X@O@<manual2.txt@>==@{@<M2@>@+@}
- X
- X@$@<M1@>+=@{@<T1@>@}
- X@$@<M2@>+=@{@<T1@>@}
- X@$@<T1@>@M==@{First lump of text shared by both documents.@+@}
- X
- X@$@<M1@>+=@{Text for first document@+@}
- X@$@<M2@>+=@{Text for second document@+@}
- X
- X@$@<M1@>+=@{@<T2@>@}
- X@$@<M2@>+=@{@<T2@>@}
- X@$@<T2@>@M==@{Second lump of text shared by both documents.@+@}
- X\end{verbatim}
- X
- An alternative approach, which might work better in situations where there
- are many small differences between the two documents rather than a few large
- ones, is to define a macro with two arguments, one for each product
- file document.
- Write the document from top to bottom, but place all stretches that
- differ between the two documents in a macro call.\xx{annual}{report}
- X
- X\begin{verbatim}
- X@! Set the definition of @#D to
- X@! @1 to create the shareholders report.
- X@! @2 to create the customers report.
- X@$@#D@(@2@)@M==@{@1@}
- X
- X@O@<report.txt@>==@{@-
- X1992 ANNUAL REPORT TO @#D@(Shareholders@,Customers@)
- X======================@#D@(============@,=========@)
- This has been a very good year for The Very Big Corporation of America.
- With your help, we have been able to successfully
- X@#D@(@"screw the customers for every cent they have@"@,
- X @"knock the shareholders into submission to bring you lower prices@"@).
- With gross earnings approaching six trillion dollars, we have been able to
- X@#D@(@"increase dividends@"@,
- X @"lower prices@"@).
- We expect to have an even better year next year.
- X@}
- X\end{verbatim}
- X
- One application where text sharing can be particularly useful is in the
- preparation of computer documentation\xx{examples}{documentation}
- containing examples. For example,
- a book describing a new programming language might be full of examples
- of small programs written in the language which the user might want to try
- without having to type them all in. The \dq{default} approach of keeping
- a copy of the examples in the text of the book and another copy in
- separate files is cumbersome and error prone, because both files have to
- be updated whenever an example is changed. A more sophisticated approach is
- to store each example in a separate file, and then use the \dq{include file}
- facility of the word processor to include each example in the text.
- This is a better solution, but suffers from a few drawbacks. First, when
- editing the book in a word processor, the
- examples in the book will not be directly accessible or visible. To see an
- example, the writer would have to open the file containing the example in
- a separate window. This could become tedious if the text contained many
- examples, as many texts do. Furthermore, there is a risk that some example
- files will be included in the wrong place. Second, because the book is
- dependent on the included files, the book will end up consisting of a
- directory of a hundred or more files instead of just a few.
- X
- An alternative solution is to construct a single FunnelWeb \p{.fw}
- file that, when processed, produces both the book file and the example files.
- This solution assumes that the book consists of a text file containing
- commands for a typesetter such as \TeX{}.
- X
- X\begin{verbatim}
- X@O@<Book.tex@>==@{@#B@}
- X
- X@$@#B+=@{@-
- The first step to learning the object oriented AdaCgol++ language is to examine
- a hello world program.
- X
- X\start{verbatim}
- X@<Ex1@>
- X\finish{verbatim}
- X@}
- X
- X@$@<Ex1@>==@{read iopack@+Enter !World~! !Hello~! ex pr flu X[1]@}
- X@O@<Ex1.c@>==@{@<Ex1@>@}
- X
- X@$@#B+=@{@-
- To understand the program, think of the execution state as a plate of cheese...
- X@}
- X\end{verbatim}
- X
- Most of the file will consist of part definitions of the additive
- macro \p{@\#B}. The definition is \dq{broken} to allow a macro definition,
- wherever an example appears.
- X
- The example above is a little messy because FunnelWeb does not allow
- macros connected to product files to be called, and it does not have
- text expressions that write to an product file as well as evaluating to text.
- Nevertheless, it presents a fairly clean solution to the problem of keeping
- the example programs in a computing text up to date.
- X
- X\subsection{Generics}
- X\xx{generics}{fudging}
- X
- It is well known that generics in programming languages are closely aligned
- with textual substitution. In fact, a good way to understand the generic
- facility of a new programming language is to ask oneself the question
- X\dq{In what way does this generic facility differ from simple text
- substitution?} The differences, if any, typically have to do with
- the difference in scoping between textual and intelligent substitution
- and whether the generic code is shared or copied by the implementation.
- In most cases the differences are quite minor.
- X
- Because generic facilities are so closely aligned with text substitution,
- it is possible to use FunnelWeb's parameterized macros to provide generics
- in programming languages that do not support generics. Simply write a
- XFunnelWeb macro whose parameters are the parameters of the generic and
- whose body is the generic object.
- X
- The following FunnelWeb file gives an example of a fully worked Vax
- Pascal\x{Pascal}
- generic set package implemented using FunnelWeb parameterized macros.
- The package was written by Barry Dwyer\xn{Barry}{Dwyer}
- of the Computer Science Department
- of the University of Adelaide\xx{University}{Adelaide}
- in 1987 and was emailed to me on
- X11~November 1987. The generic package provides a set
- abstraction\xx{set}{abstraction} implemented
- using linked lists. Note the clever use of the instantiation parameters in
- type, function, and procedure names.
- X
- X\begin{verbatim}
- X@$@<Generic Set Module@>@(@2@)==@{@-
- X@! @1 is the base type, @2 is the set type.
- X[inherit ('@1'), environment ('@2')]
- X
- module @2;
- X
- type @2 = ^@2Record;
- X @2Record = record
- X Member: @1;
- X Next: @2;
- X end;
- X
- procedure Null@2 (var Result: @2);
- begin new (Result);
- Result^.Member := (- MaxInt)::@1;
- Result^.Next := nil end;
- X
- function IsNull@2 (S: @2): boolean;
- begin IsNull@2 := S^.Member::integer = - MaxInt end;
- X
- procedure ForEach@1 (S: @2; procedure DoIt (i: @1));
- var ThisS, NextS: @2;
- begin ThisS := S;
- while ThisS^.Member::integer <> - MaxInt do
- X begin NextS := ThisS^.Next;
- X DoIt (ThisS^.Member);
- X ThisS := NextS end;
- end;
- X
- function First@1 (S: @2): @1;
- begin First@1 := S^.Member end;
- X
- function Is@1InSet (i: @1; S: @2): boolean;
- X procedure TestEquals (j: @1);
- X begin if Equal@1 (i, j) then Is@1InSet := true; end;
- begin Is@1InSet := false; ForEach@1 (S, TestEquals); end;
- X
- function Includes@2 (S1, S2: @2): boolean;
- var Result: boolean;
- X procedure TestIfInS1 (i: @1);
- X begin if Result then if not Is@1InSet (i, S1) then Result := false; end;
- begin Result := true;
- XForEach@1 (S2, TestIfInS1);
- Includes@2 := Result end;
- X
- function Disjoint@2s (S1, S2: @2): boolean;
- var Result: boolean;
- X procedure TestIfInS1 (i: @1);
- X begin if Result then if Is@1InSet (i, S1) then Result := false; end;
- begin Result := true;
- XForEach@1 (S2, TestIfInS1);
- Disjoint@2s := Result end;
- X
- function Equal@2 (S1, S2: @2): boolean;
- begin
- XEqual@2 := Includes@2 (S1, S2) and Includes@2 (S2, S1);
- end;
- X
- procedure Insert@1 (i: @1; var S: @2);
- var This, Pred, Succ: @2;
- begin
- if not Is@1InSet (i, S) then
- X begin
- X Pred := nil; Succ := S;
- X while Succ^.Member::integer > i::integer do begin
- X Pred := Succ; Succ := Succ^.Next end;
- X if Succ^.Member::integer < i::integer then begin
- X new (This); This^.Next := Succ; This^.Member := i;
- X if Pred <> nil then Pred^.Next := This else S := This;
- X end;
- X end;
- end;
- X
- procedure Insert@1s (S1: @2; var S2: @2);
- var This, Pred, Succ: @2;
- X procedure Add@1 (i: @1);
- X begin Insert@1 (i, S2) end;
- begin
- XForEach@1 (S1, Add@1);
- end;
- X
- procedure Remove@1 (i: @1; var S: @2);
- var Pred, This: @2;
- begin
- Pred := nil; This := S;
- while not Equal@1 (This^.Member, i) do begin
- X Pred := This; This := This^.Next end;
- if Pred <> nil then Pred^.Next := This^.Next else S := This^.Next;
- Dispose (This);
- end;
- X
- procedure Dispose@2 (var S: @2);
- var Old: @2;
- begin
- while S <> nil do begin Old := S; S := S^.Next; Dispose (Old) end;
- end;
- X
- end.
- X@}
- X
- X@O@<NaryTreeSet.pas@>==@{@-
- X @<Generic Set Module@>@(@"NaryTree@"@,@"NaryTreeSet@"@)@}
- X@O@<NaryTreeSetSet.pas@>==@{@-
- X @<Generic Set Module@>@(@"NaryTreeSet@"@,@"NaryTreeSetSet@"@)@}
- X\end{verbatim}
- X
- A great advantage of the approach reflected in the above example is that
- it allows the programmer to construct a generic object in a language that
- does not supply generics, \i{with complete typesafety.}\xx{typesafe}{generics}
- This contrasts to the
- approach that might be used in a language such as C where the programmer
- might choose to construct a \dq{generic} package by parameterizing a
- package with pointers to \p{void}. The resulting package is
- powerful but extremely untypesafe. Such a generic list package is used in the
- code of FunnelWeb itself and caused no end of problems, as the compiler had
- no way of telling if pointers to the correctly typed object were being
- handed to the correct list-object/function combination.
- X
- The major disadvantage of the text generic approach is that it causes the
- code of the generic object to be duplicated once for each instantiation.
- Depending on the number and size of the instantiations, this may or may not
- be acceptable.
- X
- Where the duplication of code is unacceptable, a hybrid approach may be
- taken. As in the C~example, the programmer could write
- a single generic package
- using pointers to \p{void} or some other untypesafe mechanism.
- Then the programmer
- creates a FunnelWeb generic package whose functions do nothing
- more than call the functions of the untypesafe package, and whose types do
- nothing more than contain the types of the untypesafe package. This solution
- involves the use of untypesafe programming, but this is a one-off
- and if done carefully and correctly, the result can be
- a typesafe generic package involving minimal code duplication.
- X
- X\section{Summary}
- X
- This chapter has described some of the finer aspects of the use of FunnelWeb.
- Throughout, the power and danger of FunnelWeb as a general text-rearranging
- preprocessor has been emphasised. FunnelWeb can be used both to make programs
- more readable or more obscure. It is up to the programmer to ensure that
- XFunnelWeb is used properly.
- X
- X%==============================================================================%
- X% End of Ch2.tex %
- X%==============================================================================%
- END_OF_FILE
- if test 66821 -ne `wc -c <'userman/u_ch2.tex'`; then
- echo shar: \"'userman/u_ch2.tex'\" unpacked with wrong size!
- fi
- # end of 'userman/u_ch2.tex'
- fi
- echo shar: End of archive 16 \(of 20\).
- cp /dev/null ark16isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 20 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-