OSDN Git Service

store_new_token, fast_get_avail and fast_store_new_token.
[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 #ifdef STAT
24 /* sec 0284 */
25 void restore_trace_(halfword p, char * s)
26 {
27   begin_diagnostic();
28   print_char('{');
29   print_string(s);
30   print_char(' ');
31   show_eqtb(p);
32   print_char('}');
33   end_diagnostic(false);
34 }
35 #endif
36 /* sec 0281 */
37 void unsave (void)
38 {
39   halfword p;
40   quarterword l;
41   halfword t;
42
43   if (cur_level > level_one)
44   {
45     decr(cur_level);
46     while (true) {
47       decr(save_ptr);
48
49       if (save_type(save_ptr) == level_boundary)
50         goto lab30;
51
52       p = save_index(save_ptr);
53
54       if (save_type(save_ptr) == insert_token)
55       {
56         t = cur_tok;
57         cur_tok = p;
58         back_input();
59         cur_tok = t;
60       }
61       else
62       {
63         if (save_type(save_ptr) == restore_old_value)
64         {
65           l = save_level(save_ptr);
66           decr(save_ptr);
67         }
68         else
69           save_stack[save_ptr] = eqtb[undefined_control_sequence];
70         
71         if (p < int_base)
72           if (eq_level(p) == level_one)
73           {
74             eq_destroy(save_stack[save_ptr]);
75 #ifdef STAT
76             if (tracing_restores > 0)
77               restore_trace(p, "retaining");
78 #endif /* STAT */
79           }
80           else
81           {
82             eq_destroy(eqtb[p]);
83             eqtb[p] = save_stack[save_ptr];
84 #ifdef STAT
85             if (tracing_restores > 0)
86               restore_trace(p, "restoring");
87 #endif /* STAT */
88           }
89         else if (xeq_level[p] != level_one)
90         {
91           eqtb[p] = save_stack[save_ptr];
92           xeq_level[p] = l;
93 #ifdef STAT
94           if (tracing_restores > 0)
95             restore_trace(p, "restoring");
96 #endif /* STAT */
97         }
98         else
99         {
100 #ifdef STAT
101           if (tracing_restores > 0)
102             restore_trace(p, "retaining");
103 #endif /* STAT */
104         }
105       }
106     }
107 lab30:
108     cur_group = save_level(save_ptr);
109     cur_boundary = save_index(save_ptr);
110   }
111   else
112   {
113     confusion("curlevel");
114     return;       // abort_flag set
115   }
116 }
117 /* This is where the old tex2.c used to start */
118 /* sec 0288 */
119 void prepare_mag (void) 
120 {
121   if ((mag_set > 0) && (mag != mag_set))
122   {
123     print_err("Incompatible magnification (");
124     print_int(mag);
125     print_string(");");
126     print_nl(" the previous value will be retained");
127     help2("I can handle only one magnification ratio per job. So I've",
128         "reverted to the magnification you used earlier on this run.");
129     int_error(mag_set);
130     geq_word_define(int_base + mag_code, mag_set);
131   }
132
133   if ((mag <= 0) || (mag > 32768L))
134   {
135     print_err("Illegal magnification has been changed to 1000");
136     help1("The magnification ratio must be between 1 and 32768.");
137     int_error(mag);
138     geq_word_define(int_base + mag_code, 1000);
139   }
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                 store_new_token(info(t));
939                 incr(m);
940                 u = link(t);
941                 v = s;
942
943                 while (true)
944                 {
945                   if (u == r)
946                     if (cur_tok != info(v))
947                       goto lab30;
948                     else
949                     {
950                       r = link(v);
951                       goto lab22;
952                     }
953
954                     if (info(u) != info(v))
955                       goto lab30;
956
957                     u = link(u);
958                     v = link(v);
959                 }
960 lab30:
961                 t = link(t);
962               }
963             while(!(t == r));
964
965             r = s;
966           }
967
968         if (cur_tok == par_token)
969           if (long_state != long_call)
970           {
971             if (long_state == call)
972             {
973               runaway();
974               print_err("Paragraph ended before ");
975               sprint_cs(warning_index);
976               print_string("was complete");
977               help3("I suspect you've forgotten a `}', causing me to apply this",
978                   "control sequence to too much text. How can we recover?",
979                   "My plan is to forget the whole thing and hope for the best.");
980               back_error();
981             }
982
983             pstack[n] = link(temp_head);
984             align_state = align_state - unbalance;
985
986             for (m = 0; m <= n; m++)
987               flush_list(pstack[m]);
988
989             goto lab10;
990           }
991
992         if (cur_tok < right_brace_limit)
993           if (cur_tok < left_brace_limit)
994           {
995             unbalance = 1;
996
997             while (true)
998             {
999               fast_store_new_token(cur_tok);
1000               get_token();
1001
1002               if (cur_tok == par_token)
1003                 if (long_state != long_call)
1004                 {
1005                   if (long_state == call)
1006                   {
1007                     runaway();
1008                     print_err("Paragraph ended before ");
1009                     sprint_cs(warning_index);
1010                     print_string(" was complete");
1011                     help3("I suspect you've forgotten a `}', causing me to apply this",
1012                         "control sequence to too much text. How can we recover?",
1013                         "My plan is to forget the whole thing and hope for the best.");
1014                     back_error();
1015                   }
1016
1017                   pstack[n] = link(temp_head);
1018                   align_state = align_state - unbalance;
1019
1020                   for (m = 0; m <= n; m++)
1021                     flush_list(pstack[m]);
1022                   goto lab10;
1023                 }
1024
1025               if (cur_tok < right_brace_limit)
1026                 if (cur_tok < left_brace_limit)
1027                   incr(unbalance);
1028                 else
1029                 {
1030                   decr(unbalance);
1031
1032                   if (unbalance == 0)
1033                     goto lab31;
1034                 }
1035             }
1036 lab31:
1037             rbraceptr = p;
1038             store_new_token(cur_tok);
1039           }
1040           else
1041           {
1042             back_input();
1043             print_err("Argument of ");
1044             sprint_cs(warning_index);
1045             print_string(" has an extra }");
1046             help6("I've run across a `}' that doesn't seem to match anything.",
1047                 "For example, `\\def\\a#1{...}' and `\\a}' would produce",
1048                 "this error. If you simply proceed now, the `\\par' that",
1049                 "I've just inserted will cause me to report a runaway",
1050                 "argument that might be the root of the problem. But if",
1051                 "your `}' was spurious, just type `2' and it will go away.");
1052             incr(align_state);
1053             long_state = call;
1054             cur_tok = par_token;
1055             ins_error();
1056             goto lab22;
1057           }
1058         else
1059         {
1060           if (cur_tok == space_token)
1061             if (info(r) <= end_match_token)
1062               if (info(r) >= match_token)
1063                 goto lab22;
1064
1065           store_new_token(cur_tok);
1066         }
1067
1068         incr(m);          /* m may be used without having been ... */
1069
1070         if (info(r) > end_match_token)
1071           goto lab22;
1072
1073         if (info(r) < match_token)
1074           goto lab22;
1075 lab40:
1076         if (s != 0)
1077         {
1078           if ((m == 1) && (info(p) < right_brace_limit) && (p != temp_head))
1079           {
1080             link(rbraceptr) = 0; /* rbraceptr may be used without ... */
1081             free_avail(p);
1082             p = link(temp_head);
1083             pstack[n] = link(p);
1084             free_avail(p);
1085           }
1086           else
1087             pstack[n] = link(temp_head);
1088
1089           incr(n);
1090
1091           if (tracing_macros > 0)
1092           {
1093             begin_diagnostic();
1094             //print_nl(match_chr); /* matchchar may be used without ... */
1095             print_nl(""); print(match_chr);
1096             print_int(n);
1097             print_string("<-");
1098             show_token_list(pstack[n - 1], 0, 1000);
1099             end_diagnostic(false);
1100           }
1101         }
1102       }
1103     while(!(info(r) == end_match_token));
1104   }
1105
1106   while((cur_input.state_field == token_list) && (cur_input.loc_field == 0) &&
1107       (cur_input.index_field != v_template))
1108     end_token_list();
1109
1110   begin_token_list(refcount, macro);
1111   cur_input.name_field = warning_index;
1112   cur_input.loc_field = link(r);
1113
1114   if (n > 0)
1115   {
1116     if (param_ptr + n > max_param_stack)
1117     {
1118       max_param_stack = param_ptr + n;
1119
1120 #ifdef ALLOCATEPARAMSTACK
1121       if (max_param_stack > current_param_size)
1122         param_stack = realloc_param_stack(increment_param_size);
1123
1124       if (max_param_stack > current_param_size) /* check again after allocation */
1125       {
1126         overflow("parameter stack size", current_param_size);
1127         return;     // abort_flag set
1128       }
1129 #else
1130       if (max_param_stack > param_size)
1131       {
1132         overflow("parameter stack size", param_size); /* parameter stack - not dynamic */
1133         return;     // abort_flag set
1134       }
1135 #endif
1136     }
1137
1138     for (m = 0; m <= n - 1; m++)
1139       param_stack[param_ptr + m] = pstack[m];
1140
1141     param_ptr = param_ptr + n;
1142   }
1143 lab10:
1144   scanner_status = savescannerstatus;
1145   warning_index = savewarningindex;
1146 }
1147 /* sec 0379 */
1148 void insert_relax (void)
1149 {
1150   cur_tok = cs_token_flag + cur_cs;
1151   back_input();
1152   cur_tok = cs_token_flag + frozen_relax;  /* 96/Jan/10 */
1153   back_input();
1154   cur_input.index_field = inserted;
1155 }
1156 /* sec 0366 */
1157 void expand (void)
1158 {
1159   halfword t;
1160   halfword p, q, r;
1161   integer j;
1162   integer cvbackup;
1163   small_number cvlbackup, radixbackup, cobackup;
1164   halfword backupbackup;
1165   small_number savescannerstatus;
1166
1167   cvbackup = cur_val;
1168   cvlbackup = cur_val_level;
1169   radixbackup = radix;
1170   cobackup = cur_order;
1171   backupbackup = link(backup_head);
1172
1173   if (cur_cmd < call)
1174   {
1175     if (tracing_commands > 1)
1176       show_cur_cmd_chr();
1177
1178     switch (cur_cmd)
1179     {
1180       case top_bot_mark:
1181         if (cur_mark[cur_chr] != 0)
1182           begin_token_list(cur_mark[cur_chr], mark_text);
1183         break;
1184
1185       case expand_after:
1186         get_token();
1187         t = cur_tok;
1188         get_token();
1189
1190         if (cur_cmd > max_command)
1191           expand();
1192         else
1193           back_input();
1194
1195         cur_tok = t;
1196         back_input();
1197         break;
1198
1199       case no_expand:
1200         savescannerstatus = scanner_status;
1201         scanner_status = normal;
1202         get_token();
1203         scanner_status = savescannerstatus;
1204         t = cur_tok;
1205         back_input();
1206
1207         if (t >= cs_token_flag)
1208         {
1209           p = get_avail();
1210           info(p) = cs_token_flag + frozen_dont_expand; /*96/Jan/10*/
1211           link(p) = cur_input.loc_field;
1212           cur_input.start_field = p;
1213           cur_input.loc_field = p;
1214         }
1215         break;
1216
1217       case cs_name:
1218         r = get_avail();
1219         p = r;
1220         do
1221           {
1222             get_x_token();
1223   
1224             if (cur_cs == 0)
1225               store_new_token(cur_tok);
1226           }
1227         while(!(cur_cs != 0));
1228
1229         if (cur_cmd != end_cs_name)
1230         {
1231           print_err("Missing ");
1232           print_esc("endcsname");
1233           print_string(" inserted");
1234           help2("The control sequence marked <to be read again> should",
1235               "not appear between \\csname and \\endcsname.");
1236           back_error();
1237         }
1238
1239         j = first;
1240         p = link(r);
1241
1242         while (p != 0)
1243         {
1244           if (j >= max_buf_stack)
1245           {
1246             max_buf_stack = j + 1;
1247
1248 #ifdef ALLOCATEBUFFER
1249             if (max_buf_stack == current_buf_size)
1250               buffer = realloc_buffer (increment_buf_size);
1251
1252             if (max_buf_stack == current_buf_size) /* check again after allocation */
1253             {
1254               overflow("buffer size", current_buf_size);
1255               return;     // abort_flag set
1256             }
1257 #else
1258             if (max_buf_stack == buf_size)
1259             {
1260               overflow("buffer size", buf_size); /* buffer size - not dynamic */
1261               return;     // abort_flag set
1262             }
1263 #endif
1264           }
1265
1266           buffer[j] = info(p) % 256;
1267           incr(j);
1268           p = link(p);
1269         }
1270
1271         if (j > first + 1)
1272         {
1273           no_new_control_sequence = false;
1274           cur_cs = id_lookup(first, j - first);
1275           no_new_control_sequence = true;
1276         }
1277         else if (j == first)
1278           cur_cs = null_cs;
1279         else
1280           cur_cs = single_base + buffer[first];
1281
1282         flush_list(r);
1283
1284         if (eq_type(cur_cs) == undefined_cs)
1285         {
1286           eq_define(cur_cs, relax, 256);
1287         }
1288
1289         cur_tok = cur_cs + cs_token_flag;
1290         back_input();
1291         break;
1292
1293       case convert:
1294         conv_toks();
1295         break;
1296
1297       case the:
1298         ins_the_toks();
1299         break;
1300
1301       case if_test:
1302         conditional();
1303         break;
1304
1305       case fi_or_else:
1306         if (cur_chr > if_limit)
1307           if (if_limit == 1)
1308             insert_relax();
1309           else
1310           {
1311             print_err("Extra ");
1312             print_cmd_chr(fi_or_else, cur_chr);
1313             help1("I'm ignoring this; it doesn't match any \\if.");
1314             error();
1315           }
1316         else
1317         {
1318           while(cur_chr != fi_code)
1319             pass_text();
1320
1321           {
1322             p = cond_ptr;
1323             if_line = if_line_field(p);
1324             cur_if = subtype(p);
1325             if_limit = type(p);
1326             cond_ptr = link(p);
1327             free_node(p, if_node_size);
1328           }
1329         }
1330         break;
1331
1332       case input:
1333         if (cur_chr > 0)
1334           force_eof = true;
1335         else if (name_in_progress)
1336           insert_relax();
1337         else
1338           start_input();
1339         break;
1340
1341       default:
1342         print_err("Undefined control sequence");
1343         help5("The control sequence at the end of the top line",
1344             "of your error message was never \\def'ed. If you have",
1345             "misspelled it (e.g., `\\hobx'), type `I' and the correct",
1346             "spelling (e.g., `I\\hbox'). Otherwise just continue,",
1347             "and I'll forget about whatever was undefined.");
1348         error();
1349         break;
1350     }
1351   }
1352   else if (cur_cmd < end_template)
1353   {
1354     macro_call();
1355   }
1356   else
1357   {
1358     cur_tok = cs_token_flag + frozen_endv; /* 96/Jan/10 */
1359     back_input();
1360   }
1361
1362   cur_val = cvbackup;
1363   cur_val_level = cvlbackup;
1364   radix = radixbackup;
1365   cur_order = cobackup;
1366   link(backup_head) = backupbackup;
1367 }
1368 /* sec 0380 */
1369 void get_x_token (void)
1370 {
1371 lab20:
1372   get_next();
1373
1374   if (cur_cmd <= max_command)
1375     goto lab30;
1376   if (cur_cmd >= call)
1377     if (cur_cmd < end_template)
1378       macro_call();
1379     else
1380     {
1381       cur_cs = frozen_endv;  /* 96/Jan/10 */
1382       cur_cmd = endv;
1383       goto lab30;
1384     }
1385   else
1386     expand();
1387
1388   goto lab20;
1389 lab30:
1390   if (cur_cs == 0)
1391     cur_tok = (cur_cmd * 256) + cur_chr;
1392   else
1393     cur_tok = cs_token_flag + cur_cs;
1394 }
1395 /* sec 0381 */
1396 void x_token (void)
1397 {
1398   while (cur_cmd > max_command)
1399   {
1400     expand();
1401     get_next();
1402   }
1403
1404   if (cur_cs == 0)
1405     cur_tok = (cur_cmd * 256) + cur_chr;
1406   else
1407     cur_tok = cs_token_flag + cur_cs;
1408 }
1409 /* sec 0403 */
1410 void scan_left_brace (void)
1411 {
1412   do
1413     {
1414       get_x_token();
1415     }
1416   while(!((cur_cmd != spacer) && (cur_cmd != relax)));
1417
1418   if (cur_cmd != left_brace)
1419   {
1420     print_err("Missing { inserted");
1421     help4("A left brace was mandatory here, so I've put one in.",
1422         "You might want to delete and/or insert some corrections",
1423         "so that I will find a matching right brace soon.",
1424         "(If you're confused by all this, try typing `I}' now.)");
1425     back_error();
1426     cur_tok = left_brace_token + '{';
1427     cur_cmd = left_brace;
1428     cur_chr = '{';
1429     incr(align_state);
1430   }
1431 }
1432 /* sec 0405 */
1433 void scan_optional_equals (void)
1434 {
1435   do
1436     {
1437       get_x_token();
1438     }
1439   while(!(cur_cmd != spacer));
1440
1441   if (cur_tok != other_token + '=')
1442     back_input();
1443 }
1444 /* sec 0407 */
1445 bool scan_keyword_(char * s)
1446 {
1447   halfword p;
1448   halfword q;
1449   char * k;
1450
1451   p = backup_head;
1452   link(p) = 0;
1453   k = s;
1454
1455   while (*k)
1456   {
1457     get_x_token(); 
1458
1459     if ((cur_cs == 0) && ((cur_chr == (*k)) || (cur_chr == (*k) - 'a' + 'A')))
1460     {
1461       store_new_token(cur_tok);
1462       incr(k);
1463     }
1464     else if ((cur_cmd != spacer) || (p != backup_head))
1465     {
1466       back_input();
1467
1468       if (p != backup_head)
1469         back_list(link(backup_head));
1470
1471       return false;
1472     }
1473   }
1474
1475   flush_list(link(backup_head));
1476
1477   return true;
1478 }
1479 /* sec 0408 */
1480 void mu_error (void)
1481 {
1482   print_err("Incompatible glue units");
1483   help1("I'm going to assume that 1mu=1pt when they're mixed.");
1484   error();
1485 }
1486 /* sec 0433 */
1487 void scan_eight_bit_int (void)
1488 {
1489   scan_int();
1490
1491   if ((cur_val < 0) || (cur_val > 255))
1492   {
1493     print_err("Bad register code");
1494     help2("A register number must be between 0 and 255.",
1495         "I changed this one to zero.");
1496     int_error(cur_val);
1497     cur_val = 0;
1498   }
1499 }
1500 /* sec 0434 */
1501 void scan_char_num (void)
1502 {
1503   scan_int();
1504
1505   if ((cur_val < 0) || (cur_val > 255))
1506   {
1507     print_err("Bad character code");
1508     help2("A character number must be between 0 and 255.",
1509         "I changed this one to zero.");
1510     int_error(cur_val);
1511     cur_val = 0;
1512   }
1513 }
1514 /* sec 0435 */
1515 void scan_four_bit_int (void)
1516 {
1517   scan_int();
1518
1519   if ((cur_val < 0) || (cur_val > 15))
1520   {
1521     print_err("Bad number");
1522     help2("Since I expected to read a number between 0 and 15,",
1523         "I changed this one to zero.");
1524     int_error(cur_val);
1525     cur_val = 0;
1526   }
1527 }
1528 /* sec 0436 */
1529 void scan_fifteen_bit_int (void) 
1530 {
1531   scan_int();
1532   if ((cur_val < 0) || (cur_val > 32767))
1533   {
1534     print_err("Bad mathchar");
1535     help2("A mathchar number must be between 0 and 32767.",
1536         "I changed this one to zero.");
1537     int_error(cur_val);
1538     cur_val = 0;
1539   }
1540 }
1541 /* sec 0437 */
1542 void scan_twenty_seven_bit_int (void)
1543 {
1544   scan_int();
1545
1546   if ((cur_val < 0) || (cur_val > 134217727L)) /* 2^27 - 1 */
1547   {
1548     print_err("Bad delimiter code");
1549     help2("A numeric delimiter code must be between 0 and 2^{27}-1.",
1550         "I changed this one to zero.");
1551     int_error(cur_val);
1552     cur_val = 0;
1553   }
1554 }
1555 /* sec 0577 */
1556 void scan_font_ident (void) 
1557 {
1558   internal_font_number f;
1559   halfword m;
1560
1561   do
1562     {
1563       get_x_token();
1564     }
1565   while (!(cur_cmd != spacer));
1566
1567   if (cur_cmd == def_font)
1568     f = cur_font;
1569   else if (cur_cmd == set_font)
1570     f = cur_chr; 
1571   else if (cur_cmd == def_family)
1572   {
1573     m = cur_chr;
1574     scan_four_bit_int();
1575     f = equiv(m + cur_val);
1576   }
1577   else
1578   {
1579     print_err("Missing font identifier");
1580     help2("I was looking for a control sequence whose",
1581         "current meaning has been defined by \\font.");
1582     back_error();
1583     f = null_font;
1584   }
1585
1586   cur_val = f;
1587 }
1588 /* sec 0578 */
1589 void find_font_dimen_(bool writing)
1590 {
1591   internal_font_number f;
1592   integer n;
1593
1594   scan_int();
1595   n = cur_val;
1596   scan_font_ident();
1597   f = cur_val;
1598
1599   if (n < 0 || (n == 0 && font_dimen_zero == 0)) /* change 98/Oct/5 */
1600     cur_val = fmem_ptr;
1601   else
1602   {
1603     if (writing && (n <= space_shrink_code) && (n >= space_code) && (font_glue[f] != 0)) 
1604     {
1605       delete_glue_ref(font_glue[f]);
1606       font_glue[f] = 0;
1607     }
1608
1609     if (n > font_params[f])
1610       if (f < font_ptr)
1611         cur_val = fmem_ptr;
1612     else
1613     {
1614       do
1615         {
1616  #ifdef ALLOCATEFONT
1617           if (fmem_ptr == current_font_mem_size) /* 93/Nov/28 ??? */
1618           {
1619             font_info = realloc_font_info(increment_font_mem_size);
1620           }
1621
1622           if (fmem_ptr == current_font_mem_size) /* 94/Jan/24 */
1623           {
1624             overflow("font memory", current_font_mem_size); /* font memory */
1625             return;     // abort_flag set
1626           }
1627 #else
1628           if (fmem_ptr == font_mem_size)
1629           {
1630             overflow("font memory", font_mem_size); /* font memory */
1631             return;     // abort_flag set
1632           }
1633 #endif
1634           font_info[fmem_ptr].cint = 0;
1635           incr(fmem_ptr);
1636           incr(font_params[f]);
1637         }
1638       while(!(n == font_params[f]));
1639
1640       cur_val = fmem_ptr - 1;
1641     }
1642   else if (n > 0)
1643     cur_val = n + param_base[f];    /* 98/Oct/5 */
1644 //  else
1645 //    cur_val = (&font_check[f] - &font_info[0]); /* 98/Oct/5 */
1646 /*  checksum =  (((font_check[f].b0) << 8 | font_check[f].b1) << 8 |
1647         font_check[f].b2) << 8 | font_check[f].b3; */
1648   }
1649 /* compiler error: '-' : incompatible types - from 'union fmemoryword *' to 'struct fourunsignedchars *' */
1650   if (cur_val == fmem_ptr)
1651   {
1652     print_err("Font ");
1653 /*    print_esc(hash[(hash_size + 524) + f].rh); */
1654     print_esc(""); print(font_id_text(f));
1655     print_string(" has only ");
1656     print_int(font_params[f]);
1657     print_string(" fontdimen parameters");
1658     help2("To increase the number of font parameters, you must",
1659       "use \\fontdimen immediately after the \\font is loaded.");
1660     error();
1661   }
1662 }
1663 /* sec 0413 */
1664 void scan_something_internal_(small_number level, bool negative)
1665 {
1666   halfword m;
1667   integer p;
1668
1669   m = cur_chr;
1670
1671   switch (cur_cmd)
1672   {
1673     case def_code:
1674       {
1675         scan_char_num();
1676
1677         if (m == math_code_base)
1678         {
1679           cur_val = math_code(cur_val);
1680           cur_val_level = int_val;
1681         }
1682         else if (m < math_code_base)
1683         {
1684           cur_val = equiv(m + cur_val);
1685           cur_val_level = int_val;
1686         }
1687         else
1688         {
1689           cur_val = eqtb[m + cur_val].cint;
1690           cur_val_level = int_val;
1691         }
1692       }
1693       break;
1694
1695     case toks_register:
1696     case assign_toks:
1697     case def_family:
1698     case set_font:
1699     case def_font:
1700       if (level != tok_val)
1701       {
1702         print_err("Missing number, treated as zero");
1703         help3("A number should have been here; I inserted `0'.",
1704             "(If you can't figure out why I needed to see a number,",
1705             "look up `weird error' in the index to The TeXbook.)");
1706         back_error();
1707         {
1708           cur_val = 0;
1709           cur_val_level = dimen_val;
1710         }
1711       }
1712       else if (cur_cmd <= assign_toks)
1713       {
1714         if (cur_cmd < assign_toks)
1715         {
1716           scan_eight_bit_int();
1717           m = toks_base + cur_val;
1718         }
1719
1720         {
1721           cur_val = eqtb[m].hh.rh;
1722           cur_val_level = tok_val;
1723         }
1724       }
1725       else
1726       {
1727         back_input();
1728         scan_font_ident();
1729
1730         {
1731           cur_val = font_id_base + cur_val; /* 96/Jan/10 */
1732           cur_val_level = ident_val;
1733         }
1734       }
1735       break;
1736
1737     case assign_int:
1738       {
1739         cur_val = eqtb[m].cint;
1740         cur_val_level = int_val;
1741       }
1742       break;
1743
1744     case assign_dimen:
1745       {
1746         cur_val = eqtb[m].cint;
1747         cur_val_level = dimen_val;
1748       }
1749       break; 
1750
1751     case assign_glue:
1752       {
1753         cur_val = eqtb[m].hh.rh;
1754         cur_val_level = glue_val;
1755       }
1756       break;
1757
1758     case assign_mu_glue:
1759       {
1760         cur_val = eqtb[m].hh.rh;
1761         cur_val_level = mu_val;
1762       }
1763       break;
1764
1765     case set_aux:
1766       if (abs(mode)!= m)
1767       {
1768         print_err("Improper ");
1769         print_cmd_chr(set_aux, m);
1770         help4("You can refer to \\spacefactor only in horizontal mode;",
1771             "you can refer to \\prevdepth only in vertical mode; and",
1772             "neither of these is meaningful inside \\write. So",
1773             "I'm forgetting what you said and using zero instead.");
1774         error();
1775
1776         if (level != tok_val)
1777         {
1778           cur_val = 0;
1779           cur_val_level = dimen_val;
1780         }
1781         else
1782         {
1783           cur_val = 0;
1784           cur_val_level = int_val;
1785         }
1786       }
1787       else if (m == vmode)
1788       {
1789         cur_val = cur_list.aux_field.cint;
1790         cur_val_level = dimen_val;
1791       }
1792       else
1793       {
1794         cur_val = space_factor;
1795         cur_val_level = int_val;
1796       }
1797       break;
1798
1799     case set_prev_graf:
1800       if (mode == 0)
1801       {
1802         cur_val = 0;
1803         cur_val_level = int_val;
1804       }
1805       else
1806       {
1807         nest[nest_ptr] = cur_list;
1808         p = nest_ptr;
1809
1810         while (abs(nest[p].mode_field)!= vmode)
1811           decr(p);
1812
1813         {
1814           cur_val = nest[p].pg_field;
1815           cur_val_level = int_val;
1816         }
1817       }
1818       break;
1819
1820     case set_page_int:
1821       {
1822         if (m == 0)
1823           cur_val = dead_cycles; 
1824         else
1825           cur_val = insert_penalties;
1826
1827         cur_val_level = 0;
1828       }
1829       break;
1830
1831     case set_page_dimen:
1832       {
1833         if ((page_contents == 0) && (! output_active))
1834           if (m == 0)
1835             cur_val = 1073741823L;  /* 2^30 - 1 */
1836           else
1837             cur_val = 0;
1838         else
1839           cur_val = page_so_far[m];
1840
1841         cur_val_level = dimen_val;
1842       }
1843       break;
1844
1845     case set_shape:
1846       {
1847         if (par_shape_ptr == 0)
1848           cur_val = 0; 
1849         else
1850           cur_val = info(par_shape_ptr);
1851
1852         cur_val_level = int_val;
1853       }
1854       break;
1855
1856     case set_box_dimen:
1857       {
1858         scan_eight_bit_int();
1859
1860         if (box(cur_val) == 0)
1861           cur_val = 0;
1862         else
1863           cur_val = mem[box(cur_val) + m].cint;
1864
1865         cur_val_level = dimen_val;
1866       }
1867       break;
1868
1869     case char_given:
1870     case math_given:
1871       {
1872         cur_val = cur_chr;
1873         cur_val_level = int_val;
1874       }
1875       break;
1876
1877     case assign_font_dimen:
1878       {
1879         find_font_dimen(false);
1880         font_info[fmem_ptr].cint = 0;
1881         {
1882           cur_val = font_info[cur_val].cint;
1883           cur_val_level = dimen_val;
1884         }
1885       }
1886       break;
1887
1888     case assign_font_int:
1889       {
1890         scan_font_ident();
1891
1892         if (m == 0)
1893         {
1894           cur_val = hyphen_char[cur_val];
1895           cur_val_level = int_val;
1896         }
1897         else
1898         {
1899           cur_val = skew_char[cur_val];
1900           cur_val_level = int_val;
1901         }
1902       }
1903       break;
1904
1905     case tex_register:
1906       {
1907         scan_eight_bit_int();
1908
1909         switch(m)
1910         {
1911           case int_val:
1912             cur_val = count(cur_val);
1913             break;
1914
1915           case dimen_val:
1916             cur_val = dimen(cur_val);
1917             break;
1918
1919           case glue_val:
1920             cur_val = skip(cur_val);
1921             break;
1922
1923           case mu_val:
1924             cur_val = mu_skip(cur_val);
1925             break;
1926         }
1927         
1928         cur_val_level = m;
1929       }
1930       break;
1931
1932     case last_item:
1933       if (cur_chr > glue_val)
1934       {
1935         if (cur_chr == input_line_no_code)
1936           cur_val = line;
1937         else
1938           cur_val = last_badness;
1939
1940         cur_val_level = int_val;
1941       }
1942       else
1943       {
1944         if (cur_chr == glue_val)
1945           cur_val = zero_glue;
1946         else
1947           cur_val = 0;
1948
1949         cur_val_level = cur_chr;
1950
1951         if (!(tail >= hi_mem_min) && (mode != 0))
1952           switch(cur_chr)
1953           {
1954             case int_val:
1955               if (type(tail) == penalty_node)
1956                 cur_val = penalty(tail);
1957               break;
1958
1959             case dimen_val:
1960               if (type(tail) == kern_node)
1961                 cur_val = width(tail);
1962               break;
1963
1964             case glue_val:
1965               if (type(tail) == glue_node)
1966               {
1967                 cur_val = glue_ptr(tail);
1968
1969                 if (subtype(tail) == mu_glue)
1970                   cur_val_level = mu_val;
1971               }
1972               break;
1973           }
1974         else if ((mode == 1) && (tail == cur_list.head_field))
1975           switch (cur_chr)
1976           {
1977             case int_val:
1978               cur_val = last_penalty;
1979               break;
1980
1981             case dimen_val:
1982               cur_val = last_kern;
1983               break;
1984
1985             case glue_val:
1986               if (last_glue != empty_flag)
1987                 cur_val = last_glue;
1988               break;
1989           }
1990       }
1991       break;
1992
1993     default:
1994       {
1995         print_err("You can't use `");
1996         print_cmd_chr(cur_cmd, cur_chr);
1997         print_string("' after ");
1998         print_esc("the");
1999         help1("I'm forgetting what you said and using zero instead.");
2000         error();
2001
2002         if (level != tok_val)
2003         {
2004           cur_val = 0;
2005           cur_val_level = dimen_val;
2006         }
2007         else
2008         {
2009           cur_val = 0;
2010           cur_val_level = int_val;
2011         }
2012       }
2013       break;
2014   }
2015
2016   while (cur_val_level > level)
2017   {
2018     if (cur_val_level == glue_val)
2019       cur_val = width(cur_val);
2020     else if (cur_val_level == mu_val)
2021       mu_error();
2022
2023     decr(cur_val_level);
2024   }
2025
2026   if (negative)
2027     if (cur_val_level >= 2)
2028     {
2029       cur_val = new_spec(cur_val);
2030
2031       {
2032         width(cur_val) = - (integer) width(cur_val);
2033         stretch(cur_val) = - (integer) stretch(cur_val);
2034         shrink(cur_val) = - (integer) shrink(cur_val);
2035       }
2036     }
2037     else
2038       cur_val = - (integer) cur_val;
2039   else if ((cur_val_level >= glue_val) && (cur_val_level <= mu_val))
2040     add_glue_ref(cur_val);
2041 }
2042 /* sec 0341 */
2043 void get_next (void)
2044 {
2045   integer k;
2046   halfword t;
2047 /*  char cat; */    /* make this an int ? */
2048   int cat;      /* make this an int ? 95/Jan/7 */
2049   ASCII_code c, cc;
2050   char d;
2051
2052 lab20:
2053   cur_cs = 0;
2054
2055   if (cur_input.state_field != token_list)
2056   {
2057 lab25:
2058     if (cur_input.loc_field <= cur_input.limit_field)
2059     {
2060       cur_chr = buffer[cur_input.loc_field];
2061       incr(cur_input.loc_field);
2062 lab21:
2063       cur_cmd = cat_code(cur_chr);
2064
2065       switch (cur_input.state_field + cur_cmd)
2066       {
2067         case any_state_plus(ignore):
2068         case skip_blanks + spacer:
2069         case new_line + spacer:
2070           goto lab25;
2071           break;
2072
2073         case any_state_plus(escape):
2074           {
2075             if (cur_input.loc_field > cur_input.limit_field)
2076               cur_cs = null_cs;
2077             else
2078             {
2079 lab26:
2080               k = cur_input.loc_field;
2081               cur_chr = buffer[k];
2082               cat = cat_code(cur_chr);
2083               incr(k);
2084
2085               if (cat == letter)
2086                 cur_input.state_field = skip_blanks;
2087               else if (cat == spacer)
2088                 cur_input.state_field = skip_blanks;
2089               else
2090                 cur_input.state_field = mid_line;
2091
2092               if ((cat == letter) && (k <= cur_input.limit_field))
2093               {
2094                 do
2095                   {
2096                     cur_chr = buffer[k];
2097                     cat = cat_code(cur_chr);
2098                     incr(k);
2099                   }
2100                 while(!((cat != letter) || (k > cur_input.limit_field)));
2101
2102                 {
2103                   if (buffer[k]== cur_chr)
2104                     if (cat == sup_mark)
2105                       if (k < cur_input.limit_field)
2106                       {
2107                         c = buffer[k + 1];
2108
2109                         if (c < 128)
2110                         {
2111                           d = 2;
2112                           if ((((c >= 48) && (c <= 57)) || ((c >= 97) && (c <= 102))))
2113                             if (k + 2 <= cur_input.limit_field)
2114                             {
2115                               cc = buffer[k + 2];
2116
2117                               if ((((cc >= 48) && (cc <= 57)) || ((cc >= 97) && (cc <= 102))))
2118                                 incr(d);
2119                             }
2120
2121                           if (d > 2)
2122                           {
2123                             if (c <= 57)
2124                               cur_chr = c - 48;
2125                             else
2126                               cur_chr = c - 87;
2127
2128                             if (cc <= 57)
2129                               cur_chr = 16 * cur_chr + cc - 48;
2130                             else
2131                               cur_chr = 16 * cur_chr + cc - 87;
2132
2133                             buffer[k - 1] = cur_chr;
2134                           }
2135                           else if (c < 64)
2136                             buffer[k - 1] = c + 64;
2137                           else
2138                             buffer[k - 1] = c - 64;
2139
2140                           cur_input.limit_field = cur_input.limit_field - d;
2141                           first = first - d;
2142
2143                           while (k <= cur_input.limit_field)
2144                           {
2145                             buffer[k] = buffer[k + d];
2146                             incr(k);
2147                           }
2148
2149                           goto lab26;
2150                         }
2151                       }
2152                 }
2153
2154                 if (cat != letter)
2155                   decr(k);
2156
2157                 if (k > cur_input.loc_field + 1)
2158                 {
2159                   cur_cs = id_lookup(cur_input.loc_field, k - cur_input.loc_field);
2160                   cur_input.loc_field = k;
2161                   goto lab40;
2162                 }
2163               }
2164               else
2165               {
2166                 if (buffer[k] == cur_chr)
2167                   if (cat == sup_mark)
2168                     if (k < cur_input.limit_field)
2169                     {
2170                       c = buffer[k + 1];
2171
2172                       if (c < 128)             /* ? */
2173                       {
2174                         d = 2;
2175                         if ((((c >= 48) && (c <= 57)) || ((c >= 97) && (c <= 102))))
2176                           if (k + 2 <= cur_input.limit_field)
2177                           {
2178                             cc = buffer[k + 2];
2179
2180                             if ((((cc >= 48) && (cc <= 57)) || ((cc >= 97) && (cc <= 102))))
2181                               incr(d);
2182                           }
2183
2184                         if (d > 2)
2185                         {
2186                           if (c <= 57)
2187                             cur_chr = c - 48;
2188                           else
2189                             cur_chr = c - 87;
2190
2191                           if (cc <= 57)          /* cc may be used without ... */
2192                             cur_chr = 16 * cur_chr + cc - 48;
2193                           else
2194                             cur_chr = 16 * cur_chr + cc - 87;
2195
2196                           buffer[k - 1] = cur_chr;
2197                         }
2198                         else if (c < 64)
2199                           buffer[k - 1] = c + 64;
2200                         else
2201                           buffer[k - 1] = c - 64;
2202
2203                         cur_input.limit_field = cur_input.limit_field - d;
2204                         first = first - d;
2205
2206                         while (k <= cur_input.limit_field)
2207                         {
2208                           buffer[k] = buffer[k + d];
2209                           incr(k);
2210                         }
2211                         goto lab26;
2212                       }
2213                     }
2214               }
2215               cur_cs = single_base + buffer[cur_input.loc_field];
2216               incr(cur_input.loc_field);
2217             }
2218 lab40:
2219             cur_cmd = eq_type(cur_cs);
2220             cur_chr = equiv(cur_cs);
2221             
2222             if (cur_cmd >= outer_call)
2223               check_outer_validity();
2224           }
2225           break;
2226
2227         case any_state_plus(active_char):
2228           {
2229             cur_cs = cur_chr + active_base;
2230             cur_cmd = eq_type(cur_cs);
2231             cur_chr = equiv(cur_cs);
2232             cur_input.state_field = mid_line;
2233             
2234             if (cur_cmd >= outer_call)
2235               check_outer_validity();
2236           }
2237           break;
2238
2239         case any_state_plus(sup_mark):
2240           {
2241             if (cur_chr == buffer[cur_input.loc_field])
2242               if (cur_input.loc_field < cur_input.limit_field)
2243               {
2244                 c = buffer[cur_input.loc_field + 1];
2245
2246                 if (c < 128)
2247                 {
2248                   cur_input.loc_field = cur_input.loc_field + 2;
2249
2250                   if ((((c >= 48) && (c <= 57)) || ((c >= 97) && (c <= 102))))
2251                     if (cur_input.loc_field <= cur_input.limit_field)
2252                     {
2253                       cc = buffer[cur_input.loc_field];
2254
2255                       if ((((cc >= 48) && (cc <= 57)) || ((cc >= 97) && (cc <= 102))))
2256                       {
2257                         incr(cur_input.loc_field);
2258
2259                         if (c <= 57)
2260                           cur_chr = c - 48;
2261                         else
2262                           cur_chr = c - 87;
2263
2264                         if (cc <= 57)
2265                           cur_chr = 16 * cur_chr + cc - 48;
2266                         else
2267                           cur_chr = 16 * cur_chr + cc - 87;
2268
2269                         goto lab21;
2270                       }
2271                     }
2272
2273                   if (c < 64)
2274                     cur_chr = c + 64;
2275                   else
2276                     cur_chr = c - 64;
2277
2278                   goto lab21;
2279                 }
2280               }
2281
2282               cur_input.state_field = mid_line;
2283           }
2284           break;
2285
2286         case any_state_plus(invalid_char):
2287           {
2288             print_err("Text line contains an invalid character");
2289             help2("A funny symbol that I can't read has just been input.",
2290                 "Continue, and I'll forget that it ever happened.");
2291             deletions_allowed = false;
2292             error();
2293             deletions_allowed = true;
2294             goto lab20;
2295           }
2296           break;
2297
2298         case mid_line + spacer:
2299           {
2300             cur_input.state_field = skip_blanks;
2301             cur_chr = ' ';
2302           }
2303           break;
2304
2305         case mid_line + car_ret:
2306           {
2307             cur_input.loc_field = cur_input.limit_field + 1;
2308             cur_cmd = spacer;
2309             cur_chr = ' ';
2310           }
2311           break;
2312
2313         case skip_blanks + car_ret:
2314         case any_state_plus(comment):
2315           {
2316             cur_input.loc_field = cur_input.limit_field + 1;
2317             goto lab25;
2318           }
2319           break;
2320
2321         case new_line + car_ret:
2322           {
2323             cur_input.loc_field = cur_input.limit_field + 1;
2324             cur_cs = par_loc;
2325             cur_cmd = eq_type(cur_cs);
2326             cur_chr = equiv(cur_cs);
2327             
2328             if (cur_cmd >= outer_call)
2329               check_outer_validity();
2330           }
2331           break;
2332
2333         case mid_line + left_brace:
2334           incr(align_state);
2335           break;
2336
2337         case skip_blanks + left_brace:
2338         case new_line + left_brace:
2339           {
2340             cur_input.state_field = mid_line;
2341             incr(align_state);
2342           }
2343           break;
2344
2345         case mid_line + right_brace:
2346           decr(align_state);
2347           break;
2348
2349         case skip_blanks + right_brace:
2350         case new_line + right_brace:
2351           {
2352             cur_input.state_field = 1;
2353             decr(align_state);
2354           }
2355           break;
2356
2357         case add_delims_to(skip_blanks):
2358         case add_delims_to(new_line):
2359           cur_input.state_field = 1;
2360           break;
2361
2362         default:
2363           break;
2364       }
2365     }
2366     else
2367     {
2368       cur_input.state_field = new_line;
2369
2370       if (cur_input.name_field > 17)
2371       {
2372         incr(line);
2373         first = cur_input.start_field;
2374
2375         if (!force_eof)
2376         {
2377           if (input_ln(input_file[cur_input.index_field], true))
2378             firm_up_the_line();
2379           else
2380             force_eof = true;
2381         }
2382
2383         if (force_eof)
2384         {
2385           print_char(')');
2386           decr(open_parens);
2387 #ifndef _WINDOWS
2388           fflush(stdout);
2389 #endif
2390           force_eof = false;
2391           end_file_reading();
2392           check_outer_validity();
2393           goto lab20;
2394         }
2395
2396         if ((end_line_char < 0) || (end_line_char > 255))
2397           decr(cur_input.limit_field);
2398         else
2399           buffer[cur_input.limit_field] = end_line_char;
2400
2401         first = cur_input.limit_field + 1;
2402         cur_input.loc_field = cur_input.start_field;
2403       }
2404       else
2405       {
2406         if (!(cur_input.name_field == 0))
2407         {
2408           cur_cmd = 0;
2409           cur_chr = 0;
2410           return;
2411         }
2412
2413         if (input_ptr > 0)
2414         {
2415           end_file_reading();
2416           goto lab20;
2417         }
2418
2419         if (selector < log_only)
2420           open_log_file();
2421
2422         if (interaction > nonstop_mode)
2423         {
2424           if ((end_line_char < 0) || (end_line_char > 255))
2425             incr(cur_input.limit_field);
2426
2427           if (cur_input.limit_field == cur_input.start_field)
2428             print_nl("(Please type a command or say `\\end')");
2429
2430           print_ln();
2431           first = cur_input.start_field;
2432
2433           {
2434             ;
2435             print_string("*");
2436             term_input("*", 0);
2437           }
2438
2439           cur_input.limit_field = last;
2440
2441           if ((end_line_char < 0) || (end_line_char > 255))
2442             decr(cur_input.limit_field);
2443           else
2444             buffer[cur_input.limit_field]= end_line_char;
2445
2446           first = cur_input.limit_field + 1;
2447           cur_input.loc_field = cur_input.start_field;
2448         }
2449         else
2450         {
2451           fatal_error("*** (job aborted, no legal \\end found)");
2452           return;     // abort_flag set
2453         }
2454       }
2455
2456       {
2457         if (interrupt != 0)
2458         {
2459           pause_for_instructions();
2460         }
2461       }
2462
2463       goto lab25;
2464     }
2465   }
2466   else if (cur_input.loc_field != 0)
2467   {
2468     t = info(cur_input.loc_field);
2469     cur_input.loc_field = link(cur_input.loc_field);
2470
2471     if (t >= cs_token_flag)
2472     {
2473       cur_cs = t - cs_token_flag;
2474       cur_cmd = eq_type(cur_cs);
2475       cur_chr = equiv(cur_cs);
2476
2477       if (cur_cmd >= outer_call)
2478         if (cur_cmd == dont_expand)
2479         {
2480           cur_cs = info(cur_input.loc_field) - cs_token_flag;
2481           cur_input.loc_field = 0;
2482           cur_cmd = eq_type(cur_cs);
2483           cur_chr = equiv(cur_cs);
2484
2485           if (cur_cmd > max_command)
2486           {
2487             cur_cmd = relax;
2488             cur_chr = no_expand_flag;
2489           }
2490         }
2491         else
2492         {
2493           check_outer_validity();
2494         }
2495     }
2496     else
2497     {
2498       cur_cmd = t / 256;
2499       cur_chr = t % 256;
2500
2501       switch (cur_cmd)
2502       {
2503         case left_brace:
2504           incr(align_state);
2505           break;
2506
2507         case right_brace:
2508           decr(align_state);
2509           break;
2510
2511         case out_param:
2512           {
2513             begin_token_list(param_stack[cur_input.limit_field + cur_chr - 1], parameter);
2514             goto lab20;
2515           }
2516           break;
2517
2518         default:
2519           break;
2520       }
2521     }
2522   }
2523   else
2524   {
2525     end_token_list();
2526     goto lab20;
2527   }
2528
2529   if (cur_cmd <= car_ret)
2530     if (cur_cmd >= tab_mark)
2531       if (align_state == 0)
2532       {
2533         if ((scanner_status == aligning) && (cur_align == 0))
2534         {
2535           fatal_error("(interwoven alignment preambles are not allowed)");
2536           return;     // abort_flag set
2537         }
2538
2539         cur_cmd = extra_info(cur_align);
2540         extra_info(cur_align) = cur_chr;
2541
2542         if (cur_cmd == omit)
2543           begin_token_list(omit_template, v_template);
2544         else
2545           begin_token_list(v_part(cur_align), v_template);
2546
2547         align_state = 1000000L;
2548         goto lab20;
2549       }
2550 }