OSDN Git Service

updated macros.
[putex/putex.git] / src / texsourc / tex2.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 /* following bit used to be end of tex1.c */
23
24 #ifdef STAT
25 /* sec 0284 */
26 void restore_trace_(halfword p, char * s)
27 {
28   begin_diagnostic();
29   print_char('{');
30   print_string(s);
31   print_char(' ');
32   show_eqtb(p);
33   print_char('}');
34   end_diagnostic(false);
35 }
36 #endif /* STAT */
37 /* sec 0281 */
38 void unsave (void)
39 {
40   halfword p;
41   quarterword l;
42   halfword t;
43
44   if (cur_level > level_one)
45   {
46     decr(cur_level);
47     while (true) {
48       decr(save_ptr);
49
50       if (save_type(save_ptr) == level_boundary)
51         goto lab30;
52
53       p = save_index(save_ptr);
54
55       if (save_type(save_ptr) == insert_token)
56       {
57         t = cur_tok;
58         cur_tok = p;
59         back_input();
60         cur_tok = t;
61       }
62       else
63       {
64         if (save_type(save_ptr) == restore_old_value)
65         {
66           l = save_level(save_ptr);
67           decr(save_ptr);
68         }
69         else
70           save_stack[save_ptr] = eqtb[undefined_control_sequence];
71         
72         if (p < int_base)
73           if (eq_level(p) == level_one)
74           {
75             eq_destroy(save_stack[save_ptr]);
76 #ifdef STAT
77             if (tracing_restores > 0)
78               restore_trace(p, "retaining");
79 #endif /* STAT */
80           }
81           else
82           {
83             eq_destroy(eqtb[p]);
84             eqtb[p] = save_stack[save_ptr];
85 #ifdef STAT
86             if (tracing_restores > 0)
87               restore_trace(p, "restoring");
88 #endif /* STAT */
89           }
90         else if (xeq_level[p] != level_one)
91         {
92           eqtb[p] = save_stack[save_ptr];
93           xeq_level[p] = l;     /* l may be used without having been ... */
94 #ifdef STAT
95           if (tracing_restores > 0)
96             restore_trace(p, "restoring");
97 #endif /* STAT */
98         }
99         else
100         {
101 #ifdef STAT
102           if (tracing_restores > 0)
103             restore_trace(p, "retaining");
104 #endif /* STAT */
105         }
106       }
107     }
108 lab30:
109     cur_group = save_level(save_ptr);
110     cur_boundary = save_index(save_ptr);
111   }
112   else
113   {
114     confusion("curlevel");
115     return;       // abort_flag set
116   }
117 }
118 /* This is where the old tex2.c used to start */
119 /* sec 0288 */
120 void prepare_mag (void) 
121 {
122   if ((mag_set > 0) && (mag != mag_set))
123   {
124     print_err("Incompatible magnification (");
125     print_int(mag);
126     print_string(");");
127     print_nl(" the previous value will be retained");
128     help2("I can handle only one magnification ratio per job. So I've",
129         "reverted to the magnification you used earlier on this run.");
130     int_error(mag_set);
131     geq_word_define(int_base + mag_code, mag_set);
132   }
133
134   if ((mag <= 0) || (mag > 32768L))
135   {
136     print_err("Illegal magnification has been changed to 1000");
137     help1("The magnification ratio must be between 1 and 32768.");
138     int_error(mag);
139     geq_word_define(int_base + mag_code, 1000);
140   }
141   mag_set = mag;
142 }
143 /* sec 0295 */
144 void token_show_ (halfword p)
145 {
146   if (p != 0)
147     show_token_list(link(p), 0, 10000000L);
148 }
149 /* sec 0296 */
150 void print_meaning (void) 
151 {
152   print_cmd_chr(cur_cmd, cur_chr);
153
154   if (cur_cmd >= call)
155   {
156     print_char(':');
157     print_ln();
158     token_show(cur_chr);
159   }
160   else if (cur_cmd == top_bot_mark)
161   {
162     print_char(':');
163     print_ln();
164     token_show(cur_mark[cur_chr]);
165   }
166 }
167 /* sec 0299 */
168 void show_cur_cmd_chr (void)
169
170   begin_diagnostic();
171   print_nl("{");
172
173   if (mode != shown_mode)
174   {
175     print_mode(mode);
176     print_string(": ");
177     shown_mode = mode;
178   }
179
180   print_cmd_chr(cur_cmd, cur_chr);
181   print_char('}');
182   end_diagnostic(false);
183 }
184 /* sec 0311 */
185 void show_context (void)
186 {
187   char old_setting;
188   integer nn;
189   bool bottomline;
190   integer i;
191   integer j;
192   integer l;
193   integer m;
194   integer n;
195   integer p;
196   integer q;
197
198   base_ptr = input_ptr;
199   input_stack[base_ptr] = cur_input;
200   nn = -1;
201   bottomline = false;
202
203   while (true)
204   {
205     cur_input = input_stack[base_ptr];
206
207     if ((cur_input.state_field != 0))
208       if ((cur_input.name_field > 17) || (base_ptr == 0))
209         bottomline = true;
210
211     if ((base_ptr == input_ptr) || bottomline || (nn < error_context_lines))
212     {
213       if ((base_ptr == input_ptr) || (cur_input.state_field != token_list) ||
214           (cur_input.index_field != backed_up) || (cur_input.loc_field != 0))
215       {
216         tally = 0;
217         old_setting = selector;
218
219         if (cur_input.state_field != 0)
220         {
221           if (cur_input.name_field <= 17)
222             if ((cur_input.name_field == 0))
223               if (base_ptr == 0)
224                 print_nl("<*>");
225               else
226                 print_nl("<insert> ");
227             else
228             {
229               print_nl("<read ");
230               if (cur_input.name_field == 17)
231                 print_char('*');
232               else
233                 print_int(cur_input.name_field - 1);
234               print_char('>');
235             }
236           else
237           {
238             if (c_style_flag)
239             {
240               print_ln();
241               /* show current input file name - ignore if from terminal */
242               if (cur_input.name_field > 17)  /* redundant ? */
243                 print(cur_input.name_field);
244
245               print_char('(');
246               print_int(line); /* line number */
247               print_char(')');
248               print_char(' ');
249               print_char(':');
250             }
251             else
252             {
253               print_nl("l.");        /* l. ? 573 ????? 98/Dec/8 check ! */
254               print_int(line);      /* line number */
255             }
256           }
257
258           print_char(' ');
259
260           {
261             l = tally;
262             tally = 0;
263             selector = pseudo;
264             trick_count = 1000000L;
265           }
266
267           if (buffer[cur_input.limit_field] == end_line_char)
268             j = cur_input.limit_field;
269           else
270             j = cur_input.limit_field + 1;
271
272           if (j > 0)
273             for (i = cur_input.start_field; i <= j - 1; i++)
274             {
275               if (i == cur_input.loc_field)
276               {
277                 first_count = tally;
278                 trick_count = tally + 1 + error_line - half_error_line;
279
280                 if (trick_count < error_line)
281                   trick_count = error_line;
282               }
283               print(buffer[i]);
284             }
285         }
286         else
287         {
288           switch (cur_input.index_field)
289           {
290             case parameter:
291               print_nl("<argument> ");
292               break;
293
294             case u_template:
295             case v_template:
296               print_nl("<template> ");
297               break;
298
299             case backed_up:
300               if (cur_input.loc_field == 0)
301                 print_nl("<recently read> ");
302               else
303                 print_nl("<to be read again> ");
304               break;
305
306             case inserted:
307               print_nl("<inserted text> ");
308               break;
309
310             case macro:
311               print_ln();
312               print_cs(cur_input.name_field);
313               break;
314
315             case output_text:
316               print_nl("<output> ");
317               break;
318
319             case every_par_text:
320               print_nl("<everypar> ");
321               break;
322
323             case every_math_text:
324               print_nl("<everymath> ");
325               break;
326
327             case every_display_text:
328               print_nl("<everydisplay> ");
329               break;
330
331             case every_hbox_text:
332               print_nl("<everyhbox> ");
333               break;
334
335             case every_vbox_text:
336               print_nl("<everyvbox> ");
337               break;
338
339             case every_job_text:
340               print_nl("<everyjob> ");
341               break;
342
343             case every_cr_text:
344               print_nl("<everycr> ");
345               break;
346
347             case mark_text:
348               print_nl("<mark> ");
349               break;
350
351             case write_text:
352               print_nl("<write> ");
353               break;
354
355             default:
356               print_nl("?");
357               break;
358           }
359
360           {
361             l = tally;
362             tally = 0;
363             selector = pseudo;
364             trick_count = 1000000L;
365           }
366
367           if (cur_input.index_field < macro)
368             show_token_list(cur_input.start_field, cur_input.loc_field, 100000L);
369           else
370             show_token_list(link(cur_input.start_field), cur_input.loc_field, 100000L);
371         }
372
373         selector = old_setting;
374
375         if (trick_count == 1000000L)
376         {
377           first_count = tally;
378           trick_count = tally + 1 + error_line - half_error_line;
379
380           if (trick_count < error_line)
381             trick_count = error_line;
382         }
383         
384         if (tally < trick_count)
385           m = tally - first_count;
386         else
387           m = trick_count - first_count;
388
389         if (l + first_count <= half_error_line)
390         {
391           p = 0;
392           n = l + first_count;
393         }
394         else
395         {
396           print_string("...");
397           p = l + first_count - half_error_line + 3;
398           n = half_error_line;
399         }
400
401         for (q = p; q <= first_count - 1; q++)
402           print_char(trick_buf[q % error_line]);
403         
404         print_ln();
405
406         for (q = 1; q <= n; q++)
407           print_char(' ');
408
409         if (m + n <= error_line)
410           p = first_count + m;
411         else
412           p = first_count +(error_line - n - 3);
413
414         for (q = first_count; q <= p - 1; q++)
415           print_char(trick_buf[q % error_line]);
416
417         if (m + n > error_line)
418           print_string("...");
419         incr(nn);
420       }
421     }
422     else if (nn == error_context_lines)
423     {
424       print_nl("...");
425       incr(nn); 
426     }
427
428     if (bottomline)
429       goto lab30;
430
431     decr(base_ptr);
432   }
433 lab30:
434   cur_input = input_stack[input_ptr];
435 }
436 #pragma optimize("g", off)          /* 98/Dec/10 experiment */
437 /* sec 0323 */
438 void begin_token_list_ (halfword p, quarterword t)
439 {
440   {
441     if (input_ptr > max_in_stack)
442     {
443       max_in_stack = input_ptr;
444
445 #ifdef ALLOCATEINPUTSTACK
446       if (input_ptr == current_stack_size)
447         input_stack = realloc_input_stack(increment_stack_size);
448
449       if (input_ptr == current_stack_size) /* check again after allocation */
450       {
451         overflow("input stack size", current_stack_size);
452         return;     // abort_flag set
453       }
454 #else
455       if (input_ptr == stack_size) /* input stack - not dynamic */
456       {
457         overflow("input stack size", stack_size);
458         return;     // abort_flag set
459       }
460 #endif
461     }
462
463     input_stack[input_ptr] = cur_input;
464     incr(input_ptr);
465   }
466
467   cur_input.state_field = token_list;
468   cur_input.start_field = p;
469   cur_input.index_field = t;
470
471   if (t >= macro)
472   {
473     add_token_ref(p);
474
475     if (t == macro)
476       cur_input.limit_field = param_ptr;
477     else
478     {
479       cur_input.loc_field = link(p);
480
481       if (tracing_macros > 1)
482       {
483         begin_diagnostic(); 
484         print_nl("");
485
486         switch (t)
487         {
488           case mark_text:
489             print_esc("mark");
490             break;
491
492           case write_text:
493             print_esc("write");
494             break;
495
496           default:
497             print_cmd_chr(assign_toks, t + (hash_size + 1307));
498             break;
499         }
500
501         print_string("->");
502         token_show(p);
503         end_diagnostic(false);
504       }
505     }
506   }
507   else
508     cur_input.loc_field = p;
509 }
510 #pragma optimize("", on)          /* 98/Dec/10 experiment */
511 /* sec 0324 */
512 void end_token_list (void) 
513
514   if (cur_input.index_field >= backed_up)
515   {
516     if (cur_input.index_field <= inserted)
517       flush_list(cur_input.start_field); 
518     else
519     {
520       delete_token_ref(cur_input.start_field);
521       if (cur_input.index_field == macro)
522         while (param_ptr > cur_input.limit_field)
523         {
524           decr(param_ptr);
525           flush_list(param_stack[param_ptr]);
526         }
527     }
528   }
529   else if (cur_input.index_field == u_template)
530     if (align_state > 500000L)
531       align_state = 0;
532     else
533     {
534       fatal_error("(interwoven alignment preambles are not allowed)");
535       return;     // abort_flag set
536     }
537
538   {
539     decr(input_ptr);
540     cur_input = input_stack[input_ptr];
541   }
542
543   {
544     if (interrupt != 0)
545     {
546       pause_for_instructions();
547     }
548   }
549 }
550 /* sec 0325 */
551 void back_input (void)
552 {
553   halfword p;
554
555   while ((cur_input.state_field == 0) && (cur_input.loc_field == 0) &&
556       (cur_input.index_field != v_template))
557   {
558     end_token_list();
559   }
560
561   p = get_avail();
562   info(p) = cur_tok;
563
564   if (cur_tok < right_brace_limit)
565     if (cur_tok < left_brace_limit)
566       decr(align_state);
567     else
568       incr(align_state);
569
570   {
571     if (input_ptr > max_in_stack)
572     {
573       max_in_stack = input_ptr;
574 #ifdef ALLOCATEINPUTSTACK
575       if (input_ptr == current_stack_size)
576         input_stack = realloc_input_stack(increment_stack_size);
577
578       if (input_ptr == current_stack_size) /* check again after allocation */
579       {
580         overflow("input stack size", current_stack_size);
581         return;     // abort_flag set
582       }
583 #else
584       if (input_ptr == stack_size) /* stack size - not dynamic */
585       {
586         overflow("input stack size", stack_size);
587         return;     // abort_flag set
588       }
589 #endif
590     }
591     input_stack[input_ptr] = cur_input;
592     incr(input_ptr);
593   }
594
595   cur_input.state_field = token_list;
596   cur_input.start_field = p;
597   cur_input.index_field = backed_up;
598   cur_input.loc_field = p;
599 }
600 /* sec 0327 */
601 void back_error (void)
602 {
603   OK_to_interrupt = false;
604   back_input();
605   OK_to_interrupt = true;
606   error();
607 }
608 /* sec 0327 */
609 void ins_error (void) 
610 {
611   OK_to_interrupt = false;
612   back_input();
613   cur_input.index_field = inserted;
614   OK_to_interrupt = true;
615   error();
616 }
617 /* sec 0328 */
618 void begin_file_reading (void)
619 {
620   if (in_open == max_in_open)
621   {
622     overflow("text input levels", max_in_open); /* text input levels - NOT DYNAMIC */
623     return;     // abort_flag set
624   }
625 #ifdef ALLOCATEBUFFER
626   if (first == current_buf_size)
627     buffer = realloc_buffer(increment_buf_size);
628
629   if (first == current_buf_size) /* check again after allocation */
630   {
631     overflow("buffer size", current_buf_size);
632     return;     // abort_flag set
633   }
634 #else
635   if (first == buf_size)
636   {
637     overflow("buffer size", buf_size);  /* buffer size - not dynamic */
638     return;     // abort_flag set
639   }
640 #endif
641   incr(in_open);
642   if (in_open > high_in_open)     /* 1999 Jan 17 */
643     high_in_open = in_open;
644   {
645     if (input_ptr > max_in_stack)
646     {
647       max_in_stack = input_ptr;
648 #ifdef ALLOCATEINPUTSTACK
649       if (input_ptr == current_stack_size)
650         input_stack = realloc_input_stack(increment_stack_size);
651       if (input_ptr == current_stack_size)
652       {
653         overflow("input stack size", current_stack_size);  /* check again after allocation */
654         return;     // abort_flag set
655       }
656 #else
657       if (input_ptr == stack_size)
658       {
659         overflow("input stack size", stack_size);    /* input stack - not dynamic */
660         return;     // abort_flag set
661       }
662 #endif
663     }
664     input_stack[input_ptr] = cur_input;
665     incr(input_ptr);
666   }
667   cur_input.index_field = in_open;
668   line_stack[cur_input.index_field] = line;
669   cur_input.start_field = first;
670   cur_input.state_field = 1;
671   cur_input.name_field = 0;
672 }
673 /* sec 0329 */
674 void end_file_reading (void)
675 {
676   first = cur_input.start_field;
677   line = line_stack[cur_input.index_field];
678
679   if (cur_input.name_field > 17)
680     (void) a_close(input_file[cur_input.index_field]);
681
682   {
683     decr(input_ptr);
684     cur_input = input_stack[input_ptr];
685   }
686   decr(in_open);
687 }
688 /* called only form tex0.c */
689 /* sec 0330 */
690 void clear_for_error_prompt (void) 
691 {
692   while ((cur_input.state_field != 0) &&
693       (cur_input.name_field == 0) && (input_ptr > 0) &&
694       (cur_input.loc_field > cur_input.limit_field))
695     end_file_reading();
696
697   print_ln();
698 }
699 /* sec 0336 */
700 void check_outer_validity (void)
701 {
702   halfword p;
703   halfword q;
704
705   if (scanner_status != 0)
706   {
707     deletions_allowed = false;
708
709     if (cur_cs != 0)
710     {
711       if ((cur_input.state_field == 0) || (cur_input.name_field < 1) || (cur_input.name_field > 17))
712       {
713         p = get_avail();
714         info(p) = cs_token_flag + cur_cs;
715         back_list(p);
716       }
717
718       cur_cmd = spacer;
719       cur_chr = ' ';
720     }
721
722     if (scanner_status > skipping)
723     {
724       runaway();
725
726       if (cur_cs == 0)
727         print_err("File ended");
728       else
729       {
730         cur_cs = 0;
731         print_err("Forbidden control sequence found");
732       }
733
734       print_string(" while scanning ");
735       p = get_avail();
736
737       switch (scanner_status)
738       {
739         case defining:
740           print_string("definition");
741           info(p) = right_brace_token + '}';
742           break;
743
744         case matching:
745           print_string("use");
746           info(p) = par_token;
747           long_state = outer_call;
748           break;
749
750         case aligning:
751           print_string("preamble");
752           info(p) = right_brace_token + '}';
753           q = p;
754           p = get_avail();
755           link(p) = q;
756           info(p) = cs_token_flag + frozen_cr; /*96/Jan/10*/
757           align_state = -1000000L;
758           break;
759
760         case absorbing:
761           print_string("text");
762           info(p) = right_brace_token + '}';
763           break;
764       }
765       ins_list(p);
766       print_string(" of ");
767       sprint_cs(warning_index);
768       help4("I suspect you have forgotten a `}', causing me",
769           "to read past where you wanted me to stop.",
770           "I'll try to recover; but if the error is serious,",
771           "you'd better type `E' or `X' now and fix your file.");
772       error();
773     }
774     else
775     {
776       print_err("Incomplete ");
777       print_cmd_chr(if_test, cur_if);
778       print_string("; all text was ignored after line ");
779       print_int(skip_line);
780       help3("A forbidden control sequence occurred in skipped text.",
781           "This kind of error happens when you say `\\if...' and forget",
782           "the matching `\\fi'. I've inserted a `\\fi'; this might work.");
783
784       if (cur_cs != 0)
785         cur_cs = 0; 
786       else
787         help_line[2] = "The file ended while I was skipping conditional text.";
788
789       cur_tok = cs_token_flag + frozen_fi; /* 96/Jan/10 */
790       ins_error();
791   }
792     deletions_allowed = true;
793   }
794 }
795 /*****************************************************************************/
796 /* get_next() moved from here to end for pragma optimize reasons 96/Sep/12 */
797 void get_next(void);
798 /*****************************************************************************/
799 /* sec 0363 */
800 void firm_up_the_line (void)
801 {
802   integer k;
803
804   cur_input.limit_field = last;
805
806   if (pausing > 0)
807     if (interaction > nonstop_mode)
808     {
809       ;
810       print_ln();
811
812       if (cur_input.start_field < cur_input.limit_field)
813         for (k = cur_input.start_field; k <= cur_input.limit_field - 1; k++)
814           print(buffer[k]);
815
816       first = cur_input.limit_field;
817
818       {
819         ;
820         print_string("=>");
821         term_input("=>", 0);
822       }
823
824       if (last > first)
825       {
826         for (k = first; k <= last - 1; k++)
827           buffer[k + cur_input.start_field - first] = buffer[k];
828
829         cur_input.limit_field = cur_input.start_field + last - first;
830       }
831     }
832 }
833 /* sec 0365 */
834 void get_token (void)
835
836   no_new_control_sequence = false;
837   get_next();
838   no_new_control_sequence = true;
839
840   if (cur_cs == 0)
841     cur_tok = (cur_cmd * 256) + cur_chr;
842   else
843     cur_tok = cs_token_flag + cur_cs;
844 }
845 /* sec 0389 */
846 void macro_call (void)
847 {
848   halfword r;
849   halfword p;
850   halfword q;
851   halfword s;
852   halfword t;
853   halfword u, v;
854   halfword rbraceptr;
855   small_number n;
856   halfword unbalance;
857   halfword m;
858   halfword refcount;
859   small_number savescannerstatus;
860   halfword savewarningindex;
861   ASCII_code match_chr;
862
863   savescannerstatus = scanner_status;
864   savewarningindex = warning_index;
865   warning_index = cur_cs;
866   refcount = cur_chr;
867   r = link(refcount);
868   n = 0;
869
870   if (tracing_macros > 0)
871   {
872     begin_diagnostic();
873     print_ln();
874     print_cs(warning_index);
875     token_show(refcount);
876     end_diagnostic(false);
877   }
878
879   if (info(r) != end_match_token)
880   {
881     scanner_status = matching;
882     unbalance = 0;
883     long_state = eq_type(cur_cs);
884
885     if (long_state >= outer_call)
886       long_state = long_state - 2;
887
888     do
889       {
890         link(temp_head) = 0;
891
892         if ((info(r) > match_token + 255) || (info(r) < match_token))
893           s = 0;
894         else
895         {
896           match_chr = info(r) - match_token;
897           s = link(r);
898           r = s;
899           p = temp_head;
900           m = 0;
901         }
902 lab22:
903         get_token();
904
905         if (cur_tok == info(r))
906         {
907           r = link(r);
908
909           if ((info(r) >= match_token) && (info(r) <= end_match_token))
910           {
911             if (cur_tok < left_brace_limit)
912               decr(align_state);
913
914             goto lab40;
915           }
916           else
917             goto lab22;
918         }
919
920         if (s != r)
921           if (s == 0)
922           {
923             print_err("Use of ");
924             sprint_cs(warning_index);
925             print_string(" doesn't match its definition");
926             help4("If you say, e.g., `\\def\\a1{...}', then you must always",
927               "put `1' after `\\a', since control sequence names are",
928               "made up of letters only. The macro here has not been",
929               "followed by the required stuff, so I'm ignoring it.");
930             error();
931             goto lab10;
932           }
933           else
934           {
935             t = s;
936             do
937               {
938                 {
939                   q = get_avail();
940                   mem[p].hh.v.RH = q;
941                   mem[q].hh.v.LH = mem[t].hh.v.LH;
942                   p = q;
943                 }
944
945                 incr(m);
946                 u = link(t);
947                 v = s;
948
949                 while (true)
950                 {
951                   if (u == r)
952                     if (cur_tok != info(v))
953                       goto lab30;
954                     else
955                     {
956                       r = link(v);
957                       goto lab22;
958                     }
959
960                     if (info(u) != info(v))
961                       goto lab30;
962
963                     u = link(u);
964                     v = link(v);
965                 }
966 lab30:
967                 t = link(t);
968               }
969             while(!(t == r));
970
971             r = s;
972           }
973
974         if (cur_tok == par_token)
975           if (long_state != long_call)
976           {
977             if (long_state == call)
978             {
979               runaway();
980               print_err("Paragraph ended before ");
981               sprint_cs(warning_index);
982               print_string("was complete");
983               help3("I suspect you've forgotten a `}', causing me to apply this",
984                   "control sequence to too much text. How can we recover?",
985                   "My plan is to forget the whole thing and hope for the best.");
986               back_error();
987             }
988
989             pstack[n] = link(temp_head);
990             align_state = align_state - unbalance;
991
992             for (m = 0; m <= n; m++)
993               flush_list(pstack[m]);
994
995             goto lab10;
996           }
997
998         if (cur_tok < right_brace_limit)
999           if (cur_tok < left_brace_limit)
1000           {
1001             unbalance = 1;
1002
1003             while (true)
1004             {
1005               {
1006                 {
1007                   q = avail;
1008
1009                   if (q == 0)
1010                     q = get_avail();
1011                   else
1012                   {
1013                     avail = mem[q].hh.v.RH;
1014                     mem[q].hh.v.RH = 0;
1015 #ifdef STAT
1016                     incr(dyn_used);
1017 #endif /* STAT */
1018                   }
1019                 }
1020
1021                 mem[p].hh.v.RH = q;
1022                 mem[q].hh.v.LH = cur_tok;
1023                 p = q;
1024               }
1025
1026               get_token();
1027
1028               if (cur_tok == par_token)
1029                 if (long_state != long_call)
1030                 {
1031                   if (long_state == call)
1032                   {
1033                     runaway();
1034                     print_err("Paragraph ended before ");
1035                     sprint_cs(warning_index);
1036                     print_string(" was complete");
1037                     help3("I suspect you've forgotten a `}', causing me to apply this",
1038                         "control sequence to too much text. How can we recover?",
1039                         "My plan is to forget the whole thing and hope for the best.");
1040                     back_error();
1041                   }
1042
1043                   pstack[n] = link(temp_head);
1044                   align_state = align_state - unbalance;
1045
1046                   for (m = 0; m <= n; m++)
1047                     flush_list(pstack[m]);
1048                   goto lab10;
1049                 }
1050
1051               if (cur_tok < right_brace_limit)
1052                 if (cur_tok < left_brace_limit)
1053                   incr(unbalance);
1054                 else
1055                 {
1056                   decr(unbalance);
1057
1058                   if (unbalance == 0)
1059                     goto lab31;
1060                 }
1061             }
1062 lab31:
1063             rbraceptr = p;
1064
1065             {
1066               q = get_avail();
1067               mem[p].hh.v.RH = q;
1068               mem[q].hh.v.LH = cur_tok;
1069               p = q;
1070             }
1071           }
1072           else
1073           {
1074             back_input();
1075             print_err("Argument of ");
1076             sprint_cs(warning_index);
1077             print_string(" has an extra }");
1078             help6("I've run across a `}' that doesn't seem to match anything.",
1079                 "For example, `\\def\\a#1{...}' and `\\a}' would produce",
1080                 "this error. If you simply proceed now, the `\\par' that",
1081                 "I've just inserted will cause me to report a runaway",
1082                 "argument that might be the root of the problem. But if",
1083                 "your `}' was spurious, just type `2' and it will go away.");
1084             incr(align_state);
1085             long_state = call;
1086             cur_tok = par_token;
1087             ins_error();
1088             goto lab22;
1089           }
1090         else
1091         {
1092           if (cur_tok == space_token)
1093             if (info(r) <= end_match_token)
1094               if (info(r) >= match_token)
1095                 goto lab22;
1096
1097           {
1098             q = get_avail();
1099             mem[p].hh.v.RH = q;   /* p may be used without having ... */
1100             mem[q].hh.v.LH = cur_tok;
1101             p = q;
1102           }
1103         }
1104
1105         incr(m);          /* m may be used without having been ... */
1106
1107         if (info(r) > end_match_token)
1108           goto lab22;
1109
1110         if (info(r) < match_token)
1111           goto lab22;
1112 lab40:
1113         if (s != 0)
1114         {
1115           if ((m == 1) && (info(p) < right_brace_limit) && (p != temp_head))
1116           {
1117             link(rbraceptr) = 0; /* rbraceptr may be used without ... */
1118             free_avail(p);
1119             p = link(temp_head);
1120             pstack[n] = link(p);
1121             free_avail(p);
1122           }
1123           else
1124             pstack[n] = link(temp_head);
1125
1126           incr(n);
1127
1128           if (tracing_macros > 0)
1129           {
1130             begin_diagnostic();
1131             //print_nl(match_chr); /* matchchar may be used without ... */
1132             print_nl(""); print(match_chr);
1133             print_int(n);
1134             print_string("<-");
1135             show_token_list(pstack[n - 1], 0, 1000);
1136             end_diagnostic(false);
1137           }
1138         }
1139       }
1140     while(!(info(r) == end_match_token));
1141   }
1142
1143   while((cur_input.state_field == token_list) && (cur_input.loc_field == 0) &&
1144       (cur_input.index_field != v_template))
1145     end_token_list();
1146
1147   begin_token_list(refcount, macro);
1148   cur_input.name_field = warning_index;
1149   cur_input.loc_field = link(r);
1150
1151   if (n > 0)
1152   {
1153     if (param_ptr + n > max_param_stack)
1154     {
1155       max_param_stack = param_ptr + n;
1156
1157 #ifdef ALLOCATEPARAMSTACK
1158       if (max_param_stack > current_param_size)
1159         param_stack = realloc_param_stack(increment_param_size);
1160
1161       if (max_param_stack > current_param_size) /* check again after allocation */
1162       {
1163         overflow("parameter stack size", current_param_size);
1164         return;     // abort_flag set
1165       }
1166 #else
1167       if (max_param_stack > param_size)
1168       {
1169         overflow("parameter stack size", param_size); /* parameter stack - not dynamic */
1170         return;     // abort_flag set
1171       }
1172 #endif
1173     }
1174
1175     for (m = 0; m <= n - 1; m++)
1176       param_stack[param_ptr + m] = pstack[m];
1177
1178     param_ptr = param_ptr + n;
1179   }
1180 lab10:
1181   scanner_status = savescannerstatus;
1182   warning_index = savewarningindex;
1183 }
1184 /* sec 0379 */
1185 void insert_relax (void)
1186 {
1187   cur_tok = cs_token_flag + cur_cs;
1188   back_input();
1189   cur_tok = cs_token_flag + frozen_relax;  /* 96/Jan/10 */
1190   back_input();
1191   cur_input.index_field = inserted;
1192 }
1193 /* sec 0366 */
1194 void expand (void)
1195 {
1196   halfword t;
1197   halfword p, q, r;
1198   integer j;
1199   integer cvbackup;
1200   small_number cvlbackup, radixbackup, cobackup;
1201   halfword backupbackup;
1202   small_number savescannerstatus;
1203
1204   cvbackup = cur_val;
1205   cvlbackup = cur_val_level;
1206   radixbackup = radix;
1207   cobackup = cur_order;
1208   backupbackup = link(backup_head);
1209
1210   if (cur_cmd < call)
1211   {
1212     if (tracing_commands > 1)
1213       show_cur_cmd_chr();
1214
1215     switch (cur_cmd)
1216     {
1217       case top_bot_mark:
1218         if (cur_mark[cur_chr] != 0)
1219           begin_token_list(cur_mark[cur_chr], mark_text);
1220         break;
1221
1222       case expand_after:
1223         get_token();
1224         t = cur_tok;
1225         get_token();
1226
1227         if (cur_cmd > max_command)
1228           expand();
1229         else
1230           back_input();
1231
1232         cur_tok = t;
1233         back_input();
1234         break;
1235
1236       case no_expand:
1237         savescannerstatus = scanner_status;
1238         scanner_status = normal;
1239         get_token();
1240         scanner_status = savescannerstatus;
1241         t = cur_tok;
1242         back_input();
1243
1244         if (t >= cs_token_flag)
1245         {
1246           p = get_avail();
1247           info(p) = cs_token_flag + frozen_dont_expand; /*96/Jan/10*/
1248           link(p) = cur_input.loc_field;
1249           cur_input.start_field = p;
1250           cur_input.loc_field = p;
1251         }
1252         break;
1253
1254       case cs_name:
1255         r = get_avail();
1256         p = r;
1257         do
1258           {
1259             get_x_token();
1260   
1261             if (cur_cs == 0)
1262             {
1263               q = get_avail();
1264               mem[p].hh.v.RH = q;
1265               mem[q].hh.v.LH = cur_tok;
1266               p = q;
1267             }
1268           }
1269         while(!(cur_cs != 0));
1270
1271         if (cur_cmd != end_cs_name)
1272         {
1273           print_err("Missing ");
1274           print_esc("endcsname");
1275           print_string(" inserted");
1276           help2("The control sequence marked <to be read again> should",
1277               "not appear between \\csname and \\endcsname.");
1278           back_error();
1279         }
1280
1281         j = first;
1282         p = link(r);
1283
1284         while (p != 0)
1285         {
1286           if (j >= max_buf_stack)
1287           {
1288             max_buf_stack = j + 1;
1289
1290 #ifdef ALLOCATEBUFFER
1291             if (max_buf_stack == current_buf_size)
1292               buffer = realloc_buffer (increment_buf_size);
1293
1294             if (max_buf_stack == current_buf_size) /* check again after allocation */
1295             {
1296               overflow("buffer size", current_buf_size);
1297               return;     // abort_flag set
1298             }
1299 #else
1300             if (max_buf_stack == buf_size)
1301             {
1302               overflow("buffer size", buf_size); /* buffer size - not dynamic */
1303               return;     // abort_flag set
1304             }
1305 #endif
1306           }
1307
1308           buffer[j] = info(p) % 256;
1309           incr(j);
1310           p = link(p);
1311         }
1312
1313         if (j > first + 1)
1314         {
1315           no_new_control_sequence = false;
1316           cur_cs = id_lookup(first, j - first);
1317           no_new_control_sequence = true;
1318         }
1319         else if (j == first)
1320           cur_cs = null_cs;
1321         else
1322           cur_cs = single_base + buffer[first];
1323
1324         flush_list(r);
1325
1326         if (eq_type(cur_cs) == undefined_cs)
1327         {
1328           eq_define(cur_cs, relax, 256);
1329         }
1330
1331         cur_tok = cur_cs + cs_token_flag;
1332         back_input();
1333         break;
1334
1335       case convert:
1336         conv_toks();
1337         break;
1338
1339       case the:
1340         ins_the_toks();
1341         break;
1342
1343       case if_test:
1344         conditional();
1345         break;
1346
1347       case fi_or_else:
1348         if (cur_chr > if_limit)
1349           if (if_limit == 1)
1350             insert_relax();
1351           else
1352           {
1353             print_err("Extra ");
1354             print_cmd_chr(fi_or_else, cur_chr);
1355             help1("I'm ignoring this; it doesn't match any \\if.");
1356             error();
1357           }
1358         else
1359         {
1360           while(cur_chr != fi_code)
1361             pass_text();
1362
1363           {
1364             p = cond_ptr;
1365             if_line = if_line_field(p);
1366             cur_if = subtype(p);
1367             if_limit = type(p);
1368             cond_ptr = link(p);
1369             free_node(p, if_node_size);
1370           }
1371         }
1372         break;
1373
1374       case input:
1375         if (cur_chr > 0)
1376           force_eof = true;
1377         else if (name_in_progress)
1378           insert_relax();
1379         else
1380           start_input();
1381         break;
1382
1383       default:
1384         print_err("Undefined control sequence");
1385         help5("The control sequence at the end of the top line",
1386             "of your error message was never \\def'ed. If you have",
1387             "misspelled it (e.g., `\\hobx'), type `I' and the correct",
1388             "spelling (e.g., `I\\hbox'). Otherwise just continue,",
1389             "and I'll forget about whatever was undefined.");
1390         error();
1391         break;
1392     }
1393   }
1394   else if (cur_cmd < end_template)
1395   {
1396     macro_call();
1397   }
1398   else
1399   {
1400     cur_tok = cs_token_flag + frozen_endv; /* 96/Jan/10 */
1401     back_input();
1402   }
1403
1404   cur_val = cvbackup;
1405   cur_val_level = cvlbackup;
1406   radix = radixbackup;
1407   cur_order = cobackup;
1408   link(backup_head) = backupbackup;
1409 }
1410 /* sec 0380 */
1411 void get_x_token (void)
1412 {
1413 lab20:
1414   get_next();
1415
1416   if (cur_cmd <= max_command)
1417     goto lab30;
1418   if (cur_cmd >= call)
1419     if (cur_cmd < end_template)
1420       macro_call();
1421     else
1422     {
1423       cur_cs = frozen_endv;  /* 96/Jan/10 */
1424       cur_cmd = endv;
1425       goto lab30;
1426     }
1427   else
1428     expand();
1429
1430   goto lab20;
1431 lab30:
1432   if (cur_cs == 0)
1433     cur_tok = (cur_cmd * 256) + cur_chr;
1434   else
1435     cur_tok = cs_token_flag + cur_cs;
1436 }
1437 /* sec 0381 */
1438 void x_token (void)
1439 {
1440   while (cur_cmd > max_command)
1441   {
1442     expand();
1443     get_next();
1444   }
1445
1446   if (cur_cs == 0)
1447     cur_tok = (cur_cmd * 256) + cur_chr;
1448   else
1449     cur_tok = cs_token_flag + cur_cs;
1450 }
1451 /* sec 0403 */
1452 void scan_left_brace (void)
1453 {
1454   do
1455     {
1456       get_x_token();
1457     }
1458   while(!((cur_cmd != spacer) && (cur_cmd != relax)));
1459
1460   if (cur_cmd != left_brace)
1461   {
1462     print_err("Missing { inserted");
1463     help4("A left brace was mandatory here, so I've put one in.",
1464         "You might want to delete and/or insert some corrections",
1465         "so that I will find a matching right brace soon.",
1466         "(If you're confused by all this, try typing `I}' now.)");
1467     back_error();
1468     cur_tok = left_brace_token + '{';
1469     cur_cmd = left_brace;
1470     cur_chr = '{';
1471     incr(align_state);
1472   }
1473 }
1474 /* sec 0405 */
1475 void scan_optional_equals (void)
1476 {
1477   do
1478     {
1479       get_x_token();
1480     }
1481   while(!(cur_cmd != spacer));
1482
1483   if (cur_tok != other_token + '=')
1484     back_input();
1485 }
1486 /* sec 0407 */
1487 bool scan_keyword_(char * s)
1488 {
1489   halfword p;
1490   halfword q;
1491   char * k;
1492
1493   p = backup_head;
1494   link(p) = 0;
1495   k = s;
1496
1497   while (*k)
1498   {
1499     get_x_token(); 
1500
1501     if ((cur_cs == 0) && ((cur_chr == (*k)) || (cur_chr == (*k) - 'a' + 'A')))
1502     {
1503       {
1504         q = get_avail();
1505         mem[p].hh.v.RH = q;
1506         mem[q].hh.v.LH = cur_tok;
1507         p = q;
1508       }
1509
1510       incr(k);
1511     }
1512     else if ((cur_cmd != spacer) || (p != backup_head))
1513     {
1514       back_input();
1515
1516       if (p != backup_head)
1517         back_list(link(backup_head));
1518
1519       return false;
1520     }
1521   }
1522
1523   flush_list(link(backup_head));
1524
1525   return true;
1526 }
1527 /* sec 0408 */
1528 void mu_error (void)
1529 {
1530   print_err("Incompatible glue units");
1531   help1("I'm going to assume that 1mu=1pt when they're mixed.");
1532   error();
1533 }
1534 /* sec 0433 */
1535 void scan_eight_bit_int (void)
1536 {
1537   scan_int();
1538
1539   if ((cur_val < 0) || (cur_val > 255))
1540   {
1541     print_err("Bad register code");
1542     help2("A register number must be between 0 and 255.",
1543         "I changed this one to zero.");
1544     int_error(cur_val);
1545     cur_val = 0;
1546   }
1547 }
1548 /* sec 0434 */
1549 void scan_char_num (void)
1550 {
1551   scan_int();
1552
1553   if ((cur_val < 0) || (cur_val > 255))
1554   {
1555     print_err("Bad character code");
1556     help2("A character number must be between 0 and 255.",
1557         "I changed this one to zero.");
1558     int_error(cur_val);
1559     cur_val = 0;
1560   }
1561 }
1562 /* sec 0435 */
1563 void scan_four_bit_int (void)
1564 {
1565   scan_int();
1566
1567   if ((cur_val < 0) || (cur_val > 15))
1568   {
1569     print_err("Bad number");
1570     help2("Since I expected to read a number between 0 and 15,",
1571         "I changed this one to zero.");
1572     int_error(cur_val);
1573     cur_val = 0;
1574   }
1575 }
1576 /* sec 0436 */
1577 void scan_fifteen_bit_int (void) 
1578 {
1579   scan_int();
1580   if ((cur_val < 0) || (cur_val > 32767))
1581   {
1582     print_err("Bad mathchar");
1583     help2("A mathchar number must be between 0 and 32767.",
1584         "I changed this one to zero.");
1585     int_error(cur_val);
1586     cur_val = 0;
1587   }
1588 }
1589 /* sec 0437 */
1590 void scan_twenty_seven_bit_int (void)
1591 {
1592   scan_int();
1593
1594   if ((cur_val < 0) || (cur_val > 134217727L)) /* 2^27 - 1 */
1595   {
1596     print_err("Bad delimiter code");
1597     help2("A numeric delimiter code must be between 0 and 2^{27}-1.",
1598         "I changed this one to zero.");
1599     int_error(cur_val);
1600     cur_val = 0;
1601   }
1602 }
1603 /* sec 0577 */
1604 void scan_font_ident (void) 
1605 {
1606   internal_font_number f;
1607   halfword m;
1608
1609   do
1610     {
1611       get_x_token();
1612     }
1613   while (!(cur_cmd != spacer));
1614
1615   if (cur_cmd == def_font)
1616     f = cur_font;
1617   else if (cur_cmd == set_font)
1618     f = cur_chr; 
1619   else if (cur_cmd == def_family)
1620   {
1621     m = cur_chr;
1622     scan_four_bit_int();
1623     f = equiv(m + cur_val);
1624   }
1625   else
1626   {
1627     print_err("Missing font identifier");
1628     help2("I was looking for a control sequence whose",
1629         "current meaning has been defined by \\font.");
1630     back_error();
1631     f = null_font;
1632   }
1633
1634   cur_val = f;
1635 }
1636 /* sec 0578 */
1637 void find_font_dimen_(bool writing)
1638 {
1639   internal_font_number f;
1640   integer n;
1641
1642   scan_int();
1643   n = cur_val;
1644   scan_font_ident();
1645   f = cur_val;
1646
1647   if (n < 0 || (n == 0 && font_dimen_zero == 0)) /* change 98/Oct/5 */
1648     cur_val = fmem_ptr;
1649   else
1650   {
1651     if (writing && (n <= space_shrink_code) && (n >= space_code) && (font_glue[f] != 0)) 
1652     {
1653       delete_glue_ref(font_glue[f]);
1654       font_glue[f] = 0;
1655     }
1656
1657     if (n > font_params[f])
1658       if (f < font_ptr)
1659         cur_val = fmem_ptr;
1660     else
1661     {
1662       do
1663         {
1664  #ifdef ALLOCATEFONT
1665           if (fmem_ptr == current_font_mem_size) /* 93/Nov/28 ??? */
1666           {
1667             font_info = realloc_font_info(increment_font_mem_size);
1668           }
1669
1670           if (fmem_ptr == current_font_mem_size) /* 94/Jan/24 */
1671           {
1672             overflow("font memory", current_font_mem_size); /* font memory */
1673             return;     // abort_flag set
1674           }
1675 #else
1676           if (fmem_ptr == font_mem_size)
1677           {
1678             overflow("font memory", font_mem_size); /* font memory */
1679             return;     // abort_flag set
1680           }
1681 #endif
1682           font_info[fmem_ptr].cint = 0;
1683           incr(fmem_ptr);
1684           incr(font_params[f]);
1685         }
1686       while(!(n == font_params[f]));
1687
1688       cur_val = fmem_ptr - 1;
1689     }
1690   else if (n > 0)
1691     cur_val = n + param_base[f];    /* 98/Oct/5 */
1692   else
1693     cur_val = (&font_check[f] - &font_info[0]); /* 98/Oct/5 */
1694 /*  checksum =  (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
1695         font_check[f].b2) << 8 | font_check[f].b3; */
1696   }
1697 /* compiler error: '-' : incompatible types - from 'union fmemoryword *' to 'struct fourunsignedchars *' */
1698   if (cur_val == fmem_ptr)
1699   {
1700     print_err("Font ");
1701 /*    print_esc(hash[(hash_size + 524) + f].v.RH); */
1702     print_esc(""); print(font_id_text(f));
1703     print_string(" has only ");
1704     print_int(font_params[f]);
1705     print_string(" fontdimen parameters");
1706     help2("To increase the number of font parameters, you must",
1707       "use \\fontdimen immediately after the \\font is loaded.");
1708     error();
1709   }
1710 }
1711 /* NOTE: the above use of /fontdimen0 to access the checksum is a kludge */
1712 /* In future would be better to do this by allocating one more slot for */
1713 /* for parameters when a font is read rather than carry checksum separately */
1714 /* The above gets the value byte order reversed ... 98/Oct/5 */
1715 /* sec 0413 */
1716 void scan_something_internal_(small_number level, bool negative)
1717 {
1718   halfword m;
1719   integer p;
1720
1721   m = cur_chr;
1722
1723   switch (cur_cmd)
1724   {
1725     case def_code:
1726       {
1727         scan_char_num();
1728
1729         if (m == math_code_base)
1730         {
1731           cur_val = math_code(cur_val);
1732           cur_val_level = int_val;
1733         }
1734         else if (m < math_code_base)
1735         {
1736           cur_val = equiv(m + cur_val);
1737           cur_val_level = int_val;
1738         }
1739         else
1740         {
1741           cur_val = eqtb[m + cur_val].cint;
1742           cur_val_level = int_val;
1743         }
1744       }
1745       break;
1746
1747     case toks_register:
1748     case assign_toks:
1749     case def_family:
1750     case set_font:
1751     case def_font:
1752       if (level != tok_val)
1753       {
1754         print_err("Missing number, treated as zero");
1755         help3("A number should have been here; I inserted `0'.",
1756             "(If you can't figure out why I needed to see a number,",
1757             "look up `weird error' in the index to The TeXbook.)");
1758         back_error();
1759         {
1760           cur_val = 0;
1761           cur_val_level = dimen_val;
1762         }
1763       }
1764       else if (cur_cmd <= assign_toks)
1765       {
1766         if (cur_cmd < assign_toks)
1767         {
1768           scan_eight_bit_int();
1769           m = toks_base + cur_val;
1770         }
1771
1772         {
1773           cur_val = eqtb[m].hh.v.RH;
1774           cur_val_level = tok_val;
1775         }
1776       }
1777       else
1778       {
1779         back_input();
1780         scan_font_ident();
1781
1782         {
1783           cur_val = font_id_base + cur_val; /* 96/Jan/10 */
1784           cur_val_level = ident_val;
1785         }
1786       }
1787       break;
1788
1789     case assign_int:
1790       {
1791         cur_val = eqtb[m].cint;
1792         cur_val_level = int_val;
1793       }
1794       break;
1795
1796     case assign_dimen:
1797       {
1798         cur_val = eqtb[m].cint;
1799         cur_val_level = dimen_val;
1800       }
1801       break; 
1802
1803     case assign_glue:
1804       {
1805         cur_val = eqtb[m].hh.v.RH;
1806         cur_val_level = glue_val;
1807       }
1808       break;
1809
1810     case assign_mu_glue:
1811       {
1812         cur_val = eqtb[m].hh.v.RH;
1813         cur_val_level = mu_val;
1814       }
1815       break;
1816
1817     case set_aux:
1818       if (abs(mode)!= m)
1819       {
1820         print_err("Improper ");
1821         print_cmd_chr(set_aux, m);
1822         help4("You can refer to \\spacefactor only in horizontal mode;",
1823             "you can refer to \\prevdepth only in vertical mode; and",
1824             "neither of these is meaningful inside \\write. So",
1825             "I'm forgetting what you said and using zero instead.");
1826         error();
1827
1828         if (level != tok_val)
1829         {
1830           cur_val = 0;
1831           cur_val_level = dimen_val;
1832         }
1833         else
1834         {
1835           cur_val = 0;
1836           cur_val_level = int_val;
1837         }
1838       }
1839       else if (m == vmode)
1840       {
1841         cur_val = cur_list.aux_field.cint;
1842         cur_val_level = dimen_val;
1843       }
1844       else
1845       {
1846         cur_val = space_factor;
1847         cur_val_level = int_val;
1848       }
1849       break;
1850
1851     case set_prev_graf:
1852       if (mode == 0)
1853       {
1854         cur_val = 0;
1855         cur_val_level = int_val;
1856       }
1857       else
1858       {
1859         nest[nest_ptr] = cur_list;
1860         p = nest_ptr;
1861
1862         while (abs(nest[p].mode_field)!= vmode)
1863           decr(p);
1864
1865         {
1866           cur_val = nest[p].pg_field;
1867           cur_val_level = int_val;
1868         }
1869       }
1870       break;
1871
1872     case set_page_int:
1873       {
1874         if (m == 0)
1875           cur_val = dead_cycles; 
1876         else
1877           cur_val = insert_penalties;
1878
1879         cur_val_level = 0;
1880       }
1881       break;
1882
1883     case set_page_dimen:
1884       {
1885         if ((page_contents == 0) && (! output_active))
1886           if (m == 0)
1887             cur_val = 1073741823L;  /* 2^30 - 1 */
1888           else
1889             cur_val = 0;
1890         else
1891           cur_val = page_so_far[m];
1892
1893         cur_val_level = dimen_val;
1894       }
1895       break;
1896
1897     case set_shape:
1898       {
1899         if (par_shape_ptr == 0)
1900           cur_val = 0; 
1901         else
1902           cur_val = info(par_shape_ptr);
1903
1904         cur_val_level = int_val;
1905       }
1906       break;
1907
1908     case set_box_dimen:
1909       {
1910         scan_eight_bit_int();
1911
1912         if (box(cur_val) == 0)
1913           cur_val = 0;
1914         else
1915           cur_val = mem[box(cur_val) + m].cint;
1916
1917         cur_val_level = dimen_val;
1918       }
1919       break;
1920
1921     case char_given:
1922     case math_given:
1923       {
1924         cur_val = cur_chr;
1925         cur_val_level = int_val;
1926       }
1927       break;
1928
1929     case assign_font_dimen:
1930       {
1931         find_font_dimen(false);
1932         font_info[fmem_ptr].cint = 0;
1933         {
1934           cur_val = font_info[cur_val].cint;
1935           cur_val_level = dimen_val;
1936         }
1937       }
1938       break;
1939
1940     case assign_font_int:
1941       {
1942         scan_font_ident();
1943
1944         if (m == 0)
1945         {
1946           cur_val = hyphen_char[cur_val];
1947           cur_val_level = int_val;
1948         }
1949         else
1950         {
1951           cur_val = skew_char[cur_val];
1952           cur_val_level = int_val;
1953         }
1954       }
1955       break;
1956
1957     case tex_register:
1958       {
1959         scan_eight_bit_int();
1960
1961         switch(m)
1962         {
1963           case int_val:
1964             cur_val = count(cur_val);
1965             break;
1966
1967           case dimen_val:
1968             cur_val = dimen(cur_val);
1969             break;
1970
1971           case glue_val:
1972             cur_val = skip(cur_val);
1973             break;
1974
1975           case mu_val:
1976             cur_val = mu_skip(cur_val);
1977             break;
1978         }
1979         
1980         cur_val_level = m;
1981       }
1982       break;
1983
1984     case last_item:
1985       if (cur_chr > glue_val)
1986       {
1987         if (cur_chr == input_line_no_code)
1988           cur_val = line;
1989         else
1990           cur_val = last_badness;
1991
1992         cur_val_level = int_val;
1993       }
1994       else
1995       {
1996         if (cur_chr == glue_val)
1997           cur_val = zero_glue;
1998         else
1999           cur_val = 0;
2000
2001         cur_val_level = cur_chr;
2002
2003         if (!(tail >= hi_mem_min) && (mode != 0))
2004           switch(cur_chr)
2005           {
2006             case int_val:
2007               if (type(tail) == penalty_node)
2008                 cur_val = penalty(tail);
2009               break;
2010
2011             case dimen_val:
2012               if (type(tail) == kern_node)
2013                 cur_val = width(tail);
2014               break;
2015
2016             case glue_val:
2017               if (type(tail) == glue_node)
2018               {
2019                 cur_val = glue_ptr(tail);
2020
2021                 if (subtype(tail) == mu_glue)
2022                   cur_val_level = mu_val;
2023               }
2024               break;
2025           }
2026         else if ((mode == 1) && (tail == cur_list.head_field))
2027           switch (cur_chr)
2028           {
2029             case int_val:
2030               cur_val = last_penalty;
2031               break;
2032
2033             case dimen_val:
2034               cur_val = last_kern;
2035               break;
2036
2037             case glue_val:
2038               if (last_glue != empty_flag)
2039                 cur_val = last_glue;
2040               break;
2041           }
2042       }
2043       break;
2044
2045     default:
2046       {
2047         print_err("You can't use `");
2048         print_cmd_chr(cur_cmd, cur_chr);
2049         print_string("' after ");
2050         print_esc("the");
2051         help1("I'm forgetting what you said and using zero instead.");
2052         error();
2053
2054         if (level != tok_val)
2055         {
2056           cur_val = 0;
2057           cur_val_level = dimen_val;
2058         }
2059         else
2060         {
2061           cur_val = 0;
2062           cur_val_level = int_val;
2063         }
2064       }
2065       break;
2066   }
2067
2068   while (cur_val_level > level)
2069   {
2070     if (cur_val_level == glue_val)
2071       cur_val = width(cur_val);
2072     else if (cur_val_level == mu_val)
2073       mu_error();
2074
2075     decr(cur_val_level);
2076   }
2077
2078   if (negative)
2079     if (cur_val_level >= 2)
2080     {
2081       cur_val = new_spec(cur_val);
2082
2083       {
2084         width(cur_val) = - (integer) width(cur_val);
2085         stretch(cur_val) = - (integer) stretch(cur_val);
2086         shrink(cur_val) = - (integer) shrink(cur_val);
2087       }
2088     }
2089     else
2090       cur_val = - (integer) cur_val;
2091   else if ((cur_val_level >= glue_val) && (cur_val_level <= mu_val))
2092     add_glue_ref(cur_val);
2093 }
2094 /*****************************************************************************/
2095 /* Moved here to avoid question about pragma optimize 96/Sep/12 */
2096 /* sec 0341 */
2097 void get_next (void)
2098 {
2099   integer k;
2100   halfword t;
2101 /*  char cat; */    /* make this an int ? */
2102   int cat;      /* make this an int ? 95/Jan/7 */
2103   ASCII_code c, cc;
2104   char d;
2105
2106 lab20:
2107   cur_cs = 0;
2108
2109   if (cur_input.state_field != token_list)
2110   {
2111 lab25:
2112     if (cur_input.loc_field <= cur_input.limit_field)
2113     {
2114       cur_chr = buffer[cur_input.loc_field];
2115       incr(cur_input.loc_field);
2116 lab21:
2117       cur_cmd = cat_code(cur_chr);
2118
2119       switch (cur_input.state_field + cur_cmd)
2120       {
2121         case any_state_plus(ignore):
2122         case skip_blanks + spacer:
2123         case new_line + spacer:
2124           goto lab25;
2125           break;
2126
2127         case any_state_plus(escape):
2128           {
2129             if (cur_input.loc_field > cur_input.limit_field)
2130               cur_cs = null_cs;
2131             else
2132             {
2133 lab26:
2134               k = cur_input.loc_field;
2135               cur_chr = buffer[k];
2136               cat = cat_code(cur_chr);
2137               incr(k);
2138
2139               if (cat == letter)
2140                 cur_input.state_field = skip_blanks;
2141               else if (cat == spacer)
2142                 cur_input.state_field = skip_blanks;
2143               else
2144                 cur_input.state_field = mid_line;
2145
2146               if ((cat == letter) && (k <= cur_input.limit_field))
2147               {
2148                 do
2149                   {
2150                     cur_chr = buffer[k];
2151                     cat = cat_code(cur_chr);
2152                     incr(k);
2153                   }
2154                 while(!((cat != letter) || (k > cur_input.limit_field)));
2155
2156                 {
2157                   if (buffer[k]== cur_chr)
2158                     if (cat == sup_mark)
2159                       if (k < cur_input.limit_field)
2160                       {
2161                         c = buffer[k + 1];
2162
2163                         if (c < 128)
2164                         {
2165                           d = 2;
2166                           if ((((c >= 48) && (c <= 57)) || ((c >= 97) && (c <= 102))))
2167                             if (k + 2 <= cur_input.limit_field)
2168                             {
2169                               cc = buffer[k + 2];
2170
2171                               if ((((cc >= 48) && (cc <= 57)) || ((cc >= 97) && (cc <= 102))))
2172                                 incr(d);
2173                             }
2174
2175                           if (d > 2)
2176                           {
2177                             if (c <= 57)
2178                               cur_chr = c - 48;
2179                             else
2180                               cur_chr = c - 87;
2181
2182                             if (cc <= 57)
2183                               cur_chr = 16 * cur_chr + cc - 48;
2184                             else
2185                               cur_chr = 16 * cur_chr + cc - 87;
2186
2187                             buffer[k - 1] = cur_chr;
2188                           }
2189                           else if (c < 64)
2190                             buffer[k - 1] = c + 64;
2191                           else
2192                             buffer[k - 1] = c - 64;
2193
2194                           cur_input.limit_field = cur_input.limit_field - d;
2195                           first = first - d;
2196
2197                           while (k <= cur_input.limit_field)
2198                           {
2199                             buffer[k] = buffer[k + d];
2200                             incr(k);
2201                           }
2202
2203                           goto lab26;
2204                         }
2205                       }
2206                 }
2207
2208                 if (cat != letter)
2209                   decr(k);
2210
2211                 if (k > cur_input.loc_field + 1)
2212                 {
2213                   cur_cs = id_lookup(cur_input.loc_field, k - cur_input.loc_field);
2214                   cur_input.loc_field = k;
2215                   goto lab40;
2216                 }
2217               }
2218               else
2219               {
2220                 if (buffer[k] == cur_chr)
2221                   if (cat == sup_mark)
2222                     if (k < cur_input.limit_field)
2223                     {
2224                       c = buffer[k + 1];
2225
2226                       if (c < 128)             /* ? */
2227                       {
2228                         d = 2;
2229                         if ((((c >= 48) && (c <= 57)) || ((c >= 97) && (c <= 102))))
2230                           if (k + 2 <= cur_input.limit_field)
2231                           {
2232                             cc = buffer[k + 2];
2233
2234                             if ((((cc >= 48) && (cc <= 57)) || ((cc >= 97) && (cc <= 102))))
2235                               incr(d);
2236                           }
2237
2238                         if (d > 2)
2239                         {
2240                           if (c <= 57)
2241                             cur_chr = c - 48;
2242                           else
2243                             cur_chr = c - 87;
2244
2245                           if (cc <= 57)          /* cc may be used without ... */
2246                             cur_chr = 16 * cur_chr + cc - 48;
2247                           else
2248                             cur_chr = 16 * cur_chr + cc - 87;
2249
2250                           buffer[k - 1] = cur_chr;
2251                         }
2252                         else if (c < 64)
2253                           buffer[k - 1] = c + 64;
2254                         else
2255                           buffer[k - 1] = c - 64;
2256
2257                         cur_input.limit_field = cur_input.limit_field - d;
2258                         first = first - d;
2259
2260                         while (k <= cur_input.limit_field)
2261                         {
2262                           buffer[k] = buffer[k + d];
2263                           incr(k);
2264                         }
2265                         goto lab26;
2266                       }
2267                     }
2268               }
2269               cur_cs = single_base + buffer[cur_input.loc_field];
2270               incr(cur_input.loc_field);
2271             }
2272 lab40:
2273             cur_cmd = eq_type(cur_cs);
2274             cur_chr = equiv(cur_cs);
2275             
2276             if (cur_cmd >= outer_call)
2277               check_outer_validity();
2278           }
2279           break;
2280
2281         case any_state_plus(active_char):
2282           {
2283             cur_cs = cur_chr + active_base;
2284             cur_cmd = eq_type(cur_cs);
2285             cur_chr = equiv(cur_cs);
2286             cur_input.state_field = mid_line;
2287             
2288             if (cur_cmd >= outer_call)
2289               check_outer_validity();
2290           }
2291           break;
2292
2293         case any_state_plus(sup_mark):
2294           {
2295             if (cur_chr == buffer[cur_input.loc_field])
2296               if (cur_input.loc_field < cur_input.limit_field)
2297               {
2298                 c = buffer[cur_input.loc_field + 1];
2299
2300                 if (c < 128)
2301                 {
2302                   cur_input.loc_field = cur_input.loc_field + 2;
2303
2304                   if ((((c >= 48) && (c <= 57)) || ((c >= 97) && (c <= 102))))
2305                     if (cur_input.loc_field <= cur_input.limit_field)
2306                     {
2307                       cc = buffer[cur_input.loc_field];
2308
2309                       if ((((cc >= 48) && (cc <= 57)) || ((cc >= 97) && (cc <= 102))))
2310                       {
2311                         incr(cur_input.loc_field);
2312
2313                         if (c <= 57)
2314                           cur_chr = c - 48;
2315                         else
2316                           cur_chr = c - 87;
2317
2318                         if (cc <= 57)
2319                           cur_chr = 16 * cur_chr + cc - 48;
2320                         else
2321                           cur_chr = 16 * cur_chr + cc - 87;
2322
2323                         goto lab21;
2324                       }
2325                     }
2326
2327                   if (c < 64)
2328                     cur_chr = c + 64;
2329                   else
2330                     cur_chr = c - 64;
2331
2332                   goto lab21;
2333                 }
2334               }
2335
2336               cur_input.state_field = mid_line;
2337           }
2338           break;
2339
2340         case any_state_plus(invalid_char):
2341           {
2342             print_err("Text line contains an invalid character");
2343             help2("A funny symbol that I can't read has just been input.",
2344                 "Continue, and I'll forget that it ever happened.");
2345             deletions_allowed = false;
2346             error();
2347             deletions_allowed = true;
2348             goto lab20;
2349           }
2350           break;
2351
2352         case mid_line + spacer:
2353           {
2354             cur_input.state_field = skip_blanks;
2355             cur_chr = ' ';
2356           }
2357           break;
2358
2359         case mid_line + car_ret:
2360           {
2361             cur_input.loc_field = cur_input.limit_field + 1;
2362             cur_cmd = spacer;
2363             cur_chr = ' ';
2364           }
2365           break;
2366
2367         case skip_blanks + car_ret:
2368         case any_state_plus(comment):
2369           {
2370             cur_input.loc_field = cur_input.limit_field + 1;
2371             goto lab25;
2372           }
2373           break;
2374
2375         case new_line + car_ret:
2376           {
2377             cur_input.loc_field = cur_input.limit_field + 1;
2378             cur_cs = par_loc;
2379             cur_cmd = eq_type(cur_cs);
2380             cur_chr = equiv(cur_cs);
2381             
2382             if (cur_cmd >= outer_call)
2383               check_outer_validity();
2384           }
2385           break;
2386
2387         case mid_line + left_brace:
2388           incr(align_state);
2389           break;
2390
2391         case skip_blanks + left_brace:
2392         case new_line + left_brace:
2393           {
2394             cur_input.state_field = mid_line;
2395             incr(align_state);
2396           }
2397           break;
2398
2399         case mid_line + right_brace:
2400           decr(align_state);
2401           break;
2402
2403         case skip_blanks + right_brace:
2404         case new_line + right_brace:
2405           {
2406             cur_input.state_field = 1;
2407             decr(align_state);
2408           }
2409           break;
2410
2411         case add_delims_to(skip_blanks):
2412         case add_delims_to(new_line):
2413           cur_input.state_field = 1;
2414           break;
2415
2416         default:
2417           break;
2418       }
2419     }
2420     else
2421     {
2422       cur_input.state_field = new_line;
2423
2424       if (cur_input.name_field > 17)
2425       {
2426         incr(line);
2427         first = cur_input.start_field;
2428
2429         if (!force_eof)
2430         {
2431           if (input_ln(input_file[cur_input.index_field], true))
2432             firm_up_the_line();
2433           else
2434             force_eof = true;
2435         }
2436
2437         if (force_eof)
2438         {
2439           print_char(')');
2440           decr(open_parens);
2441 #ifndef _WINDOWS
2442           fflush(stdout);
2443 #endif
2444           force_eof = false;
2445           end_file_reading();
2446           check_outer_validity();
2447           goto lab20;
2448         }
2449
2450         if ((end_line_char < 0) || (end_line_char > 255))
2451           decr(cur_input.limit_field);
2452         else
2453           buffer[cur_input.limit_field] = end_line_char;
2454
2455         first = cur_input.limit_field + 1;
2456         cur_input.loc_field = cur_input.start_field;
2457       }
2458       else
2459       {
2460         if (!(cur_input.name_field == 0))
2461         {
2462           cur_cmd = 0;
2463           cur_chr = 0;
2464           return;
2465         }
2466
2467         if (input_ptr > 0)
2468         {
2469           end_file_reading();
2470           goto lab20;
2471         }
2472
2473         if (selector < log_only)
2474           open_log_file();
2475
2476         if (interaction > nonstop_mode)
2477         {
2478           if ((end_line_char < 0) || (end_line_char > 255))
2479             incr(cur_input.limit_field);
2480
2481           if (cur_input.limit_field == cur_input.start_field)
2482             print_nl("(Please type a command or say `\\end')");
2483
2484           print_ln();
2485           first = cur_input.start_field;
2486
2487           {
2488             ;
2489             print_string("*");
2490             term_input("*", 0);
2491           }
2492
2493           cur_input.limit_field = last;
2494
2495           if ((end_line_char < 0) || (end_line_char > 255))
2496             decr(cur_input.limit_field);
2497           else
2498             buffer[cur_input.limit_field]= end_line_char;
2499
2500           first = cur_input.limit_field + 1;
2501           cur_input.loc_field = cur_input.start_field;
2502         }
2503         else
2504         {
2505           fatal_error("*** (job aborted, no legal \\end found)");
2506           return;     // abort_flag set
2507         }
2508       }
2509
2510       {
2511         if (interrupt != 0)
2512         {
2513           pause_for_instructions();
2514         }
2515       }
2516
2517       goto lab25;
2518     }
2519   }
2520   else if (cur_input.loc_field != 0)
2521   {
2522     t = info(cur_input.loc_field);
2523     cur_input.loc_field = link(cur_input.loc_field);
2524
2525     if (t >= cs_token_flag)
2526     {
2527       cur_cs = t - cs_token_flag;
2528       cur_cmd = eq_type(cur_cs);
2529       cur_chr = equiv(cur_cs);
2530
2531       if (cur_cmd >= outer_call)
2532         if (cur_cmd == dont_expand)
2533         {
2534           cur_cs = info(cur_input.loc_field) - cs_token_flag;
2535           cur_input.loc_field = 0;
2536           cur_cmd = eq_type(cur_cs);
2537           cur_chr = equiv(cur_cs);
2538
2539           if (cur_cmd > max_command)
2540           {
2541             cur_cmd = relax;
2542             cur_chr = no_expand_flag;
2543           }
2544         }
2545         else
2546         {
2547           check_outer_validity();
2548         }
2549     }
2550     else
2551     {
2552       cur_cmd = t / 256;
2553       cur_chr = t % 256;
2554
2555       switch (cur_cmd)
2556       {
2557         case left_brace:
2558           incr(align_state);
2559           break;
2560
2561         case right_brace:
2562           decr(align_state);
2563           break;
2564
2565         case out_param:
2566           {
2567             begin_token_list(param_stack[cur_input.limit_field + cur_chr - 1], parameter);
2568             goto lab20;
2569           }
2570           break;
2571
2572         default:
2573           break;
2574       }
2575     }
2576   }
2577   else
2578   {
2579     end_token_list();
2580     goto lab20;
2581   }
2582
2583   if (cur_cmd <= car_ret)
2584     if (cur_cmd >= tab_mark)
2585       if (align_state == 0)
2586       {
2587         if ((scanner_status == aligning) && (cur_align == 0))
2588         {
2589           fatal_error("(interwoven alignment preambles are not allowed)");
2590           return;     // abort_flag set
2591         }
2592
2593         cur_cmd = extra_info(cur_align);
2594         extra_info(cur_align) = cur_chr;
2595
2596         if (cur_cmd == omit)
2597           begin_token_list(omit_template, v_template);
2598         else
2599           begin_token_list(v_part(cur_align), v_template);
2600
2601         align_state = 1000000L;
2602         goto lab20;
2603       }
2604 }
2605 #pragma optimize ("", on)             /* 96/Sep/12 */