OSDN Git Service

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