OSDN Git Service

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