OSDN Git Service

0dc07e272f2f90283d1406ffa57959e1032d2a34
[putex/putex.git] / src / texsourc / tex6.c
1 /* Copyright 2014 Clerk Ma
2
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; either version 2 of the License, or
6    (at your option) any later version.
7
8    This program is distributed in the hope that it will be useful, but
9    WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    General Public License for more details.
12
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16    02110-1301 USA.  */
17
18 #define EXTERN extern
19
20 #include "texd.h"
21
22 /* sec 0785 */
23 void align_peek (void)
24 {
25 restart:
26   align_state = 1000000L;
27
28   do
29     {
30       get_x_token();
31     }
32   while (!(cur_cmd != spacer));
33
34   if (cur_cmd == no_align)
35   {
36     scan_left_brace();
37
38     new_save_level(no_align_group);
39
40     if (mode == -1)
41       normal_paragraph();
42   }
43   else if (cur_cmd == right_brace)
44   {
45     fin_align();
46   }
47   else if ((cur_cmd == car_ret) && (cur_chr == cr_cr_code))
48     goto restart;
49   else
50   {
51     init_row();
52     init_col();
53   }
54 }
55 /* sec 0826 */
56 halfword finite_shrink_(halfword p)
57 {
58   halfword q;
59
60   if (no_shrink_error_yet)
61   {
62     no_shrink_error_yet = false;
63     print_err("Infinite glue shrinkage found in a paragraph");
64     help5("The paragraph just ended includes some glue that has",
65         "infinite shrinkability, e.g., `\\hskip 0pt minus 1fil'.",
66         "Such glue doesn't belong there---it allows a paragraph",
67         "of any length to fit on one line. But it's safe to proceed,",
68         "since the offensive shrinkability has been made finite.");
69     error();
70   }
71
72   q = new_spec(p);
73   shrink_order(q) = normal;
74   delete_glue_ref(p);
75
76   return q;
77 }
78 /* sec 0829 */
79 void try_break_ (integer pi, small_number break_type)
80 {
81   halfword r;
82   halfword prev_r;
83   halfword old_l;
84   boolean no_break_yet;
85   halfword prev_prev_r;
86   halfword s;
87   halfword q;
88   halfword v;
89   integer t;
90   internal_font_number f;
91   halfword l;
92   boolean node_r_stays_active;
93   scaled line_width;
94   char fit_class;
95   halfword b;
96   integer d;
97   boolean artificial_demerits;
98   halfword save_link;
99   scaled shortfall;
100
101   if (abs(pi)>= inf_penalty)
102     if (pi > 0)
103       goto exit;
104     else
105       pi = eject_penalty;
106
107   no_break_yet = true;
108   prev_r = active;
109   old_l = 0;
110   do_all_six(copy_to_cur_active);
111
112   while (true)
113   {
114 continu:
115     r = link(prev_r);
116
117     if (type(r) == delta_node)
118     {
119       do_all_six(update_width);
120       prev_prev_r = prev_r;
121       prev_r = r;
122       goto continu;
123     }
124
125     {
126       l = line_number(r);
127
128       if (l > old_l)
129       {
130         if ((minimum_demerits < awful_bad) && ((old_l != easyline) || (r == active)))
131         {
132           if (no_break_yet)
133           {
134             no_break_yet = false;
135             do_all_six(set_break_width_to_background);
136             s = cur_p;
137
138             if (break_type > unhyphenated)
139               if (cur_p != 0)
140               {
141                 t = replace_count(cur_p);
142                 v = cur_p;
143                 s = post_break(cur_p);
144
145                 while (t > 0)
146                 {
147                   decr(t);
148                   v = link(v);
149
150                   if (is_char_node(v))
151                   {
152                     f = font(v);
153                     break_width[1] = break_width[1] - char_width(f, char_info(f, character(v)));
154                   }
155                   else switch (type(v))
156                   {
157                     case ligature_node:
158                       {
159                         f = font(lig_char(v));
160                         break_width[1] = break_width[1] - char_width(f, char_info(f, character(lig_char(v))));
161                       }
162                       break;
163
164                     case hlist_node:
165                     case vlist_node:
166                     case rule_node:
167                     case kern_node:
168                       break_width[1] = break_width[1] - width(v);
169                       break;
170
171                     default:
172                       {
173                         confusion("disc1");
174                         return;
175                       }
176                       break;
177                   }
178                 }
179
180                 while (s != 0)
181                 {
182                   if (is_char_node(s))
183                   {
184                     f = font(s);
185                     break_width[1] = break_width[1] + char_width(f, char_info(f, character(s)));
186                   }
187                   else switch(type(s))
188                   {
189                     case ligature_node:
190                       {
191                         f = font(lig_char(s));
192                         break_width[1] = break_width[1] + char_width(f, char_info(f, character(lig_char(s))));
193                       }
194                       break;
195
196                     case hlist_node:
197                     case vlist_node:
198                     case rule_node:
199                     case kern_node:
200                       break_width[1] = break_width[1] + width(s);
201                       break;
202
203                     default:
204                       {
205                         confusion("disc2");
206                         return;
207                       }
208                       break;
209                   }
210
211                   s = link(s);
212                 }
213
214                 break_width[1] = break_width[1] + disc_width;
215
216                 if (post_break(cur_p) == 0)
217                   s = link(v);
218               }
219
220               while (s != 0)
221               {
222                 if (is_char_node(s))
223                   goto done;
224
225                 switch (type(s))
226                 {
227                   case glue_node:
228                     {
229                       v = glue_ptr(s);
230                       break_width[1] = break_width[1] - width(v);
231                       break_width[2 + stretch_order(v)] = break_width[2 + stretch_order(v)] - stretch(v);
232                       break_width[6] = break_width[6] - shrink(v);
233                     }
234                     break;
235
236                   case penalty_node:
237                     ;
238                     break;
239
240                   case math_node:
241                     break_width[1] = break_width[1] - width(s);
242                     break;
243
244                   case kern_node:
245                     if (subtype(s) != explicit)
246                       goto done;
247                     else
248                       break_width[1] = break_width[1] - width(s);
249                     break;
250
251                   default:
252                     goto done;
253                     break;
254                 }
255
256                 s = link(s);
257               }
258 done:;
259           }
260
261           if (type(prev_r) == delta_node)
262           {
263             do_all_six(convert_to_break_width);
264           }
265           else if (prev_r == active)
266           {
267             do_all_six(store_break_width);
268           }
269           else
270           {
271             q = get_node(delta_node_size);
272             link(q) = r;
273             type(q) = delta_node;
274             subtype(q) = 0;
275             do_all_six(new_delta_to_break_width);
276             link(prev_r) = q;
277             prev_prev_r = prev_r;
278             prev_r = q;
279           }
280
281           if (abs(adj_demerits) >= awful_bad - minimum_demerits)
282             minimum_demerits = awful_bad - 1;
283           else
284             minimum_demerits = minimum_demerits + abs(adj_demerits);
285
286           for (fit_class = very_loose_fit; fit_class <= tight_fit; fit_class++)
287           {
288             if (minimal_demerits[fit_class] <= minimum_demerits)
289             {
290               q = get_node(passive_node_size);
291               link(q) = passive;
292               passive = q;
293               cur_break(q) = cur_p;
294 #ifdef STAT
295               incr(pass_number);
296               serial(q) = pass_number;
297 #endif
298               prev_break(q) = best_place[fit_class];
299               q = get_node(active_node_size);
300               break_node(q) = passive;
301               line_number(q) = best_pl_line[fit_class] + 1;
302               fitness(q) = fit_class;
303               type(q) = break_type;
304               total_demerits(q) = minimal_demerits[fit_class];
305               link(q) = r;
306               link(prev_r) = q;
307               prev_r = q;
308 #ifdef STAT
309               if (tracing_paragraphs > 0)
310               {
311                 print_nl("@@");
312                 print_int(serial(passive));
313                 prints(": line ");
314                 print_int(line_number(q) - 1);
315                 print_char('.');
316                 print_int(fit_class);
317
318                 if (break_type == hyphenated)
319                   print_char('-');
320
321                 prints(" t=");
322                 print_int(total_demerits(q));
323                 prints(" -> @@");
324
325                 if (prev_break(passive) == 0)
326                   print_char('0');
327                 else
328                   print_int(serial(prev_break(passive)));
329               }
330 #endif /* STAT */
331             }
332
333             minimal_demerits[fit_class] = awful_bad;
334           }
335
336           minimum_demerits = awful_bad;
337
338           if (r != active)
339           {
340             q = get_node(delta_node_size);
341             link(q) = r;
342             type(q) = delta_node;
343             subtype(q) = 0;
344             do_all_six(new_delta_from_break_width);
345             link(prev_r) = q;
346             prev_prev_r = prev_r;
347             prev_r = q;
348           }
349         }
350
351         if (r == active)
352           goto exit;
353
354         if (l > easyline)
355         {
356           line_width = second_width;
357           old_l = max_halfword - 1; /*262142L*/ /* 2^18 - 2 ? */
358         }
359         else
360         {
361           old_l = l;
362
363           if (l > last_special_line)
364             line_width = second_width;
365           else if (par_shape_ptr == 0)
366             line_width = first_width;
367           else
368             line_width = mem[par_shape_ptr + 2 * l].cint;
369         }
370       }
371     }
372
373     {
374       artificial_demerits = false;
375       shortfall = line_width - cur_active_width[1];
376
377       if (shortfall > 0)
378         if ((cur_active_width[3] != 0) || (cur_active_width[4] != 0) || (cur_active_width[5] != 0))
379         {
380           b = 0;
381           fit_class = decent_fit;
382         }
383         else
384         {
385           if (shortfall > 7230584L)
386             if (cur_active_width[2] < 1663497L)
387             {
388               b = 10000;
389               fit_class = very_loose_fit;
390               goto done1;
391             }
392
393           b = badness(shortfall, cur_active_width[2]);
394
395           if (b > 12)
396             if (b > 99)
397               fit_class = very_loose_fit;
398             else
399               fit_class = loose_fit;
400           else
401             fit_class = decent_fit;
402 done1:;
403         }
404       else
405       {
406         if (- (integer) shortfall > cur_active_width[6])
407           b = inf_bad + 1;
408         else
409           b = badness(- (integer) shortfall, cur_active_width[6]);
410
411         if (b > 12)
412           fit_class = tight_fit;
413         else
414           fit_class = decent_fit;
415       }
416
417       if ((b > inf_bad) || (pi == eject_penalty))
418       {
419         if (final_pass && (minimum_demerits == awful_bad) && (link(r) == active) && (prev_r == active))
420           artificial_demerits = true;
421         else if (b > threshold)
422           goto deactivate;
423
424         node_r_stays_active = false;
425       }
426       else
427       {
428         prev_r = r;
429
430         if (b > threshold)
431           goto continu;
432
433         node_r_stays_active = true;
434       }
435
436       if (artificial_demerits)
437         d = 0;
438       else
439       {
440         d = line_penalty + b;
441
442         if (abs(d) >= 10000)
443           d = 100000000L;
444         else
445           d = d * d;
446
447         if (pi != 0)
448           if (pi > 0)
449             d = d + pi * pi;
450           else if (pi > -10000)
451             d = d - pi * pi;
452
453         if ((break_type == hyphenated) && (type(r) == hyphenated))
454           if (cur_p != 0)
455             d = d + double_hyphen_demerits;
456           else
457             d = d + final_hyphen_demerits;
458
459         if (abs(toint(fit_class)- toint(fitness(r))) > 1)
460           d = d + adj_demerits;
461       }
462
463 #ifdef STAT
464       if (tracing_paragraphs > 0)
465       {
466         if (printed_node != cur_p)
467         {
468           print_nl("");
469
470           if (cur_p == 0)
471             short_display(link(printed_node));
472           else
473           {
474             save_link = link(cur_p);
475             link(cur_p) = 0;
476             print_nl("");
477             short_display(link(printed_node));
478             link(cur_p) = save_link;
479           }
480
481           printed_node = cur_p;
482         }
483
484         print_nl("@");
485
486         if (cur_p == 0)
487           print_esc("par");
488         else if (type(cur_p) != glue_node)
489         {
490           if (type(cur_p) == penalty_node)
491             print_esc("penalty");
492           else if (type(cur_p) == disc_node)
493             print_esc("discretionary");
494           else if (type(cur_p) == kern_node)
495             print_esc("kern");
496           else
497             print_esc("math");
498         }
499
500         prints(" via @@");
501
502         if (break_node(r) == 0)
503           print_char('0');
504         else
505           print_int(serial(break_node(r)));
506
507         prints(" b=");
508
509         if (b > inf_bad)
510           print_char('*');
511         else
512           print_int(b);
513
514         prints(" p=");
515         print_int(pi);
516         prints(" d=");
517
518         if (artificial_demerits)
519           print_char('*');
520         else
521           print_int(d);
522       }
523 #endif /* STAT */
524
525       d = d + total_demerits(r);
526
527       if (d <= minimal_demerits[fit_class])
528       {
529         minimal_demerits[fit_class] = d;
530         best_place[fit_class] = break_node(r);
531         best_pl_line[fit_class] = l;
532
533         if (d < minimum_demerits)
534           minimum_demerits = d;
535       }
536
537       if (node_r_stays_active)
538         goto continu;
539 deactivate:
540       link(prev_r) = link(r);
541       free_node(r, active_node_size);
542
543       if (prev_r == active)
544       {
545         r = link(active);
546
547         if (type(r) == delta_node)
548         {
549           do_all_six(update_active);
550           do_all_six(copy_to_cur_active);
551           link(active) = link(r);
552           free_node(r, delta_node_size);
553         }
554       }
555       else if (type(prev_r) == delta_node)
556       {
557         r = link(prev_r);
558
559         if (r == active)
560         {
561           do_all_six(downdate_width);
562           link(prev_prev_r) = active;
563           free_node(prev_r, delta_node_size);
564           prev_r = prev_prev_r;
565         }
566         else if (type(r) == delta_node)
567         {
568           do_all_six(update_width);
569           do_all_six(combine_two_deltas);
570           link(prev_r) = link(r);
571           free_node(r, delta_node_size);
572         }
573       }
574     }
575   }
576 exit:
577   ;
578 #ifdef STAT
579   if (cur_p == printed_node)
580     if (cur_p != 0)
581       if (type(cur_p) == disc_node)
582       {
583         t = replace_count(cur_p);
584
585         while (t > 0)
586         {
587           decr(t);
588           printed_node = link(printed_node);
589         }
590       }
591 #endif /* STAT */
592 }
593 /* end of the old tex5.c here */
594 /* sec 0877 */
595 void post_line_break_(integer final_widow_penalty)
596 {
597   halfword q, r, s;
598   boolean disc_break;
599   boolean post_disc_break;
600   scaled cur_width;
601   scaled cur_indent;
602   quarterword t;
603   integer pen;
604   halfword cur_line;
605
606   q = break_node(best_bet);
607   cur_p = 0;
608
609   do
610     {
611       r = q;
612       q = prev_break(q);
613       next_break(r) = cur_p;
614       cur_p = r;
615     }
616   while (!(q == 0));
617
618   cur_line = prev_graf + 1;
619
620   do
621     {
622       q = cur_break(cur_p);
623       disc_break = false;
624       post_disc_break = false;
625
626       if (q != 0)
627         if (type(q) == glue_node)
628         {
629           delete_glue_ref(glue_ptr(q));
630           glue_ptr(q) = right_skip;
631           subtype(q) = right_skip_code + 1;
632           add_glue_ref(right_skip);
633           goto done;
634         }
635         else
636         {
637           if (type(q) == disc_node)
638           {
639             t = replace_count(q);
640
641             if (t == 0)
642               r = link(q);
643             else
644             {
645               r = q;
646
647               while (t > 1)
648               {
649                 r = link(r);
650                 decr(t);
651               }
652
653               s = link(r);
654               r = link(s);
655               link(s) = 0;
656               flush_node_list(link(q));
657               replace_count(q) = 0;
658             }
659
660             if (post_break(q) != 0)
661             {
662               s = post_break(q);
663
664               while (link(s) != 0)
665                 s = link(s);
666
667               link(s) = r;
668               r = post_break(q);
669               post_break(q) = 0;
670               post_disc_break = true;
671             }
672
673             if (pre_break(q) != 0)
674             {
675               s = prev_break(q);
676               link(q) = s;
677
678               while (link(s) != 0)
679                 s = link(s);
680
681               prev_break(q) = 0;
682               q = s;
683             }
684
685             link(q) = r;
686             disc_break = true;
687           }
688           else if ((type(q) == math_node) || (type(q) == kern_node))
689             width(q) = 0;
690         }
691       else
692       {
693         q = temp_head;
694
695         while (link(q) != 0)
696           q = link(q);
697       }
698
699       r = new_param_glue(right_skip_code);
700       link(r) = link(q);
701       link(q) = r;
702       q = r;
703 done:
704       r = link(q);
705       link(q) = 0;
706       q = link(temp_head);
707       link(temp_head) = r;
708
709       if (left_skip != 0)
710       {
711         r = new_param_glue(left_skip_code);
712         link(r) = q;
713         q = r;
714       }
715
716       if (cur_line > last_special_line)
717       {
718         cur_width = second_width;
719         cur_indent = second_indent;
720       }
721       else if (par_shape_ptr == 0)
722       {
723         cur_width = first_width;
724         cur_indent = first_indent;
725       }
726       else
727       {
728         cur_width = mem[par_shape_ptr + 2 * cur_line].cint;
729         cur_indent = mem[par_shape_ptr + 2 * cur_line - 1].cint;
730       }
731
732       adjust_tail = adjust_head;
733       just_box = hpack(q, cur_width, 0);
734       shift_amount(just_box) = cur_indent;
735       append_to_vlist(just_box);
736
737       if (adjust_head != adjust_tail)
738       {
739         link(tail) = link(adjust_head);
740         tail = adjust_tail;
741       }
742
743       adjust_tail = 0;
744
745       if (cur_line + 1 != best_line)
746       {
747         pen = inter_line_penalty;
748
749         if (cur_line == prev_graf + 1)
750           pen = pen + club_penalty;
751
752         if (cur_line + 2 == best_line)
753           pen = pen + final_widow_penalty;
754
755         if (disc_break)
756           pen = pen + broken_penalty;
757
758         if (pen != 0)
759         {
760           r = new_penalty(pen);
761           link(tail) = r;
762           tail = r;
763         }
764       }
765
766       incr(cur_line);
767       cur_p = next_break(cur_p);
768
769       if (cur_p != 0)
770         if (!post_disc_break)
771         {
772           r = temp_head;
773
774           while (true)
775           {
776             q = link(r);
777
778             if (q == cur_break(cur_p))
779               goto done1;
780
781             if (is_char_node(q))
782               goto done1;
783
784             if (non_discardable(q))
785               goto done1;
786
787             if (type(q) == kern_node)
788               if (subtype(q) != 1)
789                 goto done1;
790
791             r = q;
792           }
793 done1:
794           if (r != temp_head)
795           {
796             link(r) = 0;
797             flush_node_list(link(temp_head));
798             link(temp_head) = q;
799           }
800         }
801     }
802   while (!(cur_p == 0));
803
804   if ((cur_line != best_line) || (link(temp_head) != 0))
805   {
806     confusion("line breaking");
807     return;
808   }
809
810   prev_graf = best_line - 1;
811 }
812 /* sec 0906 */
813 small_number reconstitute_(small_number j, small_number n, halfword bchar, halfword hchar)
814 {
815   halfword p;
816   halfword t;
817   four_quarters q;
818   halfword cur_rh;
819   halfword test_char;
820   scaled w;
821   font_index k;
822
823   hyphen_passed = 0;
824   t = hold_head;
825   w = 0;
826   link(hold_head) = 0;
827   cur_l = hu[j];
828   cur_q = t;
829
830   if (j == 0)
831   {
832     ligature_present = init_lig;
833     p = init_list; 
834
835     if (ligature_present)
836       lft_hit = init_lft; 
837
838     while (p != 0)
839     {
840       append_charnode_to_t(character(p));
841       p = link(p);
842     }
843   }
844   else if (cur_l < 256)
845   {
846     append_charnode_to_t(cur_l);
847   }
848
849   lig_stack = 0;
850   set_cur_r();
851
852 continu:
853   if (cur_l == non_char)
854   {
855     k = bchar_label[hf];
856
857     if (k == non_address)
858       goto done;
859     else
860       q = font_info[k].qqqq;
861   }
862   else
863   {
864     q = char_info(hf, cur_l);
865
866     if (char_tag(q) != lig_tag)
867       goto done;
868
869     k = lig_kern_start(hf, q);
870     q = font_info[k].qqqq;
871
872     if (skip_byte(q) > stop_flag)
873     {
874       k = lig_kern_restart(hf, q);
875       q = font_info[k].qqqq;
876     }
877   }
878
879   if (cur_rh < non_char)
880     test_char = cur_rh;
881   else
882     test_char = cur_r;
883
884   while (true)
885   {
886     if (next_char(q) == test_char)
887       if (skip_byte(q) <= 128)
888         if (cur_rh < non_char)
889         {
890           hyphen_passed = j;
891           hchar = non_char;
892           cur_rh = non_char;
893           goto continu;
894         }
895         else
896         {
897           if (hchar < non_char)
898             if (odd(hyf[j]))
899             {
900               hyphen_passed = j;
901               hchar = non_char;
902             }
903
904           if (op_byte(q) < kern_flag)
905           {
906             if (cur_l == non_char)
907               lft_hit = true;
908
909             if (j == n)
910               if (lig_stack == 0)
911                 rt_hit = true;
912
913             check_interrupt();
914
915             switch (op_byte(q))
916             {
917               case 1:
918               case 5:
919                 {
920                   cur_l = rem_byte(q);
921                   ligature_present = true;
922                 }
923                 break;
924
925               case 2:
926               case 6:
927                 {
928                   cur_r = rem_byte(q);
929
930                   if (lig_stack != 0)
931                     character(lig_stack) = cur_r;
932                   else
933                   {
934                     lig_stack = new_lig_item(cur_r);
935
936                     if (j == n)
937                       bchar = non_char;
938                     else
939                     {
940                       p = get_avail();
941                       list_ptr(lig_stack) = p;
942                       character(p) = hu[j + 1];
943                       font(p) = hf;
944                     }
945                   }
946                 }
947                 break;
948
949               case 3:
950                 {
951                   cur_r = rem_byte(q);
952                   p = lig_stack;
953                   lig_stack = new_lig_item(cur_r);
954                   link(lig_stack) = p;
955                 }
956                 break;
957
958               case 7:
959               case 11:
960                 {
961                   if (ligature_present)
962                   {
963                     p = new_ligature(hf, cur_l, mem[cur_q].hh.rh);
964
965                     if (lft_hit)
966                     {
967                       mem[p].hh.b1 = 2;
968                       lft_hit = false;
969                     }
970
971                     mem[cur_q].hh.rh = p;
972                     t = p;
973                     ligature_present = false;
974                   }
975                   cur_q = t;
976                   cur_l = rem_byte(q);
977                   ligature_present = true;
978                 }
979                 break;
980
981               default:
982                 {
983                   cur_l = rem_byte(q);
984                   ligature_present = true;
985
986                   if (lig_stack != 0)
987                   {
988                     if (lig_ptr(lig_stack) != 0)
989                     {
990                       link(t) = lig_ptr(lig_stack);
991                       t = link(t);
992                       incr(j);
993                     }
994
995                     p = lig_stack;
996                     lig_stack = link(p);
997                     free_node(p, small_node_size);
998
999                     if (lig_stack == 0)
1000                     {
1001                       if (j < n)
1002                         cur_r = hu[j + 1];
1003                       else
1004                         cur_r = bchar;
1005
1006                       if (odd(hyf[j]))
1007                         cur_rh = hchar;
1008                       else
1009                         cur_rh = 256;
1010                     }
1011                     else
1012                       cur_r = character(lig_stack);
1013                   }
1014                   else if (j == n)
1015                     goto done;
1016                   else
1017                   {
1018                     append_charnode_to_t(cur_r);
1019                     incr(j);
1020                     set_cur_r();
1021                   }
1022                 }
1023                 break;
1024             }
1025
1026             if (op_byte(q) > 4)
1027               if (op_byte(q) != 7)
1028                 goto done;
1029
1030             goto continu;
1031           }
1032
1033           w = char_kern(hf, q);
1034           goto done;
1035         }
1036
1037     if (q.b0 >= stop_flag)
1038       if (cur_rh == non_char)
1039         goto done;
1040       else
1041       {
1042         cur_rh = non_char;
1043         goto continu;
1044       }
1045       
1046     k = k + skip_byte(q) + 1;
1047     q = font_info[k].qqqq;
1048   }
1049 done:
1050   wrap_lig(rt_hit);
1051
1052   if (w != 0)
1053   {
1054     link(t) = new_kern(w);
1055     t = link(t);
1056     w = 0;
1057   }
1058
1059   if (lig_stack != 0)        /* l.17841 */
1060   {
1061     cur_q = t;
1062     cur_l = character(lig_stack);
1063     ligature_present = true;
1064     pop_lig_stack();
1065     goto continu;
1066   }
1067
1068   return j;
1069 }
1070 /* sec 0895 */
1071 void hyphenate (void)
1072 {
1073 /*  char i, j, l;  */
1074   char i, j;
1075   int l;              /* 95/Jan/7 */
1076   halfword q, r, s;
1077   halfword bchar;
1078   halfword major_tail, minor_tail;
1079 /*  ASCII_code c;  */
1080   int c;              /* 95/Jan/7 */
1081   char c_loc;
1082 /*  integer r_count; */
1083   int r_count;           /* 95/Jan/7 */
1084   halfword hyf_node;
1085   trie_pointer z;
1086   integer v;
1087   hyph_pointer h;
1088   str_number k;
1089   pool_pointer u;
1090
1091   for (j = 0; j <= hn; j++)
1092     hyf[j] = 0;
1093
1094   h = hc[1];
1095   incr(hn);
1096   hc[hn] = cur_lang;
1097
1098   for (j = 2; j <= hn; j++)
1099     h = (h + h + hc[j]) % hyphen_prime;
1100
1101   while (true)
1102   {
1103     k = hyph_word[h];
1104
1105     if (k == 0)
1106       goto not_found;
1107
1108     if (length(k) < hn)
1109       goto not_found;
1110
1111     if (length(k) == hn)
1112     {
1113       j = 1;
1114       u = str_start[k];
1115
1116       do
1117         {
1118           if (str_pool[u] < hc[j])
1119             goto not_found;
1120
1121           if (str_pool[u] > hc[j])
1122             goto done;
1123
1124           incr(j);
1125           incr(u);
1126         }
1127       while (!(j > hn));
1128
1129       s = hyph_list[h];
1130
1131       while (s != 0)
1132       {
1133         hyf[info(s)] = 1;
1134         s = link(s);
1135       }
1136
1137       decr(hn);
1138       goto found;
1139     }
1140
1141 done:;
1142     if (h > 0)
1143       decr(h);
1144     else
1145       h = hyphen_prime;
1146   }
1147 not_found:
1148   decr(hn);
1149
1150   if (trie_trc[cur_lang + 1] != cur_lang)
1151     return;
1152
1153   hc[0] = 0;
1154   hc[hn + 1] = 0;
1155   hc[hn + 2] = 256;
1156
1157   for (j = 0; j <= hn - rhyf + 1; j++)
1158   {
1159     z = trie_trl[cur_lang + 1] + hc[j];
1160     l = j;
1161
1162     while (hc[l] == trie_trc[z])
1163     {
1164       if (trie_tro[z] != min_trie_op)
1165       {
1166         v = trie_tro[z];
1167
1168         do
1169           {
1170             v = v + op_start[cur_lang];
1171             i = l - hyf_distance[v];
1172
1173             if (hyf_num[v] > hyf[i])
1174               hyf[i]= hyf_num[v];
1175
1176             v = hyf_next[v];
1177           }
1178         while (!(v == min_trie_op));
1179       }
1180
1181       incr(l);
1182       z = trie_trl[z] + hc[l];
1183     }
1184   }
1185
1186 found:
1187   for (j = 0; j <= lhyf - 1; j++)
1188     hyf[j] = 0;
1189
1190   for (j = 0; j <= rhyf - 1; j++)
1191     hyf[hn - j]= 0;
1192
1193   for (j = lhyf; j <= hn - rhyf; j++)
1194     if (odd(hyf[j]))
1195       goto found1;
1196
1197   return;
1198
1199 found1:;
1200   q = link(hb);
1201   link(hb) = 0;
1202   r = link(ha);
1203   link(ha) = 0;
1204   bchar = hyfbchar;
1205
1206   if (is_char_node(ha))
1207     if (font(ha) != hf)
1208       goto found2;
1209     else
1210     {
1211       init_list = ha;
1212       init_lig = false;
1213       hu[0] = character(ha);
1214     }
1215   else if (type(ha) == ligature_node)
1216     if (font(lig_char(ha)) != hf)
1217       goto found2;
1218     else
1219     {
1220       init_list = lig_ptr(ha);
1221       init_lig = true;
1222       init_lft = (subtype(ha) > 1);
1223       hu[0] = character(lig_char(ha));
1224
1225       if (init_list == 0)
1226         if (init_lft)
1227         {
1228           hu[0] = 256;
1229           init_lig = false;
1230         }
1231
1232       free_node(ha, small_node_size);
1233     }
1234   else
1235   {
1236     if (!is_char_node(r))
1237       if (type(r) == ligature_node)
1238         if (subtype(r) > 1)
1239           goto found2;
1240
1241     j = 1;
1242     s = ha;
1243     init_list = 0;
1244     goto common_ending;
1245   }
1246
1247   s = cur_p;
1248
1249   while (link(s) != ha)
1250     s = link(s);
1251
1252   j = 0;
1253   goto common_ending;
1254 found2:
1255   s = ha;
1256   j = 0;
1257   hu[0] = 256;
1258   init_lig = false;
1259   init_list = 0;
1260 common_ending:
1261   flush_node_list(r);
1262
1263   do
1264     {
1265       l = j;
1266       j = reconstitute(j, hn, bchar, hyf_char) + 1;
1267
1268       if (hyphen_passed == 0)
1269       {
1270         link(s) = link(hold_head);
1271
1272         while (link(s) != 0) /* l.17903 */
1273           s = link(s);
1274
1275         if (odd(hyf[j - 1]))
1276         {
1277           l = j;
1278           hyphen_passed = j - 1;
1279           link(hold_head) = 0;
1280         }
1281       }
1282
1283       if (hyphen_passed > 0)
1284         do
1285           {
1286             r = get_node(small_node_size);
1287             link(r) = link(hold_head);
1288             type(r) = disc_node;
1289             major_tail = r;
1290             r_count = 0;
1291
1292             while (mem[major_tail].hh.rh != 0)
1293             {
1294               major_tail = link(major_tail);
1295               incr(r_count);
1296             }
1297
1298             i = hyphen_passed;
1299             hyf[i] = 0;
1300             minor_tail = 0;
1301             pre_break(r) = 0;
1302             hyf_node = new_character(hf, hyf_char);
1303
1304             if (hyf_node != 0)
1305             {
1306               incr(i);
1307               c = hu[i];
1308               hu[i] = hyf_char;
1309               free_avail(hyf_node);
1310             }
1311
1312             while (l <= i)
1313             {
1314               l = reconstitute(l, i, font_bchar[hf], non_char) + 1;
1315
1316               if (link(hold_head) != 0) /* BUG FIX ??? */
1317               {
1318                 if (minor_tail == 0)
1319                   pre_break(r) = link(hold_head);
1320                 else
1321                   link(minor_tail) = link(hold_head);
1322
1323                 minor_tail = link(hold_head);
1324
1325                 while (link(minor_tail) != 0)  /* BUG FIX */
1326                   minor_tail = link(minor_tail);
1327               }
1328             }
1329
1330             if (hyf_node != 0) /* if hyf_node<>null then l.17956 */
1331             {
1332               hu[i] = c;
1333               l = i;
1334               decr(i);
1335             }
1336
1337             minor_tail = 0;
1338             post_break(r) = 0;
1339             c_loc = 0;
1340
1341             if (bchar_label[hf] != non_address) /* i.e. 0 --- 96/Jan/15 */
1342             {
1343               decr(l);
1344               c = hu[l];
1345               c_loc = l;
1346               hu[l]= 256;
1347             }
1348
1349             while (l < j)
1350             {
1351               do
1352                 {
1353                   l = reconstitute(l, hn, bchar, 256) + 1;
1354
1355                   if (c_loc > 0)
1356                   {
1357                     hu[c_loc] = c;
1358                     c_loc = 0;
1359                   }
1360
1361                   if (link(hold_head) != 0)     /* BUG FIX */
1362                   {
1363                     if (minor_tail == 0) /* begin if minor_tail=null then */
1364                       post_break(r) = link(hold_head);
1365                     else
1366                       link(minor_tail) = link(hold_head);
1367
1368                     minor_tail = link(hold_head);
1369
1370                     while (link(minor_tail) != 0)    /* ??? */
1371                       minor_tail = link(minor_tail);
1372                   }
1373                 }
1374               while (!(l >= j));
1375
1376               while (l > j)
1377               {
1378                 j = reconstitute(j, hn, bchar, non_char) + 1;
1379                 link(major_tail) = link(hold_head);
1380
1381                 while (mem[major_tail].hh.rh != 0)
1382                 {
1383                   major_tail = link(major_tail);
1384                   incr(r_count);
1385                 }
1386               }
1387             }
1388
1389             if (r_count > 127)
1390             {
1391               link(s) = link(r);
1392               link(r) = 0;
1393               flush_node_list(r);
1394             }
1395             else
1396             {
1397               link(s) = r;
1398               replace_count(r) = r_count;
1399             }
1400
1401             s = major_tail;
1402             hyphen_passed = j - 1;
1403             link(hold_head) = 0;
1404           }
1405         while (!(! odd(hyf[j - 1])));
1406     }
1407   while (!(j > hn));
1408
1409   link(s) = q;
1410   flush_list(init_list);
1411 }
1412 /* sec 0934 */
1413 void new_hyph_exceptions (void)
1414 {
1415 /*  small_number n;  */ /* in 3.141 */
1416   char n;
1417 /*  small_number j;  */ /* in 3.141 */
1418   char j;
1419   hyph_pointer h;
1420   str_number k;
1421   halfword p;
1422   halfword q;
1423   str_number s, t;
1424   pool_pointer u, v;
1425
1426   scan_left_brace();
1427   set_cur_lang();
1428   n = 0;
1429   p = 0;
1430
1431   while (true)
1432   {
1433     get_x_token();
1434 reswitch:
1435     switch (cur_cmd)
1436     {
1437       case letter:
1438       case other_char:
1439       case char_given:
1440         if (cur_chr == '-')
1441         {
1442           if (n < 63)
1443           {
1444             q = get_avail();
1445             link(q) = p;
1446             info(q) = n;
1447             p = q;
1448           }
1449         }
1450         else
1451         {
1452           if (lc_code(cur_chr) == 0)
1453           {
1454             print_err("Not a letter");
1455             help2("Letters in \\hyphenation words must have \\lccode>0.",
1456                 "Proceed; I'll ignore the character I just read.");
1457             error();
1458           }
1459           else if (n < 63)
1460           {
1461             incr(n);
1462             hc[n] = lc_code(cur_chr);
1463           }
1464         }
1465         break;
1466
1467       case char_num:
1468         {
1469           scan_char_num();
1470           cur_chr = cur_val;
1471           cur_cmd = char_given;
1472           goto reswitch;
1473         }
1474         break;
1475
1476       case spacer:
1477       case right_brace:
1478         {
1479           if (n > 1)
1480           {
1481             incr(n);
1482             hc[n] = cur_lang;
1483             str_room(n);
1484             h = 0;
1485
1486             for (j = 1; j <= n; j++)
1487             {
1488               h = (h + h + hc[j]) % hyphen_prime;
1489               append_char(hc[j]);
1490             }
1491
1492             s = make_string();
1493
1494             if (hyph_count == hyphen_prime)
1495             {
1496               overflow("exception dictionary", hyphen_prime); /* exception dictionary - NOT DYNAMIC */
1497               return;
1498             }
1499
1500             incr(hyph_count);
1501
1502             while (hyph_word[h] != 0)
1503             {
1504               k = hyph_word[h];
1505
1506               if (length(k) < length(s))
1507                 goto found;
1508
1509               if (length(k) > length(s))
1510                 goto not_found;
1511
1512               u = str_start[k];
1513               v = str_start[s];
1514
1515               do
1516                 {
1517                   if (str_pool[u] < str_pool[v])
1518                     goto found;
1519
1520                   if (str_pool[u] > str_pool[v])
1521                     goto not_found;
1522
1523                   incr(u);
1524                   incr(v);
1525                 }
1526               while (!(u == str_start[k + 1]));
1527 found:
1528               q = hyph_list[h];
1529               hyph_list[h] = p;
1530               p = q;
1531               t = hyph_word[h];
1532               hyph_word[h] = s;
1533               s = t;
1534 not_found:;
1535               if (h > 0)
1536                 decr(h);
1537               else
1538                 h = hyphen_prime;
1539             }
1540
1541             hyph_word[h] = s;
1542             hyph_list[h] = p;
1543           }
1544
1545           if (cur_cmd == right_brace)
1546             return;
1547
1548           n = 0;
1549           p = 0;
1550         }
1551         break;
1552
1553       default:
1554         {
1555           print_err("Improper ");
1556           print_esc("hyphenation");
1557           prints(" will be flushed");
1558           help2("Hyphenation exceptions must contain only letters",
1559               "and hyphens. But continue; I'll forgive and forget.");
1560           error();
1561         }
1562         break;
1563     } /* end of switch */
1564   }
1565 }
1566 /* sec 0968 */
1567 halfword prune_page_top_(halfword p)
1568 {
1569   halfword prev_p;
1570   halfword q;
1571
1572   prev_p = temp_head;
1573   link(temp_head) = p;
1574
1575   while (p != 0)
1576     switch(type(p))
1577     {
1578       case hlist_node:
1579       case vlist_node:
1580       case rule_node:
1581         {
1582           q = new_skip_param(split_top_skip_code);
1583           link(prev_p) = q;
1584           link(q) = p;
1585
1586           if (width(temp_ptr) > height(p))
1587             width(temp_ptr) = width(temp_ptr) - height(p);
1588           else
1589             width(temp_ptr) = 0;
1590
1591           p = 0;
1592         }
1593         break;
1594
1595       case whatsit_node:
1596       case mark_node:
1597       case ins_node:
1598         {
1599           prev_p = p;
1600           p = link(prev_p);
1601         }
1602         break;
1603
1604       case glue_node:
1605       case kern_node:
1606       case penalty_node:
1607         {
1608           q = p;
1609           p = link(q);
1610           link(q) = 0;
1611           link(prev_p) = p;
1612           flush_node_list(q);
1613         }
1614         break;
1615
1616       default:
1617         {
1618           confusion("pruning");
1619           return 0;
1620         }
1621         break;
1622     }
1623
1624   return link(temp_head);
1625 }
1626 /* sec 0970 */
1627 halfword vert_break_(halfword p, scaled h, scaled d)
1628 {
1629   halfword prev_p;
1630   halfword q, r;
1631   integer pi;
1632   integer b;
1633   integer least_cost;
1634   halfword best_place;
1635   scaled prev_dp; 
1636 /*  small_number t;  */
1637   int t;              /* 95/Jan/7 */
1638   prev_p = p;
1639
1640   least_cost = awful_bad;
1641   do_all_six(set_height_zero);
1642   prev_dp = 0;
1643
1644   while (true)
1645   {
1646     if (p == 0)
1647       pi = eject_penalty;
1648     else switch(type(p))
1649     {
1650       case hlist_node:
1651       case vlist_node:
1652       case rule_node:
1653         {
1654           cur_height = cur_height + prev_dp + height(p);
1655           prev_dp = depth(p);
1656           goto not_found;
1657         }
1658         break;
1659
1660       case whatsit_node:
1661         goto not_found;
1662         break;
1663
1664       case glue_node:
1665         if (precedes_break(prev_p))
1666           pi = 0;
1667         else
1668           goto update_heights;
1669         break;
1670
1671       case kern_node:
1672         {
1673           if (link(p) == 0)
1674             t = penalty_node;
1675           else
1676             t = type(link(p));
1677
1678           if (t == glue_node)
1679             pi = 0;
1680           else
1681             goto update_heights;
1682         }
1683         break;
1684
1685       case penalty_node:
1686         pi = penalty(p);
1687         break;
1688
1689       case mark_node:
1690       case ins_node:
1691         goto not_found;
1692         break;
1693
1694       default:
1695         {
1696           confusion("vertbreak");
1697           return 0;
1698         }
1699         break;
1700     }
1701
1702     if (pi < inf_penalty)
1703     {
1704       if (cur_height < h)
1705         if ((active_width[3] != 0) || (active_width[4] != 0) || (active_width[5]!= 0))
1706           b = 0;
1707         else
1708           b = badness(h - cur_height, active_width[2]);
1709       else
1710         if (act_width - h > active_width[6])
1711           b = awful_bad;
1712         else
1713           b = badness(cur_height - h, active_width[6]);
1714
1715       if (b < awful_bad)
1716         if (pi <= eject_penalty)
1717           b = pi;
1718         else
1719           if (b < inf_bad)
1720             b = b + pi;
1721           else
1722             b = deplorable;
1723
1724       if (b <= least_cost)
1725       {
1726         best_place = p;
1727         least_cost = b;
1728         best_height_plus_depth = cur_height + prev_dp;
1729       }
1730
1731       if ((b == awful_bad) || (pi <= eject_penalty))
1732         goto done;
1733     }
1734
1735     if ((type(p) < glue_node) || (type(p) > kern_node))
1736       goto not_found;
1737
1738 update_heights:
1739     if (type(p) == kern_node)
1740       q = p;
1741     else
1742     {
1743       q = glue_ptr(p);
1744       active_width[2 + stretch_order(q)] = active_width[2 + stretch_order(q)] + stretch(q);
1745       active_width[6] = active_width[6] + shrink(q);
1746
1747       if ((shrink_order(q) != normal) && (shrink(q) != 0))
1748       {
1749         print_err("Infinite glue shrinkage found in box being split");
1750         help4("The box you are \\vsplitting contains some infinitely",
1751             "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
1752             "Such glue doesn't belong there; but you can safely proceed,",
1753             "since the offensive shrinkability has been made finite.");
1754         error();
1755         r = new_spec(q);
1756         shrink_order(r) = normal;
1757         delete_glue_ref(q);
1758         glue_ptr(p) = r;
1759         q = r;
1760       }
1761     }
1762
1763     cur_height = cur_height + prev_dp + width(q);
1764     prev_dp = 0;
1765 not_found:
1766     if (prev_dp > d)
1767     {
1768       cur_height = cur_height + prev_dp - d;
1769       prev_dp = d;
1770     }
1771
1772     prev_p = p;
1773     p = link(prev_p);
1774   }
1775
1776 done:
1777   return best_place;
1778 }
1779 /* sec 0977 */
1780 halfword vsplit_(eight_bits n, scaled h)
1781 {
1782   halfword v;
1783   halfword p;
1784   halfword q;
1785
1786   v = box(n);
1787
1788   if (split_first_mark != 0)
1789   {
1790     delete_token_ref(split_first_mark);
1791     split_first_mark = 0;
1792     delete_token_ref(split_bot_mark);
1793     split_bot_mark = 0;
1794   }
1795
1796   if (v == 0)
1797   {
1798     return 0;
1799   }
1800
1801   if (type(v) != vlist_node)
1802   {
1803     print_err("");
1804     print_esc("vsplit");
1805     prints(" needs a ");
1806     print_esc("vbox");
1807     help2("The box you are trying to split is an \\hbox.",
1808         "I can't split such a box, so I'll leave it alone.");
1809     error();
1810     return 0;
1811   }
1812
1813   q = vert_break(list_ptr(v), h, split_max_depth);
1814   p = list_ptr(v);
1815
1816   if (p == q)
1817     list_ptr(v) = 0;
1818   else while (true)
1819   {
1820     if (type(p) == mark_node)
1821       if (split_first_mark == 0)
1822       {
1823         split_first_mark = mark_ptr(p);
1824         split_bot_mark = split_first_mark;
1825         token_ref_count(split_first_mark) = token_ref_count(split_first_mark) + 2;
1826       }
1827       else
1828       {
1829         delete_token_ref(split_bot_mark);
1830         split_bot_mark = mark_ptr(p);
1831         add_token_ref(split_bot_mark);
1832       }
1833
1834     if (link(p) == q)
1835     {
1836       link(p) = 0;
1837       goto done;
1838     }
1839     p = link(p);
1840   }
1841 done:;
1842   q = prune_page_top(q);
1843   p = list_ptr(v);
1844   free_node(v, box_node_size);
1845  
1846   if (q == 0)
1847     box(n) = 0;
1848   else
1849     box(n) = vpackage(q, 0, 1, 1073741823L);  /* 2^30 - 1 */
1850
1851   return vpackage(p, h, exactly, split_max_depth);
1852 }
1853 /* sec 0985 */
1854 void print_totals (void)
1855 {
1856   print_scaled(page_so_far[1]);
1857
1858   if (page_so_far[2] != 0)
1859   {
1860     prints(" plus ");
1861     print_scaled(page_so_far[2]);
1862     prints("");
1863   }
1864
1865   if (page_so_far[3] != 0)
1866   {
1867     prints(" plus ");
1868     print_scaled(page_so_far[3]);
1869     prints("fil");
1870   }
1871
1872   if (page_so_far[4] != 0)
1873   {
1874     prints(" plus ");
1875     print_scaled(page_so_far[4]);
1876     prints("fill");
1877   }
1878
1879   if (page_so_far[5] != 0)
1880   {
1881     prints(" plus ");
1882     print_scaled(page_so_far[5]);
1883     prints("filll");
1884   }
1885
1886   if (page_so_far[6] != 0)
1887   {
1888     prints(" minus ");
1889     print_scaled(page_so_far[6]);
1890   }
1891 }
1892 /* sec 0987 */
1893 void freeze_page_specs_(small_number s)
1894 {
1895   page_contents = s;
1896   page_goal = vsize;
1897   page_max_depth = max_depth;
1898   page_depth = 0;
1899   do_all_six(set_page_so_far_zero);
1900   least_page_cost = awful_bad;
1901
1902 #ifdef STAT
1903   if (tracing_pages > 0)
1904   {
1905     begin_diagnostic();
1906     print_nl("%% goal height=");
1907     print_scaled(page_goal);
1908     prints(", max depth=");
1909     print_scaled(page_max_depth);
1910     end_diagnostic(false);
1911   }
1912 #endif
1913 }
1914 /* sec 0992 */
1915 void box_error_(eight_bits n)
1916 {
1917   error();
1918   begin_diagnostic();
1919   print_nl("The following box has been deleted:");
1920   show_box(box(n));
1921   end_diagnostic(true);
1922   flush_node_list(box(n));
1923   box(n) = 0;
1924 }
1925 /* sec 0993 */
1926 void ensure_vbox_(eight_bits n)
1927 {
1928   halfword p;
1929
1930   p = box(n);
1931
1932   if (p != 0)
1933     if (type(p) == hlist_node)
1934     {
1935       print_err("Insertions can only be added to a vbox");
1936       help3("Tut tut: You're trying to \\insert into a",
1937           "\\box register that now contains an \\hbox.",
1938           "Proceed, and I'll discard its present contents.");
1939       box_error(n);
1940     }
1941 }
1942 /* sec 1012 */
1943 void fire_up_(halfword c)
1944 {
1945   pointer p, q, r, s;
1946   pointer prev_p;
1947 /*  unsigned char n;  */
1948   unsigned int n;         /* 95/Jan/7 */
1949   boolean wait;
1950   integer save_vbadness;
1951   scaled save_vfuzz;
1952   pointer save_split_top_skip;
1953
1954   if (type(best_page_break) == penalty_node)
1955   {
1956     geq_word_define(int_base + output_penalty_code, penalty(best_page_break));
1957     penalty(best_page_break) = inf_penalty;
1958   }
1959   else
1960     geq_word_define(int_base + output_penalty_code, inf_penalty);
1961
1962   if (bot_mark != 0)
1963   {
1964     if (top_mark != 0)
1965       delete_token_ref(top_mark);
1966
1967     top_mark = bot_mark;
1968     add_token_ref(top_mark);
1969     delete_token_ref(first_mark);
1970     first_mark = 0;
1971   }
1972
1973   if (c == best_page_break)
1974     best_page_break = 0;
1975
1976   if (box(255) != 0)
1977   {
1978     print_err("");
1979     print_esc("box");
1980     prints("255 is not void");
1981     help2("You shouldn't use \\box255 except in \\output routines.",
1982         "Proceed, and I'll discard its present contents.");
1983     box_error(255);
1984   }
1985
1986   insert_penalties = 0;
1987   save_split_top_skip = split_top_skip;
1988
1989   if (holding_inserts <= 0)
1990   {
1991     r = link(page_ins_head);
1992
1993     while (r != page_ins_head)
1994     {
1995       if (best_ins_ptr(r) != 0)
1996       {
1997         n = subtype(r);
1998         ensure_vbox(n);
1999
2000         if (box(n) == 0)
2001           box(n) = new_null_box();
2002
2003         p = box(n) + list_offset;
2004
2005         while (link(p) != 0)
2006           p = link(p);
2007
2008         last_ins_ptr(r) = p;
2009       }
2010
2011       r = link(r);
2012     }
2013   }
2014
2015   q = hold_head;
2016   link(q) = 0;
2017   prev_p = page_head;
2018   p = link(prev_p);
2019
2020   while (p != best_page_break)
2021   {
2022     if (type(p) == ins_node)
2023     {
2024       if (holding_inserts <= 0)
2025       {
2026         r = link(page_ins_head);
2027
2028         while (subtype(r) != subtype(p))
2029           r = link(r);
2030
2031         if (best_ins_ptr(r) == 0)
2032           wait = true;
2033         else
2034         {
2035           wait = false;
2036           s = last_ins_ptr(r);
2037           link(s) = ins_ptr(p);
2038
2039           if (best_ins_ptr(r) == p)
2040           {
2041             if (type(r) == split_up)
2042               if ((broken_ins(r) == p) && (broken_ins(r) != 0))
2043               {
2044                 while (link(s) != broken_ptr(r))
2045                   s = link(s);
2046
2047                 link(s) = 0;
2048                 split_top_skip = split_top_ptr(p);
2049                 ins_ptr(p) = prune_page_top(broken_ptr(r));
2050
2051                 if (ins_ptr(p) != 0)
2052                 {
2053                   temp_ptr = vpackage(ins_ptr(p), 0, 1, 1073741823L);  /* 2^30 - 1 */
2054                   height(p) = height(temp_ptr) + depth(temp_ptr);
2055                   free_node(temp_ptr, box_node_size);
2056                   wait = true;
2057                 }
2058               }
2059
2060             best_ins_ptr(r) = 0;
2061             n = subtype(r);
2062             temp_ptr = list_ptr(box(n));
2063             free_node(box(n), box_node_size);
2064             box(n) = vpackage(temp_ptr, 0, 1, 1073741823L);  /* 2^30 - 1 */
2065           }
2066           else
2067           {
2068             while (link(s) != 0)
2069               s = link(s);
2070
2071             last_ins_ptr(r) = s;
2072           }
2073         }
2074
2075         link(prev_p) = link(p);
2076         link(p) = 0;
2077
2078         if (wait)
2079         {
2080           link(q) = p;
2081           q = p;
2082           incr(insert_penalties);
2083         }
2084         else
2085         {
2086           delete_glue_ref(split_top_ptr(p));
2087           free_node(p, ins_node_size);
2088         }
2089
2090         p = prev_p;
2091       }
2092     }
2093     else if (type(p) == mark_node)
2094     {
2095       if (first_mark == 0)
2096       {
2097         first_mark = mark_ptr(p);
2098         add_token_ref(first_mark);
2099       }
2100
2101       if (bot_mark != 0)
2102         delete_token_ref(bot_mark);
2103
2104       bot_mark = mark_ptr(p);
2105       add_token_ref(bot_mark);
2106     }
2107     prev_p = p;
2108     p = link(prev_p);
2109   }
2110
2111   split_top_skip = save_split_top_skip;
2112
2113   if (p != 0)
2114   {
2115     if (link(contrib_head) == 0)
2116       if (nest_ptr == 0)
2117         tail = page_tail;
2118       else
2119         nest[0].tail_field = page_tail;
2120
2121     link(page_tail) = link(contrib_head);
2122     link(contrib_head) = p;
2123     link(prev_p) = 0;
2124   }
2125
2126   save_vbadness = vbadness;
2127   vbadness = inf_bad;
2128   save_vfuzz = vfuzz;
2129   vfuzz = max_dimen;
2130   box(255) = vpackage(link(page_head), best_size, 0, page_max_depth);
2131   vbadness = save_vbadness;
2132   vfuzz = save_vfuzz;
2133
2134   if (last_glue != empty_flag)
2135     delete_glue_ref(last_glue);
2136
2137   page_contents = 0;
2138   page_tail = page_head;
2139   link(page_head) = 0;
2140   last_glue = empty_flag;
2141   last_penalty = 0;
2142   last_kern = 0;
2143   page_depth = 0;
2144   page_max_depth = 0;
2145
2146   if (q != hold_head)
2147   {
2148     link(page_head) = link(hold_head);
2149     page_tail = q;
2150   }
2151
2152   r = link(page_ins_head);
2153
2154   while (r != page_ins_head)
2155   {
2156     q = link(r);
2157     free_node(r, page_ins_node_size);
2158     r = q;
2159   }
2160  
2161   link(page_ins_head) = page_ins_head;
2162
2163   if ((top_mark != 0) && (first_mark == 0))
2164   {
2165     first_mark = top_mark;
2166     add_token_ref(top_mark);
2167   }
2168
2169   if (output_routine != 0)
2170     if (dead_cycles >= max_dead_cycles)
2171     {
2172       print_err("Output loop---");
2173       print_int(dead_cycles);
2174       prints(" consecutive dead cycles");
2175       help3("I've concluded that your \\output is awry; it never does",
2176           "\\ship_out, so I'm shipping \box255 out myself. Next ",
2177           "increase \\maxdeadcycles if you want me to be more patient!");
2178       error();
2179     }
2180     else
2181     {
2182       output_active = true;
2183       incr(dead_cycles);
2184       push_nest();
2185       mode = -vmode;
2186       prev_depth = ignore_depth;
2187       mode_line = - (integer) line;
2188       begin_token_list(output_routine, output_text);
2189       new_save_level(output_group);
2190       normal_paragraph();
2191       scan_left_brace();
2192       return;
2193     }
2194
2195   {
2196     if (link(page_head) != 0)
2197     {
2198       if (link(contrib_head) == 0)
2199         if (nest_ptr == 0)
2200           tail = page_tail;
2201         else
2202           nest[0].tail_field = page_tail;
2203       else
2204         link(page_tail) = link(contrib_head);
2205
2206       link(contrib_head) = link(page_head);
2207       link(page_head) = 0;
2208       page_tail = page_head;
2209     }
2210
2211     ship_out(box(255));
2212     box(255) = 0;
2213   }
2214 }