OSDN Git Service

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