OSDN Git Service

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