OSDN Git Service

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