home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Tex / Tex29 / StTeXsrc.zoo / src / hyph.c < prev    next >
C/C++ Source or Header  |  1988-03-13  |  22KB  |  873 lines

  1.  
  2. /*
  3.  * @(#)hyph.c 2.6 EPA
  4.  *
  5.  * Copyright 1987,1988 Pat J Monardo
  6.  *
  7.  * Redistribution of this file is permitted through
  8.  * the specifications in the file COPYING.
  9.  *
  10.  * 
  11.  */
  12.  
  13. #include "tex.h"
  14. #include "token.h"
  15. #include "tfm.h"
  16. #include "box.h"
  17. #include "scan.h"
  18. #include "tokenstack.h"
  19. #include "par.h"
  20. #include "hyph.h"
  21.  
  22. ptr     ha;
  23. ptr     hb;
  24. hword   hc[66];
  25. fnt     hf;
  26. int     hn;
  27. ascii   hu[64];
  28. byte    hyf[65];
  29. int     hyf_char;
  30. int     hyf_distance[256];
  31. qword   hyf_next[256];
  32. int     hyf_num[256];
  33. int     hyph_count;
  34. ptr     hyph_list[HYPH_SIZE+1];
  35. str     hyph_word[HYPH_SIZE+1];
  36. int     hyphen_passed;
  37. int     trie_max;
  38. hh      trie[TRIE_SIZE+1];
  39.  
  40. try_hyph ()
  41. {
  42.     int     c;
  43.     int     j;
  44.     ptr     q;
  45.     ptr     s;
  46.     
  47.     s = link(cur_p);
  48.     if (s != NULL) {
  49.         loop {
  50.             if (is_char_node(s)) {
  51.                 c = qo(character(s));
  52.                 hf = font(s);
  53.             } else if (type(s) == LIGATURE_NODE) {
  54.                 q = lig_ptr(s);
  55.                 c = qo(character(q));
  56.                 hf = font(q);
  57.             } else if (type(s) == KERN_NODE &&
  58.                     subtype(s) == NORMAL)
  59.                 c = 128;
  60.             else if (type(s) == WHATSIT_NODE)
  61.                 c = 128;
  62.             else goto done1;
  63.             if (c < 128 && lc_code(c) != 0) {
  64.                 if (lc_code(c) == c || uc_hyph > 0)
  65.                     goto done2;
  66.                 else goto done1;
  67.             }
  68.             s = link(s);
  69.         }
  70.  
  71.     done2:
  72.         hyf_char = hyphen_char[hf];
  73.         if (hyf_char < 0 || hyf_char > 255)
  74.             goto done1;
  75.         ha = s;
  76.         hn = 0;
  77.         loop {
  78.             if (is_char_node(s)) {
  79.                 if (font(s) != hf)
  80.                     goto done3;
  81.                 c = qo(character(s));
  82.                 if (c >= 128)
  83.                     goto done3;
  84.                 if (lc_code(c) == 0 || hn == 63)
  85.                     goto done3;
  86.                 hb = s;
  87.                 incr(hn);
  88.                 hu[hn] = c;
  89.                 hc[hn] = lc_code(c) - 1;
  90.             } else if (type(s) == LIGATURE_NODE) {
  91.                 j = hn;
  92.                 q = lig_ptr(s);
  93.                 if (font(q) != hf)
  94.                     goto done3;
  95.                 do {
  96.                     c = qo(character(q));
  97.                     if (c >= 128)
  98.                         goto done3;
  99.                     if (lc_code(c) == 0 || j == 63)
  100.                         goto done3;
  101.                     incr(j);
  102.                     hu[j] = c;
  103.                     hc[j] = lc_code(c) - 1;
  104.                     q = link(q);
  105.                 } while (q != NULL);
  106.                 hb = s;
  107.                 hn = j;
  108.             } else if (type(s) != KERN_NODE ||
  109.                     subtype(s) != NORMAL)
  110.                 goto done3;
  111.             s = link(s);
  112.         }
  113.  
  114.     done3:
  115.         if (hn < 5)
  116.             goto done1;
  117.         loop {
  118.             if (!is_char_node(s)) {
  119.                 switch (type(s))
  120.                 {
  121.                 case LIGATURE_NODE:
  122.                     break;
  123.  
  124.                 case KERN_NODE:
  125.                     if (subtype(s) != NORMAL)
  126.                         goto done4;
  127.                     break;
  128.  
  129.                 case WHATSIT_NODE:
  130.                 case GLUE_NODE:
  131.                 case PENALTY_NODE:
  132.                 case INS_NODE:
  133.                 case ADJUST_NODE:
  134.                 case MARK_NODE:
  135.                     goto done4;
  136.                 
  137.                 default: 
  138.                     goto done1;
  139.                 }
  140.             }
  141.             s = link(s);
  142.         }
  143.  
  144.     done4:
  145.         hyphenate();
  146.     }
  147. done1: ;
  148. }
  149.  
  150. hyphenate ()
  151. {
  152.     ascii   c;
  153.     int     h;
  154.     int     i;
  155.     int     j;
  156.     str     k;
  157.     int     l;
  158.     ptr     q;
  159.     ptr     r;
  160.     ptr     s;
  161.     int     u;
  162.     qword   v;
  163.     int     z;
  164.     ptr     hyf_node;
  165.     ptr     major_tail;
  166.     ptr     minor_tail;
  167.  
  168.     for (j = 0; j <= hn; incr(j))
  169.         hyf[j] = 0;
  170.     h = hc[1];
  171.     for (j = 2; j <= hn; incr(j))
  172.         h = (h + h + hc[j]) % HYPH_SIZE;
  173.     loop {
  174.         k = hyph_word[h];
  175.         if (k == 0) goto not_found;
  176.         if (length(k) < hn) goto not_found;
  177.         if (length(k) == hn) {
  178.             j = 1;
  179.             u = str_start[k];
  180.             do {
  181.                 if (str_pool[u] < hc[j]) goto not_found;
  182.                 if (str_pool[u] > hc[j]) goto done;
  183.                 incr(u); incr(j);
  184.             } while (j <= hn);
  185.             for (s = hyph_list[h]; s != NULL; s = link(s))
  186.                 hyf[info(s)] = 1;
  187.             goto found;
  188.         }
  189.  
  190.     done:
  191.         if (h > 0)
  192.             decr(h);
  193.         else h = HYPH_SIZE;
  194.     }
  195.  
  196. not_found:
  197.     hc[0] = 127;
  198.     hc[hn + 1] = 127;
  199.     hc[hn + 2] = 256;
  200.     for (j = 0; j <= hn - 2; incr(j)) {
  201.         z = hc[j];
  202.         l = j;
  203.         while (hc[l] == trie_char(z)) {
  204.             if (trie_op(z) != MIN_QUARTERWORD) {
  205.                 v = trie_op(z);
  206.                 do {
  207.                     i = l - hyf_distance[v];
  208.                     if (hyf_num[v] > hyf[i])
  209.                         hyf[i] = hyf_num[v];
  210.                     v = hyf_next[v];
  211.                 } while (v != MIN_QUARTERWORD);
  212.             }
  213.             incr(l);
  214.             z = trie_link(z) + hc[l];
  215.         }
  216.     }
  217.  
  218. found:
  219.     hyf[1] = 0;
  220.     hyf[hn - 2] = 0;
  221.     hyf[hn - 1] = 0;
  222.     hyf[hn] = 0;
  223.  
  224.     for (j = 2; j <= hn - 3; incr(j))
  225.         if (odd(hyf[j])) goto found1;
  226.     return;
  227.  
  228. found1:
  229.     q = link(hb);
  230.     link(hb) = NULL;
  231.     s = cur_p;
  232.     while (link(s) != ha)
  233.         s = link(s);
  234.     link(s) = NULL;
  235.     flush_node_list(ha);
  236.     j = 0;
  237.     do {
  238.         l = j;
  239.         j = reconstitute(j + 1, hn);
  240.         if (hyphen_passed != 0) {
  241.             r = get_node(SMALL_NODE_SIZE);
  242.             link(s) = r;
  243.             link(r) = link(hold_head);
  244.             type(r) = DISC_NODE;
  245.             major_tail = link(hold_head);
  246.             if (link(major_tail) != NULL)
  247.                 major_tail = link(major_tail);
  248.             i = hyphen_passed;
  249.             minor_tail = NULL;
  250.             hyf_node = new_character(hf, (ascii) hyf_char);
  251.             if (hyf_node != NULL) {
  252.                 incr(i);
  253.                 c = hu[i];
  254.                 hu[i] = hyf_char;
  255.             }
  256.             do {
  257.                 l = reconstitute(l + 1, i);
  258.                 if (minor_tail == NULL)
  259.                     pre_break(r) = link(hold_head);
  260.                 else link(minor_tail) = link(hold_head);
  261.                 minor_tail = link(hold_head);
  262.                 if (link(minor_tail) != NULL)
  263.                     minor_tail = link(minor_tail);
  264.             } while (l != i);
  265.             if (hyf_node != NULL) {
  266.                 hu[i] = c;
  267.                 free_avail(hyf_node);
  268.                 decr(i);
  269.                 l = i;
  270.             }
  271.             hyf[i] = 0;
  272.             minor_tail = NULL;
  273.             post_break(r) = NULL;
  274.             while (l < j) {
  275.                 do {
  276.                     l = reconstitute(l + 1, hn);
  277.                     if (minor_tail == NULL)
  278.                         post_break(r) = link(hold_head);
  279.                     else link(minor_tail) = link(hold_head);
  280.                     minor_tail = link(hold_head);
  281.                     if (link(minor_tail) != NULL) {
  282.                         hyf[l] = 0;
  283.                         minor_tail = link(minor_tail);
  284.                     }
  285.                 } while (l < j);
  286.                 while (l > j) {
  287.                     j = reconstitute(j + 1, hn);
  288.                     link(major_tail) = link(hold_head);
  289.                     major_tail = link(hold_head);
  290.                     if (link(major_tail) != NULL) {
  291.                         hyf[j] = 0;
  292.                         major_tail = link(major_tail);
  293.                     }
  294.                 }
  295.             }
  296.             i = 0; 
  297.             s = r;
  298.             while(link(s) != NULL) {
  299.                 incr(i);
  300.                 s =  link(s);
  301.             }
  302.             replace_count(r) = i;
  303.         } else {
  304.             link(s) = link(hold_head);
  305.             s = link(s);
  306.             if (link(s) != NULL)
  307.                 s = link(s);
  308.         }
  309.         if (odd(hyf[j])) {
  310.             r = new_disc();
  311.             pre_break(r) = new_character(hf, (ascii) hyf_char);
  312.             link(s) = r;
  313.             s = r;
  314.         }
  315.     } while (j != hn);
  316.     link(s) = q;
  317. }
  318.  
  319. reconstitute (j, n)
  320.     int     j;
  321.     int     n;
  322. {
  323.     qword   c;
  324.     qword   d;
  325.     ptr     p;
  326.     qqqq    q;
  327.     int     r;
  328.     ptr     s;
  329.     scal    w;
  330.  
  331.     hyphen_passed = 0;
  332.     s = hold_head;
  333.     w = 0;
  334.     c = d = qi(hu[j]);
  335.     loop {
  336. contin: p = get_avail();
  337.         font(p) = hf;
  338.         character(p) = c;
  339.         link(s) = p;
  340.         if (j == n) break;
  341.         q = char_info(hf, d);
  342.         if (char_tag(q) != LIG_TAG) break;
  343.         r = lig_kern_start(hf, q);
  344.         c = qi(hu[j + 1]);
  345.         loop {
  346.             q = font_info[r].qqqq;
  347.             if (next_char(q) == c) {
  348.                 if (odd(hyf[j]) && hyphen_passed == 0)
  349.                     hyphen_passed = j;
  350.                 if (op_bit(q) < KERN_FLAG) {
  351.                     d = rem_byte(q);
  352.                     incr(j);
  353.                     s = p;
  354.                     goto contin;
  355.                 } else {
  356.                     w = char_kern(hf, q);
  357.                     goto done;
  358.                 }
  359.             } else if (stop_bit(q) < STOP_FLAG)
  360.                 incr(r);
  361.             else goto done;
  362.         }
  363.     }
  364.  
  365. done:
  366.     if (s != hold_head) {
  367.         p = new_ligature(hf, d, link(hold_head));
  368.         link(hold_head) = p;
  369.     }
  370.     if (w != 0)
  371.         link(link(hold_head)) = new_kern(w);
  372.     return j;
  373. }
  374.  
  375. new_hyph_exceptions ()
  376. {
  377.     int     h;
  378.     int     j;
  379.     str     k;
  380.     int     n;
  381.     ptr     p;
  382.     ptr     q;
  383.     str     s;
  384.     str     t;
  385.     int     u;
  386.     int     v;
  387.  
  388.     n = 0;
  389.     p = NULL;
  390.     scan_left_brace();
  391.     loop {
  392.         get_x_token();
  393.  
  394.     reswitch:
  395.         switch (cur_cmd)
  396.         {
  397.         case LETTER:
  398.         case OTHER_CHAR:
  399.         case CHAR_GIVEN:
  400.             if (cur_chr == '-') {
  401.                 if (n > 1) {
  402.                     q = get_avail();
  403.                     link(q) = p;
  404.                     info(q) = n;
  405.                     p = q;
  406.                 }
  407.             } else {
  408.                 if (cur_chr > 127 || lc_code(cur_chr) == 0) {
  409.                     print_err("Not a letter");
  410.                     help_hyph_lccode();
  411.                     error();
  412.                 } else if (n < 63) {
  413.                     incr(n);
  414.                     hc[n] = lc_code(cur_chr) - 1;
  415.                 }
  416.             }
  417.             break;
  418.         
  419.         case CHAR_NUM:
  420.             scan_char_num();
  421.             cur_chr = cur_val;
  422.             cur_cmd = CHAR_GIVEN;
  423.             goto reswitch;
  424.  
  425.         case SPACER:
  426.         case RIGHT_BRACE:
  427.             if (n > 4) {
  428.                 str_room(n);
  429.                 h = 0;
  430.                 for (j = 1; j <= n; incr(j)) {
  431.                     h = (h + h + hc[j]) % HYPH_SIZE;
  432.                     append_char(hc[j]);
  433.                 }
  434.                 s = make_str();
  435.                 loop {
  436.                     if (p == NULL)
  437.                         break;
  438.                     if (info(p) < n - 2)
  439.                         break;
  440.                     q = link(p);
  441.                     free_avail(p);
  442.                     p = q;
  443.                 }
  444.                 if (hyph_count == HYPH_SIZE)
  445.                     overflow("exception dictionary", HYPH_SIZE);
  446.                 incr(hyph_count);
  447.                 while (hyph_word[h] != 0) {
  448.                     k = hyph_word[h];
  449.                     if (length(k) < length(s))
  450.                         goto found;
  451.                     if (length(k) > length(s))
  452.                         goto not_found;
  453.                     u = str_start[k];
  454.                     v = str_start[s];
  455.                     do {
  456.                         if (str_pool[u] < str_pool[v])
  457.                             goto found;
  458.                         if (str_pool[u] > str_pool[v])
  459.                             goto not_found;
  460.                         incr(u); incr(v);
  461.                     } while (u != str_start[k + 1]);
  462.  
  463.                 found:
  464.                     q = hyph_list[h];
  465.                     hyph_list[h] = p;
  466.                     p = q;
  467.                     t = hyph_word[h];
  468.                     hyph_word[h] = s;
  469.                     s = t;
  470.                 
  471.             not_found:
  472.                     if (h > 0)
  473.                         decr(h);
  474.                     else h = HYPH_SIZE;
  475.                 }
  476.                 hyph_word[h] = s;
  477.                 hyph_list[h] = p;
  478.             }
  479.             if (cur_cmd == RIGHT_BRACE)
  480.                 return;
  481.             n = 0;
  482.             p = NULL;
  483.             break;
  484.  
  485.         default:
  486.             print_err("Improper ");
  487.             print_esc("hyphenation");
  488.             print(" will be flushed");
  489.             help_hyph();
  490.             error();
  491.             break;
  492.         }
  493.     }
  494. }
  495.  
  496. /*
  497.  *  Help text
  498.  */
  499.  
  500. help_hyph_lccode ()
  501. {
  502.     help2("Letters in \\hyphenation words must have \\lccode > 0",
  503.     "Proceed; I'll ignore the character I just read.");
  504. }
  505.  
  506. help_hyph ()
  507. {
  508.     help2("Hyphenation exceptions must contain only letters",
  509.     "and hyphens. But continue; I'll forgive and forget.");
  510. }
  511.  
  512. qword   trie_op_ptr;
  513.  
  514. #ifdef INIT
  515.  
  516. qword   trie_op_hash[TRIE_OP_HASH_SIZE+1];  
  517. int     trie_hash[TRIE_SIZE+1];
  518. ascii   trie_c[TRIE_SIZE+1];
  519. qword   trie_o[TRIE_SIZE+1];
  520. int     trie_l[TRIE_SIZE+1];
  521. int     trie_r[TRIE_SIZE+1];
  522. int     trie_min;
  523. int     trie_ptr;
  524. bool    trie_taken[TRIE_SIZE+1];
  525.  
  526. qword
  527. new_trie_op (d, n, v)
  528.     int     d;
  529.     int     n;
  530.     qword   v;
  531. {
  532.     int     h;
  533.     qword   u;
  534.  
  535.     h = abs(n + 313 * d + 361 * v) % TRIE_OP_HASH_SIZE;
  536.     loop {
  537.         u = trie_op_hash[h];
  538.         if (u == MIN_QUARTERWORD) {
  539.             if (trie_op_ptr == MAX_QUARTERWORD)
  540.                 return MIN_QUARTERWORD;
  541.             incr(trie_op_ptr);
  542.             hyf_distance[trie_op_ptr] = d;
  543.             hyf_num[trie_op_ptr] = n;
  544.             hyf_next[trie_op_ptr] = v;
  545.             trie_op_hash[h] = trie_op_ptr;
  546.             return trie_op_ptr;
  547.         }
  548.         if (hyf_distance[u] == d && 
  549.             hyf_num[u] == n &&
  550.             hyf_next[u] == v)
  551.                 return u;
  552.         if (h > 0)
  553.             decr(h);
  554.         else h = TRIE_OP_HASH_SIZE;
  555.     }
  556. }
  557.         
  558. trie_node (p)
  559.     int     p;
  560. {
  561.     int     h;
  562.     int     q;
  563.  
  564.     h = abs(trie_c[p] + 
  565.             1009 * trie_o[p] +
  566.             2718 * trie_l[p] +
  567.             3142 * trie_r[p])
  568.             % TRIE_SIZE;
  569.     loop {
  570.         q = trie_hash[h];
  571.         if (q == 0) {
  572.             trie_hash[h] = p; 
  573.             return p;
  574.         }
  575.         if (trie_c[q] == trie_c[p] &&
  576.             trie_o[q] == trie_o[p] &&
  577.             trie_l[q] == trie_l[p] && 
  578.             trie_r[q] == trie_r[p])
  579.             return q;
  580.         if (h > 0) 
  581.             decr(h);
  582.         else h = TRIE_SIZE;
  583.     }
  584. }
  585.  
  586. compress_trie (p)
  587.     int     p;
  588. {
  589.     if (p == 0)
  590.         return 0;
  591.     else {
  592.         trie_l[p] = compress_trie(trie_l[p]);
  593.         trie_r[p] = compress_trie(trie_r[p]);
  594.         return (trie_node(p));
  595.     }
  596. }
  597.  
  598. init_pattern_memory ()
  599. {
  600.     int     h;
  601.     int     p;
  602.  
  603.     for (h = 0; h <= TRIE_OP_HASH_SIZE; incr(h))
  604.         trie_op_hash[h] = MIN_QUARTERWORD;
  605.     trie_op_ptr = MIN_QUARTERWORD;
  606.     trie_root = 0;
  607.     trie_c[0] = 0;
  608.     trie_ptr = 0;
  609.     for (p = 0; p <= TRIE_SIZE; incr(p))
  610.         trie_hash[p] = 0;
  611. }
  612.  
  613. init_trie_memory ()
  614. {
  615.     int     p;
  616.  
  617.     for (p = 0; p <= trie_ptr; incr(p))
  618.         trie_ref[p] = 0;
  619.     trie_max = trie_min = 128;
  620.     trie_link(0) = 1;
  621.     trie_taken[0] = FALSE;
  622.     for (p = 1; p <= 128; p++) {
  623.         trie_back(p) = p - 1;
  624.         trie_link(p) = p + 1;
  625.         trie_taken[p] = FALSE;
  626.     }
  627. }
  628.  
  629. first_fit (p)
  630.     int     p;
  631. {
  632.     ascii   c;
  633.     int     h;
  634.     int     q;
  635.     int     z;
  636.  
  637.     c = trie_c[p];
  638.     if (c < trie_min)
  639.         trie_min = c;
  640.     z = trie_link(trie_min - 1);
  641.     loop {
  642.         if (z < c)
  643.             goto not_found;
  644.         h = z - c;
  645.         if (trie_max < h + 128) {
  646.             if (TRIE_SIZE <= h + 128)
  647.                 overflow("pattern memory", TRIE_SIZE);
  648.             do {
  649.                 incr(trie_max); 
  650.                 trie_taken[trie_max] = FALSE;
  651.                 trie_link(trie_max) = trie_max + 1;
  652.                 trie_back(trie_max) = trie_max - 1;
  653.             } while (trie_max != h + 128);
  654.         }
  655.         if (trie_taken[h])
  656.             goto not_found;
  657.         for (q = trie_r[p]; q > 0; q = trie_r[q])
  658.             if (trie_link(h + trie_c[q]) == 0)
  659.                 goto not_found;
  660.         goto found;
  661.  
  662.     not_found:
  663.         z = trie_link(z);
  664.     }
  665.  
  666. found:
  667.     trie_taken[h] = TRUE;
  668.     trie_ref[p] = h;
  669.     q = p;
  670.     do {
  671.         z = h + trie_c[q];
  672.         trie_back(trie_link(z)) = trie_back(z);
  673.         trie_link(trie_back(z)) = trie_link(z);
  674.         trie_link(z) = 0;
  675.         q = trie_r[q];
  676.     } while (q != 0);
  677. }
  678.  
  679. trie_pack (p)
  680.     int     p;
  681. {
  682.     int     q;
  683.  
  684.     do {    
  685.         q = trie_l[p];
  686.         if (q > 0 && trie_ref[q] == 0) {
  687.             first_fit(q);
  688.             trie_pack(q);
  689.         }
  690.         p = trie_r[p];
  691.     } while (p != 0);
  692. }
  693.  
  694. trie_fix (p)
  695.     int     p;
  696. {
  697.     ascii   c;
  698.     int     q;
  699.     int     z;
  700.  
  701.     z = trie_ref[p];
  702.     while (p != 0) {
  703.         q = trie_l[p];
  704.         c = trie_c[p];
  705.         trie_link(z + c) = trie_ref[q];
  706.         trie_char(z + c) = c;
  707.         trie_op(z + c) = trie_o[p];
  708.         if (q > 0)
  709.             trie_fix(q);
  710.         p = trie_r[p];
  711.     }
  712. }
  713.  
  714. new_patterns ()
  715. {
  716.     ascii   c;
  717.     hh      h;
  718.     int     k;
  719.     int     l;
  720.     int     p;
  721.     int     q;
  722.     int     r;
  723.     int     s;
  724.     qword   v;
  725.     bool    digit_sensed;
  726.     bool    first_child;
  727.  
  728.     scan_left_brace();
  729.     init_pattern_memory();
  730.     k = 0;
  731.     hyf[0] = 0;
  732.     digit_sensed = FALSE;
  733.     loop {
  734.         get_x_token();
  735.         switch (cur_cmd)
  736.         {
  737.         case LETTER:
  738.         case OTHER_CHAR:
  739.             if (digit_sensed || cur_chr < '0' || cur_chr > '9') {
  740.                 if (cur_chr == '.')
  741.                     cur_chr = 128;
  742.                 else {
  743.                     cur_chr = lc_code(cur_chr);
  744.                     if (cur_chr == 0) {
  745.                         print_err("Nonletter");
  746.                         help1("(See Appendix H.)");
  747.                         error();
  748.                         cur_chr = 128;
  749.                     }
  750.                 }
  751.                 if (k < 63) {
  752.                     incr(k);
  753.                     hc[k] = cur_chr - 1;
  754.                     hyf[k] = 0;
  755.                     digit_sensed = FALSE;
  756.                 }
  757.             } else {
  758.                 hyf[k] = cur_chr - '0';
  759.                 if (k < 63)
  760.                     digit_sensed = TRUE;
  761.             }
  762.             break;
  763.  
  764.         case SPACER:
  765.         case RIGHT_BRACE:
  766.             if (k > 0) {
  767.                 if (hc[1] == 127)
  768.                     hyf[0] = 0;
  769.                 if (hc[k] == 127)
  770.                     hyf[k] = 0;
  771.                 l = k;
  772.                 v = MIN_QUARTERWORD;
  773.                 loop {
  774.                     if (hyf[l] != 0)
  775.                         v = new_trie_op(k - l, hyf[l], v);
  776.                     if (l > 0)
  777.                         decr(l);
  778.                     else break;
  779.                 }
  780.                 q = 0; 
  781.                 while (l < k) {
  782.                     incr(l);
  783.                     c = hc[l];
  784.                     p = trie_l[q];
  785.                     first_child = TRUE;
  786.                     while (p > 0 && c > trie_c[p]) {
  787.                         q = p;
  788.                         p = trie_r[q];
  789.                         first_child = FALSE;
  790.                     }
  791.                     if (p == 0 || c < trie_c[p]) {
  792.                         if (trie_ptr == TRIE_SIZE)
  793.                             overflow("pattern memory", TRIE_SIZE);
  794.                         incr(trie_ptr);
  795.                         trie_r[trie_ptr] = p;
  796.                         p = trie_ptr;
  797.                         trie_l[p] = 0;
  798.                         if (first_child)
  799.                             trie_l[q] = p;
  800.                         else trie_r[q] = p;
  801.                         trie_c[p] = c;
  802.                         trie_o[p] = MIN_QUARTERWORD;
  803.                     }
  804.                     q = p;
  805.                 }
  806.                 if (trie_o[q] != MIN_QUARTERWORD) {
  807.                     print_err("Duplicate pattern");
  808.                     help1("(See Appendix H.)");
  809.                     error();
  810.                 }
  811.                 trie_o[q] = v;
  812.             }
  813.             if (cur_cmd == RIGHT_BRACE)
  814.                 goto done;
  815.             k = 0;
  816.             hyf[0] = 0;
  817.             digit_sensed = FALSE;
  818.             break;
  819.  
  820.         default:
  821.             print_err("Bad ");
  822.             print_esc("patterns");
  823.             help1("(See Appendix H.)");
  824.             error();
  825.             break;
  826.         }
  827.     }
  828.  
  829. done:
  830.     trie_root = compress_trie(trie_root);
  831.     init_trie_memory();
  832.     if (trie_root != 0) {
  833.         first_fit(trie_root);
  834.         trie_pack(trie_root);
  835.     }
  836.     r = 0;
  837.     while (trie_taken[r])
  838.         incr(r);
  839.     trie_ref[0] = r;
  840.     trie_fix(trie_root);
  841.     r = 0;
  842.     h.hh2.rh = 0;
  843.     h.hh2.b0 = 0;
  844.     h.hh2.b1 = 0;
  845.     do {
  846.         s = trie_link(r);
  847.         trie[r] = h;
  848.         r = s;
  849.     } while (r <= trie_max);
  850. }
  851. #endif
  852.  
  853. init_hyph ()
  854. {
  855. #ifdef INIT
  856.     int     k;
  857.     int     z;
  858.  
  859.     trie_op_ptr = MIN_QUARTERWORD;
  860.     trie_link(0) = 0;
  861.     trie_char(0) = 0;
  862.     trie_op(0) = MIN_QUARTERWORD;
  863.     for (k = 1; k <= 127; k++)
  864.         trie[k] = trie[0];
  865.     trie_max = 127;
  866.     for (z = 0; z <= HYPH_SIZE; z++) {
  867.         hyph_word[z] = 0;
  868.         hyph_list[z] = NULL;
  869.     }
  870.     hyph_count = 0;
  871. #endif
  872. }
  873.