OSDN Git Service

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