OSDN Git Service

6dda55c4e7e89abdb6515165d7534ed9ef6729ef
[putex/putex.git] / src / texsourc / tex5.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 0715 */
23 halfword rebox_(halfword b, scaled w)
24 {
25   halfword p;
26   internal_font_number f;
27   scaled v;
28
29   if ((width(b) != w) && (list_ptr(b) != 0))
30   {
31     if (type(b) == vlist_node)
32       b = hpack(b, 0, 1);
33
34     p = list_ptr(b);
35
36     if (((p >= hi_mem_min)) && (link(p) == 0))
37     {
38       f = font(p);
39       v = char_width(f, char_info(f, character(p)));
40
41       if (v != width(b))
42         link(p) = new_kern(width(b) - v);
43     }
44
45     free_node(b, box_node_size);
46     b = new_glue(ss_glue);
47     link(b) = p;
48
49     while (link(p) != 0)
50       p = link(p);
51
52     link(p) = new_glue(ss_glue);
53     return hpack(b, w, exactly);
54   }
55   else
56   {
57     width(b) = w;
58     return b;
59   }
60 }
61 /* This is to be the start of tex5.c */
62 /* sec 0716 */
63 halfword math_glue_(halfword g, scaled m)
64 {
65   halfword p;
66   integer n;
67   scaled f;
68
69   n = x_over_n(m, 65536L);
70   f = tex_remainder;
71
72   if (f < 0)
73   {
74     decr(n);
75     f = f + 65536L;
76   }
77
78   p = get_node(glue_spec_size);
79   width(p) = mult_and_add(n, width(g), xn_over_d(width(g), f, 65536L), 1073741823L);  /* 2^30 - 1 */
80   stretch_order(p) = stretch_order(g);
81
82   if (stretch_order(p) == normal)
83     stretch(p) = mult_and_add(n, stretch(g), xn_over_d(stretch(g), f, 65536L), 1073741823L);  /* 2^30 - 1 */
84   else
85     stretch(p) = stretch(g);
86
87   shrink_order(p) = shrink_order(g);
88
89   if (shrink_order(p) == normal)
90     shrink(p) = mult_and_add(n, shrink(g), xn_over_d(shrink(g), f, 65536L), 1073741823L);  /* 2^30 - 1 */
91   else
92     shrink(p) = shrink(g);
93
94   return p;
95 }
96 /* sec 0717 */
97 void math_kern_ (halfword p, scaled m)
98 {
99   integer n;
100   scaled f;
101
102   if (subtype(p) == mu_glue)
103   {
104     n = x_over_n(m, 65536L);
105     f = tex_remainder;
106
107     if (f < 0)
108     {
109       decr(n);
110       f = f + 65536L;
111     }
112
113     width(p) = mult_and_add(n, width(p), xn_over_d(width(p), f, 65536L), 1073741823L);  /* 2^30 - 1 */
114     subtype(p) = explicit;
115   }
116 }
117 /* sec 0718 */
118 void flush_math (void)
119 {
120   flush_node_list(link(head));
121   flush_node_list(incompleat_noad);
122   link(head) = 0;
123   tail = head;
124   incompleat_noad = 0;
125 }
126 /* sec 0720 */
127 halfword clean_box_(halfword p, small_number s)
128 {
129   halfword q;
130   small_number save_style;
131   halfword x;
132   halfword r;
133
134   switch(math_type(p))
135   {
136     case math_char:
137       {
138         cur_mlist = new_noad();
139         mem[nucleus(cur_mlist)] = mem[p];
140       }
141       break;
142
143     case sub_box:
144       {
145         q = info(p);
146         goto lab40;
147       }
148       break;
149
150     case sub_mlist:
151       cur_mlist = info(p);
152       break;
153
154     default:
155       {
156         q = new_null_box();
157         goto lab40;
158       }
159     break;
160   }
161
162   save_style = cur_style;
163   cur_style = s;
164   mlist_penalties = false;
165   mlist_to_hlist();
166   q = link(temp_head);
167   cur_style = save_style;
168
169   {
170     if (cur_style < script_style)
171       cur_size = text_size;
172     else
173       cur_size = 16 * ((cur_style - text_style) / 2);
174
175     cur_mu = x_over_n(math_quad(cur_size), 18);
176   }
177 lab40:
178   if ((q >= hi_mem_min) || (q == 0))
179     x = hpack(q, 0, 1);
180   else if ((link(q) == 0) && (type(q) <= vlist_node) && (shift_amount(q) == 0))
181     x = q;
182   else
183     x = hpack(q, 0, 1);
184
185   q = list_ptr(x);
186
187   if ((q >= hi_mem_min))
188   {
189     r = link(q);
190
191     if (r != 0)
192       if (link(r) == 0)
193         if (!(r >= hi_mem_min))
194           if (type(r) == kern_node)
195           {
196             free_node(r, small_node_size);
197             link(q) = 0;
198           }
199   }
200
201   return x;
202 }
203 /* sec 0722 */
204 void fetch_(halfword a)
205 {
206   cur_c = character(a);
207   cur_f = fam_fnt(fam(a) + cur_size);
208
209   if (cur_f == null_font)
210   {
211     print_err("");
212     print_size(cur_size);
213     print_char(' ');
214     print_int(fam(a));
215     print_string(" is undefined (character ");
216     print(cur_c);
217     print_char(')');
218     help4("Somewhere in the math formula just ended, you used the",
219         "stated character from an undefined font family. For example,",
220         "plain TeX doesn't allow \\it or \\sl in subscripts. Proceed,",
221         "and I'll try to forget that I needed that character.");
222     error();
223     cur_i = null_character;
224     math_type(a) = 0;
225   }
226   else
227   {
228     if ((cur_c >= font_bc[cur_f]) && (cur_c <= font_ec[cur_f]))
229       cur_i = char_info(cur_f, cur_c);
230     else
231       cur_i = null_character;
232
233     if (!((cur_i.b0 > 0)))
234     {
235       char_warning(cur_f, cur_c);
236       math_type(a) = 0;
237     }
238   }
239 }
240 /* sec 0734 */
241 void make_over_(halfword q)
242 {
243   info(nucleus(q)) = overbar(clean_box(nucleus(q), 2 * (cur_style / 2) + 1),
244       3 * default_rule_thickness, default_rule_thickness);
245   math_type(nucleus(q)) = sub_box;
246 }
247 /* sec 0735 */
248 void make_under_(halfword q)
249 {
250   halfword p, x, y;
251   scaled delta;
252
253   x = clean_box(nucleus(q), cur_style);
254   p = new_kern(3 * default_rule_thickness);
255   link(x) = p;
256   link(p) = fraction_rule(default_rule_thickness);
257   y = vpackage(x, 0, 1, 1073741823L); /* 2^30 - 1 */
258   delta = height(y) + depth(y) + default_rule_thickness;
259   height(y) = height(x);
260   depth(y) = delta - height(y);
261   info(nucleus(q)) = y;
262   math_type(nucleus(q)) = sub_box;
263 }
264 /* sec 0736 */
265 void make_vcenter_(halfword q)
266
267   halfword v;
268   scaled delta;
269
270   v = info(nucleus(q));
271
272   if (type(v) != vlist_node)
273   {
274     confusion("vcenter");
275     return;         // abort_flag set
276   }
277
278   delta = height(v) + depth(v);
279   height(v) = axis_height(cur_size) + half(delta);
280   depth(v) = delta - height(v);
281 }
282 /* sec 0737 */
283 void make_radical_(halfword q)
284 {
285   halfword x, y;
286   scaled delta, clr;
287
288   x = clean_box(nucleus(q), 2 * (cur_style / 2) + 1);
289
290   if (cur_style < text_style)
291     clr = default_rule_thickness + (abs(math_x_height(cur_size)) / 4);
292   else
293   {
294     clr = default_rule_thickness;
295     clr = clr + (abs(clr) / 4);
296   }
297
298   y = var_delimiter(left_delimiter(q), cur_size, height(x) + depth(x) + clr + default_rule_thickness);
299   delta = depth(y) -(height(x) + depth(x) + clr);
300
301   if (delta > 0)
302     clr = clr + half(delta);
303
304   shift_amount(y) = - (integer) (height(x) + clr);
305   link(y) = overbar(x, clr, height(y));
306   info(nucleus(q)) = hpack(y, 0, 1);
307   math_type(nucleus(q)) = sub_box;
308 }
309 /* sec 0738 */
310 void make_math_accent_(halfword q)
311 {
312   halfword p, x, y;
313   integer a;
314   quarterword c;
315   internal_font_number f;
316   ffour_quarters i;
317   scaled s;
318   scaled h;
319   scaled delta;
320   scaled w;
321
322   fetch(accent_chr(q));
323
324   if ((cur_i.b0 > 0))
325   {
326     i = cur_i;
327     c = cur_c;
328     f = cur_f;
329     s = 0;
330
331     if (math_type(nucleus(q)) == math_char)
332     {
333       fetch(nucleus(q));
334
335       if (char_tag(cur_i) == lig_tag)
336       {
337         a = lig_kern_start(cur_f, cur_i);
338         cur_i = font_info[a].qqqq;
339
340         if (skip_byte(cur_i) > stop_flag)
341         {
342           a = lig_kern_restart(cur_f, cur_i);
343           cur_i = font_info[a].qqqq;
344         }
345
346         while (true)
347         {
348           if (next_char(cur_i) == skew_char[cur_f])
349           {
350             if (op_byte(cur_i) >= kern_flag)
351               if (skip_byte(cur_i) <= stop_flag)
352                 s = char_kern(cur_f, cur_i);
353             goto lab31;
354           }
355
356           if (skip_byte(cur_i) >= stop_flag)
357             goto lab31;
358
359           a = a + skip_byte(cur_i) + 1;
360           cur_i = font_info[a].qqqq;
361         }
362       }
363     }
364 lab31:;
365     x = clean_box(nucleus(q), cramped_style(cur_style));
366     w = width(x);
367     h = height(x);
368
369     while (true)
370     {
371       if (char_tag(i) != list_tag)
372         goto lab30;
373
374       y = rem_byte(i);
375       i = char_info(f, y);
376
377       if (!(i.b0 > 0))
378         goto lab30;
379
380       if (char_width(f, i) > w)
381         goto lab30;
382
383       c = y;
384     }
385 lab30:;
386     if (h < x_height(f))
387       delta = h;
388     else
389       delta = x_height(f);
390
391     if ((math_type(supscr(q)) != 0) || (math_type(subscr(q)) != 0))
392       if (math_type(nucleus(q)) == math_char)
393       {
394         flush_node_list(x);
395         x = new_noad();
396         mem[nucleus(x)]= mem[nucleus(q)];
397         mem[supscr(x)]= mem[supscr(q)];
398         mem[subscr(x)]= mem[subscr(q)];
399         mem[supscr(q)].hh = empty_field;
400         mem[subscr(q)].hh = empty_field;
401         math_type(nucleus(q)) = sub_mlist;
402         info(nucleus(q)) = x;
403         x = clean_box(nucleus(q), cur_style);
404         delta = delta + height(x) - h;
405         h = height(x);
406       }
407
408     y = char_box(f, c);
409     shift_amount(y) = s + half(w - width(y));
410     width(y) = 0;
411     p = new_kern(- (integer) delta);
412     link(p) = x;
413     link(y) = p;
414     y = vpackage(y, 0, 1, 1073741823L);  /* 2^30 - 1 */
415     width(y) = width(x);
416
417     if (height(y) < h)
418     {
419       p = new_kern(h - height(y));
420       link(p) = list_ptr(y);
421       list_ptr(y) = p;
422       height(y) = h;
423     }
424
425     info(nucleus(q)) = y;
426     math_type(nucleus(q)) = sub_box;
427   }
428 }
429 /* sec 0743 */
430 void make_fraction_(halfword q)
431 {
432   halfword p, v, x, y, z;
433   scaled delta, delta1, delta2, shift_up, shift_down, clr;
434   
435   if (thickness(q) == default_code) /* 2^30 */
436     thickness(q) = default_rule_thickness;
437
438   x = clean_box(numerator(q), num_style(cur_style));
439   z = clean_box(denominator(q), denom_style(cur_style));
440
441   if (width(x) < width(z))
442     x = rebox(x, width(z));
443   else
444     z = rebox(z, width(x));
445
446   if (cur_style < text_style)
447   {
448     shift_up = num1(cur_size);
449     shift_down = denom1(cur_size);
450   }
451   else
452   {
453     shift_down = denom2(cur_size);
454
455     if (thickness(q) != 0)
456       shift_up = num2(cur_size);
457     else
458       shift_up = num3(cur_size);
459   }
460
461   if (thickness(q) == 0)
462   {
463     if (cur_style < text_style)
464       clr = 7 * default_rule_thickness;
465     else
466       clr = 3 * default_rule_thickness;
467
468     delta = half(clr - ((shift_up - depth(x)) - (height(z) - shift_down)));
469
470     if (delta > 0)
471     {
472       shift_up = shift_up + delta;
473       shift_down = shift_down + delta;
474     }
475   }
476   else
477   {
478     if (cur_style < text_style)
479       clr = 3 * thickness(q);
480     else
481       clr = thickness(q);
482
483     delta = half(thickness(q));
484     delta1 = clr - ((shift_up - depth(x)) - (axis_height(cur_size) + delta));
485     delta2 = clr -((axis_height(cur_size) - delta) - (height(z) - shift_down));
486
487     if (delta1 > 0)
488       shift_up = shift_up + delta1;
489
490     if (delta2 > 0)
491       shift_down = shift_down + delta2;
492   }
493
494   v = new_null_box();
495   type(v) = vlist_node;
496   height(v) = shift_up + height(x);
497   depth(v) = depth(z) + shift_down;
498   width(v) = width(x);
499
500   if (thickness(q) == 0)
501   {
502     p = new_kern((shift_up - depth(x)) - (height(z) - shift_down));
503     link(p) = z;
504   }
505   else
506   {
507     y = fraction_rule(thickness(q));
508     p = new_kern((axis_height(cur_size) - delta) - (height(z) - shift_down));
509     link(y) = p;
510     link(p) = z;
511     p = new_kern((shift_up - depth(x)) - (axis_height(cur_size) + delta));
512     link(p) = y;
513   }
514
515   link(x) = p;
516   list_ptr(v) = x;
517
518   if (cur_style < text_style)
519     delta = delim1(cur_size);
520   else
521     delta = delim2(cur_size);
522
523   x = var_delimiter(left_delimiter(q), cur_size, delta);
524   link(x) = v;
525   z = var_delimiter(right_delimiter(q), cur_size, delta);
526   link(v) = z;
527   new_hlist(q) = hpack(x, 0, 1);
528 }
529 /***************************************************************************/
530 scaled make_op_ (halfword);
531 /***************************************************************************/
532 /* sec 0752 */
533 void make_ord_(halfword q)
534 {
535   integer a;
536   halfword p, r;
537
538 lab20:
539   if (math_type(subscr(q)) == 0)
540     if (math_type(supscr(q)) == 0)
541       if (math_type(nucleus(q)) == math_char)
542       {
543         p = link(q);
544
545         if (p != 0)
546           if ((type(p) >= ord_noad) && (type(p) <= punct_noad))
547             if (math_type(nucleus(p)) == math_char)
548               if (fam(nucleus(p)) == fam(nucleus(q)))
549               {
550                 math_type(nucleus(q)) = math_text_char;
551                 fetch(nucleus(q));
552
553                 if (char_tag(cur_i) == lig_tag)
554                 {
555                   a = lig_kern_start(cur_f, cur_i);
556                   cur_c = character(nucleus(p));
557                   cur_i = font_info[a].qqqq;
558
559                   if (skip_byte(cur_i) > stop_flag)
560                   {
561                     a = lig_kern_restart(cur_f, cur_i);
562                     cur_i = font_info[a].qqqq;
563                   }
564
565                   while (true)
566                   {
567                     if (next_char(cur_i) == cur_c)
568                       if (skip_byte(cur_i) <= stop_flag)
569                         if (op_byte(cur_i) >= kern_flag)
570                         {
571                           p = new_kern(char_kern(cur_f, cur_i));
572                           link(p) = link(q);
573                           link(q) = p;
574                           return;
575                         }
576                         else
577                         {
578                           {
579                             if (interrupt != 0)
580                             {
581                               pause_for_instructions();
582                             }
583                           }
584
585                           switch (op_byte(cur_i))
586                           {
587                             case 1:
588                             case 5:
589                               character(nucleus(q)) = rem_byte(cur_i);
590                               break;
591                             case 2:
592                             case 6:
593                               character(nucleus(p)) = rem_byte(cur_i);
594                               break;
595                             case 3:
596                             case 7:
597                             case 11:
598                               {
599                                 r = new_noad();
600                                 character(nucleus(r)) = rem_byte(cur_i);
601                                 fam(nucleus(r)) = fam(nucleus(q));
602                                 link(q) = r;
603                                 link(r) = p;
604
605                                 if (op_byte(cur_i) < 11)
606                                   math_type(nucleus(r)) = math_char;
607                                 else
608                                   math_type(nucleus(r)) = math_text_char;
609                               }
610                               break;
611
612                             default:
613                               {
614                                 link(q) = link(p);
615                                 character(nucleus(q)) = rem_byte(cur_i);
616                                 mem[subscr(q)] = mem[subscr(p)];
617                                 mem[supscr(q)] = mem[supscr(p)];
618                                 free_node(p, noad_size);
619                               }
620                               break;
621                           }
622
623                           if (op_byte(cur_i) > 3)
624                             return;
625
626                           math_type(nucleus(q)) = math_char;
627                           goto lab20;
628                         }
629
630                     if (skip_byte(cur_i) >= stop_flag)
631                       return;
632
633                     a = a + skip_byte(cur_i) + 1;
634                     cur_i = font_info[a].qqqq;
635                   }
636                 }
637               }
638       }
639 }
640 /***************************************************************************/
641 void make_scripts_ (halfword, scaled);
642 /***************************************************************************/
643 /* sec 0762 */
644 small_number make_left_right_(halfword q, small_number style, scaled max_d, scaled max_h)
645 {
646   scaled delta, delta1, delta2;
647
648   if (style < script_style)
649     cur_size = text_size;
650   else
651     cur_size = 16 * ((style - text_style) / 2);
652
653   delta2 = max_d + axis_height(cur_size);
654   delta1 = max_h + max_d - delta2;
655
656   if (delta2 > delta1)
657     delta1 = delta2;
658
659   delta = (delta1 / 500) * delimiter_factor;
660   delta2 = delta1 + delta1 - delimiter_shortfall;
661
662   if (delta < delta2)
663     delta = delta2;
664
665   new_hlist(q) = var_delimiter(delimiter(q), cur_size, delta);
666   return type(q) - (left_noad - open_noad);
667 }
668 /* sec 0726 */
669 void mlist_to_hlist (void)
670 {
671   halfword mlist;
672   bool penalties;
673   small_number style;
674   small_number save_style;
675   halfword q;
676   halfword r;
677 /*  small_number r_type;  */
678   int r_type;            /* 95/Jan/7 */
679 /*  small_number t; */
680   int t;              /* 95/Jan/7 */
681   halfword p, x, y, z;
682   integer pen;
683   small_number s;
684   scaled max_h, max_d;
685   scaled delta;
686
687   mlist = cur_mlist;
688   penalties = mlist_penalties;
689   style = cur_style;
690   q = mlist;
691   r = 0;
692   r_type = op_noad;
693   max_h = 0;
694   max_d = 0;
695
696   {
697     if (cur_style < script_style)
698       cur_size = text_size;
699     else
700       cur_size = 16 * ((cur_style - text_style) / 2);
701
702     cur_mu = x_over_n(math_quad(cur_size), 18);
703   }
704
705   while (q != 0)
706   {
707 lab21:
708     delta = 0;
709
710     switch (type(q))
711     {
712       case bin_noad:
713         switch (r_type)
714         {
715           case bin_noad:
716           case op_noad:
717           case rel_noad:
718           case open_noad:
719           case punct_noad:
720           case left_noad:
721             {
722               type(q) = ord_noad;
723               goto lab21;
724             }
725             break;
726
727           default:
728             ;
729             break;
730         }
731         break;
732
733       case rel_noad:
734       case close_noad:
735       case punct_noad:
736       case right_noad:
737         {
738           if (r_type == bin_noad)
739             type(r) = ord_noad;
740
741           if (type(q) == right_noad)
742             goto lab80;
743         }
744         break;
745
746       case left_noad:
747         goto lab80;
748         break;
749
750       case fraction_noad:
751         {
752           make_fraction(q);
753           goto lab82;
754         }
755         break;
756
757       case op_noad:
758         {
759           delta = make_op(q);
760
761           if (subtype(q) == limits)
762             goto lab82;
763         }
764         break;
765
766       case ord_noad:
767         make_ord(q);
768         break;
769
770       case open_noad:
771       case inner_noad:
772         ;
773         break;
774
775       case radical_noad:
776         make_radical(q);
777         break;
778
779       case over_noad:
780         make_over(q);
781         break;
782
783       case under_noad:
784         make_under(q);
785         break;
786
787       case accent_noad:
788         make_math_accent(q);
789         break;
790
791       case vcenter_noad:
792         make_vcenter(q);
793         break;
794
795       case style_node:
796         {
797           cur_style = subtype(q);
798
799           {
800             if (cur_style < script_style)
801               cur_size = text_size;
802             else
803               cur_size = 16 * ((cur_style - text_style) / 2);
804
805             cur_mu = x_over_n(math_quad(cur_size), 18);
806           }
807
808           goto lab81;
809         }
810         break;
811
812       case choice_node:
813         {
814           switch (cur_style / 2)
815           {
816             case 0:
817               {
818                 p = display_mlist(q);
819                 display_mlist(q) = 0;
820               }
821               break;
822
823             case 1:
824               {
825                 p = text_mlist(q);
826                 text_mlist(q) = 0;
827               }
828               break;
829
830             case 2:
831               {
832                 p = script_mlist(q);
833                 script_mlist(q) = 0;
834               }
835               break;
836
837             case 3:
838               {
839                 p = script_script_mlist(q);
840                 script_script_mlist(q) = 0;
841               }
842               break;
843           }
844
845           flush_node_list(display_mlist(q));
846           flush_node_list(text_mlist(q));
847           flush_node_list(script_mlist(q));
848           flush_node_list(script_script_mlist(q));
849           type(q) = style_node;
850           subtype(q) = cur_style;
851           width(q) = 0;
852           depth(q) = 0;
853
854           if (p != 0)
855           {
856             z = link(q);
857             link(q) = p;
858
859             while (link(p) != 0)
860               p = link(p);
861
862             link(p) = z;
863           }
864           goto lab81;
865         }
866         break;
867
868       case ins_node:
869       case mark_node:
870       case adjust_node:
871       case whatsit_node:
872       case penalty_node:
873       case disc_node:
874         goto lab81;
875         break;
876
877       case rule_node:
878         {
879           if (height(q) > max_h)
880             max_h = height(q);
881
882           if (depth(q) > max_d)
883             max_d = depth(q);
884
885           goto lab81;
886         }
887         break;
888
889       case glue_node:
890         {
891           if (subtype(q) == mu_glue)
892           {
893             x = glue_ptr(q);
894             y = math_glue(x, cur_mu);
895             delete_glue_ref(x);
896             glue_ptr(q) = y;
897             subtype(q) = normal;
898           }
899           else if ((cur_size != text_size) && (subtype(q) == cond_math_glue))
900           {
901             p = link(q);
902
903             if (p != 0)
904               if ((type(q) == glue_node) || (type(p) == kern_node))
905               {
906                 link(q) = link(p);
907                 link(p) = 0;
908                 flush_node_list(p);
909               }
910           }
911           goto lab81;
912         }
913         break;
914
915       case kern_node:
916         {
917           math_kern(q, cur_mu);
918           goto lab81;
919         }
920         break;
921
922       default:
923         {
924           confusion("mlist1");
925           return;       // abort_flag set
926         }
927         break;
928     }
929
930     switch (math_type(nucleus(q)))
931     {
932       case math_char:
933       case math_text_char:
934         {
935           fetch(nucleus(q));
936
937           if ((cur_i.b0 > 0))
938           {
939             delta = char_italic(cur_f, cur_i);
940             p = new_character(cur_f, cur_c);
941
942             if ((math_type(nucleus(q)) == math_text_char) && (space(cur_f) != 0))
943               delta = 0;
944
945             if ((math_type(subscr(q)) == 0) && (delta != 0))
946             {
947               link(p) = new_kern(delta);
948               delta = 0;
949             }
950           }
951           else
952             p = 0;
953         }
954         break;
955
956       case 0:
957         p = 0;
958         break;
959
960       case sub_box:
961         p = info(nucleus(q));
962         break;
963
964       case sub_mlist:
965         {
966           cur_mlist = info(nucleus(q));
967           save_style = cur_style;
968           mlist_penalties = false;
969           mlist_to_hlist();
970           cur_style = save_style;
971
972           {
973             if (cur_style < script_style)
974               cur_size = text_size;
975             else
976               cur_size = 16 * ((cur_style - text_style) / 2);
977
978             cur_mu = x_over_n(math_quad(cur_size), 18);
979           }
980
981           p = hpack(link(temp_head), 0, 1);
982         }
983         break;
984
985       default:
986         {
987           confusion("mlist2");
988           return;       // abort_flag set
989         }
990         break;
991     }
992   
993     new_hlist(q) = p;
994
995     if ((math_type(subscr(q)) == 0) && (math_type(supscr(q)) == 0))
996       goto lab82;
997
998     make_scripts(q, delta);
999 lab82:
1000     z = hpack(new_hlist(q), 0, 1);
1001
1002     if (height(z) > max_h)
1003       max_h = height(z);
1004
1005     if (depth(z) > max_d)
1006       max_d = depth(z);
1007
1008     free_node(z, box_node_size);
1009 lab80:
1010     r = q;
1011     r_type = type(r);
1012 lab81:
1013     q = link(q);
1014   }
1015
1016   if (r_type == bin_noad)
1017     type(r) = ord_noad;
1018
1019   p = temp_head;
1020   link(p) = 0;
1021   q = mlist;
1022   r_type = 0;
1023   cur_style = style;
1024
1025   {
1026     if (cur_style < script_style)
1027       cur_size = text_size;
1028     else
1029       cur_size = 16 *((cur_style - text_style) / 2);
1030
1031     cur_mu = x_over_n(math_quad(cur_size), 18);
1032   }
1033
1034   while (q != 0)
1035   {
1036     t = ord_noad;
1037     s = noad_size;
1038     pen = inf_penalty;
1039
1040     switch (type(q))
1041     {
1042       case op_noad:
1043       case open_noad:
1044       case close_noad:
1045       case punct_noad:
1046       case inner_noad:
1047         t = type(q);
1048         break;
1049
1050       case bin_noad:
1051         {
1052           t = bin_noad;
1053           pen = bin_op_penalty;
1054         }
1055         break;
1056
1057       case rel_noad:
1058         {
1059           t = rel_noad;
1060           pen = rel_penalty;
1061         }
1062         break;
1063
1064       case ord_noad:
1065       case vcenter_noad:
1066       case over_noad:
1067       case under_noad:
1068         ;
1069         break;
1070
1071       case radical_noad:
1072         s = radical_noad_size;
1073         break;
1074
1075       case accent_noad:
1076         s = accent_noad_size;
1077         break;
1078
1079       case fraction_noad:
1080         {
1081           t = inner_noad;
1082           s = fraction_noad_size;
1083         }
1084         break;
1085
1086       case left_noad:
1087       case right_noad:
1088         t = make_left_right(q, style, max_d, max_h);
1089         break;
1090
1091       case style_node:
1092         {
1093           cur_style = subtype(q);
1094           s = style_node_size;
1095
1096           {
1097             if (cur_style < script_style)
1098               cur_size = text_size;
1099             else
1100               cur_size = 16 *((cur_style - text_style) / 2);
1101
1102             cur_mu = x_over_n(math_quad(cur_size), 18);
1103           }
1104
1105           goto lab83;
1106         }
1107         break;
1108
1109       case whatsit_node:
1110       case penalty_node:
1111       case rule_node:
1112       case disc_node:
1113       case adjust_node:
1114       case ins_node:
1115       case mark_node:
1116       case glue_node:
1117       case kern_node:
1118         {
1119           link(p) = q;
1120           p = q;
1121           q = link(q);
1122           link(p) = 0;
1123           goto lab30;
1124         }
1125         break;
1126
1127       default:
1128         {
1129           confusion("mlist3");
1130           return;       // abort_flag set
1131         }
1132         break;
1133     }
1134
1135     if (r_type > 0)
1136     {
1137       switch (str_pool[r_type * 8 + t + magic_offset])
1138       {
1139         case '0':
1140           x = 0;
1141           break;
1142
1143         case '1':
1144           if (cur_style < script_style)
1145             x = thin_mu_skip_code;
1146           else
1147             x = 0;
1148           break;
1149
1150         case '2':
1151           x = thin_mu_skip_code;
1152           break;
1153
1154         case '3':
1155           if (cur_style < script_style)
1156             x = med_mu_skip_code;
1157           else
1158             x = 0;
1159           break;
1160
1161         case '4':
1162           if (cur_style < script_style)
1163             x = thick_mu_skip_code;
1164           else
1165             x = 0;
1166           break;
1167
1168         default:
1169           {
1170             confusion("mlist4");
1171             return;       // abort_flag set
1172           }
1173           break;
1174       }
1175
1176       if (x != 0)
1177       {
1178         y = math_glue(glue_par(x), cur_mu);
1179         z = new_glue(y);
1180         glue_ref_count(y) = 0;
1181         link(p) = z;
1182         p = z;
1183         subtype(z) = x + 1;
1184       }
1185     }
1186
1187     if (new_hlist(q) != 0)
1188     {
1189       link(p) = new_hlist(q);
1190
1191       do
1192         {
1193           p = link(p);
1194         }
1195       while (!(link(p) == 0));
1196     }
1197
1198     if (penalties)
1199       if (link(q) != 0)
1200         if (pen < inf_penalty)
1201         {
1202           r_type = type(link(q));
1203
1204           if (r_type != penalty_node)
1205             if (r_type != rel_noad)
1206             {
1207               z = new_penalty(pen);
1208               link(p) = z;
1209               p = z;
1210             }
1211         }
1212
1213     r_type = t;
1214 lab83:
1215     r = q;
1216     q = link(q);
1217     free_node(r, s);
1218 lab30:;
1219   }
1220 }
1221 /* sec 0772 */
1222 void push_alignment (void)
1223 {
1224   halfword p;
1225
1226   p = get_node(align_stack_node_size);
1227   link(p) = align_ptr;
1228   info(p) = cur_align;
1229   llink(p) = preamble;
1230   rlink(p) = cur_span;
1231   mem[p + 2].cint = cur_loop;
1232   mem[p + 3].cint = align_state;
1233   info(p + 4) = cur_head;
1234   link(p + 4) = cur_tail;
1235   align_ptr = p;
1236   cur_head = get_avail();
1237 }
1238 /* sec 0772 */
1239 void pop_alignment (void)
1240 {
1241   halfword p;
1242
1243   free_avail(cur_head);
1244   p = align_ptr;
1245   cur_tail = link(p + 4);
1246   cur_head = info(p + 4);
1247   align_state = mem[p + 3].cint;
1248   cur_loop = mem[p + 2].cint;
1249   cur_span = rlink(p);
1250   preamble = llink(p);
1251   cur_align = info(p);
1252   align_ptr = link(p);
1253   free_node(p, align_stack_node_size);
1254 }
1255 /* sec 0782 */
1256 void get_preamble_token (void)
1257 {
1258 lab20:
1259   get_token();
1260
1261   while ((cur_chr == span_code) && (cur_cmd == tab_mark))
1262   {
1263     get_token();
1264
1265     if (cur_cmd > max_command)
1266     {
1267       expand();
1268       get_token();
1269     }
1270   }
1271
1272   if (cur_cmd == endv)
1273   {
1274     fatal_error("(interwoven alignment preambles are not allowed)");
1275     return;     // abort_flag set
1276   }
1277
1278   if ((cur_cmd == assign_glue) && (cur_chr == glue_base + tab_skip_code))
1279   {
1280     scan_optional_equals();
1281     scan_glue(glue_val);
1282
1283     if (global_defs > 0)
1284       geq_define(glue_base + tab_skip_code, glue_ref, cur_val);
1285     else
1286       eq_define(glue_base + tab_skip_code, glue_ref, cur_val);
1287
1288     goto lab20;
1289   }
1290 }
1291 /* sec 0774 */
1292 void init_align (void)
1293 {
1294   halfword save_cs_ptr;
1295   halfword p;
1296
1297   save_cs_ptr = cur_cs;
1298   push_alignment();
1299   align_state = -1000000L;
1300
1301   if ((mode == mmode) && ((tail != cur_list.head_field) || (incompleat_noad != 0)))
1302   {
1303     print_err("Improper ");
1304     print_esc("halign");
1305     print_string(" inside $$'s");
1306     help3("Displays can use special alignments (like \\eqalignno)",
1307         "only if nothing but the alignment itself is between $$'s.",
1308         "So I've deleted the formulas that preceded this alignment.");
1309     error();
1310     flush_math();
1311   }
1312
1313   push_nest();
1314
1315   if (mode == mmode)
1316   {
1317     mode = -vmode;
1318     prev_depth = nest[nest_ptr - 2].aux_field.cint;
1319   }
1320   else if (mode > 0)
1321     mode = - (integer) mode;
1322
1323   scan_spec(align_group, false);
1324   preamble = 0;
1325   cur_align = align_head;
1326   cur_loop = 0;
1327   scanner_status = aligning;
1328   warning_index = save_cs_ptr;
1329   align_state = -1000000L;
1330
1331   while (true)
1332   {
1333     link(cur_align) = new_param_glue(tab_skip_code);
1334     cur_align = link(cur_align);
1335
1336     if (cur_cmd == car_ret)
1337       goto lab30;
1338
1339     p = hold_head;
1340     link(p) = 0;
1341
1342     while (true)
1343     {
1344       get_preamble_token();
1345
1346       if (cur_cmd == mac_param)
1347         goto lab31;
1348
1349       if ((cur_cmd <= car_ret) && (cur_cmd >= tab_mark) && (align_state == -1000000L))
1350         if ((p == hold_head) && (cur_loop == 0) && (cur_cmd == tab_mark))
1351           cur_loop = cur_align;
1352         else
1353         {
1354           print_err("Missing # inserted in alignment preamble");
1355           help3("There should be exactly one # between &'s, when an",
1356               "\\halign or \\valign is being set up. In this case you had",
1357               "none, so I've put one in; maybe that will work.");
1358           back_error();
1359           goto lab31;
1360         }
1361       else if ((cur_cmd != spacer) || (p != hold_head))
1362       {
1363         link(p) = get_avail();
1364         p = link(p);
1365         info(p) = cur_tok;
1366       }
1367     }
1368
1369 lab31:
1370     link(cur_align) = new_null_box();
1371     cur_align = link(cur_align);
1372     info(cur_align) = end_span;
1373     width(cur_align) = null_flag;  /* - 2^30 */
1374     u_part(cur_align) = link(hold_head);
1375     p = hold_head;
1376     link(p) = 0;
1377
1378     while (true)
1379     {
1380 lab22:
1381       get_preamble_token();
1382
1383       if ((cur_cmd <= car_ret) && (cur_cmd >= tab_mark) && (align_state == -1000000L))
1384         goto lab32;
1385
1386       if (cur_cmd == mac_param)
1387       {
1388         print_err("Only one # is allowed per tab");
1389         help3("There should be exactly one # between &'s, when an",
1390             "\\halign or \\valign is being set up. In this case you had",
1391             "more than one, so I'm ignoring all but the first.");
1392         error();
1393         goto lab22;
1394       }
1395
1396       link(p) = get_avail();
1397       p = link(p);
1398       info(p) = cur_tok;
1399     }
1400
1401 lab32:
1402     link(p) = get_avail();
1403     p = link(p);
1404     info(p) = end_template_token;
1405     v_part(cur_align) = link(hold_head);
1406   }
1407
1408 lab30:
1409   scanner_status = 0;
1410   new_save_level(align_group);
1411
1412   if (every_cr != 0)
1413     begin_token_list(every_cr, every_cr_text);
1414   align_peek();
1415 }
1416 /* sec 0787 */
1417 void init_span_ (halfword p)
1418 {
1419   push_nest();
1420
1421   if (mode == -hmode)
1422     space_factor = 1000;
1423   else
1424   {
1425     cur_list.aux_field.cint = ignore_depth;
1426     normal_paragraph();
1427   }
1428
1429   cur_span = p;
1430 }
1431 /* sec 0786 */
1432 void init_row (void)
1433 {
1434   push_nest();
1435
1436   mode = (-hmode - vmode) - mode;
1437
1438   if (mode == -hmode)
1439     space_factor = 0;
1440   else
1441     cur_list.aux_field.cint = 0;
1442
1443   tail_append(new_glue(glue_ptr(preamble)));
1444   subtype(tail) = tab_skip_code + 1;
1445   cur_align = link(preamble);
1446   cur_tail = cur_head;
1447   init_span(cur_align);
1448 }
1449 /* sec 0788 */
1450 void init_col (void)
1451 {
1452   extra_info(cur_align) = cur_cmd;
1453
1454   if (cur_cmd == omit)
1455     align_state = 0;
1456   else
1457   {
1458     back_input();
1459     begin_token_list(u_part(cur_align), u_template);
1460   }
1461 }
1462 /* sec 0799 */
1463 void fin_row (void)
1464 {
1465   halfword p;
1466
1467   if (mode == -hmode)
1468   {
1469     p = hpack(link(head), 0, 1);
1470     pop_nest();
1471     append_to_vlist(p);
1472
1473     if (cur_head != cur_tail)
1474     {
1475       link(tail) = link(cur_head);
1476       tail = cur_tail;
1477     }
1478   }
1479   else
1480   {
1481     p = vpackage(link(head), 0, 1, 1073741823L);   /* 2^30 - 1 */
1482     pop_nest();
1483     link(tail) = p;
1484     tail = p;
1485     space_factor = 1000;
1486   }
1487
1488   type(p) = unset_node;
1489   glue_stretch(p) = 0;
1490
1491   if (every_cr != 0)
1492     begin_token_list(every_cr, every_cr_text);
1493
1494   align_peek();
1495 }
1496 /* sec 0800 */
1497 void fin_align (void)
1498 {
1499   halfword p, q, r, s, u, v;
1500   scaled t, w;
1501   scaled o;
1502   halfword n;
1503   scaled rule_save;
1504   memory_word aux_save;
1505
1506   if (cur_group != align_group)
1507   {
1508     confusion("align1");
1509     return;       // abort_flag set
1510   }
1511
1512   unsave();
1513
1514   if (cur_group != align_group)
1515   {
1516     confusion("align0");
1517     return;       // abort_flag set
1518   }
1519
1520   unsave();
1521
1522   if (nest[nest_ptr - 1].mode_field == mmode)
1523     o = display_indent;
1524   else
1525     o = 0;
1526
1527   q = link(preamble);
1528
1529   do
1530     {
1531       flush_list(u_part(q));
1532       flush_list(v_part(q));
1533       p = link(link(q));
1534
1535       if (width(q) == null_flag) /* - 2^30 */
1536       {
1537         width(q) = 0;
1538         r = link(q);
1539         s = glue_ptr(r);
1540
1541         if (s != zero_glue)
1542         {
1543           add_glue_ref(zero_glue);
1544           delete_glue_ref(s);
1545           glue_ptr(c) = zero_glue;
1546         }
1547       }
1548
1549       if (info(q) != end_span)
1550       {
1551         t = width(q) + width(glue_ptr(link(q)));
1552         r = info(q);
1553         s = end_span;
1554         info(s) = p;
1555         n = min_quarterword + 1;
1556
1557         do
1558           {
1559             width(r) = width(r) - t;
1560             u = info(r);
1561
1562             while (link(r) > n)
1563             {
1564               s = info(s);
1565               n = link(info(s)) + 1;
1566             }
1567
1568             if (link(r) < n)
1569             {
1570               info(r) = info(s);
1571               info(s) = r;
1572               decr(link(r));
1573               s = r;
1574             }
1575             else
1576             {
1577               if (width(r) > width(info(s)))
1578                 width(info(s)) = width(r);
1579
1580               free_node(r, span_node_size);
1581             }
1582
1583             r = u;
1584           }
1585         while (!(r == end_span));
1586       }
1587
1588       type(q) = unset_node;
1589       span_count(q) = min_quarterword;
1590       height(q) = 0;
1591       depth(q) = 0;
1592       glue_order(q) = normal;
1593       glue_sign(q) = normal;
1594       glue_stretch(q) = 0;
1595       glue_shrink(q) = 0;
1596       q = p;
1597     }
1598   while (!(q == 0));
1599
1600   save_ptr = save_ptr - 2;
1601   pack_begin_line = - (integer) mode_line;
1602
1603   if (mode == -vmode)
1604   {
1605     rule_save = overfull_rule;
1606     overfull_rule = 0;
1607     p = hpack(preamble, saved(1), saved(0));
1608     overfull_rule = rule_save;
1609   }
1610   else
1611   {
1612     q = link(preamble);
1613
1614     do
1615       {
1616         height(q) = width(q);
1617         width(q) = 0;
1618         q = link(link(q));
1619       }
1620     while (!(q == 0));
1621
1622     p = vpackage(preamble, saved(1), saved(0), 1073741823L);  /* 2^30 - 1 */
1623     q = link(preamble);
1624
1625     do
1626       {
1627         width(q) = height(q);
1628         height(q) = 0;
1629         q = link(link(q));
1630       }
1631     while (!(q == 0));
1632   }
1633
1634   pack_begin_line = 0;
1635   q = link(head);
1636   s = head;
1637
1638   while (q != 0)
1639   {
1640     if (!(q >= hi_mem_min))
1641       if (type(q) == unset_node)
1642       {
1643         if (mode == -vmode)
1644         {
1645           type(q) = hlist_node;
1646           width(q) = width(p);
1647         }
1648         else
1649         {
1650           type(q) = vlist_node;
1651           height(q) = height(p);
1652         }
1653
1654         glue_order(q) = glue_order(p);
1655         glue_sign(q) = glue_sign(p);
1656         glue_set(q) = glue_set(p);
1657         shift_amount(q) = o;
1658         r = link(list_ptr(q));
1659         s = link(list_ptr(p));
1660
1661         do
1662           {
1663             n = span_count(r);
1664             t = width(s);
1665             w = t;
1666             u = hold_head;
1667
1668             while (n > min_quarterword)
1669             {
1670               decr(n);
1671               s = link(s);
1672               v = glue_ptr(s);
1673               link(u) = new_glue(v);
1674               u = link(u);
1675               subtype(u) = tab_skip_code + 1;
1676               t = t + width(v);
1677
1678               if (glue_sign(p) == stretching)
1679               {
1680                 if (stretch_order(v) == glue_order(p))
1681                   t = t + round(glue_set(p) * stretch(v));
1682               }
1683               else if (glue_sign(p) == shrinking)
1684               {
1685                 if (shrink_order(v) == glue_order(p))
1686                   t = t - round(glue_set(p) * shrink(v));
1687               }
1688
1689               s = link(s);
1690               link(u) = new_null_box();
1691               u = link(u);
1692               t = t + width(s);
1693
1694               if (mode == -vmode)
1695                 width(u) = width(s);
1696               else
1697               {
1698                 type(u) = vlist_node;
1699                 height(u) = width(s);
1700               }
1701             }
1702             
1703
1704             if (mode == -vmode)
1705             {
1706               height(r) = height(q);
1707               depth(r) = depth(q);
1708
1709               if (t == width(r))
1710               {
1711                 glue_sign(r) = normal;
1712                 glue_order(r) = normal;
1713                 glue_set(r) = 0.0;
1714               }
1715               else if (t > width(r))
1716               {
1717                 glue_sign(r) = stretching;
1718
1719                 if (glue_stretch(r) == 0)
1720                   glue_set(r) = 0.0;
1721                 else
1722                   glue_set(r) = (t - width(r)) / ((double) glue_stretch(r));
1723               }
1724               else
1725               {
1726                 glue_order(r) = glue_sign(r);
1727                 glue_sign(r) = shrinking;
1728
1729                 if (glue_shrink(r) == 0)
1730                   glue_set(r) = 0.0;
1731                 else if ((glue_order(r) == normal) && (width(r) - t > glue_shrink(r)))
1732                   glue_set(r) = 1.0;
1733                 else
1734                   glue_set(r) = (width(r) - t)/ ((double) glue_shrink(r));
1735               }
1736
1737               width(r) = w;
1738               type(r) = hlist_node;
1739             }
1740             else
1741             {
1742               width(r) = width(q);
1743
1744               if (t == height(r))
1745               {
1746                 glue_sign(r) = normal;
1747                 glue_order(r) = normal;
1748                 glue_set(r) = 0.0;
1749               }
1750               else if (t > height(r))
1751               {
1752                 glue_sign(r) = stretching;
1753
1754                 if (glue_stretch(r) == 0)
1755                   glue_set(r) = 0.0;
1756                 else
1757                   glue_set(r) = (t - height(r)) / ((double) glue_stretch(r));
1758               }
1759               else
1760               {
1761                 glue_order(r) = glue_sign(r);
1762                 glue_sign(r) = shrinking;
1763
1764                 if (glue_shrink(r) == 0)
1765                   glue_set(r) = 0.0;
1766                 else if ((glue_order(r) == normal) && (height(r) - t > glue_shrink(r)))
1767                   glue_set(r) = 1.0;
1768                 else
1769                   glue_set(r) = (height(r) - t) / ((double) glue_shrink(r));
1770               }
1771
1772               height(r) = w;
1773               type(r) = vlist_node;
1774             }
1775
1776             shift_amount(r) = 0;
1777
1778             if (u != hold_head)
1779             {
1780               link(u) = link(r);
1781               link(r) = link(hold_head);
1782               r = u;
1783             }
1784
1785             r = link(link(r));
1786             s = link(link(s));
1787           }
1788         while(!(r == 0));
1789       }
1790       else if (type(q) == rule_node)
1791       {
1792         if ((width(q) == -1073741824L))  /* 2^30  */
1793           width(q) = width(p);
1794
1795         if ((height(q) == -1073741824L))  /* 2^30  */
1796           height(q) = height(p);
1797
1798         if ((depth(q) == -1073741824L))  /* 2^30  */
1799           depth(q) = depth(p);
1800
1801         if (o != 0)
1802         {
1803           r = link(q);
1804           link(q) = 0;
1805           q = hpack(q, 0, 1);
1806           shift_amount(q) = o;
1807           link(q) = r;
1808           link(s) = q;
1809         }
1810       }
1811     s = q;
1812     q = link(q);
1813   }
1814
1815   flush_node_list(p);
1816   pop_alignment();
1817   aux_save = cur_list.aux_field;
1818   p = link(head);
1819   q = tail;
1820   pop_nest();
1821
1822   if (mode == mmode)
1823   {
1824     do_assignments();
1825
1826     if (cur_cmd != math_shift)
1827     {
1828       print_err("Missing $$ inserted");
1829       help2("Displays can use special alignments (like \\eqalignno)",
1830           "only if nothing but the alignment itself is between $$'s.");
1831       back_error();
1832     }
1833     else
1834     {
1835       get_x_token();
1836
1837       if (cur_cmd != math_shift)
1838       {
1839         print_err("Display math should end with $$");
1840         help2("The `$' that I just saw supposedly matches a previous `$$'.",
1841             "So I shall assume that you typed `$$' both times.");
1842         back_error();
1843       }
1844     }
1845
1846     pop_nest();
1847     tail_append(new_penalty(pre_display_penalty));
1848     tail_append(new_param_glue(above_display_skip_code));
1849     link(tail) = p;
1850
1851     if (p != 0)
1852       tail = q;
1853
1854     tail_append(new_penalty(post_display_penalty));
1855     tail_append(new_param_glue(below_display_skip_code));
1856     cur_list.aux_field.cint = aux_save.cint;
1857     resume_after_display();
1858   }
1859   else
1860   {
1861     cur_list.aux_field = aux_save;
1862     link(tail) = p;
1863
1864     if (p != 0)
1865       tail = q;
1866
1867     if (mode == vmode)
1868     {
1869       build_page();
1870     }
1871   }
1872 }
1873 /* used to be align_peek, zfintieshrink, etc in old tex5.c */
1874 /************************************************************************/
1875 /* moved down here to avoid questions about pragma optimize */
1876 /* #pragma optimize("g", off) */
1877 /* for MC VS compiler */
1878 /* Moved down here 96/Oct/12 in response to problem with texerror.tex */
1879 /* pragma optimize("a", off) not strong enough - this may slow things */
1880 /* sec 0791 */
1881 bool fin_col (void)
1882 {
1883   halfword p;
1884   halfword q, r;
1885   halfword s;
1886   halfword u;
1887   scaled w;
1888   glue_ord o;
1889   halfword n;
1890
1891   if (cur_align == 0)
1892   {
1893     confusion("endv");
1894     return 0;       // abort_flag set
1895   }
1896
1897   q = link(cur_align);
1898
1899   if (q == 0)
1900   {
1901     confusion("endv");
1902     return 0;       // abort_flag set
1903   }
1904
1905   if (align_state < 500000L)
1906   {
1907     fatal_error("(interwoven alignment preambles are not allowed)");
1908     return 0;     // abort_flag set
1909   }
1910
1911   p = link(q);
1912
1913   if ((p == 0) && (extra_info(cur_align) < cr_code))
1914     if (cur_loop != 0)
1915     {
1916 /*  potential problem here if new_null_box causes memory reallocation ??? */
1917 /*  compiler optimization does not refresh `mem' loaded in registers ? */
1918       link(q) = new_null_box();
1919       p = link(q);
1920       info(p) = end_span;
1921       width(p) = null_flag;
1922       cur_loop = link(cur_loop);
1923       q = hold_head;
1924       r = u_part(cur_loop);
1925
1926       while (r != 0)
1927       {
1928         link(q) = get_avail();
1929         q = link(q);
1930         info(q) = info(r);
1931         r = link(r);
1932       }
1933
1934       link(q) = 0;
1935       u_part(p) = link(hold_head);
1936       q = hold_head;
1937       r = v_part(cur_loop);
1938
1939       while (r != 0)
1940       {
1941         link(q) = get_avail();
1942         q = link(q);
1943         info(q) = info(r);
1944         r = link(r);
1945       }
1946
1947       link(q) = 0;
1948       v_part(p) = link(hold_head);
1949       cur_loop = link(cur_loop);
1950       link(p) = new_glue(glue_ptr(cur_loop));
1951     }
1952     else
1953     {
1954       print_err("Extra alignment tab has been changed to ");
1955       print_esc("cr");
1956       help3("You have given more \\span or & marks than there were",
1957           "in the preamble to the \\halign or \\valign now in progress.",
1958           "So I'll assume that you meant to type \\cr instead.");
1959       extra_info(cur_align) = cr_code;
1960       error();
1961     }
1962
1963   if (extra_info(cur_align) != span_code)
1964   {
1965     unsave();
1966
1967     new_save_level(align_group);
1968
1969     {
1970       if (mode == -hmode)
1971       {
1972         adjust_tail = cur_tail;
1973         u = hpack(link(head), 0, 1);
1974         w = width(u);
1975         cur_tail = adjust_tail;
1976         adjust_tail = 0;
1977       }
1978       else
1979       {
1980         u = vpackage(link(head), 0, 1, 0);
1981         w = height(u);
1982       }
1983
1984       n = min_quarterword;
1985
1986       if (cur_span != cur_align)
1987       {
1988         q = cur_span;
1989
1990         do
1991           {
1992             incr(n);
1993             q = link(link(q));
1994           }
1995         while (!(q == cur_align));
1996
1997         if (n > max_quarterword)
1998         {
1999           confusion("256 spans");   /* 256 spans --- message wrong now, but ... */
2000           return 0;       // abort_flag set
2001         }
2002
2003         q = cur_span;
2004
2005         while (link(info(q)) < n)
2006           q = info(q);
2007
2008         if (link(info(q)) > n)
2009         {
2010           s = get_node(span_node_size);
2011           info(s) = info(q);
2012           link(s) = n;
2013           info(q) = s;
2014           width(s) = w;
2015         }
2016         else if (width(info(q)) < w)
2017           width(info(q)) = w;
2018       }
2019       else if (w > width(cur_align))
2020         width(cur_align) = w;
2021
2022       type(u) = unset_node;
2023       span_count(u) = n;
2024
2025       if (total_stretch[filll] != 0)
2026         o = filll;
2027       else if (total_stretch[fill] != 0)
2028         o = fill;
2029       else if (total_stretch[fil] != 0)
2030         o = fil;
2031       else
2032         o = normal;
2033
2034       glue_order(u) = o;
2035       glue_stretch(u) = total_stretch[o];
2036
2037       if (total_shrink[filll] != 0)
2038         o = filll;
2039       else if (total_shrink[fill] != 0)
2040         o = fill;
2041       else if (total_shrink[fil] != 0)
2042         o = fil;
2043       else
2044         o = normal;
2045
2046       glue_sign(u) = o;
2047       glue_shrink(u) = total_shrink[o];
2048       pop_nest();
2049       link(tail) = u;
2050       tail = u;
2051     }
2052
2053     tail_append(new_glue(glue_ptr(link(cur_align))));
2054     subtype(tail) = tab_skip_code + 1;
2055
2056     if (extra_info(cur_align) >= cr_code)
2057     {
2058       return true;
2059     }
2060
2061     init_span(p);
2062   }
2063
2064   align_state = 1000000L;
2065
2066   do
2067     {
2068       get_x_token();
2069     }
2070   while (!(cur_cmd != spacer));
2071
2072   cur_align = p;
2073   init_col();
2074
2075   return false;
2076 }
2077 /* sec 0749 */
2078 scaled make_op_(halfword q)
2079 {
2080   scaled delta;
2081   halfword p, v, x, y, z;
2082   quarterword c;
2083   ffour_quarters i;
2084   scaled shift_up, shift_down;
2085
2086   if ((subtype(q) == normal) && (cur_style < text_style))
2087     subtype(q) = limits;
2088
2089   if (math_type(nucleus(q)) == math_char)
2090   {
2091     fetch(nucleus(q));
2092
2093     if ((cur_style < text_style) && (char_tag(cur_i) == list_tag))
2094     {
2095       c = rem_byte(cur_i);
2096       i = char_info(cur_f, c);
2097
2098       if ((i.b0 > 0))
2099       {
2100         cur_c = c;
2101         cur_i = i;
2102         character(nucleus(q)) = c;
2103       }
2104     }
2105
2106     delta = char_italic(cur_f, cur_i);
2107     x = clean_box(nucleus(q), cur_style);
2108
2109     if ((math_type(subscr(q)) != 0) && (subtype(q) != limits))
2110       width(x) = width(x) - delta;
2111
2112     shift_amount(x) = half(height(x) - depth(x)) - axis_height(cur_size);
2113     math_type(nucleus(q)) = sub_box;
2114     info(nucleus(q)) = x;
2115   }
2116   else
2117     delta = 0;
2118
2119   if (subtype(q) == limits)
2120   {
2121     x = clean_box(supscr(q), sup_style(cur_style));
2122     y = clean_box(nucleus(q), cur_style);
2123     z = clean_box(subscr(q), sub_style(cur_style));
2124     v = new_null_box();
2125     type(v) = vlist_node;
2126     width(v) = width(y);
2127
2128     if (width(x) > width(v))
2129       width(v) = width(x);
2130
2131     if (width(z) > width(v))
2132       width(v) = width(z);
2133
2134     x = rebox(x, width(v));
2135     y = rebox(y, width(v));
2136     z = rebox(z, width(v));
2137     shift_amount(x) = half(delta);
2138     shift_amount(z) = - (integer) shift_amount(x);
2139     height(v) = height(y);
2140     depth(v) = depth(y);
2141
2142     if (math_type(supscr(q)) == 0)
2143     {
2144       free_node(x, box_node_size);
2145       list_ptr(v) = y;
2146     }
2147     else
2148     {
2149       shift_up = big_op_spacing3 - depth(x);
2150
2151       if (shift_up < big_op_spacing1)
2152         shift_up = big_op_spacing1;
2153
2154       p = new_kern(shift_up);
2155       link(p) = y;
2156       link(x) = p;
2157       p = new_kern(big_op_spacing5);
2158       link(p) = x;
2159       list_ptr(v) = p;
2160       height(v) = height(v) + big_op_spacing5 + height(x) + depth(x) + shift_up;
2161     }
2162
2163     if (math_type(subscr(q)) == 0)
2164       free_node(z, box_node_size);
2165     else
2166     {
2167       shift_down = big_op_spacing4 - height(z);
2168
2169       if (shift_down < big_op_spacing2)
2170         shift_down = big_op_spacing2;
2171
2172       p = new_kern(shift_down);
2173       link(y) = p;
2174       link(p) = z;
2175       p = new_kern(big_op_spacing5);
2176       link(z) = p;
2177       depth(v) = depth(v) + big_op_spacing5 + height(z) + depth(z) + shift_down;
2178     }
2179
2180     new_hlist(q) = v;
2181   }
2182
2183   return delta;
2184 }
2185 /* sec 0756 */
2186 void make_scripts_(halfword q, scaled delta)
2187 {
2188   halfword p, x, y, z;
2189   scaled shift_up, shift_down, clr;
2190   small_number t;
2191
2192   p = new_hlist(q);
2193
2194   if ((p >= hi_mem_min))
2195   {
2196     shift_up = 0;
2197     shift_down = 0;
2198   }
2199   else
2200   {
2201     z = hpack(p, 0, 1);
2202
2203     if (cur_style < script_style)
2204       t = script_size;
2205     else
2206       t = script_script_size;
2207
2208     shift_up = height(z) - sup_drop(t);
2209     shift_down = depth(z) + sub_drop(t);
2210     free_node(z, box_node_size);
2211   }
2212
2213   if (math_type(supscr(q)) == 0)
2214   {
2215     x = clean_box(subscr(q), sub_style(cur_style));
2216     width(x) = width(x) + script_space;
2217
2218     if (shift_down < sub1(cur_size))
2219       shift_down = sub1(cur_size);
2220
2221     clr = height(x) -(abs(math_x_height(cur_size) * 4) / 5);
2222
2223     if (shift_down < clr)
2224       shift_down = clr;
2225
2226     shift_amount(x) = shift_down;
2227   }
2228   else
2229   {
2230     {
2231       x = clean_box(supscr(q), sup_style(cur_style));
2232       width(x) = width(x) + script_space;
2233
2234       if (odd(cur_style))
2235         clr = sup3(cur_size);
2236       else if (cur_style < text_style)
2237         clr = sup1(cur_size);
2238       else
2239         clr = sup2(cur_size);
2240
2241       if (shift_up < clr)
2242         shift_up = clr;
2243
2244       clr = depth(x) +(abs(math_x_height(cur_size)) / 4);
2245
2246       if (shift_up < clr)
2247         shift_up = clr;
2248     }
2249
2250     if (math_type(subscr(q)) == 0)
2251       shift_amount(x) = - (integer) shift_up;
2252     else
2253     {
2254       y = clean_box(subscr(q), sub_style(cur_style));
2255       width(y) = width(y) + script_space;
2256
2257       if (shift_down < sub2(cur_size))
2258         shift_down = sub2(cur_size);
2259
2260       clr = 4 * default_rule_thickness - ((shift_up - depth(x)) - (height(y) - shift_down));
2261
2262       if (clr > 0)
2263       {
2264         shift_down = shift_down + clr;
2265
2266         clr = (abs(math_x_height(cur_size) * 4) / 5) - (shift_up - depth(x));
2267
2268         if (clr > 0)
2269         {
2270           shift_up = shift_up + clr;
2271           shift_down = shift_down - clr;
2272         }
2273       }
2274
2275       shift_amount(x) = delta;
2276       p = new_kern((shift_up - depth(x)) - (height(y) - shift_down));
2277       link(x) = p;
2278       link(p) = y;
2279       x = vpackage(x, 0, 1, 1073741823L);  /* 2^30 - 1 */
2280       shift_amount(x) = shift_down;
2281     }
2282   }
2283
2284   if (new_hlist(q) == 0)
2285     new_hlist(q) = x;
2286   else
2287   {
2288     p = new_hlist(q);
2289
2290     while (link(p) != 0)
2291       p = link(p);
2292
2293     link(p) = x;
2294   }
2295 }