From 2f4268e5e02216be53cd85816362191373512463 Mon Sep 17 00:00:00 2001 From: "Jeffrey H. Kingston" Date: Tue, 14 Sep 2010 20:36:01 +0000 Subject: Lout 3.20. git-svn-id: http://svn.savannah.nongnu.org/svn/lout/trunk@9 9365b830-b601-4143-9ba8-b4a8e2c3339c --- doc/user/README | 2 +- doc/user/all | 7 +- doc/user/cpp | 86 - doc/user/cpp_chan | 91 - doc/user/cpp_comm | 27 - doc/user/cpp_embe | 82 - doc/user/cpp_erro | 39 - doc/user/cpp_lone | 37 - doc/user/cpp_opti | 105 -- doc/user/cpp_pipe | 57 - doc/user/cpp_prog | 35 - doc/user/cpp_tabs | 66 - doc/user/preface | 2 +- doc/user/prg | 103 ++ doc/user/prg_chan | 108 ++ doc/user/prg_comm | 27 + doc/user/prg_embe | 81 + doc/user/prg_erro | 39 + doc/user/prg_lone | 42 + doc/user/prg_opti | 101 ++ doc/user/prg_perl | 108 ++ doc/user/prg_pipe | 57 + doc/user/prg_prog | 35 + doc/user/prg_tabs | 66 + doc/user/user.ps | 5202 +++++++++++++++++++++++++++++++++++++++++++++++++++++ doc/user/vcpp | 1 - doc/user/vprg | 1 + 27 files changed, 5976 insertions(+), 631 deletions(-) delete mode 100644 doc/user/cpp delete mode 100644 doc/user/cpp_chan delete mode 100644 doc/user/cpp_comm delete mode 100644 doc/user/cpp_embe delete mode 100644 doc/user/cpp_erro delete mode 100644 doc/user/cpp_lone delete mode 100644 doc/user/cpp_opti delete mode 100644 doc/user/cpp_pipe delete mode 100644 doc/user/cpp_prog delete mode 100644 doc/user/cpp_tabs create mode 100644 doc/user/prg create mode 100644 doc/user/prg_chan create mode 100644 doc/user/prg_comm create mode 100644 doc/user/prg_embe create mode 100644 doc/user/prg_erro create mode 100644 doc/user/prg_lone create mode 100644 doc/user/prg_opti create mode 100644 doc/user/prg_perl create mode 100644 doc/user/prg_pipe create mode 100644 doc/user/prg_prog create mode 100644 doc/user/prg_tabs create mode 100644 doc/user/user.ps delete mode 100644 doc/user/vcpp create mode 100644 doc/user/vprg (limited to 'doc/user') diff --git a/doc/user/README b/doc/user/README index 0fc5704..0cf3731 100644 --- a/doc/user/README +++ b/doc/user/README @@ -34,4 +34,4 @@ A copy of the final PostScript output file (A4 paper size) is stored at "ftp://ftp.cs.su.oz.au/jeff/lout/lout-3.19.user.ps.gz". Jeffrey H. Kingston -9 March 2000 +8 April 2000 diff --git a/doc/user/all b/doc/user/all index a4bb049..64eaf96 100644 --- a/doc/user/all +++ b/doc/user/all @@ -7,6 +7,7 @@ @SysInclude { diag } @SysInclude { cprint } @SysInclude { eiffel } +@SysInclude { perl } @SysInclude { book } # @Include { letterbook } # for testing Letter size formatting @@ -20,8 +21,8 @@ Lout Document Formatting System } @Author { Jeffrey H. Kingston } - @Edition { Version 3.19 -March, 2000 } + @Edition { Version 3.20 +April, 2000 } @Publisher { Copyright @CopyRight 1991, 2000 Jeffrey H. Kingston, Basser Department of Computer Science, @@ -42,7 +43,7 @@ The University of Sydney 2006, Australia. ISBN 0 86758 951 5. @Include { bgr } @Include { dia } @Include { gra } -@Include { cpp } +@Include { prg } @Include { pascal } @Include { ap_qck } @Include { ap_byp } diff --git a/doc/user/cpp b/doc/user/cpp deleted file mode 100644 index 0e7748a..0000000 --- a/doc/user/cpp +++ /dev/null @@ -1,86 +0,0 @@ -@Chapter - @Title { Computer Programs } - @Tag { cprint } -@Begin -@LP -This chapter describes how to typeset computer program text using Lout -in conjunction with the @Code prg2lout -prg2lout. @Index { @Code prg2lout filter program } -@FootNote { -Prior to Version 3.18 of Lout, this chapter described how to typeset -programs written in the C programming language using the -@Code c2lout filter, and Eiffel programs using the @Code eif2lout -filter. These have now been withdrawn and replaced by {@Code prg2lout}, -which handles multiple languages. Ordinary Lout documents require no -modifications as a result of this change. -} -filter program, which is always installed wherever Lout is. -@PP -It is possible to simply print out one or more program files independently -of any document. Alternatively, the program text may be printed as part of -a larger Lout document. Either way, Lout does not lay out the programs in -the sense of choosing line breaks and indenting; it uses whatever line -breaks and indenting you give to the program. What Lout does do is cope -with characters in the program text that it would ordinarily either reject -or interpret in some way (braces and so on), ensuring that you can include -program texts with absolutely no modifications; plus, if you wish, Lout -will print keywords in bold, identifiers in italics, etc. -@PP -At the time of writing, the available programming languages are: -eiffel. @Index { Eiffel program printing } -c. @Index { C and C++ program printing } -blue. @Index { Blue program printing } -@CD @Tbl - mv { 0.5vx } - af { Italic } - arb { yes } - aformat { @Cell A | @Cell B | @Cell C | @Cell D | @Cell E } - bformat { @Cell A | @Cell @Code B | @Cell @Code C | @Cell @Code D | @Cell E } -{ -@Rowa - A { Language name } - B { Setup file name } - C { Lout symbol } - D { Default style } - E { ` ' escapes } -@Rowb - A { C, C++ } - B { cprint } - C { "@CP" } - D { fixed } - E { No } -@Rowb - A { Eiffel } - B { eiffel } - C { "@Eiffel" } - D { varying } - E { Yes } -@Rowb - A { Blue } - B { blue } - C { "@Blue" } - D { varying } - E { Yes } -} -C and C++ are handled together since, for formatting purposes, they -differ only in that C++ has some additional keywords plus an extra -way to make comments. Whenever we mention C from now on, we mean -both C and C++. The second to fifth columns of this table will be -explained at various points later in this chapter. -@PP -The list of languages is likely to expand, because the @Code "prg2lout" -program has been designed to make it easy to add new languages. Consult -the instructions at the top of the source file of that program if you -want to try it yourself. -@BeginSections -@Include { cpp_lone } -@Include { cpp_embe } -@Include { cpp_opti } -@Include { cpp_chan } -@Include { cpp_tabs } -@Include { cpp_comm } -@Include { cpp_prog } -@Include { cpp_pipe } -@Include { cpp_erro } -@EndSections -@End @Chapter diff --git a/doc/user/cpp_chan b/doc/user/cpp_chan deleted file mode 100644 index bee0493..0000000 --- a/doc/user/cpp_chan +++ /dev/null @@ -1,91 +0,0 @@ -@Section - @Title { Changing the appearance of all programs simultaneously } - @Tag { cpsetup } -@Begin -@PP -We have just seen that the {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols -have many options for changing the appearance of the program text. However, -most people would not want to have a different style for every program text -in their document; they want to define the style once at the start, and have -all their program texts come out in that style without laboriously setting -options on every symbol. You do this by copying the setup file and -changing it. -@PP -For general information about how to make your own setup file, consult -Section {@NumberOf setup}. The options that determine the default -values are in the @Code "@Use" clause which occupies most of the setup -file. Here is the @Code "@Use" clause from {@Code cprint}: -cprint. @Index @Code "@CPSetup" -@ID @Code @Tbl - mv { 0.5vx } - aformat { @Cell A | @Cell B | @Cell C } - bformat { @Cell { " #" A } | @Cell { "{" B } | @Cell "}" } -{ -@Rowa A { "@Use { @CPSetup" } -@Rowb A { "pipe" } B { } -@Rowb A { "style" } B { fixed } - -@Rowa -@Rowb A { "fixedfont" } B { Courier } -@Rowb A { "fixedstrings" } B { Base } -@Rowb A { "fixedidentifiers" } B { Base } -@Rowb A { "fixedcomments" } B { Base } -@Rowb A { "fixedkeywords" } B { Base } -@Rowb A { "fixednumbers" } B { Base } -@Rowb A { "fixedoperators" } B { Base } -@Rowb A { "fixedsize" } B { -1.0p } -@Rowb A { "fixedline" } B { 1.0vx } -@Rowb A { "fixedtabin" } B { 8 } -@Rowb A { "fixedtabout" } B { 8s } - -@Rowa -@Rowb A { "varyingfont" } B { } -@Rowb A { "varyingstrings" } B { Slope } -@Rowb A { "varyingidentifiers" } B { Slope } -@Rowb A { "varyingcomments" } B { Base } -@Rowb A { "varyingkeywords" } B { Bold } -@Rowb A { "varyingnumbers" } B { Base } -@Rowb A { "varyingoperators" } B { Base } -@Rowb A { "varyingsize" } B { 1.0f } -@Rowb A { "varyingline" } B { 1.0vx } -@Rowb A { "varyingtabin" } B { 8 } -@Rowb A { "varyingtabout" } B { 3f } - -@Rowa -@Rowb A { "symbolfont" } B { } -@Rowb A { "symbolstrings" } B { Slope } -@Rowb A { "symbolidentifiers" } B { Slope } -@Rowb A { "symbolcomments" } B { Base } -@Rowb A { "symbolkeywords" } B { Bold } -@Rowb A { "symbolnumbers" } B { Base } -@Rowb A { "symboloperators" } B { Base } -@Rowb A { "symbolsize" } B { 1.0f } -@Rowb A { "symbolline" } B { 1.0vx } -@Rowb A { "symboltabin" } B { 8 } -@Rowb A { "symboltabout" } B { 3f } - -@Rowa A { "}" } -} -This shows the default font families, font faces, font sizes, line -spacings, and tab settings in force for the three styles, and also that -the default style is {@Code "fixed"}. Notice that the font family name -for @Code "fixed" style is {@Code "Courier"}, but for the other styles is -empty. This causes the @Code "fixed" style to always switch to Courier, -and the other styles to use the same font family as in the surrounding -document. The @Code pipe option will be explained in Section {@NumberOf pipes}. -@PP -To change a default value, delete the preceding @Code "#" and change the -part between braces. For example, suppose you are happy with @Code "fixed" -except that you want bold keywords. Then one line needs to be changed, to -@ID @Code "fixedkeywords { Bold }" -Or suppose you like @Code "varying" as it stands, but would like it to be -the default style rather than {@Code "fixed"}. Again, only one line needs -to be changed, to {@Code "style { varying }"}. -@PP -The setup files for the other languages are identical to this one, except -that the symbol after @Code "@Use" is different, and some of the -default values may be different. Changing an option affects only the -language of that setup file; if you have multiple languages you can -have multiple setup files and change their options quite independently -of each other. -@End @Section diff --git a/doc/user/cpp_comm b/doc/user/cpp_comm deleted file mode 100644 index 96ac110..0000000 --- a/doc/user/cpp_comm +++ /dev/null @@ -1,27 +0,0 @@ -@Section - @Title { Embedding Lout commands within program comments } - @Tag { cpcomm } -@Begin -@PP -It is possible to embed Lout text inside program comments. How this -is done could in principle vary from language to language, but in -every language supported so far it is done by starting off the comment -with an @Code "@" character. If the language has several ways to get -a comment, this will work every way. The entire comment after the @Code "@" -character should then be Lout text. For example, to force Lout to start -a new page at some point within a C program, place -@ID @Code "/*@ @NP */" -at that point. (In this case you can also simply include a formfeed -formfeed. @Index { formfeed in program texts } -character, control-L, without any comment; whatever the language, a formfeed -in program text is taken to be a request to start a new page.) Or, to -make a heading in an Eiffel program, do this: -@ID @Code "--@ @Display @Heading { treeprint() }" -(Eiffel comments begin with @Code "--" and end at the end of the -line.) Other possible uses for this feature include index entries and -margin notes. Incredible as it may seem, you can even write -@ID @Code "/*@ @CD @Heading { Function @CP { treeprint() } } */" -with a @Code "@CP" symbol and some C code inside the Lout code -inside the C code. You probably can't go further, however, at least -not in C, since that would require a C comment inside a C comment. -@End @Section diff --git a/doc/user/cpp_embe b/doc/user/cpp_embe deleted file mode 100644 index 0cefc84..0000000 --- a/doc/user/cpp_embe +++ /dev/null @@ -1,82 +0,0 @@ -@Section - @Title { Typesetting computer programs as part of a larger document } - @Tag { embedded } -@Begin -@PP -When the program texts are to be part of a larger Lout document, -the procedure is somewhat different. You need to include the setup file -appropriate to your language, like this: -@ID @OneRow @Code { -"@SysInclude { cprint }" -"@SysInclude { doc }" -"@Doc @Text @Begin" -"..." -"@End @Text" -} -The @Code cprint setup file includes everything needed to set up for C -program formatting; for the other languages, consult the second column -of the table at the start of this chapter. -@PP -The program texts within the Lout document are enclosed in braces -preceded by the Lout symbol from the third column of the table, like -this for the C language: -@ID @OneRow @Code { -"@IndentedDisplay @CP {" -"#include " -"" -"treeprint(p) /* print tree p recursively */" -"struct tnode *p;" -"{" -" if (p != NULL) {" -" treeprint(p->left);" -" printf(\"%4d %s\\n\", p->count, p->word);" -" treeprint(p->right);" -" }" -"}" -"}" -} -Although computer programs violate the rules of legal Lout input in many ways, -these rules are suspended by the {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols, -allowing the program text to be incorporated with absolutely no -modifications. The result is -@ID @OneRow @CP { -#include - -treeprint(p) /* print tree p recursively */ -struct tnode *p; -{ - if (p != NULL) { - treeprint(p->left); - printf("%4d %s\n", p->count, p->word); - treeprint(p->right); - } -} -} -We have chosen to use the @Code "@IndentedDisplay" symbol from Section -{@NumberOf displays} to obtain an indented display, but in fact -{@Code "@CP"}, {@Code "@Eiffel"} and the rest may appear anywhere at -all: the result is an object in the usual way, which may go -anywhere. When including a program text within a paragraph, use -@Code "@OneCol @CP { ... }" (or @Code "@OneCol @Eiffel { ... }" etc. for -other languages) to prevent it being broken across two lines, if desired. -@PP -In cases where the program text has unbalanced braces, it is necessary to -use the alternative form @Code "@CP @Begin ... @End @CP" (or the -equivalent for other languages), so that Lout does not confuse program -braces with Lout braces. In that case the program text must not -contain {@Code "@End"}; and in either case the program text must not -include @Code "@Include" or @Code "@SysInclude" unless you are really -including a file at that point (which is allowed, and follows the -rules given for @Code "@Verbatim" in Section {@NumberOf verbatim}). -@PP -If your Lout document contains program texts in several languages, -simply add one @Code "@SysInclude" line for each of them and proceed -as before. If your programming language is not currently supported, -a viable alternative is -@ID @Code "@F @Verbatim { ... }" -These symbols cause the text between braces to be set verbatim in -a fixed-width font, as explained elsewhere in this guide. This fallback -method will not handle tab and formfeed characters very well. Again, -use @Code "@Begin" and @Code "@End @Verbatim" instead of braces if -your program text contains unbalanced braces. -@End @Section diff --git a/doc/user/cpp_erro b/doc/user/cpp_erro deleted file mode 100644 index ff89591..0000000 --- a/doc/user/cpp_erro +++ /dev/null @@ -1,39 +0,0 @@ -@Section - @Title { Error messages } - @Tag { cpp_erro } -@Begin -@PP -In order to understand the error messages produced by program -printing, it is necessary to understand that Lout's first step when -given a program text is to pass it to the separate {@Code prg2lout} -program for analysis. This separate program is the source of most -of the error messages associated with program printing. -@PP -The {@Code prg2lout} program is quite happy to format a fragment of a -computer program: there is no need to supply a complete routine, or -a complete statement, or any such thing. However, it will complain if -you supply only a fragment of one lexical unit, such as a comment or -string without its terminating delimiter. It will also complain if -there is a character that cannot be classified as part of an identifier, -number, etc. according to the rules of the language as they have been -given to @Code prg2lout by the implementer. Irrespective of the -language rules, @Code prg2lout always interprets spaces, tabs, newlines, -and formfeed characters in the usual way. -@PP -If an error message is generated by {@Code prg2lout}, it will contain -a line and column number counting from the start of the program text -involved. Lout will precede this error message with a file name, -line number, and column number pointing to the Lout symbol -({@Code "@CP"}, {@Code "@Eiffel"} etc.) whose program text caused the -error message, like this: -@ID @Code @Verbatim { -lout file "cpp_tabs" (from "cpp" line 80, from "all" line 45): - 56,23: prg2lout 2,1: program text ended within comment -} -This is an actual message produced when formatting this chapter. The -program text in question has only one line, containing an incomplete comment, -so when @Code "prg2lout" tried to start the second line and found nothing, -it complained as shown. In general, then, you have to add -{@Code "prg2lout"}'s line number to Lout's line number, and use some -initiative, to find the precise point of the problem. -@End @Section diff --git a/doc/user/cpp_lone b/doc/user/cpp_lone deleted file mode 100644 index a377d86..0000000 --- a/doc/user/cpp_lone +++ /dev/null @@ -1,37 +0,0 @@ -@Section - @Title { Typesetting computer programs independently of any document } - @Tag { alone } -@Begin -@PP -Printing of program files independently of any document is accomplished by -the following Unix pipeline: -@ID @Code "prg2lout -l language options files | lout -s > out.ps" -where @Code language stands for any one of the programming language -names in the first column of the table above. As usual with Lout, the -output will be a PostScript file. Each input file will begin on a new -page of the output, starting with its name in bold type. The options -provide control over the final appearance, as follows: -@WideTaggedList -@TI { {@Code-p}{@I style} } { -Select a printing style. Your choices are {@Code -pfixed}, -{@Code -pvarying}, and {@Code -psymbol}, with the default value -varying with the language as given in the fourth column of the -table above. Consult Section {@NumberOf embedded} for examples -of these styles. -} -@TI { @Code -n } { -Do not print file names. -} -@TI { {@Code -f}{@I font} } { -Select a Lout font family. The default is @Code "-fCourier" for -{@Code -pfixed}, and @Code "-fTimes" for @Code -pvarying and {@Code -psymbol}. -} -@TI { {@Code -v}{@I vsize} } { -Select an inter-line spacing size in Lout units. The default is -@Code -v1.1fx meaning 1.1 times the font size measured from baseline -to baseline. -} -@EndList -There are also {@Code -t} and {@Code -T} options for dealing with tab -characters (Section {@NumberOf tabs}). -@End @Section diff --git a/doc/user/cpp_opti b/doc/user/cpp_opti deleted file mode 100644 index 538bda2..0000000 --- a/doc/user/cpp_opti +++ /dev/null @@ -1,105 +0,0 @@ -@Section - @Title { Changing the appearance of a program } - @Tag { cpp_opti } -@Begin -@PP -The {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols have a number of -options for changing the appearance of the printed program. These -options are the same for all symbols, although their default values -may vary. The @Code "style" option changes the printing style; its -value may be {@Code "fixed"} (fixed-width font), {@Code "varying"} -(varying-width font), or {@Code "symbol"} (varying-width font with -mathematical symbols used for some operators). Its default value -depends on the language, and may be found in the fourth column of -the table at the start of this chapter. The example in the previous -section was in @Code fixed style; we can switch styles like this: -@ID @OneRow @Code { -"@CP" -" style { varying }" -"{" -"#include " -"" -"treeprint(p) /* print tree p recursively */" -"struct tnode *p;" -"{" -" if (p != NULL) {" -" treeprint(p->left);" -" printf(\"%4d %s\\n\", p->count, p->word);" -" treeprint(p->right);" -" }" -"}" -"}" -} -The result in this case will be -@ID @OneRow @CP style { varying } -{ -#include - -treeprint(p) /* print tree p recursively */ -struct tnode *p; -{ - if (p != NULL) { - treeprint(p->left); - printf("%4d %s\n", p->count, p->word); - treeprint(p->right); - } -} -} -If we use @Code "style { symbol }" we get this: -@ID @OneRow @CP style { symbol } -{ -#include - -treeprint(p) /* print tree p recursively */ -struct tnode *p; -{ - if (p != NULL) { - treeprint(p->left); - printf("%4d %s\n", p->count, p->word); - treeprint(p->right); - } -} -} -with mathematical symbols replacing some of the operators. -@PP -The {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols have additional options -which allow a finer control over the style. Here they all are, with their -default values: -@ID @OneRow @Code { -"@CP [ or @Eiffel, @Blue, etc. ]" -" style { fixed }" -" font { Courier }" -" strings { Base }" -" identifiers { Base }" -" comments { Base }" -" keywords { Base }" -" numbers { Base }" -" operators { Base }" -" size { -1.0p }" -" line { 1.0vx }" -" tabin { 8 }" -" tabout { 8s }" -"{" -" ..." -"}" -} -We are already familiar with {@Code "style"}. After that comes -{@Code "font"}, which determines the font family to use, followed -by six options giving the particular faces within that family in which to -print strings, identifiers, comments, keywords, numbers, and -operators. {@Code "Base"} means the basic face; other commonly available -choices are {@Code "Slope"} and {@Code "Bold"}. These options may all be -set to different faces if desired. The default values shown are correct -for @Code "style { fixed }" only; the other styles have other defaults -(Section {@NumberOf cpsetup}). -@PP -The @Code "size" option is the font size to use, and @Code "line" is the -inter-line spacing. The default values specify that @Code "size" is -to be one point smaller than in the surrounding document; this was done -to compensate for Courier's relatively large appearance compared -to other fonts of the same nominal size. Again, these defaults are -different for different values of {@Code "style"}. -@PP -The @Code "tabin" and @Code "tabout" options are the subject of -Section {@NumberOf tabs}. -@End @Section diff --git a/doc/user/cpp_pipe b/doc/user/cpp_pipe deleted file mode 100644 index afbb87e..0000000 --- a/doc/user/cpp_pipe +++ /dev/null @@ -1,57 +0,0 @@ -@Section - @Title { Reading and selecting program text from separate files } - @Tag { pipes } -@Begin -@PP -We have said that program text within @Code "@CP { ... }" and the other -symbols is passed directly to @Code prg2lout for analysis. However, -there is an exception. The program text may contain an -@Code "@Include" or @Code "@SysInclude" command, which, as for the -@Code "@Verbatim" symbol (Section {@NumberOf verbatim}), causes Lout -to take the program text from a file: -@ID @Code { -"@Eiffel" -"{" -" @Include { \"/usr/staff/jeff/Eiffel/hash.e\" }" -"}" -} -The included file is not examined for balanced braces or @Code "@End" or -{@Code "@Include"}; it is treated entirely verbatim and passed straight -on to {@Code prg2lout}. There may be several @Code "@Include" commands, -and any amount of program text as well, within @Code "@CP { ... }" and -the rest. -@PP -When including files in this way it often happens that only part of an -actual program file is wanted for display. Rather than placing the -wanted part in a separate file, which is error-prone and tedious when -the program is changing, Unix users can use the @Code "pipe" option -to pipe the entire file through an arbitrary sequence of Unix commands, -which may be used to make the wanted selection before the program text -is passed to {@Code prg2lout}. -@PP -For example, suppose that all your Eiffel routines begin with the -routine name one tab stop from the left margin and end at the first -following @Eiffel { end } indented two tab stops. Then -@ID @Code { -"@Eiffel" -" pipe { \"sed -n /^.insert/,/^..end/p\" }" -"{" -" @Include { \"/usr/staff/jeff/Eiffel/hash.e\" }" -"}" -} -will select just the @Eiffel { insert } routine from the @Code { hash.e } -file. Assuming that your program text has been laid out in a -disciplined manner, every line of the selection will begin with a -tab character that is not wanted in this display, so an even better -pipe is -@ID @Code { -"@Eiffel" -" pipe { \"sed -n /^.insert/,/^..end/p | cut -c2-\" }" -"{" -" @Include { \"/usr/staff/jeff/Eiffel/hash.e\" }" -"}" -} -since it cuts away the unwanted tab characters. Unfortunately, we -can't show the result of this on an actual example, since that would -prevent this manual from being formatted on a non-Unix system. -@End @Section diff --git a/doc/user/cpp_prog b/doc/user/cpp_prog deleted file mode 100644 index a049e3d..0000000 --- a/doc/user/cpp_prog +++ /dev/null @@ -1,35 +0,0 @@ -@Section - @Title { Embedding program text within program comments } - @Tag { cpp_prog } -@Begin -@PP -The standard reference for the Eiffel language @Cite { $meyer1992eiffel } -specifies that identifiers within comments may or should be enclosed -in ` and ' so that they may be noticed and printed in an italic -font: -@ID lines @Break @F @Verbatim { -@ID @Eiffel { -deposit(amount: REAL) is - -- deposit `amount' dollars -} -} -produces -@ID @Eiffel { -deposit(amount: REAL) is - -- deposit `amount' dollars -} -This has been generalized in Lout: arbitrary text within an -Eiffel comment between ` and ' will be treated as Eiffel text and -printed accordingly. Some other languages may also offer this -feature: see the fifth column of the table at the start of this -chapter. In principle the precise means of getting it could vary -from language to language, but the languages available at the moment -either do not have it at all, or else they use ` and ' like Eiffel. -@PP -On the subject of Eiffel, the Eiffel reference @Cite { $meyer1992eiffel } -has some quite detailed style guidelines, and these have been closely -followed in the implementation of the @Code "@Eiffel" symbol. In -particular, @Code "@Eiffel" prints dots larger than usual when they -denote feature calls, as the example @OneCol @Eiffel { account.deposit(20) } -shows. -@End @Section diff --git a/doc/user/cpp_tabs b/doc/user/cpp_tabs deleted file mode 100644 index 3a04bfa..0000000 --- a/doc/user/cpp_tabs +++ /dev/null @@ -1,66 +0,0 @@ -@Section - @Title { Dealing with tab characters in programs } - @Tag { tabs } -@Begin -@PP -Tab characters provide a convenient way to indent and align parts of -tab.c @Index { tab characters in programs } -computer programs. With care, this alignment can be preserved in the final -print even with varying-width fonts. -@PP -The distance between two tab stops in the program text is by default taken -to be 8 characters, which is standard for Unix. This can be changed with -the @Code "tabin" option. For example, -@ID @Code "@CP tabin { 4 }" -informs Lout that tab stops occur every 4 characters in the program -text. All the symbols ({@Code "@CP"}, {@Code "@Eiffel"}, etc.) and -their setup files have this option and the next; but to save repetition -we will stick with C for the rest of this section. -@PP -The distance between two tab stops on the printed page is quite a different -thing, and it is determined by the value of the @Code "tabout" option, which -must be a Lout length. For example, -@ID @Code "@CP tabout { 0.5i }" -requests that tab stops be placed at half-inch intervals. In other -words, a distance of one tab stop in the program text will be equivalent to a -distance of half an inch on the printed page. For example, -@ID @Code "@CP style { varying } tabout { 3f }" -might produce the following, where tab characters in the program text -have been used for indenting and also to align the comments: -@ID @OneRow @CP style { varying } tabout { 3f } { -struct tnode { /* the basic node */ - char *word; /* points to the text */ - int count; /* number of occurrences */ - struct tnode *left; /* left child */ - struct tnode *right; /* right child */ -}; -} -The value {@Code "3f"} means three times the current font size, and -it is the default value of @Code "tabout" for the @Code { varying } -and @Code { symbol } styles (Section {@NumberOf cpsetup}). In a -12 point font this is 36 points, or half an inch. -@PP -If @Code "tabout" is too small, there is a danger that the -alignment might fail. For example, -@ID @Code "@CP style { varying } tabout { 0.2i }" -produces -@ID @OneRow @CP style { varying } tabout { 0.2i } { -struct tnode { /* the basic node */ - char *word; /* points to the text */ - int count; /* number of occurrences */ - struct tnode *left; /* left child */ - struct tnode *right; /* right child */ -}; -} -given the same C text as the previous example. The problem here is that -we are asking for @CP { /* } to appear four tab stops or 0.8 inches -from the left edge, and yet the material to its left on the line is -wider than this. This causes @CP { /* } to be shifted further to the -right than expected, and the alignment is lost. The only solution is -to increase {@Code "tabout"}. -@PP -When typesetting computer program texts independently of any document, -there are @Code "-t" and @Code "-T" options to the @Code "prg2lout" -program equivalent to @Code "tabin" and @Code "tabout" respectively. For -example, @Code "-T0.5i" produces a half-inch tab width. -@End @Section diff --git a/doc/user/preface b/doc/user/preface index 3634a89..2f258eb 100644 --- a/doc/user/preface +++ b/doc/user/preface @@ -18,7 +18,7 @@ gnu. @Index { GNU Public License } primary source is directory @ID @Code "ftp://ftp.cs.usyd.edu.au/jeff/lout" in which may be found a gzipped tar file containing the main distribution -(currently {@Code "lout-3.19.tar.gz"}), and various other things including +(currently {@Code "lout-3.20.tar.gz"}), and various other things including a PostScript version of this guide. The distribution contains source code, libraries, documentation, license, and installation instructions. @PP diff --git a/doc/user/prg b/doc/user/prg new file mode 100644 index 0000000..ec473aa --- /dev/null +++ b/doc/user/prg @@ -0,0 +1,103 @@ +@Chapter + @Title { Computer Programs } + @Tag { cprint } +@Begin +@LP +This chapter describes how to typeset computer program text using Lout +in conjunction with the @Code prg2lout +prg2lout. @Index { @Code prg2lout filter program } +@FootNote { +Prior to Version 3.18 of Lout, this chapter described how to typeset +programs written in the C programming language using the +@Code c2lout filter, and Eiffel programs using the @Code eif2lout +filter. These have now been withdrawn and replaced by {@Code prg2lout}, +which handles multiple languages. Ordinary Lout documents require no +modifications as a result of this change. +} +filter program, which is always installed wherever Lout is. +@PP +It is possible to simply print out one or more program files independently +of any document. Alternatively, the program text may be printed as part of +a larger Lout document. Either way, Lout does not lay out the programs in +the sense of choosing line breaks and indenting; it uses whatever line +breaks and indenting you give to the program. What Lout does do is cope +with characters in the program text that it would ordinarily either reject +or interpret in some way (braces and so on), ensuring that you can include +program texts with absolutely no modifications; plus, if you wish, Lout +will print keywords in bold, identifiers in italics, etc. +@PP +At the time of writing, the available programming languages are: +eiffel. @Index { Eiffel program printing } +c. @Index { C and C++ program printing } +blue. @Index { Blue program printing } +perl. @Index { Perl program printing } +pod. @Index { Pod (for Perl) printing } +@CD @Tbl + mv { 0.5vx } + af { Italic } + arb { yes } + aformat { @Cell A | @Cell B | @Cell C | @Cell D | @Cell E } + bformat { @Cell A | @Cell @Code B | @Cell @Code C | @Cell @Code D | @Cell E } +{ +@Rowa + A { Language name } + B { Setup file name } + C { Lout symbol } + D { Default style } + E { ` ' escapes } +@Rowb + A { C, C++ } + B { cprint } + C { "@CP" } + D { fixed } + E { No } +@Rowb + A { Eiffel } + B { eiffel } + C { "@Eiffel" } + D { varying } + E { Yes } +@Rowb + A { Blue } + B { blue } + C { "@Blue" } + D { varying } + E { Yes } +@Rowb + A { Perl } + B { perl } + C { "@Perl" } + D { fixed } + E { No } +@Rowb + A { Pod } + B { pod } + C { "@Pod" } + D { varying } + E { No } +} +C and C++ are handled together since, for formatting purposes, they +differ only in that C++ has some additional keywords plus an extra +way to make comments. Whenever we mention C from now on, we mean +both C and C++. See Section {@NumberOf prg_perl} for more on Perl +and its handmaiden Pod. The second to fifth columns of this table will be +explained at various points later in this chapter. +@PP +The list of languages is likely to expand, because the @Code "prg2lout" +program has been designed to make it relatively easy to add new languages +(you don't have to write executable code, just declare a lot of records +describing your language). Consult the instructions at the top of the +source file of that program ({@I prg2lout.c}) if you want to try it yourself. +@BeginSections +@Include { prg_lone } +@Include { prg_embe } +@Include { prg_opti } +@Include { prg_chan } +@Include { prg_tabs } +@Include { prg_comm } +@Include { prg_prog } +@Include { prg_pipe } +@Include { prg_erro } +@Include { prg_perl } +@EndSections +@End @Chapter diff --git a/doc/user/prg_chan b/doc/user/prg_chan new file mode 100644 index 0000000..6273b7d --- /dev/null +++ b/doc/user/prg_chan @@ -0,0 +1,108 @@ +@Section + @Title { Changing the appearance of all programs simultaneously } + @Tag { cpsetup } +@Begin +@PP +We have just seen that the {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols +have many options for changing the appearance of the program text. However, +most people would not want to have a different style for every program text +in their document; they want to define the style once at the start, and have +all their program texts come out in that style without laboriously setting +options on every symbol. You do this by copying the setup file and +changing it. +@PP +For general information about how to make your own setup file, consult +Section {@NumberOf setup}. The options that determine the default +values are in the @Code "@Use" clause which occupies most of the setup +file. Here is part of the @Code "@Use" clause from {@Code cprint}: +cprint. @Index @Code "@CPSetup" +@ID @Code @Tbl + mv { 0.5vx } + aformat { @Cell A | @Cell B | @Cell C } + bformat { @Cell { " #" A } | @Cell { "{" B } | @Cell "}" } +{ +@Rowa A { "@Use { @CPSetup" } +@Rowb A { "pipe" } B { } +@Rowb A { "style" } B { fixed } + +@Rowa +@Rowb A { "fixedfont" } B { Courier } +@Rowb A { "fixedsize" } B { -1.0p } +@Rowb A { "fixedline" } B { 1.0vx } +@Rowb A { "fixedtabin" } B { 8 } +@Rowb A { "fixedtabout" } B { 8s } + +@Rowa +@Rowb A { "fixedidentifiers" } B { Base } +@Rowb A { "fixedkeywords" } B { Base } +@Rowb A { "fixedoperators" } B { Base } +@Rowb A { "fixednumbers" } B { Base } +@Rowb A { "fixedstrings" } B { Base } +@Rowb A { "fixedcomments" } B { Base } + +@Rowa +@Rowb A { "fixedidentifiersformat" } B { "@Body" } +@Rowb A { "fixedkeywordsformat" } B { "@Body" } +@Rowb A { "fixedoperatorsformat" } B { "@Body" } +@Rowb A { "fixednumbersformat" } B { "@Body" } +@Rowb A { "fixedstringsformat" } B { "@Body" } +@Rowb A { "fixedcommentsformat" } B { "@Body" } + +@Rowa +@Rowa A { "..." } + +@Rowa +@Rowa A { "}" } +} +The @Code pipe option will be explained in Section {@NumberOf pipes}. The +options whose name begins with @Code "fixed" apply only when +@Code style is {@Code fixed}; there are corresponding options, not +shown, which apply when @Code style is {@Code varying} and {@Code symbol}. +@PP +We can see in this extract that the default value of @Code style is +{@Code fixed}. We can also see the default font family, font face, font size, +line spacing, and tab settings when the style is {@Code "fixed"}. The +font family name for @Code "fixed" style is {@Code "Courier"}, but for the +other styles (not shown) it is empty. This causes the @Code "fixed" style +to always switch to Courier, and the other styles to use the same font +family as in the surrounding document. +@PP +The @Code fixedidentifiersformat option allows you to make a more +radical change to the format of identifiers than just the font. Within +this option, @Code "@Body" stands for the identifier being formatted, and +by applying Lout symbols to it, you apply them to every identifier. For +example, +@ID @Code "fixedidentifiersformat { red @Colour @Body }" +will cause identifiers to be printed red. +@FootNote { +@Code "@Colour" is not a Lout primitive like, say, {@Code "@Font"}; it is +defined when you write @Code "@SysInclude { doc }" or the equivalent for +the other document types. This is true of quite a few generally useful +symbols, including {@Code "@Box"} and {@Code "@I"}. If you want to use +these symbols here, you must include your setup file @I after +@Code "@SysInclude { doc }" or whatever, the reverse of the usual +arrangement, so that they are defined before Lout reads your setup +file. This reversal is carried out automatically when formatting +programs independently of any document, so you can use these symbols +in a setup file given by a @Code { -S } command line flag. +} If you do use exotic formats, remember that in some programming languages, +comments and even strings may occupy more than one line: {@Code "@Box"}, +for example, will give a logical but probably unwanted result when +formatting a multi-line string. +@PP +As always with setup files, to change a default value, delete the preceding +@Code "#" and change the part between braces. For example, suppose you are +happy with @Code "fixed" except that you want bold keywords. Then one line +needs to be changed, to +@ID @Code "fixedkeywords { Bold }" +Or suppose you like @Code "varying" as it stands, but would like it to be +the default style rather than {@Code "fixed"}. Again, only one line needs +to be changed, to {@Code "style { varying }"}. +@PP +The setup files for the other languages are identical to this one, except +that the symbol after @Code "@Use" is different, and some of the +default values may be different. Changing an option affects only the +language of that setup file; if you have multiple languages you can +have multiple setup files and change their options quite independently +of each other. +@End @Section diff --git a/doc/user/prg_comm b/doc/user/prg_comm new file mode 100644 index 0000000..a679f4f --- /dev/null +++ b/doc/user/prg_comm @@ -0,0 +1,27 @@ +@Section + @Title { Embedding Lout commands within program comments } + @Tag { cpcomm } +@Begin +@PP +It is possible to embed Lout text inside program comments. How this +is done could in principle vary from language to language, but in +every language supported so far it is done by starting off the comment +with an @Code "@" character. If the language has several ways to get +a comment, this will work every way. The entire comment after the @Code "@" +character should then be Lout text. For example, to force Lout to start +a new page at some point within a C program, place +@ID @Code "/*@ @NP */" +at that point. (In this case you can also simply include a formfeed +formfeed. @Index { formfeed in program texts } +character, control-L, without any comment; whatever the language, a formfeed +in program text is taken to be a request to start a new page.) Or, to +make a heading in an Eiffel program, do this: +@ID @Code "--@ @Display @Heading { treeprint }" +(Eiffel comments begin with @Code "--" and end at the end of the +line.) Other possible uses for this feature include index entries and +margin notes. Incredible as it may seem, you can even write +@ID @Code "/*@ @CD @Heading { Function @CP { treeprint() } } */" +with a @Code "@CP" symbol and some C code inside the Lout code +inside the C code. You probably can't go further, however, at least +not in C, since that would require a C comment inside a C comment. +@End @Section diff --git a/doc/user/prg_embe b/doc/user/prg_embe new file mode 100644 index 0000000..cfa84d4 --- /dev/null +++ b/doc/user/prg_embe @@ -0,0 +1,81 @@ +@Section + @Title { Typesetting computer programs as part of a larger document } + @Tag { embedded } +@Begin +@PP +When the program texts are to be part of a larger Lout document, +the procedure is somewhat different. You need to include the setup file +appropriate to your language, like this: +@ID @OneRow @Code { +"@SysInclude { cprint }" +"@SysInclude { doc }" +"@Doc @Text @Begin" +"..." +"@End @Text" +} +The @Code cprint setup file includes everything needed to set up for C +program formatting; for the other languages, consult the second column +of the table at the start of this chapter. +@PP +The program texts within the Lout document are enclosed in braces +preceded by the Lout symbol from the third column of the table, like +this for the C language: +@ID @OneRow @Code { +"@IndentedDisplay @CP {" +"#include " +"" +"treeprint(p) /* print tree p recursively */" +"struct tnode *p;" +"{" +" if (p != NULL) {" +" treeprint(p->left);" +" printf(\"%4d %s\\n\", p->count, p->word);" +" treeprint(p->right);" +" }" +"}" +"}" +} +Although computer programs violate the rules of legal Lout input in many ways, +these rules are suspended by the {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols, +allowing the program text to be incorporated with absolutely no +modifications. The result is +@ID @OneRow @CP { +#include + +treeprint(p) /* print tree p recursively */ +struct tnode *p; +{ + if (p != NULL) { + treeprint(p->left); + printf("%4d %s\n", p->count, p->word); + treeprint(p->right); + } +} +} +We have chosen to use the @Code "@IndentedDisplay" symbol from Section +{@NumberOf displays} to obtain an indented display, but in fact +{@Code "@CP"}, {@Code "@Eiffel"} and the rest may appear anywhere at +all: the result is an object in the usual way, which may go +anywhere. When including a program text within a paragraph, use +@Code "@OneCol @CP { ... }" (or @Code "@OneCol @Eiffel { ... }" etc. for +other languages) to prevent it being broken across two lines, if desired. +@PP +In cases where the program text has unbalanced braces, it is necessary to +use the alternative form @Code "@CP @Begin ... @End @CP" (or the +equivalent for other languages), so that Lout does not confuse program +braces with Lout braces. In that case the program text must not +contain {@Code "@End"}; and in either case the program text must not +include @Code "@Include" or @Code "@SysInclude" unless you are really +including a file at that point (Section {@NumberOf pipes}). +@PP +If your Lout document contains program texts in several languages, +simply add one @Code "@SysInclude" line for each of them and proceed +as before. If your programming language is not currently supported, +a viable alternative is +@ID @Code "@F @Verbatim { ... }" +These symbols cause the text between braces to be set verbatim in +a fixed-width font, as explained elsewhere in this guide. This fallback +method will not handle tab and formfeed characters very well. Again, +use @Code "@Verbatim @Begin ... @End @Verbatim" if your program text +contains unbalanced braces. +@End @Section diff --git a/doc/user/prg_erro b/doc/user/prg_erro new file mode 100644 index 0000000..7ebbe3e --- /dev/null +++ b/doc/user/prg_erro @@ -0,0 +1,39 @@ +@Section + @Title { Error messages } + @Tag { cpp_erro } +@Begin +@PP +In order to understand the error messages produced by program +printing, it is necessary to understand that Lout's first step when +given a program text is to pass it to the separate {@Code prg2lout} +program for analysis. This separate program is the source of most +of the error messages associated with program printing. +@PP +The {@Code prg2lout} program is quite happy to format a fragment of a +computer program: there is no need to supply a complete routine, or +a complete statement, or any such thing. However, it will complain if +you supply only a fragment of one lexical unit, such as a comment or +string without its terminating delimiter. It will also complain if +there is a character that cannot be classified as part of an identifier, +number, etc. according to the rules of the language as they have been +given to @Code prg2lout by the implementer. Irrespective of the +language rules, @Code prg2lout always interprets spaces, tabs, newlines, +and formfeed characters in the usual way. +@PP +If an error message is generated by {@Code prg2lout}, it will contain +a line and column number counting from the start of the program text +involved. Lout will precede this error message with a file name, +line number, and column number pointing to the Lout symbol +({@Code "@CP"}, {@Code "@Eiffel"} etc.) whose program text caused the +error message, like this: +@ID @Code @Verbatim { +lout file "prg_tabs" (from "prg" line 96, from "all" line 46): + 56,23: prg2lout 2,1: program text ended within comment +} +This is an actual message produced when formatting this chapter. The +program text in question has only one line, containing an incomplete comment, +so when @Code "prg2lout" tried to start the second line and found nothing, +it complained as shown. In general, then, you have to add +{@Code "prg2lout"}'s line number to Lout's line number, and use some +initiative, to find the precise point of the problem. +@End @Section diff --git a/doc/user/prg_lone b/doc/user/prg_lone new file mode 100644 index 0000000..1717998 --- /dev/null +++ b/doc/user/prg_lone @@ -0,0 +1,42 @@ +@Section + @Title { Typesetting computer programs independently of any document } + @Tag { alone } +@Begin +@PP +Printing of program files independently of any document is accomplished by +the following Unix pipeline: +@ID @Code "prg2lout -l language options files | lout -s > out.ps" +where @Code language stands for any one of the programming language +names in the first column of the table above. As usual with Lout, the +output will be a PostScript file. Each input file will begin on a new +page of the output, starting with its name in bold type. The options +provide control over the final appearance, as follows: +@WideTaggedList +@TI { {@Code-p}{@I style} } { +Select a printing style. Your choices are {@Code -pfixed}, +{@Code -pvarying}, and {@Code -psymbol}, with the default value +varying with the language as given in the fourth column of the +table above. Consult Section {@NumberOf embedded} for examples +of these styles. +} +@TI { @Code -n } { +Do not print file names. +} +@TI { {@Code -f}{@I font} } { +Select a Lout font family. The default is @Code "-fCourier" for +{@Code -pfixed}, and @Code "-fTimes" for @Code -pvarying and {@Code -psymbol}. +} +@TI { {@Code -v}{@I vsize} } { +Select an inter-line spacing size in Lout units. The default is +@Code -v1.1fx meaning 1.1 times the font size measured from baseline +to baseline. +} +@TI { {@Code -S}{@I file} } { +Use @I file as the setup file for printing your language. This allows +you to change all the options mentioned in subsequent sections, rather +than just the few given here. +} +@EndList +There are also {@Code -t} and {@Code -T} options for dealing with tab +characters (Section {@NumberOf tabs}). +@End @Section diff --git a/doc/user/prg_opti b/doc/user/prg_opti new file mode 100644 index 0000000..9eb1818 --- /dev/null +++ b/doc/user/prg_opti @@ -0,0 +1,101 @@ +@Section + @Title { Changing the appearance of a program } + @Tag { prg_opti } +@Begin +@PP +The {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols have a number of +options for changing the appearance of the printed program. These +options are the same for all symbols, although their default values +may vary. The @Code "style" option changes the printing style; its +value may be {@Code "fixed"} (fixed-width font), {@Code "varying"} +(varying-width font), or {@Code "symbol"} (varying-width font with +mathematical symbols used for some operators). Its default value +depends on the language, and may be found in the fourth column of +the table at the start of this chapter. The example in the previous +section was in @Code fixed style; we can switch styles like this: +@ID @OneRow @Code { +"@CP" +" style { varying }" +"{" +"#include " +"" +"treeprint(p) /* print tree p recursively */" +"struct tnode *p;" +"{" +" if (p != NULL) {" +" treeprint(p->left);" +" printf(\"%4d %s\\n\", p->count, p->word);" +" treeprint(p->right);" +" }" +"}" +"}" +} +The result in this case will be +@ID @OneRow @CP style { varying } +{ +#include + +treeprint(p) /* print tree p recursively */ +struct tnode *p; +{ + if (p != NULL) { + treeprint(p->left); + printf("%4d %s\n", p->count, p->word); + treeprint(p->right); + } +} +} +If we use @Code "style { symbol }" we get this: +@ID @OneRow @CP style { symbol } +{ +#include + +treeprint(p) /* print tree p recursively */ +struct tnode *p; +{ + if (p != NULL) { + treeprint(p->left); + printf("%4d %s\n", p->count, p->word); + treeprint(p->right); + } +} +} +with mathematical symbols replacing some of the operators. +@PP +The {@Code "@CP"}, {@Code "@Eiffel"} etc. symbols have additional options +which allow a finer control over the style. Here they all are, with their +default values: +@ID @OneRow @Code { +"@CP [ or @Eiffel, @Blue, etc. ]" +" style { fixed }" +" font { Courier }" +" size { -1.0p }" +" line { 1.0vx }" +" tabin { 8 }" +" tabout { 8s }" +" identifiers { Base }" +" keywords { Base }" +" operators { Base }" +" numbers { Base }" +" strings { Base }" +" comments { Base }" +"{" +" ..." +"}" +} +We are already familiar with {@Code "style"}. After that comes +{@Code "font"}, which determines the font family to use, {@Code "size"}, +the font size to use, and {@Code "line"}, the inter-line spacing. The +default value for @Code "size" asks for one point smaller than in the +surrounding document; this was done to compensate for Courier's relatively +large appearance compared to other fonts of the same nominal size. +@PP +The @Code "tabin" and @Code "tabout" options are the subject of +Section {@NumberOf tabs}. After them come six options giving the +particular font faces in which to print identifiers, keywords, operators, +numbers, strings, and comments. {@Code "Base"} means the basic face; other +commonly available choices are {@Code "Slope"} and {@Code "Bold"}. These +options may all be set to different faces if desired. The default values +shown are correct for @Code "style { fixed }" only; the other styles +have other defaults (Section {@NumberOf cpsetup}). +@End @Section diff --git a/doc/user/prg_perl b/doc/user/prg_perl new file mode 100644 index 0000000..4a14860 --- /dev/null +++ b/doc/user/prg_perl @@ -0,0 +1,108 @@ +@Section + @Title { Notes on Perl and Pod } + @Tag { prg_perl } +@Begin +@PP +The Perl programming language +@FootNote { My thanks to Mark Summerfield for help with Perl and Pod. } +is quite a difficult one for the @Code { prg2lout } program to deal with, +and our boast that programs can be included with `absolutely no +modifications' is not quite true for Perl. +@PP +Here is the complete list of problem areas. In most cases their +effect is to get the formatting wrong over a short region, which is not +perhaps so disastrous; and it should be easy to modify your Perl program +without changing its meaning, to work around these problems. After all, +in Perl there is always more than one way to do it. +@NumberedList + +@LI { +@I Here-documents such as +@ID @Verbatim { +<<"EOF" +These lines will be read as though +enclosed in double quotes +EOF +} +will be handled correctly only if the string appearing immediately after +the @Perl { << } operator (that is, the string used to terminate the +here-document) is one of @Perl { EOF }, @Perl { EOT }, @Perl { END }, +and the empty string, all optionally enclosed in quotes of any of the +three kinds. If this condition is not met, then the here-document will +be treated as Perl program text. If the condition is met, there is still +another problem: everything after the @Perl { << } symbol on the same +line will be treated (incorrectly) as a string; the worst consequence +of this is that stacked here-documents will not be printed properly. +} + +@LI { +When @Code { prg2lout } is scanning the program text looking for the +beginning of a lexical unit, it may come upon a @Code "/" character, +and this @I initial @Code "/" (not subsequent ones in the same lexical +unit) it finds difficult to interpret, since it may be the beginning +of a regular expression, to be formatted like a string, or it may be a +complete lexical unit denoting division. The program chooses the regular +expression (or equivalently, string) interpretation if the @Code "/" +character is immediately preceded by @Code { "q" }, @Code { "qq" }, +@Code { "qx" }, @Code { "qw" }, @Code { "qr" }, @Code { "m" }, +@Code { "s" }, @Code { "y" }, or @Code { "tr" }. It also chooses the +regular expression interpretation if the @Code "/" character appears +at the start of a line, or if it is +immediately preceded by zero, one, or two space or tab characters, which +are themselves immediately preceded by a complete lexical unit which is +one of @Code { "(" }, @Code { "=" }, @Code { "=~" }, @Code { "!~" }, +@Code { "split" }, @Code { "if" }, @Code { "not" }, @Code { "unless" }, +@Code { "for" }, @Code { "foreach" }, and @Code { "while" }. Otherwise +it chooses the division interpretation. In the rare cases where this +rule fails, you can force @Code { prg2lout } to choose the regular expression +interpretation by placing an @Code { m } in front of the initial @Code "/" +(this does not change the meaning of the program), and you can force the +division interpretation by placing at least three spaces before the +@Code "/" character. +} + +@LI { +The @Code { prg2lout } program recognises complete substitution operators, +such as @Code "s/abc/ABC/" and {@Code "s{abc}{ABC}"}, as individual lexical +units, and it formats them as it does strings. However, its rule for +deciding where these units end is rather simple-minded: at the start, +it works out what character finishes the unit (in the examples above, +@Code "/" and @Code "}" respectively), and scans along until it reaches +the second occurrence of this character not preceded by the @Code "\\" +escape character. This is inadequate in two respects. Firstly, +@ID @Code "s{{}}{}" +is a complete legal substitution expression in Perl, but @Code { prg2lout } +will think it ends after the second {@Code "}"}, and so format the rest +of it wrongly. Secondly, and more seriously, +@ID @Code "s{abc}" +is also allowed in Perl, but @Code { prg2lout } does not understand that +the finishing character can change in this way, so in this example it will +keep scanning forever, looking for the second @Code "}" character, which is +disastrous. +} + +@EndList +Further work may eliminate some of these problems. +@PP +The Pod language is used by Perl programmers for creating documentation, +and may be found within Perl programs or standing alone. Lout supports +both arrangements without any special action by the user. At the +beginning of the @Code perl setup line, the following line has been placed: +@ID @Code "@SysInclude { pod }" +Thus, asking for Perl always gives you Pod as well. If you are using +your own setup files for both languages, it is probably better to +break this connection by deleting this line from your copy of the +@Code perl setup file and placing +@ID @Code { +"@Include { mypod }" +"@Include { myperl }" +} +at the start of your document in the usual way. +@PP +Because Pod is a documentation language rather than a programming +language, the setup file options listed in Section {@NumberOf cpsetup} +do not really apply. So for Pod only these have been discarded and replaced +by a completely different set of options, controlling such things as +the size of headings and the gaps between list items, which you can +find documented in the @Code { pod } setup file. +@End @Section diff --git a/doc/user/prg_pipe b/doc/user/prg_pipe new file mode 100644 index 0000000..afbb87e --- /dev/null +++ b/doc/user/prg_pipe @@ -0,0 +1,57 @@ +@Section + @Title { Reading and selecting program text from separate files } + @Tag { pipes } +@Begin +@PP +We have said that program text within @Code "@CP { ... }" and the other +symbols is passed directly to @Code prg2lout for analysis. However, +there is an exception. The program text may contain an +@Code "@Include" or @Code "@SysInclude" command, which, as for the +@Code "@Verbatim" symbol (Section {@NumberOf verbatim}), causes Lout +to take the program text from a file: +@ID @Code { +"@Eiffel" +"{" +" @Include { \"/usr/staff/jeff/Eiffel/hash.e\" }" +"}" +} +The included file is not examined for balanced braces or @Code "@End" or +{@Code "@Include"}; it is treated entirely verbatim and passed straight +on to {@Code prg2lout}. There may be several @Code "@Include" commands, +and any amount of program text as well, within @Code "@CP { ... }" and +the rest. +@PP +When including files in this way it often happens that only part of an +actual program file is wanted for display. Rather than placing the +wanted part in a separate file, which is error-prone and tedious when +the program is changing, Unix users can use the @Code "pipe" option +to pipe the entire file through an arbitrary sequence of Unix commands, +which may be used to make the wanted selection before the program text +is passed to {@Code prg2lout}. +@PP +For example, suppose that all your Eiffel routines begin with the +routine name one tab stop from the left margin and end at the first +following @Eiffel { end } indented two tab stops. Then +@ID @Code { +"@Eiffel" +" pipe { \"sed -n /^.insert/,/^..end/p\" }" +"{" +" @Include { \"/usr/staff/jeff/Eiffel/hash.e\" }" +"}" +} +will select just the @Eiffel { insert } routine from the @Code { hash.e } +file. Assuming that your program text has been laid out in a +disciplined manner, every line of the selection will begin with a +tab character that is not wanted in this display, so an even better +pipe is +@ID @Code { +"@Eiffel" +" pipe { \"sed -n /^.insert/,/^..end/p | cut -c2-\" }" +"{" +" @Include { \"/usr/staff/jeff/Eiffel/hash.e\" }" +"}" +} +since it cuts away the unwanted tab characters. Unfortunately, we +can't show the result of this on an actual example, since that would +prevent this manual from being formatted on a non-Unix system. +@End @Section diff --git a/doc/user/prg_prog b/doc/user/prg_prog new file mode 100644 index 0000000..8d343f6 --- /dev/null +++ b/doc/user/prg_prog @@ -0,0 +1,35 @@ +@Section + @Title { Embedding program text within program comments } + @Tag { cpp_prog } +@Begin +@PP +The standard reference for the Eiffel language @Cite { $meyer1992eiffel } +specifies that identifiers within comments may or should be enclosed +in ` and ' so that they may be noticed and printed in an italic +font: +@ID @Code @Verbatim { +@ID @Eiffel { +deposit(amount: REAL) is + -- deposit `amount' dollars +} +} +produces +@ID @Eiffel { +deposit(amount: REAL) is + -- deposit `amount' dollars +} +This has been generalized in Lout: arbitrary text within an +Eiffel comment between ` and ' will be treated as Eiffel text and +printed accordingly. Some other languages may also offer this +feature: see the fifth column of the table at the start of this +chapter. In principle the precise means of getting it could vary +from language to language, but the languages available at the moment +either do not have it at all, or else they use ` and ' like Eiffel. +@PP +On the subject of Eiffel, the Eiffel reference @Cite { $meyer1992eiffel } +has some quite detailed style guidelines, and these have been closely +followed in the implementation of the @Code "@Eiffel" symbol. In +particular, @Code "@Eiffel" prints dots larger than usual when they +denote feature calls, as the example @OneCol @Eiffel { account.deposit(20) } +shows. +@End @Section diff --git a/doc/user/prg_tabs b/doc/user/prg_tabs new file mode 100644 index 0000000..3a04bfa --- /dev/null +++ b/doc/user/prg_tabs @@ -0,0 +1,66 @@ +@Section + @Title { Dealing with tab characters in programs } + @Tag { tabs } +@Begin +@PP +Tab characters provide a convenient way to indent and align parts of +tab.c @Index { tab characters in programs } +computer programs. With care, this alignment can be preserved in the final +print even with varying-width fonts. +@PP +The distance between two tab stops in the program text is by default taken +to be 8 characters, which is standard for Unix. This can be changed with +the @Code "tabin" option. For example, +@ID @Code "@CP tabin { 4 }" +informs Lout that tab stops occur every 4 characters in the program +text. All the symbols ({@Code "@CP"}, {@Code "@Eiffel"}, etc.) and +their setup files have this option and the next; but to save repetition +we will stick with C for the rest of this section. +@PP +The distance between two tab stops on the printed page is quite a different +thing, and it is determined by the value of the @Code "tabout" option, which +must be a Lout length. For example, +@ID @Code "@CP tabout { 0.5i }" +requests that tab stops be placed at half-inch intervals. In other +words, a distance of one tab stop in the program text will be equivalent to a +distance of half an inch on the printed page. For example, +@ID @Code "@CP style { varying } tabout { 3f }" +might produce the following, where tab characters in the program text +have been used for indenting and also to align the comments: +@ID @OneRow @CP style { varying } tabout { 3f } { +struct tnode { /* the basic node */ + char *word; /* points to the text */ + int count; /* number of occurrences */ + struct tnode *left; /* left child */ + struct tnode *right; /* right child */ +}; +} +The value {@Code "3f"} means three times the current font size, and +it is the default value of @Code "tabout" for the @Code { varying } +and @Code { symbol } styles (Section {@NumberOf cpsetup}). In a +12 point font this is 36 points, or half an inch. +@PP +If @Code "tabout" is too small, there is a danger that the +alignment might fail. For example, +@ID @Code "@CP style { varying } tabout { 0.2i }" +produces +@ID @OneRow @CP style { varying } tabout { 0.2i } { +struct tnode { /* the basic node */ + char *word; /* points to the text */ + int count; /* number of occurrences */ + struct tnode *left; /* left child */ + struct tnode *right; /* right child */ +}; +} +given the same C text as the previous example. The problem here is that +we are asking for @CP { /* } to appear four tab stops or 0.8 inches +from the left edge, and yet the material to its left on the line is +wider than this. This causes @CP { /* } to be shifted further to the +right than expected, and the alignment is lost. The only solution is +to increase {@Code "tabout"}. +@PP +When typesetting computer program texts independently of any document, +there are @Code "-t" and @Code "-T" options to the @Code "prg2lout" +program equivalent to @Code "tabin" and @Code "tabout" respectively. For +example, @Code "-T0.5i" produces a half-inch tab width. +@End @Section diff --git a/doc/user/user.ps b/doc/user/user.ps new file mode 100644 index 0000000..203f7e3 --- /dev/null +++ b/doc/user/user.ps @@ -0,0 +1,5202 @@ +%!PS-Adobe-3.0 +%%Creator: Basser Lout Version 3.19 (March 2000) +%%CreationDate: Mon Apr 3 16:16:36 2000 +%%DocumentData: Binary +%%DocumentNeededResources: (atend) +%%DocumentSuppliedResources: (atend) +%%DocumentMedia: A4 595 842 0 white () +%%PageOrder: Ascend +%%Pages: (atend) +%%BoundingBox: 0 0 595 842 +%%EndComments + +%%BeginProlog +%%BeginResource: procset LoutStartUp +/m { 3 1 roll moveto show } bind def +/mo { 3 1 roll moveto true charpath stroke } bind def +/s { exch currentpoint exch pop moveto show } bind def +/so { exch currentpoint exch pop moveto true charpath stroke } bind def +/k { exch neg 0 rmoveto show } bind def +/ko { exch neg 0 rmoveto true charpath stroke } bind def +/ul { gsave setlinewidth dup 3 1 roll + moveto lineto stroke grestore } bind def +/in { 1440 mul } def +/cm { 567 mul } def +/pt { 20 mul } def +/em { 120 mul } def +/sp { louts mul } def +/vs { loutv mul } def +/ft { loutf mul } def +/dg { } def + +/LoutGraphic { + /louts exch def + /loutv exch def + /loutf exch def + /ymark exch def + /xmark exch def + /ysize exch def + /xsize exch def +} def + +/LoutGr2 { gsave translate LoutGraphic gsave } def + +/LoutFont +{ findfont exch scalefont setfont +} bind def + +/LoutRecode { + { findfont dup length dict begin + {1 index /FID ne {def} {pop pop} ifelse} forall + /Encoding exch def + currentdict end definefont pop + } + stopped pop +} bind def + +/BeginEPSF { + /LoutEPSFState save def + /dict_count countdictstack def + /op_count count 1 sub def + userdict begin + /showpage { } def + 0 setgray 0 setlinecap + 1 setlinewidth 0 setlinejoin + 10 setmiterlimit [] 0 setdash newpath + /languagelevel where + { pop languagelevel + 1 ne + { false setstrokeadjust false setoverprint + } if + } if +} bind def + +/EndEPSF { + count op_count sub { pop } repeat + countdictstack dict_count sub { end } repeat + LoutEPSFState restore +} bind def +%%EndResource + +%%BeginResource: encoding vec2 +/vec2 [ +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef +/space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright +/parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +/zero /one /two /three /four /five /six /seven +/eight /nine /colon /semicolon /less /equal /greater /question +/at /A /B /C /D /E /F /G +/H /I /J /K /L /M /N /O +/P /Q /R /S /T /U /V /W +/X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +/quoteleft /a /b /c /d /e /f /g +/h /i /j /k /l /m /n /o +/p /q /r /s /t /u /v /w +/x /y /z /braceleft /bar /braceright /asciitilde /.notdef +/quotesinglbase /quotedblbase /ellipsis /OE /oe /quotedblleft /quotedblright /fi +/fl /endash /emdash /bullet /dagger /daggerdbl /florin /fraction +/dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent +/dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron +/space /exclamdown /cent /sterling /currency /yen /brokenbar /section +/dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron +/degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered +/cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown +/Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla +/Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis +/Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply +/Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls +/agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla +/egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis +/eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide +/oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis +] def +%%EndResource + +%%BeginResource: procset LoutTabPrependGraphic +% @PrependGraphic file /export/home/6monthspace/jeff/lout.lib/include/tabf.lpg +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PostScript @SysPrependGraphic file for @Tab % +% % +% To assist in avoiding name clashes, the names % +% of all these symbols begin with "ltab". % +% % +% Jeffrey H. Kingston % +% 24 September 1991 % +% 22 December 1992 % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% linewidth ltabhs - +% horizontal single line +/ltabhs +{ 0 0 moveto xsize 0 lineto + setlinewidth 0 setlinecap stroke +} def + +% linewidth ltabhsp - +% horizontal single line with projecting ends +/ltabhsp +{ 0 0 moveto xsize 0 lineto + setlinewidth 2 setlinecap stroke +} def + +% linewidth ltabhd - +% horizontal double line +/ltabhd +{ dup dup + 0 0 moveto xsize 0 lineto + 0 exch 3 mul moveto xsize exch 3 mul lineto + setlinewidth 0 setlinecap stroke +} def + +% linewidth ltabhdb - +% horizontal double line below mark +/ltabhdb +{ dup dup + 0 0 moveto xsize 0 lineto + 0 exch -3 mul moveto xsize exch -3 mul lineto + setlinewidth 0 setlinecap stroke +} def + +% linewidth ltabhdnw - +% horizontal double line with northwest corner +/ltabhdnw +{ dup dup dup dup + 0 0 moveto xsize 0 lineto + xsize exch 3 mul moveto + -3 mul exch 3 mul lineto + -3 mul 0 lineto + setlinewidth 0 setlinejoin 2 setlinecap stroke +} def + +% linewidth ltabhdne - +% horizontal double line with northeast corner +/ltabhdne +{ dup dup dup dup + 0 0 moveto xsize 0 lineto + 0 exch 3 mul moveto + 3 mul xsize add exch 3 mul lineto + 3 mul xsize add 0 lineto + setlinewidth 0 setlinejoin 2 setlinecap stroke +} def + +% linewidth ltabhdsw - +% horizontal double line with southwest corner +/ltabhdsw +{ dup dup dup dup + 0 0 moveto xsize 0 lineto + xsize exch -3 mul moveto + -3 mul exch -3 mul lineto + -3 mul 0 lineto + setlinewidth 0 setlinejoin 2 setlinecap stroke +} def + +% linewidth ltabhdse - +% horizontal double line with southeast corner +/ltabhdse +{ dup dup dup dup + 0 0 moveto xsize 0 lineto + 0 exch -3 mul moveto + 3 mul xsize add exch -3 mul lineto + 3 mul xsize add 0 lineto + setlinewidth 0 setlinejoin 2 setlinecap stroke +} def + +% linewidth ltabvs - +% vertical single line +/ltabvs +{ 0 0 moveto 0 ysize lineto + setlinewidth 0 setlinecap stroke +} def + +% linewidth ltabvd - +% vertical double line +/ltabvd +{ dup dup + 0 0 moveto 0 ysize lineto + -3 mul 0 moveto -3 mul ysize lineto + setlinewidth 0 setlinecap stroke +} def + +% linewidth ltabvdr - +% vertical double line to right of mark +/ltabvdr +{ dup dup + 0 0 moveto 0 ysize lineto + 3 mul 0 moveto 3 mul ysize lineto + setlinewidth 0 setlinecap stroke +} def +%%EndResource + +%%BeginResource: procset LoutTblPrependGraphic +% @PrependGraphic file /export/home/6monthspace/jeff/lout.lib/include/tblf.lpg +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PostScript @SysPrependGraphic file for @Tbl Jeffrey H. Kingston % +% Version 1.0 June 1998 % +% % +% To assist in avoiding name clashes, the names of all symbols % +% defined here begin with "ltbl". % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% painting (i.e. filling): - ltblwhite - (etc.) +/ltblnopaint { } def +/ltblnochange { fill } def +/ltbldarkblue { 0.0 0.0 0.5 setrgbcolor fill } def +/ltblblue { 0.0 0.0 1.0 setrgbcolor fill } def +/ltbllightblue { 0.5 0.5 1.0 setrgbcolor fill } def +/ltbldarkgreen { 0.0 0.5 0.0 setrgbcolor fill } def +/ltblgreen { 0.0 1.0 0.0 setrgbcolor fill } def +/ltbllightgreen { 0.5 1.0 0.5 setrgbcolor fill } def +/ltbldarkred { 0.5 0.0 0.0 setrgbcolor fill } def +/ltblred { 1.0 0.0 0.0 setrgbcolor fill } def +/ltbllightred { 1.0 0.5 0.5 setrgbcolor fill } def +/ltbldarkcyan { 0.0 0.5 0.5 setrgbcolor fill } def +/ltblcyan { 0.0 1.0 1.0 setrgbcolor fill } def +/ltbllightcyan { 0.5 1.0 1.0 setrgbcolor fill } def +/ltbldarkmagenta { 0.5 0.0 0.5 setrgbcolor fill } def +/ltblmagenta { 1.0 0.0 1.0 setrgbcolor fill } def +/ltbllightmagenta { 1.0 0.5 1.0 setrgbcolor fill } def +/ltbldarkyellow { 0.5 0.5 0.0 setrgbcolor fill } def +/ltblyellow { 1.0 1.0 0.0 setrgbcolor fill } def +/ltbllightyellow { 1.0 1.0 0.5 setrgbcolor fill } def +/ltbldarkgray { 0.2 0.2 0.2 setrgbcolor fill } def +/ltblgray { 0.5 0.5 0.5 setrgbcolor fill } def +/ltbllightgray { 0.8 0.8 0.8 setrgbcolor fill } def +/ltbldarkgrey { 0.2 0.2 0.2 setrgbcolor fill } def +/ltblgrey { 0.5 0.5 0.5 setrgbcolor fill } def +/ltbllightgrey { 0.8 0.8 0.8 setrgbcolor fill } def +/ltblblack { 0.0 0.0 0.0 setrgbcolor fill } def +/ltblwhite { 1.0 1.0 1.0 setrgbcolor fill } def +%%EndResource + +%%BeginResource: procset LoutFigPrependGraphic +% @PrependGraphic file /export/home/6monthspace/jeff/lout.lib/include/figf.lpg +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PostScript @SysPrependGraphic file for @Fig Jeffrey H. Kingston % +% Version 2.0 (includes CIRCUM label) January 1992 % +% % +% To assist in avoiding name clashes, the names of all symbols % +% defined here begin with "lfig". However, this is not feasible % +% with user-defined labels and some labels used by users. % +% % +% is two numbers, a point. % +% is one number, a length % +% is one number, an angle in degrees % +% is one number, the preferred length of a dash % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +errordict begin + /handleerror + { + { /Times-Roman findfont 8 pt scalefont setfont + 0 setgray 4 pt 4 pt moveto + $error /errorname get + dup lfigdict exch known + { lfigdict exch get } + { 30 string cvs } ifelse + show + ( Command: ) show + $error /command get 30 string cvs show + } stopped {} if + showpage stop + } def +end + +% concat strings: lfigconcat +% must be defined outside lfigdict since used in lfigpromotelabels +/lfigconcat +{ 2 copy length exch length add string + dup 0 4 index putinterval + dup 3 index length 3 index putinterval + 3 1 roll pop pop +} def + +% lfigdebugprint - +% must be defined outside lfigdict since used in arbitrary places +% /lfigdebugprint +% { print +% (; operand stack:\n) print +% count copy +% count 2 idiv +% { == +% (\n) print +% } repeat +% (\n) print +% } def + +/lfigdict 120 dict def +lfigdict begin + +% error messages +/dictfull (dictfull error: too many labels?) def +/dictstackoverflow (dictstackoverflow error: labels nested too deeply?) def +/execstackoverflow (execstackoverflow error: figure nested too deeply?) def +/limitcheck (limitcheck error: figure nested too deeply or too large?) def +/syntaxerror (syntaxerror error: syntax error in text of figure?) def +/typecheck (typecheck error: syntax error in text of figure?) def +/undefined (undefined error: unknown or misspelt label?) def +/VMError (VMError error: run out of memory?) def + +% push pi onto stack: - lfigpi +/lfigpi 3.14159 def + +% arc directions +/clockwise false def +/anticlockwise true def + +% maximum of two numbers: lfigmax +/lfigmax { 2 copy gt { pop } { exch pop } ifelse } def + +% minimum of two numbers: lfigmin +/lfigmin { 2 copy lt { pop } { exch pop } ifelse } def + +% add two points: lfigpadd +/lfigpadd { exch 3 1 roll add 3 1 roll add exch } def + +% subtract first point from second: lfigpsub +/lfigpsub { 3 2 roll sub 3 1 roll exch sub exch } def + +% max two points: lfigpmax +/lfigpmax { exch 3 1 roll lfigmax 3 1 roll lfigmax exch } def + +% min two points: lfigpmin +/lfigpmin { exch 3 1 roll lfigmin 3 1 roll lfigmin exch } def + +% scalar multiplication: lfigpmul +/lfigpmul { dup 3 1 roll mul 3 1 roll mul exch } def + +% point at angle and distance: lfigatangle +/lfigatangle { 2 copy cos mul 3 1 roll sin mul lfigpadd } def + +% angle from one point to another: lfigangle +/lfigangle { lfigpsub 2 copy 0 eq exch 0 eq and {pop} {exch atan} ifelse } def + +% distance between two points: lfigdistance +/lfigdistance { lfigpsub dup mul exch dup mul add sqrt } def + +% difference in x coords: lfigxdistance +/lfigxdistance { pop 3 1 roll pop sub } def + +%difference in y coords: lfigydistance +/lfigydistance { 3 1 roll pop sub exch pop } def + +% stroke a solid line: lfigsolid - +/lfigsolid +{ pop pop [] 0 setdash stroke +} def + +% stroke a lfigdashed line: lfigdashed - +/lfigdashed +{ 2 copy div 2 le 1 index 0 le or + { exch pop 1 pt lfigmax [ exch dup ] 0 setdash } + { dup [ exch 4 2 roll 2 copy div + 1 sub 2 div ceiling dup 4 1 roll + 1 add mul sub exch div ] 0 setdash + } ifelse stroke +} def + +% stroke a lfigcdashed line: lfigcdashed - +/lfigcdashed +{ 2 copy le 1 index 0 le or + { exch pop 1 pt lfigmax [ exch dup ] dup 0 get 2 div setdash } + { dup [ 4 2 roll exch 2 copy exch div + 2 div ceiling div 1 index sub + ] exch 2 div setdash + } ifelse stroke +} def + +% stroke a dotted line: lfigdotted - +/lfigdotted +{ 2 copy le 1 index 0 le or + { exch pop 1 pt lfigmax [ exch 0 exch ] 0 setdash } + { 1 index exch div ceiling div + [ 0 3 2 roll ] 0 setdash + } ifelse stroke +} def + +% stroke a noline line: lfignoline - +/lfignoline +{ pop pop +} def + +% painting (i.e. filling): - lfigwhite - (etc.) +/lfignopaint { } def +/lfignochange { fill } def +/lfigdarkblue { 0.0 0.0 0.5 setrgbcolor fill } def +/lfigblue { 0.0 0.0 1.0 setrgbcolor fill } def +/lfiglightblue { 0.5 0.5 1.0 setrgbcolor fill } def +/lfigdarkgreen { 0.0 0.5 0.0 setrgbcolor fill } def +/lfiggreen { 0.0 1.0 0.0 setrgbcolor fill } def +/lfiglightgreen { 0.5 1.0 0.5 setrgbcolor fill } def +/lfigdarkred { 0.5 0.0 0.0 setrgbcolor fill } def +/lfigred { 1.0 0.0 0.0 setrgbcolor fill } def +/lfiglightred { 1.0 0.5 0.5 setrgbcolor fill } def +/lfigdarkcyan { 0.0 0.5 0.5 setrgbcolor fill } def +/lfigcyan { 0.0 1.0 1.0 setrgbcolor fill } def +/lfiglightcyan { 0.5 1.0 1.0 setrgbcolor fill } def +/lfigdarkmagenta { 0.5 0.0 0.5 setrgbcolor fill } def +/lfigmagenta { 1.0 0.0 1.0 setrgbcolor fill } def +/lfiglightmagenta { 1.0 0.5 1.0 setrgbcolor fill } def +/lfigdarkyellow { 0.5 0.5 0.0 setrgbcolor fill } def +/lfigyellow { 1.0 1.0 0.0 setrgbcolor fill } def +/lfiglightyellow { 1.0 1.0 0.5 setrgbcolor fill } def +/lfigdarkgray { 0.2 0.2 0.2 setrgbcolor fill } def +/lfiggray { 0.5 0.5 0.5 setrgbcolor fill } def +/lfiglightgray { 0.8 0.8 0.8 setrgbcolor fill } def +/lfigdarkgrey { 0.2 0.2 0.2 setrgbcolor fill } def +/lfiggrey { 0.5 0.5 0.5 setrgbcolor fill } def +/lfiglightgrey { 0.8 0.8 0.8 setrgbcolor fill } def +/lfigblack { 0.0 0.0 0.0 setrgbcolor fill } def +/lfigwhite { 1.0 1.0 1.0 setrgbcolor fill } def + +% line caps (and joins, not currently used) +/lfigbutt 0 def +/lfiground 1 def +/lfigprojecting 2 def +/lfigmiter 0 def +/lfigbevel 2 def + +% shape and labels of the @Box symbol +/lfigbox +{ + 0 0 /SW lfigpointdef + xsize 0 /SE lfigpointdef + xsize ysize /NE lfigpointdef + 0 ysize /NW lfigpointdef + SE 0.5 lfigpmul /S lfigpointdef + NW 0.5 lfigpmul /W lfigpointdef + W SE lfigpadd /E lfigpointdef + S NW lfigpadd /N lfigpointdef + NE 0.5 lfigpmul /CTR lfigpointdef + [ CTR NE lfigpsub /lfigboxcircum cvx ] lfigcircumdef + SW SE NE NW SW +} def + +% shape and labels of the @CurveBox symbol +/lfigcurvebox +{ + + xsize 0.5 mul ysize 0.5 mul /CTR lfigpointdef + xsize 0.5 mul 0 /S lfigpointdef + xsize ysize 0.5 mul /E lfigpointdef + xsize 0.5 mul ysize /N lfigpointdef + 0 ysize 0.5 mul /W lfigpointdef + + xmark 0.293 mul xmark 0.293 mul /SW lfigpointdef + xsize xmark 0.293 mul sub xmark 0.293 mul /SE lfigpointdef + xsize xmark 0.293 mul sub ysize xmark 0.293 mul sub /NE lfigpointdef + xmark 0.293 mul ysize xmark 0.293 mul sub /NW lfigpointdef + + [ xsize ysize 0.5 lfigpmul xmark /lfigcurveboxcircum cvx ] lfigcircumdef + + xmark 0 + xsize xmark sub 0 + [ xsize xmark sub xmark ] + xsize xmark + xsize ysize xmark sub + [ xsize xmark sub ysize xmark sub ] + xsize xmark sub ysize + xmark ysize + [ xmark ysize xmark sub ] + 0 ysize xmark sub + 0 xmark + [ xmark xmark ] + xmark 0 +} def + +% shadow of the @ShadowBox symbol +% its shape and labels are done, somewhat inaccurately, with lfigbox +/lfigshadow +{ xmark 2 mul 0 moveto xsize 0 lineto + xsize ysize xmark 2 mul sub lineto + xsize xmark sub ysize xmark 2 mul sub lineto + xsize xmark sub xmark lineto + xmark 2 mul xmark lineto closepath fill +} def + +% shape and labels of the @Square symbol +/lfigsquare +{ + xsize ysize 0.5 lfigpmul /CTR lfigpointdef + CTR xsize xsize ysize ysize lfigpmax 0.5 lfigpmul lfigpadd /NE lfigpointdef + CTR 0 0 CTR NE lfigdistance 135 lfigatangle lfigpadd /NW lfigpointdef + CTR 0 0 CTR NE lfigdistance 225 lfigatangle lfigpadd /SW lfigpointdef + CTR 0 0 CTR NE lfigdistance 315 lfigatangle lfigpadd /SE lfigpointdef + SW 0.5 lfigpmul SE 0.5 lfigpmul lfigpadd /S lfigpointdef + NW 0.5 lfigpmul NE 0.5 lfigpmul lfigpadd /N lfigpointdef + SW 0.5 lfigpmul NW 0.5 lfigpmul lfigpadd /W lfigpointdef + SE 0.5 lfigpmul NE 0.5 lfigpmul lfigpadd /E lfigpointdef + [ CTR NE lfigpsub /lfigboxcircum cvx ] lfigcircumdef + SW SE NE NW SW +} def + +% shape and labels of the @Diamond symbol +/lfigdiamond +{ + xsize 0 0.5 lfigpmul /S lfigpointdef + 0 ysize 0.5 lfigpmul /W lfigpointdef + S W lfigpadd /CTR lfigpointdef + CTR W lfigpadd /N lfigpointdef + CTR S lfigpadd /E lfigpointdef + [ xsize ysize 0.5 lfigpmul /lfigdiamondcircum cvx ] lfigcircumdef + S E N W S +} def + +% shape and labels of the @Ellipse symbol +/lfigellipse +{ + xsize 0 0.5 lfigpmul /S lfigpointdef + 0 ysize 0.5 lfigpmul /W lfigpointdef + S W lfigpadd /CTR lfigpointdef + CTR W lfigpadd /N lfigpointdef + CTR S lfigpadd /E lfigpointdef + CTR xsize 0 0.3536 lfigpmul lfigpadd 0 ysize 0.3536 lfigpmul lfigpadd /NE lfigpointdef + 0 ysize 0.3536 lfigpmul CTR xsize 0 0.3536 lfigpmul lfigpadd lfigpsub /SE lfigpointdef + xsize 0 0.3536 lfigpmul CTR lfigpsub 0 ysize 0.3536 lfigpmul lfigpadd /NW lfigpointdef + 0 ysize 0.3536 lfigpmul xsize 0 0.3536 lfigpmul CTR lfigpsub lfigpsub /SW lfigpointdef + [ xsize ysize 0.5 lfigpmul /lfigellipsecircum cvx ] lfigcircumdef + S [ CTR ] E [ CTR ] N [ CTR ] W [ CTR ] S +} def + +% shape and labels of the @Circle symbol +/lfigcircle +{ + xsize ysize 0.5 lfigpmul /CTR lfigpointdef + CTR xsize 0 ysize 0 lfigpmax 0.5 lfigpmul lfigpadd /E lfigpointdef + CTR 0 0 CTR E lfigdistance 45 lfigatangle lfigpadd /NE lfigpointdef + CTR 0 0 CTR E lfigdistance 90 lfigatangle lfigpadd /N lfigpointdef + CTR 0 0 CTR E lfigdistance 135 lfigatangle lfigpadd /NW lfigpointdef + CTR 0 0 CTR E lfigdistance 180 lfigatangle lfigpadd /W lfigpointdef + CTR 0 0 CTR E lfigdistance 225 lfigatangle lfigpadd /SW lfigpointdef + CTR 0 0 CTR E lfigdistance 270 lfigatangle lfigpadd /S lfigpointdef + CTR 0 0 CTR E lfigdistance 315 lfigatangle lfigpadd /SE lfigpointdef + [ S E lfigpsub /lfigellipsecircum cvx ] lfigcircumdef + S [ CTR ] E [ CTR ] N [ CTR ] W [ CTR ] S +} def + +% shape and labels of the @HLine and @HArrow symbols +/lfighline +{ + 0 ymark lfigprevious /FROM lfigpointdef + xsize ymark lfigprevious /TO lfigpointdef +} def + +% shape and labels of the @VLine and @VArrow symbols +/lfigvline +{ + xmark ysize lfigprevious /FROM lfigpointdef + xmark 0 lfigprevious /TO lfigpointdef +} def + +% points of a polygon around base with given no of sides, vert init angle: +% figpolygon ... +/lfigpolygon +{ xsize ysize 0.5 lfigpmul /CTR lfigpointdef + 90 sub CTR 2 copy lfigmax 5 3 roll + [ 4 copy pop /lfigpolycircum cvx ] lfigcircumdef + exch dup 360 exch div exch + 1 1 3 2 roll + { 4 string cvs (P) exch lfigconcat cvn + 6 copy pop pop lfigatangle 2 copy 10 2 roll + 3 2 roll lfigpointdef + dup 3 1 roll add exch + } for + pop lfigatangle +} def + +% next array element: lfiggetnext true +% or false +/lfiggetnext +{ 2 copy exch length ge + { false } + { 2 copy get exch 1 add exch true } ifelse +} def + +% check whether thing is number: lfigisnumbertype +/lfigisnumbertype +{ dup type dup + /integertype eq exch /realtype eq or +} def + +% check whether thing is an array: lfigisarraytype +/lfigisarraytype { dup type /arraytype eq } def + +% get next item: lfiggetnextitem 0 +% or 1 +% or 2 +/lfiggetnextitem +{ lfiggetnext + { lfigisarraytype + { 1 + } + { lfigisnumbertype + { 3 1 roll + lfiggetnext + { lfigisnumbertype + { 4 3 roll exch 2 + } + { pop 3 2 roll pop 0 + } ifelse + } + { 3 2 roll pop 0 + } ifelse + } + { pop 0 + } ifelse + } ifelse + } + { 0 + } ifelse +} def + +% set arc path: bool x1 y1 x2 y2 x0 y0 lfigsetarc +% the path goes from x1 y1 to x2 y2 about centre x0 y0, +% anticlockwise if bool is true else clockwise. +% The orientations of backwards pointing and forwards pointing +% arrowheads are returned in the two angles, and +% the length of the arc is returned in . +/lfigsetarc +{ + 20 dict begin + matrix currentmatrix 8 1 roll + 2 copy translate 2 copy 8 2 roll + 4 2 roll lfigpsub 6 2 roll lfigpsub + dup /y1 exch def dup mul /y1s exch def + dup /x1 exch def dup mul /x1s exch def + dup /y2 exch def dup mul /y2s exch def + dup /x2 exch def dup mul /x2s exch def + + y1s y2s eq + { -1 + } + { y1s x2s mul y2s x1s mul sub y1s y2s sub div + } ifelse + /da exch def + + x1s x2s eq + { -1 + } + { x1s y2s mul x2s y1s mul sub x1s x2s sub div + } ifelse + /db exch def + + da 0 gt db 0 gt and + { /LMax da sqrt db sqrt lfigmax def + /scalex da sqrt LMax div def + /scaley db sqrt LMax div def + scalex scaley scale + 0 0 LMax + 0 0 x1 scalex mul y1 scaley mul lfigangle + 0 0 x2 scalex mul y2 scaley mul lfigangle + 2 copy eq { 360 add } if + 2 copy 8 2 roll + 5 index { arc } { arcn } ifelse + 2 index 1 index + { 90 sub } { 90 add } ifelse + dup sin scaley mul exch cos scalex mul atan + 2 index 2 index + { 90 add } { 90 sub } ifelse + dup sin scaley mul exch cos scalex mul atan + 5 2 roll % res1 res2 ang1 ang2 anticlockwise + { exch sub } { sub } ifelse + dup 0 le { 360 add } if lfigpi mul LMax mul 180 div + } + { 0 0 x1 y1 lfigdistance 0 0 x2 y2 lfigdistance eq + 0 0 x1 y1 lfigdistance 0 gt and + { 0 0 + 0 0 x1 y1 lfigdistance + 0 0 x1 y1 lfigangle + 0 0 x2 y2 lfigangle + 2 copy eq { 360 add } if + 2 copy 8 2 roll + 5 index { arc } { arcn } ifelse + 2 index 1 index + { 90 sub } { 90 add } ifelse + 2 index 2 index + { 90 add } { 90 sub } ifelse + 5 2 roll % res1 res2 ang1 ang2 clockwise + { exch sub } { sub } ifelse + dup 0 le { 360 add } if lfigpi mul 0 0 x1 y1 lfigdistance mul 180 div + } + { x2 y2 lineto pop + x2 y2 x1 y1 lfigangle + x1 y1 x2 y2 lfigangle + x1 y1 x2 y2 lfigdistance + } ifelse + } ifelse + 4 -1 roll setmatrix + end +} def + +% lfigsetcurve: set up a Bezier curve from x0 y0 to x3 y3 +% and return arrowhead angles and length of curve (actually 0) +% x0 y0 x1 y1 x2 y2 x3 y3 lfigsetcurve +/lfigsetcurve +{ 8 copy curveto pop pop + lfigangle + 5 1 roll + 4 2 roll lfigangle + exch + 0 +} def + +% lfigpaintpath: paint a path of the given shape +% /paint [ shape ] lfigpaintpath - +/lfigpaintpath +{ + 10 dict begin + 0 newpath + /prevseen false def + /curveseen false def + { lfiggetnextitem + dup 0 eq { pop exit } + { 1 eq + { /curveseen true def + /curve exch def + curve length 0 eq { /curveseen false def } if + } + { /ycurr exch def + /xcurr exch def + prevseen + { curveseen + { curve length 4 eq + { xprev yprev + curve 0 get curve 1 get + curve 2 get curve 3 get + xcurr ycurr + lfigsetcurve pop pop pop + } + { xprev yprev xcurr ycurr + curve length 1 ge { curve 0 get } { 0 } ifelse + curve length 2 ge { curve 1 get } { 0 } ifelse + curve length 3 ge { curve 2 get } { true } ifelse + 7 1 roll + lfigsetarc pop pop pop + } ifelse + } + { xcurr ycurr lineto + } ifelse + } + { xcurr ycurr moveto + } ifelse + /xprev xcurr def + /yprev ycurr def + /prevseen true def + /curveseen false def + } ifelse + } ifelse + } loop pop pop cvx exec + end +} def + +% stroke a path of the given shape in the given linestyle and dash length. +% Return the origin and angle of the backward and forward arrow heads. +% dashlength /linestyle [shape] lfigdopath [ ] [ ] +/lfigdopath +{ + 10 dict begin + 0 + /prevseen false def + /curveseen false def + /backarrow [] def + /fwdarrow [] def + { + lfiggetnextitem + dup 0 eq { pop exit } + { + 1 eq + { /curveseen true def + /curve exch def + curve length 0 eq { /prevseen false def } if + } + { /ycurr exch def + /xcurr exch def + prevseen + { newpath xprev yprev moveto + curveseen + { curve length 4 eq + { xprev yprev + curve 0 get curve 1 get + curve 2 get curve 3 get + xcurr ycurr lfigsetcurve + } + { xprev yprev xcurr ycurr + curve length 1 ge { curve 0 get } { 0 } ifelse + curve length 2 ge { curve 1 get } { 0 } ifelse + curve length 3 ge { curve 2 get } { true } ifelse + 7 1 roll + lfigsetarc + } ifelse + } + { xcurr ycurr lineto + xcurr ycurr xprev yprev lfigangle dup 180 sub + xprev yprev xcurr ycurr lfigdistance + } ifelse + 6 index 6 index cvx exec + [ xprev yprev 5 -1 roll ] + backarrow length 0 eq + { /backarrow exch def } + { pop } ifelse + [ xcurr ycurr 4 -1 roll ] /fwdarrow exch def + } if + /xprev xcurr def + /yprev ycurr def + /prevseen true def + /curveseen false def + } ifelse + } ifelse + } loop + pop pop pop pop + backarrow length 0 eq { [ 0 0 0 ] } { backarrow } ifelse + fwdarrow length 0 eq { [ 0 0 0 ] } { fwdarrow } ifelse + end +} def + +% lfigdoarrow: draw an arrow head of given form +% dashlength /lstyle /pstyle hfrac height width [ ] lfigdoarrow - +/lfigdoarrow +{ matrix currentmatrix 8 1 roll + dup 0 get 1 index 1 get translate + 2 get rotate + [ 2 index neg 2 index 0 0 + 3 index 3 index neg + 1 index 10 index mul 0 + 7 index 7 index ] + 4 1 roll pop pop pop + dup 3 1 roll + gsave lfigpaintpath grestore lfigdopath pop pop + setmatrix +} def + +% arrow head styles +/lfigopen 0.0 def +/lfighalfopen 0.5 def +/lfigclosed 1.0 def + +% stroke no arrows, forward, back, and both +/lfignoarrow { pop pop pop pop pop pop pop pop } def +/lfigforward { 7 -1 roll lfigdoarrow pop } def +/lfigback { 8 -2 roll pop lfigdoarrow } def +/lfigboth { 8 -1 roll 7 copy lfigdoarrow pop 7 -1 roll lfigdoarrow } def + +% lfigprevious: return previous point on path +/lfigprevious +{ lfigisnumbertype + { 2 copy } + { lfigisarraytype + { 2 index 2 index } + { 0 0 } + ifelse + } ifelse +} def + +% label a point in 2nd top dictionary: /name lfigpointdef - +/lfigpointdef +{ + % (Entering lfigpointdef) lfigdebugprint + [ 4 2 roll transform + /itransform cvx ] cvx + currentdict end + 3 1 roll + % currentdict length currentdict maxlength lt + % { def } + % { exec moveto (too many labels) show stop } + % ifelse + def + begin + % (Leaving lfigpointdef) lfigdebugprint +} def + +% promote labels from second top to third top dictionary +% lfigpromotelabels - +/lfigpromotelabels +{ + % (Entering lfigpromotelabels) lfigdebugprint + currentdict end exch currentdict end + { exch 20 string cvs 2 index + (@) lfigconcat exch lfigconcat cvn exch def + } forall pop begin + % (Leaving lfigpromotelabels) lfigdebugprint +} def + +% show labels (except CIRCUM): - lfigshowlabels - +/lfigshowlabels +{ + % (Entering lfigshowlabels) lfigdebugprint + currentdict end + currentdict + { 1 index 20 string cvs (CIRCUM) search % if CIRCUM in key + { pop pop pop pop pop } + { pop cvx exec 2 copy + newpath 1.5 pt 0 360 arc + 0 setgray fill + /Times-Roman findfont 8 pt scalefont setfont + moveto 0.2 cm 0.1 cm rmoveto 20 string cvs show + } + ifelse + } forall + begin + % (Leaving lfigshowlabels) lfigdebugprint +} def + +% fix an angle to 0 <= res < 360: lfigfixangle +/lfigfixangle +{ + % (Entering lfigfixangle) lfigdebugprint + { dup 0 ge { exit } if + 360 add + } loop + { dup 360 lt { exit } if + 360 sub + } loop + % (Leaving lfigfixangle) lfigdebugprint +} def + +% find point on circumference of box: alpha a b lfigboxcircum x y +/lfigboxcircum +{ + % (Entering lfigboxcircum) lfigdebugprint + 4 dict begin + /b exch def + /a exch def + lfigfixangle /alpha exch def + 0 0 a b lfigangle /theta exch def + + % if alpha <= theta, return (a, a*tan(alpha)) + alpha theta le + { a a alpha sin mul alpha cos div } + { + % else if alpha <= 180 - theta, return (b*cot(alpha), b) + alpha 180 theta sub le + { b alpha cos mul alpha sin div b } + { + % else if alpha <= 180 + theta, return (-a, -a*tan(alpha)) + alpha 180 theta add le + { a neg a neg alpha sin mul alpha cos div } + { + % else if alpha <= 360 - theta, return (-b*cot(alpha), -b) + alpha 360 theta sub le + { b neg alpha cos mul alpha sin div b neg } + { + % else 360 - theta <= alpha, return (a, a*tan(alpha)) + a a alpha sin mul alpha cos div + } ifelse + } ifelse + } ifelse + } ifelse + end + % (Leaving lfigboxcircum) lfigdebugprint +} def + +% find quadratic roots (assume a != 0): a b c lfigqroots x1 x2 2 +% or x2 1 +% or 0 +/lfigqroots +{ + 4 dict begin + /c exch def + /b exch def + /a exch def + /disc b b mul 4 a c mul mul sub def + disc 0 lt + { 0 + } + { disc 0 eq + { b neg 2 a mul div + 1 + } + { b neg disc sqrt add 2 a mul div + b neg disc sqrt sub 2 a mul div + 2 + } + ifelse + } + ifelse + end +} def + +% work our which quadrant: lfigquadrant <0-3> +/lfigquadrant +{ dup 90 lt + { pop 0 + } + { dup 180 lt + { pop 1 + } + { 270 lt + { 2 + } + { 3 + } ifelse + } ifelse + } ifelse +} def + +% find curvebox circum, assuming upper right quadrant: alpha a b xmk lfigcb x y +/lfigcb +{ + 6 dict begin + /xmk exch def + /b exch def + /a exch def + /alpha exch def + /theta1 0 0 a b xmk sub lfigangle def + /theta2 0 0 a xmk sub b lfigangle def + alpha theta1 le + { % if alpha <= theta1, return (a, a*tan(alpha)) + a a alpha sin mul alpha cos div + } + { alpha theta2 ge + { % else if alpha > theta2, return (b*cot(alpha), b) + b alpha cos mul alpha sin div b + } + { + % else, return the intersection of line and circle + a xmk sub b xmk sub xmk 0 0 alpha lfigcircleintersect + dup 0 eq + { % should never happen, just return any reasonable point + pop + a b 0.5 lfigpmul + } + { 1 eq + { % should never happen, just return the point on top of stack + } + { % the usual case, two points on stack, return the larger + lfigpmax + } ifelse + } ifelse + } ifelse + } ifelse + end +} def + +% find point on circumference of curvebox: alpha a b xmk lfigcurveboxcircum x y +/lfigcurveboxcircum +{ + % (Entering lfigcurveboxcircum) lfigdebugprint + 5 dict begin + /xmk exch def + /b exch def + /a exch def + lfigfixangle /alpha exch def + + % work out which quadrant we are in, and reflect accordingly + /quad alpha lfigquadrant def + quad 0 eq + { alpha a b xmk lfigcb + } + { quad 1 eq + { 180 alpha sub a b xmk lfigcb exch neg exch + } + { quad 2 eq + { alpha 180 sub a b xmk lfigcb neg exch neg exch + } + { 360 alpha sub a b xmk lfigcb neg + } ifelse + } ifelse + } ifelse + end + % (Leaving lfigcurveboxcircum) lfigdebugprint +} def + +% find point on circumference of diamond: alpha a b lfigdiamondcircum x y +/lfigdiamondcircum +{ + % (Entering lfigdiamondcircum) lfigdebugprint + 4 dict begin + /b exch def + /a exch def + lfigfixangle /alpha exch def + b alpha cos abs mul a alpha sin abs mul add /denom exch def + a b mul alpha cos mul denom div + a b mul alpha sin mul denom div + end + % (Leaving lfigdiamondcircum) lfigdebugprint +} def + +% find point on circumference of ellipse: alpha a b lfigellipsecircum x y +/lfigellipsecircum +{ + % (Entering lfigellipsecircum) lfigdebugprint + 4 dict begin + /b exch def + /a exch def + lfigfixangle /alpha exch def + b alpha cos mul dup mul a alpha sin mul dup mul add sqrt /denom exch def + a b mul alpha cos mul denom div + a b mul alpha sin mul denom div + end + % (Leaving lfigellipsecircum) lfigdebugprint +} def + +% find point of intersection of two lines each defined by two points +% x1 y1 x2 y2 x3 y3 x4 y4 lfiglineintersect x y +/lfiglineintersect +{ + % (Entering lfiglineintersect) lfigdebugprint + 13 dict begin + /y4 exch def + /x4 exch def + /y3 exch def + /x3 exch def + /y2 exch def + /x2 exch def + /y1 exch def + /x1 exch def + x2 x1 sub /x21 exch def + x4 x3 sub /x43 exch def + y2 y1 sub /y21 exch def + y4 y3 sub /y43 exch def + y21 x43 mul y43 x21 mul sub /det exch def + + % calculate x + y21 x43 mul x1 mul + y43 x21 mul x3 mul sub + y3 y1 sub x21 mul x43 mul add + det div + + % calculate y + x21 y43 mul y1 mul + x43 y21 mul y3 mul sub + x3 x1 sub y21 mul y43 mul add + det neg div + + end + % (Leaving lfiglineintersect) lfigdebugprint +} def + +% find point on circumference of polygon +% alpha radius num theta lfigpolycircum x y +/lfigpolycircum +{ + % (Entering lfigpolycircum) lfigdebugprint + 13 dict begin + /theta exch def + /num exch def + /radius exch def + /alpha exch def + + % calculate delta, the angle from theta to alpha + alpha theta sub lfigfixangle + + % calculate the angle which is the multiple of 360/num closest to delta + 360 num div div truncate 360 num div mul theta add /anglea exch def + + % calculate the next multiple of 360/num after anglea + anglea 360 num div add /angleb exch def + + % intersect the line through these two points with the alpha line + anglea cos anglea sin angleb cos angleb sin + 0 0 alpha cos 2 mul alpha sin 2 mul + lfiglineintersect radius lfigpmul + + end + % (Leaving lfigpolycircum) lfigdebugprint +} def + +% find point of intersection of a point and a circle +% x0 y0 r x1 y1 theta lfigcircleintersect xa ya xb yb 2 +% or xb yb 1 +% or 0 +/lfigcircleintersect +{ + % (Entering lfigcircleintersect) lfigdebugprint + 15 dict begin + /theta exch def + /y1 exch def + /x1 exch def + /r exch def + /y0 exch def + /x0 exch def + + % if sin(theta) = 0 then line is horizontal and y must be y1 + theta sin abs 0.00001 lt + { + /a 1 def + /b -2 x0 mul def + /c x0 dup mul y1 y0 sub dup mul add r dup mul sub def + a b c lfigqroots dup + 0 eq + { pop + 0 + } + { 1 eq + { y1 1 + } + { y1 exch y1 2 + } ifelse + } ifelse + } + { + /ct theta cos theta sin div def + /a ct ct mul 1 add def + /b ct x1 x0 sub mul y1 add y0 sub 2 mul def + /c x1 x0 sub dup mul y1 y0 sub dup mul add r dup mul sub def + a b c lfigqroots dup + 0 eq + { pop + 0 + } + { 1 eq + { y1 add /yb exch def + yb y1 sub ct mul x1 add /xb exch def + xb yb 1 + } + { y1 add /ya exch def + ya y1 sub ct mul x1 add /xa exch def + y1 add /yb exch def + yb y1 sub ct mul x1 add /xb exch def + xa ya xb yb 2 + } ifelse + } ifelse + } ifelse + end + % (Leaving lfigcircleintersect) lfigdebugprint +} def + +% add CIRCUM operator with this body: lfigcircumdef - +/lfigcircumdef +{ % (Entering lfigcircumdef) lfigdebugprint + /CIRCUM exch cvx + currentdict end + 3 1 roll + % currentdict length currentdict maxlength lt + % { def } + % { exec moveto (too many labels) show stop } + % ifelse + def + begin + % (Leaving lfigcircumdef) lfigdebugprint +} def + +end +%%EndResource + +%%BeginResource: procset LoutGraphPrependGraphic +% @PrependGraphic file /export/home/6monthspace/jeff/lout.lib/include/graphf.lpg +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PostScript @SysPrependGraphic file for @Graph (Version 1.0) % +% % +% Version 1.0 by Jeffrey H. Kingston, December 1993. % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +errordict begin + /handleerror + { + { /Times-Roman findfont 8 pt scalefont setfont + 0 setgray 4 pt 4 pt moveto + $error /errorname get + dup lgraphdict exch known + { lgraphdict exch get } + { 30 string cvs } ifelse + show + ( Command: ) show + $error /command get 30 string cvs show + } stopped {} if + showpage stop + } def +end + +/lgraphdict 200 dict def +lgraphdict begin + +% error messages +/dictfull (dictfull error) def +/dictstackoverflow (dictstackoverflow error) def +/execstackoverflow (execstackoverflow error: expression too complex?) def +/limitcheck (limitcheck error: graph too complex or too large?) def +/syntaxerror (syntaxerror error: syntax error in text of graph?) def +/typecheck (typecheck error: syntax error in text of graph?) def +/undefined (undefined error: unknown or misspelt symbol?) def +/rangecheck (rangecheck error: undefined expression (e.g. divide by zero)?) def +/VMError (VMError error: run out of memory?) def + +% random number between x and y inclusive: x y dorand num +/dorand { 1 index sub 1 add rand exch mod add } def + +% log to given base: base num dolog num +/dolog { ln exch ln div } def + +% maximum of two numbers: max +/max { 2 copy gt { pop } { exch pop } ifelse } def + +% add two points: padd +/padd { exch 3 1 roll add 3 1 roll add exch } def + +% subtract first point from second: psub +/psub { 3 2 roll sub 3 1 roll exch sub exch } def + +% distance between two points: distance +/distance { psub dup mul exch dup mul add sqrt } def + +% point at angle and distance: atangle +/atangle { 2 copy cos mul 3 1 roll sin mul padd } def + +% angle from one point to another: angle +/angle { psub 2 copy 0 eq exch 0 eq and {pop} {exch atan} ifelse } def + + +% set up for line +% - linesetup +/linesetup +{ newpath + xcurr ycurr trpoint xprev yprev trpoint + 4 copy moveto lineto distance dashlength +} def + +% set up for icon-avoiding line +% - ilinesetup +/ilinesetup +{ newpath + xprev yprev trpoint xcurr ycurr trpoint 4 copy + 4 copy angle symbolsize 1.5 mul exch 4 2 roll pop pop atangle + 6 2 roll 4 2 roll + 4 copy angle symbolsize 1.5 mul exch 4 2 roll pop pop atangle + 4 copy moveto lineto distance dashlength +} def + + +% stroke a solid line: solid - +/solid +{ pop pop [] 0 setdash linewidth setlinewidth stroke +} def + +% stroke a dashed line: dashed - +/dashed +{ 2 copy 2 mul le 1 index 0 le or + { exch pop 1 pt max [ exch dup ] 0 setdash } + { dup [ exch 4 2 roll 2 copy div + 1 sub 2 div ceiling dup 4 1 roll + 1 add mul sub exch div ] 0 setdash + } ifelse linewidth setlinewidth stroke +} def + +% stroke a cdashed line: cdashed - +/cdashed +{ 2 copy le 1 index 0 le or + { exch pop 1 pt max [ exch dup ] dup 0 get 2 div setdash } + { dup [ 4 2 roll exch 2 copy exch div + 2 div ceiling div 1 index sub + ] exch 2 div setdash + } ifelse linewidth setlinewidth stroke +} def + +% stroke a dotted line: dotted - +/dotted +{ 2 copy le 1 index 0 le or + { exch pop 1 pt max [ exch 0 exch ] 0 setdash } + { 1 index exch div ceiling div 0.99999 mul + [ 0 3 2 roll ] 0 setdash + } ifelse gsave 1 setlinecap linewidth setlinewidth stroke grestore newpath +} def + +% stroke a noline line: noline - +/noline +{ pop pop +} def + +% stroke a y histogram: - yhisto - +/yhisto +{ xprev yleft trpoint yextra sub moveto + xprev yprev trpoint lineto + xcurr yprev trpoint lineto + xcurr yleft trpoint yextra sub lineto + linewidth setlinewidth stroke +} def + +% stroke an x histogram: - xhisto - +/xhisto +{ xleft yprev trpoint exch xextra sub exch moveto + xcurr yprev trpoint lineto + xcurr ycurr trpoint lineto + xleft ycurr trpoint exch xextra sub exch lineto + linewidth setlinewidth stroke +} def + +% stroke a surface y histogram: - surfaceyhisto - +/surfaceyhisto +{ firstpair + { xprev yleft trpoint yextra sub moveto + xprev yprev trpoint lineto + } + { xprev yprev trpoint moveto + } ifelse + xcurr yprev trpoint lineto + lastpair + { xcurr yleft trpoint yextra sub lineto + } + { xcurr ycurr trpoint lineto + } ifelse + linewidth setlinewidth stroke +} def + +% stroke a surface x histogram: - surfacexhisto - +/surfacexhisto +{ firstpair + { xleft yprev trpoint exch xextra sub exch moveto + } + { xprev yprev trpoint moveto + } ifelse + xcurr yprev trpoint lineto + xcurr ycurr trpoint lineto + lastpair + { xleft ycurr trpoint exch xextra sub exch lineto + } if + linewidth setlinewidth stroke +} def + +% stroke a filled y histogram: - filledyhisto - +/filledyhisto +{ + linewidth setlinewidth + xprev yleft trpoint exch currentlinewidth 2 div add exch yextra sub moveto + xprev yprev trpoint exch currentlinewidth 2 div add exch lineto + xcurr yprev trpoint exch currentlinewidth 2 div sub exch lineto + xcurr yleft trpoint exch currentlinewidth 2 div sub exch yextra sub lineto + closepath fill +} def + +% stroke a filled x histogram: - filledxhisto - +/filledxhisto +{ + linewidth setlinewidth + xleft yprev trpoint currentlinewidth 2 div add exch xextra sub exch moveto + xcurr yprev trpoint currentlinewidth 2 div add lineto + xcurr ycurr trpoint currentlinewidth 2 div sub lineto + xleft ycurr trpoint currentlinewidth 2 div sub exch xextra sub exch lineto + closepath fill +} def + + +% cross: show a small cross +/cross +{ newpath + xcurr ycurr trpoint moveto + symbolsize neg symbolsize neg rmoveto + symbolsize 2 mul symbolsize 2 mul rlineto + 0 symbolsize -2 mul rmoveto + symbolsize -2 mul symbolsize 2 mul rlineto + [] 0 setdash stroke +} def + +% plus: show a small plus +/plus +{ newpath + xcurr ycurr trpoint moveto + symbolsize neg 0 rmoveto + symbolsize 2 mul 0 rlineto + symbolsize neg symbolsize neg rmoveto + 0 symbolsize 2 mul rlineto + [] 0 setdash stroke +} def + +% square: show a small square +/square +{ newpath + xcurr ycurr trpoint moveto + symbolsize neg symbolsize neg rmoveto + symbolsize 2 mul 0 rlineto + 0 symbolsize 2 mul rlineto + symbolsize -2 mul 0 rlineto + closepath [] 0 setdash stroke +} def + +% filledsquare: show a small filled square +/filledsquare +{ newpath + xcurr ycurr trpoint moveto + symbolsize neg symbolsize neg rmoveto + symbolsize 2 mul 0 rlineto + 0 symbolsize 2 mul rlineto + symbolsize -2 mul 0 rlineto + closepath gsave [] 0 setdash stroke grestore fill +} def + +% diamond: show a small diamond +/diamond +{ newpath + xcurr ycurr trpoint moveto + symbolsize neg 0 rmoveto + symbolsize symbolsize neg rlineto + symbolsize symbolsize rlineto + symbolsize neg symbolsize rlineto + closepath [] 0 setdash stroke +} def + +% filleddiamond: show a small filled diamond +/filleddiamond +{ newpath + xcurr ycurr trpoint moveto + symbolsize neg 0 rmoveto + symbolsize symbolsize neg rlineto + symbolsize symbolsize rlineto + symbolsize neg symbolsize rlineto + closepath gsave [] 0 setdash stroke grestore fill +} def + +% circle: show a small circle +/circle +{ newpath + xcurr ycurr trpoint symbolsize 0 360 arc [] 0 setdash stroke +} def + +% filledcircle: show a small filled circle +/filledcircle +{ newpath + xcurr ycurr trpoint symbolsize 0 360 arc gsave [] 0 setdash stroke grestore fill +} def + +% triangle: show a small triangle +/triangle +{ newpath + xcurr ycurr trpoint moveto + 0 symbolsize 1.5 mul rmoveto + symbolsize neg symbolsize -2.5 mul rlineto + symbolsize 2 mul 0 rlineto + closepath [] 0 setdash stroke +} def + +% filledtriangle: show a small filled triangle +/filledtriangle +{ newpath + xcurr ycurr trpoint moveto + 0 symbolsize 1.5 mul rmoveto + symbolsize neg symbolsize -2.5 mul rlineto + symbolsize 2 mul 0 rlineto + closepath gsave [] 0 setdash stroke grestore fill +} def + + +%plog: like log only with a base, and protected from failing if <= 0 +% base x plog res +/plog { dup 0 le { pop pop 0 } { ln exch ln div } ifelse } def + +% xtr: transform one x value logarithmically if xlog > 1 +% xtr +/xtr +{ xlog 1 gt + { xlog exch plog + } if +} def + +% ytr: transform one y value logarithmically if ylog > 1 +% ytr +/ytr +{ ylog 1 gt + { ylog exch plog + } if +} def + +% % trpoint: transform (x, y) in graph space into (x', y') in print space +% % x y trpoint x' y' +% /trpoint +% { exch xtr trxmin sub trxmax trxmin sub div xwidth mul xextra add +% exch ytr trymin sub trymax trymin sub div ywidth mul yextra add +% } def + + +% trpoint: transform (x, y) in graph space into (x', y') in print space +% x y trpoint x' y' +/trpoint +{ exch xtr xdecr { trxmax exch sub } { trxmin sub } ifelse + trxmax trxmin sub div xwidth mul xextra add + + exch ytr ydecr { trymax exch sub } { trymin sub } ifelse + trymax trymin sub div ywidth mul yextra add +} def + + +% yonly: interpolate x values 1, 2, ... into data +% [ data ] yonly [ newdata ] +/yonly +{ dup /tmp exch def + length [ exch 1 exch 1 exch + { dup tmp exch 1 sub get + } for + ] +} def + +% xonly: interpolate y values 1, 2, ... into data +% [ data ] yonly [ newdata ] +/xonly +{ dup /tmp exch def + length [ exch 1 exch 1 exch + { dup tmp exch 1 sub get exch + } for + ] +} def + +% xandy: no interpolation of x or y values +% [ data ] xandy [ data ] +/xandy {} def + + +% expstringwidth: calculate width of string containing optional exponent +% expstringwidth +/expstringwidth +{ (^) search + { exch pop stringwidth pop exch stringwidth pop 0.7 mul add } + { stringwidth pop } + ifelse +} def + +% expstringshow: show string containing optional exponent +% expstringshow - +/expstringshow +{ (^) search + { exch pop show 0 0.5 ft rmoveto + gsave currentfont 0.7 scalefont setfont show grestore + } + { show + } + ifelse +} def + +% concatenate two strings: strconcat +/strconcat +{ 2 copy length exch length add string + dup 0 4 index putinterval + dup 3 index length 3 index putinterval + 3 1 roll pop pop +} def + +% lgen: generate one label automatically +% num lgen num string +/lgen { dup 20 string cvs } def + +% loglgen: generate one logarithmic label (with exponent) +% loglgen +/loglgen +{ 20 string cvs exch 20 string cvs + (^) strconcat exch strconcat +} def + + +% printxtick: print one x tick +% xpos printxtick - +/printxtick +{ newpath + yleft trpoint moveto 0 yextra neg rmoveto + 0 xticklength neg rlineto [] 0 setdash stroke +} def + +% printxlabel: print one x label +% (xlabel) xpos printxlabel - +/printxlabel +{ yleft trpoint moveto 0 yextra neg rmoveto + 0 xticklength neg rmoveto 0 0.9 ft neg rmoveto + xlog 1 gt { 0 0.3 ft neg rmoveto } if + dup expstringwidth -2 div 0 rmoveto expstringshow +} def + +% printytick: print one y tick +% ypos printytick - +/printytick +{ newpath + xleft exch trpoint moveto xextra neg 0 rmoveto + yticklength neg 0 rlineto [] 0 setdash stroke +} def + +% printylabel: print one y label +% (ylabel) ypos printylabel - +/printylabel +{ xleft exch trpoint moveto xextra neg 0 rmoveto + yticklength neg 0 rmoveto -0.3 ft -0.3 ft rmoveto + dup expstringwidth neg 0 rmoveto expstringshow +} def + +% printrtick: print one r tick +% ypos printrtick - +/printrtick +{ newpath + xright exch trpoint moveto xextra 0 rmoveto + rticklength 0 rlineto [] 0 setdash stroke +} def + +% printrlabel: print one r label +% (rlabel) ypos printrlabel - +/printrlabel +{ xright exch trpoint moveto xextra 0 rmoveto + rticklength 0 rmoveto 0.3 ft -0.3 ft rmoveto + expstringshow +} def + +% printticks: print ticks and labels +% /tickproc /labelproc [ tickandlabeldata ] min printticks - +/printticks +{ /prev exch def + { dup type dup dup /integertype eq exch /realtype eq or + { pop dup /prev exch def 2 index cvx exec + } + { /stringtype eq + { prev 2 index cvx exec + } + { pop + } ifelse + } ifelse + } forall + pop pop +} def + + +% printxaxistick: print one x axis tick +% xpos printxaxistick - +/printxaxistick +{ newpath + yaxis trpoint moveto 0 xticklength -2 div rmoveto + 0 xticklength rlineto [] 0 setdash stroke +} def + +% printxaxislabel: print one x axis label +% (xlabel) xpos printxaxislabel - +/printxaxislabel +{ yaxis trpoint moveto + 0 xticklength -2 div rmoveto 0 0.9 ft neg rmoveto + xlog 1 gt { 0 0.3 ft neg rmoveto } if + dup expstringwidth -2 div 0 rmoveto expstringshow +} def + +% printyaxistick: print one y axis tick +% ypos printyaxistick - +/printyaxistick +{ newpath + xaxis exch trpoint moveto + yticklength -2 div 0 rmoveto + yticklength 0 rlineto [] 0 setdash stroke +} def + +% printyaxislabel: print one y axis label +% (ylabel) ypos printyaxislabel - +/printyaxislabel +{ xaxis exch trpoint moveto + yticklength -2 div 0 rmoveto -0.3 ft -0.3 ft rmoveto + dup expstringwidth neg 0 rmoveto expstringshow +} def + + +% minmax - +% perform minv := min(minv, val); maxv := max(maxv, val) +% allowing for the possibility of minv, maxv, val being false (undefined) +/minmax +{ dup false eq + { pop } + { minv false eq + { dup /minv exch def /maxv exch def } + { dup minv lt + { /minv exch def } + { dup maxv gt + { /maxv exch def } + { pop } + ifelse + } ifelse + } ifelse + } ifelse +} def + +% ticksundef +% returns true iff the ticks array is undefined (one false entry) +/ticksundef +{ dup length 1 eq + { dup 0 get false eq + } + { false } + ifelse +} def + +% integral +% true if the number has an integral value +/integral { dup round eq } def + +% ticksep ticks xory alldata minval maxval axis base ticksandlimits ticks min max base +% ticksandlimits: sort out value of x or y ticks and limits and log base +/ticksandlimits +{ /base exch def + /minv false def + /maxv false def + + % min and max of user-supplied minval, maxval, and axis + minmax minmax minmax + + % min and max of data points + { 0 get dup dup length 1 sub 3 index exch 2 exch + { get minmax dup + } for pop pop + } forall + pop dup + + % min and max of tick values + { dup type /stringtype eq + { pop } { minmax } ifelse + } forall + + % fix minv and maxv if undefined (false) or equal + minv false eq + { /minv -1 def /maxv 1 def } + { minv maxv eq + { minv 0 lt + { /minv 2 minv mul def /maxv 0 def + } + { minv 0 eq + { /minv -1 def /maxv 1 def + } + { /minv 0 def /maxv 2 maxv mul def + } ifelse + } ifelse + } if + } ifelse + + % invent ticks if undefined + ticksundef + { pop /ticksep exch def + + % if base is reasonable and minv is positive, logarithmic ticks + base 1 gt minv 0 gt and + { + % get integral log of minv and maxv + /logminv base minv plog floor cvi def + /logmaxv base maxv plog ceiling cvi def + + % if minv close to base, make it 1; reset minv and maxv + logminv 1 eq logmaxv 4 ge and { /logminv 0 def } if + /minv base logminv exp def + /maxv base logmaxv exp def + + % ticks := [ base**logminv, ... , base**logmaxv ] + [ logminv 1 logmaxv + { dup base exch exp + exch base exch loglgen + } for + ] + } + { % non-logarithmic ticks + { + % fix tick separation if undefined (0) or too small + /base 0 def + /delta maxv minv sub def + ticksep delta 30 div le + { /ticksep 10 delta log 1 sub ceiling exp def + ticksep delta 2 div ge + { /ticksep ticksep 2 div def } + { ticksep delta 5 div lt + { /ticksep 2 ticksep mul def + } if + } ifelse + } if + + % adjust minv and maxv to be multiples of ticksep + /minv minv ticksep div floor ticksep mul def + /maxv maxv ticksep div ceiling ticksep mul def + /delta maxv minv sub def + + % if minv or maxv near zero, move to zero and redo + minv ticksep eq + { /minv 0 def } + { maxv ticksep neg eq { /maxv 0 def } { exit } ifelse + } ifelse + } loop + + % if minv, maxv, and ticksep are all integral, set "makeint" to true + /makeint minv integral maxv integral ticksep integral and and def + + % ticks := [ minv, minv+ticksep, ... , maxv ] + [ 0 1 delta ticksep div round + { ticksep mul minv add makeint { cvi } if lgen } + for + ] + } ifelse + } + { exch pop + } ifelse + minv maxv base +} def + +% xset: set up all data for x axis, including limits and ticks +% xticksep xticks 0 alldata xmin xmax xlog xextra xdecr xaxis xticklength xset - +/xset +{ /xticklength exch def + /xaxis exch def + /xdecr exch def + /xextra exch def + xaxis exch ticksandlimits + /xlog exch def /xmax exch def /xmin exch def /xticks exch def + /xleft xdecr { xmax } { xmin } ifelse def + /xright xdecr { xmin } { xmax } ifelse def + /xwidth xsize xextra 2 mul sub def + /trxmin xmin xtr def /trxmax xmax xtr def +} def + +% yset: set up all data for y axis, including limits and yticks +% yticksep yticks 0 alldata ymin ymax ylog yextra ydecr yaxis yticklength yset - +/yset +{ /yticklength exch def + /yaxis exch def + /ydecr exch def + /yextra exch def + yaxis exch ticksandlimits + /ylog exch def /ymax exch def /ymin exch def /yticks exch def + /yleft ydecr { ymax } { ymin } ifelse def + /yright ydecr { ymin } { ymax } ifelse def + /ywidth ysize yextra 2 mul sub def + /trymin ymin ytr def /trymax ymax ytr def +} def + +% rset: set up all data for y axis (again), but including limits and rticks +% rticksep rticks 0 alldata ymin ymax ylog yextra ydecr yaxis rticklength rset - +/rset +{ /rticklength exch def + /yaxis exch def + /ydecr exch def + /yextra exch def + yaxis exch ticksandlimits + /ylog exch def /ymax exch def /ymin exch def /rticks exch def + /yleft ydecr { ymax } { ymin } ifelse def + /yright ydecr { ymin } { ymax } ifelse def + /ywidth ysize yextra 2 mul sub def + /trymin ymin ytr def /trymax ymax ytr def +} def + +% norset: set up data for no rticks +% - norset - +/norset +{ /rticklength 0 def + /rticks [] def +} def + +% framestyle: print a frame around the graph +/framestyle +{ 0 0 moveto xsize 0 lineto xsize ysize lineto + 0 ysize lineto closepath stroke + /printxtick /printxlabel xticks xleft printticks + /printytick /printylabel yticks ymin printticks + /printrtick /printrlabel rticks ymin printticks +} def + +% nonestyle: print nothing around the graph +/nonestyle +{ +} def + +% axesstyle: print axes for the graph (unless axis values missing) +/axesstyle +{ + xaxis false eq yaxis false eq or + { framestyle } + { xaxis yaxis trpoint dup 0 exch moveto xsize exch lineto + dup 0 moveto ysize lineto stroke + /printxaxistick /printxaxislabel xticks xleft printticks + /printyaxistick /printyaxislabel yticks ymin printticks + } ifelse +} def + +% rundata: run all data sets +/rundata +{ alldata + { gsave + dup dup dup dup + 4 get /dopaint exch def + 3 get /initrun exch def + 2 get /pairs exch def + 1 get /points exch def + 0 get /data exch def + dopaint + { data length 4 ge + { initrun + newpath + data 0 get ymin trpoint yextra sub moveto + 0 2 data length 2 sub + { dup 1 add + data exch get /ycurr exch def + data exch get /xcurr exch def + xcurr ycurr trpoint lineto + } for + data dup length 2 sub get ymin trpoint yextra sub lineto + closepath fill + } if + } if + initrun + data length 2 ge + { + /xcurr data 0 get def + /ycurr data 1 get def + points + data length 4 ge + { 2 2 data length 2 sub + { /xprev xcurr def + /yprev ycurr def + dup dup 2 eq /firstpair exch def + data length 2 sub eq /lastpair exch def + dup 1 add + data exch get /ycurr exch def + data exch get /xcurr exch def + pairs + points + } for + } if + } if + grestore + } forall +} def + +end +%%EndResource + +%%BeginResource: procset LoutFigPrependGraphic +% @PrependGraphic file /export/home/6monthspace/jeff/lout.lib/include/diagf.lpg +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% PostScript @SysPrependGraphic file for @Diag Jeffrey H. Kingston % +% Version 2.0 (includes CIRCUM label) September 1996 % +% % +% To assist in avoiding name clashes, the names of all symbols % +% defined here begin with "ldiag". However, this is not feasible % +% with user-defined labels and some labels used by users. % +% % +% is two numbers, a point. % +% is one number, a length % +% is one number, an angle in degrees % +% is one number, the preferred length of a dash % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +errordict begin + /handleerror + { + { /Times-Roman findfont 8 pt scalefont setfont + 0 setgray 4 pt 4 pt moveto + $error /errorname get + dup ldiagdict exch known + { ldiagdict exch get } + { 50 string cvs } ifelse + show + ( Command: ) show + $error /command get 50 string cvs show + } stopped {} if + showpage stop + } def +end + +% begin diagram: ldiagbegin - +% must be defined outside ldiagdict since it loads it +/ldiagbegin +{ xsize 0 0 ysize ldiagdict begin + 5 -1 roll /ldiagmaxlabels exch def + (@Diag) ldiagpushtagdict + /OOY ldiagpointdef /OOX ldiagpointdef 0 0 /OOO ldiagpointdef +} def + +% end diagram: - ldiagend - +/ldiagend +{ ldiagpoptagdict end +} def + +% concat strings: ldiagconcat +% must be defined outside ldiagdict since used in ldiagpromotelabels +/ldiagconcat +{ 2 copy length exch length add string + dup 0 4 index putinterval + dup 3 index length 3 index putinterval + 3 1 roll pop pop +} def + +/ldiagdebugposy 432 def +/ldiagdebugposx 72 def + +% ldiagdebugprint - +% must be defined outside ldiagdict since used in arbitrary places +% print count or stack entries, which ever is the smaller +/ldiagdebugprint +{ + exch + gsave + initgraphics + ldiagdebugposy 72 lt + { /ldiagdebugposx ldiagdebugposx 144 add store + /ldiagdebugposy 432 store + } + { + /ldiagdebugposy ldiagdebugposy 12 sub store + } ifelse + ldiagdebugposx ldiagdebugposy moveto + /Times-Roman findfont 10 scalefont setfont + 0 setgray show + count 1 sub 2 copy lt { pop } { exch pop } ifelse 1 sub + 0 exch 1 exch + { + /ldiagdebugposy ldiagdebugposy 12 sub store + ldiagdebugposx 12 add ldiagdebugposy moveto + index 50 string cvs show + } for + grestore +} def + +/ldiagdict 200 dict def +ldiagdict begin + +% error messages +/dictfull (dictfull error: too many labels?) def +/dictstackoverflow (dictstackoverflow error: labels nested too deeply?) def +/execstackoverflow (execstackoverflow error: figure nested too deeply?) def +/limitcheck (limitcheck error: figure nested too deeply or too large?) def +/syntaxerror (syntaxerror error: syntax error in text of figure?) def +/typecheck (typecheck error: syntax error in text of figure?) def +/undefined (undefined error: unknown or misspelt label?) def +/VMError (VMError error: run out of memory?) def + +% push pi onto stack: - ldiagpi +/ldiagpi 3.14159 def + +% push e onto stack: - ldiage +/ldiage 2.71828 def + +% arc directions +/clockwise false def +/anticlockwise true def + +% test equality between two angles: ldiagangleeq +/ldiagangleeq { ldiagfixangle exch ldiagfixangle eq } def + +% test inequality between two angles: ldiaganglene +/ldiaganglene { ldiagangleeq not } def + +% maximum of two numbers: ldiagmax +/ldiagmax { 2 copy gt { pop } { exch pop } ifelse } def + +% minimum of two numbers: ldiagmin +/ldiagmin { 2 copy lt { pop } { exch pop } ifelse } def + +% add two points: ldiagpadd +/ldiagpadd +{ + % (Entering padd) 4 ldiagdebugprint + exch 3 1 roll add 3 1 roll add exch + % (Leaving padd) 2 ldiagdebugprint +} def + +% subtract first point from second: ldiagpsub +/ldiagpsub { 3 2 roll sub 3 1 roll exch sub exch } def + +% max two points: ldiagpmax +/ldiagpmax { exch 3 1 roll ldiagmax 3 1 roll ldiagmax exch } def + +% min two points: ldiagpmin +/ldiagpmin { exch 3 1 roll ldiagmin 3 1 roll ldiagmin exch } def + +% scalar multiplication: ldiagpmul +/ldiagpmul { dup 3 1 roll mul 3 1 roll mul exch } def + +% point at angle and distance: ldiagatangle +/ldiagatangle { 2 copy cos mul 3 1 roll sin mul ldiagpadd } def + +% angle from one point to another: ldiagangleto +/ldiagangleto { ldiagpsub 2 copy 0 eq exch 0 eq and {pop} {exch atan} ifelse } def + +% distance between two points: ldiagdistance +/ldiagdistance { ldiagpsub dup mul exch dup mul add sqrt } def + +% stroke a solid line: ldiagsolid - +/ldiagsolid +{ pop pop [] 0 setdash 1 setlinecap stroke +} def + +% stroke a dashed line: ldiagdashed - +/ldiagdashed +{ 2 copy div 2 le 1 index 0 le or + { exch pop 1 pt ldiagmax [ exch dup ] 0 setdash } + { dup [ exch 4 2 roll 2 copy div + 1 sub 2 div ceiling dup 4 1 roll + 1 add mul sub exch div ] 0 setdash + } ifelse 0 setlinecap stroke +} def + +% stroke a cdashed line: ldiagcdashed - +/ldiagcdashed +{ % (Entering ldiagcdashed) 2 ldiagdebugprint + 2 copy le 1 index 0 le or + { exch pop 1 pt ldiagmax [ exch dup ] dup 0 get 2 div setdash } + { dup [ 4 2 roll exch 2 copy exch div + 2 div ceiling div 1 index sub + ] exch 2 div setdash + } ifelse 0 setlinecap stroke + % (Leaving ldiagcdashed) 0 ldiagdebugprint +} def + +% stroke a dotted line: ldiagdotted - +/ldiagdotted +{ 2 copy le 1 index 0 le or + { exch pop 1 pt ldiagmax [ exch 0 exch ] 0 setdash } + { 1 index exch div ceiling div + [ 0 3 2 roll ] 0 setdash + } ifelse 1 setlinecap stroke +} def + +% stroke a noline line: ldiagnoline - +/ldiagnoline +{ pop pop +} def + +% painting (i.e. filling): - ldiagwhite - (etc.) +/ldiagnopaint { } def +/ldiagnochange { fill } def +/ldiagdarkblue { 0.0 0.0 0.5 setrgbcolor fill } def +/ldiagblue { 0.0 0.0 1.0 setrgbcolor fill } def +/ldiaglightblue { 0.5 0.5 1.0 setrgbcolor fill } def +/ldiagdarkgreen { 0.0 0.5 0.0 setrgbcolor fill } def +/ldiaggreen { 0.0 1.0 0.0 setrgbcolor fill } def +/ldiaglightgreen { 0.5 1.0 0.5 setrgbcolor fill } def +/ldiagdarkred { 0.5 0.0 0.0 setrgbcolor fill } def +/ldiagred { 1.0 0.0 0.0 setrgbcolor fill } def +/ldiaglightred { 1.0 0.5 0.5 setrgbcolor fill } def +/ldiagdarkcyan { 0.0 0.5 0.5 setrgbcolor fill } def +/ldiagcyan { 0.0 1.0 1.0 setrgbcolor fill } def +/ldiaglightcyan { 0.5 1.0 1.0 setrgbcolor fill } def +/ldiagdarkmagenta { 0.5 0.0 0.5 setrgbcolor fill } def +/ldiagmagenta { 1.0 0.0 1.0 setrgbcolor fill } def +/ldiaglightmagenta { 1.0 0.5 1.0 setrgbcolor fill } def +/ldiagdarkyellow { 0.5 0.5 0.0 setrgbcolor fill } def +/ldiagyellow { 1.0 1.0 0.0 setrgbcolor fill } def +/ldiaglightyellow { 1.0 1.0 0.5 setrgbcolor fill } def +/ldiagdarkgray { 0.2 0.2 0.2 setrgbcolor fill } def +/ldiaggray { 0.5 0.5 0.5 setrgbcolor fill } def +/ldiaglightgray { 0.8 0.8 0.8 setrgbcolor fill } def +/ldiagdarkgrey { 0.2 0.2 0.2 setrgbcolor fill } def +/ldiaggrey { 0.5 0.5 0.5 setrgbcolor fill } def +/ldiaglightgrey { 0.8 0.8 0.8 setrgbcolor fill } def +/ldiagblack { 0.0 0.0 0.0 setrgbcolor fill } def +/ldiagwhite { 1.0 1.0 1.0 setrgbcolor fill } def + +% shape and labels of the @Box symbol +/ldiagbox +{ + 0 0 /SW ldiagpointdef + xsize 0 /SE ldiagpointdef + xsize ysize /NE ldiagpointdef + 0 ysize /NW ldiagpointdef + SE 0.5 ldiagpmul /S ldiagpointdef + NW 0.5 ldiagpmul /W ldiagpointdef + W SE ldiagpadd /E ldiagpointdef + S NW ldiagpadd /N ldiagpointdef + NE 0.5 ldiagpmul /CTR ldiagpointdef + + 0 dg /S@ANGLE ldiagangledef + 45 dg /SE@ANGLE ldiagangledef + 90 dg /E@ANGLE ldiagangledef + 135 dg /NE@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 225 dg /NW@ANGLE ldiagangledef + 270 dg /W@ANGLE ldiagangledef + 315 dg /SW@ANGLE ldiagangledef + + [ CTR NE ldiagpsub /ldiagboxcircum cvx ] ldiagcircumdef + SW SE NE NW SW +} def + +% shape and labels of the @CurveBox symbol +% ldiagcurvebox +/ldiagcurvebox +{ + + % (Entering ldiagcurvebox) 1 ldiagdebugprint + ldiagdecodelength /cbmgn exch def + + xsize 0.5 mul ysize 0.5 mul /CTR ldiagpointdef + xsize 0.5 mul 0 /S ldiagpointdef + xsize ysize 0.5 mul /E ldiagpointdef + xsize 0.5 mul ysize /N ldiagpointdef + 0 ysize 0.5 mul /W ldiagpointdef + + cbmgn 0.293 mul cbmgn 0.293 mul /SW ldiagpointdef + xsize cbmgn 0.293 mul sub cbmgn 0.293 mul /SE ldiagpointdef + xsize cbmgn 0.293 mul sub ysize cbmgn 0.293 mul sub /NE ldiagpointdef + cbmgn 0.293 mul ysize cbmgn 0.293 mul sub /NW ldiagpointdef + + 0 dg /S@ANGLE ldiagangledef + 45 dg /SE@ANGLE ldiagangledef + 90 dg /E@ANGLE ldiagangledef + 135 dg /NE@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 225 dg /NW@ANGLE ldiagangledef + 270 dg /W@ANGLE ldiagangledef + 315 dg /SW@ANGLE ldiagangledef + + [ xsize ysize 0.5 ldiagpmul cbmgn /ldiagcurveboxcircum cvx ] ldiagcircumdef + + cbmgn 0 + xsize cbmgn sub 0 + [ xsize cbmgn sub cbmgn ] + xsize cbmgn + xsize ysize cbmgn sub + [ xsize cbmgn sub ysize cbmgn sub ] + xsize cbmgn sub ysize + cbmgn ysize + [ cbmgn ysize cbmgn sub ] + 0 ysize cbmgn sub + 0 cbmgn + [ cbmgn cbmgn ] + cbmgn 0 + + % (Leaving ldiagcurvebox) 0 ldiagdebugprint +} def + +% shadow of the @ShadowBox symbol +% its shape and labels are done, somewhat inaccurately, with ldiagbox +% ldiagshadow - +/ldiagshadow +{ + /lfshm exch def + + lfshm 0 moveto + 0 lfshm neg rlineto + xsize 0 rlineto + 0 ysize rlineto + lfshm neg 0 rlineto + xsize 0 lineto + closepath fill + +} def + +% shape and labels of the @Square symbol +/ldiagsquare +{ + xsize ysize 0.5 ldiagpmul /CTR ldiagpointdef + CTR xsize xsize ysize ysize ldiagpmax 0.5 ldiagpmul ldiagpadd /NE ldiagpointdef + CTR 0 0 CTR NE ldiagdistance 135 ldiagatangle ldiagpadd /NW ldiagpointdef + CTR 0 0 CTR NE ldiagdistance 225 ldiagatangle ldiagpadd /SW ldiagpointdef + CTR 0 0 CTR NE ldiagdistance 315 ldiagatangle ldiagpadd /SE ldiagpointdef + SW 0.5 ldiagpmul SE 0.5 ldiagpmul ldiagpadd /S ldiagpointdef + NW 0.5 ldiagpmul NE 0.5 ldiagpmul ldiagpadd /N ldiagpointdef + SW 0.5 ldiagpmul NW 0.5 ldiagpmul ldiagpadd /W ldiagpointdef + SE 0.5 ldiagpmul NE 0.5 ldiagpmul ldiagpadd /E ldiagpointdef + + 0 dg /S@ANGLE ldiagangledef + 45 dg /SE@ANGLE ldiagangledef + 90 dg /E@ANGLE ldiagangledef + 135 dg /NE@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 225 dg /NW@ANGLE ldiagangledef + 270 dg /W@ANGLE ldiagangledef + 315 dg /SW@ANGLE ldiagangledef + + [ CTR NE ldiagpsub /ldiagboxcircum cvx ] ldiagcircumdef + SW SE NE NW SW +} def + +% shape and labels of the @Diamond symbol +/ldiagdiamond +{ + xsize 0 0.5 ldiagpmul /S ldiagpointdef + 0 ysize 0.5 ldiagpmul /W ldiagpointdef + S W ldiagpadd /CTR ldiagpointdef + CTR W ldiagpadd /N ldiagpointdef + CTR S ldiagpadd /E ldiagpointdef + E N ldiagpadd 0.5 ldiagpmul /NE ldiagpointdef + N W ldiagpadd 0.5 ldiagpmul /NW ldiagpointdef + S W ldiagpadd 0.5 ldiagpmul /SW ldiagpointdef + S E ldiagpadd 0.5 ldiagpmul /SE ldiagpointdef + + 0 dg /S@ANGLE ldiagangledef + 90 dg /E@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 270 dg /W@ANGLE ldiagangledef + S E ldiagangleto /SE@ANGLE ldiagangledef + E N ldiagangleto /NE@ANGLE ldiagangledef + N W ldiagangleto /NW@ANGLE ldiagangledef + W S ldiagangleto /SW@ANGLE ldiagangledef + + [ xsize ysize 0.5 ldiagpmul /ldiagdiamondcircum cvx ] ldiagcircumdef + S E N W S +} def + +% shape and labels of the @Ellipse symbol +/ldiagellipse +{ + xsize 0 0.5 ldiagpmul /S ldiagpointdef + 0 ysize 0.5 ldiagpmul /W ldiagpointdef + S W ldiagpadd /CTR ldiagpointdef + CTR W ldiagpadd /N ldiagpointdef + CTR S ldiagpadd /E ldiagpointdef + CTR xsize 0 0.3536 ldiagpmul ldiagpadd 0 ysize 0.3536 ldiagpmul ldiagpadd /NE ldiagpointdef + 0 ysize 0.3536 ldiagpmul CTR xsize 0 0.3536 ldiagpmul ldiagpadd ldiagpsub /SE ldiagpointdef + xsize 0 0.3536 ldiagpmul CTR ldiagpsub 0 ysize 0.3536 ldiagpmul ldiagpadd /NW ldiagpointdef + 0 ysize 0.3536 ldiagpmul xsize 0 0.3536 ldiagpmul CTR ldiagpsub ldiagpsub /SW ldiagpointdef + [ xsize ysize 0.5 ldiagpmul /ldiagellipsecircum cvx ] ldiagcircumdef + + 0 dg /S@ANGLE ldiagangledef + 90 dg /E@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 270 dg /W@ANGLE ldiagangledef + + S E ldiagangleto /SE@ANGLE ldiagangledef + E N ldiagangleto /NE@ANGLE ldiagangledef + N W ldiagangleto /NW@ANGLE ldiagangledef + W S ldiagangleto /SW@ANGLE ldiagangledef + + S [ CTR ] E [ CTR ] N [ CTR ] W [ CTR ] S +} def + +% shape and labels of the @Circle symbol +/ldiagcircle +{ + xsize ysize 0.5 ldiagpmul /CTR ldiagpointdef + CTR xsize 0 ysize 0 ldiagpmax 0.5 ldiagpmul ldiagpadd /E ldiagpointdef + CTR 0 0 CTR E ldiagdistance 45 ldiagatangle ldiagpadd /NE ldiagpointdef + CTR 0 0 CTR E ldiagdistance 90 ldiagatangle ldiagpadd /N ldiagpointdef + CTR 0 0 CTR E ldiagdistance 135 ldiagatangle ldiagpadd /NW ldiagpointdef + CTR 0 0 CTR E ldiagdistance 180 ldiagatangle ldiagpadd /W ldiagpointdef + CTR 0 0 CTR E ldiagdistance 225 ldiagatangle ldiagpadd /SW ldiagpointdef + CTR 0 0 CTR E ldiagdistance 270 ldiagatangle ldiagpadd /S ldiagpointdef + CTR 0 0 CTR E ldiagdistance 315 ldiagatangle ldiagpadd /SE ldiagpointdef + [ S E ldiagpsub /ldiagellipsecircum cvx ] ldiagcircumdef + + 0 dg /S@ANGLE ldiagangledef + 45 dg /SE@ANGLE ldiagangledef + 90 dg /E@ANGLE ldiagangledef + 135 dg /NE@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 225 dg /NW@ANGLE ldiagangledef + 270 dg /W@ANGLE ldiagangledef + 315 dg /SW@ANGLE ldiagangledef + + S [ CTR ] E [ CTR ] N [ CTR ] W [ CTR ] S +} def + +% shape and labels of the @VLine and @VArrow symbols +/ldiagvline +{ + xmark ysize ldiagprevious /FROM ldiagpointdef + xmark 0 ldiagprevious /TO ldiagpointdef +} def + +% points of a polygon around base with given no of sides, vert init angle: +% ldiagpolygon ... +/ldiagpolygon +{ exch round cvi exch + xsize ysize 0.5 ldiagpmul /CTR ldiagpointdef + 90 sub CTR 2 copy ldiagmax 5 3 roll + [ 4 copy pop /ldiagpolycircum cvx ] ldiagcircumdef + exch dup 360 exch div exch + 1 1 3 2 roll + { 4 string cvs (P) exch ldiagconcat + 3 copy exch pop (@ANGLE) ldiagconcat cvn exch 90 add exch ldiagangledef + cvn 6 copy pop pop ldiagatangle 2 copy 10 2 roll + 3 2 roll ldiagpointdef + dup 3 1 roll add exch + } for + pop ldiagatangle +} def + +% shape and labels of the @Isosceles triangle symbol +/ldiagisosceles +{ + xsize ysize 0.5 ldiagpmul /CTR ldiagpointdef + 0 0 /SW ldiagpointdef + xsize 0 /SE ldiagpointdef + xsize 0.5 mul ysize /N ldiagpointdef + xsize 0.5 mul 0 /S ldiagpointdef + SE 0.5 ldiagpmul N 0.5 ldiagpmul ldiagpadd /NE ldiagpointdef + SW 0.5 ldiagpmul N 0.5 ldiagpmul ldiagpadd /NW ldiagpointdef + + [ xsize ysize /ldiagisoscelescircum cvx ] ldiagcircumdef + + 0 dg /SW@ANGLE ldiagangledef + 0 dg /SE@ANGLE ldiagangledef + 180 dg /N@ANGLE ldiagangledef + 0 dg /S@ANGLE ldiagangledef + SE N ldiagangleto /NE@ANGLE ldiagangledef + N SW ldiagangleto /NW@ANGLE ldiagangledef + + SW SE N SW +} def + +% next array element: ldiaggetnext true +% or false +/ldiaggetnext +{ 2 copy exch length ge + { false } + { 2 copy get exch 1 add exch true } ifelse +} def + +% check whether thing is number: ldiagisnumbertype +/ldiagisnumbertype +{ dup type dup + /integertype eq exch /realtype eq or +} def + +% check whether thing is an array: ldiagisarraytype +/ldiagisarraytype { dup type /arraytype eq } def + +% check whether thing is an array: ldiagisnametype +/ldiagisnametype { dup type /nametype eq } def + +% get next item: ldiaggetnextitem 0 +% or 1 +% or 2 +/ldiaggetnextitem +{ ldiaggetnext + { ldiagisarraytype + { 1 + } + { ldiagisnumbertype + { 3 1 roll + ldiaggetnext + { ldiagisnumbertype + { 4 3 roll exch 2 + } + { pop 3 2 roll pop 0 + } ifelse + } + { 3 2 roll pop 0 + } ifelse + } + { pop 0 + } ifelse + } ifelse + } + { 0 + } ifelse +} def + +% approximate equality: num1 num2 approxeq +/approxeq +{ dup 0 eq + { pop 0 eq + } + { dup 3 1 roll sub exch div abs 0.001 lt + } ifelse +} def + +% set arc path: bool x1 y1 x2 y2 x0 y0 ldiagsetarc +% the path goes from x1 y1 to x2 y2 about centre x0 y0, +% anticlockwise if bool is true else clockwise. +% The orientations of backwards pointing and forwards pointing +% arrowheads are returned in the two angles, and +% the length of the arc is returned in . +/ldiagsetarc +{ + % (Entering ldiagsetarc) 7 ldiagdebugprint + 20 dict begin + matrix currentmatrix 8 1 roll + 2 copy translate 2 copy 8 2 roll + 4 2 roll ldiagpsub 6 2 roll ldiagpsub + dup /y1 exch def dup mul /y1s exch def + dup /x1 exch def dup mul /x1s exch def + dup /y2 exch def dup mul /y2s exch def + dup /x2 exch def dup mul /x2s exch def + /dist1 0 0 x1 y1 ldiagdistance def + /dist2 0 0 x2 y2 ldiagdistance def + + y1s y2s approxeq + { -1 + } + { y1s x2s mul y2s x1s mul sub y1s y2s sub div + } ifelse + /da exch def + + x1s x2s approxeq + { -1 + } + { x1s y2s mul x2s y1s mul sub x1s x2s sub div + } ifelse + /db exch def + + da 0 gt db 0 gt and + { + % ( case 1, ellipse) 0 ldiagdebugprint + /LMax da sqrt db sqrt ldiagmax def + /scalex da sqrt LMax div def + /scaley db sqrt LMax div def + scalex scaley scale + 0 0 LMax + 0 0 x1 scalex mul y1 scaley mul ldiagangleto + 0 0 x2 scalex mul y2 scaley mul ldiagangleto + 2 copy eq { 360 add } if + 2 copy 8 2 roll + 5 index { arc } { arcn } ifelse + 2 index 1 index + { 90 sub } { 90 add } ifelse + dup sin scaley mul exch cos scalex mul atan + 2 index 2 index + { 90 add } { 90 sub } ifelse + dup sin scaley mul exch cos scalex mul atan + 5 2 roll % res1 res2 ang1 ang2 anticlockwise + { exch sub } { sub } ifelse + dup 0 le { 360 add } if ldiagpi mul LMax mul 180 div + } + { + dist1 dist2 approxeq + % x1 y1 dist1 ( x1 y1, d) 3 ldiagdebugprint pop pop pop + % x2 y2 dist2 ( x2 y2, d) 3 ldiagdebugprint pop pop pop + { + % ( case 2, circle) 0 ldiagdebugprint + 0 0 + dist1 + 0 0 x1 y1 ldiagangleto + 0 0 x2 y2 ldiagangleto + 2 copy eq { 360 add } if + 2 copy 8 2 roll + 5 index { arc } { arcn } ifelse + 2 index 1 index + { 90 sub } { 90 add } ifelse + 2 index 2 index + { 90 add } { 90 sub } ifelse + 5 2 roll % res1 res2 ang1 ang2 clockwise + { exch sub } { sub } ifelse + dup 0 le { 360 add } if + ldiagpi mul dist1 mul 180 div + } + { + % ( case 3, line) 0 ldiagdebugprint + x2 y2 lineto pop + x2 y2 x1 y1 ldiagangleto + x1 y1 x2 y2 ldiagangleto + x1 y1 x2 y2 ldiagdistance + } ifelse + } ifelse + 4 -1 roll setmatrix + end + % (Leaving ldiagsetarc) 3 ldiagdebugprint +} def + +% ldiagsetcurve: set up a Bezier curve from x0 y0 to x3 y3 +% and return arrowhead angles and length of curve (actually 0) +% x0 y0 x1 y1 x2 y2 x3 y3 ldiagsetcurve +/ldiagsetcurve +{ 8 copy curveto pop pop + ldiagangleto + 5 1 roll + 4 2 roll ldiagangleto + exch + 0 +} def + +% ldiagsetpath: convert a Diag path into a PostScript path +% [ shape ] ldiagsetpath +/ldiagsetpath +{ + 10 dict begin + 0 newpath + /prevseen false def + /curveseen false def + { ldiaggetnextitem + dup 0 eq { pop exit } + { 1 eq + { /curveseen true def + /curve exch def + curve length 0 eq { /curveseen false def } if + } + { /ycurr exch def + /xcurr exch def + prevseen + { curveseen + { curve length 4 eq + { xprev yprev + curve 0 get curve 1 get + curve 2 get curve 3 get + xcurr ycurr + ldiagsetcurve pop pop pop + } + { xprev yprev xcurr ycurr + curve length 1 ge { curve 0 get } { 0 } ifelse + curve length 2 ge { curve 1 get } { 0 } ifelse + curve length 3 ge { curve 2 get } { true } ifelse + 7 1 roll + ldiagsetarc pop pop pop + } ifelse + } + { xcurr ycurr lineto + } ifelse + } + { xcurr ycurr moveto + } ifelse + /xprev xcurr def + /yprev ycurr def + /prevseen true def + /curveseen false def + } ifelse + } ifelse + } loop pop pop + end +} def + +% ldiagpaintpath: paint a path of the given shape +% /paint [ shape ] ldiagpaintpath - +/ldiagpaintpath +{ + ldiagsetpath cvx exec +} def + +% stroke a path of the given shape in the given linestyle and dash length. +% Return the origin and angle of the backward and forward arrow heads. +% dashlength /linestyle [shape] ldiagdopath [ ] [ ] +/ldiagdopath +{ + 10 dict begin + 0 + /prevseen false def + /curveseen false def + /backarrow [] def + /fwdarrow [] def + { + ldiaggetnextitem + dup 0 eq { pop exit } + { + 1 eq + { /curveseen true def + /curve exch def + curve length 0 eq { /prevseen false def } if + } + { /ycurr exch def + /xcurr exch def + prevseen + { newpath xprev yprev moveto + curveseen + { curve length 4 eq + { xprev yprev + curve 0 get curve 1 get + curve 2 get curve 3 get + xcurr ycurr ldiagsetcurve + } + { xprev yprev xcurr ycurr + curve length 1 ge { curve 0 get } { 0 } ifelse + curve length 2 ge { curve 1 get } { 0 } ifelse + curve length 3 ge { curve 2 get } { true } ifelse + 7 1 roll + ldiagsetarc + } ifelse + } + { xcurr ycurr lineto + xcurr ycurr xprev yprev ldiagangleto dup 180 sub + xprev yprev xcurr ycurr ldiagdistance + } ifelse + 6 index 6 index cvx exec + [ xprev yprev 5 -1 roll ] + backarrow length 0 eq + { /backarrow exch def } + { pop } ifelse + [ xcurr ycurr 4 -1 roll ] /fwdarrow exch def + } if + /xprev xcurr def + /yprev ycurr def + /prevseen true def + /curveseen false def + } ifelse + } ifelse + } loop + pop pop pop pop + backarrow length 0 eq { [ 0 0 0 ] } { backarrow } ifelse + fwdarrow length 0 eq { [ 0 0 0 ] } { fwdarrow } ifelse + end +} def + + +% stroke a path of the given shape in the given linestyle and dash length. +% dashlength [ /linestyle ] [shape] ldiagdosegpath - +/ldiagdosegpath +{ + 12 dict begin + 1 index /seg exch def + 1 index length /seglength exch def + 0 /segcount exch def + 0 + /prevseen false def + /curveseen false def + /backarrow [] def + /fwdarrow [] def + { + ldiaggetnextitem + dup 0 eq { pop exit } + { + 1 eq + { /curveseen true def + /curve exch def + curve length 0 eq { /prevseen false def } if + } + { /ycurr exch def + /xcurr exch def + prevseen + { newpath xprev yprev moveto + curveseen + { curve length 4 eq + { xprev yprev + curve 0 get curve 1 get + curve 2 get curve 3 get + xcurr ycurr ldiagsetcurve + } + { xprev yprev xcurr ycurr + curve length 1 ge { curve 0 get } { 0 } ifelse + curve length 2 ge { curve 1 get } { 0 } ifelse + curve length 3 ge { curve 2 get } { true } ifelse + 7 1 roll + ldiagsetarc + } ifelse + } + { xcurr ycurr lineto + xcurr ycurr xprev yprev ldiagangleto dup 180 sub + xprev yprev xcurr ycurr ldiagdistance + } ifelse + 6 index seg segcount seglength mod get cvx exec + /segcount segcount 1 add def + [ xprev yprev 5 -1 roll ] + backarrow length 0 eq + { /backarrow exch def } + { pop } ifelse + [ xcurr ycurr 4 -1 roll ] /fwdarrow exch def + } if + /xprev xcurr def + /yprev ycurr def + /prevseen true def + /curveseen false def + } ifelse + } ifelse + } loop + pop pop pop pop + end +} def + +% ldiagnodebegin: start of node parameters +% ldiagnodebegin - +/ldiagnodebegin +{ % (Entering ldiagnodebegin) 0 ldiagdebugprint + ldiagmaxlabels dict begin +} def + +% ldiagnodeend: end of node parameters (so do the node) +%