OSDN Git Service

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