OSDN Git Service

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