home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / os / minix / 5041 < prev    next >
Encoding:
Text File  |  1993-01-03  |  28.5 KB  |  1,505 lines

  1. Newsgroups: comp.os.minix
  2. Path: sparky!uunet!mcsun!sun4nl!star.cs.vu.nl!ast
  3. From: ast@cs.vu.nl (Andy Tanenbaum)
  4. Subject: Re: Unpacking 1.6.24b/commands.sh.Z
  5. Message-ID: <C0A96n.IxF@cs.vu.nl>
  6. Sender: news@cs.vu.nl
  7. Organization: Fac. Wiskunde & Informatica, VU, Amsterdam
  8. References: <1993Jan3.033135.9210@runx.oz.au>
  9. Date: Sun, 3 Jan 1993 14:49:35 GMT
  10. Lines: 1493
  11.  
  12. In article <1993Jan3.033135.9210@runx.oz.au> bde@runx.oz.au (Bruce Evans) writes:
  13. >The commands packaging has a few bugs.
  14. >
  15. >1. hypenate.c contains some German characters (>= 128) in a comment.  
  16. Indeed it does.  I fixed it (see below) and replaced commands.sh.Z in the FTP
  17. directory.
  18.  
  19. Andy Tanenbaum (ast@cs.vu.nl)
  20.  
  21. /* Hyphenate English text for mroff    Author: Alan I. Holub */
  22.  
  23. /* This filter reads English text and ouputs it with \% at reasonable
  24.  * places to hyphenate words.  It is normally used as an mroff preprocessor.
  25.  * The original algorithm is due to Donald Knuth.  The program itself
  26.  * came with Michael Haardt's mroff package.
  27.  */
  28.  
  29. #include <ctype.h>
  30. #include <string.h>
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33.  
  34. typedef enum { FALSE, TRUE} bool;
  35.  
  36. #define PRIVATE static
  37. #define PUBLIC
  38.  
  39. #define HYPHEN          0x80
  40. #define HYPHENATE(c)    ( (c) |=  HYPHEN )
  41. #define UNHYPHENATE(c)  ( (c) &= ~HYPHEN )
  42. #define HAS_HYPHEN(c)   ( (c) &   HYPHEN )
  43.  
  44. char **States;
  45. extern char *Suffixes[];
  46. extern char *Prefixes[];
  47.  
  48. #define ER(p,end) ((* p & 0x7f)=='e' && (*(p+1) & 0x7f) == 'r' && (p+1) == end)
  49.  
  50. #define CH ('z' + 1 )        /* {   0x7b  \173    */
  51. #define GH ('z' + 2 )        /* |   0x7c  \174    */
  52. #define PH ('z' + 3 )        /* }   0x7d  \175    */
  53. #define SH ('z' + 4 )        /* ~   0x7e  \176    */
  54. #define TH ('z' + 5 )        /* DEL   0x7f  \177    */
  55.  
  56. /* a b c d e f g h i j k l m n o p q r s t u v w x y z */
  57. char vt[] = {1,0,0,0,1,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0};
  58.  
  59. #define isvowel(c)  ( islower((c) & 0x7f)  &&  vt[ ((c) & 0x7f) - 'a'] )
  60. #define isconsonant(c)  ((c) && !isvowel(c))
  61.  
  62. typedef struct
  63. {
  64.   char arg, type;
  65.   void *variable;
  66. } ARG;
  67.  
  68.  
  69. _PROTOTYPE(char *suffix, (char *beg, char *end ));
  70. _PROTOTYPE(char *prefix, (char *beg, char *end ));
  71. _PROTOTYPE(PRIVATE char nextch, (char **pp, char *endp ));
  72. _PROTOTYPE(int isweird, (int x, int y, char *p ));
  73. _PROTOTYPE(void consonants, (char *beg, char *end ));
  74. _PROTOTYPE(int hyphen, (char *beg, char *end ));
  75. _PROTOTYPE(PRIVATE int next, (int cur_state, int cur_char ));
  76. _PROTOTYPE(int S, (int s0 ));
  77. _PROTOTYPE(int S, (int s1 ));
  78. _PROTOTYPE(int S, (int s2 ));
  79. _PROTOTYPE(int S, (int s3 ));
  80. _PROTOTYPE(int S, (int s4 ));
  81. _PROTOTYPE(int S, (int s5 ));
  82. _PROTOTYPE(int S, (int s6 ));
  83. _PROTOTYPE(int S, (int s7 ));
  84. _PROTOTYPE(int S, (int s8 ));
  85. _PROTOTYPE(int S, (int s9 ));
  86. _PROTOTYPE(int S, (int s10 ));
  87. _PROTOTYPE(int S, (int s11 ));
  88. _PROTOTYPE(int S, (int s12 ));
  89. _PROTOTYPE(int S, (int s13 ));
  90. _PROTOTYPE(int S, (int s14 ));
  91. _PROTOTYPE(int S, (int s15 ));
  92. _PROTOTYPE(int S, (int s16 ));
  93. _PROTOTYPE(int S, (int s17 ));
  94. _PROTOTYPE(int S, (int s18 ));
  95. _PROTOTYPE(int S, (int s19 ));
  96. _PROTOTYPE(int S, (int s20 ));
  97. _PROTOTYPE(int S, (int s21 ));
  98. _PROTOTYPE(int S, (int s22 ));
  99. _PROTOTYPE(int S, (int s23 ));
  100. _PROTOTYPE(int S, (int s24 ));
  101. _PROTOTYPE(int S, (int s25 ));
  102. _PROTOTYPE(int S, (int s26 ));
  103. _PROTOTYPE(int S, (int s27 ));
  104. _PROTOTYPE(int S, (int s28 ));
  105. _PROTOTYPE(int S, (int s29 ));
  106. _PROTOTYPE(int S, (int s30 ));
  107. _PROTOTYPE(int S, (int s31 ));
  108. _PROTOTYPE(int S, (int s32 ));
  109. _PROTOTYPE(int S, (int s33 ));
  110. _PROTOTYPE(int S, (int s34 ));
  111. _PROTOTYPE(int S, (int s35 ));
  112. _PROTOTYPE(int S, (int s36 ));
  113. _PROTOTYPE(int S, (int s37 ));
  114. _PROTOTYPE(int S, (int s38 ));
  115. _PROTOTYPE(int S, (int s39 ));
  116. _PROTOTYPE(int S, (int s40 ));
  117. _PROTOTYPE(int S, (int s41 ));
  118. _PROTOTYPE(int S, (int s42 ));
  119. _PROTOTYPE(int S, (int s43 ));
  120. _PROTOTYPE(int S, (int s44 ));
  121. _PROTOTYPE(int S, (int s45 ));
  122. _PROTOTYPE(int S, (int s46 ));
  123. _PROTOTYPE(int S, (int s47 ));
  124. _PROTOTYPE(int S, (int s48 ));
  125. _PROTOTYPE(int S, (int s49 ));
  126. _PROTOTYPE(int S, (int s50 ));
  127. _PROTOTYPE(int S, (int s51 ));
  128. _PROTOTYPE(int S, (int s52 ));
  129. _PROTOTYPE(int S, (int s53 ));
  130. _PROTOTYPE(int S, (int s54 ));
  131. _PROTOTYPE(int S, (int s55 ));
  132. _PROTOTYPE(int S, (int p0 ));
  133. _PROTOTYPE(int S, (int p1 ));
  134. _PROTOTYPE(int S, (int p2 ));
  135. _PROTOTYPE(int S, (int p3 ));
  136. _PROTOTYPE(int S, (int p4 ));
  137. _PROTOTYPE(int S, (int p5 ));
  138. _PROTOTYPE(int S, (int p6 ));
  139. _PROTOTYPE(int S, (int p7 ));
  140. _PROTOTYPE(int S, (int p8 ));
  141. _PROTOTYPE(int S, (int p9 ));
  142. _PROTOTYPE(int S, (int p10 ));
  143. _PROTOTYPE(int S, (int p11 ));
  144. _PROTOTYPE(int S, (int p12 ));
  145. _PROTOTYPE(int S, (int p13 ));
  146. _PROTOTYPE(int S, (int p14 ));
  147. _PROTOTYPE(int S, (int p15 ));
  148. _PROTOTYPE(int S, (int p16 ));
  149. _PROTOTYPE(int S, (int p17 ));
  150. _PROTOTYPE(int S, (int p18 ));
  151. _PROTOTYPE(int S, (int p19 ));
  152. _PROTOTYPE(int S, (int p20 ));
  153. _PROTOTYPE(int S, (int p21 ));
  154. _PROTOTYPE(int S, (int p22 ));
  155. _PROTOTYPE(int S, (int p23 ));
  156. _PROTOTYPE(int S, (int p24 ));
  157. _PROTOTYPE(int S, (int p25 ));
  158. _PROTOTYPE(int S, (int p26 ));
  159. _PROTOTYPE(int S, (int p27 ));
  160. _PROTOTYPE(int S, (int p28 ));
  161. _PROTOTYPE(int S, (int p29 ));
  162. _PROTOTYPE(int S, (int p30 ));
  163. _PROTOTYPE(int S, (int p31 ));
  164. _PROTOTYPE(int S, (int p32 ));
  165. _PROTOTYPE(int S, (int p33 ));
  166. _PROTOTYPE(int S, (int p34 ));
  167. _PROTOTYPE(int S, (int p35 ));
  168. _PROTOTYPE(int S, (int p36 ));
  169. _PROTOTYPE(int S, (int p37 ));
  170. _PROTOTYPE(int S, (int p38 ));
  171. _PROTOTYPE(int S, (int p39 ));
  172. _PROTOTYPE(int S, (int p40 ));
  173. _PROTOTYPE(int S, (int p41 ));
  174. _PROTOTYPE(int S, (int p42 ));
  175. _PROTOTYPE(int S, (int p43 ));
  176. _PROTOTYPE(int S, (int p44 ));
  177. _PROTOTYPE(int S, (int p45 ));
  178. _PROTOTYPE(int S, (int p46 ));
  179. _PROTOTYPE(int S, (int p47 ));
  180. _PROTOTYPE(int S, (int p48 ));
  181. _PROTOTYPE(int S, (int p49 ));
  182. _PROTOTYPE(int S, (int p50 ));
  183. _PROTOTYPE(int S, (int p51 ));
  184. _PROTOTYPE(int S, (int p52 ));
  185. _PROTOTYPE(int S, (int p53 ));
  186. _PROTOTYPE(int S, (int p54 ));
  187. _PROTOTYPE(int S, (int p55 ));
  188. _PROTOTYPE(int S, (int p56 ));
  189. _PROTOTYPE(int S, (int p57 ));
  190. _PROTOTYPE(int S, (int p58 ));
  191. _PROTOTYPE(int S, (int p59 ));
  192. _PROTOTYPE(int S, (int p60 ));
  193. _PROTOTYPE(int S, (int p61 ));
  194. _PROTOTYPE(int S, (int p62 ));
  195. _PROTOTYPE(int S, (int p63 ));
  196. _PROTOTYPE(int S, (int p64 ));
  197. _PROTOTYPE(int S, (int p65 ));
  198. _PROTOTYPE(int S, (int p66 ));
  199. _PROTOTYPE(int S, (int p67 ));
  200. _PROTOTYPE(int S, (int p68 ));
  201. _PROTOTYPE(int S, (int p69 ));
  202. _PROTOTYPE(int S, (int p70 ));
  203. _PROTOTYPE(bool process_word, (char *w ));
  204. _PROTOTYPE(int wcmp, (char *word, char **tabp ));
  205. _PROTOTYPE(int exception, (char *word, char *end ));
  206. _PROTOTYPE(char *setarg, (ARG *argp, char *linep ));
  207. _PROTOTYPE(ARG *findarg, (int c, ARG *tabp, int tabsize ));
  208. _PROTOTYPE(int argparse, (int argc, char **argv, ARG *tabp, int tabsize ));
  209. _PROTOTYPE(void fail, (char *word ));
  210. _PROTOTYPE(void outtext, (int c ));
  211. _PROTOTYPE(void outspec, (int c ));
  212. _PROTOTYPE(int nextchar, (void));
  213. _PROTOTYPE(int escapeseq, (void));
  214. _PROTOTYPE(void nonletter, (void));
  215. _PROTOTYPE(int special, (void));
  216. _PROTOTYPE(int letter, (void));
  217. _PROTOTYPE(void word, (void));
  218. _PROTOTYPE(void words, (void));
  219. _PROTOTYPE(int macro, (void));
  220. _PROTOTYPE(void line, (void));
  221. _PROTOTYPE(void text, (FILE *fd ));
  222. _PROTOTYPE(int main, (int argc, char *argv []));
  223.  
  224.  
  225. char *suffix(beg, end)
  226. char *beg, *end;
  227. {
  228.   register char *p, c, c2;
  229.   register unsigned int state, times;
  230.  
  231.   state = 1;
  232.   times = 0;
  233.   States = Suffixes;
  234.  
  235.   for (p = end; p >= beg;) {
  236.     state = next(state, c = *p-- & 0x7f);
  237.  
  238.     if (!('a' <= c && c <= 'z'))    /* Worter mit Grossbuch-  */
  239.         return end;    /* staben werden nicht   */
  240.  
  241.     if (state == 0) {
  242.         if (times == 0)
  243.             p = end;    /* entferne endendes e,d */
  244.         else if (times == 1)    /* entf. endendes ed, de */
  245.             p = end - 1;    /* ee oder dd            */
  246.         else
  247.             return end;
  248.  
  249.         times++;
  250.     }
  251.     switch (state) {
  252.         case 86:
  253.         c = *p & 0x7f;
  254.         c2 = *(p - 1) & 0x7f;
  255.  
  256.         if (p - beg < 3) return end;    /* FAIL */
  257.         else if ((c == c2) && (!isvowel(c))
  258.              && (c != 'f') && (c != 's')
  259.              && (c != 'l') && (c != 'z')) {
  260.             --p;
  261.         } else if (c == 'l' && strchr("bcdfghkptz", c2)) {
  262.             p -= (c2 == 'k' && (*(p - 2) & 0x7f) == 'c')
  263.                 ? 1 : 2;
  264.         }
  265.  
  266.         case 87:
  267.         HYPHENATE(*(p + 1));
  268.         return p;
  269.  
  270.         case 88:
  271.         HYPHENATE(*(p + 2));
  272.         return(p + 1);
  273.  
  274.         case 89:
  275.         HYPHENATE(*(p + 5));
  276.         HYPHENATE(*(p + 1));
  277.         return p;
  278.  
  279.         case 82:
  280.         p++;        /* p += 3 */
  281.         case 81:
  282.         p++;        /* p += 2 */
  283.         case 80:
  284.         p++;        /* P += 1 */
  285.         case 83:
  286.         end = p;
  287.         HYPHENATE(*(p + 1));
  288.         state = 1;
  289.         break;
  290.  
  291.         case 84:        /* Fehl-Status */
  292.         return end;
  293.     }
  294.   }
  295.  
  296.   return end;
  297. }
  298. char *prefix(beg, end)
  299. char *beg, *end;
  300. {
  301.  
  302.   register char *p, c;
  303.   register int state;
  304.  
  305.   state = 1;
  306.   States = Prefixes;
  307.  
  308.   for (p = beg; p < end;) {
  309.     switch (state = next(state, c = *p++ & 0x7f)) {
  310.         case 82:
  311.         HYPHENATE(*p);
  312.         HYPHENATE(*(p - 1));
  313.         return p;
  314.         case 83:
  315.         HYPHENATE(*p);
  316.         HYPHENATE(*(p - 2));
  317.         return p;
  318.         case 84:
  319.         HYPHENATE(*p);
  320.         HYPHENATE(*(p - 3));
  321.         return p;
  322.  
  323.         case 81:
  324.         --p;
  325.         case 87:
  326.         HYPHENATE(*p);
  327.         return p;
  328.  
  329.         case 85:
  330.         --p;
  331.         case 86:
  332.         beg = p;
  333.         state = 1;
  334.         case 69:    HYPHENATE(*p);    break;
  335.  
  336.         case 70:    HYPHENATE(*(p - 1));    break;
  337.         case 71:
  338.         case 72:
  339.         case 73:
  340.         case 74:
  341.         case 75:
  342.         case 76:
  343.         case 77:
  344.         case 78:    case 79:    break;
  345.     }
  346.   }
  347.  
  348.   return beg;
  349. }
  350.  
  351. char *vccv_except[] =
  352. {
  353.   /* A  */ "",
  354.   /* B  */ "lr",
  355.   /* C  */ "lr",
  356.   /* D  */ "gr",
  357.   /* E  */ "",
  358.   /* F  */ "lr",
  359.   /* G  */ "lr",
  360.   /* H  */ "",
  361.   /* I  */ "",
  362.   /* J  */ "",
  363.   /* K  */ "n",
  364.   /* L  */ "kq",
  365.   /* M  */ "",
  366.   /* N  */ "{kx",        /* CH, k, x */
  367.   /* O  */ "",
  368.   /* P  */ "lr",
  369.   /* Q  */ "",
  370.   /* R  */ "k",
  371.   /* S  */ "pq",
  372.   /* T  */ "{r",        /* CH, r    */
  373.   /* U  */ "",
  374.   /* V  */ "",
  375.   /* W  */ "hlnr",
  376.   /* X  */ "",
  377.   /* Y  */ "",
  378.   /* Z  */ "",
  379.   /* CH */ "lr",
  380.   /* GH */ "t",
  381.   /* PH */ "r",
  382.   /* SH */ "",
  383.   /* TH */ "r"
  384. };
  385. PRIVATE char nextch(pp, endp)
  386. char **pp, *endp;
  387. {
  388.  
  389.   register char rval, *p;
  390.  
  391.   if ((p = *pp) > endp) return(char) 0;
  392.  
  393.   rval = *p++ & 0x7f;
  394.  
  395.   if ((*p & 0x7f) == 'h') {
  396.     switch ((int) rval) {
  397.         case 't':
  398.         rval = TH;
  399.         p++;
  400.         break;
  401.         case 's':
  402.         rval = SH;
  403.         p++;
  404.         break;
  405.         case 'p':
  406.         rval = PH;
  407.         p++;
  408.         break;
  409.         case 'c':
  410.         rval = CH;
  411.         p++;
  412.         break;
  413.         case 'g':
  414.         rval = GH;
  415.         p++;
  416.         break;
  417.     }
  418.   }
  419.   *pp = p;
  420.   return rval;
  421. }
  422. isweird(x, y, p)
  423. char x, y, *p;
  424. {
  425.  
  426.   register unsigned int c1, c2, c3;
  427.  
  428.   c1 = *p++ & 0x7f;
  429.   c2 = *p++ & 0x7f;
  430.   c3 = *p & 0x7f;
  431.  
  432.   x &= 0x7f;
  433.   y &= 0x7f;
  434.  
  435.   return(
  436.     (
  437.      (c1 == 'e' && c2 == 'r')
  438.      || (c1 == 'a' && c2 == 'g' && c3 == 'e')
  439.      || (c1 == 'e' && c2 == 's' && c3 == 't')
  440.      )
  441.     &&
  442.     ((x == 'f' && y == 't')
  443.      || (x == 'l' && y == 'd')
  444.      || (x == 'm' && y == 'p')
  445.      || (x == 's' && y == 't')
  446.      || (x == 'n' && strchr("dgst", (int) (y & 0x7f)))
  447.      || (x == 'r' && strchr("gmnt", (int) (y & 0x7f)))
  448.      )
  449.     );
  450. }
  451. void consonants(beg, end)
  452. char *beg, *end;
  453. {
  454.  
  455.   register char c1, c2, *cp;
  456.   register char *p;
  457.  
  458.   while (1) {
  459. state1:
  460.  
  461.     do {
  462.         c2 = nextch(&beg, end);
  463.     } while (isconsonant(c2));
  464.  
  465.     do {
  466.         for (c1 = c2; isvowel(c1);) {
  467.             cp = beg;
  468.             c1 = nextch(&beg, end);
  469.         }
  470.  
  471.  
  472.         if (c1 == 'q' && *beg == 'u') {    /* Vqu */
  473.             HYPHENATE(*cp);    /* V-qu */
  474.             nextch(&beg, end);    /* uberspringe u */
  475.             goto state1;
  476.         }
  477.         cp = beg;
  478.         c2 = nextch(&beg, end);
  479.  
  480.     } while (isvowel(c2));
  481.  
  482.     if (!c1 || !c2) break;
  483.  
  484.     if (c1 == 'c' && c2 == 'k') {    /* Vck  */
  485.         if (*beg) HYPHENATE(*beg);    /* Vck- */
  486.     } else if (c1 == c2) {    /* ller(s) */
  487.         if ((c1 != 'l' && c1 != 's') ||
  488.             (isvowel(*beg) && !ER(beg, end)))
  489.             HYPHENATE(*cp);
  490.     } else if (isvowel(*beg)) {    /* VCCV */
  491.         if (!isweird(c1, c2, beg)) {
  492.             if (!((p = vccv_except[(int) c1 - 'a'])
  493.                   && strchr(p, (int) c2)))
  494.                 HYPHENATE(*cp);
  495.         }
  496.     }
  497.   }
  498.  
  499.   UNHYPHENATE(*end);
  500. }
  501.  
  502. hyphen(beg, end)
  503. char *beg, *end;
  504. {
  505.  
  506.   register char *prefixp, *suffixp;
  507.   char *p;
  508.   int c;
  509.  
  510.   if (end - beg <= 4) return 0;
  511.  
  512.   for (prefixp = beg; prefixp <= end; prefixp++) {
  513.     if (HAS_HYPHEN(*prefixp)) return 1;
  514.  
  515.     if (!islower(*prefixp)) return 0;
  516.   }
  517.  
  518.   if (exception(beg, end)) return 1;
  519.  
  520.   suffixp = suffix(beg, end);    /* Trenne und entferne alle     */
  521.   /* Endungen (Suffixe)           */
  522.   if (suffixp == end) {
  523.     c = *end & 0x7f;
  524.  
  525.     if (c == 's' || c == 'e') suffixp = end - 1;
  526.  
  527.     else if ((*(end - 1) & 0x7f) == 'e' && c == 'd')
  528.         suffixp = end - 2;
  529.   }
  530.   prefixp = prefix(beg, suffixp);    /* Trenne und entferne alle */
  531.   /* Vorsilben (Prafixe)      */
  532.  
  533.   if ((suffixp - prefixp) >= 3) {
  534.     /* Die Anwendung der Konsonantenpaar-Regel findet nur auf
  535.      * Worter mit mindestens 4 Buchsten statt (nachdem Vor- und
  536.      * Nachsilben entfernt wurden) */
  537.  
  538.     consonants(prefixp, suffixp);
  539.   }
  540.   return 1;
  541. }
  542. PRIVATE int next(cur_state, cur_char)
  543. char cur_char;
  544. int cur_state;
  545. {
  546.   char *p = States[cur_state];
  547.   int rval, i, c;
  548.  
  549.   c = cur_char & 0x7f;
  550.  
  551.  
  552.   if (!*p)
  553.     rval = (int) (p[(c - 'a') + 1]);
  554.   else {
  555.     for (rval = 0, i = *p++; --i >= 0; p += 2)
  556.         if (c == p[0]) {
  557.             rval = p[1];
  558.             break;
  559.         }
  560.   }
  561.  
  562.  
  563.   return(rval);
  564. }
  565.  
  566. #define S(x)  char x[]
  567.  
  568. S(s0) =
  569. {0,84,84,84,1,1,84,84,84,84,84,84,84,84,84,84,84,84,84,1,84,84,84,84,84,84,84};
  570.  
  571. S(s1) = {0,0,0,2,0,7,0,21,0,0,0,0,23,0,30,0,0,0,33,38,45,0,0,0,0,49,0};
  572. S(s2) ={  1, 'i', 3};
  573. S(s3) ={  1, 'p', 4};
  574. S(s4) ={  1, 'o', 5};
  575. S(s5) ={  1, 'c', 6};
  576. S(s6) ={  1, 's', 87};
  577. S(s7) ={0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,4,0,10,0,16,0,15,0,0,0,19};
  578. S(s8) ={  1, 'b', 9};
  579. S(s9) ={  1, 'a', 55};
  580. S(s10) ={  2, 'e', 11, 'u', 14};
  581. S(s11) ={  1, 'h', 12};
  582. S(s12) ={  1, 'p', 6};
  583. S(s13) ={  2, 'n', 81, 'r', 81};
  584. S(s14) ={  1, 't', 87};
  585. S(s15) ={  1, 'i', 14};
  586. S(s16) ={  1, 'a', 17};
  587. S(s17) ={  2, 'c', 18, 'l', 18};
  588. S(s18) ={0,88,0,0,0,88,0,0,0,88,0,0,0,0,0,88,0,0,0,0,0,88,0,0,0,88,0};
  589. S(s19) ={  1, 'i', 20};
  590. S(s20) ={  1, 'l', 80};
  591. S(s21) ={  1, 'n', 22};
  592. S(s22) ={  1, 'i', 86};
  593. S(s23) ={  2, 'a', 25, 'u', 24};
  594. S(s24) ={  1, 'f', 83};
  595. S(s25) ={0,0,0,87,0,0,0,0,0,26,0,0,0,0,27,0,0,0,0,0,87,0,0,0,0,0,0};
  596. S(s26) ={  2, 't', 87, 'c', 87};
  597. S(s27) ={  1, 'o', 28};
  598. S(s28) ={  1, 'i', 29};
  599. S(s29) ={  1, 't', 89};
  600. S(s30) ={  1, 'o', 31};
  601. S(s31) ={  1, 'i', 32};
  602. S(s32) ={  2, 't', 87, 'c', 6};
  603. S(s33) ={  1, 'e', 34};
  604. S(s34) ={  1, 'h', 35};
  605. S(s35) ={  1, 'p', 36};
  606. S(s36) ={  1, 'a', 37};
  607. S(s37) ={  1, 'r', 87};
  608. S(s38) ={  2, 's', 39, 'u', 41};
  609. S(s39) ={  1, 'e', 40};
  610. S(s40) ={  2, 'l', 83, 'n', 83};
  611. S(s41) ={  1, 'o', 42};
  612. S(s42) ={  1, 'i', 43};
  613. S(s43) ={  1, 'c', 44};
  614. S(s44)={0,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,88,87,
  615.                             88,88,88,88,88,88,88};
  616. S(s45) ={  1, 'n', 46};
  617. S(s46) ={  1, 'e', 47};
  618. S(s47)={0,0,0,0,87,0,0,0,0,48,0,0,0,83,0,0,0,0,0,0,0,0,0,0,0,0,0};
  619. S(s48) ={  1, 'c', 87};
  620. S(s49)={0,0,0,0,0,0,0,50,35,0,0,0,83,0,0,0,0,0,51,0,0,0,0,0,0,0,0};
  621. S(s50) ={  1, 'o', 87};
  622. S(s51) ={  1, 'a', 52};
  623. S(s52) ={  1, 'n', 53};
  624. S(s53)={0,88,88,88,88,81,88,88,88,88,88,88,88,88,88,54,88,88,
  625.                         88,88,88,88,88,88,88,88,88};
  626. S(s54) ={  1, 'i', 82};
  627. S(s55)={0,0,0,0,0,80,0,0,80,80,0,80,80,0,0,80,0,0,0,0,13,80,80,80,80,80,0};
  628.  
  629.  
  630. char *Suffixes[] =
  631. {
  632.  s0, s1, s2, s3, s4, s5, s6, s7, s8, s9,
  633.  s10, s11, s12, s13, s14, s15, s16, s17, s18, s19,
  634.  s20, s21, s22, s23, s24, s25, s26, s27, s28, s29,
  635.  s30, s31, s32, s33, s34, s35, s36, s37, s38, s39,
  636.  s40, s41, s42, s43, s44, s45, s46, s47, s48, s49,
  637.  s50, s51, s52, s53, s54, s55
  638. };
  639. S(p0) =
  640. {
  641.   1, 0, 0
  642. };
  643.  
  644. S(p1) =
  645. {
  646.   0, 0, 2, 4, 6, 9, 0, 0, 13, 22, 0, 0, 26, 29, 39, 41, 45, 50, 0, 53, 57, 64,
  647.     0, 0, 0, 0, 0
  648. };
  649.  
  650. S(p2) =
  651. {
  652.   1, 'e', 3
  653. };
  654.  
  655. S(p3) =
  656. {
  657.   0, 0, 0, 81, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 81, 0, 0, 0
  658. };
  659.  
  660. S(p4) =
  661. {
  662.   1, 'o', 5
  663. };
  664.  
  665. S(p5) =
  666. {
  667.   2, 'm', 87, 'n', 87
  668. };
  669.  
  670. S(p6) =
  671. {
  672.   1, 'i', 7
  673. };
  674.  
  675. S(p7) =
  676. {
  677.   1, 's', 8
  678. };
  679.  
  680. S(p8) =
  681. {
  682.   0, 85, 85, 85, 85, 85, 85, 85, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  683.     85, 85, 85, 85, 0, 85
  684. };
  685.  
  686. S(p9) =
  687. {
  688.   2, 'q', 10, 'x', 87
  689. };
  690.  
  691. S(p10) =
  692. {
  693.   1, 'u', 11
  694. };
  695.  
  696. S(p11) =
  697. {
  698.   1, 'i', 12
  699. };
  700.  
  701. S(p12) =
  702. {
  703.   0, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, 81,
  704.     81, 0, 81, 81, 81, 81
  705. };
  706.  
  707. S(p13) =
  708. {
  709.   0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 0
  710. };
  711.  
  712. S(p14) =
  713. {
  714.   1, 'n', 15
  715. };
  716.  
  717. S(p15) =
  718. {
  719.   1, 'd', 87
  720. };
  721.  
  722. S(p16) =
  723. {
  724.   1, 'r', 17
  725. };
  726.  
  727. S(p17) =
  728. {
  729.   1, 's', 18
  730. };
  731.  
  732. S(p18) =
  733. {
  734.   1, 'e', 87
  735. };
  736.  
  737. S(p19) =
  738. {
  739.   1, 'p', 20
  740. };
  741.  
  742. S(p20) =
  743. {
  744.   1, 'e', 21
  745. };
  746.  
  747. S(p21) =
  748. {
  749.   1, 'r', 84
  750. };
  751.  
  752. S(p22) =
  753. {
  754.   2, 'n', 69, 'm', 86
  755. };
  756.  
  757. S(p23) =
  758. {
  759.   0, 81, 0, 0, 0, 0, 81, 81, 0, 0, 0, 0, 81, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  760. };
  761.  
  762. S(p24) =
  763. {
  764.   2, 'e', 21, 'r', 25
  765. };
  766.  
  767. S(p25) =
  768. {
  769.   1, 'o', 87
  770. };
  771.  
  772. S(p26) =
  773. {
  774.   1, 'e', 27
  775. };
  776.  
  777. S(p27) =
  778. {
  779.   1, 'x', 35
  780. };
  781.  
  782. S(p28) =
  783. {
  784.   1, 'i', 87
  785. };
  786.  
  787. S(p29) =
  788. {
  789.   0, 30, 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0
  790. };
  791.  
  792. S(p30) =
  793. {
  794.   0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 35, 0, 0
  795. };
  796.  
  797. S(p31) =
  798. {
  799.   1, 'r', 32
  800. };
  801.  
  802. S(p32) =
  803. {
  804.   1, 'o', 83
  805. };
  806.  
  807. S(p33) =
  808. {
  809.   1, 'h', 34
  810. };
  811.  
  812. S(p34) =
  813. {
  814.   1, 'e', 82
  815. };
  816.  
  817. S(p35) =
  818. {
  819.   1, 'i', 82
  820. };
  821.  
  822. S(p36) =
  823. {
  824.   1, 'n', 35
  825. };
  826.  
  827. S(p37) =
  828. {
  829.   1, 'l', 38
  830. };
  831.  
  832. S(p38) =
  833. {
  834.   1, 't', 65
  835. };
  836.  
  837. S(p39) =
  838. {
  839.   1, 'o', 40
  840. };
  841.  
  842. S(p40) =
  843. {
  844.   1, 'n', 86
  845. };
  846.  
  847. S(p41) =
  848. {
  849.   2, 'u', 42, 'v', 43
  850. };
  851.  
  852. S(p42) =
  853. {
  854.   1, 't', 87
  855. };
  856.  
  857. S(p43) =
  858. {
  859.   1, 'e', 44
  860. };
  861.  
  862. S(p44) =
  863. {
  864.   1, 'r', 86
  865. };
  866.  
  867. S(p45) =
  868. {
  869.   1, 's', 46
  870. };
  871.  
  872. S(p46) =
  873. {
  874.   1, 'e', 47
  875. };
  876.  
  877. S(p47) =
  878. {
  879.   1, 'u', 48
  880. };
  881.  
  882. S(p48) =
  883. {
  884.   1, 'd', 49
  885. };
  886.  
  887. S(p49) =
  888. {
  889.   1, 'o', 83
  890. };
  891.  
  892. S(p50) =
  893. {
  894.   1, 'u', 51
  895. };
  896.  
  897. S(p51) =
  898. {
  899.   1, 'a', 52
  900. };
  901.  
  902. S(p52) =
  903. {
  904.   1, 'd', 87
  905. };
  906.  
  907. S(p53) =
  908. {
  909.   0, 0, 0, 0, 0, 54, 0, 0, 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, 0, 0, 56, 0, 0, 0, 0, 0
  910. };
  911.  
  912. S(p54) =
  913. {
  914.   1, 'm', 28
  915. };
  916.  
  917. S(p55) =
  918. {
  919.   1, 'm', 18
  920. };
  921.  
  922. S(p56) =
  923. {
  924.   2, 'b', 87, 'p', 20
  925. };
  926.  
  927. S(p57) =
  928. {
  929.   2, 'h', 58, 'r', 61
  930. };
  931.  
  932. S(p58) =
  933. {
  934.   1, 'e', 59
  935. };
  936.  
  937. S(p59) =
  938. {
  939.   1, 'r', 60
  940. };
  941.  
  942. S(p60) =
  943. {
  944.   1, 'e', 87
  945. };
  946.  
  947. S(p61) =
  948. {
  949.   2, 'a', 62, 'i', 68
  950. };
  951.  
  952. S(p62) =
  953. {
  954.   1, 'n', 63
  955. };
  956.  
  957. S(p63) =
  958. {
  959.   1, 's', 23
  960. };
  961.  
  962. S(p64) =
  963. {
  964.   1, 'n', 66
  965. };
  966.  
  967. S(p65) =
  968. {
  969.   1, 'i', 83
  970. };
  971.  
  972. S(p66) =
  973. {
  974.   0, 85, 85, 85, 70, 85, 85, 85, 85, 0, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  975.     85, 85, 85, 85, 85, 85, 85, 85
  976. };
  977.  
  978. S(p67) =
  979. {
  980.   1, 'r', 87
  981. };
  982.  
  983. S(p68) =
  984. {
  985.   0, 81, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 81, 0, 0, 0, 0, 0
  986. };
  987.  
  988. S(p69) =
  989. {
  990.   0, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
  991.     85, 24, 85, 85, 85, 85, 85, 85
  992. };
  993.  
  994. S(p70) =
  995. {
  996.   1, 'e', 67
  997. };
  998.  
  999. char *Prefixes[] =
  1000. {
  1001.  p0, p1, p2, p3, p4, p5, p6, p7, p8, p9,
  1002.  p10, p11, p12, p13, p14, p15, p16, p17, p18, p19,
  1003.  p20, p21, p22, p23, p24, p25, p26, p27, p28, p29,
  1004.  p30, p31, p32, p33, p34, p35, p36, p37, p38, p39,
  1005.  p40, p41, p42, p43, p44, p45, p46, p47, p48, p49,
  1006.  p50, p51, p52, p53, p54, p55, p56, p57, p58, p59,
  1007.  p60, p61, p62, p63, p64, p65, p66, p67, p68, p69,
  1008.  p70
  1009. };
  1010.  
  1011. bool process_word(w)
  1012. char *w;
  1013. {
  1014.   char word[80], *s = word;
  1015.  
  1016.   hyphen(w, w + strlen(w) - 1);
  1017.   strcpy(word, w);
  1018.   while (*s) {
  1019.     if (HAS_HYPHEN(*s)) {
  1020.         *w++ = '\\';
  1021.         *w++ = '%';
  1022.     }
  1023.     *w++ = UNHYPHENATE(*s++);
  1024.   }
  1025.   *w++ = '\0';
  1026.   return TRUE;
  1027. }
  1028.  
  1029.  
  1030. char *Hyexcept[] =
  1031. {
  1032.  "ab-sorb-ent", "ac-cept-able", "ac-ceptor",
  1033.  "ac-cord-ance", "ac-count-ant", "ac-know-ledge",
  1034.  "adapt-able", "adapt-er", "af-firm-ative",
  1035.  "al-go-rithm", "an-nouncer", "ant-acid",
  1036.  "ant-eater", "ant-hill", "an-tiq-uity",
  1037.  "any-thing", "apart-heid", "arch-an-gel",
  1038.  "arch-ery", "ar-mi-stice", "art-ist",
  1039.  "askance", "astig-ma-tism", "astir",
  1040.  "astonish-ment", "at-mos-phere", "bal-ding",
  1041.  "bar-on-ess", "beach-comber", "beck-on",
  1042.  "bes-tial", "be-tween", "bib-li-og-raphy",
  1043.  "bind-ery", "bi-no-mial", "blast-off",
  1044.  "board-er", "bomb-er", "bouncer",
  1045.  "bound-ary", "buff-er", "bull-ish",
  1046.  "buzz-er", "by-stand-er", "candle-stick",
  1047.  "carb-on", "cast-away", "cast-off",
  1048.  "cat-ion", "cav-ern-ous", "cen-ter",
  1049.  "change-over", "child-ish", "chordal",
  1050.  "civ-i-lize", "class-ify", "class-room",
  1051.  "climb-er", "clinch-er",
  1052.  "coars-en", "cognac",
  1053.  "cole-slaw", "com-a-tose", "com-bat-ive",
  1054.  "come-back", "co-me-dian", "com-men-da-tory",
  1055.  "comp-troller", "com-put-abil-ity", "con-de-scend",
  1056.  "cone-flower", "con-form-ity", "con-sult-ant",
  1057.  "con-test-ant", "con-trol-lable", "co-nun-drum",
  1058.  "con-vert-ible", "co-star", "count-ess",
  1059.  "court-house", "court-yard", "cre-scendo",
  1060.  "crest-fallen", "cross-over", "crypt-analysis",
  1061.  "crys-tal-lize", "curl-i-cue", "damp-en",
  1062.  "damp-est", "dar-ling", "debt-or",
  1063.  "dec-la-ra-tion", "de-cre-scendo", "de-duct-ible",
  1064.  "de-form-ity", "de-gree", "de-pend-able",
  1065.  "de-pend-ent", "de-scend-ent", "de-scent",
  1066.  "de-test-able", "di-gest-ible", "dis-cern-ible",
  1067.  "dis-miss-al", "dis-till-ery", "dump-ling",
  1068.  "earth-en-ware", "east-ern", "egg-head",
  1069.  "egg-nog", "eld-est", "else-where",
  1070.  "eq-uable", "equipped", "err-ing",
  1071.  "es-tab-lish", "eu-logy", "eve-ning",
  1072.  "every-thing", "ex-ac-ti-tude", "ex-ist-ence",
  1073.  "ex-pend-able", "ex-press-ible", "fall-out",
  1074.  "false-hood", "far-thing", "fencer",
  1075.  "fiend-ish", "for-eign-er", "fore-short-en",
  1076.  "fore-stall", "found-ling", "gen-er-ator",
  1077.  "gold-en", "handle-bar", "hang-out",
  1078.  "hang-over", "hap-hazard", "ha-rangue",
  1079.  "hard-en", "hard-ened", "hard-est",
  1080.  "harp-ist", "haz-ard-ous", "heart-ache",
  1081.  "heart-ily", "hence-forth", "her-bal",
  1082.  "hogs-head", "hold-out", "hold-over",
  1083.  "hold-up",
  1084.  "idler", "im-mo-bi-lize",
  1085.  "im-pass-able", "im-per-turb-able", "inch-worm",
  1086.  "in-clem-ent", "in-con-test-able", "in-de-pend-ent",
  1087.  "in-di-gest-ible", "ineq-uity", "in-ex-acti-tude",
  1088.  "in-ex-haust-ible", "in-form-ant", "iniq-uity",
  1089.  "ink-blot", "ink-ling", "inn-keeper",
  1090.  "in-sa-tiable", "in-te-rior", "in-ter-rupt-ible",
  1091.  "ir-re-vers-ible", "jeop-ard-ize", "kib-itzer",
  1092.  "land-owner", "launch-er", "left-ist",
  1093.  "left-over", "less-en", "life-style",
  1094.  "lift-off", "lime-stone", "li-on-ess",
  1095.  "liq-uefy", "liq-uid", "liq-ui-date",
  1096.  "liq-ui-da-tion", "liq-uor", "live-stock",
  1097.  "lull-aby", "lunch-eon", "lus-cious",
  1098.  "main-spring", "mast-head", "me-ringue",
  1099.  "me-ta-bo-lize", "met-al", "mile-stone",
  1100.  "mince-meat", "min-is-ter", "min-is-try",
  1101.  "mo-bi-lize", "mod-ern-ize", "mo-nop-o-lize",
  1102.  "morgue", "needle-work", "neg-li-gible",
  1103.  "ne-go-tiable", "nerv-ous", "nest-ling",
  1104.  "non-con-form-ist", "none-the-less", "non-ex-ist-ent",
  1105.  "non-metal", "north-east", "north-ern",
  1106.  "nurse-maid", "nurs-ery", "ob-serv-able",
  1107.  "ob-server", "off-beat", "off-hand",
  1108.  "off-print", "off-shoot", "off-shore",
  1109.  "off-spring", "orange-ade", "out-land-ish",
  1110.  "pal-ate", "pass-able", "ped-a-gogy",
  1111.  "pent-house", "per-cent-age", "pe-ri-odic",
  1112.  "per-sist-ent", "pet-al", "pho-to-stat",
  1113.  "play-thing", "pleb-i-scite", "plumb-er",
  1114.  "poly-no-mial", "port-hole", "post-al",
  1115.  "post-hu-mous", "pre-dict-able", "pre-req-ui-site",
  1116.  "pre-school", "pre-serv-ative", "pre-vious",
  1117.  "priest-hood", "prob-abil-ity", "prob-able",
  1118.  "pro-ce-dure", "pro-gram", "pro-gram-mer",
  1119.  "pro-grams", "psalm-ist", "pub-li-ca-tion",
  1120.  "pub-lish", "qua-drille", "ranch-er",
  1121.  "rattle-snake", "re-corder", "re-hears-al",
  1122.  "rent-al", "re-place-ment", "rep-re-sentative",
  1123.  "req-ui-si-tion", "re-scind", "re-search-er",
  1124.  "re-solv-able", "re-spect-able", "re-start-ed",
  1125.  "re-state-ment", "re-store", "re-vers-ible",
  1126.  "re-volv-er", "roll-away", "round-about",
  1127.  "sap-ling", "sea-scape", "self-ish",
  1128.  "sell-out", "send-off", "sense-less",
  1129.  "serv-er", "serv-ice-able", "sharpen",
  1130.  "shoe-string", "short-en", "shy-ster",
  1131.  "sib-ling", "side-step", "side-swipe",
  1132.  "si-lencer",
  1133.  "smoke-stack",
  1134.  "snake-skin", "so-ciable", "soft-hearted",
  1135.  "solv-able", "som-er-sault", "some-thing",
  1136.  "sta-bi-lize", "stand-ard-ize", "stand-out",
  1137.  "star-ling", "stat-ure", "ster-ling",
  1138.  "stew-ard-ess", "stiff-en", "sub-se-quence",
  1139.  "sug-gest-ible", "su-pe-rior", "surf-er",
  1140.  "tan-ta-lize", "thermo-stat", "tongue",
  1141.  "torque", "toss-up", "trench-ant",
  1142.  "turn-about", "turn-over", "turn-table",
  1143.  "ubiq-ui-tous", "una-nim-ity", "u-nan-i-mous",
  1144.  "un-civ-i-lized", "un-class-ified", "un-con-trollable",
  1145.  "unc-tuous", "un-der-stand-able", "un-err-ing",
  1146.  "un-gov-ern-able", "un-pre-dict-able", "un-search-able",
  1147.  "un-so-ciable", "un-solv-able", "up-swing",
  1148.  "venge-ance", "vict-ual", "vignette",
  1149.  "volt-age", "wall-eye", "waste-bas-ket",
  1150.  "waste-land", "watt-meter", "weak-ling",
  1151.  "west-ern-ize", "when-ever", "whisk-er",
  1152.  "wors-en", "yard-age", "year-ling"
  1153. };
  1154.  
  1155. #define TABSIZE ( sizeof( Hyexcept ) / sizeof(char *) )
  1156.  
  1157. wcmp(word, tabp)
  1158. char *word;
  1159. char **tabp;
  1160. {
  1161.   /* Zur Behandlung des Plurals modifiziert am 17.7.87. Die Funktion
  1162.    * liefert TRUE, falls das Wort passt, jedoch auf ein s oder es endet. */
  1163.  
  1164.   register char *p = *tabp;
  1165.  
  1166.   while (*word && *p) {
  1167.     if (*p == '-') p++;
  1168.  
  1169.     if (*word != *p) break;
  1170.  
  1171.     word++;
  1172.     p++;
  1173.   }
  1174.  
  1175.   if (!*p && (word[0] == 's' ||
  1176.         (word[0] == 'e' && word[1] == 's')))
  1177.     return 0;
  1178.  
  1179.   return(*word - *p);
  1180. }
  1181.  
  1182. int exception(word, end)
  1183. char *word, *end;
  1184. {
  1185.   /* Durchsucht die Ausnahmeliste und liefert einen Zeiger auf den
  1186.    * Eintrag, falls es einen gibt, Null, falls nicht. */
  1187.  
  1188.   char **pp, *p;
  1189.   char oend;
  1190.   int rval = 0;
  1191.  
  1192.   oend = *++end;
  1193.   *end = 0;
  1194.  
  1195.   pp = (char **) bsearch(word, Hyexcept, TABSIZE, sizeof(char *),  wcmp);
  1196.  
  1197.   if (pp) {
  1198.     for (p = *pp; *p; word++, p++) {
  1199.         if (*p == '-') {
  1200.             HYPHENATE(*word);
  1201.             p++;
  1202.         }
  1203.     }
  1204.  
  1205.     rval = 1;
  1206.   }
  1207.   *end = oend;
  1208.   return rval;
  1209. }
  1210.  
  1211. char linebuf[512], *s;
  1212. bool font4 = FALSE, only_font4 = FALSE, usage = FALSE;
  1213.  
  1214. #define INT_ARG 0
  1215. #define BOOL_ARG 1
  1216. #define CHAR_ARG 2
  1217. #define STRING_ARG 3
  1218.  
  1219. char *setarg( argp, linep ) ARG *argp; char *linep;
  1220. /* set an argument.  argp points to the entry in the argument table, which
  1221.  * fits to *linep.  returns linep which points after the processed argument.
  1222.  */
  1223. {
  1224.   char *s;
  1225.  
  1226.   ++linep;
  1227.  
  1228.   switch( argp->type )
  1229.   {
  1230.     case INT_ARG:
  1231.     *(int*)argp->variable=atoi(linep);
  1232.     while (*linep) linep++;
  1233.     break;
  1234.  
  1235.     case BOOL_ARG: 
  1236.     *(int*)argp->variable = 1; break;
  1237.  
  1238.     case CHAR_ARG: 
  1239.      *(char*)argp->variable = *linep++; break;
  1240.  
  1241.     case STRING_ARG:
  1242.     s = (char*) argp->variable;
  1243.     while (*linep) *s++ = *linep++;
  1244.     *s='\0';
  1245.     break;
  1246.   }
  1247.   return(linep);
  1248. }
  1249.  
  1250. ARG *findarg(c, tabp, tabsize) 
  1251. char c; ARG *tabp; 
  1252. int tabsize;
  1253. {
  1254.   for (; --tabsize >= 0 ; tabp++ )
  1255.   if (tabp->arg == c ) return tabp;
  1256.  
  1257.   return NULL;
  1258. }
  1259.  
  1260. int argparse(argc,argv,tabp,tabsize)
  1261. int argc; char **argv; 
  1262. ARG *tabp; 
  1263. int tabsize;
  1264. {
  1265.   int nargc;
  1266.   char **nargv, *p;
  1267.   ARG   *argp;
  1268.  
  1269.   nargc = 1 ;
  1270.   for(nargv = ++argv ; --argc > 0 ; argv++ )
  1271.   {
  1272.     if (**argv=='-' && (argp = findarg(*(p=argv[0]+1), tabp, tabsize)))
  1273.       do 
  1274.         if (*(p=setarg(argp,p))) argp=findarg(*p,tabp,tabsize);
  1275.       while (*p);
  1276.     else
  1277.     {
  1278.       *nargv++ = *argv ;
  1279.       nargc++;
  1280.     }
  1281.   }
  1282.   return nargc ;
  1283. }
  1284.  
  1285.  
  1286. void fail(word)
  1287. char *word;
  1288. {
  1289.   fprintf(stderr, "Can't process '%s'\nLine: %s\n", word, linebuf);
  1290. }
  1291.  
  1292. char transbuf[512], *t = transbuf;
  1293.  
  1294. void outtext(c)
  1295. char c;
  1296. {
  1297.   *t++ = c;
  1298. }
  1299.  
  1300. void outspec(c)
  1301. char c;
  1302. {
  1303.   if (t != transbuf) {
  1304.     *t++ = '\0';
  1305.     if (only_font4 && !font4)
  1306.         printf("%s", transbuf);
  1307.     else if (process_word(transbuf))
  1308.         printf("%s", transbuf);
  1309.     t = transbuf;
  1310.   }
  1311.   putchar(c);
  1312. }
  1313.  
  1314. int nextchar()
  1315. {
  1316.   if (*s == '\0') return 0;
  1317.   s++;
  1318.   return 1;
  1319. }
  1320.  
  1321. /* I don't echo the backslash, because special did it when it failed to match
  1322.    the special rule.  Not the best way, but who cares.
  1323. */
  1324. int escapeseq()
  1325. {
  1326.   if (*s != '\\') return 0;
  1327.   nextchar();
  1328.   switch (*s) {
  1329.       case '*':
  1330.       case 'n':
  1331.     {
  1332.         outspec(*s);
  1333.         nextchar();
  1334.         if (*s == '(') {
  1335.             outspec('(');
  1336.             nextchar();
  1337.             outspec(*s);
  1338.             nextchar();
  1339.         }
  1340.         outspec(*s);
  1341.         nextchar();
  1342.         break;
  1343.     }
  1344.       default:
  1345.     outspec(*s);
  1346.     nextchar();
  1347.   }
  1348.   return 1;
  1349. }
  1350.  
  1351. void nonletter()
  1352. {
  1353.   if (!escapeseq()) {
  1354.     outspec(*s);
  1355.     nextchar();
  1356.   }
  1357. }
  1358.  
  1359. /* This rule is context-sensitive, because not all special characters are
  1360.  * accepted as a letter, see the return codes.
  1361.  */
  1362. int special()
  1363. {
  1364.   char *olds;
  1365.  
  1366.   if (*s != '\\') return 0;
  1367.   olds = s;
  1368.   nextchar();
  1369.   switch (*s) {
  1370.       case '%':
  1371.     outspec('\\');
  1372.     outspec('%');
  1373.     nextchar();
  1374.     return 1;
  1375.       case 'z':
  1376.     outspec('\\');
  1377.     outspec('z');
  1378.     nextchar();
  1379.     return 1;
  1380.       case 'f':            /* font ::= 'f' anychar */
  1381.     {
  1382.         outspec('\\');
  1383.         outspec('f');
  1384.         nextchar();
  1385.         font4 = (*s == '4');
  1386.         outspec(*s);
  1387.         nextchar();
  1388.         return 1;
  1389.     }
  1390.  
  1391.       case 's':            /* size ::= [ '+' | '-' ] { digit } */
  1392.     {
  1393.         outspec('\\');
  1394.         outspec('s');
  1395.         nextchar();
  1396.         if (*s == '-' || *s == '+') nextchar();
  1397.         while (*s >= '0' && *s <= '9') nextchar();
  1398.         return 1;
  1399.     }
  1400.  
  1401.       case '(':
  1402.     {
  1403.         outspec('\\');
  1404.         outspec('(');
  1405.         nextchar();
  1406.         outspec(*s);
  1407.         nextchar();
  1408.         return 2;
  1409.     }
  1410.  
  1411.       default:
  1412.     outspec('\\');
  1413.     s = olds;
  1414.     return 0;
  1415.   }
  1416. }
  1417.  
  1418. int letter()
  1419. {
  1420.   int x;
  1421.  
  1422.   x = special();
  1423.   if (x) return 1;
  1424.   if (x == 0)
  1425.     if ((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z')) {
  1426.         outtext(*s);
  1427.         nextchar();
  1428.         return 1;
  1429.     }
  1430.   return 0;
  1431. }
  1432.  
  1433. void word()
  1434. {
  1435.   if (letter()) {
  1436.     while (letter());
  1437.   }
  1438. }
  1439.  
  1440. void words()
  1441. {
  1442.   while (*s) {
  1443.     word();
  1444.     if (*s) nonletter();
  1445.   }
  1446. }
  1447.  
  1448. /* Arguments not implemented yet */
  1449. int macro()
  1450. {
  1451.   if (*s == '.') {
  1452.     printf("%s", s);
  1453.     return 1;
  1454.   } else
  1455.     return 0;
  1456. }
  1457.  
  1458. void line()
  1459. {
  1460.   if (!macro()) words();
  1461. }
  1462.  
  1463. void text(fd)
  1464. FILE *fd;
  1465. {
  1466.   int l;
  1467.  
  1468.   while (fgets(linebuf, sizeof(linebuf), fd)) {
  1469.     if (l = strlen(linebuf)) linebuf[l - 1] = '\0';
  1470.     s = linebuf;
  1471.     line();
  1472.     outspec('\n');
  1473.   }
  1474. }
  1475.  
  1476. #define argnum 2
  1477.  
  1478. ARG argtab[argnum] =
  1479. {
  1480.  '?', BOOL_ARG, &usage,
  1481.  '4', BOOL_ARG, &only_font4
  1482. };
  1483.  
  1484. main(argc, argv)
  1485. int argc;
  1486. char *argv[];
  1487. {
  1488.   FILE *in;
  1489.  
  1490.   argc = argparse(argc, argv, argtab, argnum);
  1491.   if (usage) {
  1492.     fprintf(stderr, "Usage: %s {-4} {file}\n");
  1493.     exit(0);
  1494.   }
  1495.   if (argc == 2) {
  1496.     if ((in = fopen(argv[1], "r")) == NULL) {
  1497.         fprintf(stderr, "%s: unvalid argument\n", argv[0]);
  1498.         exit(1);
  1499.     }
  1500.   } else
  1501.     in = stdin;
  1502.   text(in);
  1503.   if (in != stdin) fclose(in);
  1504. }
  1505.