diff options
author | rsc <devnull@localhost> | 2004-05-15 23:24:00 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-05-15 23:24:00 +0000 |
commit | 5cedca1b69d020c32466f70843a11767773d7e3b (patch) | |
tree | a15a3d84e92aa262543b0010763a5e6920c9ba24 /src/cmd/troff | |
parent | 76e6aca867e3e48ea04fbcf7284c45369a69829e (diff) | |
download | plan9port-5cedca1b69d020c32466f70843a11767773d7e3b.tar.gz plan9port-5cedca1b69d020c32466f70843a11767773d7e3b.tar.bz2 plan9port-5cedca1b69d020c32466f70843a11767773d7e3b.zip |
Let's try this. It's BUGGERED.
Diffstat (limited to 'src/cmd/troff')
-rw-r--r-- | src/cmd/troff/FIXES | 821 | ||||
-rw-r--r-- | src/cmd/troff/README | 31 | ||||
-rw-r--r-- | src/cmd/troff/cvt | 45 | ||||
-rw-r--r-- | src/cmd/troff/dwbinit.c | 313 | ||||
-rw-r--r-- | src/cmd/troff/dwbinit.h | 19 | ||||
-rw-r--r-- | src/cmd/troff/ext.h | 184 | ||||
-rw-r--r-- | src/cmd/troff/find | 1 | ||||
-rw-r--r-- | src/cmd/troff/fns.h | 384 | ||||
-rw-r--r-- | src/cmd/troff/hytab.c | 126 | ||||
-rw-r--r-- | src/cmd/troff/mbwc.c | 165 | ||||
-rw-r--r-- | src/cmd/troff/mk.log | 136 | ||||
-rw-r--r-- | src/cmd/troff/mkfile | 58 | ||||
-rw-r--r-- | src/cmd/troff/n1.c | 1136 | ||||
-rw-r--r-- | src/cmd/troff/n10.c | 549 | ||||
-rw-r--r-- | src/cmd/troff/n2.c | 325 | ||||
-rw-r--r-- | src/cmd/troff/n3.c | 954 | ||||
-rw-r--r-- | src/cmd/troff/n4.c | 828 | ||||
-rw-r--r-- | src/cmd/troff/n5.c | 1149 | ||||
-rw-r--r-- | src/cmd/troff/n6.c | 362 | ||||
-rw-r--r-- | src/cmd/troff/n7.c | 834 | ||||
-rw-r--r-- | src/cmd/troff/n8.c | 540 | ||||
-rw-r--r-- | src/cmd/troff/n9.c | 488 | ||||
-rw-r--r-- | src/cmd/troff/ni.c | 390 | ||||
-rw-r--r-- | src/cmd/troff/suftab.c | 612 | ||||
-rw-r--r-- | src/cmd/troff/t10.c | 512 | ||||
-rw-r--r-- | src/cmd/troff/t11.c | 255 | ||||
-rw-r--r-- | src/cmd/troff/t6.c | 881 | ||||
-rw-r--r-- | src/cmd/troff/tdef.h | 670 | ||||
-rw-r--r-- | src/cmd/troff/unansi | 49 |
29 files changed, 12817 insertions, 0 deletions
diff --git a/src/cmd/troff/FIXES b/src/cmd/troff/FIXES new file mode 100644 index 00000000..5765832c --- /dev/null +++ b/src/cmd/troff/FIXES @@ -0,0 +1,821 @@ +March 11, 1994 + + If we are just plain old nroff (and not doing UNICODE) we should + only Lookup characters, not Install when we don't know them. + If we are troff, we Install them anyway + +March 8, 1994 + + Nroff had problems with parsing quoted white space as options or + character code in some terminals tables. Changed by having scanf + include white space when necessary as suggested by Rich. + +March 1, 1994 + + Made sanity check for terminal type depending on the trace level; + trace level set with -tn flag at start up + +22 Feb, 1994 + + More pointer shuffling fixes. + +18 Feb, 1994 + + More disabling of multibyte stuff. Fixed bug in n5.c: casetm didn' + know about the new format in the fontables. + +Feb 17, 1994 + + Removed extra include <setlocale> from n1.c + + Fixed dubious pointer shuffling in n7.c, t10.c & n8.c. Thanks Rich! + +Feb 10, 1994 + + Disabled the multybyte stuff; only plan 9 will get it. + +Jan 24, 1994 + + Fixed nasty bug discovered by td, which caused core dumps on + \D'l-0.002775i 0i' and apparently all numbers closer to 0 + than -.002775. Fixed in storeline() and storeword() (n7.c). + +Dec 16, 1993 + + nroff & troff -N were looking for the TYPESETTER variable, causing + + troff: cannot open /sys/lib/troff/term/tab.202; line 1, file stdin + + fixed my moving getenv("TYPESETTER") to t10.c in t_ptinit(void). + +Dec 3, 1993: + + The sequence \s+2\H'+10' came sometimes out in the wrong order + (x H before s), so there wasn't a difference bewteen \s+2\H'+10' + and \H'+10'\s+2. Now the fonts bits of the CHARHT are used to + register the current pontsize, so we can issue a s10 in t10.c + if needed. A bit sneaky. + + Try to prevent double slashes in path names. Especially under + plan9 things started to look ugly. + + Exception word list now grows dynamic. + +Nov 30, 1993: + + Allow multiple calls to .pi, requested by Rob. + .pi cat + .pi dogs + is now equivalent with + .pi cat | dogs + + + .ab now takes also optional error code: + .ab [n] [string] + If n and string, n is exit code, string is message + If n, n is exit code, ``User Abort, exit code n" is message + If !n and string, standard exit code, string is message + If !n and ! string, standard exit code, "User Abort" is message + +Nov 24, 1993: + + Reordered code to keep the UNASNI scripts happy. + + Nroff dumped core reading terminal tables: apparenty under plan 9, + scanf includes the '\n'; added test for '\0' in parse in n10.c. + + Relative tab settings (.ta +1C +2C) didn't work; anding the + previous value with TABMASK fixes this (caseta). + +Nov 23, 1993: + + Included code, originally done by bwk for plan 9, to handle + multi-byte characters. + +Nov 3, 1993: + + ``pair internal'' two char names by shifting 16 bits. Will allow + the use of 16 bit characters sets (Unicode in plan9 etc.) for + macro's etc. + +Oct 20, 1993: + + Word & line buffers are now dynamic: No more word or line overflow + unless when we run out of memory. + +Oct 11, 1993: + + lost diversion warning pops up regularly with man macro's. Due + to a possible macro coding problem. Triggered by something like + troff -man: + .TP + .TP + foo + .ex + Minimal code: + .di aa + throw away this diversion (aa) while being defined. + .rm aa + .br + .di + + Fixed by disallowing .rm to throw away current diversion. The + rn request will complain with: + + cannot remove diversion aa during definition; etc. + +Sep 29, 1993: + + Some long standing fixes which never went back in the source. + Thanks to Janet & Rich. + +Sep 28, 1993: + + Changed getach() (n1.c), so it does't consider truncated + special characters as (8-bit) ascii. STX ETX ENQ ACK and BELL + are still allowed for the ultimate backwards compatibility. + + Some code changes, so real ANSI compilers like the SGI version + (acc from Sun is a poor excuse for an ANSI compiler) don't + barf. Some compromises (static Tchar wbuf in n9.c) allowed so + the unansified stuff for non-ansi compilers (cc on Sun's) will + work as well. + +Sep 9, 1993: + + Be nice to Gerard. Now also word spaces in .tl and after + tabs/fleids etc. + +Aug 12, 1993: + + Tabs setting can now be humongous. We also allow 99 tabs to + accomodate tbl. As a side effect, NTM buffers are now 1K + +Aug 11, 1993: + + .R register, now contains maximum number of addessable + registers minus the number actually used. + + Small esthetic changes in error messages; removed a statement + which wasn't reached anyway. + +Aug 10, 1993: + + Some more speed hacks: be smarter doing the linear table + lookups in alloc() and finds(). + + The real name of the det diversion size macro is now gd. + +Aug 9, 1993: + + A much faster way to find the end of a string/macro, by + remembering that when defined. + +Aug 6, 1993: + + Slightly more eficient way of skipping to the end of a + string/macro + +Aug 5, 1993: + + Prevent character sign extension for 8-bit charnames diversions + etc. by unpair + +Aug 4, 1993: + + Growing the dynamical macro/strings name space and registers + space (See the experiment of 21 July) now with bigger + increments. Casts added to satisfy non-ANSI compilers. + +Aug 3, 1993: + + Should check return value in alloc (n3.c), to prevent core dump + when memory gets tight. + +July 28, 1993: + + New request: .sg <div> sets the dn and dl registers to the size + of the diversion named in the argument. Doesn't do anything + when the named diversion doesn't exist. The name sg is + temporary until we find a better one. + +July 21, 1993: + + Experiment: Macro space & registers name allocated + dynamically. Note that current reallocation occurs in + increments of 1, to force the code to be executed a lot; a kind + of stress testing. Also, eight bit characters allowed in + macro/string names. + +July 21, 1993: + + Turn on the escape mode if the end macro is called. + +July 20, 1993: + + Tracing mode now default off + + Don't print s stackdump either when a file specfied on the + command line argument cannot be opened + +July 15, 1993: + + Don't print useless line & current file informations when a + file specfied on the command line argument cannot be opened. + + Sun ansi compiler doesn't default adhere to standards. Undid + the kludge in tdef.h + +July 14, 1993: + + Coding error made the tab type R not function properly + +July 12, 1993: + + Fixed a typo in the version stuff, noticed by Rich + +July 9, 1993: + + Added the dwb home configuration stuff, thanks RIch. Also, + NCHARS is big enough. Added a fflush to casetm, so .fm <file> + will be up to date. + +June 25, 1993 (Rich): + + -t option + + reinstated for the sake of compatibility. Some old + shells scripts and man(1) from SunOs want this, sigh + + Compiler and system dependencies + + Some systems pull in sys/types.h via #include <time.h> and then + the compiler complains about two ushort typedefs. Therefore, + ushort is now Ushort (and uchar Uchar). + + The SVID specifies a strdup, POSIX doesn't, anyway, troff + provides its own version, slightly different then the standard + one. A To prevent name clashes with that definion, renamed to + strdupl. + +June 24, 1993 (Rich): + + -V option added for DWB3.4 (rich) + +May 18, 1993: + + Trivial fix (.cf) request for troff -a + + issuing + + .cf /dev/null + + with troff -a gives some spurious output: + + H720 + H720 + s10 + f1 + + fixed by checking for ascii mode it ptesc(), ptps() and + ptfont() in t10.c + + + Enhancement + + Added a .tm request to roff. Works just like .tm, but now + it will do it to file. The name is coined by Carmela. Great + for creating indeces & toc's (we hope). + +May 18 1993: + + Compatibilty change + + Somebody complained that his favorite macro didn't work: + it had a BELL (^G) in the name. This was a non-documented + feature of earlier versions of troff (although the + documentation actually doesn't say that you can. (They can + only be used for delimiters or with the tr request), so it + isn't that important). + + But the sake of eternal backward compatibilaty I allowed + some control characters like, STX, ACK, etc. also be part + of a macro/string name. + + While at it, I made it also possible to have eight bit + characters be part of the name. It might be that this screws + up the way users think about these things. For UNICODE + versions, they probably want to do that as well, and that + won't work as easy, (because these characters are 16-bits + wide), so it is dubious whether we actually want this. + + BTW. Now + + .de \(ts\ts + .tm terminal sigma macro + .. + .\(ts\(ts + + also works, as long the internal cookie for ts isn't more then + eight bits. + +May 12, 1993: + + Syntax change + + Some requests accept tabs as a separator, some don't and + this can be a nuisance. Now a tab is also recognized as + an argument separator for requests, this makes + + .so /dev/null + + works. + + To be more precise, any motion character is allowed, so + + .so\h'5i'/dev/null + + will work as well, if one really wants that. + + It will be a problem for users who really relied on this as in + + .ds x string + + and expect the tab to become part of the string a, but I haven't + seen any use of that (obscure trick). + +May 6, 1993: + + Eileen count fixed + + Troff sometimes went in a loop, and exited with: ``job + looping; check abuse of macros'' (also known as the Eileen's + loop). It can be forced with the next trivial programme: + + .de ff + .di xx + .. + .wh -1 ff + .bp + + Basically what happens is that a page transition now will + happen in a diversion, which doesn't make sense. Wat really + happens is that eject() (in n7.c) doesn't eject the frame + because we are in a diversion. This cause the loop in n1.c + (because now always stack->pname <= ejl). Adding check on + whether we are not in a diversion takes care of the problem. + +March 30, 1993: + + Need request, .ne + + When there is a begin of page trap set, and the first thing + in the file is a .ne request, the trap gets fired, but, + the x font R etc. cookies doen't come out, because the + troff thinks that the first page pseudo transition already + took place. Fixed by forcing the start of the first page + in the casene request with the same code as in casetl (which + caused a similar problem quite some time ago). + + Change to .cf request ``Here document'' + + If the argument of .cf starts with a <<, the rest of it is taken + as an EOF token. It will reat the rest of the input until it hits + the EOF token and copies it to the output. This is similar as + the shell's ``here document'' mechanisme and put in place to + improve the kludgy way picasso, picpack etc. now include + postscript. + + Using troff -TLatin1 (DWB version) and \N'...' caused core dump + + In t11, in chadd, it should test on NCHARS - ALPHABET to see + whether we run out of table space (and we probably should beaf + up NCHARS for the DWB version). + +March 16, 1993: + + Diversion rename bug fix + + It is possible to get troff in an infinite loop by renaming a + diversion in progress, and calling it later with the + new name (as in .di xx, .rn xx yy, .yy). The effect depends on + whether troff already put stuff in the diversion or not. + + Fix by having .rn also rename the current diversion (if + there is any and when appropriate). If the diversion calls + itself by the new name and given the fix made on 11 nov + 1992, this will now result in an error. (BTW, the fix from + 11 nov is improved: diversions nest, so we have to account + for that). + +December 18, 1992: + Some people have complete novels as comments, so we need + to skip comments while checking the legality of font files. + thaks Rixh + +December 16, 1992 + + Some people rely on the order that -r arguments are given, + so that troff -rC1 -rC3 ends up setting register C to 3. + Because cpushback() pushes things in a LIFO order back, we + have to do the same to get -r args in a FIFO order. + +Nov 17, 1992: + + Giving a -rL8 option cuased the string .nr L 8 to be printed + on the output, using the wonderful 3b2. Some garbage was + left in buf[100] in main(). Fixed by setting buf[0] explicitly + to 0 (because some C-compilers complain about ``no automatic + aggregate initialization''). + +Nov 11, 1992: + + Diversion bug fix + + If a diversion was being read and the input is faulty so + the diversion was reading in itself, it caused troff to + loop undefinitely. This was easily fixed by a test in + control(a,b) in n1.c. + + Something similar things might happen with macros causing + the ``eileenct problem'', but I didn't look for that. We + have to wait until it happens. + +Oct 26, 1992: + + Numeric arguments: + + Illegal argments are treated as missing arguments. This + changed the semantics of .ll, .ls, .in, .lg, .ul, .cu .lt + (which acted as if the argument was 0) and .ps which was + simply ignored with an illegal argument. + + Tidied up number parsing in atoi1(). This prevents arguments + like .x or 1.2.3.4 being interpret as a legal number (nonumb = 0) + + Numeric arguments error reporting: + + Controlled by .pt, illegal numbers are now reported (default + trace mode is 1). This is also true for the escapes: + \h'..', \v'..' \H'..', \S'..', \N'..', \D'..', \l'.., \L'.. + and \x'..'. + + \D'c' is the only drawing request which doesn't take a pair + of numbers as arguments, so a special case is put here in + setdraw() (This code actually could use an overhaul to get + better parsing. As long as the \D'..' cookies are machine + generated it is low on the priority list). + + Don't generate an error if the illegal argument to a request + is a \}. It is too painful to do right (although it can be + done, but it would clutter getch() and getcho() even more). + + Input line numbers (.c register) bug fixes: + + In not taken branches of .if or .ie, the input line # + (numtab[CD].val) should be raised when necessary (in eatblk()). + + For concealed newlines, we still should count the line for input. + + Setfield (n9.c) sometimes pushes the rest of the line back to + the input (including \n), without adjusting numtab[CD].val + + Because .c (and so numtab[CD].val) is the number of lines read + and the error might actually happen in the current line + (before seeing the '\n), we need to apply correction in + errprint when nlflg set. (This correction needs to be undone + when inside a macro because the nlflg is set by reading the + args to the macro). + + Line number setting (.lf) request bug fixes: + + I interpret that the .c register will contain the number of + read lines, not including the current one. + + Also, don't change the input line number when the first + argument of .lf is not a number. + + As a net effect, the next input + + .EQ + .EN + .ab + + will generate the same output whether eqn has been used or not. + + If request bug fix: + + A ``.if page .tm foo'' caused the next line being ignored; + This bcause when the 2nd delimiter of a string couldn't be + found in cmpstr, the next line was always eaten. Solution: + in caseif1, if the condition is false, we should check + nlflg before eating a block. (Note: We might have eaten + \{\ as well. We could disallow the \{\ in a string to be + compared to prevent that but that might break other things). + + Enhancement to .pt: + + The .pt now pops the previous values when no argument is + specified. Turned out to be handy when chasing for problems. + Just ``bracked'' the code with .pt 7 and .pt and you get + a trace of only that block. The meaning of the arguments + is now: + 01 trace numeric arguments (default on) + 02 trace requests + 04 trace macros + + Abort request (.ab) beautification: + + Don't print the extra carriage return when .ab is called + without an argument. + +Oct 12, 1992: + + (Comments & spelling errors from this day on by jaap) + + replaced 32767 by INT_MAX in several places to allow for very + long pages (on 32-but machines). + + The ``.fp 1 R \"COMMENT'' complains about ``./troff: Can't + open font file /usr/lib/font/devpost/h'' on some systems. It + sees the tab as part of the optional font file. Apparently it + is system dependent whether isgraph() includes the tab + character. Fixed by using getach() in getname() in n1.c + instead. + +Aug 28, 1992: + removed call to popi from rdtty(); it was eating up the + rest of the macro if it was used from within one. (thanks, jaap) + + +Jul 21, 1992: + added extra test in nextfile() to pop current input file + only if not in .nx command. thanks to jaap. + + added test in getword() to avoid hyphenating after \z character, + which prevents any hyphenation inside \X'...'. thanks to jaap. + + added, then removed, code in getword() to prevent hyphenating + anything shorter than 6 characters. looks like it changed a + lot more than i thought. + +Jul 12, 1992: + added .pt request to trace macros and requests (from jaap). + .pt N Print trace of macros (N=1), requests (N=2) or both (N=3) + +Jun 5, 1992: + added tests to t.twrest and t.twinit to avoid 0 deref in + n2 and n10, for nroff -t xxxxx. thanks to Rich Drechsler. + +May 22, 1992: + added extern decls to e.g., void Tchar (*hmot)(void) in tdef.h + and added definition to ni.c, so pointers are defined explicitly. + makes it work on turbo c++ and probably others. + + changed a couple of isdigit's and isgraph(getch()) to avoid + multiple evaluation (even though it shouldn't happen). + + Made /usr/bin/nroff a shell script. + +May 12, 1992: + n1.c: need p++ after strrchr to skip / in program name. + thanks to Rich Drechsler. + +Apr 17, 1992: + casefi(), n5.c: .u register should be 0 or 1, not incremented + with each .fi. + +Apr 5, 1992: + fiddled n7.c and added _nmwid to the environment, to add a + 5th argument to .nm: the maximum number of digits in any + line number. default is 3, which was previously hardwired in. + + added jaap's code for yet another register which actually delivers + a string, called .S (so it can easily go in the switch in setn() + in n4.c); it delivers the current tabstop and alignment modes in + a format suitable for a subsequent .ta \n(.S command: + .ds T \n(.S + ... + .ta \*T + +Mar 30, 1992: + added test in getword to avoid hyphenating things with motions + (and avoid a core dump sometimes too). + +Mar 13, 1992: + \n(sb initialized wrong in setwd(). + + TYPESETTER=foo troff -Tpost used foo instead of post. + +Mar 12, 1992: + rearranged tests in popf so that .so is closed properly before + moving on to the next macro package. + +Mar 1, 1992: + input mechanism rearranged to use getc() instead of stack of + explicit input buffers. 5-10% slowdown. + +Jan 28, 1992: + fixed .tm \(mi to print something sensible. thanks to jaap. + +Jan 2, 1992: + fiddle setfp so doesn't put out font stuff if -a turned on. + +Dec 17, 1991: + copy 3rd argument in .fp commands to x font ... lines when it contains + a /, for testing fonts locally. + +Dec 13, 1991: + parameterize the font directories, etc., so can be set in makefiles. + added -N argument to run as nroff. + +Nov 8, 1991: + add a maplow(towlower...) in n8.c to handle brain-damaged libraries. + +Nov 2, 1991: + merged nroff into troff, based on Ken's plan 9 version. + merged nii.c into ni.c, removed tw.h, etc. more work needed + to make this stuff cleaner. + +July 27, 1991: + added test in setn in n4 to fix bug that permitted things like + \n (ab to work "properly". thanks to jaap for finding and fixing. + + added paranoid testing in t11 to make sure font files look ok. + +May 13, 1991: + moved evaluation of \(xx from copy mode to non-copy mode, so that + weird character names wouldn't get reevaluated in argument parsing. + installed july 27. + +May 6, 1991: + increased size of hyphenation exception buffer to 512 from 128 + +Apr 14, 1991: + added an extra redundant call of ptfont in setfp, since it appears + that some versions of adobe transcript assume that an "x font" command + means to change the actual font as well. the fix preserves the current font. + thanks to david brailsford and friends for spotting the problem. + + fixed up tests in alpha() in n8 to defend isalpha() against too-big inputs. + punct() argument had wrong type too. thanks to rich drexler and peter nelson. + +Mar 19, 1991: + fixed bug that prevented .rd from working with new corebuf organization. + + fixed bug that caused .ig inside diversions to give bad storage + allocation. thanks to arthur david olson, whose fix was on netnews + 3 years earlier. + +Mar 5, 1991: + huge table sizes for kanji. + +Feb ??, 1991: + working on dealing with large alphabets, notably kanji. + added "defaultwidth" to font descriptions, for characters + not given an explicit width. + +Jan, 1991: + added tex hyphenation, using standard tex data files, but not the + elaborate compressed trie, which is a lot of trouble to save maybe + 40k bytes. this appears to run at exactly the same speed as before. + + so far this stuff reads into a fixed size array; that should change. + it should also be possible to deal with multiple languages. + + the command .ha sets the algorithm. .ha 1 => tex, with troff rules + if tex doesn't hyphenate; .ha 0 gives troff rules, and .ha resets + to the default, which is tex. the hyphenation algorithm is part of + the environment, a nod to a future in which i handle more than one + language. + + replaced the fixed size corebuf array for string/macro storage by + a dynamic structure that can grow. + + this appears to slow things down by maybe 3%. the code is about + the same complexity. + +Dec 27, 1990: + converted to ansi c, based on some work by ken thompson, but not + as thoroughly as he did. there is a shell script unansi and an awk + program cvt that will help you step back in time if you do not have + an ansi c compiler. + + moved the special-name characters up to 256 instead of 128, although + done in terms of ALPHABET, so one can pass 8 bit characters through. + removed lots of 0177's and similar numbers. input is now not filtered, + and if a character with the 8th bit on comes in, it will go out again. + + fixed t11.c to read character names in hex or octal as well as + single-character ascii. + + unknown characters are now carried through with width = spacewidth. + needs a way to set widths. + + removed all signal handling from troff. you signal, you die. + + added -d option to print version number. + +Dec 7, 1990: + .fp 3 V VERYLONGNAME used to truncate the name to 10 chars; fixed. + + increased the limit on FBUFSZ for tables with very long fields. + + changed atoi1() to use double to avoid intermediate overflow. + + moved filenames like /usr/lib/font into tdef.h for easy change. + removed some dreggish definitions. + + cleaned up non-portable error printing stuff; fixed up some messages. + +Dec 12, 1989: + Removed the .! command, an undocumented synonym for .sy. + +Dec 4, 1989: + Another wart to the \X code, to try to preserve blanks in all situations. + +Nov 17, 1989: + A number of small changes preparatory to getting rid of nroff. + The argument -Tnroff or -Tnroff-12 changes some internal values + so that the predicate .if n is true and certain arithmetic operations + are done as if nroff. This design is not yet final. + +Nov 7, 1989: + Fixed hyphenation for nov-ice, ad-vice, de-vice, ser-vice, *-vice. + +Oct 11, 1989: + It is now permitted to do an explicit change to font S. + It is not clear what will break (though nothing seems to have). + +Oct 10, 1989: + Modified flush code to always put out \nH instead of sometimes h. + This makes it easier to parse the output for positioning. + +Sep 9, 1989: + Fixed internal representation of \D'~...' so that it + is immune to .tr ~ and variations. No external change. + +Aug 9, 1989: + Changed .tm so it outputs \e, \%, \-, \&, \(blank). + This might break indexing code. + Only in the new version, as are all subsequent fixes. + +July, 1989: + A major internal change: font information is read in ascii + instead of the weird binary format of makedev (which is now dead). + character names need not all appear in DESC; new names that + appear when a font is used become part of the set of known names. + + There are some flaky bits here (it's conceivable that some \N + number will collide with a real name), and it's probably 10-15% + slower. Tant pis. + + As a by-product, nroff no longer compiles. I'll probably get + back to this, but an alternative is to bag it once and for all. + +May 25, 1989: + Another bug in \l, this time when width is 0. Not installed, + since it's in the new font version. + +Apr 23, 1989: + Fixed bug in n9 that caused core dump with unterminated + \l command, like \l'1.5i + + ptflush no longer called when -a is on. + +Apr 12, 1989: + fixed bug in n2 that failed to suppress printing of \! + output when a -o was in effect. + +Apr 5, 1989: + .fl and \X now cause output of size, font, hpos and vpos. + this is necesary for postprocessors that intend to insert + independent material, such as postscript. + +Feb 1, 1989: + wait for .pi pipe to empty before exiting + +Oct 2, 1988: + default is now -Tpost + +Sep 19, 1988: + added abortive code to handle built-up characters by + passing something through as \D'b...'. never used. + +Jul 4, 1988: + replaced the sbrk nonsense in n3.c by calls to malloc. + + \N now tests against proper font size. + + installed Jaap Akkerhuis's code (mutatis mutandis) for + permitting up to 99 fonts, swapping them into font pos 0 + as needed. fixes the long-standing problem of having + multiple font changes on a single output line. + +Jul 2, 1988: + \X now preserves spaces even when contents are diverted. + + \N code safer -- NTRTAB and NWIDCACHE enlarged. + +Jul 14, 1987: + Fixed obscure bug causing incorrect indentation of .mc output. diff --git a/src/cmd/troff/README b/src/cmd/troff/README new file mode 100644 index 00000000..6dc8fa09 --- /dev/null +++ b/src/cmd/troff/README @@ -0,0 +1,31 @@ +To make troff (actually a.out): + + make + +You will also need to write a driver for your favorite output device. +d202.c provides a model, although it is specialized to a machine no +one has. There are also a variety of postscript drivers that are the +best thing to use if you have a postscript device. + +You will also have to make a DESC file for your typesetter and some +font description files; see dev202 for examples. These describe the +named characters, widths, kerning information, and output codes. + +Nroff is the same program as troff, so you should + + cp a.out /usr/bin/troff + ln /usr/bin/troff /usr/bin/nroff + +or the equivalent. + +You will also need terminal description files for your terminals; see +tab.37, tab.450 and tab.lp for examples. + +Troff uses files that are normally stored in /usr/lib/font; +macro packages are in /usr/lib/tmac; and nroff tables are in +/usr/lib/term. You can edit tdef.h to change these assumptions. + +There have been a few features since the last version, and a number of +significant internal changes. Not all are improvements, of course. +Most of the more recent changes, including bug fixes, are in FIXES, +which you should read also. diff --git a/src/cmd/troff/cvt b/src/cmd/troff/cvt new file mode 100644 index 00000000..3426d626 --- /dev/null +++ b/src/cmd/troff/cvt @@ -0,0 +1,45 @@ + +awk ' + +/^{/ { + if (prev != "") { + # comments can be trouble (e.g. ffree()) + if ( (c = match(prev, /\/\*.*\*\/$/)) != 0 ) { + comment = substr(prev, c) + sub(/\/\*.*\*\/$/, "", prev) + } else comment = "" + + x = prev + + # isolate argument list + sub(/^[^(]*\(/, "", x) + sub(/\)[^)]*$/, "", x) + + # find the names in it + n = split(x, args) + arglist = "" + for (i = 2; i <= n; i += 2) + arglist = arglist args[i] + gsub(/\(\*f\)\(Tchar\)/, "f", arglist) # special case for n4.c + gsub(/\[[0-9]+\]/, "", arglist) # for n8.c + gsub(/[*()\[\]]/, "", arglist) # discard noise characters *()[] + gsub(/,/, ", ", arglist) # space nicely + sub(/\(.*\)/, "(" arglist ")", prev) # reconstruct + print prev comment + + # argument declarations + gsub(/,/, ";", x) + gsub(/\(\*f\)\(Tchar\)/, "(*f)()", x) # special case for n4.c + if (x != "") + print "\t" x ";" + } + prev = $0 + next +} + +{ print prev + prev = $0 +} + +END { print prev } +' $* diff --git a/src/cmd/troff/dwbinit.c b/src/cmd/troff/dwbinit.c new file mode 100644 index 00000000..a63e5fde --- /dev/null +++ b/src/cmd/troff/dwbinit.c @@ -0,0 +1,313 @@ +/* + * + * Pathname management routines for DWB C programs. + * + * Applications should initialize a dwbinit array with the string + * pointers and arrays that need to be updated, and then hand that + * array to DWBinit before much else happens in their main program. + * DWBinit calls DWBhome to get the current home directory. DWBhome + * uses the last definition of DWBENV (usually "DWBHOME") in file + * DWBCONFIG (e.g., /usr/lib/dwb3.4) or the value assigned to that + * variable in the environment if the DWBCONFIG file doesn't exist, + * can't be read, or doesn't define DWBENV. + * + * DWBCONFIG must be a simple shell script - comments, a definition + * of DWBHOME, and perhaps an export or echo is about all that's + * allowed. The parsing in DWBhome is simple and makes no attempt + * to duplicate the shell. It only looks for DWBHOME= as the first + * non-white space string on a line, so + * + * # + * # A sample DWBCONFIG shell script + * # + * + * DWBHOME=/usr/add-on/dwb3.4 + * export DWBHOME + * + * means DWBhome would return "/usr/add-on/dwb3.4" for the DWB home + * directory. A DWBCONFIG file means there can only be one working + * copy of a DWB release on a system, which seems like a good idea. + * Using DWBCONFIG also means programs will always include correct + * versions of files (e.g., prologues or macro packages). + * + * Relying on an environment variable guarantees nothing. You could + * execute a version of dpost, but your environment might point at + * incorrect font tables or prologues. Despite the obvious problems + * we've also implemented an environment variable approach, but it's + * only used if there's no DWBCONFIG file. + * + * DWBinit calls DWBhome to get the DWB home directory prefix and + * then marches through its dwbinit argument, removing the default + * home directory and prepending the new home. DWBinit stops when + * it reaches an element that has NULL for its address and value + * fields. Pointers in a dwbinit array are reallocated and properly + * initialized; arrays are simply reinitialized if there's room. + * All pathnames that are to be adjusted should be relative. For + * example, + * + * char *fontdir = "lib/font"; + * char xyzzy[25] = "etc/xyzzy"; + * + * would be represented in a dwbinit array as, + * + * dwbinit allpaths[] = { + * &fontdir, NULL, 0, + * NULL, xyzzy, sizeof(xyzzy), + * NULL, NULL, 0 + * }; + * + * The last element must have NULL entries for the address and + * value fields. The main() routine would then do, + * + * #include "dwbinit.h" + * + * main() { + * + * DWBinit("program name", allpaths); + * ... + * } + * + * Debugging is enabled if DWBDEBUG is in the environment and has + * the value ON. Output is occasionally useful and probably should + * be documented. + * + */ + +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> + +#include "dwbinit.h" + +#ifndef DWBCONFIG +#define DWBCONFIG "/dev/null" +#endif + +#ifndef DWBENV +#define DWBENV "DWBHOME" +#endif + +#ifndef DWBHOME +#define DWBHOME "" +#endif + +#ifndef DWBDEBUG +#define DWBDEBUG "DWBDEBUG" +#endif + +#ifndef DWBPREFIX +#define DWBPREFIX "\\*(.P" +#endif + +/*****************************************************************************/ + +void DWBdebug(dwbinit *ptr, int level) +{ + + char *path; + char *home; + static char *debug = NULL; + +/* + * + * Debugging output, but only if DWBDEBUG is defined to be ON in the + * environment. Dumps general info the first time through. + * + */ + + if ( debug == NULL && (debug = getenv(DWBDEBUG)) == NULL ) + debug = "OFF"; + + if ( strcmp(debug, "ON") == 0 ) { + if ( level == 0 ) { + fprintf(stderr, "Environment variable: %s\n", DWBENV); + fprintf(stderr, "Configuration file: %s\n", DWBCONFIG); + fprintf(stderr, "Default home: %s\n", DWBHOME); + if ( (home = DWBhome()) != NULL ) + fprintf(stderr, "Current home: %s\n", home); + } /* End if */ + + fprintf(stderr, "\n%s pathnames:\n", level == 0 ? "Original" : "Final"); + for ( ; ptr->value != NULL || ptr->address != NULL; ptr++ ) { + if ( (path = ptr->value) == NULL ) { + path = *ptr->address; + fprintf(stderr, " pointer: %s\n", path); + } else fprintf(stderr, " array[%d]: %s\n", ptr->length, path); + if ( level == 0 && *path == '/' ) + fprintf(stderr, " WARNING - absolute path\n"); + } /* End for */ + } /* End if */ + +} /* End of DWBdebug */ + +/*****************************************************************************/ + +char *DWBhome(void) +{ + + FILE *fp; + char *ptr; + char *path; + int len; + char buf[200]; + char *home = NULL; + +/* + * + * Return the DWB home directory. Uses the last definition of DWBENV + * (usually "DWBHOME") in file DWBCONFIG (perhaps /usr/lib/dwb3.4) or + * the value assigned to the variable named by the DWBENV string in + * the environment if DWBCONFIG doesn't exist or doesn't define DWBENV. + * Skips the file lookup if DWBCONFIG can't be read. Returns NULL if + * there's no home directory. + * + */ + + if ( (fp = fopen(DWBCONFIG, "r")) != NULL ) { + len = strlen(DWBENV); + while ( fgets(buf, sizeof(buf), fp) != NULL ) { + for ( ptr = buf; isspace(*ptr); ptr++ ) ; + if ( strncmp(ptr, DWBENV, len) == 0 && *(ptr+len) == '=' ) { + path = ptr + len + 1; + for ( ptr = path; !isspace(*ptr) && *ptr != ';'; ptr++ ) ; + *ptr = '\0'; + if ( home != NULL ) + free(home); + if ( (home = malloc(strlen(path)+1)) != NULL ) + strcpy(home, path); + } /* End if */ + } /* End while */ + fclose(fp); + } /* End if */ + + if ( home == NULL ) { + if ( (home = getenv(DWBENV)) == NULL ) { + if ( (home = DWBHOME) == NULL || *home == '\0' || *home == ' ' ) + home = NULL; + } /* End if */ + } /* End if */ + + while (home && *home == '/' && *(home +1) == '/') /* remove extra slashes */ + home++; + return(home); + +} /* End of DWBhome */ + +/*****************************************************************************/ + +void DWBinit(char *prog, dwbinit *paths) +{ + + char *prefix; + char *value; + char *path; + int plen; + int length; + dwbinit *opaths = paths; + +/* + * + * Adjust the pathnames listed in paths, using the home directory + * returned by DWBhome(). Stops when it reaches an element that has + * NULL address and value fields. Assumes pathnames are relative, + * but changes everything. DWBdebug issues a warning if an original + * path begins with a /. + * + * A non-NULL address refers to a pointer, which is reallocated and + * then reinitialized. A NULL address implies a non-NULL value field + * and describes a character array that we only reinitialize. The + * length field for an array is the size of that array. The length + * field of a pointer is an increment that's added to the length + * required to store the new pathname string - should help when we + * want to change character arrays to pointers in applications like + * troff. + * + */ + + if ( (prefix = DWBhome()) == NULL ) { + fprintf(stderr, "%s: no DWB home directory\n", prog); + exit(1); + } /* End if */ + + DWBdebug(opaths, 0); + plen = strlen(prefix); + + for ( ; paths->value != NULL || paths->address != NULL; paths++ ) { + if ( paths->address == NULL ) { + length = 0; + value = paths->value; + } else { + length = paths->length; + value = *paths->address; + } /* End else */ + + length += plen + 1 + strlen(value); /* +1 is for the '/' */ + + if ( (path = malloc(length+1)) == NULL ) { + fprintf(stderr, "%s: can't allocate pathname memory\n", prog); + exit(1); + } /* End if */ + + if ( *value != '\0' ) { + char *eop = prefix; + while(*eop++) + ; + eop -= 2; + if (*value != '/' && *eop != '/') { + sprintf(path, "%s/%s", prefix, value); + } else if (*value == '/' && *eop == '/') { + value++; + sprintf(path, "%s%s", prefix, value); + } else + sprintf(path, "%s%s", prefix, value); + } else + sprintf(path, "%s", prefix); + + if ( paths->address == NULL ) { + if ( strlen(path) >= paths->length ) { + fprintf(stderr, "%s: no room for %s\n", prog, path); + exit(1); + } /* End if */ + strcpy(paths->value, path); + free(path); + } else *paths->address = path; + } /* End for */ + + DWBdebug(opaths, 1); + +} /* End of DWBinit */ + +/*****************************************************************************/ + +void DWBprefix( char *prog, char *path, int length) +{ + + char *home; + char buf[512]; + int len = strlen(DWBPREFIX); + +/* + * + * Replace a leading DWBPREFIX string in path by the current DWBhome(). + * Used by programs that pretend to handle .so requests. Assumes path + * is an array with room for length characters. The implementation is + * not great, but should be good enough for now. Also probably should + * have DWBhome() only do the lookup once, and remember the value if + * called again. + * + */ + + if ( strncmp(path, DWBPREFIX, len) == 0 ) { + if ( (home = DWBhome()) != NULL ) { + if ( strlen(home) + strlen(path+len) < length ) { + sprintf(buf, "%s%s", home, path+len); + strcpy(path, buf); /* assuming there's room in path */ + } else fprintf(stderr, "%s: no room to grow path %s", prog, path); + } /* End if */ + } /* End if */ + +} /* End of DWBprefix */ + +/*****************************************************************************/ + diff --git a/src/cmd/troff/dwbinit.h b/src/cmd/troff/dwbinit.h new file mode 100644 index 00000000..acb1476c --- /dev/null +++ b/src/cmd/troff/dwbinit.h @@ -0,0 +1,19 @@ +/* + * + * A structure used to adjust pathnames in DWB C code. Pointers + * set the address field, arrays use the value field and must + * also set length to the number elements in the array. Pointers + * are always reallocated and then reinitialized; arrays are only + * reinitialized, if there's room. + * + */ + +typedef struct { + char **address; + char *value; + int length; +} dwbinit; + +extern void DWBinit(char *, dwbinit *); +extern char* DWBhome(void); +extern void DWBprefix(char *, char *, int); diff --git a/src/cmd/troff/ext.h b/src/cmd/troff/ext.h new file mode 100644 index 00000000..42147880 --- /dev/null +++ b/src/cmd/troff/ext.h @@ -0,0 +1,184 @@ +extern int TROFF; + +extern int alphabet; +extern char **argp; +extern char *eibuf; +extern char *ibufp; +extern char *obufp; +extern char *unlkp; +extern char *xbufp; +extern char *xeibuf; +extern char cfname[NSO+1][NS]; +extern int trace; +extern char devname[]; +extern char ibuf[IBUFSZ]; +extern char mfiles[NMF][NS]; +extern char nextf[]; +extern char obuf[]; +extern char termtab[]; +extern char fontdir[]; +extern Font fonts[MAXFONTS+1]; +extern char xbuf[IBUFSZ]; +extern Offset apptr; +extern Offset ip; +extern Offset nextb; +extern Offset offset; +extern Offset woff; +extern Numerr numerr; +extern int *pnp; +extern int pstab[]; +extern int nsizes; +extern int app; +extern int ascii; +extern int bd; +extern int bdtab[]; +extern int ccs; +extern char *chnames[]; /* chnames[n-ALPHABET] -> name of char n */ +extern int copyf; +extern int cs; +extern int dfact; +extern int dfactd; +extern int diflg; +extern int dilev; +extern int donef; +extern int dotT; +extern int dpn; +extern int ds; +extern int ejf; +extern int em; +extern int eqflg; +extern int error; +extern int esc; +extern int eschar; +extern int ev; +extern int evi; +extern int evlist[EVLSZ]; +extern int fc; +extern int flss; +extern int fontlab[]; +extern int hflg; +extern int ibf; +extern int ifi; +extern int iflg; +extern int init; +extern int lead; +extern int lg; +extern int lgf; +extern int macerr; +extern int mflg; +extern int mfont; +extern int mlist[NTRAP]; +extern int mpts; +extern int nchnames; +extern int ndone; +extern int newmn; +extern int nflush; +extern int nfo; +extern int nfonts; +extern int nform; +extern int nhyp; +extern int nlflg; +extern int nlist[NTRAP]; +extern int nmfi; +extern int nonumb; +extern int noscale; +extern int npn; +extern int npnflg; +extern int nx; +extern int oldbits; +extern int oldmn; +extern int over; +extern int padc; +extern int pfont; +extern int pfrom; +extern int pipeflg; +extern int pl; +extern int pnlist[]; +extern int po1; +extern int po; +extern int ppts; +extern int print; +extern FILE *ptid; +extern int pto; +extern int quiet; +extern int ralss; +extern int rargc; +extern int raw; +extern int res; +extern int sbold; +extern int setwdf; +extern int sfont; +extern int smnt; +extern int stdi; +extern int stop; +extern int sv; +extern int tabch, ldrch; +extern int tflg; +extern int totout; +extern int trap; +extern Ushort trtab[]; +extern int tty; +extern int ulfont; +extern int vflag; +extern int whichroff; +extern int widthp; +extern int xfont; +extern int xpts; +extern Stack *ejl; +extern Stack *frame; +extern Stack *stk; +extern Stack *nxf; +extern Tchar **hyp; +extern Tchar *olinep; +extern Tchar pbbuf[NC]; +extern Tchar *pbp; +extern Tchar *lastpbp; +extern Tchar ch; +extern Tchar nrbits; +extern Tbuf _oline; +extern Wcache widcache[]; +extern char gchtab[]; +extern Diver d[NDI]; +extern Diver *dip; + + +extern char xchname[]; +extern short xchtab[]; +extern char *codestr; +extern char *chnamep; +extern short *chtab; +extern int nchtab; + +extern Numtab *numtabp; + +/* these characters are used as various signals or values +/* in miscellaneous places. +/* values are set in specnames in t10.c +*/ + +extern int c_hyphen; +extern int c_emdash; +extern int c_rule; +extern int c_minus; +extern int c_fi; +extern int c_fl; +extern int c_ff; +extern int c_ffi; +extern int c_ffl; +extern int c_acute; +extern int c_grave; +extern int c_under; +extern int c_rooten; +extern int c_boxrule; +extern int c_lefthand; +extern int c_dagger; +extern int c_isalnum; + +/* + * String pointers for DWB pathname management. + */ + +extern char *DWBfontdir; +extern char *DWBntermdir; +extern char *DWBalthyphens; + diff --git a/src/cmd/troff/find b/src/cmd/troff/find new file mode 100644 index 00000000..eccbfbdb --- /dev/null +++ b/src/cmd/troff/find @@ -0,0 +1 @@ +grep $1 *.[ch] diff --git a/src/cmd/troff/fns.h b/src/cmd/troff/fns.h new file mode 100644 index 00000000..6bd94ada --- /dev/null +++ b/src/cmd/troff/fns.h @@ -0,0 +1,384 @@ +/* + * other + */ +int pclose(FILE*); +long filesize(int fd); +int open(char *, int); +int read(int, char *, int); +int lseek(int, long, int); +int close(int); +int getpid(void); + +/* + * c1.c + */ +void init0(void); +void init2(void); +void cvtime(void); +void errprint(void); +int control(int a, int b); +void casept(void); +int getrq(void); +Tchar getch(void); +void setxon(void); +Tchar getch0(void); +Tchar get1ch(FILE *); +void pushback(Tchar *b); +void cpushback(char *b); +int nextfile(void); +int popf(void); +void flushi(void); +int getach(void); +void casenx(void); +int getname(void); +void caseso(void); +void caself(void); +void casecf(void); +void getline(char *s, int n); +void casesy(void); +void getpn(char *a); +void setrpt(void); + +/* + * n2.c + */ +int pchar(Tchar i); +void pchar1(Tchar i); +int pchar2(Tchar i); +int flusho(void); +void casedone(void); +void caseex(void); +void done(int x); +void done1(int x); +void done2(int x); +void done3(int x); +void edone(int x); +void casepi(void); + +/* + * c3.c + */ +void blockinit(void); +char* grow(char *, int, int); +void mnspace(void); +void caseig(void); +void casern(void); +void maddhash(Contab *rp); +void munhash(Contab *mp); +void mrehash(void); +void caserm(void); +void caseas(void); +void caseds(void); +void caseam(void); +void casede(void); +int findmn(int i); +void clrmn(int i); +Offset finds(int mn); +int skip(void); +int copyb(void); +void copys(void); +Offset alloc(void); +void ffree(Offset i); +void wbf(Tchar i); +Tchar rbf(void); +Tchar popi(void); +Offset pushi(Offset newip, int mname); +void* setbrk(int x); +int getsn(void); +Offset setstr(void); +void collect(void); +void seta(void); +void caseda(void); +void casegd(void); +void casedi(void); +void casedt(void); +void casetl(void); +void casepc(void); +void casepm(void); +void stackdump(void); + +/* + * c4.c + */ +void setn(void); +int wrc(Tchar i); +void setn1(int i, int form, Tchar bits); +void nnspace(void); +void nrehash(void); +void nunhash(Numtab *rp); +int findr(int i); +int usedr(int i); +int fnumb(int i, int (*f)(Tchar)); +int decml(int i, int (*f)(Tchar)); +int roman(int i, int (*f)(Tchar)); +int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp); +int abc(int i, int (*f)(Tchar)); +int abc0(int i, int (*f)(Tchar)); +long atoi0(void); +long ckph(void); +long atoi1(Tchar ii); +void caserr(void); +void casenr(void); +void caseaf(void); +void setaf(void); +int vnumb(int *i); +int hnumb(int *i); +int inumb(int *n); +int quant(int n, int m); + +/* + * c5.c + */ +void casead(void); +void casena(void); +void casefi(void); +void casenf(void); +void casers(void); +void casens(void); +int chget(int c); +void casecc(void); +void casec2(void); +void casehc(void); +void casetc(void); +void caselc(void); +void casehy(void); +int max(int aa, int bb); +void casenh(void); +void casece(void); +void casein(void); +void casell(void); +void caselt(void); +void caseti(void); +void casels(void); +void casepo(void); +void casepl(void); +void casewh(void); +void casech(void); +int findn(int i); +void casepn(void); +void casebp(void); +void casextm(void); +void casetm(void); +void casefm(void); +void casetm1(int ab, FILE *out); +void casesp(void); +void casesp1(int a); +void casert(void); +void caseem(void); +void casefl(void); +void caseev(void); +void envcopy(Env *e1, Env *e2); +void caseel(void); +void caseie(void); +void casexif(void); +void caseif(void); +void caseif1(int); +void eatblk(int inblk); +int cmpstr(Tchar c); +void caserd(void); +int rdtty(void); +void caseec(void); +void caseeo(void); +void caseta(void); +void casene(void); +void casetr(void); +void casecu(void); +void caseul(void); +void caseuf(void); +void caseit(void); +void casemc(void); +void casemk(void); +void casesv(void); +void caseos(void); +void casenm(void); +void getnm(int *p, int min); +void casenn(void); +void caseab(void); +void save_tty(void); +void restore_tty(void); +void set_tty(void); +void echo_off(void); +void echo_on(void); + +/* + * t6.c + */ +int t_width(Tchar j); +void zapwcache(int s); +int onfont(int n, int f); +int getcw(int i); +void xbits(Tchar i, int bitf); +Tchar t_setch(int c); +Tchar t_setabs(void); +int t_findft(int i); +void caseps(void); +void casps1(int i); +int findps(int i); +void t_mchbits(void); +void t_setps(void); +Tchar t_setht(void); +Tchar t_setslant(void); +void caseft(void); +void t_setfont(int a); +void t_setwd(void); +Tchar t_vmot(void); +Tchar t_hmot(void); +Tchar t_mot(void); +Tchar t_sethl(int k); +Tchar t_makem(int i); +Tchar getlg(Tchar i); +void caselg(void); +void casefp(void); +char *strdupl(const char *); +int setfp(int pos, int f, char *truename, int print); +void casecs(void); +void casebd(void); +void casevs(void); +void casess(void); +Tchar t_xlss(void); +Uchar* unpair(int i); +void outascii(Tchar i); + +/* + * c7.c + */ +void tbreak(void); +void donum(void); +void text(void); +void nofill(void); +void callsp(void); +void ckul(void); +void storeline(Tchar c, int w); +void newline(int a); +int findn1(int a); +void chkpn(void); +int findt(int a); +int findt1(void); +void eject(Stack *a); +int movword(void); +void horiz(int i); +void setnel(void); +int getword(int x); +void storeword(Tchar c, int w); +Tchar gettch(void); + +/* + * c8.c + */ +void hyphen(Tchar *wp); +int punct(Tchar i); +int alph(int i); +void caseha(void); +void caseht(void); +void casehw(void); +int exword(void); +int suffix(void); +int maplow(int i); +int vowel(int i); +Tchar* chkvow(Tchar *w); +void digram(void); +int dilook(int a, int b, char t[26][13]); + +/* + * c9.c + */ +Tchar setz(void); +void setline(void); +int eat(int c); +void setov(void); +void setbra(void); +void setvline(void); +void setdraw(void); +void casefc(void); +Tchar setfield(int x); + +/* + * t10.c + */ +void t_ptinit(void); +void t_specnames(void); +void t_ptout(Tchar i); +int ptout0(Tchar *pi); +void ptchname(int); +void ptflush(void); +void ptps(void); +void ptfont(void); +void ptfpcmd(int f, char *s, char *fn); +void t_ptlead(void); +void ptesc(void); +void ptpage(int n); +void pttrailer(void); +void ptstop(void); +void t_ptpause(void); + +/* + * t11.c + */ +int getdesc(char *name); +int getfont(char *name, int pos); +int chadd(char *s, int, int); +char* chname(int n); +int getlig(FILE *fin); + +/* + * n6.c + */ +int n_width(Tchar j); +Tchar n_setch(int c); +Tchar n_setabs(void); +int n_findft(int i); +void n_mchbits(void); +void n_setps(void); +Tchar n_setht(void); +Tchar n_setslant(void); +void n_caseft(void); +void n_setfont(int a); +void n_setwd(void); +Tchar n_vmot(void); +Tchar n_hmot(void); +Tchar n_mot(void); +Tchar n_sethl(int k); +Tchar n_makem(int i); +void n_casefp(void); +void n_casebd(void); +void n_casevs(void); +Tchar n_xlss(void); + +/* + * n10.c + */ +void n_ptinit(void); +char* skipstr(char *s); +char* getstr(char *s, char *t); +char* getint(char *s, int *pn); +void twdone(void); +void n_specnames(void); +int findch(char *s); +void n_ptout(Tchar i); +void ptout1(void); +char* plot(char *x); +void move(void); +void n_ptlead(void); +void n_ptpause(void); + +/* + * indirect calls on TROFF/!TROFF. these are variables! + */ +extern Tchar (*hmot)(void); +extern Tchar (*makem)(int i); +extern Tchar (*setabs)(void); +extern Tchar (*setch)(int c); +extern Tchar (*sethl)(int k); +extern Tchar (*setht)(void); +extern Tchar (*setslant)(void); +extern Tchar (*vmot)(void); +extern Tchar (*xlss)(void); +extern int (*findft)(int i); +extern int (*width)(Tchar j); +extern void (*mchbits)(void); +extern void (*ptlead)(void); +extern void (*ptout)(Tchar i); +extern void (*ptpause)(void); +extern void (*setfont)(int a); +extern void (*setps)(void); +extern void (*setwd)(void); diff --git a/src/cmd/troff/hytab.c b/src/cmd/troff/hytab.c new file mode 100644 index 00000000..623637fc --- /dev/null +++ b/src/cmd/troff/hytab.c @@ -0,0 +1,126 @@ +/* + * Hyphenation digram tables + */ + +typedef unsigned char Uchar; + + +Uchar bxh[26][13] = { + 0060,0000,0040,0000,0040,0000,0000,0040,0000,0000,0040,0000,0040 +}; + +Uchar hxx[26][13] = { + 0006,0042,0041,0123,0021,0024,0063,0042,0002,0043,0021,0001,0022, + 0140,0000,0200,0003,0260,0006,0000,0160,0007,0000,0140,0000,0320, + 0220,0000,0160,0005,0240,0010,0000,0100,0006,0000,0200,0000,0320, + 0240,0000,0120,0003,0140,0000,0000,0240,0010,0000,0220,0000,0160, + 0042,0023,0041,0040,0040,0022,0043,0041,0030,0064,0021,0000,0041, + 0100,0000,0140,0000,0220,0006,0000,0140,0003,0000,0200,0000,0000, + 0200,0000,0120,0002,0220,0010,0000,0160,0006,0000,0140,0000,0320, + 0020,0000,0020,0000,0020,0000,0000,0020,0000,0000,0020,0000,0000, + 0043,0163,0065,0044,0022,0043,0104,0042,0061,0146,0061,0000,0007, + 0100,0000,0140,0000,0040,0000,0000,0100,0000,0000,0120,0000,0000, + 0140,0000,0040,0011,0060,0004,0001,0120,0003,0000,0140,0000,0040, + 0200,0000,0100,0000,0140,0000,0000,0140,0000,0000,0140,0000,0240, + 0200,0000,0140,0000,0160,0000,0000,0220,0000,0000,0140,0000,0240, + 0200,0000,0140,0000,0160,0000,0000,0220,0000,0000,0060,0000,0240, + 0021,0043,0041,0121,0040,0023,0042,0003,0142,0042,0061,0001,0022, + 0120,0000,0140,0010,0140,0010,0000,0140,0002,0000,0120,0000,0120, + 0000,0000,0000,0000,0360,0000,0000,0000,0000,0000,0160,0000,0000, + 0100,0000,0040,0005,0120,0000,0000,0100,0000,0000,0060,0000,0140, + 0140,0040,0100,0001,0240,0041,0000,0242,0000,0002,0140,0000,0100, + 0240,0000,0120,0002,0200,0000,0000,0320,0007,0000,0240,0000,0340, + 0101,0021,0041,0020,0040,0005,0042,0121,0002,0021,0201,0000,0020, + 0160,0000,0100,0000,0140,0000,0000,0160,0006,0000,0220,0000,0140, + 0140,0000,0020,0001,0020,0000,0000,0100,0001,0000,0300,0000,0000, + 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, + 0106,0041,0040,0147,0040,0000,0063,0041,0001,0102,0160,0002,0002, + 0300,0000,0040,0017,0140,0017,0000,0240,0000,0000,0140,0000,0120, +}; + +Uchar bxxh[26][13] = { + 0005,0150,0153,0062,0062,0246,0152,0127,0146,0203,0310,0017,0206, + 0100,0000,0120,0000,0140,0000,0000,0100,0000,0000,0120,0000,0060, + 0100,0000,0040,0000,0060,0000,0000,0060,0000,0000,0220,0000,0040, + 0100,0000,0120,0000,0200,0000,0000,0100,0000,0000,0140,0000,0060, + 0043,0142,0046,0140,0062,0147,0210,0131,0046,0106,0246,0017,0111, + 0060,0000,0020,0000,0060,0000,0000,0040,0000,0000,0100,0000,0000, + 0060,0000,0040,0000,0040,0000,0000,0040,0000,0000,0100,0000,0040, + 0100,0000,0100,0000,0100,0000,0000,0040,0000,0000,0100,0000,0140, + 0066,0045,0145,0140,0000,0070,0377,0030,0130,0103,0003,0017,0006, + 0040,0000,0040,0000,0020,0000,0000,0040,0000,0000,0100,0000,0000, + 0200,0000,0020,0000,0140,0000,0000,0120,0000,0000,0120,0000,0040, + 0120,0000,0040,0000,0060,0000,0000,0060,0000,0000,0160,0000,0040, + 0120,0000,0040,0000,0120,0000,0000,0040,0000,0000,0160,0000,0040, + 0120,0000,0020,0000,0140,0000,0000,0120,0000,0000,0140,0000,0040, + 0051,0126,0150,0140,0060,0210,0146,0006,0006,0165,0003,0017,0244, + 0120,0000,0040,0000,0160,0000,0000,0140,0000,0000,0060,0000,0140, + 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, + 0140,0000,0140,0000,0060,0000,0000,0100,0000,0000,0140,0000,0020, + 0120,0000,0020,0000,0060,0000,0000,0060,0000,0000,0060,0000,0040, + 0140,0000,0020,0000,0100,0000,0000,0140,0000,0000,0140,0000,0020, + 0070,0125,0051,0162,0120,0105,0126,0104,0006,0044,0000,0017,0052, + 0140,0000,0020,0000,0140,0000,0000,0060,0000,0000,0060,0000,0040, + 0020,0000,0000,0000,0020,0000,0000,0000,0000,0000,0000,0000,0060, + 0140,0000,0160,0000,0200,0000,0000,0140,0000,0000,0000,0000,0240, + 0065,0042,0060,0200,0000,0210,0222,0146,0006,0204,0220,0012,0003, + 0240,0000,0020,0000,0120,0000,0000,0200,0000,0000,0200,0000,0240, +}; + +Uchar xhx[26][13] = { + 0032,0146,0042,0107,0076,0102,0042,0146,0202,0050,0006,0000,0051, + 0036,0377,0057,0013,0057,0366,0377,0057,0001,0377,0057,0000,0040, + 0037,0377,0020,0000,0100,0022,0377,0057,0362,0116,0100,0000,0017, + 0057,0377,0057,0031,0137,0363,0377,0037,0362,0270,0077,0000,0117, + 0074,0142,0012,0236,0076,0125,0063,0165,0341,0046,0047,0000,0024, + 0020,0017,0075,0377,0040,0001,0377,0017,0001,0204,0020,0000,0040, + 0057,0017,0057,0340,0140,0362,0314,0117,0003,0302,0100,0000,0057, + 0057,0357,0077,0017,0100,0366,0314,0057,0342,0346,0037,0000,0060, + 0252,0145,0072,0157,0377,0165,0063,0066,0164,0050,0363,0000,0362, + 0000,0000,0020,0000,0020,0000,0000,0017,0000,0000,0020,0000,0000, + 0117,0017,0237,0377,0200,0354,0125,0110,0004,0257,0000,0000,0300, + 0057,0367,0054,0357,0157,0216,0314,0114,0217,0353,0053,0000,0057, + 0077,0213,0077,0077,0177,0317,0377,0114,0377,0352,0077,0000,0076, + 0077,0213,0077,0077,0157,0177,0377,0054,0377,0352,0117,0000,0075, + 0125,0230,0065,0216,0057,0066,0063,0047,0345,0126,0011,0000,0033, + 0057,0377,0051,0360,0120,0361,0273,0056,0001,0256,0057,0000,0060, + 0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000,0000, + 0076,0310,0056,0310,0137,0174,0273,0055,0335,0266,0033,0000,0155, + 0077,0157,0057,0360,0057,0063,0042,0024,0077,0206,0020,0000,0040, + 0057,0037,0077,0360,0100,0365,0377,0037,0362,0176,0050,0000,0026, + 0167,0146,0042,0112,0077,0110,0062,0254,0366,0052,0377,0000,0163, + 0060,0000,0040,0000,0120,0000,0377,0060,0012,0000,0037,0000,0257, + 0037,0232,0157,0361,0040,0003,0125,0010,0001,0256,0000,0000,0340, + 0377,0377,0377,0377,0377,0377,0377,0377,0377,0377,0377,0017,0277, + 0253,0315,0257,0216,0377,0206,0146,0306,0371,0126,0232,0000,0004, + 0057,0012,0100,0360,0160,0360,0000,0040,0000,0017,0157,0000,0176, +}; + +Uchar xxh[26][13] = { + 0045,0150,0154,0162,0042,0246,0210,0147,0152,0103,0230,0017,0206, + 0100,0000,0040,0000,0140,0000,0000,0100,0000,0021,0120,0017,0060, + 0100,0000,0040,0002,0140,0320,0000,0060,0000,0001,0220,0017,0040, + 0100,0001,0120,0001,0241,0000,0000,0100,0000,0020,0140,0017,0060, + 0023,0162,0046,0142,0022,0207,0210,0131,0052,0106,0250,0017,0110, + 0060,0000,0042,0000,0160,0000,0000,0040,0000,0212,0100,0017,0000, + 0140,0000,0040,0002,0140,0000,0000,0120,0000,0040,0120,0017,0040, + 0100,0000,0100,0000,0140,0001,0021,0140,0000,0046,0100,0017,0140, + 0066,0045,0025,0201,0020,0130,0146,0030,0130,0103,0025,0017,0006, + 0100,0000,0040,0000,0020,0000,0000,0040,0000,0000,0200,0017,0000, + 0200,0000,0020,0001,0140,0000,0000,0140,0000,0000,0120,0017,0040, + 0120,0026,0042,0020,0140,0161,0042,0143,0000,0022,0162,0017,0040, + 0121,0042,0060,0020,0140,0200,0000,0123,0000,0021,0220,0017,0041, + 0121,0042,0060,0120,0140,0200,0000,0123,0000,0021,0160,0017,0041, + 0051,0126,0150,0141,0060,0210,0146,0066,0026,0165,0026,0017,0247, + 0120,0000,0040,0003,0160,0000,0000,0140,0000,0021,0100,0017,0140, + 0000,0000,0000,0000,0200,0000,0000,0000,0000,0000,0000,0017,0000, + 0141,0023,0122,0040,0160,0143,0042,0142,0000,0047,0143,0017,0020, + 0120,0000,0040,0006,0140,0060,0000,0141,0000,0026,0100,0017,0040, + 0140,0000,0020,0007,0100,0000,0000,0140,0000,0001,0140,0017,0020, + 0110,0125,0051,0162,0120,0125,0127,0104,0006,0104,0000,0017,0052, + 0140,0000,0040,0000,0160,0000,0000,0140,0000,0000,0060,0017,0000, + 0040,0005,0020,0000,0040,0313,0231,0030,0000,0140,0000,0017,0056, + 0140,0000,0160,0000,0200,0000,0000,0140,0000,0000,0000,0017,0240, + 0065,0042,0060,0040,0000,0206,0231,0146,0006,0224,0220,0017,0004, + 0240,0000,0020,0000,0140,0000,0000,0220,0000,0000,0200,0017,0141, +}; diff --git a/src/cmd/troff/mbwc.c b/src/cmd/troff/mbwc.c new file mode 100644 index 00000000..66a98219 --- /dev/null +++ b/src/cmd/troff/mbwc.c @@ -0,0 +1,165 @@ +#include <stdlib.h> + +/* + * Use the FSS-UTF transformation proposed by posix. + * We define 7 byte types: + * T0 0xxxxxxx 7 free bits + * Tx 10xxxxxx 6 free bits + * T1 110xxxxx 5 free bits + * T2 1110xxxx 4 free bits + * + * Encoding is as follows. + * From hex Thru hex Sequence Bits + * 00000000 0000007F T0 7 + * 00000080 000007FF T1 Tx 11 + * 00000800 0000FFFF T2 Tx Tx 16 + */ + +int +mblen(const char *s, size_t n) +{ + + return mbtowc(0, s, n); +} + +int +mbtowc(wchar_t *pwc, const char *s, size_t n) +{ + int c, c1, c2; + long l; + + if(!s) + return 0; + + if(n < 1) + goto bad; + c = s[0] & 0xff; + if((c & 0x80) == 0x00) { + if(pwc) + *pwc = c; + if(c == 0) + return 0; + return 1; + } + + if(n < 2) + goto bad; + c1 = (s[1] ^ 0x80) & 0xff; + if((c1 & 0xC0) != 0x00) + goto bad; + if((c & 0xE0) == 0xC0) { + l = ((c << 6) | c1) & 0x7FF; + if(l < 0x080) + goto bad; + if(pwc) + *pwc = l; + return 2; + } + + if(n < 3) + goto bad; + c2 = (s[2] ^ 0x80) & 0xff; + if((c2 & 0xC0) != 0x00) + goto bad; + if((c & 0xF0) == 0xE0) { + l = ((((c << 6) | c1) << 6) | c2) & 0xFFFF; + if(l < 0x0800) + goto bad; + if(pwc) + *pwc = l; + return 3; + } + + /* + * bad decoding + */ +bad: + return -1; + +} + +int +wctomb(char *s, wchar_t wchar) +{ + long c; + + if(!s) + return 0; + + c = wchar & 0xFFFF; + if(c < 0x80) { + s[0] = c; + return 1; + } + + if(c < 0x800) { + s[0] = 0xC0 | (c >> 6); + s[1] = 0x80 | (c & 0x3F); + return 2; + } + + s[0] = 0xE0 | (c >> 12); + s[1] = 0x80 | ((c >> 6) & 0x3F); + s[2] = 0x80 | (c & 0x3F); + return 3; +} + +size_t +mbstowcs(wchar_t *pwcs, const char *s, size_t n) +{ + int i, d, c; + + for(i=0; i < n; i++) { + c = *s & 0xff; + if(c < 0x80) { + *pwcs = c; + if(c == 0) + break; + s++; + } else { + d = mbtowc(pwcs, s, 3); + if(d <= 0) + return (size_t)((d<0) ? -1 : i); + s += d; + } + pwcs++; + } + return i; +} + +size_t +wcstombs(char *s, const wchar_t *pwcs, size_t n) +{ + int i, d; + long c; + char *p, *pe; + char buf[3]; + + p = s; + pe = p+n-3; + while(p < pe) { + c = *pwcs++; + if(c < 0x80) + *p++ = c; + else + p += wctomb(p, c); + if(c == 0) + return p-s; + } + while(p < pe+3) { + c = *pwcs++; + d = wctomb(buf, c); + if(p+d <= pe+3) { + *p++ = buf[0]; + if(d > 1) { + *p++ = buf[2]; + if(d > 2) + *p++ = buf[3]; + } + } + if(c == 0) + break; + } + return p-s; +} + diff --git a/src/cmd/troff/mk.log b/src/cmd/troff/mk.log new file mode 100644 index 00000000..26b610d6 --- /dev/null +++ b/src/cmd/troff/mk.log @@ -0,0 +1,136 @@ +9c -c -DUNICODE -DFONTDIR="sys/lib/troff/font" -DNTERMDIR="sys/lib/troff/term/tab." -DTEXHYPHENS="#9/sys/lib/texmf/tex/generic/hyphen/hyphen.tex" -DALTHYPHENS="sys/lib/texmf/tex/generic/hyphen/hyphen.tex" -DDWBHOME="#9/" n1.c +n1.c:51: warning: return type defaults to `int' +n1.c: In function `getch0': +n1.c:676: warning: unused variable `j' +n1.c:719: warning: label `g2' defined but not used +n1.c: In function `get1ch': +n1.c:745: warning: `n' might be used uninitialized in this function +n1.c:745: warning: `c' might be used uninitialized in this function +n1.c: In function `nextfile': +n1.c:830: warning: implicit declaration of function `unsharp' +n1.c:830: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n1.c: At top level: +n1.c:842: warning: return type defaults to `int' +n1.c:875: warning: return type defaults to `int' +n1.c:915: warning: return type defaults to `int' +n1.c: In function `getname': +n1.c:917: warning: unused variable `i' +n1.c: In function `caseso': +n1.c:939: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n1.c:935: warning: unused variable `p' +n1.c:935: warning: unused variable `q' +n1.c:934: warning: `fp' might be used uninitialized in this function +n1.c: In function `casecf': +n1.c:1008: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +9c -c -DUNICODE n2.c +n2.c: In function `outascii': +n2.c:140: warning: unused variable `p' +9c -c -DUNICODE n3.c +n3.c: In function `grow': +n3.c:67: warning: unused variable `new' +n3.c: In function `finds': +n3.c:310: warning: unused variable `j' +n3.c: In function `copyb': +n3.c:372: warning: `savoff' might be used uninitialized in this function +9c -c -DUNICODE n4.c +n4.c: In function `setn': +n4.c:144: warning: int format, long unsigned int arg (arg 3) +9c -c -DUNICODE n5.c +n5.c:83: warning: return type defaults to `int' +n5.c: In function `chget': +n5.c:84: warning: `i' might be used uninitialized in this function +n5.c: At top level: +n5.c:147: warning: return type defaults to `int' +n5.c:338: warning: return type defaults to `int' +n5.c: In function `casefm': +n5.c:411: warning: implicit declaration of function `unsharp' +n5.c:411: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n5.c: At top level: +n5.c:747: warning: return type defaults to `int' +n5.c:835: warning: return type defaults to `int' +9c -c -DUNICODE t6.c +t6.c:18: warning: return type defaults to `int' +t6.c:79: warning: return type defaults to `int' +t6.c:112: warning: return type defaults to `int' +t6.c: In function `t_setch': +t6.c:217: warning: unused variable `j' +t6.c: At top level: +t6.c:288: warning: return type defaults to `int' +t6.c:367: warning: return type defaults to `int' +t6.c: In function `t_setps': +t6.c:397: warning: `j' might be used uninitialized in this function +t6.c: At top level: +t6.c:707: warning: return type defaults to `int' +t6.c: In function `setfp': +t6.c:708: warning: unused variable `sl' +t6.c: In function `casebd': +t6.c:781: warning: `j' might be used uninitialized in this function +9c -c -DUNICODE n6.c +n6.c:11: warning: return type defaults to `int' +n6.c: In function `n_casebd': +n6.c:295: warning: `j' might be used uninitialized in this function +9c -c -DUNICODE n7.c +n7.c: In function `newline': +n7.c:354: warning: `nlss' might be used uninitialized in this function +n7.c: At top level: +n7.c:450: warning: return type defaults to `int' +n7.c:482: warning: return type defaults to `int' +n7.c:509: warning: return type defaults to `int' +n7.c:544: warning: return type defaults to `int' +n7.c:653: warning: return type defaults to `int' +n7.c: In function `getword': +n7.c:654: warning: `j' might be used uninitialized in this function +9c -c -DUNICODE -DTEXHYPHENS="#9/sys/lib/texmf/tex/generic/hyphen/hyphen.tex" n8.c +n8.c:76: warning: return type defaults to `int' +n8.c:87: warning: return type defaults to `int' +n8.c:222: warning: return type defaults to `int' +n8.c:274: warning: return type defaults to `int' +n8.c:282: warning: return type defaults to `int' +n8.c: In function `digram': +n8.c:310: warning: `maxw' might be used uninitialized in this function +n8.c: At top level: +n8.c:346: warning: return type defaults to `int' +n8.c: In function `readpats': +n8.c:469: warning: implicit declaration of function `unsharp' +n8.c:469: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n8.c:470: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +9c -c -DUNICODE n9.c +n9.c:80: warning: return type defaults to `int' +n9.c: In function `setfield': +n9.c:340: warning: `rchar' might be used uninitialized in this function +9c -c -DUNICODE -DTDEVNAME="utf" t10.c +t10.c: In function `ptout0': +t10.c:179: warning: int format, long int arg (arg 3) +t10.c:183: warning: int format, long unsigned int arg (arg 3) +t10.c:303: warning: int format, long int arg (arg 3) +t10.c:157: warning: `w' might be used uninitialized in this function +9c -c -DUNICODE -DTDEVNAME="utf" n10.c +n10.c: In function `getnrfont': +n10.c:77: warning: unused variable `fin' +n10.c:81: warning: unused variable `cmd' +n10.c:80: warning: `code' might be used uninitialized in this function +n10.c: In function `n_ptinit': +n10.c:189: warning: implicit declaration of function `unsharp' +n10.c:189: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +n10.c:142: warning: unused variable `cp' +9c -c -DUNICODE t11.c +t11.c:21: warning: return type defaults to `int' +t11.c: In function `getdesc': +t11.c:26: warning: implicit declaration of function `unsharp' +t11.c:26: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +t11.c: In function `checkfont': +t11.c:67: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +t11.c: At top level: +t11.c:89: warning: return type defaults to `int' +t11.c: In function `getfont': +t11.c:100: warning: passing arg 1 of `fopen' makes pointer from integer without a cast +t11.c:94: warning: `nw' might be used uninitialized in this function +t11.c:94: warning: `code' might be used uninitialized in this function +t11.c: At top level: +t11.c:193: warning: return type defaults to `int' +t11.c:235: warning: return type defaults to `int' +9c -c -DUNICODE -DTMACDIR="sys/lib/tmac/tmac." ni.c +9c -c -DUNICODE hytab.c +9c -c -DUNICODE suftab.c +9c -c -DUNICODE -DDWBHOME="#9/" dwbinit.c +9l -o o.troff n1.o n2.o n3.o n4.o n5.o t6.o n6.o n7.o n8.o n9.o t10.o n10.o t11.o ni.o hytab.o suftab.o dwbinit.o /usr/local/plan9/lib/libbio.a /usr/local/plan9/lib/lib9.a diff --git a/src/cmd/troff/mkfile b/src/cmd/troff/mkfile new file mode 100644 index 00000000..c02084e7 --- /dev/null +++ b/src/cmd/troff/mkfile @@ -0,0 +1,58 @@ +<$PLAN9/src/mkhdr + +TARG=troff +OFILES=n1.$O\ + n2.$O\ + n3.$O\ + n4.$O\ + n5.$O\ + t6.$O\ + n6.$O\ + n7.$O\ + n8.$O\ + n9.$O\ + t10.$O\ + n10.$O\ + t11.$O\ + ni.$O\ + hytab.$O\ + suftab.$O\ + dwbinit.$O\ + mbwc.$O + +HFILES=tdef.h\ + fns.h\ + ext.h\ + dwbinit.h\ + + +SHORTLIB=bio 9 +<$PLAN9/src/mkone +CFLAGS=-c -DUNICODE + +TMACDIR='"tmac/tmac."' +FONTDIR='"troff/font"' +NTERMDIR='"troff/term/tab."' +ALTHYPHENS='"lib/hyphen.tex"' +TEXHYPHENS='"#9/lib/hyphen.tex"' +DWBHOME='"#9/"' +TDEVNAME='"utf"' +NDEVNAME='"utf"' + +ni.$O: ni.c $HFILES + $CC $CFLAGS -DTMACDIR=$TMACDIR ni.c + +t10.$O: t10.c $HFILES + $CC $CFLAGS -DTDEVNAME=$TDEVNAME t10.c + +n1.$O: n1.c $HFILES + $CC $CFLAGS -DFONTDIR=$FONTDIR -DNTERMDIR=$NTERMDIR -DTEXHYPHENS=$TEXHYPHENS -DALTHYPHENS=$ALTHYPHENS -DDWBHOME=$DWBHOME n1.c + +n10.$O: n10.c $HFILES + $CC $CFLAGS -DTDEVNAME=$NDEVNAME n10.c + +n8.$O: n8.c $HFILES + $CC $CFLAGS -DTEXHYPHENS=$TEXHYPHENS n8.c + +dwbinit.$O: dwbinit.c + $CC $CFLAGS -DDWBHOME=$DWBHOME dwbinit.c diff --git a/src/cmd/troff/n1.c b/src/cmd/troff/n1.c new file mode 100644 index 00000000..d0949fe2 --- /dev/null +++ b/src/cmd/troff/n1.c @@ -0,0 +1,1136 @@ +/* + * n1.c + * + * consume options, initialization, main loop, + * input routines, escape function calling + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" +#include "dwbinit.h" + +#undef MB_CUR_MAX +#define MB_CUR_MAX 3 + +#include <setjmp.h> +#include <time.h> + +char *Version = "March 11, 1994"; + +#ifndef DWBVERSION +#define DWBVERSION "???" +#endif + +char *DWBfontdir = FONTDIR; +char *DWBntermdir = NTERMDIR; +char *DWBalthyphens = ALTHYPHENS; +char *DWBhomedir = ""; + +dwbinit dwbpaths[] = { + &DWBfontdir, NULL, 0, + &DWBntermdir, NULL, 0, + &DWBalthyphens, NULL, 0, + &DWBhomedir, NULL, 0, + NULL, nextf, NS, + NULL, NULL, 0 +}; + +int TROFF = 1; /* assume we started in troff... */ + +jmp_buf sjbuf; +Offset ipl[NSO]; + +static FILE *ifile; +static FILE *ifl[NSO]; /* open input file pointers */ +char cfname[NSO+1][NS] = { "stdin" }; /* file name stack */ +int cfline[NSO]; /* input line count stack */ +char *progname; /* program name (troff or nroff) */ + +int trace = 0; /* tracing mode: default off */ +int trace1 = 0; + +main(int argc, char *argv[]) +{ + char *p; + int j; + Tchar i; + char buf[100]; + + ifile = stdin; + ptid = stdout; + + buf[0] = '\0'; /* make sure it's empty (silly 3b2) */ + progname = argv[0]; + if ((p = strrchr(progname, '/')) == NULL) + p = progname; + else + p++; + DWBinit(progname, dwbpaths); + if (strcmp(p, "nroff") == 0) + TROFF = 0; +#ifdef UNICODE + alphabet = 128; /* unicode for plan 9 */ +#endif /*UNICODE*/ + mnspace(); + nnspace(); + mrehash(); + nrehash(); + numtabp[NL].val = -1; + + while (--argc > 0 && (++argv)[0][0] == '-') + switch (argv[0][1]) { + + case 'N': /* ought to be used first... */ + TROFF = 0; + break; + case 'd': + fprintf(stderr, "troff/nroff version %s\n", Version); + break; + case 'F': /* switch font tables from default */ + if (argv[0][2] != '\0') { + strcpy(termtab, &argv[0][2]); + strcpy(fontdir, &argv[0][2]); + } else { + argv++; argc--; + strcpy(termtab, argv[0]); + strcpy(fontdir, argv[0]); + } + break; + case 0: + goto start; + case 'i': + stdi++; + break; + case 'n': + npn = atoi(&argv[0][2]); + break; + case 'u': /* set emboldening amount */ + bdtab[3] = atoi(&argv[0][2]); + if (bdtab[3] < 0 || bdtab[3] > 50) + bdtab[3] = 0; + break; + case 's': + if (!(stop = atoi(&argv[0][2]))) + stop++; + break; + case 'r': + sprintf(buf + strlen(buf), ".nr %c %s\n", + argv[0][2], &argv[0][3]); + /* not yet cpushback(buf);*/ + /* dotnr(&argv[0][2], &argv[0][3]); */ + break; + case 'm': + if (mflg++ >= NMF) { + ERROR "Too many macro packages: %s", argv[0] WARN; + break; + } + strcpy(mfiles[nmfi], nextf); + strcat(mfiles[nmfi++], &argv[0][2]); + break; + case 'o': + getpn(&argv[0][2]); + break; + case 'T': + strcpy(devname, &argv[0][2]); + dotT++; + break; + case 'a': + ascii = 1; + break; + case 'h': + hflg++; + break; + case 'e': + eqflg++; + break; + case 'q': + quiet++; + save_tty(); + break; + case 'V': + fprintf(stdout, "%croff: DWB %s\n", + TROFF ? 't' : 'n', DWBVERSION); + exit(0); + case 't': + if (argv[0][2] != '\0') + trace = trace1 = argv[0][2]; + break; /* for the sake of compatibility */ + default: + ERROR "unknown option %s", argv[0] WARN; + done(02); + } + +start: + /* + * cpushback maintains a LIFO, so push pack the -r arguments + * in reverse order to maintain a FIFO in case someone did -rC1 -rC3 + */ + if (buf[0]) { + char *p = buf; + while(*p++) + ; + while(p > buf) { + while(strncmp(p, ".nr", 3) != 0) + p--; + cpushback(p); + *p-- = '\0'; + } + } + argp = argv; + rargc = argc; + nmfi = 0; + init2(); + setjmp(sjbuf); +loop: + copyf = lgf = nb = nflush = nlflg = 0; + if (ip && rbf0(ip) == 0 && ejf && frame->pframe <= ejl && dip == d) { + nflush++; + trap = 0; + eject((Stack *)0); + goto loop; + } + i = getch(); + if (pendt) + goto Lt; + if ((j = cbits(i)) == XPAR) { + copyf++; + tflg++; + while (cbits(i) != '\n') + pchar(i = getch()); + tflg = 0; + copyf--; + goto loop; + } + if (j == cc || j == c2) { + if (j == c2) + nb++; + copyf++; + while ((j = cbits(i = getch())) == ' ' || j == '\t') + ; + ch = i; + copyf--; + control(getrq(), 1); + flushi(); + goto loop; + } +Lt: + ch = i; + text(); + if (nlflg) + numtabp[HP].val = 0; + goto loop; +} + + + +void init2(void) +{ + int i; + char buf[100]; + + for (i = NTRTAB; --i; ) + trtab[i] = i; + trtab[UNPAD] = ' '; + iflg = 0; + obufp = obuf; + if (TROFF) + t_ptinit(); + else + n_ptinit(); + mchbits(); + cvtime(); + numtabp[PID].val = getpid(); + numtabp[HP].val = init = 0; + numtabp[NL].val = -1; + nfo = 0; + copyf = raw = 0; + sprintf(buf, ".ds .T %s\n", devname); + cpushback(buf); + sprintf(buf, ".ds .P %s\n", DWBhomedir); + cpushback(buf); + numtabp[CD].val = -1; /* compensation */ + nx = mflg; + frame = stk = (Stack *)setbrk(STACKSIZE); + dip = &d[0]; + nxf = frame + 1; + for (i = 1; i < NEV; i++) /* propagate the environment */ + envcopy(&env[i], &env[0]); + for (i = 0; i < NEV; i++) { + if ((env[i]._word._bufp = (Tchar *)calloc(WDSIZE, sizeof(Tchar))) == NULL) { + ERROR "not enough room for word buffers" WARN; + done2(1); + } + env[i]._word._size = WDSIZE; + if ((env[i]._line._bufp = (Tchar *)calloc(LNSIZE, sizeof(Tchar))) == NULL) { + ERROR "not enough room for line buffers" WARN; + done2(1); + } + env[i]._line._size = LNSIZE; + } + if ((oline = (Tchar *)calloc(OLNSIZE, sizeof(Tchar))) == NULL) { + ERROR "not enough room for line buffers" WARN; + done2(1); + } + olinep = oline; + olnsize = OLNSIZE; + blockinit(); +} + +void cvtime(void) +{ + long tt; + struct tm *ltime; + + time(&tt); + ltime = localtime(&tt); + numtabp[YR].val = ltime->tm_year % 100; + numtabp[YR].fmt = 2; + numtabp[MO].val = ltime->tm_mon + 1; /* troff uses 1..12 */ + numtabp[DY].val = ltime->tm_mday; + numtabp[DW].val = ltime->tm_wday + 1; /* troff uses 1..7 */ +} + + + +char errbuf[200]; + +void errprint(void) /* error message printer */ +{ + int savecd = numtabp[CD].val; + + if (!nlflg) + numtabp[CD].val++; + + fprintf(stderr, "%s: ", progname); + fputs(errbuf, stderr); + if (cfname[ifi][0]) + fprintf(stderr, "; %s:%d", cfname[ifi], numtabp[CD].val); + fputs("\n", stderr); + if (cfname[ifi][0]) + stackdump(); + numtabp[CD].val = savecd; +} + + +int control(int a, int b) +{ + int j, k; + extern Contab *contabp; + + numerr.type = RQERR; + numerr.req = a; + if (a == 0 || (j = findmn(a)) == -1) + return(0); + if (contabp[j].f == 0) { + if (trace & TRMAC) + fprintf(stderr, "invoke macro %s\n", unpair(a)); + if (dip != d) + for (k = dilev; k; k--) + if (d[k].curd == a) { + ERROR "diversion %s invokes itself during diversion", + unpair(a) WARN; + edone(0100); + } + nxf->nargs = 0; + if (b) + collect(); + flushi(); + return pushi(contabp[j].mx, a); /* BUG??? all that matters is 0/!0 */ + } + if (b) { + if (trace & TRREQ) + fprintf(stderr, "invoke request %s\n", unpair(a)); + (*contabp[j].f)(); + } + return(0); +} + +void casept(void) +{ + int i; + + noscale++; + if (skip()) + i = trace1; + else { + i = max(inumb(&trace), 0); + if (nonumb) + i = trace1; + } + trace1 = trace; + trace = i; + noscale = 0; +} + + +int getrq(void) +{ + int i, j; + + if ((i = getach()) == 0 || (j = getach()) == 0) + goto rtn; + i = PAIR(i, j); +rtn: + return(i); +} + +/* + * table encodes some special characters, to speed up tests + * in getch, viz FLSS, RPT, f, \b, \n, fc, tabch, ldrch + */ + +char gchtab[NCHARS] = { + 000,004,000,000,010,000,000,000, /* fc, ldr */ + 001,002,001,000,001,000,000,000, /* \b, tab, nl, RPT */ + 000,000,000,000,000,000,000,000, + 000,001,000,001,000,000,000,000, /* FLSS, ESC */ + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,001,000, /* f */ + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, + 000,000,000,000,000,000,000,000, +}; + +int realcbits(Tchar c) /* return character bits, or MOTCH if motion */ +{ + if (ismot(c)) + return MOTCH; + else + return c & 0xFFFF; +} + +Tchar getch(void) +{ + int k; + Tchar i, j; + +g0: + if (ch) { + i = ch; + if (cbits(i) == '\n') + nlflg++; + ch = 0; + return(i); + } + + if (nlflg) + return('\n'); + i = getch0(); + if (ismot(i)) + return(i); + k = cbits(i); + if (k >= sizeof(gchtab)/sizeof(gchtab[0]) || gchtab[k] == 0) /* nothing special */ + return(i); + if (k != ESC) { + if (k == '\n') { + nlflg++; + if (ip == 0) + numtabp[CD].val++; /* line number */ + return(k); + } + if (k == FLSS) { + copyf++; + raw++; + i = getch0(); + if (!fi) + flss = i; + copyf--; + raw--; + goto g0; + } + if (k == RPT) { + setrpt(); + goto g0; + } + if (!copyf) { + if (k == 'f' && lg && !lgf) { + i = getlg(i); + return(i); + } + if (k == fc || k == tabch || k == ldrch) { + if ((i = setfield(k)) == 0) + goto g0; + else + return(i); + } + if (k == '\b') { + i = makem(-width(' ' | chbits)); + return(i); + } + } + return(i); + } + + k = cbits(j = getch0()); + if (ismot(j)) + return(j); + + switch (k) { + case 'n': /* number register */ + setn(); + goto g0; + case '$': /* argument indicator */ + seta(); + goto g0; + case '*': /* string indicator */ + setstr(); + goto g0; + case '{': /* LEFT */ + i = LEFT; + goto gx; + case '}': /* RIGHT */ + i = RIGHT; + goto gx; + case '"': /* comment */ + while (cbits(i = getch0()) != '\n') + ; + if (ip == 0) + numtabp[CD].val++; /* line number */ + nlflg++; + return(i); + +/* experiment: put it here instead of copy mode */ + case '(': /* special char name \(xx */ + case 'C': /* \C'...' */ + if ((i = setch(k)) == 0) + goto g0; + goto gx; + + case ESC: /* double backslash */ + i = eschar; + goto gx; + case 'e': /* printable version of current eschar */ + i = PRESC; + goto gx; + case '\n': /* concealed newline */ + numtabp[CD].val++; + goto g0; + case ' ': /* unpaddable space */ + i = UNPAD; + goto gx; + case '\'': /* \(aa */ + i = ACUTE; + goto gx; + case '`': /* \(ga */ + i = GRAVE; + goto gx; + case '_': /* \(ul */ + i = UNDERLINE; + goto gx; + case '-': /* current font minus */ + i = MINUS; + goto gx; + case '&': /* filler */ + i = FILLER; + goto gx; + case 'c': /* to be continued */ + i = CONT; + goto gx; + case '!': /* transparent indicator */ + i = XPAR; + goto gx; + case 't': /* tab */ + i = '\t'; + return(i); + case 'a': /* leader (SOH) */ +/* old: *pbp++ = LEADER; goto g0; */ + i = LEADER; + return i; + case '%': /* ohc */ + i = OHC; + return(i); + case 'g': /* return format of a number register */ + setaf(); /* should this really be in copy mode??? */ + goto g0; + case '.': /* . */ + i = '.'; +gx: + setsfbits(i, sfbits(j)); + return(i); + } + if (copyf) { + *pbp++ = j; + return(eschar); + } + switch (k) { + + case 'f': /* font indicator */ + setfont(0); + goto g0; + case 's': /* size indicator */ + setps(); + goto g0; + case 'v': /* vert mot */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if (i = vmot()) { + return(i); + } + goto g0; + case 'h': /* horiz mot */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if (i = hmot()) + return(i); + goto g0; + case '|': /* narrow space */ + if (NROFF) + goto g0; + return(makem((int)(EM)/6)); + case '^': /* half narrow space */ + if (NROFF) + goto g0; + return(makem((int)(EM)/12)); + case 'w': /* width function */ + setwd(); + goto g0; + case 'p': /* spread */ + spread++; + goto g0; + case 'N': /* absolute character number */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if ((i = setabs()) == 0) + goto g0; + return i; + case 'H': /* character height */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + return(setht()); + case 'S': /* slant */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + return(setslant()); + case 'z': /* zero with char */ + return(setz()); + case 'l': /* hor line */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + setline(); + goto g0; + case 'L': /* vert line */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + setvline(); + goto g0; + case 'D': /* drawing function */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + setdraw(); + goto g0; + case 'X': /* \X'...' for copy through */ + setxon(); + goto g0; + case 'b': /* bracket */ + setbra(); + goto g0; + case 'o': /* overstrike */ + setov(); + goto g0; + case 'k': /* mark hor place */ + if ((k = findr(getsn())) != -1) { + numtabp[k].val = numtabp[HP].val; + } + goto g0; + case '0': /* number space */ + return(makem(width('0' | chbits))); + case 'x': /* extra line space */ + numerr.type = numerr.escarg = 0; numerr.esc = k; + if (i = xlss()) + return(i); + goto g0; + case 'u': /* half em up */ + case 'r': /* full em up */ + case 'd': /* half em down */ + return(sethl(k)); + default: + return(j); + } + /* NOTREACHED */ +} + +void setxon(void) /* \X'...' for copy through */ +{ + Tchar xbuf[NC]; + Tchar *i; + Tchar c; + int delim, k; + + if (ismot(c = getch())) + return; + delim = cbits(c); + i = xbuf; + *i++ = XON | chbits; + while ((k = cbits(c = getch())) != delim && k != '\n' && i < xbuf+NC-1) { + if (k == ' ') + setcbits(c, WORDSP); + *i++ = c | ZBIT; + } + *i++ = XOFF | chbits; + *i = 0; + pushback(xbuf); +} + + +char ifilt[32] = { 0, 001, 002, 003, 0, 005, 006, 007, 010, 011, 012 }; + +Tchar getch0(void) +{ + int j; + Tchar i; + +again: + if (pbp > lastpbp) + i = *--pbp; + else if (ip) { + /* i = rbf(); */ + i = rbf0(ip); + if (i == 0) + i = rbf(); + else { + ++ip; + if (pastend(ip)) { + --ip; + rbf(); + } + } + } else { + if (donef || ndone) + done(0); + if (nx || 1) { /* BUG: was ibufp >= eibuf, so EOF test is wrong */ + if (nfo < 0) + ERROR "in getch0, nfo = %d", nfo WARN; + if (nfo == 0) { +g0: + if (nextfile()) { + if (ip) + goto again; + } + } + nx = 0; +#ifdef UNICODE + if (MB_CUR_MAX > 1) + i = get1ch(ifile); + else +#endif /*UNICODE*/ + i = getc(ifile); + if (i == EOF) + goto g0; + if (ip) + goto again; + } +g2: + if (i >= 040) /* zapped: && i < 0177 */ + goto g4; + i = ifilt[i]; + } + if (cbits(i) == IMP && !raw) + goto again; + if (i == 0 && !init && !raw) { /* zapped: || i == 0177 */ + goto again; + } +g4: + if (ismot(i)) + return i; + if (copyf == 0 && sfbits(i) == 0) + i |= chbits; + if (cbits(i) == eschar && !raw) + setcbits(i, ESC); + return(i); +} + + +#ifdef UNICODE +Tchar get1ch(FILE *fp) /* get one "character" from input, figure out what alphabet */ +{ + wchar_t wc; + char buf[100], *p; + int i, n, c; + + for (i = 0, p = buf; i < MB_CUR_MAX; i++) { + if ((c = getc(fp)) == EOF) + return c; + *p++ = c; + if ((n = mbtowc(&wc, buf, p-buf)) >= 0) + break; + } + if (n == 1) /* real ascii, presumably */ + return wc; + if (n == 0) + return p[-1]; /* illegal, but what else to do? */ + if (c == EOF) + return EOF; + *p = 0; + return chadd(buf, MBchar, Install); /* add name even if haven't seen it */ +} +#endif /*UNICODE*/ + +void pushback(Tchar *b) +{ + Tchar *ob = b; + + while (*b++) + ; + b--; + while (b > ob && pbp < &pbbuf[NC-3]) + *pbp++ = *--b; + if (pbp >= &pbbuf[NC-3]) { + ERROR "pushback overflow" WARN; + done(2); + } +} + +void cpushback(char *b) +{ + char *ob = b; + + while (*b++) + ; + b--; + while (b > ob && pbp < &pbbuf[NC-3]) + *pbp++ = *--b; + if (pbp >= &pbbuf[NC-3]) { + ERROR "cpushback overflow" WARN; + done(2); + } +} + +int nextfile(void) +{ + char *p; + +n0: + if (ifile != stdin) + fclose(ifile); + if (ifi > 0 && !nx) { + if (popf()) + goto n0; /* popf error */ + return(1); /* popf ok */ + } + if (nx || nmfi < mflg) { + p = mfiles[nmfi++]; + if (*p != 0) + goto n1; + } + if (rargc-- <= 0) { + if ((nfo -= mflg) && !stdi) { + done(0); +} + nfo++; + numtabp[CD].val = stdi = mflg = 0; + ifile = stdin; + strcpy(cfname[ifi], "stdin"); + return(0); + } + p = (argp++)[0]; + if (rargc >= 0) + cfname[ifi][0] = 0; +n1: + numtabp[CD].val = 0; + if (p[0] == '-' && p[1] == 0) { + ifile = stdin; + strcpy(cfname[ifi], "stdin"); + } else if ((ifile = fopen(unsharp(p), "r")) == NULL) { + ERROR "cannot open file %s", p WARN; + nfo -= mflg; + done(02); + } else + strcpy(cfname[ifi],p); + nfo++; + return(0); +} + + +popf(void) +{ + --ifi; + if (ifi < 0) { + ERROR "popf went negative" WARN; + return 1; + } + numtabp[CD].val = cfline[ifi]; /* restore line counter */ + ip = ipl[ifi]; /* input pointer */ + ifile = ifl[ifi]; /* input FILE * */ + return(0); +} + + +void flushi(void) +{ + if (nflush) + return; + ch = 0; + copyf++; + while (!nlflg) { + if (donef && frame == stk) + break; + getch(); + } + copyf--; +} + +/* + * return 16-bit, ascii/alphabetic character, ignore chars with more bits, + * (internal names), spaces and special cookies (below 040). + * Leave STX ETX ENQ ACK and BELL in to maintain compatibility with v7 troff. + */ +getach(void) +{ + Tchar i; + int j; + + lgf++; + j = cbits(i = getch()); + if (ismot(i) + || j > SHORTMASK + || (j <= 040 && j != 002 /*STX*/ + && j != 003 /*ETX*/ + && j != 005 /*ENQ*/ + && j != 006 /*ACK*/ + && j != 007)) { /*BELL*/ + ch = i; + j = 0; + } + lgf--; + return j; +} + + +void casenx(void) +{ + lgf++; + skip(); + getname(); + nx++; + if (nmfi > 0) + nmfi--; + strcpy(mfiles[nmfi], nextf); + nextfile(); + nlflg++; + ip = 0; + pendt = 0; + frame = stk; + nxf = frame + 1; +} + + +getname(void) +{ + int j, k; + Tchar i; + + lgf++; + for (k = 0; k < NS - 1; k++) { + j = getach(); + if (!j) + break; + nextf[k] = j; + } + nextf[k] = 0; + lgf--; + return(nextf[0]); +} + + +void caseso(void) +{ + FILE *fp; + char *p, *q; + + lgf++; + nextf[0] = 0; + if (skip() || !getname() || (fp = fopen(unsharp(nextf), "r")) == NULL || ifi >= NSO) { + ERROR "can't open file %s", nextf WARN; + done(02); + } + strcpy(cfname[ifi+1], nextf); + cfline[ifi] = numtabp[CD].val; /*hold line counter*/ + numtabp[CD].val = 0; + flushi(); + ifl[ifi] = ifile; + ifile = fp; + ipl[ifi] = ip; + ip = 0; + nx++; + nflush++; + ifi++; +} + +void caself(void) /* set line number and file */ +{ + int n; + + if (skip()) + return; + n = atoi0(); + if (!nonumb) + cfline[ifi] = numtabp[CD].val = n - 1; + if (!skip()) + if (getname()) { /* eats '\n' ? */ + strcpy(cfname[ifi], nextf); + if (!nonumb) + numtabp[CD].val--; + } +} + +void cpout(FILE *fin, char *token) +{ + int n; + char buf[1024]; + + if (token) { /* BUG: There should be no NULL bytes in input */ + char *newl = buf; + while ((fgets(buf, sizeof buf, fin)) != NULL) { + if (newl) { + numtabp[CD].val++; /* line number */ + if (strcmp(token, buf) == 0) + return; + } + newl = strchr(buf, '\n'); + fputs(buf, ptid); + } + } else { + while ((n = fread(buf, sizeof *buf, sizeof buf, fin)) > 0) + fwrite(buf, n, 1, ptid); + fclose(fin); + } +} + +void casecf(void) +{ /* copy file without change */ + FILE *fd; + char *eof, *p; + extern int hpos, esc, po; + + /* this may not make much sense in nroff... */ + + lgf++; + nextf[0] = 0; + if (!skip() && getname()) { + if (strncmp("<<", nextf, 2) != 0) { + if ((fd = fopen(unsharp(nextf), "r")) == NULL) { + ERROR "can't open file %s", nextf WARN; + done(02); + } + eof = (char *) NULL; + } else { /* current file */ + if (pbp > lastpbp || ip) { + ERROR "casecf: not reading from file" WARN; + done(02); + } + eof = &nextf[2]; + if (!*eof) { + ERROR "casecf: missing end of input token" WARN; + done(02); + } + p = eof; + while(*++p) + ; + *p++ = '\n'; + *p = 0; + fd = ifile; + } + } else { + ERROR "casecf: no argument" WARN; + lgf--; + return; + } + lgf--; + + /* make it into a clean state, be sure that everything is out */ + tbreak(); + hpos = po; + esc = 0; + ptesc(); /* to left margin */ + esc = un; + ptesc(); + ptlead(); + ptps(); + ptfont(); + flusho(); + cpout(fd, eof); + ptps(); + ptfont(); +} + +void getline(char *s, int n) /* get rest of input line into s */ +{ + int i; + + lgf++; + copyf++; + skip(); + for (i = 0; i < n-1; i++) + if ((s[i] = cbits(getch())) == '\n' || s[i] == RIGHT) + break; + s[i] = 0; + copyf--; + lgf--; +} + +void casesy(void) /* call system */ +{ + char sybuf[NTM]; + + getline(sybuf, NTM); + system(sybuf); +} + + +void getpn(char *a) +{ + int n, neg; + + if (*a == 0) + return; + neg = 0; + for ( ; *a; a++) + switch (*a) { + case '+': + case ',': + continue; + case '-': + neg = 1; + continue; + default: + n = 0; + if (isdigit(*a)) { + do + n = 10 * n + *a++ - '0'; + while (isdigit(*a)); + a--; + } else + n = 9999; + *pnp++ = neg ? -n : n; + neg = 0; + if (pnp >= &pnlist[NPN-2]) { + ERROR "too many page numbers" WARN; + done3(-3); + } + } + if (neg) + *pnp++ = -9999; + *pnp = -INT_MAX; + print = 0; + pnp = pnlist; + if (*pnp != -INT_MAX) + chkpn(); +} + + +void setrpt(void) +{ + Tchar i, j; + + copyf++; + raw++; + i = getch0(); + copyf--; + raw--; + if ((long) i < 0 || cbits(j = getch0()) == RPT) + return; + while (i > 0 && pbp < &pbbuf[NC-3]) { + i--; + *pbp++ = j; + } +} diff --git a/src/cmd/troff/n10.c b/src/cmd/troff/n10.c new file mode 100644 index 00000000..0183cadc --- /dev/null +++ b/src/cmd/troff/n10.c @@ -0,0 +1,549 @@ +/* +n10.c + +Device interfaces +*/ + +#include "tdef.h" +#include "ext.h" +#include "fns.h" +#include <ctype.h> + +Term t; /* terminal characteristics */ + +int dtab; +int plotmode; +int esct; + +enum { Notype = 0, Type = 1 }; + +static char *parse(char *s, int typeit) /* convert \0, etc to nroff driving table format */ +{ /* typeit => add a type id to the front for later use */ + static char buf[100], *t, *obuf; + int quote = 0; + wchar_t wc; + + obuf = typeit == Type ? buf : buf+1; +#ifdef UNICODE + if (mbtowc(&wc, s, strlen(s)) > 1) { /* it's multibyte, */ + buf[0] = MBchar; + strcpy(buf+1, s); + return obuf; + } /* so just hand it back */ +#endif /*UNICODE*/ + buf[0] = Troffchar; + t = buf + 1; + if (*s == '"') { + s++; + quote = 1; + } + for (;;) { + if (quote && *s == '"') { + s++; + break; + } + if (!quote && (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\0')) + break; + if (*s != '\\') + *t++ = *s++; + else { + s++; /* skip \\ */ + if (isdigit(s[0]) && isdigit(s[1]) && isdigit(s[2])) { + *t++ = (s[0]-'0')<<6 | (s[1]-'0')<<3 | s[2]-'0'; + s += 2; + } else if (isdigit(s[0])) { + *t++ = *s - '0'; + } else if (*s == 'b') { + *t++ = '\b'; + } else if (*s == 'n') { + *t++ = '\n'; + } else if (*s == 'r') { + *t++ = '\r'; + } else if (*s == 't') { + *t++ = '\t'; + } else { + *t++ = *s; + } + s++; + } + } + *t = '\0'; + return obuf; +} + + +static int getnrfont(FILE *fp) /* read the nroff description file */ +{ + FILE *fin; + Chwid chtemp[NCHARS]; + static Chwid chinit; + int i, nw, n, wid, code, type; + char buf[100], ch[100], s1[100], s2[100], cmd[300]; + wchar_t wc; + + + chinit.wid = 1; + chinit.str = ""; + for (i = 0; i < ALPHABET; i++) { + chtemp[i] = chinit; /* zero out to begin with */ + chtemp[i].num = chtemp[i].code = i; /* every alphabetic character is itself */ + chtemp[i].wid = 1; /* default ascii widths */ + } + skipline(fp); + nw = ALPHABET; + while (fgets(buf, sizeof buf, fp) != NULL) { + sscanf(buf, "%s %s %[^\n]", ch, s1, s2); + if (!eq(s1, "\"")) { /* genuine new character */ + sscanf(s1, "%d", &wid); + } /* else it's a synonym for prev character, */ + /* so leave previous values intact */ + + /* decide what kind of alphabet it might come from */ + + if (strlen(ch) == 1) { /* it's ascii */ + n = ch[0]; /* origin includes non-graphics */ + chtemp[n].num = ch[0]; + } else if (ch[0] == '\\' && ch[1] == '0') { + n = strtol(ch+1, 0, 0); /* \0octal or \0xhex */ + chtemp[n].num = n; +#ifdef UNICODE + } else if (mbtowc(&wc, ch, strlen(ch)) > 1) { + chtemp[nw].num = chadd(ch, MBchar, Install); + n = nw; + nw++; +#endif /*UNICODE*/ + } else { + if (strcmp(ch, "---") == 0) { /* no name */ + sprintf(ch, "%d", code); + type = Number; + } else + type = Troffchar; +/* BUG in here somewhere when same character occurs twice in table */ + chtemp[nw].num = chadd(ch, type, Install); + n = nw; + nw++; + } + chtemp[n].wid = wid; + chtemp[n].str = strdupl(parse(s2, Type)); + } + t.tfont.nchars = nw; + t.tfont.wp = (Chwid *) malloc(nw * sizeof(Chwid)); + if (t.tfont.wp == NULL) + return -1; + for (i = 0; i < nw; i++) + t.tfont.wp[i] = chtemp[i]; + return 1; +} + + +void n_ptinit(void) +{ + int i; + char *p, *cp; + char opt[50], cmd[100]; + FILE *fp; + + hmot = n_hmot; + makem = n_makem; + setabs = n_setabs; + setch = n_setch; + sethl = n_sethl; + setht = n_setht; + setslant = n_setslant; + vmot = n_vmot; + xlss = n_xlss; + findft = n_findft; + width = n_width; + mchbits = n_mchbits; + ptlead = n_ptlead; + ptout = n_ptout; + ptpause = n_ptpause; + setfont = n_setfont; + setps = n_setps; + setwd = n_setwd; + + if ((p = getenv("NROFFTERM")) != 0) + strcpy(devname, p); + if (termtab[0] == 0) + strcpy(termtab,DWBntermdir); + if (fontdir[0] == 0) + strcpy(fontdir, ""); + if (devname[0] == 0) + strcpy(devname, NDEVNAME); + pl = 11*INCH; + po = PO; + hyf = 0; + ascii = 1; + lg = 0; + fontlab[1] = 'R'; + fontlab[2] = 'I'; + fontlab[3] = 'B'; + fontlab[4] = PAIR('B','I'); + fontlab[5] = 'D'; + bdtab[3] = 3; + bdtab[4] = 3; + + /* hyphalg = 0; /* for testing */ + + strcat(termtab, devname); + if ((fp = fopen(unsharp(termtab), "r")) == NULL) { + ERROR "cannot open %s", termtab WARN; + exit(-1); + } + + +/* this loop isn't robust about input format errors. */ +/* it assumes name, name-value pairs..., charset */ +/* god help us if we get out of sync. */ + + fscanf(fp, "%s", cmd); /* should be device name... */ + if (!is(devname) && trace) + ERROR "wrong terminal name: saw %s, wanted %s", cmd, devname WARN; + for (;;) { + fscanf(fp, "%s", cmd); + if (is("charset")) + break; + fscanf(fp, " %[^\n]", opt); + if (is("bset")) t.bset = atoi(opt); + else if (is("breset")) t.breset = atoi(opt); + else if (is("Hor")) t.Hor = atoi(opt); + else if (is("Vert")) t.Vert = atoi(opt); + else if (is("Newline")) t.Newline = atoi(opt); + else if (is("Char")) t.Char = atoi(opt); + else if (is("Em")) t.Em = atoi(opt); + else if (is("Halfline")) t.Halfline = atoi(opt); + else if (is("Adj")) t.Adj = atoi(opt); + else if (is("twinit")) t.twinit = strdupl(parse(opt, Notype)); + else if (is("twrest")) t.twrest = strdupl(parse(opt, Notype)); + else if (is("twnl")) t.twnl = strdupl(parse(opt, Notype)); + else if (is("hlr")) t.hlr = strdupl(parse(opt, Notype)); + else if (is("hlf")) t.hlf = strdupl(parse(opt, Notype)); + else if (is("flr")) t.flr = strdupl(parse(opt, Notype)); + else if (is("bdon")) t.bdon = strdupl(parse(opt, Notype)); + else if (is("bdoff")) t.bdoff = strdupl(parse(opt, Notype)); + else if (is("iton")) t.iton = strdupl(parse(opt, Notype)); + else if (is("itoff")) t.itoff = strdupl(parse(opt, Notype)); + else if (is("ploton")) t.ploton = strdupl(parse(opt, Notype)); + else if (is("plotoff")) t.plotoff = strdupl(parse(opt, Notype)); + else if (is("up")) t.up = strdupl(parse(opt, Notype)); + else if (is("down")) t.down = strdupl(parse(opt, Notype)); + else if (is("right")) t.right = strdupl(parse(opt, Notype)); + else if (is("left")) t.left = strdupl(parse(opt, Notype)); + else + ERROR "bad tab.%s file, %s %s", devname, cmd, opt WARN; + } + + getnrfont(fp); + fclose(fp); + + sps = EM; + ics = EM * 2; + dtab = 8 * t.Em; + for (i = 0; i < 16; i++) + tabtab[i] = dtab * (i + 1); + pl = 11 * INCH; + po = PO; + spacesz = SS; + lss = lss1 = VS; + ll = ll1 = lt = lt1 = LL; + smnt = nfonts = 5; /* R I B BI S */ + n_specnames(); /* install names like "hyphen", etc. */ + if (eqflg) + t.Adj = t.Hor; +} + + +void n_specnames(void) +{ + + int i; + + for (i = 0; spnames[i].n; i++) + *spnames[i].n = chadd(spnames[i].v, Troffchar, Install); + if (c_isalnum == 0) + c_isalnum = NROFFCHARS; +} + +void twdone(void) +{ + if (!TROFF && t.twrest) { + obufp = obuf; + oputs(t.twrest); + flusho(); + if (pipeflg) { + pclose(ptid); + } + restore_tty(); + } +} + + +void n_ptout(Tchar i) +{ + *olinep++ = i; + if (olinep >= &oline[LNSIZE]) + olinep--; + if (cbits(i) != '\n') + return; + olinep--; + lead += dip->blss + lss - t.Newline; + dip->blss = 0; + esct = esc = 0; + if (olinep > oline) { + move(); + ptout1(); + oputs(t.twnl); + } else { + lead += t.Newline; + move(); + } + lead += dip->alss; + dip->alss = 0; + olinep = oline; +} + + +void ptout1(void) +{ + int k; + char *codep; + int w, j, phyw; + Tchar *q, i; + static int oxfont = FT; /* start off in roman */ + + for (q = oline; q < olinep; q++) { + i = *q; + if (ismot(i)) { + j = absmot(i); + if (isnmot(i)) + j = -j; + if (isvmot(i)) + lead += j; + else + esc += j; + continue; + } + if ((k = cbits(i)) <= ' ') { + switch (k) { + case ' ': /*space*/ + esc += t.Char; + break; + case '\033': + case '\007': + case '\016': + case '\017': + oput(k); + break; + } + continue; + } + phyw = w = t.Char * t.tfont.wp[k].wid; + if (iszbit(i)) + w = 0; + if (esc || lead) + move(); + esct += w; + xfont = fbits(i); + if (xfont != oxfont) { + switch (oxfont) { + case ULFONT: oputs(t.itoff); break; + case BDFONT: oputs(t.bdoff); break; + case BIFONT: oputs(t.itoff); oputs(t.bdoff); break; + } + switch (xfont) { + case ULFONT: + if (*t.iton & 0377) oputs(t.iton); break; + case BDFONT: + if (*t.bdon & 0377) oputs(t.bdon); break; + case BIFONT: + if (*t.bdon & 0377) oputs(t.bdon); + if (*t.iton & 0377) oputs(t.iton); + break; + } + oxfont = xfont; + } + if ((xfont == ulfont || xfont == BIFONT) && !(*t.iton & 0377)) { + for (j = w / t.Char; j > 0; j--) + oput('_'); + for (j = w / t.Char; j > 0; j--) + oput('\b'); + } + if (!(*t.bdon & 0377) && ((j = bdtab[xfont]) || xfont == BDFONT || xfont == BIFONT)) + j++; + else + j = 1; /* number of overstrikes for bold */ + if (k < ALPHABET) { /* ordinary ascii */ + oput(k); + while (--j > 0) { + oput('\b'); + oput(k); + } + } else if (k >= t.tfont.nchars) { /* BUG -- not really understood */ +/* fprintf(stderr, "big char %d, name %s\n", k, chname(k)); /* */ + oputs(chname(k)+1); /* BUG: should separate Troffchar and MBchar... */ + } else if (t.tfont.wp[k].str == 0) { +/* fprintf(stderr, "nostr char %d, name %s\n", k, chname(k)); /* */ + oputs(chname(k)+1); /* BUG: should separate Troffchar and MBchar... */ + } else if (t.tfont.wp[k].str[0] == MBchar) { /* parse() puts this on */ +/* fprintf(stderr, "MBstr char %d, name %s\n", k, chname(k)); /* */ + oputs(t.tfont.wp[k].str+1); + } else { + int oj = j; +/* fprintf(stderr, "str char %d, name %s\n", k, chname(k)); /* */ + codep = t.tfont.wp[k].str+1; /* Troffchar by default */ + while (*codep != 0) { + if (*codep & 0200) { + codep = plot(codep); + oput(' '); + } else { + if (*codep == '%') /* escape */ + codep++; + oput(*codep); + if (*codep == '\033') + oput(*++codep); + else if (*codep != '\b') + for (j = oj; --j > 0; ) { + oput('\b'); + oput(*codep); + } + codep++; + } + } + } + if (!w) + for (j = phyw / t.Char; j > 0; j--) + oput('\b'); + } +} + + +char *plot(char *x) +{ + int i; + char *j, *k; + + oputs(t.ploton); + k = x; + if ((*k & 0377) == 0200) + k++; + for (; *k; k++) { + if (*k == '%') { /* quote char within plot mode */ + oput(*++k); + } else if (*k & 0200) { + if (*k & 0100) { + if (*k & 040) + j = t.up; + else + j = t.down; + } else { + if (*k & 040) + j = t.left; + else + j = t.right; + } + if ((i = *k & 037) == 0) { /* 2nd 0200 turns it off */ + ++k; + break; + } + while (i--) + oputs(j); + } else + oput(*k); + } + oputs(t.plotoff); + return(k); +} + + +void move(void) +{ + int k; + char *i, *j; + char *p, *q; + int iesct, dt; + + iesct = esct; + if (esct += esc) + i = "\0"; + else + i = "\n\0"; + j = t.hlf; + p = t.right; + q = t.down; + if (lead) { + if (lead < 0) { + lead = -lead; + i = t.flr; + /* if(!esct)i = t.flr; else i = "\0";*/ + j = t.hlr; + q = t.up; + } + if (*i & 0377) { + k = lead / t.Newline; + lead = lead % t.Newline; + while (k--) + oputs(i); + } + if (*j & 0377) { + k = lead / t.Halfline; + lead = lead % t.Halfline; + while (k--) + oputs(j); + } else { /* no half-line forward, not at line begining */ + k = lead / t.Newline; + lead = lead % t.Newline; + if (k > 0) + esc = esct; + i = "\n"; + while (k--) + oputs(i); + } + } + if (esc) { + if (esc < 0) { + esc = -esc; + j = "\b"; + p = t.left; + } else { + j = " "; + if (hflg) + while ((dt = dtab - (iesct % dtab)) <= esc) { + if (dt % t.Em) + break; + oput(TAB); + esc -= dt; + iesct += dt; + } + } + k = esc / t.Em; + esc = esc % t.Em; + while (k--) + oputs(j); + } + if ((*t.ploton & 0377) && (esc || lead)) { + oputs(t.ploton); + esc /= t.Hor; + lead /= t.Vert; + while (esc--) + oputs(p); + while (lead--) + oputs(q); + oputs(t.plotoff); + } + esc = lead = 0; +} + + +void n_ptlead(void) +{ + move(); +} + + +void n_ptpause(void ) +{ + char junk; + + flusho(); + read(2, &junk, 1); +} diff --git a/src/cmd/troff/n2.c b/src/cmd/troff/n2.c new file mode 100644 index 00000000..8164c038 --- /dev/null +++ b/src/cmd/troff/n2.c @@ -0,0 +1,325 @@ +/* + * n2.c + * + * output, cleanup + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" +#include <setjmp.h> + +#ifdef STRICT + /* not in ANSI or POSIX */ +FILE* popen(char*, char*); +#endif + + +extern jmp_buf sjbuf; +int toolate; +int error; + +char obuf[2*BUFSIZ]; +char *obufp = obuf; + + /* pipe command structure; allows redicously long commends for .pi */ +struct Pipe { + char *buf; + int tick; + int cnt; +} Pipe; + + +int xon = 0; /* records if in middle of \X */ + +int pchar(Tchar i) +{ + int j; + static int hx = 0; /* records if have seen HX */ + + if (hx) { + hx = 0; + j = absmot(i); + if (isnmot(i)) { + if (j > dip->blss) + dip->blss = j; + } else { + if (j > dip->alss) + dip->alss = j; + ralss = dip->alss; + } + return 0; + } + if (ismot(i)) { + pchar1(i); + return 0; + } + switch (j = cbits(i)) { + case 0: + case IMP: + case RIGHT: + case LEFT: + return 0; + case HX: + hx = 1; + return 0; + case XON: + xon++; + break; + case XOFF: + xon--; + break; + case PRESC: + if (!xon && !tflg && dip == &d[0]) + j = eschar; /* fall through */ + default: + setcbits(i, trtab[j]); + } + if (NROFF & xon) /* rob fix for man2html */ + return 0; + pchar1(i); + return 0; +} + + +void pchar1(Tchar i) +{ + int j; + + j = cbits(i); + if (dip != &d[0]) { + wbf(i); + dip->op = offset; + return; + } + if (!tflg && !print) { + if (j == '\n') + dip->alss = dip->blss = 0; + return; + } + if (j == FILLER && !xon) + return; + if (tflg) { /* transparent mode, undiverted */ + if (print) /* assumes that it's ok to print */ + /* OUT "%c", j PUT; /* i.e., is ascii */ + outascii(i); + return; + } + if (TROFF && ascii) + outascii(i); + else + ptout(i); +} + + +void outweird(int k) /* like ptchname() but ascii */ +{ + char *chn = chname(k); + + switch (chn[0]) { + case MBchar: + OUT "%s", chn+1 PUT; /* \n not needed? */ + break; + case Number: + OUT "\\N'%s'", chn+1 PUT; + break; + case Troffchar: + if (strlen(chn+1) == 2) + OUT "\\(%s", chn+1 PUT; + else + OUT "\\C'%s'", chn+1 PUT; + break; + default: + OUT " %s? ", chn PUT; + break; + } +} + +void outascii(Tchar i) /* print i in best-guess ascii */ +{ + char *p; + int j = cbits(i); + +/* is this ever called with NROFF set? probably doesn't work at all. */ + + if (ismot(i)) + oput(' '); + else if (j < ALPHABET && j >= ' ' || j == '\n' || j == '\t') + oput(j); + else if (j == DRAWFCN) + oputs("\\D"); + else if (j == HYPHEN) + oput('-'); + else if (j == MINUS) /* special pleading for strange encodings */ + oputs("\\-"); + else if (j == PRESC) + oputs("\\e"); + else if (j == FILLER) + oputs("\\&"); + else if (j == UNPAD) + oputs("\\ "); + else if (j == OHC) /* this will never occur; stripped out earlier */ + oputs("\\%"); + else if (j == XON) + oputs("\\X"); + else if (j == XOFF) + oputs(" "); + else if (j == LIG_FI) + oputs("fi"); + else if (j == LIG_FL) + oputs("fl"); + else if (j == LIG_FF) + oputs("ff"); + else if (j == LIG_FFI) + oputs("ffi"); + else if (j == LIG_FFL) + oputs("ffl"); + else if (j == WORDSP) { /* nothing at all */ + if (xon) /* except in \X */ + oput(' '); + + } else + outweird(j); +} + +int flusho(void) +{ + if (NROFF && !toolate && t.twinit) + fwrite(t.twinit, strlen(t.twinit), 1, ptid); + + if (obufp > obuf) { + if (pipeflg && !toolate) { + /* fprintf(stderr, "Pipe to <%s>\n", Pipe.buf); */ + if (!Pipe.buf[0] || (ptid = popen(Pipe.buf, "w")) == NULL) + ERROR "pipe %s not created.", Pipe.buf WARN; + if (Pipe.buf) + free(Pipe.buf); + } + if (!toolate) + toolate++; + *obufp = 0; + fputs(obuf, ptid); + fflush(ptid); + obufp = obuf; + } + return 1; +} + + +void caseex(void) +{ + done(0); +} + + +void done(int x) +{ + int i; + + error |= x; + app = ds = lgf = 0; + if (i = em) { + donef = -1; + eschar = '\\'; + em = 0; + if (control(i, 0)) + longjmp(sjbuf, 1); + } + if (!nfo) + done3(0); + mflg = 0; + dip = &d[0]; + if (woff) /* BUG!!! This isn't set anywhere */ + wbf((Tchar)0); + if (pendw) + getword(1); + pendnf = 0; + if (donef == 1) + done1(0); + donef = 1; + ip = 0; + frame = stk; + nxf = frame + 1; + if (!ejf) + tbreak(); + nflush++; + eject((Stack *)0); + longjmp(sjbuf, 1); +} + + +void done1(int x) +{ + error |= x; + if (numtabp[NL].val) { + trap = 0; + eject((Stack *)0); + longjmp(sjbuf, 1); + } + if (!ascii) + pttrailer(); + done2(0); +} + + +void done2(int x) +{ + ptlead(); + if (TROFF && !ascii) + ptstop(); + flusho(); + done3(x); +} + +void done3(int x) +{ + error |= x; + flusho(); + if (NROFF) + twdone(); + if (pipeflg) + pclose(ptid); + exit(error); +} + + +void edone(int x) +{ + frame = stk; + nxf = frame + 1; + ip = 0; + done(x); +} + + +void casepi(void) +{ + int j; + char buf[NTM]; + + if (Pipe.buf == NULL) { + if ((Pipe.buf = (char *)calloc(NTM, sizeof(char))) == NULL) { + ERROR "No buf space for pipe cmd" WARN; + return; + } + Pipe.tick = 1; + } else + Pipe.buf[Pipe.cnt++] = '|'; + + getline(buf, NTM); + j = strlen(buf); + if (toolate) { + ERROR "Cannot create pipe to %s", buf WARN; + return; + } + Pipe.cnt += j; + if (j >= NTM +1) { + Pipe.tick++; + if ((Pipe.buf = (char *)realloc(Pipe.buf, Pipe.tick * NTM * sizeof(char))) == NULL) { + ERROR "No more buf space for pipe cmd" WARN; + return; + } + } + strcat(Pipe.buf, buf); + pipeflg++; +} diff --git a/src/cmd/troff/n3.c b/src/cmd/troff/n3.c new file mode 100644 index 00000000..6918d06d --- /dev/null +++ b/src/cmd/troff/n3.c @@ -0,0 +1,954 @@ +/* + * troff3.c + * + * macro and string routines, storage allocation + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +Tchar *argtop; +int pagech = '%'; +int strflg; + +#define MHASHSIZE 128 /* must be 2**n */ +#define MHASH(x) ((x>>6)^x) & (MHASHSIZE-1) +Contab *mhash[MHASHSIZE]; + + +Blockp *blist; /* allocated blocks for macros and strings */ +int nblist; /* how many there are */ +int bfree = -1; /* first (possible) free block in the list */ + +Contab *contabp = NULL; +#define MDELTA 500 +int nm = 0; + +int savname; /* name of macro/string being defined */ +int savslot; /* place in Contab of savname */ +int freeslot = -1; /* first (possible) free slot in contab */ + +void prcontab(Contab *p) +{ + int i; + for (i = 0; i < nm; i++) + if (p) + if (p[i].rq != 0) + fprintf(stderr, "slot %d, %-2.2s\n", i, unpair(p[i].rq)); + else + fprintf(stderr, "slot %d empty\n", i); + else + fprintf(stderr, "slot %d empty\n", i); +} + + +void blockinit(void) +{ + blist = (Blockp *) calloc(NBLIST, sizeof(Blockp)); + if (blist == NULL) { + ERROR "not enough room for %d blocks", NBLIST WARN; + done2(1); + } + nblist = NBLIST; + blist[0].nextoff = blist[1].nextoff = -1; + blist[0].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); + blist[1].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); + /* -1 prevents blist[0] from being used; temporary fix */ + /* for a design botch: offset==0 is overloaded. */ + /* blist[1] reserved for .rd indicator -- also unused. */ + /* but someone unwittingly looks at these, so allocate something */ + bfree = 2; +} + + +char *grow(char *ptr, int num, int size) /* make array bigger */ +{ + char *p, new; + + if (ptr == NULL) + p = (char *) calloc(num, size); + else + p = (char *) realloc(ptr, num * size); + return p; +} + +void mnspace(void) +{ + nm = sizeof(contab)/sizeof(Contab) + MDELTA; + freeslot = sizeof(contab)/sizeof(Contab) + 1; + contabp = (Contab *) grow((char *) contabp, nm, sizeof(Contab)); + if (contabp == NULL) { + ERROR "not enough memory for namespace of %d marcos", nm WARN; + exit(1); + } + contabp = (Contab *) memcpy((char *) contabp, (char *)contab, + sizeof(contab)); + if (contabp == NULL) { + ERROR "Cannot reinitialize macro/request name list" WARN; + exit(1); + } + +} + +void caseig(void) +{ + int i; + Offset oldoff = offset; + + offset = 0; + i = copyb(); + offset = oldoff; + if (i != '.') + control(i, 1); +} + + +void casern(void) +{ + int i, j, k; + + lgf++; + skip(); + if ((i = getrq()) == 0 || (oldmn = findmn(i)) < 0) + return; + skip(); + clrmn(findmn(j = getrq())); + if (j) { + munhash(&contabp[oldmn]); + contabp[oldmn].rq = j; + maddhash(&contabp[oldmn]); + if (dip != d ) + for (k = dilev; k; k--) + if (d[k].curd == i) + d[k].curd = j; + } +} + +void maddhash(Contab *rp) +{ + Contab **hp; + + if (rp->rq == 0) + return; + hp = &mhash[MHASH(rp->rq)]; + rp->link = *hp; + *hp = rp; +} + +void munhash(Contab *mp) +{ + Contab *p; + Contab **lp; + + if (mp->rq == 0) + return; + lp = &mhash[MHASH(mp->rq)]; + p = *lp; + while (p) { + if (p == mp) { + *lp = p->link; + p->link = 0; + return; + } + lp = &p->link; + p = p->link; + } +} + +void mrehash(void) +{ + Contab *p; + int i; + + for (i=0; i < MHASHSIZE; i++) + mhash[i] = 0; + for (p=contabp; p < &contabp[nm]; p++) + p->link = 0; + for (p=contabp; p < &contabp[nm]; p++) { + if (p->rq == 0) + continue; + i = MHASH(p->rq); + p->link = mhash[i]; + mhash[i] = p; + } +} + +void caserm(void) +{ + int j; + int k = 0; + + lgf++; +g0: + while (!skip() && (j = getrq()) != 0) { + if (dip != d) + for (k = dilev; k; k--) + if (d[k].curd == j) { + ERROR "cannot remove diversion %s during definition", + unpair(j) WARN; + goto g0; + } + clrmn(findmn(j)); + } + lgf--; +} + + +void caseas(void) +{ + app++; + caseds(); +} + + +void caseds(void) +{ + ds++; + casede(); +} + + +void caseam(void) +{ + app++; + casede(); +} + + +void casede(void) +{ + int i, req; + Offset savoff; + + req = '.'; + lgf++; + skip(); + if ((i = getrq()) == 0) + goto de1; + if ((offset = finds(i)) == 0) + goto de1; + if (newmn) + savslot = newmn; + else + savslot = findmn(i); + savname = i; + if (ds) + copys(); + else + req = copyb(); + clrmn(oldmn); + if (newmn) { + if (contabp[newmn].rq) + munhash(&contabp[newmn]); + contabp[newmn].rq = i; + maddhash(&contabp[newmn]); + + } + if (apptr) { + savoff = offset; + offset = apptr; + wbf((Tchar) IMP); + offset = savoff; + } + offset = dip->op; + if (req != '.') + control(req, 1); +de1: + ds = app = 0; +} + + +int findmn(int i) +{ + Contab *p; + + for (p = mhash[MHASH(i)]; p; p = p->link) + if (i == p->rq) + return(p - contabp); + return(-1); +} + + +void clrmn(int i) +{ + if (i >= 0) { + if (contabp[i].mx) + ffree(contabp[i].mx); + munhash(&contabp[i]); + contabp[i].rq = 0; + contabp[i].mx = 0; + contabp[i].emx = 0; + contabp[i].f = 0; + if (contabp[i].divsiz != NULL) { + free(contabp[i].divsiz); + contabp[i].divsiz = NULL; + } + if (freeslot > i) + freeslot = i; + } +} + +void growcontab(void) +{ + nm += MDELTA; + contabp = (Contab *) grow((char *) contabp , nm, sizeof(Contab)); + if (contabp == NULL) { + ERROR "Too many (%d) string/macro names", nm WARN; + done2(02); + } else { + memset((char *)(contabp) + (nm - MDELTA) * sizeof(Contab), + 0, MDELTA * sizeof(Contab)); + mrehash(); + } +} + + +Offset finds(int mn) +{ + int i; + Tchar j = IMP; + Offset savip; + + oldmn = findmn(mn); + newmn = 0; + apptr = 0; + if (app && oldmn >= 0 && contabp[oldmn].mx) { + savip = ip; + ip = contabp[oldmn].emx; + oldmn = -1; + apptr = ip; + if (!diflg) + ip = incoff(ip); + nextb = ip; + ip = savip; + } else { + for (i = freeslot; i < nm; i++) { + if (contabp[i].rq == 0) + break; + } + if (i == nm) + growcontab(); + freeslot = i + 1; + if ((nextb = alloc()) == -1) { + app = 0; + if (macerr++ > 1) + done2(02); + if (nextb == 0) + ERROR "Not enough space for string/macro names" WARN; + edone(04); + return(offset = 0); + } + contabp[i].mx = nextb; + if (!diflg) { + newmn = i; + if (oldmn == -1) + contabp[i].rq = -1; + } else { + contabp[i].rq = mn; + maddhash(&contabp[i]); + } + } + app = 0; + return(offset = nextb); +} + +int skip(void) +{ + Tchar i; + + while (cbits(i = getch()) == ' ' || ismot(i)) + ; + ch = i; + return(nlflg); +} + + +int copyb(void) +{ + int i, j, state; + Tchar ii; + int req, k; + Offset savoff; + Uchar *p; + + if (skip() || !(j = getrq())) + j = '.'; + req = j; + p = unpair(j); + /* was: k = j >> BYTE; j &= BYTEMASK; */ + j = p[0]; + k = p[1]; + copyf++; + flushi(); + nlflg = 0; + state = 1; + +/* state 0 eat up + * state 1 look for . + * state 2 look for first char of end macro + * state 3 look for second char of end macro + */ + + while (1) { + i = cbits(ii = getch()); + if (state == 3) { + if (i == k) + break; + if (!k) { + ch = ii; + i = getach(); + ch = ii; + if (!i) + break; + } + state = 0; + goto c0; + } + if (i == '\n') { + state = 1; + nlflg = 0; + goto c0; + } + if (state == 1 && i == '.') { + state++; + savoff = offset; + goto c0; + } + if (state == 2 && i == j) { + state++; + goto c0; + } + state = 0; +c0: + if (offset) + wbf(ii); + } + if (offset) { + offset = savoff; + wbf((Tchar)0); + } + copyf--; + return(req); +} + + +void copys(void) +{ + Tchar i; + + copyf++; + if (skip()) + goto c0; + if (cbits(i = getch()) != '"') + wbf(i); + while (cbits(i = getch()) != '\n') + wbf(i); +c0: + wbf((Tchar)0); + copyf--; +} + + +Offset alloc(void) /* return free Offset in nextb */ +{ + int i, j; + + for (i = bfree; i < nblist; i++) + if (blist[i].nextoff == 0) + break; + if (i == nblist) { + blist = (Blockp *) realloc((char *) blist, 2 * nblist * sizeof(Blockp)); + if (blist == NULL) { + ERROR "can't grow blist for string/macro defns" WARN; + done2(2); + } + nblist *= 2; + for (j = i; j < nblist; j++) { + blist[j].nextoff = 0; + blist[j].bp = 0; + } + } + blist[i].nextoff = -1; /* this block is the end */ + bfree = i + 1; + if (blist[i].bp == 0) + blist[i].bp = (Tchar *) calloc(BLK, sizeof(Tchar)); + if (blist[i].bp == NULL) { + ERROR "can't allocate memory for string/macro definitions" WARN; + done2(2); + } + nextb = (Offset) i * BLK; + return nextb; +} + + +void ffree(Offset i) /* free list of blocks starting at blist(o) */ +{ /* (doesn't actually free the blocks, just the pointers) */ + int j; + + for ( ; blist[j = bindex(i)].nextoff != -1; ) { + if (bfree > j) + bfree = j; + i = blist[j].nextoff; + blist[j].nextoff = 0; + } + blist[j].nextoff = 0; +} + + +void wbf(Tchar i) /* store i into offset, get ready for next one */ +{ + int j, off; + + if (!offset) + return; + j = bindex(offset); + if (i == 0) + contabp[savslot].emx = offset; + off = boffset(offset); + blist[j].bp[off++] = i; + offset++; + if (pastend(offset)) { /* off the end of this block */ + if (blist[j].nextoff == -1) { + if ((nextb = alloc()) == -1) { + ERROR "Out of temp file space" WARN; + done2(01); + } + blist[j].nextoff = nextb; + } + offset = blist[j].nextoff; + } +} + + +Tchar rbf(void) /* return next char from blist[] block */ +{ + Tchar i, j; + + if (ip == RD_OFFSET) { /* for rdtty */ + if (j = rdtty()) + return(j); + else + return(popi()); + } + + i = rbf0(ip); + if (i == 0) { + if (!app) + i = popi(); + return(i); + } + ip = incoff(ip); + return(i); +} + + +Offset xxxincoff(Offset p) /* get next blist[] block */ +{ + p++; + if (pastend(p)) { /* off the end of this block */ + if ((p = blist[bindex(p-1)].nextoff) == -1) { /* and nothing was allocated after it */ + ERROR "Bad storage allocation" WARN; + done2(-5); + } + } + return(p); +} + + +Tchar popi(void) +{ + Stack *p; + + if (frame == stk) + return(0); + if (strflg) + strflg--; + p = nxf = frame; + p->nargs = 0; + frame = p->pframe; + ip = p->pip; + pendt = p->ppendt; + lastpbp = p->lastpbp; + return(p->pch); +} + +/* + * test that the end of the allocation is above a certain location + * in memory + */ +#define SPACETEST(base, size) \ + if ((char*)base + size >= (char*)stk+STACKSIZE) \ + ERROR "Stacksize overflow in n3" WARN + +Offset pushi(Offset newip, int mname) +{ + Stack *p; + + SPACETEST(nxf, sizeof(Stack)); + p = nxf; + p->pframe = frame; + p->pip = ip; + p->ppendt = pendt; + p->pch = ch; + p->lastpbp = lastpbp; + p->mname = mname; + lastpbp = pbp; + pendt = ch = 0; + frame = nxf; + if (nxf->nargs == 0) + nxf += 1; + else + nxf = (Stack *)argtop; + return(ip = newip); +} + + +void *setbrk(int x) +{ + char *i; + + if ((i = (char *) calloc(x, 1)) == 0) { + ERROR "Core limit reached" WARN; + edone(0100); + } + return(i); +} + + +int getsn(void) +{ + int i; + + if ((i = getach()) == 0) + return(0); + if (i == '(') + return(getrq()); + else + return(i); +} + + +Offset setstr(void) +{ + int i, j; + + lgf++; + if ((i = getsn()) == 0 || (j = findmn(i)) == -1 || !contabp[j].mx) { + lgf--; + return(0); + } else { + SPACETEST(nxf, sizeof(Stack)); + nxf->nargs = 0; + strflg++; + lgf--; + return pushi(contabp[j].mx, i); + } +} + + + +void collect(void) +{ + int j; + Tchar i, *strp, *lim, **argpp, **argppend; + int quote; + Stack *savnxf; + + copyf++; + nxf->nargs = 0; + savnxf = nxf; + if (skip()) + goto rtn; + + { + char *memp; + memp = (char *)savnxf; + /* + * 1 s structure for the macro descriptor + * APERMAC Tchar *'s for pointers into the strings + * space for the Tchar's themselves + */ + memp += sizeof(Stack); + /* + * CPERMAC = the total # of characters for ALL arguments + */ +#define CPERMAC 200 +#define APERMAC 9 + memp += APERMAC * sizeof(Tchar *); + memp += CPERMAC * sizeof(Tchar); + nxf = (Stack *)memp; + } + lim = (Tchar *)nxf; + argpp = (Tchar **)(savnxf + 1); + argppend = &argpp[APERMAC]; + SPACETEST(argppend, sizeof(Tchar *)); + strp = (Tchar *)argppend; + /* + * Zero out all the string pointers before filling them in. + */ + for (j = 0; j < APERMAC; j++) + argpp[j] = 0; + /* ERROR "savnxf=0x%x,nxf=0x%x,argpp=0x%x,strp=argppend=0x%x, lim=0x%x", + * savnxf, nxf, argpp, strp, lim WARN; + */ + strflg = 0; + while (argpp != argppend && !skip()) { + *argpp++ = strp; + quote = 0; + if (cbits(i = getch()) == '"') + quote++; + else + ch = i; + while (1) { + i = getch(); +/* fprintf(stderr, "collect %c %d\n", cbits(i), cbits(i)); */ + if (nlflg || (!quote && argpp != argppend && cbits(i) == ' ')) + break; /* collects rest into $9 */ + if ( quote + && cbits(i) == '"' + && cbits(i = getch()) != '"') { + ch = i; + break; + } + *strp++ = i; + if (strflg && strp >= lim) { + /* ERROR "strp=0x%x, lim = 0x%x", strp, lim WARN; */ + ERROR "Macro argument too long" WARN; + copyf--; + edone(004); + } + SPACETEST(strp, 3 * sizeof(Tchar)); + } + *strp++ = 0; + } + nxf = savnxf; + nxf->nargs = argpp - (Tchar **)(savnxf + 1); + argtop = strp; +rtn: + copyf--; +} + + +void seta(void) +{ + int i; + + i = cbits(getch()) - '0'; + if (i > 0 && i <= APERMAC && i <= frame->nargs) + pushback(*(((Tchar **)(frame + 1)) + i - 1)); +} + + +void caseda(void) +{ + app++; + casedi(); +} + +void casegd(void) +{ + int i, j; + + skip(); + if ((i = getrq()) == 0) + return; + if ((j = findmn(i)) >= 0) { + if (contabp[j].divsiz != NULL) { + numtabp[DN].val = contabp[j].divsiz->dix; + numtabp[DL].val = contabp[j].divsiz->diy; + } + } +} + +#define FINDDIV(o) if ((o = findmn(dip->curd)) < 0) \ + ERROR "lost diversion %s", unpair(dip->curd) WARN + +void casedi(void) +{ + int i, j, *k; + + lgf++; + if (skip() || (i = getrq()) == 0) { + if (dip != d) { + FINDDIV(savslot); + wbf((Tchar)0); + } + if (dilev > 0) { + numtabp[DN].val = dip->dnl; + numtabp[DL].val = dip->maxl; + FINDDIV(j); + if ((contabp[j].divsiz = (Divsiz *) malloc(sizeof(Divsiz))) == NULL) { + ERROR "Cannot alloc diversion size" WARN; + done2(1); + } else { + contabp[j].divsiz->dix = numtabp[DN].val; + contabp[j].divsiz->diy = numtabp[DL].val; + } + dip = &d[--dilev]; + offset = dip->op; + } + goto rtn; + } + if (++dilev == NDI) { + --dilev; + ERROR "Diversions nested too deep" WARN; + edone(02); + } + if (dip != d) { + FINDDIV(j); + savslot = j; + wbf((Tchar)0); + } + diflg++; + dip = &d[dilev]; + dip->op = finds(i); + dip->curd = i; + clrmn(oldmn); + k = (int *) & dip->dnl; + for (j = 0; j < 10; j++) + k[j] = 0; /*not op and curd*/ +rtn: + app = 0; + diflg = 0; +} + + +void casedt(void) +{ + lgf++; + dip->dimac = dip->ditrap = dip->ditf = 0; + skip(); + dip->ditrap = vnumb((int *)0); + if (nonumb) + return; + skip(); + dip->dimac = getrq(); +} + +#define LNSIZE 4000 +void casetl(void) +{ + int j; + int w[3]; + Tchar buf[LNSIZE]; + Tchar *tp; + Tchar i, delim; + + /* + * bug fix + * + * if .tl is the first thing in the file, the p1 + * doesn't come out, also the pagenumber will be 0 + * + * tends too confuse the device filter (and the user as well) + */ + if (dip == d && numtabp[NL].val == -1) + newline(1); + dip->nls = 0; + skip(); + if (ismot(delim = getch())) { + ch = delim; + delim = '\''; + } else + delim = cbits(delim); + tp = buf; + numtabp[HP].val = 0; + w[0] = w[1] = w[2] = 0; + j = 0; + while (cbits(i = getch()) != '\n') { + if (cbits(i) == cbits(delim)) { + if (j < 3) + w[j] = numtabp[HP].val; + numtabp[HP].val = 0; + if (w[j] != 0) + *tp++ = WORDSP; + j++; + *tp++ = 0; + } else { + if (cbits(i) == pagech) { + setn1(numtabp[PN].val, numtabp[findr('%')].fmt, + i&SFMASK); + continue; + } + numtabp[HP].val += width(i); + if (tp < &buf[LNSIZE-10]) { + if (cbits(i) == ' ' && *tp != WORDSP) + *tp++ = WORDSP; + *tp++ = i; + } else { + ERROR "Overflow in casetl" WARN; + } + } + } + if (j<3) + w[j] = numtabp[HP].val; + *tp++ = 0; + *tp++ = 0; + *tp = 0; + tp = buf; + if (NROFF) + horiz(po); + while (i = *tp++) + pchar(i); + if (w[1] || w[2]) + horiz(j = quant((lt - w[1]) / 2 - w[0], HOR)); + while (i = *tp++) + pchar(i); + if (w[2]) { + horiz(lt - w[0] - w[1] - w[2] - j); + while (i = *tp++) + pchar(i); + } + newline(0); + if (dip != d) { + if (dip->dnl > dip->hnl) + dip->hnl = dip->dnl; + } else { + if (numtabp[NL].val > dip->hnl) + dip->hnl = numtabp[NL].val; + } +} + + +void casepc(void) +{ + pagech = chget(IMP); +} + + +void casepm(void) +{ + int i, k; + int xx, cnt, tcnt, kk, tot; + Offset j; + + kk = cnt = tcnt = 0; + tot = !skip(); + stackdump(); + for (i = 0; i < nm; i++) { + if ((xx = contabp[i].rq) == 0 || contabp[i].mx == 0) + continue; + tcnt++; + j = contabp[i].mx; + for (k = 1; (j = blist[bindex(j)].nextoff) != -1; ) + k++; + cnt++; + kk += k; + if (!tot) + fprintf(stderr, "%-2.2s %d\n", unpair(xx), k); + } + fprintf(stderr, "pm: total %d, macros %d, space %d\n", tcnt, cnt, kk); +} + +void stackdump(void) /* dumps stack of macros in process */ +{ + Stack *p; + + if (frame != stk) { + fprintf(stderr, "stack: "); + for (p = frame; p != stk; p = p->pframe) + fprintf(stderr, "%s ", unpair(p->mname)); + fprintf(stderr, "\n"); + } +} diff --git a/src/cmd/troff/n4.c b/src/cmd/troff/n4.c new file mode 100644 index 00000000..3b3698e4 --- /dev/null +++ b/src/cmd/troff/n4.c @@ -0,0 +1,828 @@ +/* + * troff4.c + * + * number registers, conversion, arithmetic + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + + +int regcnt = NNAMES; +int falsef = 0; /* on if inside false branch of if */ + +#define NHASHSIZE 128 /* must be 2**n */ +#define NHASH(i) ((i>>6)^i) & (NHASHSIZE-1) +Numtab *nhash[NHASHSIZE]; + +Numtab *numtabp = NULL; +#define NDELTA 400 +int ncnt = 0; + +void setn(void) +{ + int i, j, f; + Tchar ii; + Uchar *p; + char buf[NTM]; /* for \n(.S */ + + f = nform = 0; + if ((i = cbits(ii = getach())) == '+') + f = 1; + else if (i == '-') + f = -1; + else if (ii) /* don't put it back if it's already back (thanks to jaap) */ + ch = ii; + if (falsef) + f = 0; + if ((i = getsn()) == 0) + return; + p = unpair(i); + if (p[0] == '.') + switch (p[1]) { + case 's': + i = pts; + break; + case 'v': + i = lss; + break; + case 'f': + i = font; + break; + case 'p': + i = pl; + break; + case 't': + i = findt1(); + break; + case 'o': + i = po; + break; + case 'l': + i = ll; + break; + case 'i': + i = in; + break; + case '$': + i = frame->nargs; + break; + case 'A': + i = ascii; + break; + case 'c': + i = numtabp[CD].val; + break; + case 'n': + i = lastl; + break; + case 'a': + i = ralss; + break; + case 'h': + i = dip->hnl; + break; + case 'd': + if (dip != d) + i = dip->dnl; + else + i = numtabp[NL].val; + break; + case 'u': + i = fi; + break; + case 'j': + i = ad + 2 * admod; + break; + case 'w': + i = widthp; + break; + case 'x': + i = nel; + break; + case 'y': + i = un; + break; + case 'T': + i = dotT; + break; /* -Tterm used in nroff */ + case 'V': + i = VERT; + break; + case 'H': + i = HOR; + break; + case 'k': + i = ne; + break; + case 'P': + i = print; + break; + case 'L': + i = ls; + break; + case 'R': /* maximal # of regs that can be addressed */ + i = 255*256 - regcnt; + break; + case 'z': + p = unpair(dip->curd); + *pbp++ = p[1]; /* watch order */ + *pbp++ = p[0]; + return; + case 'b': + i = bdtab[font]; + break; + case 'F': + cpushback(cfname[ifi]); + return; + case 'S': + buf[0] = j = 0; + for( i = 0; tabtab[i] != 0 && i < NTAB; i++) { + if (i > 0) + buf[j++] = ' '; + sprintf(&buf[j], "%d", tabtab[i] & TABMASK); + j = strlen(buf); + if ( tabtab[i] & RTAB) + sprintf(&buf[j], "uR"); + else if (tabtab[i] & CTAB) + sprintf(&buf[j], "uC"); + else + sprintf(&buf[j], "uL"); + j += 2; + } + cpushback(buf); + return; + default: + goto s0; + } + else { +s0: + if ((j = findr(i)) == -1) + i = 0; + else { + i = numtabp[j].val = numtabp[j].val + numtabp[j].inc * f; + nform = numtabp[j].fmt; + } + } + setn1(i, nform, (Tchar) 0); +} + +Tchar numbuf[25]; +Tchar *numbufp; + +int wrc(Tchar i) +{ + if (numbufp >= &numbuf[24]) + return(0); + *numbufp++ = i; + return(1); +} + + + +/* insert into input number i, in format form, with size-font bits bits */ +void setn1(int i, int form, Tchar bits) +{ + numbufp = numbuf; + nrbits = bits; + nform = form; + fnumb(i, wrc); + *numbufp = 0; + pushback(numbuf); +} + +void prnumtab(Numtab *p) +{ + int i; + for (i = 0; i < ncnt; i++) + if (p) + if (p[i].r != 0) + fprintf(stderr, "slot %d, %s, val %d\n", i, unpair(p[i].r), p[i].val); + else + fprintf(stderr, "slot %d empty\n", i); + else + fprintf(stderr, "slot %d empty\n", i); +} + +void nnspace(void) +{ + ncnt = sizeof(numtab)/sizeof(Numtab) + NDELTA; + numtabp = (Numtab *) grow((char *)numtabp, ncnt, sizeof(Numtab)); + if (numtabp == NULL) { + ERROR "not enough memory for registers (%d)", ncnt WARN; + exit(1); + } + numtabp = (Numtab *) memcpy((char *)numtabp, (char *)numtab, + sizeof(numtab)); + if (numtabp == NULL) { + ERROR "Cannot initialize registers" WARN; + exit(1); + } +} + +void grownumtab(void) +{ + ncnt += NDELTA; + numtabp = (Numtab *) grow((char *) numtabp, ncnt, sizeof(Numtab)); + if (numtabp == NULL) { + ERROR "Too many number registers (%d)", ncnt WARN; + done2(04); + } else { + memset((char *)(numtabp) + (ncnt - NDELTA) * sizeof(Numtab), + 0, NDELTA * sizeof(Numtab)); + nrehash(); + } +} + +void nrehash(void) +{ + Numtab *p; + int i; + + for (i=0; i<NHASHSIZE; i++) + nhash[i] = 0; + for (p=numtabp; p < &numtabp[ncnt]; p++) + p->link = 0; + for (p=numtabp; p < &numtabp[ncnt]; p++) { + if (p->r == 0) + continue; + i = NHASH(p->r); + p->link = nhash[i]; + nhash[i] = p; + } +} + +void nunhash(Numtab *rp) +{ + Numtab *p; + Numtab **lp; + + if (rp->r == 0) + return; + lp = &nhash[NHASH(rp->r)]; + p = *lp; + while (p) { + if (p == rp) { + *lp = p->link; + p->link = 0; + return; + } + lp = &p->link; + p = p->link; + } +} + +int findr(int i) +{ + Numtab *p; + int h = NHASH(i); + + if (i == 0) + return(-1); +a0: + for (p = nhash[h]; p; p = p->link) + if (i == p->r) + return(p - numtabp); + for (p = numtabp; p < &numtabp[ncnt]; p++) { + if (p->r == 0) { + p->r = i; + p->link = nhash[h]; + nhash[h] = p; + regcnt++; + return(p - numtabp); + } + } + grownumtab(); + goto a0; +} + +int usedr(int i) /* returns -1 if nr i has never been used */ +{ + Numtab *p; + + if (i == 0) + return(-1); + for (p = nhash[NHASH(i)]; p; p = p->link) + if (i == p->r) + return(p - numtabp); + return -1; +} + + +int fnumb(int i, int (*f)(Tchar)) +{ + int j; + + j = 0; + if (i < 0) { + j = (*f)('-' | nrbits); + i = -i; + } + switch (nform) { + default: + case '1': + case 0: + return decml(i, f) + j; + case 'i': + case 'I': + return roman(i, f) + j; + case 'a': + case 'A': + return abc(i, f) + j; + } +} + + +int decml(int i, int (*f)(Tchar)) +{ + int j, k; + + k = 0; + nform--; + if ((j = i / 10) || (nform > 0)) + k = decml(j, f); + return(k + (*f)((i % 10 + '0') | nrbits)); +} + + +int roman(int i, int (*f)(Tchar)) +{ + + if (!i) + return((*f)('0' | nrbits)); + if (nform == 'i') + return(roman0(i, f, "ixcmz", "vldw")); + else + return(roman0(i, f, "IXCMZ", "VLDW")); +} + + +int roman0(int i, int (*f)(Tchar), char *onesp, char *fivesp) +{ + int q, rem, k; + + if (!i) + return(0); + k = roman0(i / 10, f, onesp + 1, fivesp + 1); + q = (i = i % 10) / 5; + rem = i % 5; + if (rem == 4) { + k += (*f)(*onesp | nrbits); + if (q) + i = *(onesp + 1); + else + i = *fivesp; + return(k += (*f)(i | nrbits)); + } + if (q) + k += (*f)(*fivesp | nrbits); + while (--rem >= 0) + k += (*f)(*onesp | nrbits); + return(k); +} + + +int abc(int i, int (*f)(Tchar)) +{ + if (!i) + return((*f)('0' | nrbits)); + else + return(abc0(i - 1, f)); +} + + +int abc0(int i, int (*f)(Tchar)) +{ + int j, k; + + k = 0; + if (j = i / 26) + k = abc0(j - 1, f); + return(k + (*f)((i % 26 + nform) | nrbits)); +} + +long atoi0(void) +{ + int c, k, cnt; + Tchar ii; + long i, acc; + + acc = 0; + nonumb = 0; + cnt = -1; +a0: + cnt++; + ii = getch(); + c = cbits(ii); + switch (c) { + default: + ch = ii; + if (cnt) + break; + case '+': + i = ckph(); + if (nonumb) + break; + acc += i; + goto a0; + case '-': + i = ckph(); + if (nonumb) + break; + acc -= i; + goto a0; + case '*': + i = ckph(); + if (nonumb) + break; + acc *= i; + goto a0; + case '/': + i = ckph(); + if (nonumb) + break; + if (i == 0) { + flusho(); + ERROR "divide by zero." WARN; + acc = 0; + } else + acc /= i; + goto a0; + case '%': + i = ckph(); + if (nonumb) + break; + acc %= i; + goto a0; + case '&': /*and*/ + i = ckph(); + if (nonumb) + break; + if ((acc > 0) && (i > 0)) + acc = 1; + else + acc = 0; + goto a0; + case ':': /*or*/ + i = ckph(); + if (nonumb) + break; + if ((acc > 0) || (i > 0)) + acc = 1; + else + acc = 0; + goto a0; + case '=': + if (cbits(ii = getch()) != '=') + ch = ii; + i = ckph(); + if (nonumb) { + acc = 0; + break; + } + if (i == acc) + acc = 1; + else + acc = 0; + goto a0; + case '>': + k = 0; + if (cbits(ii = getch()) == '=') + k++; + else + ch = ii; + i = ckph(); + if (nonumb) { + acc = 0; + break; + } + if (acc > (i - k)) + acc = 1; + else + acc = 0; + goto a0; + case '<': + k = 0; + if (cbits(ii = getch()) == '=') + k++; + else + ch = ii; + i = ckph(); + if (nonumb) { + acc = 0; + break; + } + if (acc < (i + k)) + acc = 1; + else + acc = 0; + goto a0; + case ')': + break; + case '(': + acc = atoi0(); + goto a0; + } + return(acc); +} + + +long ckph(void) +{ + Tchar i; + long j; + + if (cbits(i = getch()) == '(') + j = atoi0(); + else { + j = atoi1(i); + } + return(j); +} + + +/* + * print error about illegal numeric argument; + */ +void prnumerr(void) +{ + char err_buf[40]; + static char warn[] = "Numeric argument expected"; + int savcd = numtabp[CD].val; + + if (numerr.type == RQERR) + sprintf(err_buf, "%c%s: %s", nb ? cbits(c2) : cbits(cc), + unpair(numerr.req), warn); + else + sprintf(err_buf, "\\%c'%s': %s", numerr.esc, &numerr.escarg, + warn); + if (frame != stk) /* uncertainty correction */ + numtabp[CD].val--; + ERROR err_buf WARN; + numtabp[CD].val = savcd; +} + + +long atoi1(Tchar ii) +{ + int i, j, digits; + double acc; /* this is the only double in troff! */ + int neg, abs, field, decpnt; + extern int ifnum; + + + neg = abs = field = decpnt = digits = 0; + acc = 0; + for (;;) { + i = cbits(ii); + switch (i) { + default: + break; + case '+': + ii = getch(); + continue; + case '-': + neg = 1; + ii = getch(); + continue; + case '|': + abs = 1 + neg; + neg = 0; + ii = getch(); + continue; + } + break; + } +a1: + while (i >= '0' && i <= '9') { + field++; + digits++; + acc = 10 * acc + i - '0'; + ii = getch(); + i = cbits(ii); + } + if (i == '.' && !decpnt++) { + field++; + digits = 0; + ii = getch(); + i = cbits(ii); + goto a1; + } + if (!field) { + ch = ii; + goto a2; + } + switch (i) { + case 'u': + i = j = 1; /* should this be related to HOR?? */ + break; + case 'v': /*VSs - vert spacing*/ + j = lss; + i = 1; + break; + case 'm': /*Ems*/ + j = EM; + i = 1; + break; + case 'n': /*Ens*/ + j = EM; + if (TROFF) + i = 2; + else + i = 1; /*Same as Ems in NROFF*/ + break; + case 'p': /*Points*/ + j = INCH; + i = 72; + break; + case 'i': /*Inches*/ + j = INCH; + i = 1; + break; + case 'c': /*Centimeters*/ + /* if INCH is too big, this will overflow */ + j = INCH * 50; + i = 127; + break; + case 'P': /*Picas*/ + j = INCH; + i = 6; + break; + default: + j = dfact; + ch = ii; + i = dfactd; + } + if (neg) + acc = -acc; + if (!noscale) { + acc = (acc * j) / i; + } + if (field != digits && digits > 0) + while (digits--) + acc /= 10; + if (abs) { + if (dip != d) + j = dip->dnl; + else + j = numtabp[NL].val; + if (!vflag) { + j = numtabp[HP].val; + } + if (abs == 2) + j = -j; + acc -= j; + } +a2: + nonumb = (!field || field == decpnt); + if (nonumb && (trace & TRNARGS) && !ismot(ii) && !nlflg && !ifnum) { + if (cbits(ii) != RIGHT ) /* Too painful to do right */ + prnumerr(); + } + return(acc); +} + + +void caserr(void) +{ + int i, j; + Numtab *p; + + lgf++; + while (!skip() && (i = getrq()) ) { + j = usedr(i); + if (j < 0) + continue; + p = &numtabp[j]; + nunhash(p); + p->r = p->val = p->inc = p->fmt = 0; + regcnt--; + } +} + +/* + * .nr request; if tracing, don't check optional + * 2nd argument because tbl generates .in 1.5n + */ +void casenr(void) +{ + int i, j; + int savtr = trace; + + lgf++; + skip(); + if ((i = findr(getrq())) == -1) + goto rtn; + skip(); + j = inumb(&numtabp[i].val); + if (nonumb) + goto rtn; + numtabp[i].val = j; + skip(); + trace = 0; + j = atoi0(); /* BUG??? */ + trace = savtr; + if (nonumb) + goto rtn; + numtabp[i].inc = j; +rtn: + return; +} + +void caseaf(void) +{ + int i, k; + Tchar j; + + lgf++; + if (skip() || !(i = getrq()) || skip()) + return; + k = 0; + j = getch(); + if (!isalpha(cbits(j))) { + ch = j; + while ((j = cbits(getch())) >= '0' && j <= '9') + k++; + } + if (!k) + k = j; + numtabp[findr(i)].fmt = k; /* was k & BYTEMASK */ +} + +void setaf(void) /* return format of number register */ +{ + int i, j; + + i = usedr(getsn()); + if (i == -1) + return; + if (numtabp[i].fmt > 20) /* it was probably a, A, i or I */ + *pbp++ = numtabp[i].fmt; + else + for (j = (numtabp[i].fmt ? numtabp[i].fmt : 1); j; j--) + *pbp++ = '0'; +} + + +int vnumb(int *i) +{ + vflag++; + dfact = lss; + res = VERT; + return(inumb(i)); +} + + +int hnumb(int *i) +{ + dfact = EM; + res = HOR; + return(inumb(i)); +} + + +int inumb(int *n) +{ + int i, j, f; + Tchar ii; + + f = 0; + if (n) { + if ((j = cbits(ii = getch())) == '+') + f = 1; + else if (j == '-') + f = -1; + else + ch = ii; + } + i = atoi0(); + if (n && f) + i = *n + f * i; + i = quant(i, res); + vflag = 0; + res = dfactd = dfact = 1; + if (nonumb) + i = 0; + return(i); +} + + +int quant(int n, int m) +{ + int i, neg; + + neg = 0; + if (n < 0) { + neg++; + n = -n; + } + /* better as i = ((n + m/2)/m)*m */ + i = n / m; + if (n - m * i > m / 2) + i += 1; + i *= m; + if (neg) + i = -i; + return(i); +} diff --git a/src/cmd/troff/n5.c b/src/cmd/troff/n5.c new file mode 100644 index 00000000..c2801e47 --- /dev/null +++ b/src/cmd/troff/n5.c @@ -0,0 +1,1149 @@ +/* + * troff5.c + * + * misc processing requests + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +int iflist[NIF]; +int ifx; +int ifnum = 0; /* trying numeric expression for .if or .ie condition */ + +void casead(void) +{ + int i; + + ad = 1; + /* leave admod alone */ + if (skip()) + return; + switch (i = cbits(getch())) { + case 'r': /* right adj, left ragged */ + admod = 2; + break; + case 'l': /* left adj, right ragged */ + admod = ad = 0; /* same as casena */ + break; + case 'c': /*centered adj*/ + admod = 1; + break; + case 'b': + case 'n': + admod = 0; + break; + case '0': + case '2': + case '4': + ad = 0; + case '1': + case '3': + case '5': + admod = (i - '0') / 2; + } +} + + +void casena(void) +{ + ad = 0; +} + + +void casefi(void) +{ + tbreak(); + fi = 1; + pendnf = 0; +} + + +void casenf(void) +{ + tbreak(); + fi = 0; +} + + +void casers(void) +{ + dip->nls = 0; +} + + +void casens(void) +{ + dip->nls++; +} + + +chget(int c) +{ + Tchar i; + + if (skip() || ismot(i = getch()) || cbits(i) == ' ' || cbits(i) == '\n') { + ch = i; + return(c); + } else + return cbits(i); /* was (i & BYTEMASK) */ +} + + +void casecc(void) +{ + cc = chget('.'); +} + + +void casec2(void) +{ + c2 = chget('\''); +} + + +void casehc(void) +{ + ohc = chget(OHC); +} + + +void casetc(void) +{ + tabc = chget(0); +} + + +void caselc(void) +{ + dotc = chget(0); +} + + +void casehy(void) +{ + int i; + + hyf = 1; + if (skip()) + return; + noscale++; + i = atoi0(); + noscale = 0; + if (nonumb) + return; + hyf = max(i, 0); +} + + +void casenh(void) +{ + hyf = 0; +} + + +max(int aa, int bb) +{ + if (aa > bb) + return(aa); + else + return(bb); +} + + +void casece(void) +{ + int i; + + noscale++; + skip(); + i = max(atoi0(), 0); + if (nonumb) + i = 1; + tbreak(); + ce = i; + noscale = 0; +} + + +void casein(void) +{ + int i; + + if (skip()) + i = in1; + else { + i = max(hnumb(&in), 0); + if (nonumb) + i = in1; + } + tbreak(); + in1 = in; + in = i; + if (!nc) { + un = in; + setnel(); + } +} + + +void casell(void) +{ + int i; + + if (skip()) + i = ll1; + else { + i = max(hnumb(&ll), INCH / 10); + if (nonumb) + i = ll1; + } + ll1 = ll; + ll = i; + setnel(); +} + + +void caselt(void) +{ + int i; + + if (skip()) + i = lt1; + else { + i = max(hnumb(<), 0); + if (nonumb) + i = lt1; + } + lt1 = lt; + lt = i; +} + + +void caseti(void) +{ + int i; + + if (skip()) + return; + i = max(hnumb(&in), 0); + tbreak(); + un1 = i; + setnel(); +} + + +void casels(void) +{ + int i; + + noscale++; + if (skip()) + i = ls1; + else { + i = max(inumb(&ls), 1); + if (nonumb) + i = ls1; + } + ls1 = ls; + ls = i; + noscale = 0; +} + + +void casepo(void) +{ + int i; + + if (skip()) + i = po1; + else { + i = max(hnumb(&po), 0); + if (nonumb) + i = po1; + } + po1 = po; + po = i; + if (TROFF & !ascii) + esc += po - po1; +} + + +void casepl(void) +{ + int i; + + skip(); + if ((i = vnumb(&pl)) == 0) + pl = 11 * INCH; /*11in*/ + else + pl = i; + if (numtabp[NL].val > pl) + numtabp[NL].val = pl; +} + + +void casewh(void) +{ + int i, j, k; + + lgf++; + skip(); + i = vnumb((int *)0); + if (nonumb) + return; + skip(); + j = getrq(); + if ((k = findn(i)) != NTRAP) { + mlist[k] = j; + return; + } + for (k = 0; k < NTRAP; k++) + if (mlist[k] == 0) + break; + if (k == NTRAP) { + flusho(); + ERROR "cannot plant trap." WARN; + return; + } + mlist[k] = j; + nlist[k] = i; +} + + +void casech(void) +{ + int i, j, k; + + lgf++; + skip(); + if (!(j = getrq())) + return; + else + for (k = 0; k < NTRAP; k++) + if (mlist[k] == j) + break; + if (k == NTRAP) + return; + skip(); + i = vnumb((int *)0); + if (nonumb) + mlist[k] = 0; + nlist[k] = i; +} + + +findn(int i) +{ + int k; + + for (k = 0; k < NTRAP; k++) + if ((nlist[k] == i) && (mlist[k] != 0)) + break; + return(k); +} + + +void casepn(void) +{ + int i; + + skip(); + noscale++; + i = max(inumb(&numtabp[PN].val), 0); + noscale = 0; + if (!nonumb) { + npn = i; + npnflg++; + } +} + + +void casebp(void) +{ + int i; + Stack *savframe; + + if (dip != d) + return; + savframe = frame; + skip(); + if ((i = inumb(&numtabp[PN].val)) < 0) + i = 0; + tbreak(); + if (!nonumb) { + npn = i; + npnflg++; + } else if (dip->nls) + return; + eject(savframe); +} + +void casetm(void) +{ + casetm1(0, stderr); +} + + +void casefm(void) +{ + static struct fcache { + char *name; + FILE *fp; + } fcache[15]; + int i; + + if ( skip() || !getname()) { + ERROR "fm: missing filename" WARN; + return; + } + + for (i = 0; i < 15 && fcache[i].fp != NULL; i++) { + if (strcmp(nextf, fcache[i].name) == 0) + break; + } + if (i >= 15) { + ERROR "fm: too many streams" WARN; + return; + } + if (fcache[i].fp == NULL) { + if( (fcache[i].fp = fopen(unsharp(nextf), "w")) == NULL) { + ERROR "fm: cannot open %s", nextf WARN; + return; + } + fcache[i].name = strdupl(nextf); + } + casetm1(0, fcache[i].fp); +} + +void casetm1(int ab, FILE *out) +{ + int i, j, c; + char *p; + char tmbuf[NTM]; + + lgf++; + copyf++; + if (ab) { + if (skip()) + ERROR "User Abort" WARN; + else { + extern int error; + int savtrac = trace; + i = trace = 0; + noscale++; + i = inumb(&trace); + noscale--; + if (i) { + error = i; + if (nlflg || skip()) + ERROR "User Abort, exit code %d", i WARN; + } + trace = savtrac; + } + } else + skip(); + for (i = 0; i < NTM - 2; ) { + if ((c = cbits(getch())) == '\n' || c == RIGHT) + break; + else if (c == MINUS) { /* special pleading for strange encodings */ + tmbuf[i++] = '\\'; + tmbuf[i++] = '-'; + } else if (c == PRESC) { + tmbuf[i++] = '\\'; + tmbuf[i++] = 'e'; + } else if (c == FILLER) { + tmbuf[i++] = '\\'; + tmbuf[i++] = '&'; + } else if (c == UNPAD) { + tmbuf[i++] = '\\'; + tmbuf[i++] = ' '; + } else if (c == OHC) { + tmbuf[i++] = '\\'; + tmbuf[i++] = '%'; + } else if (c >= ALPHABET) { + p = chname(c); + switch (*p) { + case MBchar: + sprintf(&tmbuf[i], p+1); + break; + case Number: + sprintf(&tmbuf[i], "\\N'%s'", p+1); + break; + case Troffchar: + if ((j = strlen(p+1)) == 2) + sprintf(&tmbuf[i], "\\(%s", p+1); + else + sprintf(&tmbuf[i], "\\C'%s'", p+1); + break; + default: + sprintf(&tmbuf[i]," %s? ", p); + break; + } + j = strlen(&tmbuf[i]); + i += j; + } else + tmbuf[i++] = c; + } + tmbuf[i] = 0; + if (ab) /* truncate output */ + obufp = obuf; /* should be a function in n2.c */ + flusho(); + if (i) + fprintf(out, "%s\n", tmbuf); + fflush(out); + copyf--; + lgf--; +} + + +void casesp(void) +{ + casesp1(0); +} + +void casesp1(int a) +{ + int i, j, savlss; + + tbreak(); + if (dip->nls || trap) + return; + i = findt1(); + if (!a) { + skip(); + j = vnumb((int *)0); + if (nonumb) + j = lss; + } else + j = a; + if (j == 0) + return; + if (i < j) + j = i; + savlss = lss; + if (dip != d) + i = dip->dnl; + else + i = numtabp[NL].val; + if ((i + j) < 0) + j = -i; + lss = j; + newline(0); + lss = savlss; +} + + +void casert(void) +{ + int a, *p; + + skip(); + if (dip != d) + p = &dip->dnl; + else + p = &numtabp[NL].val; + a = vnumb(p); + if (nonumb) + a = dip->mkline; + if ((a < 0) || (a >= *p)) + return; + nb++; + casesp1(a - *p); +} + + +void caseem(void) +{ + lgf++; + skip(); + em = getrq(); +} + + +void casefl(void) +{ + tbreak(); + if (!ascii) + ptflush(); + flusho(); +} + + +void caseev(void) +{ + int nxev; + + if (skip()) { +e0: + if (evi == 0) + return; + nxev = evlist[--evi]; + goto e1; + } + noscale++; + nxev = atoi0(); + noscale = 0; + if (nonumb) + goto e0; + flushi(); + if (nxev >= NEV || nxev < 0 || evi >= EVLSZ) { + flusho(); + ERROR "cannot do .ev %d", nxev WARN; + if (error) + done2(040); + else + edone(040); + return; + } + evlist[evi++] = ev; +e1: + if (ev == nxev) + return; + ev = nxev; + envp = &env[ev]; +} + +void envcopy(Env *e1, Env *e2) /* copy env e2 to e1 */ +{ + *e1 = *e2; /* rumor hath that this fails on some machines */ +} + + +void caseel(void) +{ + if (--ifx < 0) { + ifx = 0; + iflist[0] = 0; + } + caseif1(2); +} + + +void caseie(void) +{ + if (ifx >= NIF) { + ERROR "if-else overflow." WARN; + ifx = 0; + edone(040); + } + caseif1(1); + ifx++; +} + + +void caseif(void) +{ + caseif1(0); +} + +void caseif1(int x) +{ + extern int falsef; + int notflag, true; + Tchar i; + + if (x == 2) { + notflag = 0; + true = iflist[ifx]; + goto i1; + } + true = 0; + skip(); + if ((cbits(i = getch())) == '!') { + notflag = 1; + } else { + notflag = 0; + ch = i; + } + ifnum++; + i = atoi0(); + ifnum = 0; + if (!nonumb) { + if (i > 0) + true++; + goto i1; + } + i = getch(); + switch (cbits(i)) { + case 'e': + if (!(numtabp[PN].val & 01)) + true++; + break; + case 'o': + if (numtabp[PN].val & 01) + true++; + break; + case 'n': + if (NROFF) + true++; + break; + case 't': + if (TROFF) + true++; + break; + case ' ': + break; + default: + true = cmpstr(i); + } +i1: + true ^= notflag; + if (x == 1) + iflist[ifx] = !true; + if (true) { +i2: + while ((cbits(i = getch())) == ' ') + ; + if (cbits(i) == LEFT) + goto i2; + ch = i; + nflush++; + } else { + if (!nlflg) { + copyf++; + falsef++; + eatblk(0); + copyf--; + falsef--; + } + } +} + +void eatblk(int inblk) +{ + int cnt, i; + + cnt = 0; + do { + if (ch) { + i = cbits(ch); + ch = 0; + } else + i = cbits(getch0()); + if (i == ESC) + cnt++; + else { + if (cnt == 1) + switch (i) { + case '{': i = LEFT; break; + case '}': i = RIGHT; break; + case '\n': i = 'x'; break; + } + cnt = 0; + } + if (i == LEFT) eatblk(1); + } while ((!inblk && (i != '\n')) || (inblk && (i != RIGHT))); + if (i == '\n') { + nlflg++; + if (ip == 0) + numtabp[CD].val++; + } +} + + +cmpstr(Tchar c) +{ + int j, delim; + Tchar i; + int val; + int savapts, savapts1, savfont, savfont1, savpts, savpts1; + Tchar string[1280]; + Tchar *sp; + + if (ismot(c)) + return(0); + delim = cbits(c); + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + sp = string; + while ((j = cbits(i = getch()))!=delim && j!='\n' && sp<&string[1280-1]) + *sp++ = i; + if (sp >= string + 1280) { + ERROR "too-long string compare." WARN; + edone(0100); + } + if (nlflg) { + val = sp==string; + goto rtn; + } + *sp = 0; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + val = 1; + sp = string; + while ((j = cbits(i = getch())) != delim && j != '\n') { + if (*sp != i) { + eat(delim); + val = 0; + goto rtn; + } + sp++; + } + if (*sp) + val = 0; +rtn: + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + return(val); +} + + +void caserd(void) +{ + + lgf++; + skip(); + getname(); + if (!iflg) { + if (quiet) { + if (NROFF) { + echo_off(); + flusho(); + } + fprintf(stderr, "\007"); /*bell*/ + } else { + if (nextf[0]) { + fprintf(stderr, "%s:", nextf); + } else { + fprintf(stderr, "\007"); /*bell*/ + } + } + } + collect(); + tty++; + pushi(RD_OFFSET, PAIR('r','d')); +} + + +rdtty(void) +{ + char onechar; + + onechar = 0; + if (read(0, &onechar, 1) == 1) { + if (onechar == '\n') + tty++; + else + tty = 1; + if (tty != 3) + return(onechar); + } + tty = 0; + if (NROFF && quiet) + echo_on(); + return(0); +} + + +void caseec(void) +{ + eschar = chget('\\'); +} + + +void caseeo(void) +{ + eschar = 0; +} + + +void caseta(void) +{ + int i, j, k; + + tabtab[0] = nonumb = 0; + for (i = 0; ((i < (NTAB - 1)) && !nonumb); i++) { + if (skip()) + break; + k = tabtab[max(i-1, 0)] & TABMASK; + if ((j = max(hnumb(&k), 0)) > TABMASK) { + ERROR "Tab too far away" WARN; + j = TABMASK; + } + tabtab[i] = j & TABMASK; + if (!nonumb) + switch (cbits(ch)) { + case 'C': + tabtab[i] |= CTAB; + break; + case 'R': + tabtab[i] |= RTAB; + break; + default: /*includes L*/ + break; + } + nonumb = ch = 0; + } + if (!skip()) + ERROR "Too many tab stops" WARN; + tabtab[i] = 0; +} + + +void casene(void) +{ + int i, j; + + skip(); + i = vnumb((int *)0); + if (nonumb) + i = lss; + if (dip == d && numtabp[NL].val == -1) { + newline(1); + return; + } + if (i > (j = findt1())) { + i = lss; + lss = j; + dip->nls = 0; + newline(0); + lss = i; + } +} + + +void casetr(void) +{ + int i, j; + Tchar k; + + lgf++; + skip(); + while ((i = cbits(k=getch())) != '\n') { + if (ismot(k)) + return; + if (ismot(k = getch())) + return; + if ((j = cbits(k)) == '\n') + j = ' '; + trtab[i] = j; + } +} + + +void casecu(void) +{ + cu++; + caseul(); +} + + +void caseul(void) +{ + int i; + + noscale++; + skip(); + i = max(atoi0(), 0); + if (nonumb) + i = 1; + if (ul && (i == 0)) { + font = sfont; + ul = cu = 0; + } + if (i) { + if (!ul) { + sfont = font; + font = ulfont; + } + ul = i; + } + noscale = 0; + mchbits(); +} + + +void caseuf(void) +{ + int i, j; + + if (skip() || !(i = getrq()) || i == 'S' || (j = findft(i)) == -1) + ulfont = ULFONT; /*default underline position*/ + else + ulfont = j; + if (NROFF && ulfont == FT) + ulfont = ULFONT; +} + + +void caseit(void) +{ + int i; + + lgf++; + it = itmac = 0; + noscale++; + skip(); + i = atoi0(); + skip(); + if (!nonumb && (itmac = getrq())) + it = i; + noscale = 0; +} + + +void casemc(void) +{ + int i; + + if (icf > 1) + ic = 0; + icf = 0; + if (skip()) + return; + ic = getch(); + icf = 1; + skip(); + i = max(hnumb((int *)0), 0); + if (!nonumb) + ics = i; +} + + +void casemk(void) +{ + int i, j; + + if (dip != d) + j = dip->dnl; + else + j = numtabp[NL].val; + if (skip()) { + dip->mkline = j; + return; + } + if ((i = getrq()) == 0) + return; + numtabp[findr(i)].val = j; +} + + +void casesv(void) +{ + int i; + + skip(); + if ((i = vnumb((int *)0)) < 0) + return; + if (nonumb) + i = 1; + sv += i; + caseos(); +} + + +void caseos(void) +{ + int savlss; + + if (sv <= findt1()) { + savlss = lss; + lss = sv; + newline(0); + lss = savlss; + sv = 0; + } +} + + +void casenm(void) +{ + int i; + + lnmod = nn = 0; + if (skip()) + return; + lnmod++; + noscale++; + i = inumb(&numtabp[LN].val); + if (!nonumb) + numtabp[LN].val = max(i, 0); + getnm(&ndf, 1); + getnm(&nms, 0); + getnm(&ni, 0); + getnm(&nmwid, 3); /* really kludgy! */ + noscale = 0; + nmbits = chbits; +} + +/* + * .nm relies on the fact that illegal args are skipped; don't warn + * for illegality of these + */ +void getnm(int *p, int min) +{ + int i; + int savtr = trace; + + eat(' '); + if (skip()) + return; + trace = 0; + i = atoi0(); + if (nonumb) + return; + *p = max(i, min); + trace = savtr; +} + + +void casenn(void) +{ + noscale++; + skip(); + nn = max(atoi0(), 1); + noscale = 0; +} + + +void caseab(void) +{ + casetm1(1, stderr); + done3(0); +} + + +/* nroff terminal handling has been pretty well excised */ +/* as part of the merge with troff. these are ghostly remnants, */ +/* called, but doing nothing. restore them at your peril. */ + + +void save_tty(void) /*save any tty settings that may be changed*/ +{ +} + + +void restore_tty(void) /*restore tty settings from beginning*/ +{ +} + + +void set_tty(void) +{ +} + + +void echo_off(void) /*turn off ECHO for .rd in "-q" mode*/ +{ +} + + +void echo_on(void) /*restore ECHO after .rd in "-q" mode*/ +{ +} diff --git a/src/cmd/troff/n6.c b/src/cmd/troff/n6.c new file mode 100644 index 00000000..e4affa17 --- /dev/null +++ b/src/cmd/troff/n6.c @@ -0,0 +1,362 @@ +#include "tdef.h" +#include "ext.h" +#include "fns.h" +#include <ctype.h> + +/* + * n6.c -- width functions, sizes and fonts +*/ + +n_width(Tchar j) +{ + int i, k; + + if (iszbit(j)) + return 0; + if (ismot(j)) { + if (isvmot(j)) + return(0); + k = absmot(j); + if (isnmot(j)) + k = -k; + return(k); + } + i = cbits(j); + if (i < ' ') { + if (i == '\b') + return(-widthp); + if (i == PRESC) + i = eschar; + else if (i == HX) + return(0); + } + if (i == ohc) + return(0); + i = trtab[i]; + if (i < ' ') + return(0); + if (i >= t.tfont.nchars) /* not on the font */ + k = t.Char; /* really ought to check properly */ + else + k = t.tfont.wp[i].wid * t.Char; + widthp = k; + return(k); +} + + +Tchar n_setch(int c) +{ + return t_setch(c); +} + +Tchar n_setabs(void) /* set absolute char from \N'...' */ +{ /* for now, a no-op */ + return t_setabs(); +} + +int n_findft(int i) +{ + int k; + + if ((k = i - '0') >= 0 && k <= nfonts && k < smnt) + return(k); + for (k = 0; fontlab[k] != i; k++) + if (k > nfonts) + return(-1); + return(k); +} + + + +void n_mchbits(void) +{ + chbits = 0; + setfbits(chbits, font); + sps = width(' ' | chbits); +} + + +void n_setps(void ) +{ + int i, j; + + i = cbits(getch()); + if (isdigit(i)) { /* \sd or \sdd */ + i -= '0'; + if (i == 0) /* \s0 */ + ; + else if (i <= 3 && (ch=getch()) && isdigit(cbits(ch))) { /* \sdd */ + ch = 0; + } + } else if (i == '(') { /* \s(dd */ + getch(); + getch(); + } else if (i == '+' || i == '-') { /* \s+, \s- */ + j = cbits(getch()); + if (isdigit(j)) { /* \s+d, \s-d */ + ; + } else if (j == '(') { /* \s+(dd, \s-(dd */ + getch(); + getch(); + } + } +} + + +Tchar n_setht(void) /* set character height from \H'...' */ +{ + + getch(); + inumb(&apts); + getch(); + return(0); +} + + +Tchar n_setslant(void) /* set slant from \S'...' */ +{ + int n; + + getch(); + n = 0; + n = inumb(&n); + getch(); + return(0); +} + + +void n_caseft(void) +{ + skip(); + setfont(1); +} + + +void n_setfont(int a) +{ + int i, j; + + if (a) + i = getrq(); + else + i = getsn(); + if (!i || i == 'P') { + j = font1; + goto s0; + } + if (i == 'S' || i == '0') + return; + if ((j = findft(i)) == -1) + return; +s0: + font1 = font; + font = j; + mchbits(); +} + + +void n_setwd(void) +{ + int base, wid; + Tchar i; + int delim, emsz, k; + int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; + + base = numtabp[ST].val = numtabp[ST].val = wid = numtabp[CT].val = 0; + if (ismot(i = getch())) + return; + delim = cbits(i); + savhp = numtabp[HP].val; + numtabp[HP].val = 0; + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + setwdf++; + while (cbits(i = getch()) != delim && !nlflg) { + k = width(i); + wid += k; + numtabp[HP].val += k; + if (!ismot(i)) { + emsz = (INCH * pts + 36) / 72; + } else if (isvmot(i)) { + k = absmot(i); + if (isnmot(i)) + k = -k; + base -= k; + emsz = 0; + } else + continue; + if (base < numtabp[SB].val) + numtabp[SB].val = base; + if ((k = base + emsz) > numtabp[ST].val) + numtabp[ST].val = k; + } + setn1(wid, 0, (Tchar) 0); + numtabp[HP].val = savhp; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + setwdf = 0; +} + + +Tchar n_vmot(void) +{ + dfact = lss; + vflag++; + return n_mot(); +} + + +Tchar n_hmot(void) +{ + dfact = EM; + return n_mot(); +} + + +Tchar n_mot(void) +{ + int j, n; + Tchar i; + + j = HOR; + getch(); /*eat delim*/ + if (n = atoi0()) { + if (vflag) + j = VERT; + i = makem(quant(n, j)); + } else + i = 0; + getch(); + vflag = 0; + dfact = 1; + return(i); +} + + +Tchar n_sethl(int k) +{ + int j; + Tchar i; + + j = t.Halfline; + if (k == 'u') + j = -j; + else if (k == 'r') + j = -2 * j; + vflag++; + i = makem(j); + vflag = 0; + return(i); +} + + +Tchar n_makem(int i) +{ + Tchar j; + + if (i >= 0) + j = i; + else + j = -i; + j |= MOT; + if (i < 0) + j |= NMOT; + if (vflag) + j |= VMOT; + return(j); +} + + +void n_casefp(void) +{ + int i, j; + + skip(); + if ((i = cbits(getch()) - '0') < 0 || i > nfonts) + return; + if (skip() || !(j = getrq())) + return; + fontlab[i] = j; +} + + + +void n_casebd(void) +{ + int i, j, k; + + k = 0; +bd0: + if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { + if (k) + goto bd1; + else + return; + } + if (j == smnt) { + k = smnt; + goto bd0; + } + if (k) { + sbold = j; + j = k; + } +bd1: + skip(); + noscale++; + bdtab[j] = atoi0(); + noscale = 0; +} + + +void n_casevs(void) +{ + int i; + + skip(); + vflag++; + dfact = INCH; /*default scaling is points!*/ + dfactd = 72; + res = VERT; + i = inumb(&lss); + if (nonumb) + i = lss1; + if (i < VERT) + i = VERT; /* was VERT */ + lss1 = lss; + lss = i; +} + + + + +Tchar n_xlss(void) +{ + /* stores \x'...' into + /* two successive Tchars. + /* the first contains HX, the second the value, + /* encoded as a vertical motion. + /* decoding is done in n2.c by pchar(). + */ + int i; + + getch(); + dfact = lss; + i = quant(atoi0(), VERT); + dfact = 1; + getch(); + if (i >= 0) + *pbp++ = MOT | VMOT | i; + else + *pbp++ = MOT | VMOT | NMOT | -i; + return(HX); +} diff --git a/src/cmd/troff/n7.c b/src/cmd/troff/n7.c new file mode 100644 index 00000000..c22a485c --- /dev/null +++ b/src/cmd/troff/n7.c @@ -0,0 +1,834 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +#ifdef STRICT + /* not in ANSI or POSIX */ +#define isascii(a) ((a) >= 0 && (a) <= 127) +#endif + +#define GETCH gettch +Tchar gettch(void); + + +/* + * troff7.c + * + * text + */ + +int brflg; + +void tbreak(void) +{ + int pad, k; + Tchar *i, j; + int resol; + int un0 = un; + + trap = 0; + if (nb) + return; + if (dip == d && numtabp[NL].val == -1) { + newline(1); + return; + } + if (!nc) { + setnel(); + if (!wch) + return; + if (pendw) + getword(1); + movword(); + } else if (pendw && !brflg) { + getword(1); + movword(); + } + *linep = dip->nls = 0; + if (NROFF && dip == d) + horiz(po); + if (lnmod) + donum(); + lastl = ne; + if (brflg != 1) { + totout = 0; + } else if (ad) { + if ((lastl = ll - un) < ne) + lastl = ne; + } + if (admod && ad && (brflg != 2)) { + lastl = ne; + adsp = adrem = 0; + if (admod == 1) + un += quant(nel / 2, HOR); + else if (admod == 2) + un += nel; + } + totout++; + brflg = 0; + if (lastl + un > dip->maxl) + dip->maxl = lastl + un; + horiz(un); + if (NROFF) { + if (adrem % t.Adj) + resol = t.Hor; + else + resol = t.Adj; + } else + resol = HOR; + + lastl = ne + (nwd-1) * adsp + adrem; + for (i = line; nc > 0; ) { + if ((cbits(j = *i++)) == ' ') { + pad = 0; + do { + pad += width(j); + nc--; + } while ((cbits(j = *i++)) == ' '); + i--; + pad += adsp; + --nwd; + if (adrem) { + if (adrem < 0) { + pad -= resol; + adrem += resol; + } else if ((totout & 01) || adrem / resol >= nwd) { + pad += resol; + adrem -= resol; + } + } + pchar((Tchar) WORDSP); + horiz(pad); + } else { + pchar(j); + nc--; + } + } + if (ic) { + if ((k = ll - un0 - lastl + ics) > 0) + horiz(k); + pchar(ic); + } + if (icf) + icf++; + else + ic = 0; + ne = nwd = 0; + un = in; + setnel(); + newline(0); + if (dip != d) { + if (dip->dnl > dip->hnl) + dip->hnl = dip->dnl; + } else { + if (numtabp[NL].val > dip->hnl) + dip->hnl = numtabp[NL].val; + } + for (k = ls - 1; k > 0 && !trap; k--) + newline(0); + spread = 0; +} + +void donum(void) +{ + int i, nw; + int lnv = numtabp[LN].val; + + nrbits = nmbits; + nw = width('1' | nrbits); + if (nn) { + nn--; + goto d1; + } + if (lnv % ndf) { + numtabp[LN].val++; +d1: + un += nw * (nmwid + nms + ni); + return; + } + i = 0; + do { /* count digits in numtabp[LN].val */ + i++; + } while ((lnv /= 10) > 0); + horiz(nw * (ni + max(nmwid-i, 0))); + nform = 0; + fnumb(numtabp[LN].val, pchar); + un += nw * nms; + numtabp[LN].val++; +} + + +void text(void) +{ + Tchar i; + static int spcnt; + + nflush++; + numtabp[HP].val = 0; + if ((dip == d) && (numtabp[NL].val == -1)) { + newline(1); + return; + } + setnel(); + if (ce || !fi) { + nofill(); + return; + } + if (pendw) + goto t4; + if (pendt) + if (spcnt) + goto t2; + else + goto t3; + pendt++; + if (spcnt) + goto t2; + while ((cbits(i = GETCH())) == ' ') { + spcnt++; + numtabp[HP].val += sps; + widthp = sps; + } + if (nlflg) { +t1: + nflush = pendt = ch = spcnt = 0; + callsp(); + return; + } + ch = i; + if (spcnt) { +t2: + tbreak(); + if (nc || wch) + goto rtn; + un += spcnt * sps; + spcnt = 0; + setnel(); + if (trap) + goto rtn; + if (nlflg) + goto t1; + } +t3: + if (spread) + goto t5; + if (pendw || !wch) +t4: + if (getword(0)) + goto t6; + if (!movword()) + goto t3; +t5: + if (nlflg) + pendt = 0; + adsp = adrem = 0; + if (ad) { + if (nwd == 1) + adsp = nel; + else + adsp = nel / (nwd - 1); + adsp = (adsp / HOR) * HOR; + adrem = nel - adsp*(nwd-1); + } + brflg = 1; + tbreak(); + spread = 0; + if (!trap) + goto t3; + if (!nlflg) + goto rtn; +t6: + pendt = 0; + ckul(); +rtn: + nflush = 0; +} + + +void nofill(void) +{ + int j; + Tchar i; + + if (!pendnf) { + over = 0; + tbreak(); + if (trap) + goto rtn; + if (nlflg) { + ch = nflush = 0; + callsp(); + return; + } + adsp = adrem = 0; + nwd = 10000; + } + while ((j = (cbits(i = GETCH()))) != '\n') { + if (j == ohc) + continue; + if (j == CONT) { + pendnf++; + nflush = 0; + flushi(); + ckul(); + return; + } + j = width(i); + widthp = j; + numtabp[HP].val += j; + storeline(i, j); + } + if (ce) { + ce--; + if ((i = quant(nel / 2, HOR)) > 0) + un += i; + } + if (!nc) + storeline((Tchar)FILLER, 0); + brflg = 2; + tbreak(); + ckul(); +rtn: + pendnf = nflush = 0; +} + + +void callsp(void) +{ + int i; + + if (flss) + i = flss; + else + i = lss; + flss = 0; + casesp1(i); +} + + +void ckul(void) +{ + if (ul && (--ul == 0)) { + cu = 0; + font = sfont; + mchbits(); + } + if (it && --it == 0 && itmac) + control(itmac, 0); +} + + +void storeline(Tchar c, int w) +{ + int diff; + + if (linep >= line + lnsize - 2) { + lnsize += LNSIZE; + diff = linep - line; + if (( line = (Tchar *)realloc((char *)line, lnsize * sizeof(Tchar))) != NULL) { + if (linep && diff) + linep = line + diff; + } else { + if (over) { + return; + } else { + flusho(); + ERROR "Line overflow." WARN; + over++; + *linep++ = LEFTHAND; + w = width(LEFTHAND); + nc++; + c = '\n'; + } + } + } + *linep++ = c; + ne += w; + nel -= w; + nc++; +} + + +void newline(int a) +{ + int i, j, nlss; + int opn; + + if (a) + goto nl1; + if (dip != d) { + j = lss; + pchar1((Tchar)FLSS); + if (flss) + lss = flss; + i = lss + dip->blss; + dip->dnl += i; + pchar1((Tchar)i); + pchar1((Tchar)'\n'); + lss = j; + dip->blss = flss = 0; + if (dip->alss) { + pchar1((Tchar)FLSS); + pchar1((Tchar)dip->alss); + pchar1((Tchar)'\n'); + dip->dnl += dip->alss; + dip->alss = 0; + } + if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac) + if (control(dip->dimac, 0)) { + trap++; + dip->ditf++; + } + return; + } + j = lss; + if (flss) + lss = flss; + nlss = dip->alss + dip->blss + lss; + numtabp[NL].val += nlss; + if (TROFF && ascii) { + dip->alss = dip->blss = 0; + } + pchar1((Tchar)'\n'); + flss = 0; + lss = j; + if (numtabp[NL].val < pl) + goto nl2; +nl1: + ejf = dip->hnl = numtabp[NL].val = 0; + ejl = frame; + if (donef) { + if ((!nc && !wch) || ndone) + done1(0); + ndone++; + donef = 0; + if (frame == stk) + nflush++; + } + opn = numtabp[PN].val; + numtabp[PN].val++; + if (npnflg) { + numtabp[PN].val = npn; + npn = npnflg = 0; + } +nlpn: + if (numtabp[PN].val == pfrom) { + print++; + pfrom = -1; + } else if (opn == pto) { + print = 0; + opn = -1; + chkpn(); + goto nlpn; + } + if (print) + ptpage(numtabp[PN].val); /* supposedly in a clean state so can pause */ + if (stop && print) { + dpn++; + if (dpn >= stop) { + dpn = 0; + ptpause(); + } + } +nl2: + trap = 0; + if (numtabp[NL].val == 0) { + if ((j = findn(0)) != NTRAP) + trap = control(mlist[j], 0); + } else if ((i = findt(numtabp[NL].val - nlss)) <= nlss) { + if ((j = findn1(numtabp[NL].val - nlss + i)) == NTRAP) { + flusho(); + ERROR "Trap botch." WARN; + done2(-5); + } + trap = control(mlist[j], 0); + } +} + + +findn1(int a) +{ + int i, j; + + for (i = 0; i < NTRAP; i++) { + if (mlist[i]) { + if ((j = nlist[i]) < 0) + j += pl; + if (j == a) + break; + } + } + return(i); +} + + +void chkpn(void) +{ + pto = *(pnp++); + pfrom = pto>=0 ? pto : -pto; + if (pto == -INT_MAX) { + flusho(); + done1(0); + } + if (pto < 0) { + pto = -pto; + print++; + pfrom = 0; + } +} + + +findt(int a) +{ + int i, j, k; + + k = INT_MAX; + if (dip != d) { + if (dip->dimac && (i = dip->ditrap - a) > 0) + k = i; + return(k); + } + for (i = 0; i < NTRAP; i++) { + if (mlist[i]) { + if ((j = nlist[i]) < 0) + j += pl; + if ((j -= a) <= 0) + continue; + if (j < k) + k = j; + } + } + i = pl - a; + if (k > i) + k = i; + return(k); +} + + +findt1(void) +{ + int i; + + if (dip != d) + i = dip->dnl; + else + i = numtabp[NL].val; + return(findt(i)); +} + + +void eject(Stack *a) +{ + int savlss; + + if (dip != d) + return; + ejf++; + if (a) + ejl = a; + else + ejl = frame; + if (trap) + return; +e1: + savlss = lss; + lss = findt(numtabp[NL].val); + newline(0); + lss = savlss; + if (numtabp[NL].val && !trap) + goto e1; +} + + +movword(void) +{ + int w; + Tchar i, *wp; + int savwch, hys; + + over = 0; + wp = wordp; + if (!nwd) { + while (cbits(*wp++) == ' ') { + wch--; + wne -= sps; + } + wp--; + } + if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) && + (!(hyf & 02) || (findt1() > lss))) + hyphen(wp); + savwch = wch; + hyp = hyptr; + nhyp = 0; + while (*hyp && *hyp <= wp) + hyp++; + while (wch) { + if (hyoff != 1 && *hyp == wp) { + hyp++; + if (!wdstart || (wp > wdstart + 1 && wp < wdend && + (!(hyf & 04) || wp < wdend - 1) && /* 04 => last 2 */ + (!(hyf & 010) || wp > wdstart + 2))) { /* 010 => 1st 2 */ + nhyp++; + storeline((Tchar)IMP, 0); + } + } + i = *wp++; + w = width(i); + wne -= w; + wch--; + storeline(i, w); + } + if (nel >= 0) { + nwd++; + return(0); /* line didn't fill up */ + } + if (TROFF) + xbits((Tchar)HYPHEN, 1); + hys = width((Tchar)HYPHEN); +m1: + if (!nhyp) { + if (!nwd) + goto m3; + if (wch == savwch) + goto m4; + } + if (*--linep != IMP) + goto m5; + if (!(--nhyp)) + if (!nwd) + goto m2; + if (nel < hys) { + nc--; + goto m1; + } +m2: + if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) { + *linep = (*(linep - 1) & SFMASK) | HYPHEN; + w = width(*linep); + nel -= w; + ne += w; + linep++; + } +m3: + nwd++; +m4: + wordp = wp; + return(1); /* line filled up */ +m5: + nc--; + w = width(*linep); + ne -= w; + nel += w; + wne += w; + wch++; + wp--; + goto m1; +} + + +void horiz(int i) +{ + vflag = 0; + if (i) + pchar(makem(i)); +} + + +void setnel(void) +{ + if (!nc) { + linep = line; + if (un1 >= 0) { + un = un1; + un1 = -1; + } + nel = ll - un; + ne = adsp = adrem = 0; + } +} + + +getword(int x) +{ + int j, k; + Tchar i, *wp; + int noword; + int obits; + + noword = 0; + if (x) + if (pendw) { + *pendw = 0; + goto rtn; + } + if (wordp = pendw) + goto g1; + hyp = hyptr; + wordp = word; + over = wne = wch = 0; + hyoff = 0; + obits = chbits; + while (1) { /* picks up 1st char of word */ + j = cbits(i = GETCH()); + if (j == '\n') { + wne = wch = 0; + noword = 1; + goto rtn; + } + if (j == ohc) { + hyoff = 1; /* 1 => don't hyphenate */ + continue; + } + if (j == ' ') { + numtabp[HP].val += sps; + widthp = sps; + storeword(i, sps); + continue; + } + break; + } + storeword(' ' | obits, sps); + if (spflg) { + storeword(' ' | obits, sps); + spflg = 0; + } +g0: + if (j == CONT) { + pendw = wordp; + nflush = 0; + flushi(); + return(1); + } + if (hyoff != 1) { + if (j == ohc) { + hyoff = 2; + *hyp++ = wordp; + if (hyp > hyptr + NHYP - 1) + hyp = hyptr + NHYP - 1; + goto g1; + } + if (((j == '-' || j == EMDASH)) && !(i & ZBIT)) /* zbit avoids \X */ + if (wordp > word + 1) { + hyoff = 2; + *hyp++ = wordp + 1; + if (hyp > hyptr + NHYP - 1) + hyp = hyptr + NHYP - 1; + } + } + j = width(i); + numtabp[HP].val += j; + storeword(i, j); +g1: + j = cbits(i = GETCH()); + if (j != ' ') { + static char *sentchar = ".?!"; /* sentence terminators */ + if (j != '\n') + goto g0; + wp = wordp-1; /* handle extra space at end of sentence */ + while (wp >= word) { + j = cbits(*wp--); + if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER) + continue; + for (k = 0; sentchar[k]; k++) + if (j == sentchar[k]) { + spflg++; + break; + } + break; + } + } + *wordp = 0; + numtabp[HP].val += sps; +rtn: + for (wp = word; *wp; wp++) { + if (ismot(j)) + break; /* drechsler */ + j = cbits(*wp); + if (j == ' ') + continue; + if (!(isascii(j) && isdigit(j)) && j != '-') + break; + } + if (*wp == 0) /* all numbers, so don't hyphenate */ + hyoff = 1; + wdstart = 0; + wordp = word; + pendw = 0; + *hyp++ = 0; + setnel(); + return(noword); +} + + +void storeword(Tchar c, int w) +{ + Tchar *savp; + int i; + + if (wordp >= word + wdsize - 2) { + wdsize += WDSIZE; + savp = word; + if (( word = (Tchar *)realloc((char *)word, wdsize * sizeof(Tchar))) != NULL) { + if (wordp) + wordp = word + (wordp - savp); + if (pendw) + pendw = word + (pendw - savp); + if (wdstart) + wdstart = word + (wdstart - savp); + if (wdend) + wdend = word + (wdend - savp); + for (i = 0; i < NHYP; i++) + if (hyptr[i]) + hyptr[i] = word + (hyptr[i] - savp); + } else { + if (over) { + return; + } else { + flusho(); + ERROR "Word overflow." WARN; + over++; + c = LEFTHAND; + w = width(LEFTHAND); + } + } + } + widthp = w; + wne += w; + *wordp++ = c; + wch++; +} + + +Tchar gettch(void) +{ + extern int c_isalnum; + Tchar i; + int j; + + if (TROFF) + return getch(); + + i = getch(); + j = cbits(i); + if (ismot(i) || fbits(i) != ulfont) + return(i); + if (cu) { + if (trtab[j] == ' ') { + setcbits(i, '_'); + setfbits(i, FT); /* default */ + } + return(i); + } + /* should test here for characters that ought to be underlined */ + /* in the old nroff, that was the 200 bit on the width! */ + /* for now, just do letters, digits and certain special chars */ + if (j <= 127) { + if (!isalnum(j)) + setfbits(i, FT); + } else { + if (j < c_isalnum) + setfbits(i, FT); + } + return(i); +} diff --git a/src/cmd/troff/n8.c b/src/cmd/troff/n8.c new file mode 100644 index 00000000..d1be5080 --- /dev/null +++ b/src/cmd/troff/n8.c @@ -0,0 +1,540 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +#define HY_BIT 0200 /* stuff in here only works for 7-bit ascii */ + /* this value is used (as a literal) in suftab.c */ + /* to encode possible hyphenation points in suffixes. */ + /* it could be changed, by widening the tables */ + /* to be shorts instead of chars. */ + +/* + * troff8.c + * + * hyphenation + */ + +int hexsize = 0; /* hyphenation exception list size */ +char *hbufp = NULL; /* base of list */ +char *nexth = NULL; /* first free slot in list */ +Tchar *hyend; + +#define THRESH 160 /* digram goodness threshold */ +int thresh = THRESH; + +int texhyphen(void); +static int alpha(Tchar); + +void hyphen(Tchar *wp) +{ + int j; + Tchar *i; + + i = wp; + while (punct((*i++))) + ; + if (!alpha(*--i)) + return; + wdstart = i++; + while (alpha(*i++)) + ; + hyend = wdend = --i - 1; + while (punct((*i++))) + ; + if (*--i) + return; + if (wdend - wdstart < 4) /* 4 chars is too short to hyphenate */ + return; + hyp = hyptr; + *hyp = 0; + hyoff = 2; + + /* for now, try exceptions first, then tex (if hyphalg is non-zero), + then suffix and digram if tex didn't hyphenate it at all. + */ + + if (!exword() && !texhyphen() && !suffix()) + digram(); + + /* this appears to sort hyphenation points into increasing order */ + *hyp++ = 0; + if (*hyptr) + for (j = 1; j; ) { + j = 0; + for (hyp = hyptr + 1; *hyp != 0; hyp++) { + if (*(hyp - 1) > *hyp) { + j++; + i = *hyp; + *hyp = *(hyp - 1); + *(hyp - 1) = i; + } + } + } +} + +static alpha(Tchar i) /* non-zero if really alphabetic */ +{ + if (ismot(i)) + return 0; + else if (cbits(i) >= ALPHABET) /* this isn't very elegant, but there's */ + return 0; /* no good way to make sure i is in range for */ + else /* the call of isalpha */ + return isalpha(cbits(i)); +} + + +punct(Tchar i) +{ + if (!i || alpha(i)) + return(0); + else + return(1); +} + + +void caseha(void) /* set hyphenation algorithm */ +{ + hyphalg = HYPHALG; + if (skip()) + return; + noscale++; + hyphalg = atoi0(); + noscale = 0; +} + + +void caseht(void) /* set hyphenation threshold; not in manual! */ +{ + thresh = THRESH; + if (skip()) + return; + noscale++; + thresh = atoi0(); + noscale = 0; +} + + +char *growh(char *where) +{ + char *new; + + hexsize += NHEX; + if ((new = grow(hbufp, hexsize, sizeof(char))) == NULL) + return NULL; + if (new == hbufp) { + return where; + } else { + int diff; + diff = where - hbufp; + hbufp = new; + return new + diff; + } +} + + +void casehw(void) +{ + int i, k; + char *j; + Tchar t; + + if (nexth == NULL) { + if ((nexth = hbufp = grow(hbufp, NHEX, sizeof(char))) == NULL) { + ERROR "No space for exception word list." WARN; + return; + } + hexsize = NHEX; + } + k = 0; + while (!skip()) { + if ((j = nexth) >= hbufp + hexsize - 2) + if ((j = nexth = growh(j)) == NULL) + goto full; + for (;;) { + if (ismot(t = getch())) + continue; + i = cbits(t); + if (i == ' ' || i == '\n') { + *j++ = 0; + nexth = j; + *j = 0; + if (i == ' ') + break; + else + return; + } + if (i == '-') { + k = HY_BIT; + continue; + } + *j++ = maplow(i) | k; + k = 0; + if (j >= hbufp + hexsize - 2) + if ((j = growh(j)) == NULL) + goto full; + } + } + return; +full: + ERROR "Cannot grow exception word list." WARN; + *nexth = 0; +} + + +int exword(void) +{ + Tchar *w; + char *e, *save; + + e = hbufp; + while (1) { + save = e; + if (e == NULL || *e == 0) + return(0); + w = wdstart; + while (*e && w <= hyend && (*e & 0177) == maplow(cbits(*w))) { + e++; + w++; + } + if (!*e) { + if (w-1 == hyend || (w == wdend && maplow(cbits(*w)) == 's')) { + w = wdstart; + for (e = save; *e; e++) { + if (*e & HY_BIT) + *hyp++ = w; + if (hyp > hyptr + NHYP - 1) + hyp = hyptr + NHYP - 1; + w++; + } + return(1); + } else { + e++; + continue; + } + } else + while (*e++) + ; + } +} + + +suffix(void) +{ + Tchar *w; + char *s, *s0; + Tchar i; + extern char *suftab[]; + +again: + i = cbits(*hyend); + if (!alpha(i)) + return(0); + if (i < 'a') + i -= 'A' - 'a'; + if ((s0 = suftab[i-'a']) == 0) + return(0); + for (;;) { + if ((i = *s0 & 017) == 0) + return(0); + s = s0 + i - 1; + w = hyend - 1; + while (s > s0 && w >= wdstart && (*s & 0177) == maplow(cbits(*w))) { + s--; + w--; + } + if (s == s0) + break; + s0 += i; + } + s = s0 + i - 1; + w = hyend; + if (*s0 & HY_BIT) + goto mark; + while (s > s0) { + w--; + if (*s-- & HY_BIT) { +mark: + hyend = w - 1; + if (*s0 & 0100) /* 0100 used in suftab to encode something too */ + continue; + if (!chkvow(w)) + return(0); + *hyp++ = w; + } + } + if (*s0 & 040) + return(0); + if (exword()) + return(1); + goto again; +} + + +maplow(int i) +{ + if (isupper(i)) + i = tolower(i); + return(i); +} + + +vowel(int i) +{ + switch (i) { + case 'a': case 'A': + case 'e': case 'E': + case 'i': case 'I': + case 'o': case 'O': + case 'u': case 'U': + case 'y': case 'Y': + return(1); + default: + return(0); + } +} + + +Tchar *chkvow(Tchar *w) +{ + while (--w >= wdstart) + if (vowel(cbits(*w))) + return(w); + return(0); +} + + +void digram(void) +{ + Tchar *w; + int val; + Tchar *nhyend, *maxw; + int maxval; + extern char bxh[26][13], bxxh[26][13], xxh[26][13], xhx[26][13], hxx[26][13]; + +again: + if (!(w = chkvow(hyend + 1))) + return; + hyend = w; + if (!(w = chkvow(hyend))) + return; + nhyend = w; + maxval = 0; + w--; + while (++w < hyend && w < wdend - 1) { + val = 1; + if (w == wdstart) + val *= dilook('a', cbits(*w), bxh); + else if (w == wdstart + 1) + val *= dilook(cbits(*(w-1)), cbits(*w), bxxh); + else + val *= dilook(cbits(*(w-1)), cbits(*w), xxh); + val *= dilook(cbits(*w), cbits(*(w+1)), xhx); + val *= dilook(cbits(*(w+1)), cbits(*(w+2)), hxx); + if (val > maxval) { + maxval = val; + maxw = w + 1; + } + } + hyend = nhyend; + if (maxval > thresh) + *hyp++ = maxw; + goto again; +} + + +dilook(int a, int b, char t[26][13]) +{ + int i, j; + + i = t[maplow(a)-'a'][(j = maplow(b)-'a')/2]; + if (!(j & 01)) + i >>= 4; + return(i & 017); +} + + +/* here beginneth the tex hyphenation code, as interpreted freely */ +/* the main difference is that there is no attempt to squeeze space */ +/* as tightly at tex does. */ + +static int texit(Tchar *, Tchar *); +static int readpats(void); +static void install(char *); +static void fixup(void); +static int trieindex(int, int); + +static char pats[50000]; /* size ought to be computed dynamically */ +static char *nextpat = pats; +static char *trie[27*27]; /* english-specific sizes */ + +int texhyphen(void) +{ + static int loaded = 0; /* -1: couldn't find tex file */ + + if (hyphalg == 0 || loaded == -1) /* non-zero => tex for now */ + return 0; + if (loaded == 0) { + if (readpats()) + loaded = 1; + else + loaded = -1; + } + return texit(wdstart, wdend); +} + +static int texit(Tchar *start, Tchar *end) /* hyphenate as in tex, return # found */ +{ + int nw, i, k, equal, cnt[500]; + char w[500+1], *np, *pp, *wp, *xpp, *xwp; + + w[0] = '.'; + for (nw = 1; start <= end && nw < 500-1; nw++, start++) + w[nw] = maplow(tolower(cbits(*start))); + start -= (nw - 1); + w[nw++] = '.'; + w[nw] = 0; +/* + * printf("try %s\n", w); +*/ + for (i = 0; i <= nw; i++) + cnt[i] = '0'; + + for (wp = w; wp < w + nw; wp++) { + for (pp = trie[trieindex(*wp, *(wp+1))]; pp < nextpat; ) { + if (pp == 0 /* no trie entry */ + || *pp != *wp /* no match on 1st letter */ + || *(pp+1) != *(wp+1)) /* no match on 2nd letter */ + break; /* so move to next letter of word */ + equal = 1; + for (xpp = pp+2, xwp = wp+2; *xpp; ) + if (*xpp++ != *xwp++) { + equal = 0; + break; + } + if (equal) { + np = xpp+1; /* numpat */ + for (k = wp-w; *np; k++, np++) + if (*np > cnt[k]) + cnt[k] = *np; +/* + * printf("match: %s %s\n", pp, xpp+1); +*/ + } + pp += *(pp-1); /* skip over pattern and numbers to next */ + } + } +/* + * for (i = 0; i < nw; i++) printf("%c", w[i]); + * printf(" "); + * for (i = 0; i <= nw; i++) printf("%c", cnt[i]); + * printf("\n"); +*/ +/* + * for (i = 1; i < nw - 1; i++) { + * if (i > 2 && i < nw - 3 && cnt[i] % 2) + * printf("-"); + * if (cbits(start[i-1]) != '.') + * printf("%c", cbits(start[i-1])); + * } + * printf("\n"); +*/ + for (i = 1; i < nw -1; i++) + if (i > 2 && i < nw - 3 && cnt[i] % 2) + *hyp++ = start + i - 1; + return hyp - hyptr; /* non-zero if a hyphen was found */ +} + +/* + This code assumes that hyphen.tex looks like + % some comments + \patterns{ % more comments + pat5ter4ns, 1 per line, SORTED, nothing else + } + more goo + \hyphenation{ % more comments + ex-cep-tions, one per line; i ignore this part for now + } + + this code is NOT robust against variations. unfortunately, + it looks like every local language version of this file has + a different format. i have also made no provision for weird + characters. sigh. +*/ + +static int readpats(void) +{ + FILE *fp; + char buf[200], buf1[200]; + + if ((fp = fopen(unsharp(TEXHYPHENS), "r")) == NULL + && (fp = fopen(unsharp(DWBalthyphens), "r")) == NULL) { + ERROR "warning: can't find hyphen.tex" WARN; + return 0; + } + + while (fgets(buf, sizeof buf, fp) != NULL) { + sscanf(buf, "%s", buf1); + if (strcmp(buf1, "\\patterns{") == 0) + break; + } + while (fgets(buf, sizeof buf, fp) != NULL) { + if (buf[0] == '}') + break; + install(buf); + } + fclose(fp); + fixup(); + return 1; +} + +static void install(char *s) /* map ab4c5de to: 12 abcde \0 00405 \0 */ +{ + int npat, lastpat; + char num[500], *onextpat = nextpat; + + num[0] = '0'; + *nextpat++ = ' '; /* fill in with count later */ + for (npat = lastpat = 0; *s != '\n' && *s != '\0'; s++) { + if (isdigit(*s)) { + num[npat] = *s; + lastpat = npat; + } else { + *nextpat++ = *s; + npat++; + num[npat] = '0'; + } + } + *nextpat++ = 0; + if (nextpat > pats + sizeof(pats)-20) { + ERROR "tex hyphenation table overflow, tail end ignored" WARN; + nextpat = onextpat; + } + num[lastpat+1] = 0; + strcat(nextpat, num); + nextpat += strlen(nextpat) + 1; +} + +static void fixup(void) /* build indexes of where . a b c ... start */ +{ + char *p, *lastc; + int n; + + for (lastc = pats, p = pats+1; p < nextpat; p++) + if (*p == ' ') { + *lastc = p - lastc; + lastc = p; + } + *lastc = p - lastc; + for (p = pats+1; p < nextpat; ) { + n = trieindex(p[0], p[1]); + if (trie[n] == 0) + trie[n] = p; + p += p[-1]; + } + /* printf("pats = %d\n", nextpat - pats); */ +} + +static int trieindex(int d1, int d2) +{ + return 27 * (d1 == '.' ? 0 : d1 - 'a' + 1) + (d2 == '.' ? 0 : d2 - 'a' + 1); +} diff --git a/src/cmd/troff/n9.c b/src/cmd/troff/n9.c new file mode 100644 index 00000000..5cd70648 --- /dev/null +++ b/src/cmd/troff/n9.c @@ -0,0 +1,488 @@ +#include "tdef.h" +#include "ext.h" +#include "fns.h" + +/* + * troff9.c + * + * misc functions + */ + +Tchar setz(void) +{ + Tchar i; + + if (!ismot(i = getch())) + i |= ZBIT; + return(i); +} + +void setline(void) +{ + Tchar *i; + Tchar c; + int length; + int j, w, cnt, delim, rem, temp; + Tchar linebuf[NC]; + + if (ismot(c = getch())) + return; + delim = cbits(c); + vflag = 0; + dfact = EM; + length = quant(atoi0(), HOR); + dfact = 1; + if (!length) { + eat(delim); + return; + } +s0: + if ((j = cbits(c = getch())) == delim || j == '\n') { + ch = c; + c = RULE | chbits; + } else if (cbits(c) == FILLER) + goto s0; + w = width(c); + if (w <= 0) { + ERROR "zero-width underline character ignored" WARN; + c = RULE | chbits; + w = width(c); + } + i = linebuf; + if (length < 0) { + *i++ = makem(length); + length = -length; + } + if (!(cnt = length / w)) { + *i++ = makem(-(temp = ((w - length) / 2))); + *i++ = c; + *i++ = makem(-(w - length - temp)); + goto s1; + } + if (rem = length % w) { + if (cbits(c) == RULE || cbits(c) == UNDERLINE || cbits(c) == ROOTEN) + *i++ = c | ZBIT; + *i++ = makem(rem); + } + if (cnt) { + *i++ = RPT; + *i++ = cnt; + *i++ = c; + } +s1: + *i = 0; + eat(delim); + pushback(linebuf); +} + + +eat(int c) +{ + int i; + + while ((i = cbits(getch())) != c && i != '\n') + ; + return(i); +} + + +void setov(void) +{ + int j, k; + Tchar i, o[NOV+1]; + int delim, w[NOV+1]; + + if (ismot(i = getch())) + return; + delim = cbits(i); + for (k = 0; k < NOV && (j = cbits(i = getch())) != delim && j != '\n'; k++) { + o[k] = i; + w[k] = width(i); + } + o[k] = w[k] = 0; + if (o[0]) + for (j = 1; j; ) { + j = 0; + for (k = 1; o[k] ; k++) { + if (w[k-1] < w[k]) { + j++; + i = w[k]; + w[k] = w[k-1]; + w[k-1] = i; + i = o[k]; + o[k] = o[k-1]; + o[k-1] = i; + } + } + } + else + return; + *pbp++ = makem(w[0] / 2); + for (k = 0; o[k]; k++) + ; + while (k>0) { + k--; + *pbp++ = makem(-((w[k] + w[k+1]) / 2)); + *pbp++ = o[k]; + } +} + + +void setbra(void) +{ + int k; + Tchar i, *j, dwn; + int cnt, delim; + Tchar brabuf[NC]; + + if (ismot(i = getch())) + return; + delim = cbits(i); + j = brabuf + 1; + cnt = 0; + if (NROFF) + dwn = (2 * t.Halfline) | MOT | VMOT; + else + dwn = EM | MOT | VMOT; + while ((k = cbits(i = getch())) != delim && k != '\n' && j <= brabuf + NC - 4) { + *j++ = i | ZBIT; + *j++ = dwn; + cnt++; + } + if (--cnt < 0) + return; + else if (!cnt) { + ch = *(j - 2); + return; + } + *j = 0; + if (NROFF) + *--j = *brabuf = (cnt * t.Halfline) | MOT | NMOT | VMOT; + else + *--j = *brabuf = (cnt * EM) / 2 | MOT | NMOT | VMOT; + *--j &= ~ZBIT; + pushback(brabuf); +} + + +void setvline(void) +{ + int i; + Tchar c, rem, ver, neg; + int cnt, delim, v; + Tchar vlbuf[NC]; + Tchar *vlp; + + if (ismot(c = getch())) + return; + delim = cbits(c); + dfact = lss; + vflag++; + i = quant(atoi0(), VERT); + dfact = 1; + if (!i) { + eat(delim); + vflag = 0; + return; + } + if ((cbits(c = getch())) == delim) { + c = BOXRULE | chbits; /*default box rule*/ + } else + getch(); + c |= ZBIT; + neg = 0; + if (i < 0) { + i = -i; + neg = NMOT; + } + if (NROFF) + v = 2 * t.Halfline; + else { + v = EM; + if (v < VERT) /* ATT EVK hack: Erik van Konijnenburg, */ + v = VERT; /* hvlpb!evkonij, ATT NSI Hilversum, Holland */ + } + + cnt = i / v; + rem = makem(i % v) | neg; + ver = makem(v) | neg; + vlp = vlbuf; + if (!neg) + *vlp++ = ver; + if (absmot(rem) != 0) { + *vlp++ = c; + *vlp++ = rem; + } + while (vlp < vlbuf + NC - 3 && cnt--) { + *vlp++ = c; + *vlp++ = ver; + } + *(vlp - 2) &= ~ZBIT; + if (!neg) + vlp--; + *vlp = 0; + pushback(vlbuf); + vflag = 0; +} + +#define NPAIR (NC/2-6) /* max pairs in spline, etc. */ + +void setdraw(void) /* generate internal cookies for a drawing function */ +{ + int i, j, k, dx[NPAIR], dy[NPAIR], delim, type; + Tchar c, drawbuf[NC]; + int drawch = '.'; /* character to draw with */ + + /* input is \D'f dx dy dx dy ... c' (or at least it had better be) */ + /* this does drawing function f with character c and the */ + /* specified dx,dy pairs interpreted as appropriate */ + /* pairs are deltas from last point, except for radii */ + + /* l dx dy: line from here by dx,dy */ + /* c x: circle of diameter x, left side here */ + /* e x y: ellipse of diameters x,y, left side here */ + /* a dx1 dy1 dx2 dy2: + ccw arc: ctr at dx1,dy1, then end at dx2,dy2 from there */ + /* ~ dx1 dy1 dx2 dy2...: + spline to dx1,dy1 to dx2,dy2 ... */ + /* b x c: + built-up character of type c, ht x */ + /* f dx dy ...: f is any other char: like spline */ + + if (ismot(c = getch())) + return; + delim = cbits(c); + numerr.escarg = type = cbits(getch()); + if (type == '~') /* head off the .tr ~ problem */ + type = 's'; + for (i = 0; i < NPAIR ; i++) { + skip(); + vflag = 0; + dfact = EM; + dx[i] = quant(atoi0(), HOR); + if (dx[i] > MAXMOT) + dx[i] = MAXMOT; + else if (dx[i] < -MAXMOT) + dx[i] = -MAXMOT; + skip(); + if (type == 'c') { + dy[i] = 0; + goto eat; + } + vflag = 1; + dfact = lss; + dy[i] = quant(atoi0(), VERT); + if (dy[i] > MAXMOT) + dy[i] = MAXMOT; + else if (dy[i] < -MAXMOT) + dy[i] = -MAXMOT; +eat: + if (cbits(c = getch()) != ' ') { /* must be the end */ + if (cbits(c) != delim) { + drawch = cbits(c); + getch(); + } + i++; + break; + } + } + dfact = 1; + vflag = 0; + if (TROFF) { + drawbuf[0] = DRAWFCN | chbits | ZBIT; + drawbuf[1] = type | chbits | ZBIT; + drawbuf[2] = drawch | chbits | ZBIT; + for (k = 0, j = 3; k < i; k++) { + drawbuf[j++] = MOT | ((dx[k] >= 0) ? dx[k] : (NMOT | -dx[k])); + drawbuf[j++] = MOT | VMOT | ((dy[k] >= 0) ? dy[k] : (NMOT | -dy[k])); + } + if (type == DRAWELLIPSE) { + drawbuf[5] = drawbuf[4] | NMOT; /* so the net vertical is zero */ + j = 6; + } else if (type == DRAWBUILD) { + drawbuf[4] = drawbuf[3] | NMOT; /* net horizontal motion is zero */ + drawbuf[2] &= ~ZBIT; /* width taken from drawing char */ + j = 5; + } + drawbuf[j++] = DRAWFCN | chbits | ZBIT; /* marks end for ptout */ + drawbuf[j] = 0; + pushback(drawbuf); + } +} + + +void casefc(void) +{ + int i; + Tchar j; + + gchtab[fc] &= ~FCBIT; + fc = IMP; + padc = ' '; + if (skip() || ismot(j = getch()) || (i = cbits(j)) == '\n') + return; + fc = i; + gchtab[fc] |= FCBIT; + if (skip() || ismot(ch) || (ch = cbits(ch)) == fc) + return; + padc = ch; +} + + +Tchar setfield(int x) +{ + Tchar ii, jj, *fp; + int i, j; + int length, ws, npad, temp, type; + Tchar **pp, *padptr[NPP]; + Tchar fbuf[FBUFSZ]; + int savfc, savtc, savlc; + Tchar rchar; + int savepos; + static Tchar wbuf[] = { WORDSP, 0}; + + if (x == tabch) + rchar = tabc | chbits; + else if (x == ldrch) + rchar = dotc | chbits; + temp = npad = ws = 0; + savfc = fc; + savtc = tabch; + savlc = ldrch; + tabch = ldrch = fc = IMP; + savepos = numtabp[HP].val; + gchtab[tabch] &= ~TABBIT; + gchtab[ldrch] &= ~LDRBIT; + gchtab[fc] &= ~FCBIT; + gchtab[IMP] |= TABBIT|LDRBIT|FCBIT; + for (j = 0; ; j++) { + if ((tabtab[j] & TABMASK) == 0) { + if (x == savfc) + ERROR "zero field width." WARN; + jj = 0; + goto rtn; + } + if ((length = ((tabtab[j] & TABMASK) - numtabp[HP].val)) > 0 ) + break; + } + type = tabtab[j] & ~TABMASK; + fp = fbuf; + pp = padptr; + if (x == savfc) { + while (1) { + j = cbits(ii = getch()); + jj = width(ii); + widthp = jj; + numtabp[HP].val += jj; + if (j == padc) { + npad++; + *pp++ = fp; + if (pp > padptr + NPP - 1) + break; + goto s1; + } else if (j == savfc) + break; + else if (j == '\n') { + temp = j; + if (nlflg && ip == 0) { + numtabp[CD].val--; + nlflg = 0; + } + break; + } + ws += jj; +s1: + *fp++ = ii; + if (fp > fbuf + FBUFSZ - 3) + break; + } + if (ws) + *fp++ = WORDSP; + if (!npad) { + npad++; + *pp++ = fp; + *fp++ = 0; + } + *fp++ = temp; + *fp = 0; + temp = i = (j = length - ws) / npad; + i = (i / HOR) * HOR; + if ((j -= i * npad) < 0) + j = -j; + ii = makem(i); + if (temp < 0) + ii |= NMOT; + for (; npad > 0; npad--) { + *(*--pp) = ii; + if (j) { + j -= HOR; + (*(*pp)) += HOR; + } + } + pushback(fbuf); + jj = 0; + } else if (type == 0) { + /*plain tab or leader*/ + if ((j = width(rchar)) > 0) { + int nchar = length / j; + while (nchar-->0 && pbp < &pbbuf[NC-3]) { + numtabp[HP].val += j; + widthp = j; + *pbp++ = rchar; + } + length %= j; + } + if (length) + jj = length | MOT; + else + jj = getch0(); + if (savepos > 0) + pushback(wbuf); + } else { + /*center tab*/ + /*right tab*/ + while ((j = cbits(ii = getch())) != savtc && j != '\n' && j != savlc) { + jj = width(ii); + ws += jj; + numtabp[HP].val += jj; + widthp = jj; + *fp++ = ii; + if (fp > fbuf + FBUFSZ - 3) + break; + } + *fp++ = ii; + *fp = 0; + if (type == RTAB) + length -= ws; + else + length -= ws / 2; /*CTAB*/ + pushback(fbuf); + if ((j = width(rchar)) != 0 && length > 0) { + int nchar = length / j; + while (nchar-- > 0 && pbp < &pbbuf[NC-3]) + *pbp++ = rchar; + length %= j; + } + if (savepos > 0) + pushback(wbuf); + length = (length / HOR) * HOR; + jj = makem(length); + if (nlflg) { + if (ip == 0) + numtabp[CD].val--; + nlflg = 0; + } + } +rtn: + gchtab[fc] &= ~FCBIT; + gchtab[tabch] &= ~TABBIT; + gchtab[ldrch] &= ~LDRBIT; + fc = savfc; + tabch = savtc; + ldrch = savlc; + gchtab[fc] |= FCBIT; + gchtab[tabch] = TABBIT; + gchtab[ldrch] |= LDRBIT; + numtabp[HP].val = savepos; + return(jj); +} diff --git a/src/cmd/troff/ni.c b/src/cmd/troff/ni.c new file mode 100644 index 00000000..a80cec64 --- /dev/null +++ b/src/cmd/troff/ni.c @@ -0,0 +1,390 @@ +#include <stdio.h> +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +char termtab[NS]; /* term type added in ptinit() */ +char fontdir[NS]; /* added in casefp; not used by nroff */ +char devname[20]; /* default output device */ + +Numtab numtab[NN] = { + { PAIR('%', 0) }, + { PAIR('n', 'l') }, + { PAIR('y', 'r') }, + { PAIR('h', 'p') }, + { PAIR('c', 't') }, + { PAIR('d', 'n') }, + { PAIR('m', 'o') }, + { PAIR('d', 'y') }, + { PAIR('d', 'w') }, + { PAIR('l', 'n') }, + { PAIR('d', 'l') }, + { PAIR('s', 't') }, + { PAIR('s', 'b') }, + { PAIR('c', '.') }, + { PAIR('$', '$') }, +}; + + +int alphabet = 256; /* latin-1 */ +int pto = 10000; +int pfrom = 1; +int print = 1; +char nextf[NS] = TMACDIR; +char mfiles[NMF][NS]; +int nmfi = 0; +int oldbits = -1; +int init = 1; +int fc = IMP; /* field character */ +int eschar = '\\'; +int pl; +int po; +FILE *ptid; + +int dfact = 1; +int dfactd = 1; +int res = 1; +int smnt = 0; /* beginning of special fonts */ +int ascii = 0; /* ascii normally off for troff, on for nroff; -a turns on */ +int lg; +int pnlist[NPN] = { -1 }; + + +int *pnp = pnlist; +int npn = 1; +int npnflg = 1; +int dpn = -1; +int totout = 1; +int ulfont = ULFONT; +int tabch = TAB; +int ldrch = LEADER; + + +Contab contab[NM] = { + C(PAIR('d', 's'), caseds), + C(PAIR('a', 's'), caseas), + C(PAIR('s', 'p'), casesp), + C(PAIR('f', 't'), caseft), + C(PAIR('p', 's'), caseps), + C(PAIR('v', 's'), casevs), + C(PAIR('n', 'r'), casenr), + C(PAIR('i', 'f'), caseif), + C(PAIR('i', 'e'), caseie), + C(PAIR('e', 'l'), caseel), + C(PAIR('p', 'o'), casepo), + C(PAIR('t', 'l'), casetl), + C(PAIR('t', 'm'), casetm), + C(PAIR('f', 'm'), casefm), + C(PAIR('b', 'p'), casebp), + C(PAIR('c', 'h'), casech), + C(PAIR('p', 'n'), casepn), + C(PAIR('b', 'r'), tbreak), + C(PAIR('t', 'i'), caseti), + C(PAIR('n', 'e'), casene), + C(PAIR('n', 'f'), casenf), + C(PAIR('c', 'e'), casece), + C(PAIR('f', 'i'), casefi), + C(PAIR('i', 'n'), casein), + C(PAIR('l', 'l'), casell), + C(PAIR('n', 's'), casens), + C(PAIR('m', 'k'), casemk), + C(PAIR('r', 't'), casert), + C(PAIR('a', 'm'), caseam), + C(PAIR('d', 'e'), casede), + C(PAIR('d', 'i'), casedi), + C(PAIR('d', 'a'), caseda), + C(PAIR('w', 'h'), casewh), + C(PAIR('d', 't'), casedt), + C(PAIR('i', 't'), caseit), + C(PAIR('r', 'm'), caserm), + C(PAIR('r', 'r'), caserr), + C(PAIR('r', 'n'), casern), + C(PAIR('a', 'd'), casead), + C(PAIR('r', 's'), casers), + C(PAIR('n', 'a'), casena), + C(PAIR('p', 'l'), casepl), + C(PAIR('t', 'a'), caseta), + C(PAIR('t', 'r'), casetr), + C(PAIR('u', 'l'), caseul), + C(PAIR('c', 'u'), casecu), + C(PAIR('l', 't'), caselt), + C(PAIR('n', 'x'), casenx), + C(PAIR('s', 'o'), caseso), + C(PAIR('i', 'g'), caseig), + C(PAIR('t', 'c'), casetc), + C(PAIR('f', 'c'), casefc), + C(PAIR('e', 'c'), caseec), + C(PAIR('e', 'o'), caseeo), + C(PAIR('l', 'c'), caselc), + C(PAIR('e', 'v'), caseev), + C(PAIR('r', 'd'), caserd), + C(PAIR('a', 'b'), caseab), + C(PAIR('f', 'l'), casefl), + C(PAIR('e', 'x'), caseex), + C(PAIR('s', 's'), casess), + C(PAIR('f', 'p'), casefp), + C(PAIR('c', 's'), casecs), + C(PAIR('b', 'd'), casebd), + C(PAIR('l', 'g'), caselg), + C(PAIR('h', 'c'), casehc), + C(PAIR('h', 'y'), casehy), + C(PAIR('n', 'h'), casenh), + C(PAIR('n', 'm'), casenm), + C(PAIR('n', 'n'), casenn), + C(PAIR('s', 'v'), casesv), + C(PAIR('o', 's'), caseos), + C(PAIR('l', 's'), casels), + C(PAIR('c', 'c'), casecc), + C(PAIR('c', '2'), casec2), + C(PAIR('e', 'm'), caseem), + C(PAIR('a', 'f'), caseaf), + C(PAIR('h', 'a'), caseha), + C(PAIR('h', 'w'), casehw), + C(PAIR('m', 'c'), casemc), + C(PAIR('p', 'm'), casepm), + C(PAIR('p', 'i'), casepi), + C(PAIR('u', 'f'), caseuf), + C(PAIR('p', 'c'), casepc), + C(PAIR('h', 't'), caseht), + C(PAIR('c', 'f'), casecf), + C(PAIR('s', 'y'), casesy), + C(PAIR('l', 'f'), caself), + C(PAIR('p', 't'), casept), + C(PAIR('g', 'd'), casegd), +}; + + +Tbuf _oline; + +/* + * troff environment block + */ + +Env env[NEV] = { { /* this sets up env[0] */ +/* int ics */ 0, /* insertion character space, set by .mc */ +/* int sps */ 0, +/* int spacesz */ 0, +/* int lss */ 0, +/* int lss1 */ 0, +/* int ll */ 0, +/* int ll1 */ 0, +/* int lt */ 0, +/* int lt1 */ 0, +/* Tchar ic */ 0, /* insertion character (= margin character) */ +/* int icf */ 0, /* insertion character flag */ +/* Tchar chbits */ 0, /* size+font bits for current character */ +/* Tchar spbits */ 0, +/* Tchar nmbits */ 0, /* size+font bits for number from .nm */ +/* int apts */ PS, /* actual point size -- as requested by user */ +/* int apts1 */ PS, /* need not match an existent size */ +/* int pts */ PS, /* hence, this is the size that really exists */ +/* int pts1 */ PS, +/* int font */ FT, +/* int font1 */ FT, +/* int ls */ 1, +/* int ls1 */ 1, +/* int ad */ 1, +/* int nms */ 1, /* .nm multiplier */ +/* int ndf */ 1, /* .nm separator */ +/* int nmwid */ 3, /* max width of .nm numbers */ +/* int fi */ 1, +/* int cc */ '.', +/* int c2 */ '\'', +/* int ohc */ OHC, +/* int tdelim */ IMP, +/* int hyf */ 1, +/* int hyoff */ 0, +/* int hyphalg */ HYPHALG, +/* int un1 */ -1, +/* int tabc */ 0, +/* int dotc */ '.', +/* int adsp */ 0, /* add this much space to each padding point */ +/* int adrem */ 0, /* excess space to add until it runs out */ +/* int lastl */ 0, /* last text on current output line */ +/* int nel */ 0, /* how much space left on current output line */ +/* int admod */ 0, /* adjust mode */ +/* Tchar *wordp */ 0, +/* int spflg */ 0, /* probably to indicate space after punctuation needed */ +/* Tchar *linep */ 0, +/* Tchar *wdend */ 0, +/* Tchar *wdstart */ 0, +/* int wne */ 0, +/* int ne */ 0, /* how much space taken on current output line */ +/* int nc */ 0, /* #characters (incl blank) on output line */ +/* int nb */ 0, +/* int lnmod */ 0, /* line number mode, set by .nm */ +/* int nwd */ 0, /* number of words on current output line */ +/* int nn */ 0, /* from .nn command */ +/* int ni */ 0, /* indent of .nm numbers, probably */ +/* int ul */ 0, +/* int cu */ 0, +/* int ce */ 0, +/* int in */ 0, /* indent and previous value */ +/* int in1 */ 0, +/* int un */ 0, /* unindent of left margin in some way */ +/* int wch */ 0, +/* int pendt */ 0, +/* Tchar *pendw */ (Tchar *)0, +/* int pendnf */ 0, +/* int spread */ 0, +/* int it */ 0, /* input trap count */ +/* int itmac */ 0, +} }; + +Env *envp = env; /* start off in env 0 */ + +Numerr numerr; + +Stack *frame, *stk, *ejl; +Stack *nxf; + +int pipeflg; +int hflg; /* used in nroff only */ +int eqflg; /* used in nroff only */ + +int xpts; +int ppts; +int pfont; +int mpts; +int mfont; +int cs; +int ccs; +int bd; + +int stdi; +int quiet; +int stop; +char ibuf[IBUFSZ]; +char xbuf[IBUFSZ]; +char *ibufp; +char *xbufp; +char *eibuf; +char *xeibuf; +Tchar pbbuf[NC]; /* pushback buffer for arguments, \n, etc. */ +Tchar *pbp = pbbuf; /* next free slot in pbbuf */ +Tchar *lastpbp = pbbuf; /* pbp in previous stack frame */ +int nx; +int mflg; +Tchar ch = 0; +int ibf; +int ifi; +int iflg; +int rargc; +char **argp; +Ushort trtab[NTRTAB]; +int lgf; +int copyf; +Offset ip; +int nlflg; +int donef; +int nflush; +int nfo; +int padc; +int raw; +int flss; +int nonumb; +int trap; +int tflg; +int ejf; +int dilev; +Offset offset; +int em; +int ds; +Offset woff; +int app; +int ndone; +int lead; +int ralss; +Offset nextb; +Tchar nrbits; +int nform; +int oldmn; +int newmn; +int macerr; +Offset apptr; +int diflg; +int evi; +int vflag; +int noscale; +int po1; +int nlist[NTRAP]; +int mlist[NTRAP]; +int evlist[EVLSZ]; +int ev; +int tty; +int sfont = FT; /* appears to be "standard" font; used by .ul */ +int sv; +int esc; +int widthp; +int xfont; +int setwdf; +int over; +int nhyp; +Tchar **hyp; +Tchar *olinep; +int dotT; +char *unlkp; +Wcache widcache[NWIDCACHE]; +Diver d[NDI]; +Diver *dip; + +int c_hyphen; +int c_emdash; +int c_rule; +int c_minus; +int c_fi; +int c_fl; +int c_ff; +int c_ffi; +int c_ffl; +int c_acute; +int c_grave; +int c_under; +int c_rooten; +int c_boxrule; +int c_lefthand; +int c_dagger; +int c_isalnum; + +Spnames spnames[] = +{ + &c_hyphen, "hy", + &c_emdash, "em", + &c_rule, "ru", + &c_minus, "\\-", + &c_fi, "fi", + &c_fl, "fl", + &c_ff, "ff", + &c_ffi, "Fi", + &c_ffl, "Fl", + &c_acute, "aa", + &c_grave, "ga", + &c_under, "ul", + &c_rooten, "rn", + &c_boxrule, "br", + &c_lefthand, "lh", + &c_dagger, "dg", /* not in nroff?? */ + &c_isalnum, "__", + 0, 0 +}; + + +Tchar (*hmot)(void); +Tchar (*makem)(int i); +Tchar (*setabs)(void); +Tchar (*setch)(int c); +Tchar (*sethl)(int k); +Tchar (*setht)(void); +Tchar (*setslant)(void); +Tchar (*vmot)(void); +Tchar (*xlss)(void); +int (*findft)(int i); +int (*width)(Tchar j); +void (*mchbits)(void); +void (*ptlead)(void); +void (*ptout)(Tchar i); +void (*ptpause)(void); +void (*setfont)(int a); +void (*setps)(void); +void (*setwd)(void); + diff --git a/src/cmd/troff/suftab.c b/src/cmd/troff/suftab.c new file mode 100644 index 00000000..1aa8a009 --- /dev/null +++ b/src/cmd/troff/suftab.c @@ -0,0 +1,612 @@ +/* + * Suffix table + */ + +typedef unsigned char Uchar; + +static Uchar sufa[] = { + 02,0200+'t', /* -TA */ + 02,0200+'s', /* -SA */ + 03,0200+'t','r', /* -TRA */ + 03,0200+'d','r', /* -DRA */ + 03,0200+'b','r', /* -BRA */ + 02,0200+'p', /* -PA */ + 02,0200+'n', /* -NA */ + 02,0200+'m', /* -MA */ + 03,0200+'p','l', /* -PLA */ + 02,0200+'l', /* -LA */ + 02,0200+'k', /* -KA */ + 03,0200+'t','h', /* -THA */ + 03,0200+'s','h', /* -SHA */ + 02,0200+'g', /* -GA */ + 02,0200+'d', /* -DA */ + 02,0200+'c', /* -CA */ + 02,0200+'b', /* -BA */ + 00 +}; + +static Uchar sufc[] = { + 04,'e','t',0200+'i', /* ET-IC */ + 07,'a','l',0200+'i','s',0200+'t','i', /* AL-IS-TIC */ + 04,'s',0200+'t','i', /* S-TIC */ + 04,'p',0200+'t','i', /* P-TIC */ + 05,0200+'l','y','t',0200+'i', /* -LYT-IC */ + 04,'o','t',0200+'i', /* OT-IC */ + 05,'a','n',0200+'t','i', /* AN-TIC */ + 04,'n',0200+'t','i', /* N-TIC */ + 04,'c',0200+'t','i', /* C-TIC */ + 04,'a','t',0200+'i', /* AT-IC */ + 04,'h',0200+'n','i', /* H-NIC */ + 03,'n',0200+'i', /* N-IC */ + 03,'m',0200+'i', /* M-IC */ + 04,'l',0200+'l','i', /* L-LIC */ + 04,'b',0200+'l','i', /* B-LIC */ + 04,0200+'c','l','i', /* -CLIC */ + 03,'l',0200+'i', /* L-IC */ + 03,'h',0200+'i', /* H-IC */ + 03,'f',0200+'i', /* F-IC */ + 03,'d',0200+'i', /* D-IC */ + 03,0200+'b','i', /* -BIC */ + 03,'a',0200+'i', /* A-IC */ + 03,0200+'m','a', /* -MAC */ + 03,'i',0200+'a', /* I-AC */ + 00 +}; + +static Uchar sufd[] = { + 04,0200+'w','o','r', /* -WORD */ + 04,0200+'l','o','r', /* -LORD */ + 04,0200+'f','o','r', /* -FORD */ + 04,0200+'y','a','r', /* -YARD */ + 04,0200+'w','a','r', /* -WARD */ + 05,0200+'g','u','a','r', /* -GUARD */ + 04,0200+'t','a','r', /* -TARD */ + 05,0200+'b','o','a','r', /* -BOARD */ + 04,0200+'n','a','r', /* -NARD */ + 05,0200+'l','i','a','r', /* -LIARD */ + 04,0200+'i','a','r', /* -IARD */ + 04,0200+'g','a','r', /* -GARD */ + 04,0200+'b','a','r', /* -BARD */ + 03,0200+'r','o', /* -ROD */ + 04,0200+'w','o','o', /* -WOOD */ + 04,0200+'h','o','o', /* -HOOD */ + 04,0200+'m','o','n', /* -MOND */ + 04,0200+'t','e','n', /* -TEND */ + 05,0200+'s','t','a','n', /* -STAND */ + 04,0200+'l','a','n', /* -LAND */ + 04,0200+'h','a','n', /* -HAND */ + 04,0200+'h','o','l', /* -HOLD */ + 04,0200+'f','o','l', /* -FOLD */ + 05,0200+'f','i','e','l', /* -FIELD */ + 03,0200+'v','i', /* -VID */ + 03,0200+'c','i', /* -CID */ + 04,0200+'s','a','i', /* -SAID */ + 04,0200+'m','a','i', /* -MAID */ + 04,'t',0200+'t','e', /* T-TED */ + 03,'t',0200+'e', /* T-ED */ + 04,0200+'d','r','e', /* -DRED */ + 04,0200+'c','r','e', /* -CRED */ + 04,0200+'b','r','e', /* -BRED */ + 05,'v',0200+'e','l','e', /* V-ELED */ + 0100+04,'a','l',0200+'e', /* AL/ED */ + 0140+03,0200+'e','e', /* /EED */ + 040+05,'e','d',0200+'d','e', /* ED-DED */ + 04,'d',0200+'d','e', /* D-DED */ + 040+04,'e','d',0200+'e', /* ED-ED */ + 03,'d',0200+'e', /* D-ED */ + 05,0200+'d','u','c','e', /* -DUCED */ + 0300+02,'e', /* E/D */ + 05,0200+'s','t','e','a', /* -STEAD */ + 05,0200+'a','h','e','a', /* -AHEAD */ + 04,0200+'h','e','a', /* -HEAD */ + 00 +}; + +static Uchar sufe[] = { + 05,'a','r',0200+'i','z', /* AR-IZE */ + 05,'a','n',0200+'i','z', /* AN-IZE */ + 05,'a','l',0200+'i','z', /* AL-IZE */ + 06,0200+'a','r','d',0200+'i','z', /* -ARD-IZE */ + 05,0200+'s','e','l','v', /* -SELVE */ + 05,0200+'k','n','i','v', /* -KNIVE */ + 05,0200+'l','i','e','v', /* -LIEVE */ + 0100+03,0200+'q','u', /* /QUE */ + 07,'o','n',0200+'t','i','n',0200+'u', /* ON-TIN-UE */ + 03,0200+'n','u', /* -NUE */ + 03,0200+'d','u', /* -DUE */ + 0300+02,'u', /* U/E */ + 0300+05,'q','u','a','t', /* QUAT/E */ + 04,'u',0200+'a','t', /* U-ATE */ + 05,0200+'s','t','a','t', /* -STATE */ + 04,0200+'t','a','t', /* -TATE */ + 06,0200+'t','o','r',0200+'a','t', /* -TOR-ATE */ + 05,'e','n',0200+'a','t', /* EN-ATE */ + 04,0200+'m','a','t', /* -MATE */ + 05,0200+'h','o','u','s', /* -HOUSE */ + 05,0200+'c','l','o','s', /* -CLOSE */ + 04,'i',0200+'o','s', /* I-OSE */ + 04,0200+'w','i','s', /* -WISE */ + 05,'a','s',0200+'u','r', /* AS-URE */ + 040+04,0200+'s','u','r', /* -SURE */ + 06,0200+'f','i','g',0200+'u','r', /* -FIG-URE */ + 040+03,0200+'t','r', /* -TRE */ + 05,0200+'s','t','o','r', /* -STORE */ + 04,0200+'f','o','r', /* -FORE */ + 05,0200+'w','h','e','r', /* -WHERE */ + 06,0200+'s','p','h','e','r', /* -SPHERE */ + 03,0200+'d','r', /* -DRE */ + 03,0200+'c','r', /* -CRE */ + 03,0200+'b','r', /* -BRE */ + 05,0200+'s','c','o','p', /* -SCOPE */ + 04,'y',0200+'o','n', /* Y-ONE */ + 05,0200+'s','t','o','n', /* -STONE */ + 05,0200+'p','h','o','n', /* -PHONE */ + 04,0200+'g','o','n', /* -GONE */ + 04,'e',0200+'o','n', /* E-ONE */ + 040+04,0200+'e','n','n', /* -ENNE */ + 040+05,'a',0200+'r','i','n', /* A-RINE */ + 05,0200+'c','l','i','n', /* -CLINE */ + 04,0200+'l','i','n', /* -LINE */ + 007,00200+'r','o','u',00200+'t','i','n', /*-ROU-TINE */ + 04,0200+'s','o','m', /* -SOME */ + 04,0200+'c','o','m', /* -COME */ + 04,0200+'t','i','m', /* -TIME */ + 03,0200+'z','l', /* -ZLE */ + 03,0200+'t','l', /* -TLE */ + 03,0200+'s','l', /* -SLE */ + 03,0200+'p','l', /* -PLE */ + 05,0200+'v','i','l','l', /* -VILLE */ + 04,'c','k',0200+'l', /* CK-LE */ + 03,0200+'k','l', /* -KLE */ + 03,0200+'g','l', /* -GLE */ + 03,0200+'f','l', /* -FLE */ + 03,0200+'d','l', /* -DLE */ + 03,0200+'c','l', /* -CLE */ + 05,0200+'p','a',0200+'b','l', /* -PA-BLE */ + 05,'f','a',0200+'b','l', /* FA-BLE */ + 05,0200+'c','a',0200+'b','l', /* -CA-BLE */ + 06,0200+'s','t','a','b','l', /* -STABLE */ + 04,0200+'a','b','l', /* -ABLE */ + 03,0200+'b','l', /* -BLE */ + 04,0200+'d','a','l', /* -DALE */ + 04,0200+'m','a','l', /* -MALE */ + 04,0200+'s','a','l', /* -SALE */ + 04,0200+'l','i','k', /* -LIKE */ + 0340+05,'g',0200+'u','a','g', /* -G/UAGE */ + 05,0200+'r','i','a','g', /* -RIAGE */ + 05,'e','r',0200+'a','g', /* ER-AGE */ + 04,'m',0200+'a','g', /* M-AGE */ + 04,'k',0200+'a','g', /* K-AGE */ + 04,'d',0200+'a','g', /* D-AGE */ + 04,0200+'w','i','f', /* -WIFE */ + 05,0200+'k','n','i','f', /* -KNIFE */ + 03,0200+'s','e', /* -SEE */ + 04,0200+'f','r','e', /* -FREE */ + 0340+02,'e', /* EE */ + 04,0200+'w','i','d', /* -WIDE */ + 04,0200+'t','i','d', /* -TIDE */ + 04,0200+'s','i','d', /* -SIDE */ + 06,0200+'q','u','e','n','c', /* -QUENCE */ + 07,0200+'f','l','u',0200+'e','n','c', /* -FLU-ENCE */ + 040+06,'e','s',0200+'e','n','c', /* ES-ENCE */ + 06,'e','r',0200+'e','n','c', /* ER-ENCE */ + 05,'i',0200+'e','n','c', /* I-ENCE */ + 040+05,0200+'s','a','n','c', /* -SANCE */ + 06,'e','r',0200+'a','n','c', /* ER-ANCE */ + 06,'a','r',0200+'a','n','c', /* AR-ANCE */ + 05,0200+'n','a','n','c', /* -NANCE */ + 07,0200+'b','a','l',0200+'a','n','c', /* -BAL-ANCE */ + 05,'i',0200+'a','n','c', /* I-ANCE */ + 07,0200+'j','u','s',0200+'t','i','c', /* -JUS-TICE */ + 05,0200+'s','t','i','c', /* -STICE */ + 06,0200+'n','o','v',0200+'i','c', /* NOV-ICE */ + 04,0200+'v','i','c', /* -VICE */ + 05,0200+'p','i','e','c', /* -PIECE */ + 05,0200+'p','l','a','c', /* -PLACE */ + 0340+01, /* /E */ + 00 +}; + +static Uchar suff[] = { + 03,0200+'o','f', /* -OFF */ + 05,0200+'p','r','o','o', /* -PROOF */ + 04,0200+'s','e','l', /* -SELF */ + 03,0200+'r','i', /* -RIF */ + 040+04,0200+'l','i','e', /* -LIEF */ + 00 +}; + +static Uchar sufg[] = { + 03,0200+'l','o', /* -LOG */ + 04,0200+'l','o','n', /* -LONG */ + 05,'t',0200+'t','i','n', /* T-TING */ + 06,0200+'s','t','r','i','n', /* -STRING */ + 05,'r',0200+'r','i','n', /* R-RING */ + 05,'p',0200+'p','i','n', /* P-PING */ + 05,'n',0200+'n','i','n', /* N-NING */ + 05,'m',0200+'m','i','n', /* M-MING */ + 05,'l',0200+'l','i','n', /* L-LING */ + 05,0200+'z','l','i','n', /* -ZLING */ + 05,0200+'t','l','i','n', /* -TLING */ + 040+05,'s',0200+'l','i','n', /* S-LING */ + 05,'r',0200+'l','i','n', /* R-LING */ + 05,0200+'p','l','i','n', /* -PLING */ + 06,'n',0200+'k','l','i','n', /* N-KLING */ + 05,'k',0200+'l','i','n', /* K-LING */ + 05,0200+'g','l','i','n', /* -GLING */ + 05,0200+'f','l','i','n', /* -FLING */ + 05,0200+'d','l','i','n', /* -DLING */ + 05,0200+'c','l','i','n', /* -CLING */ + 05,0200+'b','l','i','n', /* -BLING */ + 06,'y',0200+'t','h','i','n', /* Y-THING */ + 07,'e','e','t','h',0200+'i','n', /* EETH-ING */ + 06,'e',0200+'t','h','i','n', /* E-THING */ + 05,'g',0200+'g','i','n', /* G-GING */ + 05,'d',0200+'d','i','n', /* D-DING */ + 05,'b',0200+'b','i','n', /* B-BING */ + 03,0200+'i','n', /* -ING */ + 00 +}; + +static Uchar sufh[] = { + 05,0200+'m','o','u','t', /* -MOUTH */ + 05,0200+'w','o','r','t', /* -WORTH */ + 04,0200+'w','i','t', /* -WITH */ + 05,'t',0200+'t','i','s', /* T-TISH */ + 05,'e',0200+'t','i','s', /* E-TISH */ + 05,'p',0200+'p','i','s', /* P-PISH */ + 05,'r',0200+'n','i','s', /* R-NISH */ + 05,'n',0200+'n','i','s', /* N-NISH */ + 05,0200+'p','l','i','s', /* -PLISH */ + 05,0200+'g','u','i','s', /* -GUISH */ + 05,0200+'g','l','i','s', /* -GLISH */ + 05,'b',0200+'l','i','s', /* B-LISH */ + 05,'g',0200+'g','i','s', /* G-GISH */ + 05,'d',0200+'d','i','s', /* D-DISH */ + 03,0200+'i','s', /* -ISH */ + 05,0200+'g','r','a','p', /* -GRAPH */ + 07,0200+'b','o','r',0200+'o','u','g', /* -BOR-OUGH */ + 05,0200+'b','u','r','g', /* -BURGH */ + 04,0200+'v','i','c', /* -VICH */ + 03,0200+'n','a', /* -NAH */ + 03,0200+'l','a', /* -LAH */ + 04,0200+'m','i',0200+'a', /* -MI-AH */ + 00 +}; + +static Uchar sufi[] = { + 03,0200+'t','r', /* -TRI */ + 03,0200+'c','h', /* -CHI */ + 0200+03,'i','f', /* IF-I */ + 0200+03,'e','d', /* ED-I */ + 05,0200+'a','s','c','i', /* -ASCII */ + 04,0200+'s','e','m', /* -SEMI */ + 00 +}; + +static Uchar sufk[] = { + 04,0200+'w','o','r', /* -WORK */ + 04,0200+'m','a','r', /* -MARK */ + 04,0200+'b','o','o', /* -BOOK */ + 04,0200+'w','a','l', /* -WALK */ + 05,0200+'c','r','a','c', /* -CRACK */ + 04,0200+'b','a','c', /* -BACK */ + 00 +}; + +static Uchar sufl[] = { + 03,0200+'f','u', /* -FUL */ + 05,'s',0200+'w','e','l', /* S-WELL */ + 04,0200+'t','e','l', /* -TELL */ + 05,0200+'s','h','e','l', /* -SHELL */ + 05,0200+'s','t','a','l', /* -STALL */ + 04,'s',0200+'t','a', /* S-TAL */ + 04,0200+'b','a','l', /* -BALL */ + 04,0200+'c','a','l', /* -CALL */ + 03,'v',0200+'e', /* V-EL */ + 03,'u',0200+'e', /* U-EL */ + 03,'k',0200+'e', /* K-EL */ + 04,'t','h',0200+'e', /* TH-EL */ + 05,'t','c','h',0200+'e', /* TCH-EL */ + 03,'a',0200+'e', /* A-EL */ + 0140+04,0200+'q','u','a', /* /QUAL */ + 040+03,'u',0200+'a', /* U-AL */ + 03,0200+'t','a', /* -TAL */ + 04,'u','r',0200+'a', /* UR-AL */ + 040+05,'g',0200+'o',0200+'n','a', /* G-O-NAL */ + 04,'o','n',0200+'a', /* ON-AL */ + 03,0200+'n','a', /* -NAL */ + 04,0200+'t','i','a', /* -TIAL */ + 04,0200+'s','i','a', /* -SIAL */ + 040+05,0200+'t','r','i',0200+'a', /* -TRI-AL */ + 04,'r','i',0200+'a', /* RI-AL */ + 04,0200+'n','i',0200+'a', /* -NI-AL */ + 04,0200+'d','i',0200+'a', /* -DI-AL */ + 04,0200+'c','i','a', /* -CIAL */ + 03,0200+'g','a', /* -GAL */ + 04,0200+'m','e','a', /* -MEAL */ +/* 040+04,0200+'r','e',0200+'a', /* -RE-AL */ + 040+04,0200+'r','e','a', /* -REAL */ + 06,'c',0200+'t','i',0200+'c','a', /* C-TI-CAL */ + 05,0200+'s','i',0200+'c','a', /* -SI-CAL */ + 04,0200+'i',0200+'c','a', /* -I-CAL */ + 03,0200+'c','a', /* -CAL */ + 03,0200+'b','a', /* -BAL */ + 06,0200+'n','o',0200+'m','i',0200+'a', /* -NO-MI-AL */ + 00 +}; + +static Uchar sufm[] = { + 03,0200+'n','u', /* -NUM */ + 05,'o',0200+'r','i',0200+'u', /* O-RI-UM */ + 040+03,'i',0200+'u', /* I-UM */ + 040+03,'e',0200+'u', /* E-UM */ + 05,'i','v',0200+'i','s', /* IV-ISM */ + 04,0200+'t','i','s', /* -TISM */ + 05,'i',0200+'m','i','s', /* I-MISM */ + 05,'a','l',0200+'i','s', /* AL-ISM */ + 040+04,'e',0200+'i','s', /* E-ISM */ + 040+04,'a',0200+'i','s', /* A-ISM */ + 04,0200+'r','o','o', /* -ROOM */ + 03,0200+'d','o', /* -DOM */ + 03,0200+'h','a', /* -HAM */ + 06,0200+'a',0200+'r','i','t','h', /* -A-RITHM */ + 05,0200+'r','i','t','h', /* -RITHM */ + 00 +}; + +static Uchar sufn[] = { + 05,0200+'k','n','o','w', /* -KNOWN */ + 04,0200+'t','o','w', /* -TOWN */ + 04,0200+'d','o','w', /* -DOWN */ + 04,0200+'t','u','r', /* -TURN */ + 05,0200+'s','p','o','o', /* -SPOON */ + 04,0200+'n','o','o', /* -NOON */ + 04,0200+'m','o','o', /* -MOON */ + 011,'a','l',0200+'i',0200+'z','a',0200+'t','i','o', /* AL-I-ZA-TION */ + 07,0200+'i',0200+'z','a',0200+'t','i','o', /* -I-ZA-TION */ + 07,'l',0200+'i',0200+'a',0200+'t','i','o', /* L-I-A-TION */ + 04,0200+'t','i','o', /* -TION */ + 040+05,'s',0200+'s','i','o', /* S-SION */ + 04,0200+'s','i','o', /* -SION */ + 04,'n',0200+'i','o', /* N-ION */ + 04,0200+'g','i','o', /* -GION */ + 04,0200+'c','i','o', /* -CION */ + 03,0200+'c','o', /* -CON */ + 05,0200+'c','o','l','o', /* -COLON */ + 03,0200+'t','o', /* -TON */ + 04,'i','s',0200+'o', /* IS-ON */ + 03,0200+'s','o', /* -SON */ + 03,0200+'r','i', /* -RIN */ + 03,0200+'p','i', /* -PIN */ + 03,0200+'n','i', /* -NIN */ + 03,0200+'m','i', /* -MIN */ + 03,0200+'l','i', /* -LIN */ + 03,0200+'k','i', /* -KIN */ + 05,0200+'s','t','e','i', /* -STEIN */ + 04,0200+'t','a','i', /* -TAIN */ + 05,'g','h','t',0200+'e', /* GHT-EN */ + 05,0200+'w','o','m',0200+'e', /* -WOM-EN */ + 03,0200+'m','e', /* -MEN */ + 04,'o',0200+'k','e', /* O-KEN */ + 03,'k',0200+'e', /* K-EN */ + 04,0200+'t','e','e', /* -TEEN */ + 04,0200+'s','e','e', /* -SEEN */ + 040+03,0200+'s','a', /* -SAN */ + 05,0200+'w','o','m',0200+'a', /* -WOM-AN */ + 03,0200+'m','a', /* -MAN */ + 04,0200+'t','i','a', /* -TIAN */ + 04,0200+'s','i','a', /* -SIAN */ + 040+04,'e',0200+'i','a', /* E-IAN */ + 04,0200+'c','i','a', /* -CIAN */ + 0300+03,'i','a', /* IA/N */ + 05,0200+'c','l','e','a', /* -CLEAN */ + 04,0200+'m','e','a', /* -MEAN */ + 040+03,'e',0200+'a', /* E-AN */ + 00 +}; + +static Uchar sufo[] = { + 05,0200+'m','a','c',0200+'r', /* -MAC-RO */ + 00 +}; + +static Uchar sufp[] = { + 05,0200+'g','r','o','u', /* -GROUP */ + 02,0200+'u', /* -UP */ + 04,0200+'s','h','i', /* -SHIP */ + 04,0200+'k','e','e', /* -KEEP */ + 00 +}; + +static Uchar sufr[] = { + 04,0200+'z','a','r', /* -ZARR */ + 0300+02,'r', /* R/R */ + 03,0200+'t','o', /* -TOR */ + 040+03,0200+'s','o', /* -SOR */ + 040+04,0200+'r','i',0200+'o', /* -RI-OR */ + 04,'i','z',0200+'e', /* IZ-ER */ + 05,0200+'c','o','v',0200+'e', /* -COV-ER */ + 04,0200+'o','v','e', /* -OVER */ + 04,0200+'e','v',0200+'e', /* -EV-ER */ + 8,0200+'c','o','m',0200+'p','u','t',0200+'e', /* -COM-PUT-ER */ + 040+05,'u','s',0200+'t','e', /* US-TER */ + 05,'o','s','t',0200+'e', /* OST-ER */ + 040+05,0200+'a','c',0200+'t','e', /* -AC-TER */ + 06,0200+'w','r','i','t',0200+'e', /* -WRIT-ER */ + 040+05,'i','s',0200+'t','e', /* IS-TER */ + 040+05,'e','s',0200+'t','e', /* ES-TER */ + 040+05,'a','s',0200+'t','e', /* AS-TER */ + 04,0200+'s','t','e', /* -STER */ + 05,'a','r',0200+'t','e', /* AR-TER */ + 04,'r','t',0200+'e', /* RT-ER */ + 040+05,'m',0200+'e',0200+'t','e', /* M-E-TER */ + 05,0200+'w','a',0200+'t','e', /* -WA-TER */ + 03,'r',0200+'e', /* R-ER */ + 04,'o','p',0200+'e', /* OP-ER */ + 05,0200+'p','a',0200+'p','e', /* -PA-PER */ + 04,'w','n',0200+'e', /* WN-ER */ + 040+04,'s',0200+'n','e', /* S-NER */ + 04,'o','n',0200+'e', /* ON-ER */ + 04,'r','m',0200+'e', /* RM-ER */ + 03,0200+'m','e', /* -MER */ + 04,'l','l',0200+'e', /* LL-ER */ + 05,'d',0200+'d','l','e', /* D-DLER */ + 04,0200+'b','l','e', /* -BLER */ + 03,'k',0200+'e', /* K-ER */ + 05,'n',0200+'t','h','e', /* N-THER */ + 06,0200+'f','a',0200+'t','h','e', /* -FA-THER */ + 06,'e','i',0200+'t','h','e', /* EI-THER */ + 04,'t','h',0200+'e', /* TH-ER */ + 04,'s','h',0200+'e', /* SH-ER */ + 04,0200+'p','h','e', /* -PHER */ + 04,'c','h',0200+'e', /* CH-ER */ + 04,'d','g',0200+'e', /* DG-ER */ + 04,'r','d',0200+'e', /* RD-ER */ + 06,'o','u','n','d',0200+'e', /* OUND-ER */ + 04,'l','d',0200+'e', /* LD-ER */ + 04,'i','d',0200+'e', /* ID-ER */ + 05,0200+'d','u','c',0200+'e', /* -DUC-ER */ + 04,'n','c',0200+'e', /* NC-ER */ + 0100+02, 0200+'e', /* /ER */ + 03,0200+'s','a', /* -SAR */ + 040+06,'a','c',0200+'u',0200+'l','a', /* AC-U-LAR */ + 040+06,'e','c',0200+'u',0200+'l','a', /* EC-U-LAR */ + 040+06,'i','c',0200+'u',0200+'l','a', /* IC-U-LAR */ + 040+06,'e','g',0200+'u',0200+'l','a', /* EG-U-LAR */ + 00 +}; + +static Uchar sufs[] = { + 040+04,'u',0200+'o','u', /* U-OUS */ + 05,0200+'t','i','o','u', /* -TIOUS */ + 05,0200+'g','i','o','u', /* -GIOUS */ + 05,0200+'c','i','o','u', /* -CIOUS */ + 040+04,'i',0200+'o','u', /* I-OUS */ + 05,0200+'g','e','o','u', /* -GEOUS */ + 05,0200+'c','e','o','u', /* -CEOUS */ + 04,'e',0200+'o','u', /* E-OUS */ + 0140+02,0200+'u', /* /US */ + 04,0200+'n','e','s', /* -NESS */ + 04,0200+'l','e','s', /* -LESS */ + 0140+02,0200+'s', /* /SS */ + 040+05,'p',0200+'o',0200+'l','i', /* P-O-LIS */ + 0140+02,0200+'i', /* /IS */ + 0100+03,0200+'x','e', /* X/ES */ + 0100+03,0200+'s','e', /* S/ES */ + 0100+04,'s','h',0200+'e', /* SH/ES */ + 0100+04,'c','h',0200+'e', /* CH/ES */ + 0300+01, /* /S */ + 00 +}; + +static Uchar suft[] = { + 05,0200+'l','i','m',0200+'i', /* -LIM-IT */ + 06,'i','o','n',0200+'i','s', /* ION-IST */ + 05,'i','n',0200+'i','s', /* IN-IST */ + 05,'a','l',0200+'i','s', /* AL-IST */ + 06,'l',0200+'o',0200+'g','i','s', /* L-O-GIST */ + 05,'h','t',0200+'e','s', /* HT-EST */ + 04,'i',0200+'e','s', /* I-EST */ + 05,'g',0200+'g','e','s', /* G-GEST */ + 04,'g',0200+'e','s', /* G-EST */ + 05,'d',0200+'d','e','s', /* D-DEST */ + 04,'d',0200+'e','s', /* D-EST */ + 04,0200+'c','a','s', /* -CAST */ + 05,0200+'h','e','a','r', /* -HEART */ + 04,0200+'f','o','o', /* -FOOT */ + 03,'i',0200+'o', /* I-OT */ + 05,0200+'f','r','o','n', /* -FRONT */ + 05,0200+'p','r','i','n', /* -PRINT */ + 04,0200+'m','e','n', /* -MENT */ + 05,0200+'c','i','e','n', /* -CIENT */ + 04,'i',0200+'a','n', /* I-ANT */ + 06,0200+'w','r','i','g','h', /* -WRIGHT */ + 06,0200+'b','r','i','g','h', /* -BRIGHT */ + 06,0200+'f','l','i','g','h', /* -FLIGHT */ + 06,0200+'w','e','i','g','h', /* -WEIGHT */ + 05,0200+'s','h','i','f', /* -SHIFT */ + 05,0200+'c','r','a','f', /* -CRAFT */ + 040+04,'d','g',0200+'e', /* DG-ET */ + 04,0200+'g','o','a', /* -GOAT */ + 04,0200+'c','o','a', /* -COAT */ + 04,0200+'b','o','a', /* -BOAT */ + 04,0200+'w','h','a', /* -WHAT */ + 04,0200+'c','u','i', /* -CUIT */ + 00 +}; + +static Uchar sufy[] = { + 040+04,'e','s',0200+'t', /* ES-TY */ + 040+05,'q','u','i',0200+'t', /* QUI-TY */ + 04,0200+'t','i',0200+'t', /* -TI-TY */ + 040+05,'o','s',0200+'i',0200+'t', /* OS-I-TY */ + 04,0200+'s','i',0200+'t', /* -SI-TY */ + 05,'i','n',0200+'i',0200+'t', /* IN-I-TY */ + 04,'n','i',0200+'t', /* NI-TY */ + 040+010,'f','a',0200+'b','i','l',0200+'i',0200+'t', /* FA-BIL-I-TY */ + 010,0200+'c','a',0200+'b','i','l',0200+'i',0200+'t', /* -CA-BIL-I-TY */ + 010,0200+'p','a',0200+'b','i','l',0200+'i',0200+'t', /* -PA-BIL-I-TY */ + 06,0200+'b','i','l',0200+'i',0200+'t', /* -BIL-I-TY */ + 03,'i',0200+'t', /* I-TY */ + 04,0200+'b','u','r', /* -BUR-Y */ + 04,0200+'t','o',0200+'r', /* -TO-RY */ + 05,0200+'q','u','a','r', /* -QUAR-Y */ + 040+04,'u',0200+'a','r', /* U-ARY */ + 07,0200+'m','e','n',0200+'t','a',0200+'r', /* -MEN-TA-RY */ + 06,'i','o','n',0200+'a','r', /* ION-ARY */ + 04,'i',0200+'a','r', /* I-ARY */ + 04,'n',0200+'o',0200+'m', /* N-O-MY */ + 03,0200+'p','l', /* -PLY */ + 04,'g',0200+'g','l', /* G-GLY */ + 05,0200+'p','a',0200+'b','l', /* -PA-BLY */ + 05,'f','a',0200+'b','l', /* FA-BLY */ + 05,0200+'c','a',0200+'b','l', /* -CA-BLY */ + 04,0200+'a','b','l', /* -ABLY */ + 03,0200+'b','l', /* -BLY */ + 02,0200+'l', /* -LY */ + 03,0200+'s','k', /* -SKY */ + 040+06,'g',0200+'r','a',0200+'p','h', /* G-RA-PHY */ + 04,'l',0200+'o',0200+'g', /* L-O-GY */ + 02,0200+'f', /* -FY */ + 03,0200+'n','e', /* -NEY */ + 03,0200+'l','e', /* -LEY */ + 04,'c','k',0200+'e', /* CK-EY */ + 03,0200+'k','e', /* -KEY */ + 04,0200+'b','o','d', /* -BODY */ + 05,0200+'s','t','u','d', /* -STUDY */ + 0340+04,'e','e','d', /* EEDY */ + 02,0200+'b', /* -BY */ + 03,0200+'w','a', /* -WAY */ + 03,0200+'d','a', /* -DAY */ + 00 +}; + +Uchar *suftab[] = { + sufa, + 0, + sufc, + sufd, + sufe, + suff, + sufg, + sufh, + sufi, + 0, + sufk, + sufl, + sufm, + sufn, + sufo, + sufp, + 0, + sufr, + sufs, + suft, + 0, + 0, + 0, + 0, + sufy, + 0, +}; diff --git a/src/cmd/troff/t10.c b/src/cmd/troff/t10.c new file mode 100644 index 00000000..3e8026d1 --- /dev/null +++ b/src/cmd/troff/t10.c @@ -0,0 +1,512 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +/* + * troff10.c + * + * typesetter interface + */ + +int vpos = 0; /* absolute vertical position on page */ +int hpos = 0; /* ditto horizontal */ + +extern Font fonts[MAXFONTS+1]; + +int Inch; +int Hor; +int Vert; +int Unitwidth; +int nfonts; + + + +void t_ptinit(void) +{ + int i; + char buf[100], *p; + + hmot = t_hmot; + makem = t_makem; + setabs = t_setabs; + setch = t_setch; + sethl = t_sethl; + setht = t_setht; + setslant = t_setslant; + vmot = t_vmot; + xlss = t_xlss; + findft = t_findft; + width = t_width; + mchbits = t_mchbits; + ptlead = t_ptlead; + ptout = t_ptout; + ptpause = t_ptpause; + setfont = t_setfont; + setps = t_setps; + setwd = t_setwd; + + /* open table for device, */ + /* read in resolution, size info, font info, etc., set params */ + if ((p = getenv("TYPESETTER")) != 0) + strcpy(devname, p); + if (termtab[0] == 0) + strcpy(termtab, DWBfontdir); + if (fontdir[0] == 0) + strcpy(fontdir, DWBfontdir); + if (devname[0] == 0) + strcpy(devname, TDEVNAME); + hyf = 1; + lg = 1; + + sprintf(buf, "/dev%s/DESC", devname); + strcat(termtab, buf); + if (getdesc(termtab) < 0) { + ERROR "can't open DESC file %s", termtab WARN; + done3(1); + } + if (!ascii) { + OUT "x T %s\n", devname PUT; + OUT "x res %d %d %d\n", Inch, Hor, Vert PUT; + OUT "x init\n" PUT; + } + for (i = 1; i <= nfonts; i++) + setfp(i, fontlab[i], (char *) 0, 0); + sps = EM/3; /* space size */ + ics = EM; /* insertion character space */ + for (i = 0; i < (NTAB - 1) && DTAB * (i + 1) < TABMASK; i++) + tabtab[i] = DTAB * (i + 1); + tabtab[NTAB] = 0; + pl = 11 * INCH; /* paper length */ + po = PO; /* page offset */ + spacesz = SS; + lss = lss1 = VS; + ll = ll1 = lt = lt1 = LL; + t_specnames(); /* install names like "hyphen", etc. */ +} + +void t_specnames(void) +{ + int i; + + for (i = 0; spnames[i].n; i++) + *spnames[i].n = chadd(spnames[i].v, Troffchar, Install); +} + +void t_ptout(Tchar i) +{ + int dv; + Tchar *k; + int temp, a, b; + int diff; + + if (cbits(i) != '\n') { + if (olinep >= oline + olnsize) { + diff = olinep - oline; + olnsize += OLNSIZE; + if ((oline = (Tchar *)realloc((char *)oline, olnsize * sizeof(Tchar))) != NULL) { + if (diff && olinep) + olinep = oline + diff; + } else { + ERROR "Output line overflow." WARN; + done(2); + } + } + *olinep++ = i; + return; + } + if (olinep == oline) { + lead += lss; + return; + } + + hpos = po; /* ??? */ + esc = 0; /* ??? */ + ptesc(); /* the problem is to get back to the left end of the line */ + dv = 0; + for (k = oline; k < olinep; k++) { + if (ismot(*k) && isvmot(*k)) { + temp = absmot(*k); + if (isnmot(*k)) + temp = -temp; + dv += temp; + } + } + if (dv) { + vflag++; + *olinep++ = makem(-dv); + vflag = 0; + } + + b = dip->blss + lss; + lead += dip->blss + lss; + dip->blss = 0; + for (k = oline; k < olinep; ) + k += ptout0(k); /* now passing a pointer! */ + olinep = oline; + lead += dip->alss; + a = dip->alss; + dip->alss = 0; + /* + OUT "x xxx end of line: hpos=%d, vpos=%d\n", hpos, vpos PUT; +*/ + OUT "n%d %d\n", b, a PUT; /* be nice to chuck */ +} + +int ptout0(Tchar *pi) +{ + int j, k, w; + int z, dx, dy, dx2, dy2, n; + Tchar i; + int outsize; /* size of object being printed */ + + outsize = 1; /* default */ + i = *pi; + k = cbits(i); + if (ismot(i)) { + j = absmot(i); + if (isnmot(i)) + j = -j; + if (isvmot(i)) + lead += j; + else + esc += j; + return(outsize); + } + if (k == CHARHT) { + xpts = fbits(i); /* sneaky, font bits as size bits */ + if (xpts != mpts) + ptps(); + OUT "x H %d\n", sbits(i) PUT; + return(outsize); + } + if (k == SLANT) { + OUT "x S %d\n", sfbits(i)-180 PUT; + return(outsize); + } + if (k == WORDSP) { + oput('w'); + return(outsize); + } + if (sfbits(i) == oldbits) { + xfont = pfont; + xpts = ppts; + } else + xbits(i, 2); + if (k == XON) { + extern int xon; + ptflush(); /* guarantee that everything is out */ + if (esc) + ptesc(); + if (xfont != mfont) + ptfont(); + if (xpts != mpts) + ptps(); + if (lead) + ptlead(); + OUT "x X " PUT; + xon++; + for (j = 1; cbits(pi[j]) != XOFF; j++) + outascii(pi[j]); + oput('\n'); + xon--; + return j+1; + } + if (k < 040 && k != DRAWFCN) + return(outsize); + j = z = 0; + if (k != DRAWFCN) { + if (widcache[k].fontpts == (xfont<<8) + xpts && !setwdf) { + w = widcache[k].width; + bd = 0; + cs = 0; + } else + w = getcw(k); + if (cs) { + if (bd) + w += (bd - 1) * HOR; + j = (cs - w) / 2; + w = cs - j; + if (bd) + w -= (bd - 1) * HOR; + } + if (iszbit(i)) { + if (cs) + w = -j; + else + w = 0; + z = 1; + } + } + esc += j; + if (xfont != mfont) + ptfont(); + if (xpts != mpts) + ptps(); + if (lead) + ptlead(); + /* put out the real character here */ + if (k == DRAWFCN) { + if (esc) + ptesc(); + w = 0; + dx = absmot(pi[3]); + if (isnmot(pi[3])) + dx = -dx; + dy = absmot(pi[4]); + if (isnmot(pi[4])) + dy = -dy; + switch (cbits(pi[1])) { + case DRAWCIRCLE: /* circle */ + OUT "D%c %d\n", DRAWCIRCLE, dx PUT; /* dx is diameter */ + hpos += dx; + break; + case DRAWELLIPSE: + OUT "D%c %d %d\n", DRAWELLIPSE, dx, dy PUT; + hpos += dx; + break; + case DRAWBUILD: + k = cbits(pi[2]); + OUT "D%c %d ", DRAWBUILD, dx PUT; + if (k < ALPHABET) + OUT "%c\n", k PUT; + else + ptchname(k); + hpos += dx; + break; + case DRAWLINE: /* line */ + k = cbits(pi[2]); + OUT "D%c %d %d ", DRAWLINE, dx, dy PUT; + if (k < ALPHABET) + OUT "%c\n", k PUT; + else + ptchname(k); + hpos += dx; + vpos += dy; + break; + case DRAWARC: /* arc */ + dx2 = absmot(pi[5]); + if (isnmot(pi[5])) + dx2 = -dx2; + dy2 = absmot(pi[6]); + if (isnmot(pi[6])) + dy2 = -dy2; + OUT "D%c %d %d %d %d\n", DRAWARC, + dx, dy, dx2, dy2 PUT; + hpos += dx + dx2; + vpos += dy + dy2; + break; + + case 's': /* using 's' internally to avoid .tr ~ */ + pi[1] = '~'; + case DRAWSPLINE: /* spline */ + default: /* something else; copy it like spline */ + OUT "D%c %d %d", cbits(pi[1]), dx, dy PUT; + hpos += dx; + vpos += dy; + if (cbits(pi[3]) == DRAWFCN || cbits(pi[4]) == DRAWFCN) { + /* it was somehow defective */ + OUT "\n" PUT; + break; + } + for (n = 5; cbits(pi[n]) != DRAWFCN; n += 2) { + dx = absmot(pi[n]); + if (isnmot(pi[n])) + dx = -dx; + dy = absmot(pi[n+1]); + if (isnmot(pi[n+1])) + dy = -dy; + OUT " %d %d", dx, dy PUT; + hpos += dx; + vpos += dy; + } + OUT "\n" PUT; + break; + } + for (n = 3; cbits(pi[n]) != DRAWFCN; n++) + ; + outsize = n + 1; + } else if (k < ALPHABET) { + /* try to go faster and compress output */ + /* by printing nnc for small positive motion followed by c */ + /* kludgery; have to make sure set all the vars too */ + if (esc > 0 && esc < 100) { + oput(esc / 10 + '0'); + oput(esc % 10 + '0'); + oput(k); + hpos += esc; + esc = 0; + } else { + if (esc) + ptesc(); + oput('c'); + oput(k); + oput('\n'); + } + } else { + if (esc) + ptesc(); + ptchname(k); + } + if (bd) { + bd -= HOR; + if (esc += bd) + ptesc(); + if (k < ALPHABET) + OUT "c%c\n", k PUT; + else + ptchname(k); + if (z) + esc -= bd; + } + esc += w; + return(outsize); +} + +void ptchname(int k) +{ + char *chn = chname(k); + + switch (chn[0]) { + case MBchar: + OUT "c%s\n", chn+1 PUT; /* \n not needed? */ + break; + case Number: + OUT "N%s\n", chn+1 PUT; + break; + case Troffchar: + OUT "C%s\n", chn+1 PUT; + break; + default: + ERROR "illegal char type %s", chn WARN; + break; + } +} + +void ptflush(void) /* get us to a clean output state */ +{ + if (TROFF) { + /* ptesc(); but always H, no h */ + hpos += esc; + OUT "\nH%d\n", hpos PUT; + esc = 0; + ptps(); + ptfont(); + ptlead(); + } +} + +void ptps(void) +{ + int i, j, k; + + i = xpts; + for (j = 0; i > (k = pstab[j]); j++) + if (!k) { + k = pstab[--j]; + break; + } + if (!ascii) + OUT "s%d\n", k PUT; /* really should put out string rep of size */ + mpts = i; +} + +void ptfont(void) +{ + mfont = xfont; + if (ascii) + return; + if (xfont > nfonts) { + ptfpcmd(0, fonts[xfont].longname, 0); /* Put the desired font in the + * fontcache of the filter */ + OUT "f0\n" PUT; /* make sure that it gets noticed */ + } else + OUT "f%d\n", xfont PUT; +} + +void ptfpcmd(int f, char *s, char *longname) +{ + if (f > nfonts) /* a bit risky? */ + f = 0; + if (longname) { + OUT "x font %d %s %s\n", f, s, longname PUT; + } else { + OUT "x font %d %s\n", f, s PUT; + } +/* OUT "f%d\n", xfont PUT; /* need this for buggy version of adobe transcript */ + /* which apparently believes that x font means */ + /* to set the font, not just the position. */ +} + +void t_ptlead(void) +{ + vpos += lead; + if (!ascii) + OUT "V%d\n", vpos PUT; + lead = 0; +} + +void ptesc(void) +{ + hpos += esc; + if (!ascii) + if (esc > 0) { + oput('h'); + if (esc>=10 && esc<100) { + oput(esc/10 + '0'); + oput(esc%10 + '0'); + } else + OUT "%d", esc PUT; + } else + OUT "H%d\n", hpos PUT; + esc = 0; +} + +void ptpage(int n) /* called at end of each output page, we hope */ +{ + int i; + + if (NROFF) + return; + ptlead(); + vpos = 0; + if (ascii) + return; + OUT "p%d\n", n PUT; /* new page */ + for (i = 0; i <= nfonts; i++) + if (fontlab[i]) { + if (fonts[i].truename) + OUT "x font %d %s %s\n", i, fonts[i].longname, fonts[i].truename PUT; + else + OUT "x font %d %s\n", i, fonts[i].longname PUT; + } + ptps(); + ptfont(); +} + +void pttrailer(void) +{ + if (TROFF) + OUT "x trailer\n" PUT; +} + +void ptstop(void) +{ + if (TROFF) + OUT "x stop\n" PUT; +} + +void t_ptpause(void) +{ + if (ascii) + return; + ptlead(); + vpos = 0; + pttrailer(); + ptlead(); + OUT "x pause\n" PUT; + flusho(); + mpts = mfont = 0; + ptesc(); + esc = po; + hpos = vpos = 0; /* probably in wrong place */ +} diff --git a/src/cmd/troff/t11.c b/src/cmd/troff/t11.c new file mode 100644 index 00000000..5511748c --- /dev/null +++ b/src/cmd/troff/t11.c @@ -0,0 +1,255 @@ +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +#define MAXCH NCHARS /* maximum number of global char names */ +char *chnames[MAXCH]; /* chnames[n-ALPHABET] -> name of char n */ +int nchnames; /* number of Cxy names currently seen */ + +#define MAXPS 100 /* max number of point sizes */ +int pstab[MAXPS]; /* point sizes */ +int nsizes; /* number in DESC */ + +Font fonts[MAXFONTS+1]; /* font info + ptr to width info */ + + +#define skipline(f) while (getc(f) != '\n') + +#define eq(s1, s2) (strcmp(s1, s2) == 0) + +getdesc(char *name) +{ + FILE *fin; + char cmd[100], s[100]; + int i, v; + + if ((fin = fopen(unsharp(name), "r")) == NULL) + return -1; + while (fscanf(fin, "%s", cmd) != EOF) { + if (strcmp(cmd, "res") == 0) { + fscanf(fin, "%d", &Inch); + } else if (strcmp(cmd, "hor") == 0) { + fscanf(fin, "%d", &Hor); + } else if (strcmp(cmd, "vert") == 0) { + fscanf(fin, "%d", &Vert); + } else if (strcmp(cmd, "unitwidth") == 0) { + fscanf(fin, "%d", &Unitwidth); + } else if (strcmp(cmd, "sizes") == 0) { + nsizes = 0; + while (fscanf(fin, "%d", &v) != EOF && v != 0 && nsizes < MAXPS) + pstab[nsizes++] = v; + } else if (strcmp(cmd, "fonts") == 0) { + fscanf(fin, "%d", &nfonts); + for (i = 1; i <= nfonts; i++) { + fscanf(fin, "%s", s); + fontlab[i] = PAIR(s[0], s[1]); + } + } else if (strcmp(cmd, "charset") == 0) { /* add any names */ + while (fscanf(fin, "%s", s) != EOF) + chadd(s, Troffchar, Install); + break; + } + /* else + just skip anything else */ + skipline(fin); + } + fclose(fin); + return 1; +} + +static int checkfont(char *name) +{ /* in case it's not really a font description file */ + /* really paranoid, but consider \f. */ + FILE *fp; + char buf[300], buf2[300]; + int i, status = -1; + + if ((fp = fopen(unsharp(name), "r")) == NULL) + return -1; + for (i = 1; i <= 10; i++) { + if (fgets(buf, sizeof buf, fp) == NULL) + break; + sscanf(buf, "%s", buf2); + if (buf2[0] == '#') { + i--; + continue; + } + if (eq(buf2, "name") || eq(buf2, "fontname") || + eq(buf2, "special") || eq(buf2, "charset")) { + status = 1; + break; + } + } + fclose(fp); + return status; + +} + +getfont(char *name, int pos) /* create width tab for font */ +{ + FILE *fin; + Font *ftemp = &fonts[pos]; + Chwid chtemp[MAXCH]; + static Chwid chinit; + int i, nw, n, wid, kern, code, type; + char buf[100], ch[100], s1[100], s2[100], s3[100], cmd[300]; + + /* fprintf(stderr, "read font %s onto %d\n", name, pos); */ + if (checkfont(name) == -1) + return -1; + if ((fin = fopen(unsharp(name), "r")) == NULL) + return -1; + for (i = 0; i < ALPHABET; i++) + chtemp[i] = chinit; /* zero out to begin with */ + ftemp->specfont = ftemp->ligfont = 0; + ftemp->defaultwidth = ftemp->spacewidth = Inch * Unitwidth / 72 / 3; /* should be rounded */ + while (fscanf(fin, "%s", cmd) != EOF) { + if (strcmp(cmd, "name") == 0) + fscanf(fin, "%s", ftemp->longname); + else if (strcmp(cmd, "special") == 0) + ftemp->specfont = 1; + else if (strcmp(cmd, "ligatures") == 0) { + ftemp->ligfont = getlig(fin); + } else if (strcmp(cmd, "spacewidth") == 0) { + fscanf(fin, "%d", &ftemp->spacewidth); + } else if (strcmp(cmd, "defaultwidth") == 0) { + fscanf(fin, "%d", &ftemp->defaultwidth); + } else if (strcmp(cmd, "charset") == 0) { + wchar_t wc; + skipline(fin); + nw = ALPHABET; + while (fgets(buf, sizeof buf, fin) != NULL) { + sscanf(buf, "%s %s %s %s", ch, s1, s2, s3); + if (s1[0] != '"') { /* genuine new character */ + sscanf(s1, "%d", &wid); + sscanf(s2, "%d", &kern); + code = strtol(s3, 0, 0); /* dec/oct/hex */ + } + /* otherwise it's a synonym for prev character, */ + /* so leave previous values intact */ + + + /* decide what kind of alphabet it might come from here */ + + + if (strlen(ch) == 1) { /* it's ascii */ + n = ch[0]; /* origin includes non-graphics */ + chtemp[n].num = ch[0]; + } else if (ch[0] == '\\' && ch[1] == '0') { + n = strtol(ch+1, 0, 0); /* \0octal or \0xhex */ + chtemp[n].num = n; +#ifdef UNICODE + } else if (mbtowc(&wc, ch, strlen(ch)) > 1) { + chtemp[nw].num = chadd(ch, MBchar, Install); + n = nw; + nw++; +#endif /*UNICODE*/ + } else { + if (strcmp(ch, "---") == 0) { /* no name */ + sprintf(ch, "%d", code); + type = Number; + } else + type = Troffchar; + chtemp[nw].num = chadd(ch, type, Install); + n = nw; + nw++; + } + chtemp[n].wid = wid; + chtemp[n].kern = kern; + chtemp[n].code = code; + /*fprintf(stderr, "font %2.2s char %4.4s num %3d wid %2d code %3d\n", + ftemp->longname, ch, n, wid, code); + */ + } + break; + } + skipline(fin); + } + fclose(fin); + chtemp[' '].wid = ftemp->spacewidth; /* width of space on this font */ + ftemp->nchars = nw; + if (ftemp->wp) + free(ftemp->wp); /* god help us if this wasn't allocated */ + ftemp->wp = (Chwid *) malloc(nw * sizeof(Chwid)); + if (ftemp->wp == NULL) + return -1; + for (i = 0; i < nw; i++) + ftemp->wp[i] = chtemp[i]; +/* + * printf("%d chars: ", nw); + * for (i = 0; i < nw; i++) + * if (ftemp->wp[i].num > 0 && ftemp->wp[i].num < ALPHABET) { + * printf("%c %d ", ftemp->wp[i].num, ftemp->wp[i].wid); + * else if (i >= ALPHABET) + * printf("%d (%s) %d ", ftemp->wp[i].num, + * chnames[ftemp->wp[i].num-ALPHABET], ftemp->wp[i].wid); + * } + * printf("\n"); + */ + return 1; +} + +chadd(char *s, int type, int install) /* add s to global character name table; */ +{ /* or just look it up */ + + /* a temporary kludge: store the "type" as the first character */ + /* of the string, so we can remember from whence it came */ + + char *p; + int i; + +/* fprintf(stderr, "into chadd %s %c %c\n", s, type, install); /* */ + for (i = 0; i < nchnames; i++) + if (type == chnames[i][0] && eq(s, chnames[i]+1)) /* +1 since type at front */ + break; +/* fprintf(stderr, "i %d, nchnames %d\n", i, nchnames); /* */ + if (i < nchnames) /* found same type and bytes at position i */ + return ALPHABET + i; + else if (install == Lookup) /* not found, and we were just looking */ + return -1; + + chnames[nchnames] = p = (char *) malloc(strlen(s)+1+1); /* type + \0 */ + if (p == NULL) { + ERROR "out of space adding character %s", s WARN; + return LEFTHAND; + } + if (nchnames >= NCHARS - ALPHABET) { + ERROR "out of table space adding character %s", s WARN; + return LEFTHAND; + } + strcpy(chnames[nchnames]+1, s); + chnames[nchnames][0] = type; +/* fprintf(stderr, "installed %c%s at %d\n", type, s, nchnames); /* */ + return nchnames++ + ALPHABET; +} + +char *chname(int n) /* return string for char with index n */ +{ /* includes type char at front, to be peeled off elsewhere */ + if (n >= ALPHABET && n < nchnames + ALPHABET) + return chnames[n-ALPHABET]; + else + return ""; +} + +getlig(FILE *fin) /* pick up ligature list */ +{ + int lig; + char temp[200]; + + lig = 0; + while (fscanf(fin, "%s", temp) != EOF && strcmp(temp, "0") != 0) { + if (strcmp(temp, "fi") == 0) + lig |= LFI; + else if (strcmp(temp, "fl") == 0) + lig |= LFL; + else if (strcmp(temp, "ff") == 0) + lig |= LFF; + else if (strcmp(temp, "ffi") == 0) + lig |= LFFI; + else if (strcmp(temp, "ffl") == 0) + lig |= LFFL; + else + fprintf(stderr, "illegal ligature %s ignored\n", temp); + } + return lig; +} diff --git a/src/cmd/troff/t6.c b/src/cmd/troff/t6.c new file mode 100644 index 00000000..b778916c --- /dev/null +++ b/src/cmd/troff/t6.c @@ -0,0 +1,881 @@ +/* + * t6.c + * + * width functions, sizes and fonts + */ + +#include "tdef.h" +#include "fns.h" +#include "ext.h" + +int fontlab[MAXFONTS+1]; +int cstab[MAXFONTS+1]; +int ccstab[MAXFONTS+1]; +int bdtab[MAXFONTS+1]; +int sbold = 0; + +t_width(Tchar j) +{ + int i, k; + + if (iszbit(j)) + return 0; + if (ismot(j)) { + if (isvmot(j)) + return(0); + k = absmot(j); + if (isnmot(j)) + k = -k; + return(k); + } + i = cbits(j); + if (i < ' ') { + if (i == '\b') + return(-widthp); + if (i == PRESC) + i = eschar; + else if (i == HX) + return(0); + } + if (i == ohc) + return(0); + i = trtab[i]; + if (i < ' ') + return(0); + if (sfbits(j) == oldbits) { + xfont = pfont; + xpts = ppts; + } else + xbits(j, 0); + if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf) + k = widcache[i].width; + else { + k = getcw(i); + if (bd) + k += (bd - 1) * HOR; + if (cs) + k = cs; + } + widthp = k; + return(k); +} + +/* + * clear width cache-- s means just space + */ +void zapwcache(int s) +{ + int i; + + if (s) { + widcache[' '].fontpts = 0; + return; + } + for (i=0; i<NWIDCACHE; i++) + widcache[i].fontpts = 0; +} + +onfont(int n, int f) /* is char n on font f? */ +{ + int i; + Font *fp = &fonts[f]; + Chwid *cp, *ep; + char *np; + + if (n < ALPHABET) { + if (fp->wp[n].num == n) /* ascii at front */ + return n; + else + return -1; + } + cp = &fp->wp[ALPHABET]; + ep = &fp->wp[fp->nchars]; + for ( ; cp < ep; cp++) /* search others */ + if (cp->num == n) + return cp - &fp->wp[0]; + /* maybe it was a \N... */ + np = chname(n); + if (*np == Number) { + i = atoi(np+1); /* sscanf(np+1, "%d", &i); */ + cp = &fp->wp[0]; + ep = &fp->wp[fp->nchars]; + for ( ; cp < ep; cp++) { /* search others */ + if (cp->code == i) + return cp - &fp->wp[0]; + } + return -2; /* a \N that doesn't have an entry */ + } + return -1; /* vanilla not found */ +} + +getcw(int i) +{ + int k, n, x; + Font *fp; + int nocache = 0; + if (i < ' ') + return 0; + bd = 0; + fp = &fonts[xfont]; + if (i == ' ') { /* a blank */ + k = (fp->spacewidth * spacesz + 6) / 12; + /* this nonsense because .ss cmd uses 1/36 em as its units */ + /* and default is 12 */ + } else if ((n = onfont(i, xfont)) >= 0) { /* on this font at n */ + k = fp->wp[n].wid; + if (setwdf) + numtabp[CT].val |= fp->wp[n].kern; + } else if (n == -2) { /* \N with default width */ + + k = fp->defaultwidth; + } else { /* not on current font */ + nocache = 1; + k = fp->defaultwidth; /* default-size space */ + if (smnt) { + int ii, jj; + for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) { + if ((n = onfont(i, ii)) >= 0) { + k = fonts[ii].wp[n].wid; + if (xfont == sbold) + bd = bdtab[ii]; + if (setwdf) + numtabp[CT].val |= fonts[ii].wp[n].kern; + break; + } + } + } + } + if (!bd) + bd = bdtab[xfont]; + if (cs = cstab[xfont]) { + nocache = 1; + if (ccs = ccstab[xfont]) + x = ccs; + else + x = xpts; + cs = (cs * EMPTS(x)) / 36; + } + /* was (k & BYTEMASK); since .wid is unsigned, should never happen */ + if (k < 0) + ERROR "can't happen: negative width %d in getcw %d\n", k, i WARN; + k = (k * xpts + (Unitwidth / 2)) / Unitwidth; + if (nocache|bd) + widcache[i].fontpts = 0; + else { + widcache[i].fontpts = (xfont<<8) + xpts; + widcache[i].width = k; + } + return(k); + /* Unitwidth is Units/Point, where + /* Units is the fundamental digitization + /* of the character set widths, and + /* Point is the number of goobies in a point + /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6 + /* In effect, it's the size at which the widths + /* translate directly into units. + */ +} + +void xbits(Tchar i, int bitf) +{ + int k; + + if(TROFF) { + xfont = fbits(i); + k = sbits(i); + if(k) { + xpts = pstab[k-1]; + oldbits = sfbits(i); + pfont = xfont; + ppts = xpts; + return; + } + switch(bitf) { + case 0: + xfont = font; + xpts = pts; + break; + case 1: + xfont = pfont; + xpts = ppts; + break; + case 2: + xfont = mfont; + xpts = mpts; + } + } +} + + +/* these next two functions ought to be the same in troff and nroff, */ +/* but the data structures they search are different. */ +/* silly historical problem. */ + + +Tchar t_setch(int c) +{ + int j; + char temp[50]; + char *s; + + s = temp; + if (c == '(') { /* \(xx */ + if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0) + return(0); + } else { /* \C'...' */ + c = getach(); + while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1) + s++; + } + *s = '\0'; +#ifdef UNICODE + return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ +#else + if (NROFF) { + j = chadd(temp, Troffchar, Lookup); + if ( j == -1) + return 0; + else + return j | chbits; + } else + return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */ + +#endif /*UNICODE*/ +} + +Tchar t_setabs(void) /* set absolute char from \N'...' */ +{ + int n; + char temp[10]; + + getch(); /* delim */ + n = 0; + n = inumb(&n); + getch(); /* delim */ + if (nonumb) + return 0; + sprintf(temp, "%d", n); /* convert into "#n" */ + n = chadd(temp, Number, Install); + return n | chbits; +} + + +/* + * fontlab[] is a cache that contains font information + * for each font. + * fontlab[] contains the 1- or 2-character name of the + * font current associated with that font. + * fonts 1..nfonts correspond to the mounted fonts; + * the last of these are the special fonts. + * If we don't use the (named) font in one of the + * standard positions, we install the name in the next + * free slot of fontlab[] and font[]. + * Whenever we need info about the font, we + * read in the data into the next free slot with getfont. + * The ptfont() (t10.c) routine will tell + * the device filter to put the font always at position + * zero if xfont > nfonts, so no need to change these filters. + * Yes, this is a bit kludgy. + * + * This gives the new specs of findft: + * find the font name i, where i also can be a number. + * Installs the font(name) i when not present + * returns -1 on error + */ + + +t_findft(int i) +{ + int k; + Uchar *p; + + p = unpair(i); + + if (isdigit(p[0])) { /* first look for numbers */ + k = p[0] - '0'; + if (p[1] > 0 && isdigit(p[1])) + k = 10 * k + p[1] - '0'; + if (k > 0 && k <= nfonts && k < smnt) + return(k); /* mounted font: .ft 3 */ + if (fontlab[k] && k <= MAXFONTS) { /* translate */ + return(k); /*number to a name */ + } else { + fprintf(stderr, "troff: no font at position %d\n", k); + return(-1); /* wild number */ + } + } + + /* + * Now we look for font names + */ + for (k = 1; fontlab[k] != i; k++) { + if (k > MAXFONTS) + return(-1); /* running out of fontlab space */ + if (fontlab[k] == 0) { /* passed all existing names */ + if (setfp(k, i, (char *) 0, 1) == -1) + return(-1); + else { + fontlab[k] = i; /* install the name */ + return(k); + } + } + } + return(k); /* was one of the existing names */ +} + + +void caseps(void) +{ + int i; + + if (TROFF) { + if(skip()) + i = apts1; + else { + noscale++; + i = inumb(&apts); /* this is a disaster for fractional point sizes */ + noscale = 0; + if(nonumb) + i = apts1; + } + casps1(i); + } +} + + +void casps1(int i) +{ + +/* + * in olden times, it used to ignore changes to 0 or negative. + * this is meant to allow the requested size to be anything, + * in particular so eqn can generate lots of \s-3's and still + * get back by matching \s+3's. + + if (i <= 0) + return; +*/ + apts1 = apts; + apts = i; + pts1 = pts; + pts = findps(i); + mchbits(); +} + + +findps(int i) +{ + int j, k; + + for (j=k=0 ; pstab[j] != 0 ; j++) + if (abs(pstab[j]-i) < abs(pstab[k]-i)) + k = j; + + return(pstab[k]); +} + + +void t_mchbits(void) +{ + int i, j, k; + + i = pts; + for (j = 0; i > (k = pstab[j]); j++) + if (!k) { + j--; + break; + } + chbits = 0; + setsbits(chbits, ++j); + setfbits(chbits, font); + sps = width(' ' | chbits); + zapwcache(1); +} + +void t_setps(void) +{ + int i, j; + + i = cbits(getch()); + if (isdigit(i)) { /* \sd or \sdd */ + i -= '0'; + if (i == 0) /* \s0 */ + j = apts1; + else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) { /* \sdd */ + j = 10 * i + j - '0'; + ch = 0; + } else /* \sd */ + j = i; + } else if (i == '(') { /* \s(dd */ + j = cbits(getch()) - '0'; + j = 10 * j + cbits(getch()) - '0'; + if (j == 0) /* \s(00 */ + j = apts1; + } else if (i == '+' || i == '-') { /* \s+, \s- */ + j = cbits(getch()); + if (isdigit(j)) { /* \s+d, \s-d */ + j -= '0'; + } else if (j == '(') { /* \s+(dd, \s-(dd */ + j = cbits(getch()) - '0'; + j = 10 * j + cbits(getch()) - '0'; + } + if (i == '-') + j = -j; + j += apts; + } + casps1(j); +} + + +Tchar t_setht(void) /* set character height from \H'...' */ +{ + int n; + Tchar c; + + getch(); + n = inumb(&apts); + getch(); + if (n == 0 || nonumb) + n = apts; /* does this work? */ + c = CHARHT; + c |= ZBIT; + setsbits(c, n); + setfbits(c, pts); /* sneaky, CHARHT font bits are size bits */ + return(c); +} + +Tchar t_setslant(void) /* set slant from \S'...' */ +{ + int n; + Tchar c; + + getch(); + n = 0; + n = inumb(&n); + getch(); + if (nonumb) + n = 0; + c = SLANT; + c |= ZBIT; + setsfbits(c, n+180); + return(c); +} + + +void caseft(void) +{ + if (!TROFF) { + n_caseft(); + return; + } + skip(); + setfont(1); +} + + +void t_setfont(int a) +{ + int i, j; + + if (a) + i = getrq(); + else + i = getsn(); + if (!i || i == 'P') { + j = font1; + goto s0; + } + if (/* i == 'S' || */ i == '0') /* an experiment -- why can't we change to it? */ + return; + if ((j = findft(i)) == -1) + if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try to put it in position 0 */ + return; +s0: + font1 = font; + font = j; + mchbits(); +} + + +void t_setwd(void) +{ + int base, wid; + Tchar i; + int delim, emsz, k; + int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1; + + base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val = 0; + if (ismot(i = getch())) + return; + delim = cbits(i); + savhp = numtabp[HP].val; + numtabp[HP].val = 0; + savapts = apts; + savapts1 = apts1; + savfont = font; + savfont1 = font1; + savpts = pts; + savpts1 = pts1; + setwdf++; + while (cbits(i = getch()) != delim && !nlflg) { + k = width(i); + wid += k; + numtabp[HP].val += k; + if (!ismot(i)) { + emsz = (INCH/72) * xpts; + } else if (isvmot(i)) { + k = absmot(i); + if (isnmot(i)) + k = -k; + base -= k; + emsz = 0; + } else + continue; + if (base < numtabp[SB].val) + numtabp[SB].val = base; + if ((k = base + emsz) > numtabp[ST].val) + numtabp[ST].val = k; + } + setn1(wid, 0, (Tchar) 0); + numtabp[HP].val = savhp; + apts = savapts; + apts1 = savapts1; + font = savfont; + font1 = savfont1; + pts = savpts; + pts1 = savpts1; + mchbits(); + setwdf = 0; +} + + +Tchar t_vmot(void) +{ + dfact = lss; + vflag++; + return t_mot(); +} + + +Tchar t_hmot(void) +{ + dfact = EM; + return t_mot(); +} + + +Tchar t_mot(void) +{ + int j, n; + Tchar i; + + j = HOR; + getch(); /*eat delim*/ + if (n = atoi0()) { + if (vflag) + j = VERT; + i = makem(quant(n, j)); + } else + i = 0; + getch(); + vflag = 0; + dfact = 1; + return(i); +} + + +Tchar t_sethl(int k) +{ + int j; + Tchar i; + + j = EM / 2; + if (k == 'u') + j = -j; + else if (k == 'r') + j = -2 * j; + vflag++; + i = makem(j); + vflag = 0; + return(i); +} + + +Tchar t_makem(int i) +{ + Tchar j; + + if (i >= 0) + j = i; + else + j = -i; + if (Hor > 1 && !vflag) + j = (j + Hor/2)/Hor * Hor; + j |= MOT; + if (i < 0) + j |= NMOT; + if (vflag) + j |= VMOT; + return(j); +} + + +Tchar getlg(Tchar i) +{ + Tchar j, k; + int lf; + + if (!TROFF) + return i; + if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */ + return(i); + j = getch0(); + if (cbits(j) == 'i' && (lf & LFI)) + j = LIG_FI; + else if (cbits(j) == 'l' && (lf & LFL)) + j = LIG_FL; + else if (cbits(j) == 'f' && (lf & LFF)) { + if ((lf & (LFFI|LFFL)) && lg != 2) { + k = getch0(); + if (cbits(k)=='i' && (lf&LFFI)) + j = LIG_FFI; + else if (cbits(k)=='l' && (lf&LFFL)) + j = LIG_FFL; + else { + *pbp++ = k; + j = LIG_FF; + } + } else + j = LIG_FF; + } else { + *pbp++ = j; + j = i; + } + return(i & SFMASK | j); +} + + +void caselg(void) +{ + + if(TROFF) { + skip(); + lg = atoi0(); + if (nonumb) + lg = 1; + } +} + +void casefp(void) +{ + int i, j; + + if (!TROFF) { + n_casefp(); + return; + } + skip(); + i = cbits(getch()); + if (isdigit(i)) { + i -= '0'; + j = cbits(getch()); + if (isdigit(j)) + i = 10 * i + j - '0'; + } + if (i <= 0 || i > nfonts) + ERROR "fp: bad font position %d", i WARN; + else if (skip() || !(j = getrq())) + ERROR "fp: no font name" WARN; + else if (skip() || !getname()) + setfp(i, j, (char*) 0, 1); + else /* 3rd argument = filename */ + setfp(i, j, nextf, 1); +} + +char *strdupl(const char *s) /* make a copy of s */ +{ + char *t; + + t = (char *) malloc(strlen(s) + 1); + if (t == NULL) + ERROR "out of space in strdupl(%s)", s FATAL; + strcpy(t, s); + return t; +} + +setfp(int pos, int f, char *truename, int print) /* mount font f at position pos[0...nfonts] */ +{ + char pathname[NS], shortname[NS], *sl; + + zapwcache(0); + if (truename) + strcpy(shortname, truename); + else + strcpy(shortname, (char *) unpair(f)); + if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/file: use verbatim */ + sprintf(pathname, "%s", truename); + if (fonts[pos].truename) + free(fonts[pos].truename); + fonts[pos].truename = strdupl(truename); + } else if (truename) { /* synonym: .fp 1 R Avant */ + sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename); + truename = 0; /* so doesn't get repeated by ptfpcmd */ + } else /* vanilla: .fp 5 XX */ + sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname); + if (truename == 0 && fonts[pos].truename != 0) { + free(fonts[pos].truename); + fonts[pos].truename = 0; + } + if (getfont(pathname, pos) < 0) { + ERROR "Can't open font file %s", pathname WARN; + return -1; + } + if (print && !ascii) { + ptfpcmd(pos, fonts[pos].longname, truename); + ptfont(); + } + if (pos == smnt) { + smnt = 0; + sbold = 0; + } + fontlab[pos] = f; + if (smnt == 0 && fonts[pos].specfont) + smnt = pos; + bdtab[pos] = cstab[pos] = ccstab[pos] = 0; + return pos; +} + +/* + * .cs request; don't check legality of optional arguments + */ +void casecs(void) +{ + int i, j; + + if (TROFF) { + int savtr = trace; + + trace = 0; + noscale++; + skip(); + if (!(i = getrq()) || (i = findft(i)) < 0) + goto rtn; + skip(); + cstab[i] = atoi0(); + skip(); + j = atoi0(); + if(nonumb) + ccstab[i] = 0; + else + ccstab[i] = findps(j); + rtn: + zapwcache(0); + noscale = 0; + trace = savtr; + } +} + + +void casebd(void) +{ + int i, j, k; + + if (!TROFF) { + n_casebd(); + return; + } + zapwcache(0); + k = 0; +bd0: + if (skip() || !(i = getrq()) || (j = findft(i)) == -1) { + if (k) + goto bd1; + else + return; + } + if (j == smnt) { + k = smnt; + goto bd0; + } + if (k) { + sbold = j; + j = k; + } +bd1: + skip(); + noscale++; + bdtab[j] = atoi0(); + noscale = 0; +} + + +void casevs(void) +{ + int i; + + if (!TROFF) { + n_casevs(); + return; + } + skip(); + vflag++; + dfact = INCH; /* default scaling is points! */ + dfactd = 72; + res = VERT; + i = inumb(&lss); + if (nonumb) + i = lss1; + if (i < VERT) + i = VERT; + lss1 = lss; + lss = i; +} + + +void casess(void) +{ + int i; + + if(TROFF) { + noscale++; + skip(); + if(i = atoi0()) { + spacesz = i & 0177; + zapwcache(0); + sps = width(' ' | chbits); + } + noscale = 0; + } +} + + +Tchar t_xlss(void) +{ + /* stores \x'...' into two successive Tchars. + /* the first contains HX, the second the value, + /* encoded as a vertical motion. + /* decoding is done in n2.c by pchar(). + */ + int i; + + getch(); + dfact = lss; + i = quant(atoi0(), VERT); + dfact = 1; + getch(); + if (i >= 0) + *pbp++ = MOT | VMOT | i; + else + *pbp++ = MOT | VMOT | NMOT | -i; + return(HX); +} + +Uchar *unpair(int i) +{ + static Uchar name[3]; + + name[0] = i & SHORTMASK; + name[1] = (i >> SHORT) & SHORTMASK; + name[2] = 0; + return name; +} diff --git a/src/cmd/troff/tdef.h b/src/cmd/troff/tdef.h new file mode 100644 index 00000000..e9e1f65c --- /dev/null +++ b/src/cmd/troff/tdef.h @@ -0,0 +1,670 @@ +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <ctype.h> +#include <string.h> + +#define NROFF (!TROFF) + + +/* Site dependent definitions */ + +#ifndef TMACDIR +#define TMACDIR "lib/tmac/tmac." +#endif +#ifndef FONTDIR +#define FONTDIR "lib/font" +#endif +#ifndef NTERMDIR +#define NTERMDIR "lib/term/tab." +#endif +#ifndef TDEVNAME +#define TDEVNAME "post" +#endif +#ifndef NDEVNAME +#define NDEVNAME "37" +#endif +#ifndef TEXHYPHENS +#define TEXHYPHENS "/usr/lib/tex/macros/hyphen.tex" +#endif +#ifndef ALTHYPHENS +#define ALTHYPHENS "lib/tmac/hyphen.tex" /* another place to look */ +#endif + +typedef unsigned char Uchar; +typedef unsigned short Ushort; + +typedef /*unsigned*/ long Tchar; + +typedef struct Blockp Blockp; +typedef struct Diver Diver; +typedef struct Stack Stack; +typedef struct Divsiz Divsiz; +typedef struct Contab Contab; +typedef struct Numtab Numtab; +typedef struct Numerr Numerr; +typedef struct Env Env; +typedef struct Term Term; +typedef struct Chwid Chwid; +typedef struct Font Font; +typedef struct Spnames Spnames; +typedef struct Wcache Wcache; +typedef struct Tbuf Tbuf; + +/* this simulates printf into a buffer that gets flushed sporadically */ +/* the BSD goo is because SunOS sprintf doesn't return anything useful */ + +#ifdef BSD4_2 +#define OUT (obufp += strlen(sprintf(obufp, +#define PUT ))) > obuf+BUFSIZ ? flusho() : 1 +#else +#define OUT (obufp += sprintf(obufp, +#define PUT )) > obuf+BUFSIZ ? flusho() : 1 +#endif + +#define oputs(a) OUT "%s", a PUT +#define oput(c) ( *obufp++ = (c), obufp > obuf+BUFSIZ ? flusho() : 1 ) + +extern char errbuf[]; +#define ERROR sprintf(errbuf, +#define WARN ), errprint() +#define FATAL ), errprint(), exit(1) + +/* starting values for typesetting parameters: */ + +#define PS 10 /* default point size */ +#define FT 1 /* default font position */ +#define ULFONT 2 /* default underline font */ +#define BDFONT 3 /* default emboldening font */ +#define BIFONT 4 /* default bold italic font */ +#define LL (unsigned) 65*INCH/10 /* line length; 39picas=6.5in */ +#define VS ((12*INCH)/72) /* initial vert space */ + + +#define EMPTS(pts) (((long)Inch*(pts) + 36) / 72) +#define EM (TROFF? EMPTS(pts): t.Em) +#define INCH (TROFF? Inch: 240) +#define HOR (TROFF? Hor: t.Adj) +#define VERT (TROFF? Vert: t.Vert) +#define PO (TROFF? Inch: 0) +#define SPS (TROFF? EMPTS(pts)/3: INCH/10) +#define SS (TROFF? 12: INCH/10) +#define ICS (TROFF? EMPTS(pts): 2*INCH/10) +#define DTAB (TROFF? (INCH/2): 0) + +/* These "characters" are used to encode various internal functions +/* Some make use of the fact that most ascii characters between +/* 0 and 040 don't have any graphic or other function. +/* The few that do have a purpose (e.g., \n, \b, \t, ... +/* are avoided by the ad hoc choices here. +/* See ifilt[] in n1.c for others -- 1, 2, 3, 5, 6, 7, 010, 011, 012 +*/ + +#define LEADER 001 +#define IMP 004 /* impossible char; glues things together */ +#define TAB 011 +#define RPT 014 /* next character is to be repeated many times */ +#define CHARHT 015 /* size field sets character height */ +#define SLANT 016 /* size field sets amount of slant */ +#define DRAWFCN 017 /* next several chars describe arb drawing fcns */ +# define DRAWLINE 'l' /* line: 'l' dx dy char */ +# define DRAWCIRCLE 'c' /* circle: 'c' r */ +# define DRAWELLIPSE 'e' /* ellipse: 'e' rx ry */ +# define DRAWARC 'a' /* arc: 'a' dx dy dx dy */ +# define DRAWSPLINE '~' /* quadratic B spline: '~' dx dy dx dy ... */ + /* other splines go thru too */ +/* NOTE: the use of ~ is a botch since it's often used in .tr commands */ +/* better to use a letter like s, but change it in the postprocessors too */ +/* for now, this is taken care of in n9.c and t10.c */ +# define DRAWBUILD 'b' /* built-up character (e.g., { */ + +#define LEFT 020 /* \{ */ +#define RIGHT 021 /* \} */ +#define FILLER 022 /* \& and similar purposes */ +#define XON 023 /* \X'...' starts here */ +#define OHC 024 /* optional hyphenation character \% */ +#define CONT 025 /* \c character */ +#define PRESC 026 /* printable escape */ +#define UNPAD 027 /* unpaddable blank */ +#define XPAR 030 /* transparent mode indicator */ +#define FLSS 031 /* next Tchar contains vertical space */ + /* used when recalling diverted text */ +#define WORDSP 032 /* paddable word space */ +#define ESC 033 /* current escape character */ +#define XOFF 034 /* \X'...' ends here */ + /* matches XON, but they will probably never nest */ + /* so could drop this when another control is needed */ +#define HX 035 /* next character is value of \x'...' */ +#define MOTCH 036 /* this "character" is really motion; used by cbits() */ + +#define HYPHEN c_hyphen +#define EMDASH c_emdash /* \(em */ +#define RULE c_rule /* \(ru */ +#define MINUS c_minus /* minus sign on current font */ +#define LIG_FI c_fi /* \(ff */ +#define LIG_FL c_fl /* \(fl */ +#define LIG_FF c_ff /* \(ff */ +#define LIG_FFI c_ffi /* \(Fi */ +#define LIG_FFL c_ffl /* \(Fl */ +#define ACUTE c_acute /* acute accent \(aa */ +#define GRAVE c_grave /* grave accent \(ga */ +#define UNDERLINE c_under /* \(ul */ +#define ROOTEN c_rooten /* root en \(rn */ +#define BOXRULE c_boxrule /* box rule \(br */ +#define LEFTHAND c_lefthand /* left hand for word overflow */ +#define DAGGER c_dagger /* dagger for end of sentence/footnote */ + +#define HYPHALG 1 /* hyphenation algorithm: 0=>good old troff, 1=>tex */ + + +/* array sizes, and similar limits: */ + +#define MAXFONTS 99 /* Maximum number of fonts in fontab */ +#define NM 90 /* requests + macros */ +#define NN NNAMES /* number registers */ +#define NNAMES 15 /* predefined reg names */ +#define NIF 15 /* if-else nesting */ +#define NS 128 /* name buffer */ +#define NTM 1024 /* tm buffer */ +#define NEV 3 /* environments */ +#define EVLSZ 10 /* size of ev stack */ + +#define STACKSIZE (6*1024) /* stack for macros and strings in progress */ +#define NHYP 10 /* max hyphens per word */ +#define NHEX 512 /* byte size of exception word list */ +#define NTAB 100 /* tab stops */ +#define NSO 5 /* "so" depth */ +#define NMF 5 /* number of -m flags */ +#define WDSIZE 500 /* word buffer click size */ +#define LNSIZE 4000 /* line buffer click size */ +#define OLNSIZE 5000 /* output line buffer click; bigger for 'w', etc. */ +#define NDI 5 /* number of diversions */ + +#define ALPHABET alphabet /* number of characters in basic alphabet. */ + /* 128 for parochial USA 7-bit ascii, */ + /* 256 for "European" mode with e.g., Latin-1 */ + + /* NCHARS must be greater than + ALPHABET (ascii stuff) + total number of distinct char names + from all fonts that will be run in this job (including + unnamed ones and \N's) + */ + +#define NCHARS (8*1024) /* maximum size of troff character set*/ + + + /* However for nroff you want only : + 1. number of special codes in charset of DESC, which ends up being the + value of nchtab and which must be less than 512. + 2. ALPHABET, which apparently is the size of the portion of the tables reserved + for special control symbols + Apparently the max N of \N is irrelevant; */ + /* to allow \N of up to 254 with up to 338 special characters + you need NCHARS of 338 + ALPHABET = 466 */ + +#define NROFFCHARS 1024 /* maximum size of nroff character set */ + +#define NTRTAB NCHARS /* number of items in trtab[] */ +#define NWIDCACHE NCHARS /* number of items in widcache[] */ + +#define NTRAP 20 /* number of traps */ +#define NPN 20 /* numbers in "-o" */ +#define FBUFSZ 512 /* field buf size words */ +#define IBUFSZ 4096 /* bytes */ +#define NC 1024 /* cbuf size words */ +#define NOV 10 /* number of overstrike chars */ +#define NPP 10 /* pads per field */ + +/* + Internal character representation: + Internally, every character is carried around as + a 32 bit cookie, called a "Tchar" (typedef long). + Bits are numbered 31..0 from left to right. + If bit 15 is 1, the character is motion, with + if bit 16 it's vertical motion + if bit 17 it's negative motion + If bit 15 is 0, the character is a real character. + if bit 31 zero motion + bits 30..24 size + bits 23..16 font +*/ + +/* in the following, "L" should really be a Tchar, but ... */ +/* numerology leaves room for 16 bit chars */ + +#define MOT (01uL << 16) /* motion character indicator */ +#define VMOT (01uL << 30) /* vertical motion bit */ +#define NMOT (01uL << 29) /* negative motion indicator */ +/* #define MOTV (MOT|VMOT|NMOT) /* motion flags */ +/* #define MAXMOT (~MOTV) /* maximum motion permitted */ +#define MAXMOT 0xFFFF + +#define ismot(n) ((n) & MOT) +#define isvmot(n) (((n) & (MOT|VMOT)) == (MOT|VMOT)) /* must have tested MOT previously */ +#define isnmot(n) (((n) & (MOT|NMOT)) == (MOT|NMOT)) /* ditto */ +#define absmot(n) ((n) & 0xFFFF) + +#define ZBIT (01uL << 31) /* zero width char */ +#define iszbit(n) ((n) & ZBIT) + +#define FSHIFT 17 +#define SSHIFT (FSHIFT+7) +#define SMASK (0177uL << SSHIFT) /* 128 distinct sizes */ +#define FMASK (0177uL << FSHIFT) /* 128 distinct fonts */ +#define SFMASK (SMASK|FMASK) /* size and font in a Tchar */ +#define sbits(n) (((n) >> SSHIFT) & 0177) +#define fbits(n) (((n) >> FSHIFT) & 0177) +#define sfbits(n) (((n) & SFMASK) >> FSHIFT) +#define cbits(n) ((n) & 0x1FFFF) /* isolate character bits, */ + /* but don't include motions */ +extern int realcbits(Tchar); + +#define setsbits(n,s) n = (n & ~SMASK) | (Tchar)(s) << SSHIFT +#define setfbits(n,f) n = (n & ~FMASK) | (Tchar)(f) << FSHIFT +#define setsfbits(n,sf) n = (n & ~SFMASK) | (Tchar)(sf) << FSHIFT +#define setcbits(n,c) n = (n & ~0xFFFFuL | (c)) /* set character bits */ + +#define BYTEMASK 0377 +#define BYTE 8 + +#define SHORTMASK 0XFFFF +#define SHORT 16 + +#define TABMASK ((unsigned) INT_MAX >> 1) +#define RTAB ((TABMASK << 1) & ~TABMASK) +#define CTAB (RTAB << 1) + +#define TABBIT 02 /* bits in gchtab */ +#define LDRBIT 04 +#define FCBIT 010 + +#define PAIR(A,B) (A|(B<<SHORT)) + + +extern int Inch, Hor, Vert, Unitwidth; + +struct Spnames +{ + int *n; + char *v; +}; + +extern Spnames spnames[]; + +/* + String and macro definitions are stored conceptually in a giant array + indexed by type Offset. In olden times, this array was real, and thus + both huge and limited in size, leading to the "Out of temp file space" + error. In this version, the array is represented by a list of blocks, + pointed to by blist[].bp. Each block is of size BLK Tchars, and BLK + MUST be a power of 2 for the macros below to work. + + The blocks associated with a particular string or macro are chained + together in the array blist[]. Each blist[i].nextoff contains the + Offset associated with the next block in the giant array, or -1 if + this is the last block in the chain. If .nextoff is 0, the block is + free. + + To find the right index in blist for an Offset, divide by BLK. +*/ + +#define NBLIST 2048 /* starting number of blocks in all definitions */ + +#define BLK 128 /* number of Tchars in a block; must be 2^N with defns below */ + +#define rbf0(o) (blist[bindex(o)].bp[boffset(o)]) +#define bindex(o) ((o) / BLK) +#define boffset(o) ((o) & (BLK-1)) +#define pastend(o) (((o) & (BLK-1)) == 0) +/* #define incoff(o) ( (++o & (BLK-1)) ? o : blist[bindex(o-1)].nextoff ) */ +#define incoff(o) ( (((o)+1) & (BLK-1)) ? o+1 : blist[bindex(o)].nextoff ) + +#define skipline(f) while (getc(f) != '\n') +#define is(s) (strcmp(cmd, s) == 0) +#define eq(s1, s2) (strcmp(s1, s2) == 0) + + +typedef unsigned long Offset; /* an offset in macro/string storage */ + +struct Blockp { /* info about a block: */ + Tchar *bp; /* the data */ + Offset nextoff; /* offset of next block in a chain */ +}; + +extern Blockp *blist; + +#define RD_OFFSET (1 * BLK) /* .rd command uses block 1 */ + +struct Diver { /* diversion */ + Offset op; + int dnl; + int dimac; + int ditrap; + int ditf; + int alss; + int blss; + int nls; + int mkline; + int maxl; + int hnl; + int curd; +}; + +struct Stack { /* stack frame */ + int nargs; + Stack *pframe; + Offset pip; + int pnchar; + Tchar prchar; + int ppendt; + Tchar pch; + Tchar *lastpbp; + int mname; +}; + +extern Stack s; + +struct Divsiz { + int dix; + int diy; +}; + +struct Contab { /* command or macro */ + unsigned int rq; + Contab *link; + void (*f)(void); + Offset mx; + Offset emx; + Divsiz *divsiz; +}; + +#define C(a,b) {a, 0, b, 0, 0} /* how to initialize a contab entry */ + +extern Contab contab[NM]; + +struct Numtab { /* number registers */ + unsigned int r; /* name */ + int val; + short fmt; + short inc; + Numtab *link; +}; + +extern Numtab numtab[NN]; + +#define PN 0 +#define NL 1 +#define YR 2 +#define HP 3 +#define CT 4 +#define DN 5 +#define MO 6 +#define DY 7 +#define DW 8 +#define LN 9 +#define DL 10 +#define ST 11 +#define SB 12 +#define CD 13 +#define PID 14 + +struct Wcache { /* width cache, indexed by character */ + short fontpts; + short width; +}; + +struct Tbuf { /* growable Tchar buffer */ + Tchar *_bufp; + unsigned int _size; +}; + +/* the infamous environment block */ + +#define ics envp->_ics +#define sps envp->_sps +#define spacesz envp->_spacesz +#define lss envp->_lss +#define lss1 envp->_lss1 +#define ll envp->_ll +#define ll1 envp->_ll1 +#define lt envp->_lt +#define lt1 envp->_lt1 +#define ic envp->_ic +#define icf envp->_icf +#define chbits envp->_chbits +#define spbits envp->_spbits +#define nmbits envp->_nmbits +#define apts envp->_apts +#define apts1 envp->_apts1 +#define pts envp->_pts +#define pts1 envp->_pts1 +#define font envp->_font +#define font1 envp->_font1 +#define ls envp->_ls +#define ls1 envp->_ls1 +#define ad envp->_ad +#define nms envp->_nms +#define ndf envp->_ndf +#define nmwid envp->_nmwid +#define fi envp->_fi +#define cc envp->_cc +#define c2 envp->_c2 +#define ohc envp->_ohc +#define tdelim envp->_tdelim +#define hyf envp->_hyf +#define hyoff envp->_hyoff +#define hyphalg envp->_hyphalg +#define un1 envp->_un1 +#define tabc envp->_tabc +#define dotc envp->_dotc +#define adsp envp->_adsp +#define adrem envp->_adrem +#define lastl envp->_lastl +#define nel envp->_nel +#define admod envp->_admod +#define wordp envp->_wordp +#define spflg envp->_spflg +#define linep envp->_linep +#define wdend envp->_wdend +#define wdstart envp->_wdstart +#define wne envp->_wne +#define ne envp->_ne +#define nc envp->_nc +#define nb envp->_nb +#define lnmod envp->_lnmod +#define nwd envp->_nwd +#define nn envp->_nn +#define ni envp->_ni +#define ul envp->_ul +#define cu envp->_cu +#define ce envp->_ce +#define in envp->_in +#define in1 envp->_in1 +#define un envp->_un +#define wch envp->_wch +#define pendt envp->_pendt +#define pendw envp->_pendw +#define pendnf envp->_pendnf +#define spread envp->_spread +#define it envp->_it +#define itmac envp->_itmac +#define hyptr envp->_hyptr +#define tabtab envp->_tabtab +#define line envp->_line._bufp +#define lnsize envp->_line._size +#define word envp->_word._bufp +#define wdsize envp->_word._size + +#define oline _oline._bufp +#define olnsize _oline._size + +/* + * Note: + * If this structure changes in ni.c, you must change + * this as well, and vice versa. + */ + +struct Env { + int _ics; + int _sps; + int _spacesz; + int _lss; + int _lss1; + int _ll; + int _ll1; + int _lt; + int _lt1; + Tchar _ic; + int _icf; + Tchar _chbits; + Tchar _spbits; + Tchar _nmbits; + int _apts; + int _apts1; + int _pts; + int _pts1; + int _font; + int _font1; + int _ls; + int _ls1; + int _ad; + int _nms; + int _ndf; + int _nmwid; + int _fi; + int _cc; + int _c2; + int _ohc; + int _tdelim; + int _hyf; + int _hyoff; + int _hyphalg; + int _un1; + int _tabc; + int _dotc; + int _adsp; + int _adrem; + int _lastl; + int _nel; + int _admod; + Tchar *_wordp; + int _spflg; + Tchar *_linep; + Tchar *_wdend; + Tchar *_wdstart; + int _wne; + int _ne; + int _nc; + int _nb; + int _lnmod; + int _nwd; + int _nn; + int _ni; + int _ul; + int _cu; + int _ce; + int _in; + int _in1; + int _un; + int _wch; + int _pendt; + Tchar *_pendw; + int _pendnf; + int _spread; + int _it; + int _itmac; + Tchar *_hyptr[NHYP]; + long _tabtab[NTAB]; + Tbuf _line; + Tbuf _word; +}; + +extern Env env[]; +extern Env *envp; + +enum { MBchar = 'U', Troffchar = 'C', Number = 'N', Install = 'i', Lookup = 'l' }; + /* U => utf, for instance; C => \(xx, N => \N'...' */ + + + +struct Chwid { /* data on one character */ + Ushort num; /* character number: + 0 -> not on this font + >= ALPHABET -> its number among all Cxy's */ + Ushort code; /* char code for actual device. used for \N */ + char *str; /* code string for nroff */ + Uchar wid; /* width */ + Uchar kern; /* ascender/descender */ +}; + +struct Font { /* characteristics of a font */ + int name; /* int name, e.g., BI (2 chars) */ + char longname[64]; /* long name of this font (e.g., "Bembo" */ + char *truename; /* path name of table if not in standard place */ + int nchars; /* number of width entries for this font */ + char specfont; /* 1 == special font */ + int spacewidth; /* width of space on this font */ + int defaultwidth; /* default width of characters on this font */ + Chwid *wp; /* widths, etc., of the real characters */ + char ligfont; /* 1 == ligatures exist on this font */ +}; + +/* ligatures, ORed into ligfont */ + +#define LFF 01 +#define LFI 02 +#define LFL 04 +#define LFFI 010 +#define LFFL 020 + +/* tracing modes */ +#define TRNARGS 01 /* trace legality of numeric arguments */ +#define TRREQ 02 /* trace requests */ +#define TRMAC 04 /* trace macros */ +#define RQERR 01 /* processing request/macro */ + +/* typewriter driving table structure */ + + +extern Term t; +struct Term { + int bset; /* these bits have to be on */ + int breset; /* these bits have to be off */ + int Hor; /* #units in minimum horiz motion */ + int Vert; /* #units in minimum vert motion */ + int Newline; /* #units in single line space */ + int Char; /* #units in character width */ + int Em; /* ditto */ + int Halfline; /* half line units */ + int Adj; /* minimum units for horizontal adjustment */ + char *twinit; /* initialize terminal */ + char *twrest; /* reinitialize terminal */ + char *twnl; /* terminal sequence for newline */ + char *hlr; /* half-line reverse */ + char *hlf; /* half-line forward */ + char *flr; /* full-line reverse */ + char *bdon; /* turn bold mode on */ + char *bdoff; /* turn bold mode off */ + char *iton; /* turn italic mode on */ + char *itoff; /* turn italic mode off */ + char *ploton; /* turn plot mode on */ + char *plotoff; /* turn plot mode off */ + char *up; /* sequence to move up in plot mode */ + char *down; /* ditto */ + char *right; /* ditto */ + char *left; /* ditto */ + + Font tfont; /* widths and other info, as in a troff font */ +}; + +extern Term t; + +/* + * for error reporting; keep track of escapes/requests with numeric arguments + */ +struct Numerr { + char type; /* request or escape? */ + char esc; /* was escape sequence named esc */ + char escarg; /* argument of esc's like \D'l' */ + unsigned int req; /* was request or macro named req */ +}; diff --git a/src/cmd/troff/unansi b/src/cmd/troff/unansi new file mode 100644 index 00000000..67aed817 --- /dev/null +++ b/src/cmd/troff/unansi @@ -0,0 +1,49 @@ +# The awk program cvt will convert the relatively sterotyped ansi c +# in this troff distribution into older-style c, by munging function +# declarations. + +# You will also have to edit fns.h, by +# sed 's/(.*)/()/g' fns.h >foo; mv foo fns.h +# check this before doing the move! + +# you will also have to make some editing changes in +# tdef.h in the Contab structure: s/(void)/()/ +# you may have to fix up some function declarations +# in n4.c, the ones with (*f)(Tchar). + +# you will surely also have header files to deal with. + +# the most obvious cases are dealt with by the following +# commands. make sure you do this stuff on a copy! + +# function prototypes in n8.c probably belong in fns.h. readpats(void) must +# be readpats() before cvt runs. + +sed \ + -e 's/(void)/()/' \ + -e 's/(Tchar[^)]*);/();/' \ + -e 's/(char[^)]*);/();/' \ + -e 's/(int[^)]*);/();/' \ +n8.c >foo +mv foo n8.c + +for i in *.c +do + cvt $i >foo + mv foo $i +done + +sed 's/(.*)/()/g' fns.h >foo +mv foo fns.h + +sed -e 's/(void)/()/g' -e '/stdlib/d' tdef.h >foo +mv foo tdef.h + +# Compliers may not approve of void *setbrk() in fns.h and n3.c. + +sed 's/^void\*[ ]setbrk/char* setbrk/' fns.h >foo +mv foo fns.h + +sed 's/^void \*setbrk/char *setbrk/' n3.c >foo +mv foo n3.c + |