OSDN Git Service

8a0686277cc489ae896d1e903f69af6aa36271ff
[putex/putex.git] / src / texsourc / tex7.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 0994 */
23 void build_page (void)
24 {
25   halfword p;
26   halfword q, r;
27   integer b, c;
28   integer pi;
29 /*  unsigned char n;  */
30   unsigned int n;             /* 95/Jan/7 */
31   scaled delta, h, w;
32
33   if ((link(contrib_head) == 0) || output_active)
34     return;
35
36   do
37     {
38 lab22:
39       p = link(contrib_head);
40
41       if (last_glue != max_halfword)
42         delete_glue_ref(last_glue);
43
44       last_penalty = 0;
45       last_kern = 0;
46
47       if (type(p) == glue_node)
48       {
49         last_glue = glue_ptr(p);
50         add_glue_ref(last_glue);
51       }
52       else
53       {
54         last_glue = max_halfword;
55
56         if (type(p) == penalty_node)
57           last_penalty = penalty(p);
58         else if (type(p) == kern_node)
59           last_kern = width(p);
60       }
61
62       switch (type(p))
63       {
64         case hlist_node:
65         case vlist_node:
66         case rule_node:
67           if (page_contents < box_there)
68           {
69             if (page_contents == 0)
70               freeze_page_specs(box_there);
71             else
72               page_contents = box_there;
73
74             q = new_skip_param(top_skip_code);
75
76             if (width(temp_ptr) > height(p))
77               width(temp_ptr) = width(temp_ptr) - height(p);
78             else
79               width(temp_ptr) = 0;
80
81             link(q) = p;
82             link(contrib_head) = q;
83             goto lab22;
84           }
85           else
86           {
87             page_total = page_total + page_depth + height(p);
88             page_depth = depth(p);
89             goto lab80;
90           }
91           break;
92
93         case whatsit_node:
94           goto lab80;
95           break;
96
97         case glue_node:
98           if (page_contents < box_there)
99             goto lab31;
100           else if (precedes_break(page_tail))
101             pi = 0;
102           else
103             goto lab90;
104           break;
105
106         case kern_node:
107           if (page_contents < box_there)
108             goto lab31;
109           else if (link(p) == 0)
110             return;
111           else if (type(link(p)) == glue_node)
112             pi = 0;
113           else
114             goto lab90;
115           break;
116
117         case penalty_node:
118           if (page_contents < box_there)
119             goto lab31;
120           else
121             pi = penalty(p);
122           break;
123
124         case mark_node:
125           goto lab80;
126           break;
127
128         case ins_node:
129           {
130             if (page_contents == 0)
131               freeze_page_specs(inserts_only);
132
133             n = subtype(p);
134             r = page_ins_head;
135
136             while (n >= subtype(link(r)))
137               r = link(r);
138
139             n = n;
140
141             if (subtype(r) != n)
142             {
143               q = get_node(page_ins_node_size);
144               link(q) = link(r);
145               link(r) = q;
146               r = q;
147               subtype(r) = n;
148               type(r) = inserting;
149               ensure_vbox(n);
150
151               if (box(n) == 0)
152                 height(r) = 0;
153               else
154                 height(r) = height(box(n)) + depth(box(n));
155
156               best_ins_ptr(r) = 0;
157               q = skip(n);
158
159               if (count(n) == 1000)
160                 h = height(r);
161               else
162                 h = x_over_n(height(r), 1000) * count(n);
163
164               page_goal = page_goal - h - width(q);
165               page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
166               page_shrink = page_shrink + shrink(q);
167
168               if ((shrink_order(q) != normal) && (shrink(q) != 0))
169               {
170                 print_err("Infinite glue shrinkage inserted from ");
171                 print_esc("skip");
172                 print_int(n);
173                 help3("The correction glue for page breaking with insertions",
174                     "must have finite shrinkability. But you may proceed,",
175                     "since the offensive shrinkability has been made finite.");
176                 error();
177               }
178             }
179
180             if (type(r) == split_up)
181               insert_penalties = insert_penalties + float_cost(p);
182             else
183             {
184               last_ins_ptr(r) = p;
185               delta = page_goal - page_total - page_depth + page_shrink;
186
187               if (count(n) == 1000)
188                 h = height(p);
189               else
190                 h = x_over_n(height(p), 1000) * count(n);
191
192               if (((h <= 0) || (h <= delta)) && (height(p) + height(r) <= dimen(n)))
193               {
194                 page_goal = page_goal - h;
195                 height(r) = height(r) + height(p);
196               }
197               else
198               {
199                 if (count(n) <= 0)
200                   w = max_dimen;  /* 2^30 - 1 */
201                 else
202                 {
203                   w = page_goal - page_total - page_depth;
204
205                   if (count(n) != 1000)
206                     w = x_over_n(w, count(n)) * 1000;
207                 }
208
209                 if (w > dimen(n) - height(r))
210                   w = dimen(n) - height(r);
211
212                 q = vert_break(ins_ptr(p), w, depth(p));
213                 height(r) = height(r) + best_height_plus_depth;
214
215 #ifdef STAT
216                 if (tracing_pages > 0)
217                 {
218                   begin_diagnostic();
219                   print_nl("% split");
220                   print_int(n);
221                   print_string(" to");
222                   print_scaled(w);
223                   print_char(',');
224                   print_scaled(best_height_plus_depth);
225                   print_string(" p=");
226
227                   if (q == 0)
228                     print_int(eject_penalty);
229                   else if (type(q) == penalty_node)
230                     print_int(penalty(q));
231                   else
232                     print_char('0');
233
234                   end_diagnostic(false);
235                 }
236 #endif
237                 if (count(n) != 1000)
238                   best_height_plus_depth = x_over_n(best_height_plus_depth, 1000) * count(n);
239
240                 page_goal = page_goal - best_height_plus_depth;
241                 type(r) = split_up;
242                 broken_ptr(r) = q;
243                 broken_ins(r) = p;
244
245                 if (q == 0)
246                   insert_penalties = insert_penalties + (eject_penalty);
247                 else if (type(q) == penalty_node)
248                   insert_penalties = insert_penalties + penalty(q);
249               }
250             }
251             goto lab80;
252           }
253           break;
254
255         default:
256           {
257             confusion("page");
258             return;
259           }
260           break;
261       }
262
263       if (pi < inf_penalty)
264       {
265         if (page_total < page_goal)
266           if ((page_so_far[3] != 0) || (page_so_far[4] != 0) || (page_so_far[5] != 0))
267             b = 0;
268           else
269             b = badness(page_goal - page_total, page_so_far[2]);
270         else if (page_total - page_goal > page_shrink)
271           b = awful_bad;
272         else
273           b = badness(page_total - page_goal, page_shrink);
274   
275         if (b < awful_bad)
276           if (pi <= eject_penalty)
277             c = pi; 
278           else if (b < inf_bad)
279             c = b + pi + insert_penalties;
280           else
281             c = deplorable;
282         else
283           c = b;
284
285         if (insert_penalties >= 10000)
286           c = awful_bad;  /* 2^30 - 1 */
287
288 #ifdef STAT
289         if (tracing_pages > 0)
290         {
291           begin_diagnostic();
292           print_nl("%");
293           print_string(" t=");
294           print_totals();
295           print_string(" g=");
296           print_scaled(page_goal);
297           print_string(" b=");
298
299           if (b == awful_bad) /* 2^30 - 1 */
300             print_char('*');
301           else
302             print_int(b);
303
304           print_string(" p=");
305           print_int(pi);
306           print_string(" c=");
307
308           if (c == awful_bad) /* 2^30 - 1 */
309             print_char('*');
310           else
311             print_int(c);
312
313           if (c <= least_page_cost)
314             print_char('#');
315
316           end_diagnostic(false);
317         }
318 #endif /* STAT */
319
320         if (c <= least_page_cost)
321         {
322           best_page_break = p;
323           best_size = page_goal;
324           least_page_cost = c;
325           r = link(page_ins_head);
326
327           while (r != page_ins_head)
328           {
329             best_ins_ptr(r) = last_ins_ptr(r);
330             r = link(r);
331           }
332         }
333
334         if ((c == awful_bad) || (pi <= eject_penalty))  /* 2^30 - 1 */
335         {
336           fire_up(p);
337
338           if (output_active)
339             return;
340
341           goto lab30;
342         }
343       }
344
345       if ((type(p) < glue_node) || (type(p) > kern_node))
346         goto lab80; 
347 lab90:
348       if (type(p) == kern_node)
349         q = p;
350       else
351       {
352         q = glue_ptr(p);
353         page_so_far[2 + stretch_order(q)] = page_so_far[2 + stretch_order(q)] + stretch(q);
354         page_shrink = page_shrink + shrink(q);
355
356         if ((shrink_order(q) != normal) && (shrink(q) != 0))
357         {
358           print_err("Infinite glue shrinkage found on current page");
359           help4("The page about to be output contains some infinitely",
360             "shrinkable glue, e.g., `\\vss' or `\\vskip 0pt minus 1fil'.",
361             "Such glue doesn't belong there; but you can safely proceed,",
362             "since the offensive shrinkability has been made finite.");
363           error();
364           r = new_spec(q);
365           shrink_order(r) = normal;
366           delete_glue_ref(q);
367           glue_ptr(p) = r;
368           q = r;
369         }
370       }
371
372       page_total = page_total + page_depth + width(q);
373       page_depth = 0;
374 lab80:
375       if (page_depth > page_max_depth)
376       {
377         page_total = page_total + page_depth - page_max_depth;
378         page_depth = page_max_depth;
379       }
380
381       link(page_tail) = p;
382       page_tail = p;
383       link(contrib_head) = link(p);
384       link(p) = 0;
385       goto lab30;
386 lab31:
387       link(contrib_head) = link(p);
388       link(p) = 0;
389       flush_node_list(p);
390 lab30:;
391     }
392   while (!(link(contrib_head) == 0));
393
394   if (nest_ptr == 0)
395     tail = contrib_head;
396   else
397     nest[0].tail_field = contrib_head;
398
399 /* sec 1043 */
400 void app_space (void)
401 {
402   pointer q;
403
404   if ((space_factor >= 2000) && (xspace_skip != zero_glue))
405     q = new_param_glue(xspace_skip_code);
406   else
407   {
408     if (space_skip != zero_glue)
409       main_p = space_skip;
410     else
411     {
412       main_p = font_glue[cur_font];
413
414       if (main_p == 0)
415       {
416         main_p = new_spec(zero_glue);
417         main_k = param_base[cur_font] + space_code;
418         width(main_p) = font_info[main_k].cint;
419         stretch(main_p) = font_info[main_k + 1].cint;
420         shrink(main_p) = font_info[main_k + 2].cint;
421         font_glue[cur_font] = main_p;
422       }
423     }
424
425     main_p = new_spec(main_p);
426
427     if (space_factor >= 2000)
428       width(main_p) = width(main_p) + extra_space(cur_font);
429
430     stretch(main_p) = xn_over_d(stretch(main_p), space_factor, 1000);
431     shrink(main_p) = xn_over_d(shrink(main_p), 1000, space_factor);
432     q = new_glue(main_p);
433     glue_ref_count(main_p) = 0;
434   }
435
436   link(tail) = q;
437   tail = q;
438 }
439 /* sec 1047 */
440 void insert_dollar_sign (void)
441 {
442   back_input();
443   cur_tok = math_shift_token + '$';
444   print_err("Missing $ inserted");
445   help2("I've inserted a begin-math/end-math symbol since I think",
446       "you left one out. Proceed, with fingers crossed.");
447   ins_error();
448 }
449 /* sec 1049 */
450 void you_cant (void)
451 {
452   print_err("You can't use `");
453   print_cmd_chr(cur_cmd, cur_chr);
454   print_string("' in ");
455   print_mode(mode);
456 }
457 /* sec 1050 */
458 void report_illegal_case (void)
459 {
460   you_cant();
461   help4("Sorry, but I'm not programmed to handle this case;",
462       "I'll just pretend that you didn't ask for it.",
463       "If you're in the wrong mode, you might be able to",
464       "return to the right one by typing `I}' or `I$' or `I\\par'.");
465   error();
466 }
467 /* sec 1051 */
468 boolean privileged (void)
469 {
470   if (mode > 0)
471     return true;
472   else
473   {
474     report_illegal_case();
475     return false;
476   }
477 }
478 /* sec 1054 */
479 boolean its_all_over (void)
480 {
481   if (privileged())
482   {
483     if ((page_head == page_tail) && (head == tail) && (dead_cycles == 0))
484     {
485       return true;
486     }
487
488     back_input();
489     tail_append(new_null_box());
490     width(tail) = hsize;
491     tail_append(new_glue(fill_glue));
492     tail_append(new_penalty(-1073741824L));
493     build_page();
494   }
495
496   return false;
497 }
498 /* sec 1060 */
499 void append_glue (void)
500 {
501   small_number s;
502
503   s = cur_chr;
504
505   switch(s)
506   {
507     case fil_code:
508       cur_val = fil_glue;
509       break;
510
511     case fill_code:
512       cur_val = fill_glue;
513       break;
514
515     case ss_code:
516       cur_val = ss_glue;
517       break;
518
519     case fil_neg_code:
520       cur_val = fil_neg_glue;
521       break;
522
523     case skip_code:
524       scan_glue(glue_val);
525       break;
526
527     case mskip_code:
528       scan_glue(mu_val);
529       break;
530   }
531
532   tail_append(new_glue(cur_val));
533
534   if (s >= skip_code)
535   {
536     decr(glue_ref_count(cur_val));
537
538     if (s > skip_code)
539       subtype(tail) = mu_glue;
540   }
541 }
542 /* sec 1061 */
543 void append_kern (void)
544
545   quarterword s;
546
547   s = cur_chr;
548
549   scan_dimen((s == mu_glue), false, false);
550   tail_append(new_kern(cur_val));
551   subtype(tail) = s;
552 }
553 /* sec 1064 */
554 void off_save (void)
555 {
556   pointer p;
557
558   if (cur_group == bottom_level)
559   {
560     print_err("Extra ");
561     print_cmd_chr(cur_cmd, cur_chr);
562     help1("Things are pretty mixed up, but I think the worst is over.");
563     error();
564   }
565   else
566   {
567     back_input();
568     p = get_avail();
569     link(temp_head) = p;
570     print_err("Missing ");
571
572     switch (cur_group)
573     {
574       case semi_simple_group:
575         {
576           info(p) = cs_token_flag + frozen_end_group;
577           print_esc("endgroup");
578         }
579         break;
580
581       case math_shift_group:
582         {
583           info(p) = math_shift_token + '$';
584           print_char('$');
585         }
586         break;
587
588       case math_left_group:
589         {
590           info(p) = cs_token_flag + frozen_right;
591           link(p) = get_avail();
592           p = link(p);
593           info(p) = other_token + '.';
594           print_esc("right.");
595         }
596         break;
597
598       default:
599         {
600           info(p) = right_brace_token + '}';
601           print_char('}');
602         }
603         break;
604     }
605
606     print_string(" inserted");
607     ins_list(link(temp_head));
608     help5("I've inserted something that you may have forgotten.",
609         "(See the <inserted text> above.)",
610         "With luck, this will get me unwedged. But if you",
611         "really didn't forget anything, try typing `2' now; then",
612         "my insertion and my current dilemma will both disappear.");
613     error();
614   }
615 }
616 /* sec 1069 */
617 void extra_right_brace (void)
618 {
619   print_err("Extra }, or forgotten ");
620
621   switch(cur_group)
622   {
623     case semi_simple_group:
624       print_esc("endgroup");
625       break;
626
627     case math_shift_group:
628       print_char('$');
629       break;
630
631     case math_left_group:
632       print_esc("right");
633       break;
634   }
635
636   help5("I've deleted a group-closing symbol because it seems to be",
637       "spurious, as in `$x}$'. But perhaps the } is legitimate and",
638       "you forgot something else, as in `\\hbox{$x}'. In such cases",
639       "the way to recover is to insert both the forgotten and the",
640       "deleted material, e.g., by typing `I$}'.");
641   error();
642   incr(align_state);
643 }
644 /* sec 1070 */
645 void normal_paragraph (void)
646 {
647   if (looseness != 0)
648     eq_word_define(int_base + looseness_code, 0);
649
650   if (hang_indent != 0)
651     eq_word_define(dimen_base + hang_indent_code, 0);
652
653   if (hang_after != 1)
654     eq_word_define(int_base + hang_after_code, 1);
655
656   if (par_shape_ptr != 0)
657     eq_define(par_shape_loc, shape_ref, 0);
658 }
659 /* sec 1075 */
660 void box_end_(integer box_context)
661 {
662   pointer p;
663
664   if (box_context < box_flag)
665   {
666     if (cur_box != 0)
667     {
668       shift_amount(cur_box) = box_context;
669
670       if (abs(mode) == vmode)
671       {
672         append_to_vlist(cur_box);
673
674         if (adjust_tail != 0)
675         {
676           if (adjust_head != adjust_tail)
677           {
678             link(tail) = link(adjust_head);
679             tail = adjust_tail;
680           }
681
682           adjust_tail = 0;
683         }
684
685         if (mode > 0)
686           build_page();
687       }
688       else
689       {
690         if (abs(mode) == hmode)
691           space_factor = 1000;
692         else
693         {
694           p = new_noad();
695           math_type(nucleus(p)) = sub_box;
696           info(nucleus(p)) = cur_box;
697           cur_box = p;
698         }
699
700         link(tail) = cur_box;
701         tail = cur_box;
702       }
703     }
704   }
705   else if (box_context < ship_out_flag)
706     if (box_context < (box_flag + 256))
707       eq_define((box_base - box_flag) + box_context, box_ref, cur_box);
708     else
709       geq_define((box_base - box_flag - 256) + box_context, box_ref, cur_box);
710   else if (cur_box != 0)
711     if (box_context > ship_out_flag)
712     {
713       do
714         {
715           get_x_token();
716         }
717       while (!((cur_cmd != spacer) && (cur_cmd != relax)));
718
719       if (((cur_cmd == hskip) && (abs(mode) != vmode)) || ((cur_cmd == vskip) && (abs(mode) == vmode)))
720       {
721         append_glue();
722         subtype(tail) = box_context - (leader_flag - a_leaders);
723         leader_ptr(tail) = cur_box;
724       }
725       else
726       {
727         print_err("Leaders not followed by proper glue");
728         help3("You should say `\\leaders <box or rule><hskip or vskip>'.",
729             "I found the <box or rule>, but there's no suitable",
730             "<hskip or vskip>, so I'm ignoring these leaders.");
731         back_error();
732         flush_node_list(cur_box);
733       }
734     }
735     else
736       ship_out(cur_box);
737 }
738 /* sec 1079 */
739 void begin_box_(integer box_context)
740 {
741   pointer p, q;
742   quarterword m;
743   halfword k;
744   eight_bits n;
745
746   switch(cur_chr)
747   {
748     case box_code:
749       {
750         scan_eight_bit_int();
751         cur_box = box(cur_val);
752         box(cur_val) = 0;
753       }
754       break;
755
756     case copy_code:
757       {
758         scan_eight_bit_int();
759         cur_box = copy_node_list(box(cur_val));
760       }
761       break;
762
763     case last_box_code:
764       {
765         cur_box = 0;
766
767         if (abs(mode) == mmode)
768         {
769           you_cant();
770           help1("Sorry; this \\lastbox will be void.");
771           error();
772         }
773         else if ((mode == vmode) && (head == cur_list.tail_field))
774         {
775           you_cant();
776           help2("Sorry...I usually can't take things from the current page.",
777               "This \\lastbox will therefore be void.");
778           error();
779         }
780         else
781         {
782           if (!is_char_node(tail))
783             if ((type(tail) == hlist_node) || (type(tail) == vlist_node))
784             {
785               q = head;
786
787               do
788                 {
789                   p = q;
790
791                   if (!is_char_node(q))
792                     if (type(q) == disc_node)
793                     {
794                       for (m = 1; m <= replace_count(q); m++)
795                         p = link(p);
796
797                       if (p == tail)
798                         goto lab30;
799                     }
800
801                   q = link(p);
802                 }
803               while (!(q == tail));
804
805               cur_box = tail;
806               shift_amount(cur_box) = 0;
807               tail = p;
808               link(p) = 0;
809 lab30:
810               ;
811             }
812         }
813       }
814       break;
815
816     case vsplit_code:
817       {
818         scan_eight_bit_int();
819         n = cur_val;
820
821         if (!scan_keyword("to"))
822         {
823           print_err("Missing `to' inserted");
824           help2("I'm working on `\\vsplit<box number> to <dimen>';",
825               "will look for the <dimen> next.");
826           error();
827         }
828
829         scan_dimen(false, false, false);
830         cur_box = vsplit(n, cur_val);
831       }
832       break;
833
834     default:
835       {
836         k = cur_chr - vtop_code;
837         saved(0) = box_context;
838
839         if (k == hmode)
840           if ((box_context < box_flag) && (abs(mode) == vmode))
841             scan_spec(adjust_hbox_group, true);
842           else
843             scan_spec(hbox_group, true);
844         else
845         {
846           if (k == vmode)
847             scan_spec(vbox_group, true);
848           else
849           {
850             scan_spec(vtop_group, true);
851             k = vmode;
852           }
853
854           normal_paragraph();
855         }
856
857         push_nest();
858         mode = - (integer) k;
859
860         if (k == vmode)
861         {
862           prev_depth = ignore_depth;
863
864           if (every_vbox != 0)
865             begin_token_list(every_vbox, every_vbox_text);
866         }
867         else
868         {
869           space_factor = 1000;
870
871           if (every_hbox != 0)
872             begin_token_list(every_hbox, every_vbox_text);
873         }
874         return;
875       }
876       break;
877   }
878
879   box_end(box_context);
880 }
881 /* sec 1084 */
882 void scan_box_(integer box_context)
883 {
884   do
885     {
886       get_x_token(); 
887     }
888   while (!((cur_cmd != spacer) && (cur_cmd != relax)));
889
890   if (cur_cmd == make_box)
891   {
892     begin_box(box_context);
893   }
894   else if ((box_context >= leader_flag) && ((cur_cmd == hrule) || (cur_cmd == vrule)))
895   {
896     cur_box = scan_rule_spec();
897     box_end(box_context);
898   }
899   else
900   {
901     print_err("A <box> was supposed to be here");
902     help3("I was expecting to see \\hbox or \\vbox or \\copy or \\box or",
903         "something like that. So you might find something missing in",
904         "your output. But keep trying; you can fix this later.");
905     back_error();
906   }
907 }
908 /****************************************************************************/
909 void package_ (small_number);
910 /****************************************************************************/
911 /* sec 1091 */
912 small_number norm_min_ (integer h)
913 {
914   if (h <= 0)
915     return 1;
916   else if (h >= 63)
917     return 63;
918   else
919     return h;
920 }
921 /* sec 1091 */
922 void new_graf_(boolean indented)
923 {
924   prev_graf = 0;
925
926   if ((mode == vmode) || (head != tail))
927     tail_append(new_param_glue(par_skip_code));
928
929   push_nest();
930   mode = hmode;
931   space_factor = 1000;
932   set_cur_lang();
933   clang = cur_lang;
934   prev_graf =(norm_min(left_hyphen_min) * 64 + norm_min(right_hyphen_min)) * 65536L + cur_lang;
935
936   if (indented)
937   {
938     tail = new_null_box();
939     link(head) = tail;
940     width(tail) = par_indent;
941   }
942
943   if (every_par != 0)
944     begin_token_list(every_par, every_par_text);
945
946   if (nest_ptr == 1)
947     build_page();
948 }
949 /* sec 1093 */
950 void indent_in_hmode (void)
951 {
952   pointer p, q;
953
954   if (cur_chr > 0)
955   {
956     p = new_null_box();
957     width(p) = par_indent;
958
959     if (abs(mode) == hmode)
960       space_factor = 1000;
961     else
962     {
963       q = new_noad();
964       math_type(nucleus(q)) = sub_box;
965       info(nucleus(q)) = p;
966       p = q;
967     }
968
969     tail_append(p);
970   }
971 }
972 /* sec 1095 */
973 void head_for_vmode (void)
974 {
975   if (mode < 0)
976   {
977     if (cur_cmd != hrule)
978       off_save();
979     else
980     {
981       print_err("You can't use `");
982       print_esc("hrule");
983       print_string("' here except with leaders");
984       help2("To put a horizontal rule in an hbox or an alignment,",
985           "you should use \\leaders or \\hrulefill (see The TeXbook).");
986       error();
987     }
988   }
989   else
990   {
991     back_input();
992     cur_tok = par_token;
993     back_input();
994     index = inserted;
995   }
996 }
997 /* sec 1096 */
998 void end_graf (void)
999 {
1000   if (mode == hmode)
1001   {
1002     if (head == tail)
1003       pop_nest();
1004     else
1005       line_break(widow_penalty);
1006
1007     normal_paragraph();
1008     error_count = 0;
1009   }
1010 }
1011 /* sec 1099 */
1012 void begin_insert_or_adjust (void)
1013 {
1014   if (cur_cmd == vadjust)
1015     cur_val = 255;
1016   else
1017   {
1018     scan_eight_bit_int();
1019
1020     if (cur_val == 255)
1021     {
1022       print_err("You can't ");
1023       print_esc("insert");
1024       print_int(255);
1025       help1("I'm changing to \\insert0; box 255 is special.");
1026       error();
1027       cur_val = 0;
1028     }
1029   }
1030
1031   saved(0) = cur_val;
1032   incr(save_ptr);
1033   new_save_level(insert_group);
1034   scan_left_brace();
1035   normal_paragraph();
1036   push_nest();
1037   mode = -vmode;
1038   prev_depth = ignore_depth;
1039 }
1040 /* sec 1101 */
1041 void make_mark (void)
1042 {
1043   pointer p;
1044
1045   p = scan_toks(false, true);
1046   p = get_node(small_node_size);
1047   type(p) = mark_node;
1048   subtype(p) = 0;
1049   mark_ptr(p) = def_ref;
1050   link(tail) = p;
1051   tail = p;
1052 }
1053 /* sec 1103 */
1054 void append_penalty (void)
1055 {
1056   scan_int();
1057   tail_append(new_penalty(cur_val));
1058
1059   if (mode == vmode)
1060     build_page();
1061 }
1062 /* sec 1105 */
1063 void delete_last (void)
1064 {
1065   pointer p, q;
1066   quarterword m;
1067
1068   if ((mode == vmode) && (tail == head))
1069   {
1070     if ((cur_chr != glue_node) || (last_glue != max_halfword))
1071     {
1072       you_cant();
1073       help2("Sorry...I usually can't take things from the current page.",
1074           "Try `I\\vskip-\\lastskip' instead.");
1075
1076       if (cur_chr == kern_node)
1077         help_line[0] = "Try `I\\kern-\\last_kern' instead.";
1078       else if (cur_chr != glue_node)
1079         help_line[0] = "Perhaps you can make the output routine do it.";
1080       error();
1081     }
1082   }
1083   else
1084   {
1085     if (!is_char_node(tail))
1086       if (type(tail) == cur_chr)
1087       {
1088         q = head;
1089
1090         do
1091           {
1092             p = q;
1093
1094             if (!is_char_node(q))
1095               if (type(q) == disc_node)
1096               {
1097                 for (m = 1; m <= replace_count(q); m++)
1098                   p = link(p);
1099
1100                 if (p == tail)
1101                   return;
1102               }
1103
1104             q = link(p);
1105           }
1106         while (!(q == tail));
1107
1108         link(p) = 0;
1109         flush_node_list(tail);
1110         tail = p;
1111       }
1112   }
1113 }
1114 /* sec 1110 */
1115 void unpackage (void)
1116 {
1117   pointer p;
1118   char c;
1119
1120   c = cur_chr;
1121   scan_eight_bit_int();
1122   p = box(cur_val);
1123
1124   if (p == 0)
1125     return;
1126
1127   if ((abs(mode) == mmode) || ((abs(mode) == vmode) && (type(p) != vlist_node)) ||
1128     ((abs(mode) == hmode) && (type(p) != hlist_node)))
1129   {
1130     print_err("Incompatible list can't be unboxed");
1131     help3("Sorry, Pandora. (You sneaky devil.)",
1132         "I refuse to unbox an \\hbox in vertical mode or vice versa.",
1133         "And I can't open any boxes in math mode.");
1134     error();
1135     return;
1136   }
1137
1138   if (c == copy_code)
1139     link(tail) = copy_node_list(list_ptr(p));
1140   else
1141   {
1142     link(tail) = list_ptr(p);
1143     box(cur_val) = 0;
1144     free_node(p, box_node_size);
1145   }
1146
1147   while (link(tail) != 0)
1148     tail = link(tail);
1149 }
1150 /* sec 1113 */
1151 void append_italic_correction (void)
1152 {
1153   pointer p;
1154   internal_font_number f;
1155
1156   if (tail != head)
1157   {
1158     if (is_char_node(tail))
1159       p = tail;
1160     else if (type(tail) == ligature_node)
1161       p = tail + 1;
1162     else
1163       return;
1164
1165     f = font(p);
1166     tail_append(new_kern(char_italic(f, char_info(f, character(p)))));
1167     subtype(tail) = explicit;
1168   }
1169 }
1170 /* sec 1117 */
1171 void append_discretionary (void)
1172 {
1173   integer c;
1174
1175   tail_append(new_disc());
1176
1177   if (cur_chr == 1)
1178   {
1179     c = hyphen_char[cur_font];
1180
1181     if (c >= 0)
1182       if (c < 256)
1183         pre_break(tail) = new_character(cur_font, c);
1184   }
1185   else
1186   {
1187     incr(save_ptr);
1188     saved(-1) = 0;
1189     new_save_level(disc_group);
1190     scan_left_brace();
1191     push_nest();
1192     mode = -hmode;
1193     space_factor = 1000;
1194   }
1195 }
1196 /* sec 1119 */
1197 void build_discretionary (void)
1198 {
1199   pointer p, q;
1200   integer n;
1201
1202   unsave();
1203   q = head;
1204   p = link(q);
1205   n = 0;
1206
1207   while (p != 0)
1208   {
1209     if (!is_char_node(p))
1210       if (type(p) > rule_node)
1211         if (type(p) != kern_node)
1212           if (type(p) != ligature_node)
1213           {
1214             print_err("Improper discretionary list");
1215             help1("Discretionary lists must contain only boxes and kerns.");
1216             error();
1217             begin_diagnostic();
1218             print_nl("The following discretionary sublist has been deleted:");
1219             show_box(p);
1220             end_diagnostic(true);
1221             flush_node_list(p);
1222             link(q) = 0;
1223             goto lab30;
1224           }
1225
1226     q = p;
1227     p = link(q);
1228     incr(n);
1229   }
1230
1231 lab30:
1232   p = link(head);
1233   pop_nest();
1234
1235   switch (saved(-1))
1236   {
1237     case 0:
1238       pre_break(tail) = p;
1239       break;
1240
1241     case 1:
1242       post_break(tail) = p;
1243       break;
1244
1245     case 2:
1246       {
1247         if ((n > 0) && (abs(mode) == mmode))
1248         {
1249           print_err("Illegal math ");
1250           print_esc("discretionary");
1251           help2("Sorry: The third part of a discretionary break must be",
1252               "empty, in math formulas. I had to delete your third part.");
1253           flush_node_list(p);
1254           n = 0;
1255           error();
1256         }
1257         else
1258           link(tail) = p;
1259
1260         if (n <= max_quarterword)
1261           replace_count(tail) = n;
1262         else
1263         {
1264           print_err("Discretionary list is too long");
1265           help2("Wow---I never thought anybody would tweak me here.",
1266               "You can't seriously need such a huge discretionary list?");
1267           error();
1268         }
1269
1270         if (n > 0)
1271           tail = q;
1272
1273         decr(save_ptr);
1274         return;
1275       }
1276       break;
1277   }
1278
1279   incr(saved(-1));
1280   new_save_level(disc_group);
1281   scan_left_brace();
1282   push_nest();
1283   mode = -hmode;
1284   space_factor = 1000;
1285 }
1286 /* sec 1123 */
1287 void make_accent (void)
1288 {
1289   real s, t;
1290   pointer p, q, r;
1291   internal_font_number f;
1292   scaled a, h, x, w, delta;
1293   four_quarters i;
1294
1295   scan_char_num();
1296   f = cur_font;
1297   p = new_character(f, cur_val);
1298
1299   if (p != 0)
1300   {
1301     x = x_height(f);
1302     s = slant(f) / ((double) 65536.0);
1303     a = char_width(f, char_info(f, character(p)));
1304     do_assignments();
1305     q = 0;
1306     f = cur_font;
1307
1308     if ((cur_cmd == letter) || (cur_cmd == other_char) || (cur_cmd == char_given))
1309       q = new_character(f, cur_chr);
1310     else if (cur_cmd == char_num)
1311     {
1312       scan_char_num();
1313       q = new_character(f, cur_val);
1314     }
1315     else
1316       back_input();
1317
1318     if (q != 0)
1319     {
1320       t = slant(f) / ((double) 65536.0);
1321       i = char_info(f, character(q));
1322       w = char_width(f, i);
1323       h = char_height(f, height_depth(i));
1324
1325       if (h != x)
1326       {
1327         p = hpack(p, 0, 1);
1328         shift_amount(p) = x - h;
1329       }
1330
1331       delta = round((w - a) / ((double) 2.0)+ h * t - x * s);
1332       r = new_kern(delta);
1333       subtype(r) = acc_kern;
1334       link(tail) = r;
1335       link(r) = p;
1336       tail = new_kern(- (integer) a - delta);
1337       subtype(tail) = acc_kern;
1338       link(p) = tail;
1339       p = q;
1340     }
1341
1342     link(tail) = p;
1343     tail = p;
1344     space_factor = 1000;
1345   }
1346 }
1347 /* sec 1127 */
1348 void align_error (void)
1349 {
1350   if (abs(align_state) > 2)
1351   {
1352     print_err("Misplaced ");
1353     print_cmd_chr(cur_cmd, cur_chr);
1354
1355     if (cur_tok == tab_token + '&')
1356     {
1357       help6("I can't figure out why you would want to use a tab mark",
1358           "here. If you just want an ampersand, the remedy is",
1359           "simple: Just type `I\\&' now. But if some right brace",
1360           "up above has ended a previous alignment prematurely,",
1361           "you're probably due for more error messages, and you",
1362           "might try typing `S' now just to see what is salvageable.");
1363     }
1364     else
1365     {
1366       help5("I can't figure out why you would want to use a tab mark",
1367           "or \\cr or \\span just now. If something like a right brace",
1368           "up above has ended a previous alignment prematurely,",
1369           "you're probably due for more error messages, and you",
1370           "might try typing `S' now just to see what is salvageable.");
1371     }
1372
1373     error();
1374   }
1375   else
1376   {
1377     back_input();
1378
1379     if (align_state < 0)
1380     {
1381       print_err("Missing { inserted");
1382       incr(align_state);
1383       cur_tok = left_brace_token + '{';
1384     }
1385     else
1386     {
1387       print_err("Missing } inserted");
1388       decr(align_state);
1389       cur_tok = right_brace_token + '}';
1390     }
1391
1392     help3("I've put in what seems to be necessary to fix",
1393         "the current column of the current alignment.",
1394         "Try to go on, since this might almost work.");
1395     ins_error();
1396   }
1397 }
1398 /* sec 1129 */
1399 void noalign_error (void)
1400 {
1401   print_err("Misplaced ");
1402   print_esc("noalign");
1403   help2("I expect to see \\noalign only after the \\cr of",
1404       "an alignment. Proceed, and I'll ignore this case.");
1405   error();
1406 }
1407 /* sec 1129 */
1408 void omit_error (void)
1409 {
1410   print_err("Misplaced ");
1411   print_esc("omit");
1412   help2("I expect to see \\omit only after tab marks or the \\cr of",
1413       "an alignment. Proceed, and I'll ignore this case.");
1414   error();
1415 }
1416 /* sec 1131 */
1417 void do_endv (void)
1418 {
1419   base_ptr = input_ptr;
1420   input_stack[base_ptr] = cur_input;
1421
1422   while ((input_stack[base_ptr].index_field != v_template) &&
1423     (input_stack[base_ptr].loc_field == 0) &&
1424     (input_stack[base_ptr].state_field == token_list))
1425     decr(base_ptr);
1426
1427   if ((input_stack[base_ptr].index_field != v_template) ||
1428     (input_stack[base_ptr].loc_field != 0) ||
1429     (input_stack[base_ptr].state_field != token_list))
1430     fatal_error("(interwoven alignment preambles are not allowed)");
1431
1432   if (cur_group == align_group)
1433   {
1434     end_graf();
1435
1436     if (fin_col ())
1437       fin_row();
1438   }
1439   else
1440     off_save();
1441 }
1442 /* sec 1135 */
1443 void cs_error (void)
1444 {
1445   print_err("Extra ");
1446   print_esc("endcsname");
1447   help1("I'm ignoring this, since I wasn't doing a \\csname."); 
1448   error();
1449 }
1450 /* sec 1136 */
1451 void push_math_(group_code c)
1452 {
1453   push_nest();
1454   mode = -mmode;
1455   incompleat_noad = 0;
1456   new_save_level(c);
1457 }
1458 /* sec 1138 */
1459 void init_math (void)
1460 {
1461   scaled w;
1462   scaled l;
1463   scaled s;
1464   pointer p;
1465   pointer q;
1466   internal_font_number f;
1467   integer n;
1468   scaled v;
1469   scaled d;
1470
1471   get_token();
1472
1473   if ((cur_cmd == math_shift) && (mode > 0))
1474   {
1475     if (head == tail)
1476     {
1477       pop_nest();
1478       w = -max_dimen; /* - (2^30 - 1) */
1479     }
1480     else
1481     {
1482       line_break(display_widow_penalty);
1483       v = shift_amount(just_box) + 2 * quad(cur_font);
1484       w = -max_dimen;  /* - (2^30 - 1) */
1485       p = list_ptr(just_box);
1486
1487       while (p != 0)
1488       {
1489 lab21:
1490         if (is_char_node(p))
1491         {
1492           f = font(p);
1493           d = char_width(f, char_info(f, character(p)));
1494           goto lab40;
1495         }
1496
1497         switch (type(p))
1498         {
1499           case hlist_node:
1500           case vlist_node:
1501           case rule_node:
1502             {
1503               d = width(p);
1504               goto lab40;
1505             }
1506             break;
1507
1508           case ligature_node:
1509             {
1510               mem[lig_trick] = mem[lig_char(p)];
1511               link(lig_trick) = link(p);
1512               p = lig_trick;
1513               goto lab21;
1514             }
1515             break;
1516
1517           case kern_node:
1518           case math_node:
1519             d = width(p);
1520             break;
1521
1522           case glue_node:
1523             {
1524               q = glue_ptr(p);
1525               d = width(q);
1526
1527               if (glue_sign(just_box) == stretching)
1528               {
1529                 if ((glue_order(just_box) == stretch_order(q)) && (stretch(q) != 0))
1530                   v = max_dimen;  /* - (2^30 - 1) */
1531               }
1532               else if (glue_sign(just_box) == shrinking)
1533               {
1534                 if ((glue_order(just_box) == shrink_order(q)) && (shrink(q) != 0))
1535                   v = max_dimen;  /* - (2^30 - 1) */
1536               }
1537
1538               if (subtype(p) >= a_leaders)
1539                 goto lab40;
1540             }
1541             break;
1542
1543           case whatsit_node:
1544             d = 0;
1545             break;
1546
1547           default:
1548             d = 0;
1549             break;
1550         }
1551
1552         if (v < max_dimen) /* - (2^30 - 1) */
1553           v = v + d;
1554
1555         goto lab45;
1556 lab40:
1557         if (v < max_dimen) /* - (2^30 - 1) */
1558         {
1559           v = v + d;
1560           w = v;
1561         }
1562         else
1563         {
1564           w = max_dimen;  /* - (2^30 - 1) */
1565           goto lab30;
1566         }
1567 lab45:
1568         p = link(p);
1569       }
1570 lab30:;
1571     }
1572
1573     if (par_shape_ptr == 0)
1574       if ((hang_indent != 0) && (((hang_after >= 0) &&
1575         (prev_graf + 2 > hang_after)) || (prev_graf + 1 < - (integer) hang_after)))
1576       {
1577         l = hsize - abs(hang_indent);
1578
1579         if (hang_indent > 0)
1580           s = hang_indent;
1581         else
1582           s = 0;
1583       }
1584       else
1585       {
1586         l = hsize;
1587         s = 0;
1588       }
1589     else
1590     {
1591       n = info(par_shape_ptr);
1592
1593       if (prev_graf + 2 >= n)
1594         p = par_shape_ptr + 2 * n;
1595       else
1596         p = par_shape_ptr + 2 *(prev_graf + 2);
1597
1598       s = mem[p - 1].cint;
1599       l = mem[p].cint;
1600     }
1601
1602     push_math(math_shift_group);
1603     mode = mmode;
1604     eq_word_define(int_base + cur_fam_code, -1);
1605     eq_word_define(dimen_base + pre_display_size_code, w);
1606     eq_word_define(dimen_base + display_width_code, l);
1607     eq_word_define(dimen_base + display_indent_code, s);
1608
1609     if (every_display != 0)
1610       begin_token_list(every_display, every_display_text);
1611
1612     if (nest_ptr == 1)
1613     {
1614       build_page();
1615     }
1616   }
1617   else
1618   {
1619     back_input();
1620
1621     {
1622       push_math(math_shift_group);
1623       eq_word_define(int_base + cur_fam_code, -1);
1624
1625       if (every_math != 0)
1626         begin_token_list(every_math, every_math_text);
1627     }
1628   }
1629 }
1630 /* sec 1142 */
1631 void start_eq_no (void)
1632 {
1633   saved(0) = cur_chr;
1634   incr(save_ptr);
1635
1636   {
1637     push_math(math_shift_group);
1638     eq_word_define(int_base + cur_fam_code, -1);
1639
1640     if (every_math != 0)
1641       begin_token_list(every_math, every_math_text);
1642   }
1643 }
1644 /* sec 1151 */
1645 void scan_math_(pointer p)
1646 {
1647   integer c;
1648
1649 lab20:
1650   do
1651     {
1652       get_x_token();
1653     }
1654   while (!((cur_cmd != spacer) && (cur_cmd != relax)));
1655
1656 lab21:
1657   switch (cur_cmd)
1658   {
1659     case letter:
1660     case other_char:
1661     case char_given:
1662       {
1663         c = math_code(cur_chr);
1664
1665         if (c == 32768L)
1666         {
1667           {
1668             cur_cs = cur_chr + active_base;
1669             cur_cmd = eq_type(cur_cs);
1670             cur_chr = equiv(cur_cs);
1671             x_token();
1672             back_input();
1673           }
1674
1675           goto lab20;
1676         }
1677       }
1678       break;
1679
1680     case char_num:
1681       {
1682         scan_char_num();
1683         cur_chr = cur_val;
1684         cur_cmd = char_given;
1685         goto lab21;
1686       }
1687       break;
1688
1689     case math_char_num:
1690       {
1691         scan_fifteen_bit_int();
1692         c = cur_val;
1693       }
1694       break;
1695
1696     case math_given:
1697       c = cur_chr;
1698       break;
1699
1700     case delim_num:
1701       {
1702         scan_twenty_seven_bit_int();
1703         c = cur_val / 4096;
1704       }
1705       break;
1706
1707     default:
1708       {
1709         back_input();
1710         scan_left_brace();
1711         saved(0) = p;
1712         incr(save_ptr);
1713         push_math(math_group);
1714         return;
1715       }
1716       break;
1717   }
1718
1719   math_type(p) = math_char;
1720   character(p) = c % 256;
1721
1722   if ((c >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
1723     fam(p) = cur_fam;
1724   else
1725     fam(p) = (c / 256) % 16;
1726 }
1727 /* sec 1155 */
1728 void set_math_char_(integer c)
1729 {
1730   pointer p;
1731
1732   if (c >= 32768L)
1733   {
1734     cur_cs = cur_chr + active_base;
1735     cur_cmd = eq_type(cur_cs);
1736     cur_chr = equiv(cur_cs);
1737     x_token();
1738     back_input();
1739   }
1740   else
1741   {
1742     p = new_noad();
1743     math_type(nucleus(p)) = math_char;
1744     character(nucleus(p)) = c % 256;
1745     fam(nucleus(p)) = (c / 256) % 16;
1746
1747     if (c >= var_code)
1748     {
1749       if (((cur_fam >= 0) && (cur_fam < 16)))
1750         fam(nucleus(p)) = cur_fam;
1751
1752       type(p) = ord_noad;
1753     }
1754     else
1755       type(p) = ord_noad + (c / 4096);
1756
1757     link(tail) = p;
1758     tail = p;
1759   }
1760 }
1761 /* sec 1159 */
1762 void math_limit_switch (void)
1763 {
1764   if (head != tail)
1765     if (type(tail) == op_noad)
1766     {
1767       subtype(tail) = cur_chr;
1768       return;
1769     }
1770
1771   print_err("Limit controls must follow a math operator");
1772   help1("I'm ignoring this misplaced \\limits or \\nolimits command.");
1773   error();
1774 }
1775 /* sec 1160 */
1776 void scan_delimiter_(pointer p, boolean r)
1777 {
1778    if (r)
1779    {
1780      scan_twenty_seven_bit_int();
1781    }
1782    else
1783    {
1784      do
1785       {
1786         get_x_token();
1787       }
1788      while (!((cur_cmd != spacer) && (cur_cmd != relax)));
1789
1790      switch (cur_cmd)
1791      {
1792        case letter:
1793        case other_char:
1794          cur_val = del_code(cur_chr);
1795          break;
1796
1797        case delim_num:
1798          scan_twenty_seven_bit_int();
1799          break;
1800
1801        default:
1802          cur_val = -1;
1803          break;
1804      }
1805    }
1806
1807    if (cur_val < 0)
1808    {
1809      print_err("Missing delimiter (. inserted)");
1810      help6("I was expecting to see something like `(' or `\\{' or",
1811          "`\\}' here. If you typed, e.g., `{' instead of `\\{', you",
1812          "should probably delete the `{' by typing `1' now, so that",
1813          "braces don't get unbalanced. Otherwise just proceed.",
1814          "Acceptable delimiters are characters whose \\delcode is",
1815          "nonnegative, or you can use `\\delimiter <delimiter code>'.");
1816      back_error();
1817      cur_val = 0;
1818    }
1819
1820    small_fam(p) = (cur_val / 1048576L) % 16;
1821    small_char(p) = (cur_val / 4096) % 256;
1822    large_fam(p) = (cur_val / 256) % 16;
1823    large_char(p) = cur_val % 256;
1824 }
1825 /* sec 1163 */
1826 void math_radical (void)
1827 {
1828   tail_append(get_node(radical_noad_size));
1829   type(tail) = radical_noad;
1830   subtype(tail) = normal;
1831   mem[nucleus(tail)].hh = empty_field;
1832   mem[subscr(tail)].hh = empty_field;
1833   mem[supscr(tail)].hh = empty_field;
1834   scan_delimiter(left_delimiter(tail), true);
1835   scan_math(nucleus(tail));
1836 }
1837 /* sec 1165 */
1838 void math_ac (void)
1839 {
1840   if (cur_cmd == accent)
1841   {
1842     print_err("Please use ");
1843     print_esc("mathaccent");
1844     print_string(" for accents in math mode");
1845     help2("I'm changing \\accent to \\mathaccent here; wish me luck.",
1846       "(Accents are not the same in formulas as they are in text.)");
1847     error();
1848   }
1849
1850   tail_append(get_node(accent_noad_size));
1851   type(tail) = accent_noad;
1852   subtype(tail) = normal;
1853   mem[nucleus(tail)].hh = empty_field;
1854   mem[subscr(tail)].hh = empty_field;
1855   mem[supscr(tail)].hh = empty_field;
1856   math_type(accent_chr(tail)) = math_char;
1857   scan_fifteen_bit_int();
1858   character(accent_chr(tail)) = cur_val % 256;
1859
1860   if ((cur_val >= var_code) && ((cur_fam >= 0) && (cur_fam < 16)))
1861     fam(accent_chr(tail)) = cur_fam;
1862   else
1863     fam(accent_chr(tail)) = (cur_val / 256) % 16;
1864
1865   scan_math(nucleus(tail));
1866 }
1867 /* sec 1172 */
1868 void append_choices (void)
1869 {
1870   tail_append(new_choice());
1871   incr(save_ptr);
1872   saved(-1) = 0;
1873   push_math(math_choice_group);
1874   scan_left_brace();
1875 }
1876 /* sec 1184 */
1877 halfword fin_mlist_(halfword p)
1878 {
1879   pointer q;
1880
1881   if (incompleat_noad != 0)
1882   {
1883     math_type(denominator(incompleat_noad)) = sub_mlist;
1884     info(denominator(incompleat_noad)) = link(head);
1885
1886     if (p == 0)
1887       q = incompleat_noad;
1888     else
1889     {
1890       q = info(numerator(incompleat_noad));
1891
1892       if (type(q) != left_noad)
1893       {
1894         confusion("right");
1895         return 0;
1896       }
1897
1898       info(numerator(incompleat_noad)) = link(q);
1899       link(q) = incompleat_noad;
1900       link(incompleat_noad) = p;
1901     }
1902   }
1903   else
1904   {
1905     link(tail) = p;
1906     q = link(head);
1907   }
1908
1909   pop_nest();
1910
1911   return q;
1912 }
1913 /* sec 1174 */
1914 void build_choices (void)
1915 {
1916   pointer p;
1917
1918   unsave();
1919   p = fin_mlist(0);
1920
1921   switch (saved(-1))
1922   {
1923     case 0:
1924       display_mlist(tail) = p;
1925       break;
1926
1927     case 1:
1928       text_mlist(tail) = p;
1929       break;
1930
1931     case 2:
1932       script_mlist(tail) = p;
1933       break;
1934
1935     case 3:
1936       {
1937         script_script_mlist(tail) = p;
1938         decr(save_ptr);
1939         return;
1940       }
1941       break;
1942   }
1943
1944   incr(saved(-1));
1945   push_math(math_choice_group);
1946   scan_left_brace();
1947 }
1948 /* sec 1176 */
1949 void sub_sup (void)
1950 {
1951 /*  small_number t; */
1952   int t; /* 95/Jan/7 */
1953   pointer p;
1954
1955   t = 0;
1956   p = 0;
1957
1958   if (tail != head)
1959     if (script_allowed(tail))
1960     {
1961       p = supscr(tail) + cur_cmd - sup_mark;
1962       t = math_type(p);
1963     }
1964
1965   if ((p == 0) || (t != 0))
1966   {
1967     tail_append(new_noad());
1968     p = supscr(tail) + cur_cmd - sup_mark;
1969
1970     if (t != 0)
1971     {
1972       if (cur_cmd == sup_mark)
1973       {
1974         print_err("Double superscript");
1975         help1("I treat `x^1^2' essentially like `x^1{}^2'.");
1976       }
1977       else
1978       {
1979         print_err("Double subscript");
1980         help1("I treat `x_1_2' essentially like `x_1{}_2'.");
1981       }
1982       error();
1983     }
1984   }
1985   scan_math(p);
1986 }
1987 /* sec 1086 */
1988 void package_(small_number c)
1989 {
1990   scaled h;
1991   pointer p;
1992   scaled d;
1993
1994   d = box_max_depth;
1995   unsave();
1996   save_ptr = save_ptr - 3;
1997
1998   if (mode == -hmode)
1999     cur_box = hpack(link(head), saved(2), saved(1));
2000   else
2001   {
2002     cur_box = vpackage(link(head), saved(2), saved(1), d);
2003
2004     if (c == vtop_code)
2005     {
2006       h = 0;
2007       p = list_ptr(cur_box);
2008
2009       if (p != 0)
2010         if (type(p) <= rule_node)
2011           h = height(p);
2012
2013       depth(cur_box) = depth(cur_box) - h + height(cur_box);
2014       height(cur_box) = h;
2015     }
2016   }
2017
2018   pop_nest();
2019   box_end(saved(0));
2020 }