OSDN Git Service

a299c100c62585b9aa6644ce17cf10e0777ee844
[putex/putex.git] / src / texsourc / tex3.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 /* sec 0440 */
23 void scan_int (void)
24 {
25   boolean negative;
26   integer m;
27   small_number d;
28   boolean vacuous;
29   boolean OKsofar;
30
31   radix = 0;
32   OKsofar = true;
33   negative = false;
34
35   do
36     {
37       do 
38         {
39           get_x_token();
40         }
41       while (!(cur_cmd != spacer));
42
43       if (cur_tok == other_token + '-')
44       {
45         negative = !negative;
46         cur_tok = other_token + '+';
47       }
48     }
49   while (!(cur_tok != other_token + '+'));
50
51   if (cur_tok == alpha_token)
52   {
53     get_token();
54
55     if (cur_tok < cs_token_flag)
56     {
57       cur_val = cur_chr;
58
59       if (cur_cmd <= right_brace)
60         if (cur_cmd == right_brace)
61           incr(align_state);
62         else
63           decr(align_state);
64     }
65     else if (cur_tok < cs_token_flag + single_base)
66       cur_val = cur_tok - cs_token_flag - active_base;
67     else
68       cur_val = cur_tok - cs_token_flag - single_base;
69
70     if (cur_val > 255)
71     {
72       print_err("Improper alphabetic constant");
73       help2("A one-character control sequence belongs after a ` mark.",
74         "So I'm essentially inserting \\0 here.");
75       cur_val = '0';
76       back_error();
77     }
78     else
79     {
80       get_x_token();
81
82       if (cur_cmd != spacer)
83         back_input();
84     }
85   }
86   else if ((cur_cmd >= min_internal) && (cur_cmd <= max_internal))
87   {
88     scan_something_internal(int_val, false);
89   }
90   else
91   {
92     radix = 10;
93     m = 214748364L;   /* 7FFFFFFF hex */
94
95     if (cur_tok == octal_token)
96     {
97       radix = 8;
98       m = 268435456L;   /* 2^28 */
99       get_x_token();
100     }
101     else if (cur_tok == hex_token)
102     {
103       radix = 16;
104       m = 134217728L;   /* 2^27 8000000 hex */
105       get_x_token();
106     }
107
108     vacuous = true;
109     cur_val = 0;
110
111     while (true)
112     {
113       if ((cur_tok < zero_token + radix) && (cur_tok >= zero_token) && (cur_tok <= zero_token + 9))
114         d = cur_tok - zero_token;
115       else if (radix == 16)
116         if ((cur_tok <= A_token + 5) && (cur_tok >= A_token))
117           d = cur_tok - A_token + 10;
118         else if ((cur_tok <= other_A_token + 5) && (cur_tok >= other_A_token))
119           d = cur_tok - other_A_token;
120         else
121           goto lab30;
122       else
123         goto lab30;
124
125       vacuous = false;
126
127       if ((cur_val >= m) && ((cur_val > m) || (d > 7) || (radix != 10)))
128       {
129         if (OKsofar)
130         {
131           print_err("Number too big");
132           help2("I can only go up to 2147483647='17777777777=\"7FFFFFFF,",
133             "so I'm using that number instead of yours.");
134           error();
135           cur_val = 2147483647L;    /* 7FFFFFFF hex */
136           OKsofar = false;
137         }
138       }
139       else
140         cur_val = cur_val * radix + d;
141       get_x_token();
142     }
143 lab30:;
144
145     if (vacuous)
146     {
147       print_err("Missing number, treated as zero");
148       help3("A number should have been here; I inserted `0'.",
149         "(If you can't figure out why I needed to see a number,",
150         "look up `weird error' in the index to The TeXbook.)");
151       back_error();
152     } 
153     else if (cur_cmd != spacer)
154       back_input();
155   }
156
157   if (negative)
158     cur_val = - (integer) cur_val;
159 }
160 /* sec 0448 */
161 void scan_dimen_(boolean mu, boolean inf, boolean shortcut)
162 {
163   boolean negative;
164   integer f;
165   integer num, denom;
166   small_number k, kk;
167   halfword p, q;
168   scaled v;
169   integer savecurval;
170
171   f = 0;
172   arith_error = false;
173   cur_order = 0;
174   negative = false;
175
176   if (!shortcut)
177   {
178     negative = false;
179
180     do
181       {
182         do
183           {
184             get_x_token();
185           }
186         while (!(cur_cmd != spacer));
187
188         if (cur_tok == other_token + '-')
189         {
190           negative = ! negative;
191           cur_tok = other_token + '+';
192         }
193       }
194     while (!(cur_tok != other_token + '+'));
195
196     if ((cur_cmd >= min_internal) && (cur_cmd <= max_internal))
197     {
198       if (mu)
199       {
200         scan_something_internal(mu_val, false);
201
202         if (cur_val_level >= glue_val)
203         {
204           v = width(cur_val);
205           delete_glue_ref(cur_val);
206           cur_val = v;
207         }
208
209         if (cur_val_level == mu_val)
210           goto lab89;
211
212         if (cur_val_level != int_val)
213           mu_error();
214       }
215       else
216       {
217         scan_something_internal(dimen_val, false);
218
219         if (cur_val_level == dimen_val)
220           goto lab89;
221       }
222     }
223     else
224     {
225       back_input();
226
227       if (cur_tok == continental_point_token)
228         cur_tok = point_token;
229
230       if (cur_tok != point_token)
231       {
232         scan_int();
233       }
234       else
235       {
236         radix = 10;
237         cur_val = 0;
238       }
239
240       if (cur_tok == continental_point_token)
241         cur_tok = point_token;
242
243       if ((radix == 10) && (cur_tok == point_token))
244       {
245         k = 0;
246         p = 0;      /* p:=null l.8883 */
247         get_token();
248
249         while (true)
250         {
251           get_x_token();
252
253           if ((cur_tok > zero_token + 9) || (cur_tok < zero_token))
254             goto lab31;
255
256           if (k < 17)
257           {
258             q = get_avail();
259             link(q) = p;
260             info(q) = cur_tok - zero_token;
261             p = q;
262             incr(k);
263           }
264         }
265 lab31:
266         for (kk = k; kk >= 1; kk--)
267         {
268           dig[kk - 1] = info(p);
269           q = p;
270           p = link(p);
271           free_avail(q);
272         }
273
274         f = round_decimals(k);
275
276         if (cur_cmd != spacer)
277           back_input();
278         }
279       }
280   }
281
282   if (cur_val < 0)
283   {
284     negative = !negative;
285     cur_val = - (integer) cur_val;
286   }
287
288   if (inf)
289   {
290     if (scan_keyword("fil"))
291     {
292       cur_order = fil;
293
294       while (scan_keyword("l"))
295       {
296         if (cur_order == filll)
297         {
298           print_err("Illegal unit of measure (");
299           print_string("replaced by filll)");
300           help1("I dddon't go any higher than filll.");
301           error();
302         }
303         else
304           incr(cur_order);
305       }
306       goto lab88;
307     }
308   }
309
310   savecurval = cur_val;
311
312   do
313     {
314       get_x_token();
315     }
316   while (!(cur_cmd != spacer));
317
318   if ((cur_cmd < min_internal) || (cur_cmd > max_internal))
319     back_input();
320   else
321   {
322     if (mu)
323     {
324       scan_something_internal(mu_val, false);
325
326       if (cur_val_level >= glue_val)
327       {
328         v = width(cur_val);
329         delete_glue_ref(cur_val);
330         cur_val = v;
331       }
332
333       if (cur_val_level != mu_val)
334       {
335         mu_error();
336       }
337     }
338     else
339     {
340       scan_something_internal(dimen_val, false);
341     }
342
343     v = cur_val;
344     goto lab40;
345   }
346
347   if (mu)
348     goto lab45;
349
350   if (scan_keyword("em"))
351     v = quad(cur_font);
352   else if (scan_keyword("ex"))
353     v = x_height(cur_font);
354   else
355     goto lab45;
356
357   {
358     get_x_token();
359
360     if (cur_cmd != spacer)
361       back_input();
362   }
363
364 lab40:
365   cur_val = mult_and_add(savecurval, v, xn_over_d(v, f, 65536L), 1073741823L);   /* 2^30 - 1 */
366   goto lab89;
367
368 lab45:
369   if (mu)
370   {
371     if (scan_keyword("mu"))
372       goto lab88;
373     else
374     {
375       print_err("Illegal unit of measure (");
376       print_string("mu inserted)");
377       help4("The unit of measurement in math glue must be mu.",
378           "To recover gracefully from this error, it's best to",
379           "delete the erroneous units; e.g., type `2' to delete",
380           "two letters. (See Chapter 27 of The TeXbook.)");
381       error();
382       goto lab88;
383     }
384   }
385
386   if (scan_keyword("true"))
387   {
388     prepare_mag();
389
390     if (mag != 1000)
391     {
392       cur_val = xn_over_d(cur_val, 1000, mag);
393       f = (1000 * f + 65536L * tex_remainder) / mag;
394       cur_val = cur_val + (f / 65536L);
395       f = f % 65536L;
396     }
397   }
398
399   if (scan_keyword("pt"))
400     goto lab88;
401
402   if (scan_keyword("in"))
403     set_conversion(7227, 100);
404   else if (scan_keyword("pc"))
405     set_conversion(12, 1);
406   else if (scan_keyword("cm"))
407     set_conversion(7227, 254);
408   else if (scan_keyword("mm"))
409     set_conversion(7227, 2540);
410   else if (scan_keyword("bp"))
411     set_conversion(7227, 7200);
412   else if (scan_keyword("dd"))
413     set_conversion(1238, 1157);
414   else if (scan_keyword("cc"))
415     set_conversion(14856, 1157);
416   else if (scan_keyword("Q"))
417     set_conversion(7227, 10160);
418   else if (scan_keyword("H"))
419     set_conversion(7227, 10160);
420   else if (scan_keyword("sp"))
421     goto lab30;
422   else
423   {
424     print_err("Illegal unit of measure (");
425     print_string("pt inserted)");
426     help6("Dimensions can be in units of em, ex, in, pt, pc,",
427       "cm, mm, dd, cc, bp, or sp; but yours is a new one!",
428       "I'll assume that you meant to say pt, for printer's points.",
429       "To recover gracefully from this error, it's best to",
430       "delete the erroneous units; e.g., type `2' to delete",
431       "two letters. (See Chapter 27 of The TeXbook.)");
432     error();
433     goto lab32;
434   }
435
436   cur_val = xn_over_d(cur_val, num, denom);
437   f = (num * f + 65536L * tex_remainder) / denom;
438   cur_val = cur_val +(f / 65536L);
439   f = f % 65536L;
440 lab32:;
441 lab88:
442   if (cur_val >= 16384)     /* 2^14 */
443     arith_error = true;
444   else
445     cur_val = cur_val * unity + f;
446 lab30:;
447   {
448     get_x_token();
449
450     if (cur_cmd != spacer)
451       back_input();
452   }
453 lab89:
454   if (arith_error || (abs(cur_val) >= 1073741824L)) /* 2^30 */
455   {
456     print_err("Dimension too large");
457     help2("I can't work with sizes bigger than about 19 feet.",
458         "Continue and I'll use the largest value I can.");
459     error();
460     cur_val = max_dimen;
461     arith_error = false;
462   }
463
464   if (negative)
465     cur_val = - (integer) cur_val;
466 }
467 /* sec 0461 */
468 void scan_glue_(small_number level)
469 {
470   boolean negative;
471   halfword q;
472   boolean mu;
473
474   mu = (level == mu_val);
475   negative = false;
476
477   do
478     {
479       do
480         {
481           get_x_token();
482         }
483       while (!(cur_cmd != spacer));
484
485       if (cur_tok == other_token + '-')
486       {
487         negative = !negative;
488         cur_tok = other_token + '+';
489       }
490     }
491   while (!(cur_tok != other_token + '+'));
492
493   if ((cur_cmd >= min_internal) && (cur_cmd <= max_internal))
494   {
495     scan_something_internal(level, negative);
496
497     if (cur_val_level >= glue_val)
498     {
499       if (cur_val_level != level)
500       {
501         mu_error();
502       }
503       return;
504     }
505
506     if (cur_val_level == int_val)
507     {
508       scan_dimen(mu, false, true);
509     }
510     else if (level == mu_val)
511     {
512       mu_error();
513     }
514   }
515   else
516   {
517     back_input();
518     scan_dimen(mu, false, false);
519
520     if (negative)
521       cur_val = - (integer) cur_val;
522   }
523   q = new_spec(zero_glue);
524   width(q) = cur_val;
525
526   if (scan_keyword("plus"))
527   {
528     scan_dimen(mu, true, false);
529     stretch(q) = cur_val;
530     stretch_order(q) = cur_order;
531   }
532
533   if (scan_keyword("minus"))
534   {
535     scan_dimen(mu, true, false);
536     shrink(q) = cur_val;
537     shrink_order(q) = cur_order;
538   }
539
540   cur_val = q;
541 }
542 /* sec 0463 */
543 halfword scan_rule_spec (void)
544 {
545   halfword q;
546
547   q = new_rule();
548
549   if (cur_cmd == vrule)
550     width(q) = default_rule;
551   else
552   {
553     height(q) = default_rule;
554     depth(q) = 0;
555   }
556
557 lab21:
558
559   if (scan_keyword("width"))
560   {
561     scan_dimen(false, false, false);
562     width(q) = cur_val;
563     goto lab21;
564   }
565
566   if (scan_keyword("height"))
567   {
568     scan_dimen(false, false, false);
569     height(q) = cur_val;
570     goto lab21;
571   }
572
573   if (scan_keyword("depth"))
574   {
575     scan_dimen(false, false, false);
576     depth(q) = cur_val;
577     goto lab21;
578   }
579
580   return q;
581 }
582 /* sec 0464 */
583 halfword str_toks_(pool_pointer b)
584 {
585   halfword p;
586   halfword q;
587   halfword t;
588   pool_pointer k;
589
590   str_room(1);
591   p = temp_head;
592   link(p) = 0;
593   k = b;
594
595   while (k < pool_ptr)
596   {
597     t = str_pool[k];
598
599     if (t == ' ')
600       t = space_token;
601     else
602       t = other_token + t;
603
604     fast_store_new_token(t);
605     incr(k);
606   }
607
608   pool_ptr = b;
609
610   return p;
611 }
612 /* sec 0465 */
613 halfword the_toks (void)
614 {
615   register halfword Result;
616   char old_setting;
617   halfword p, q, r;
618   pool_pointer b;
619
620   get_x_token();
621   scan_something_internal(tok_val, false);
622
623   if (cur_val_level >= ident_val)
624   {
625     p = temp_head;
626     link(p) = 0;
627
628     if (cur_val_level == ident_val)
629       store_new_token(cs_token_flag + cur_val);
630     else if (cur_val != 0)
631     {
632       r = link(cur_val);
633
634       while (r != 0)
635       {
636         fast_store_new_token(info(r));
637         r = link(r);
638       }
639     }
640
641     Result = p;
642   }
643   else
644   {
645     old_setting = selector;
646     selector = new_string;
647     b = pool_ptr;
648
649     switch (cur_val_level)
650     {
651       case int_val:
652         print_int(cur_val);
653         break;
654       case dimen_val:
655         {
656           print_scaled(cur_val);
657           print_string("pt");
658         }
659         break;
660       case glue_val:
661         {
662           print_spec(cur_val, "pt");
663           delete_glue_ref(cur_val);
664         }
665         break;
666       case mu_val:
667         {
668           print_spec(cur_val, "mu");
669           delete_glue_ref(cur_val);
670         }
671         break;
672     }
673     selector = old_setting;
674     Result = str_toks(b);
675   }
676
677   return Result;
678 }
679 /* sec 0467 */
680 void ins_the_toks (void) 
681
682   link(garbage) = the_toks();
683   begin_token_list(link(temp_head), 4);
684 }
685 /* sec 0470 */
686 void conv_toks (void)
687 {
688   char old_setting;
689   char c;
690   small_number save_scanner_status;
691   pool_pointer b;
692
693   c = cur_chr;
694
695   switch (c)
696   {
697     case number_code:
698     case roman_numeral_code:
699       scan_int();
700       break;
701
702     case string_code:
703     case meaning_code:
704       save_scanner_status = scanner_status;
705       scanner_status = 0;
706       get_token();
707       scanner_status = save_scanner_status;
708       break;
709
710     case font_name_code:
711       scan_font_ident();
712       break;
713
714     case job_name_code:
715       if (job_name == 0)
716         open_log_file();
717       break;
718   }
719
720   old_setting = selector;
721   selector = new_string;
722   b = pool_ptr;
723
724   switch (c)
725   {
726     case number_code:
727       print_int(cur_val);
728       break;
729
730     case roman_numeral_code:
731       print_roman_int(cur_val);
732       break;
733
734     case string_code:
735       if (cur_cs != 0)
736         sprint_cs(cur_cs);
737       else
738         print_char(cur_chr);
739       break;
740
741     case meaning_code:
742       print_meaning();
743       break;
744
745     case font_name_code:
746       print(font_name[cur_val]);
747
748       if (font_size[cur_val] != font_dsize[cur_val])
749       {
750         print_string(" at ");
751         print_scaled(font_size[cur_val]);
752         print_string("pt");
753       }
754       break;
755
756     case job_name_code:
757       print(job_name);
758       break;
759   }
760
761   selector = old_setting;
762   link(garbage) = str_toks(b);
763   begin_token_list(link(temp_head), 4);
764 }
765 /* sec 0473 */
766 halfword scan_toks_(boolean macrodef, boolean xpand)
767 {
768   register halfword Result;
769   halfword t;
770   halfword s;
771   halfword p;
772   halfword q;
773   halfword unbalance;
774   halfword hashbrace;
775
776   if (macrodef)
777     scanner_status = defining;
778   else
779     scanner_status = absorbing;
780
781   warning_index = cur_cs;
782   def_ref = get_avail();
783   token_ref_count(def_ref) = 0;
784   p = def_ref;
785   hashbrace = 0;
786   t = zero_token;
787
788   if (macrodef)
789   {
790     while (true)
791     {
792       get_token();
793
794       if (cur_tok < right_brace_limit)
795         goto lab31;
796
797       if (cur_cmd == mac_param)
798       {
799         s = match_token + cur_chr;
800         get_token();
801
802         if (cur_cmd == left_brace)
803         {
804           hashbrace = cur_tok;
805           store_new_token(cur_tok);
806           store_new_token(end_match_token);
807           goto lab30;
808         }
809
810         if (t == zero_token + 9)
811         {
812           print_err("You already have nine parameters");
813           help1("I'm going to ignore the # sign you just used.");
814           error();
815         }
816         else
817         {
818           incr(t);
819
820           if (cur_tok != t)
821           {
822             print_err("Parameters must be numbered consecutively");
823             help2("I've inserted the digit you should have used after the #.",
824                 "Type `1' to delete what you did use.");
825             back_error();
826           }
827           cur_tok = s;
828         }
829       }
830
831       store_new_token(cur_tok);
832     }
833
834 lab31:
835     store_new_token(end_match_token);
836
837     if (cur_cmd == right_brace)
838     {
839       print_err("Missing { inserted");
840       incr(align_state);
841       help2("Where was the left brace? You said something like `\\def\\a}',",
842           "which I'm going to interpret as `\\def\\a{}'.");
843       error();
844       goto lab40;
845     }
846 lab30:;
847   }
848   else
849   {
850     scan_left_brace();
851   }
852
853   unbalance = 1;
854
855   while (true)
856   {
857     if (xpand)
858     {
859       while (true)
860       {
861         get_next();
862
863         if (cur_cmd <= max_command)
864           goto lab32;
865
866         if (cur_cmd != the)
867         {
868           expand();
869         }
870         else
871         {
872           q = the_toks();
873
874           if (link(temp_head) != 0)
875           {
876             link(p) = link(temp_head);
877             p = q;
878           }
879         }
880       }
881 lab32:
882       x_token();
883     }
884     else
885       get_token();
886
887     if (cur_tok < right_brace_limit)
888       if (cur_cmd < right_brace)
889         incr(unbalance);
890       else
891       {
892         decr(unbalance);
893
894         if (unbalance == 0)
895           goto lab40;
896       }
897     else if (cur_cmd == mac_param)
898       if (macrodef)
899       {
900         s = cur_tok;
901
902         if (xpand)
903           get_x_token();
904         else
905           get_token();
906
907         if (cur_cmd != mac_param)
908           if ((cur_tok <= zero_token) || (cur_tok > t))
909           {
910             print_err("Illegal parameter number in definition of ");
911             sprint_cs(warning_index);
912             help3("You meant to type ## instead of #, right?",
913                 "Or maybe a } was forgotten somewhere earlier, and things",
914                 "are all screwed up? I'm going to assume that you meant ##.");
915             back_error();
916             cur_tok = s;
917           }
918           else
919             cur_tok = out_param_token - '0' + cur_chr;
920       }
921
922     store_new_token(cur_tok);
923   }
924 lab40:
925   scanner_status = 0;
926
927   if (hashbrace != 0)
928     store_new_token(hashbrace);
929
930   Result = p;
931   return Result;
932 }
933 /* used only in ITEX.C */
934 /* sec 0482 */
935 void read_toks_(integer n, halfword r)
936 {
937   halfword p;
938   halfword q;
939   integer s;
940 /*  small_number m;  */
941   int m; /* 95/Jan/7 */
942
943   scanner_status = defining;
944   warning_index = r;
945   def_ref = get_avail();
946   token_ref_count(def_ref) = 0;
947   p = def_ref;
948   store_new_token(end_match_token);
949
950   if ((n < 0) || (n > 15))
951     m = 16;
952   else
953     m = n;
954
955   s = align_state;
956   align_state = 1000000L;
957
958   do
959     {
960       begin_file_reading();
961       cur_input.name_field = m + 1;
962
963       if (read_open[m] == closed)
964         if (interaction > nonstop_mode)
965           if (n < 0)
966             prompt_input("");
967           else
968           {
969             print_ln();
970             sprint_cs(r);
971             prompt_input("=");
972             n = -1;
973           }
974         else
975         {
976           fatal_error("*** (cannot \\read from terminal in nonstop modes)");
977           return;
978         }
979       else if (read_open[m] == 1)
980         if (input_ln(read_file[m], false))
981           read_open[m] = 0;
982         else
983         {
984           (void) a_close(read_file[m]);
985           read_open[m] = 2;
986         }
987       else
988       {
989         if (!input_ln(read_file[m], true))
990         {
991           (void) a_close(read_file[m]);
992           read_open[m] = 2;
993
994           if (align_state != 1000000L)
995           {
996             runaway();
997             print_err("File ended within ");
998             print_esc("read");
999             help1("This \\read has unbalanced braces.");
1000             align_state = 1000000L;
1001             error();
1002           }
1003         }
1004       }
1005
1006       limit = last;
1007
1008       if (end_line_char_inactive())
1009         decr(limit);
1010       else
1011         buffer[limit] = end_line_char;
1012
1013       first = limit + 1;
1014       loc = start;
1015       state = new_line;
1016
1017       while (true)
1018       {
1019         get_token();
1020
1021         if (cur_tok == 0)
1022           goto lab30;
1023
1024         if (align_state < 1000000L)
1025         {
1026           do
1027             {
1028               get_token();
1029             }
1030           while (!(cur_tok == 0));
1031
1032           align_state = 1000000L;
1033           goto lab30;
1034         }
1035
1036         store_new_token(cur_tok);
1037       }
1038 lab30:
1039       end_file_reading();
1040     }
1041   while (!(align_state == 1000000L));
1042
1043   cur_val = def_ref;
1044   scanner_status = normal;
1045   align_state = s;
1046 }
1047 /* sec 0494 */
1048 void pass_text (void)
1049 {
1050   integer l;
1051   small_number save_scanner_status;
1052
1053   save_scanner_status = scanner_status;
1054   scanner_status = skipping;
1055   l = 0;
1056   skip_line = line;
1057
1058   while (true)
1059   {
1060     get_next();
1061
1062     if (cur_cmd == fi_or_else)
1063     {
1064       if (l == 0)
1065         goto lab30;
1066
1067       if (cur_chr == 2)
1068         decr(l);
1069     }
1070     else if (cur_cmd == if_test)
1071       incr(l);
1072   }
1073 lab30:
1074   scanner_status = save_scanner_status;
1075 }
1076 /* sec 0497 */
1077 void change_if_limit_(small_number l, halfword p)
1078 {
1079   halfword q;
1080
1081   if (p == cond_ptr)
1082     if_limit = l;
1083   else
1084   {
1085     q = cond_ptr;
1086
1087     while (true)
1088     {
1089       if (q == 0)
1090       {
1091         confusion("if");
1092         return;
1093       }
1094
1095       if (link(q) == p)
1096       {
1097         type(p) = l;
1098         return;
1099       }
1100
1101       q = link(q);
1102     }
1103   }
1104 }
1105 /* called from tex2.c */
1106 /* sec 0498 */
1107 void conditional (void)
1108 {
1109   boolean b;
1110   char r;
1111   integer m, n;
1112   halfword p, q;
1113   small_number save_scanner_status;
1114   halfword savecondptr;
1115   small_number thisif;
1116
1117   {
1118     p = get_node(if_node_size);
1119     link(p) = cond_ptr;
1120     type(p) = if_limit;
1121     subtype(p) = cur_if;
1122     if_line_field(p) = if_line;
1123     cond_ptr = p;
1124     cur_if = cur_chr;
1125     if_limit = if_code;
1126     if_line = line;
1127   }
1128
1129   savecondptr = cond_ptr;
1130   thisif = cur_chr;
1131
1132   switch (thisif)
1133   {
1134     case if_char_code:
1135     case if_cat_code:
1136       {
1137         {
1138           get_x_token();
1139
1140           if (cur_cmd == relax)
1141             if (cur_chr == no_expand_flag)
1142             {
1143               cur_cmd = active_char;
1144               cur_chr = cur_tok - cs_token_flag - active_base;
1145             }
1146         }
1147
1148         if ((cur_cmd > active_char) || (cur_chr > 255))
1149         {
1150           m = relax;
1151           n = 256;
1152         }
1153         else
1154         {
1155           m = cur_cmd;
1156           n = cur_chr;
1157         }
1158         {
1159           get_x_token();
1160
1161           if (cur_cmd == relax)
1162             if (cur_chr == no_expand_flag)
1163             {
1164               cur_cmd = active_char;
1165               cur_chr = cur_tok - cs_token_flag - active_base;
1166             }
1167         }
1168
1169         if ((cur_cmd > active_char) || (cur_chr > 255))
1170         {
1171           cur_cmd = relax;
1172           cur_chr = 256;
1173         }
1174
1175         if (thisif == if_char_code)
1176           b = (n == cur_chr); 
1177         else
1178           b = (m == cur_cmd);
1179       }
1180       break;
1181
1182     case if_int_code:
1183     case if_dim_code:
1184       {
1185         if (thisif == if_int_code)
1186           scan_int();
1187         else
1188           scan_dimen(false, false, false);
1189
1190         n = cur_val;
1191         
1192         do
1193           {
1194             get_x_token();
1195           }
1196         while (!(cur_cmd != spacer));
1197
1198         if ((cur_tok >= other_token + '<') && (cur_tok <= other_token + '>'))
1199           r = cur_tok - other_token;
1200         else
1201         {
1202           print_err("Missing = inserted for ");
1203           print_cmd_chr(if_test, thisif);
1204           help1("I was expecting to see `<', `=', or `>'. Didn't.");
1205           back_error();
1206           r = '=';
1207         }
1208
1209         if (thisif == if_int_code)
1210           scan_int();
1211         else 
1212           scan_dimen(false, false, false);
1213
1214         switch (r)
1215         {
1216           case '<':
1217             b = (n < cur_val);
1218             break;
1219
1220           case '=':
1221             b = (n == cur_val);
1222             break;
1223
1224           case '>':
1225             b = (n > cur_val);
1226             break;
1227         }
1228       }
1229       break;
1230
1231     case if_odd_code:
1232       scan_int();
1233       b = odd(cur_val);
1234       break;
1235
1236     case if_vmode_code:
1237       b = (abs(mode) == 1);
1238       break;
1239
1240     case if_hmode_code:
1241       b = (abs(mode) == 102);
1242       break;
1243
1244     case if_mmode_code:
1245       b = (abs(mode) == 203);
1246       break;
1247
1248     case if_inner_code:
1249       b = (mode < 0);
1250       break;
1251
1252     case if_void_code:
1253     case if_hbox_code:
1254     case if_vbox_code:
1255       {
1256         scan_eight_bit_int();
1257         p = box(cur_val);
1258
1259         if (thisif == if_void_code)
1260           b = (p == 0);
1261         else if (p == 0)
1262           b = false;
1263         else if (thisif == if_hbox_code)
1264           b = (type(p) == hlist_node);
1265         else
1266           b = (type(p) == vlist_node);
1267       }
1268       break;
1269
1270     case ifx_code:
1271       {
1272         save_scanner_status = scanner_status;
1273         scanner_status = 0;
1274         get_next();
1275         n = cur_cs;
1276         p = cur_cmd;
1277         q = cur_chr;
1278         get_next();
1279
1280         if (cur_cmd != p)
1281           b = false;
1282         else if (cur_cmd < call)
1283           b = (cur_chr == q);
1284         else
1285         {
1286           p = link(cur_chr);
1287           q = link(equiv(n));
1288
1289           if (p == q)
1290             b = true;
1291           else
1292           {
1293             while ((p != 0) && (q != 0))
1294               if (info(p) != info(q))
1295                 p = 0;
1296               else
1297               {
1298                 p = link(p);
1299                 q = link(q);
1300               }
1301
1302             b = ((p == 0) && (q == 0));
1303           }
1304         }
1305
1306         scanner_status = save_scanner_status;
1307       }
1308       break;
1309
1310     case if_eof_code:
1311       {
1312         scan_four_bit_int();
1313         b = (read_open[cur_val] == closed);
1314       }
1315       break;
1316
1317     case if_true_code:
1318       b = true;
1319       break;
1320
1321     case if_false_code:
1322       b = false;
1323       break;
1324
1325     case if_case_code:
1326       {
1327         scan_int();
1328         n = cur_val;
1329
1330         if (tracing_commands > 1)
1331         {
1332           begin_diagnostic();
1333           print_string("{case ");
1334           print_int(n); 
1335           print_char('}');
1336           end_diagnostic(false);
1337         }
1338
1339         while (n != 0)
1340         {
1341           pass_text();
1342
1343           if (cond_ptr == savecondptr)
1344             if (cur_chr == or_code)
1345               decr(n);
1346             else 
1347               goto lab50;
1348           else if (cur_chr == fi_code)
1349           {
1350             p = cond_ptr;
1351             if_line = if_line_field(p);
1352             cur_if = subtype(p);
1353             if_limit = type(p);
1354             cond_ptr = link(p);
1355             free_node(p, if_node_size);
1356           }
1357         }
1358
1359         change_if_limit(or_code, savecondptr);
1360         return;
1361       }
1362       break;
1363   }
1364
1365   if (tracing_commands > 1)
1366   {
1367     begin_diagnostic();
1368
1369     if (b)
1370       print_string("{true}");
1371     else
1372       print_string("{false}");
1373
1374     end_diagnostic(false);
1375   }
1376
1377   if (b)     /* b may be used without ... */
1378   {
1379     change_if_limit(else_code, savecondptr);
1380     return;
1381   }
1382
1383   while (true)
1384   {
1385     pass_text();
1386
1387     if (cond_ptr == savecondptr)
1388     {
1389       if (cur_chr != or_code)
1390         goto lab50;
1391
1392       print_err("Extra ");
1393       print_esc("or");
1394       help1("I'm ignoring this; it doesn't match any \\if.");
1395       error();
1396     }
1397     else if (cur_chr == fi_code)
1398     {
1399       p = cond_ptr;
1400       if_line = if_line_field(p);
1401       cur_if = subtype(p);
1402       if_limit = type(p);
1403       cond_ptr = link(p);
1404       free_node(p, if_node_size);
1405     }
1406   }
1407
1408 lab50:
1409   if (cur_chr == fi_code)
1410   {
1411     p = cond_ptr;
1412     if_line = if_line_field(p);
1413     cur_if = subtype(p);
1414     if_limit = type(p);
1415     cond_ptr = link(p);
1416     free_node(p, if_node_size);
1417   }
1418   else
1419     if_limit = fi_code;
1420 }
1421 /* sec 0515 */
1422 void begin_name (void)
1423 {
1424   area_delimiter = 0;
1425   ext_delimiter = 0;
1426 }
1427 /* This gathers up a file name and makes a string of it */
1428 /* Also tries to break it into `file area' `file name' and `file extension' */
1429 /* Used by scan_file_name and prompt_file_name */
1430 /* We assume tilde has been converted to pseudo_tilde and space to pseudo_space */
1431 /* returns false if it is given a space character - end of file name */
1432 /* sec 0516 */
1433 boolean more_name_(ASCII_code c)
1434 {
1435   if (quoted_file_name == 0 && c == ' ')
1436     return false;
1437   else if (quoted_file_name != 0 && c == '"')
1438   {
1439     quoted_file_name = 0; /* catch next space character */
1440     return true;    /* accept ending quote, but throw away */
1441   }
1442   else
1443   {   
1444     str_room(1);
1445     append_char(c);
1446     //  for DOS/Windows
1447     if ((c == '/' || c == '\\' || c == ':')) 
1448     {
1449       area_delimiter = cur_length;
1450       ext_delimiter = 0;
1451     } 
1452     else if (c == '.')
1453       ext_delimiter = cur_length;
1454
1455     return true;
1456   }
1457 }
1458
1459 /* sec 0517 */
1460 void end_name (void) 
1461 {
1462 #ifdef ALLOCATESTRING
1463   if (str_ptr + 3 > current_max_strings)
1464     str_start = realloc_str_start(increment_max_strings + 3);
1465
1466   if (str_ptr + 3 > current_max_strings)
1467   {
1468     overflow("number of strings", current_max_strings - init_str_ptr);
1469     return;
1470   }
1471 #else
1472   if (str_ptr + 3 > max_strings)
1473   {
1474     overflow("number of strings", max_strings - init_str_ptr);
1475     return;
1476   }
1477 #endif
1478
1479   if (area_delimiter == 0)   // no area delimiter ':' '/' or '\' found
1480     cur_area = 335;     // "" default area 
1481   else
1482   {
1483     cur_area = str_ptr;
1484     str_start[str_ptr + 1] = str_start[str_ptr] + area_delimiter;
1485     incr(str_ptr);
1486   }
1487
1488   if (ext_delimiter == 0) // no extension delimiter '.' found
1489   {
1490     cur_ext = 335;        // "" default extension 
1491     cur_name = make_string();
1492   } 
1493   else            // did find an extension
1494   {
1495     cur_name = str_ptr;
1496     str_start[str_ptr + 1] = str_start[str_ptr]+ ext_delimiter - area_delimiter - 1;
1497     incr(str_ptr);
1498     cur_ext = make_string();
1499   }
1500 }
1501
1502 /* n current name, a current area, e current extension */
1503 /* result in name_of_file[] */
1504 /* sec 0519 */
1505 void pack_file_name_(str_number n, str_number a, str_number e)
1506 {
1507   integer k;
1508   ASCII_code c;
1509   pool_pointer j;
1510
1511   k = 0;
1512
1513   for (j = str_start[a]; j <= str_start[a + 1] - 1; j++)
1514   {
1515     c = str_pool[j];
1516     incr(k);
1517
1518     if (k <= file_name_size)
1519       name_of_file[k] = xchr[c];
1520   }
1521
1522   for (j = str_start[n]; j <= str_start[n + 1] - 1; j++)
1523   {
1524     c = str_pool[j];
1525     incr(k);
1526
1527     if (k <= file_name_size)
1528       name_of_file[k] = xchr[c];
1529   }
1530
1531   for (j = str_start[e]; j <= str_start[e + 1] - 1; j++)
1532   {
1533     c = str_pool[j];
1534     incr(k);
1535
1536     if (k <= file_name_size)
1537       name_of_file[k] = xchr[c];
1538   }
1539
1540   if (k < file_name_size)
1541     name_length = k;
1542   else
1543     name_length = file_name_size - 1;
1544
1545 /*  pad it out with spaces ... what for ? in case we modify and forget  ? */
1546   for (k = name_length + 1; k <= file_name_size; k++)
1547     name_of_file[k] = ' ';
1548
1549   name_of_file[file_name_size] = '\0';    /* paranoia 94/Mar/24 */
1550
1551   {
1552     name_of_file [name_length+1] = '\0';
1553
1554     if (trace_flag)
1555     {
1556       sprintf(log_line, " pack_file_name `%s' (%d) ", name_of_file + 1, name_length); /* debugging */
1557       show_line(log_line, 0);
1558     }
1559
1560     name_of_file [name_length + 1] = ' ';
1561   }
1562 }
1563 /* Called only from two places tex9.c for format name - specified and default */
1564 /* for specified format name args are 0, a, b name in buffer[a] --- buffer[b] */
1565 /* for default args are format_default_length-4, 1, 0 */
1566 /* sec 0523 */
1567 void pack_buffered_name_(small_number n, integer a, integer b)
1568 {
1569   integer k;
1570   ASCII_code c;
1571   integer j;
1572
1573   if (n + b - a + 5 > file_name_size)
1574     b = a + file_name_size - n - 5;
1575
1576   k = 0;
1577
1578 /*  This loop kicks in when we want the default format name */
1579   for (j = 1; j <= n; j++)
1580   {
1581     c = xord[TEX_format_default[j]];
1582     incr(k);
1583
1584     if (k <= file_name_size)
1585       name_of_file[k] = xchr[c];
1586   }
1587 /*  This loop kicks in when we want a specififed format name */
1588   for (j = a; j <= b; j++)
1589   {
1590     c = buffer[j];
1591     incr(k);
1592
1593     if (k <= file_name_size)
1594       name_of_file[k] = xchr[c];
1595   }
1596
1597 /*  This adds the extension from the default format name */
1598   for (j = format_default_length - 3; j <= format_default_length; j++)
1599   {
1600     c = xord[TEX_format_default[j]];
1601     incr(k);
1602
1603     if (k <= file_name_size)
1604       name_of_file[k] = xchr[c];
1605   }
1606
1607   if (k < file_name_size)
1608     name_length = k;
1609   else
1610     name_length = file_name_size - 1;
1611
1612  /*  pad it out with spaces ... what for ? */
1613   for (k = name_length + 1; k <= file_name_size; k++)
1614     name_of_file[k]= ' ';
1615
1616   name_of_file[file_name_size] = '\0';    /* paranoia 94/Mar/24 */
1617 }
1618 /* sec 0525 */
1619 str_number make_name_string (void)
1620 {
1621   integer k;
1622
1623 #ifdef ALLOCATESTRING
1624   if (pool_ptr + name_length > current_pool_size)
1625     str_pool = realloc_str_pool(increment_pool_size + name_length);
1626
1627   if (str_ptr == current_max_strings)
1628     str_start = realloc_str_start(increment_max_strings);
1629
1630   if ((pool_ptr + name_length > current_pool_size) || (str_ptr == current_max_strings) || (cur_length > 0))
1631 #else
1632   if ((pool_ptr + name_length > pool_size) || (str_ptr == max_strings) || (cur_length > 0))
1633 #endif
1634   {
1635     return '?';
1636   }
1637   else
1638   {
1639     for (k = 1; k <= name_length; k++)
1640       append_char(xord[name_of_file[k]]);
1641
1642     return make_string();
1643   }
1644 }
1645 /* sec 0525 */
1646 //str_number a_make_name_string_(alpha_file * f)
1647 str_number a_make_name_string_(void)
1648 {
1649   return make_name_string();
1650 }
1651 /* sec 0525 */
1652 //str_number b_make_name_string_(byte_file * f)
1653 str_number b_make_name_string_(void)
1654 {
1655   return make_name_string(); 
1656 }
1657 /* sec 0525 */
1658 //str_number w_make_name_string_(word_file * f)
1659 str_number w_make_name_string_(void)
1660 {
1661   return make_name_string();
1662 }
1663
1664 /* Used by start_input to scan file name on command line */
1665 /* Also in tex8.c new_font_, open_or_close_in, and do_extension */
1666 /* sec 0526 */
1667 void scan_file_name (void)
1668 {
1669   name_in_progress = true;
1670   begin_name();
1671
1672   do
1673     {
1674       get_x_token(); 
1675     }
1676   while (!(cur_cmd != spacer));
1677
1678   quoted_file_name = false;
1679
1680   if (allow_quoted_names)
1681   {
1682     if (cur_chr == '"')
1683     {
1684       quoted_file_name = 1;
1685       get_x_token();
1686     }
1687   }
1688
1689   while (true)
1690   {
1691     if ((cur_cmd > other_char) || (cur_chr > 255)) 
1692     {
1693       back_input();
1694       goto lab30; 
1695     } 
1696
1697     if (!more_name(cur_chr))    /* up to next white space */
1698       goto lab30;
1699
1700     get_x_token();
1701   }
1702
1703 lab30:
1704   end_name();
1705   name_in_progress = false;
1706 }
1707 /* argument is string .fmt, .log, or .dvi */
1708 /* sec 0529 */
1709 void pack_job_name_(str_number s)
1710 {
1711   cur_area = 335;       /* "" */
1712   cur_ext  = s;
1713   cur_name = job_name;
1714   pack_file_name(cur_name, cur_area, cur_ext);
1715 }
1716
1717 /**********************************************************************/
1718 /* sec 0530 */
1719 /* s - what can't be found, e - default */
1720 void prompt_file_name_(char * s, str_number e) 
1721 {
1722   integer k;
1723
1724   if (interaction == scroll_mode);
1725
1726   if (!strcmp("input file name", s))
1727     print_err("I can't find file `");
1728   else
1729     print_err("I can't write on file `");
1730
1731   print_file_name(cur_name, cur_area, cur_ext);
1732   print_string("'.");
1733
1734   if (e == 785)    /* .tex */
1735     show_context();
1736
1737   print_nl("Please type another ");
1738   print_string(s); 
1739
1740   if (interaction < 2)
1741   {
1742     fatal_error("*** (job aborted, file error in nonstop mode)");
1743     return;
1744   }
1745
1746   if (!knuth_flag)
1747 #ifdef _WINDOWS
1748     show_line(" (or ^z to exit)", 0);
1749 #else
1750     show_line(" (or Ctrl-Z to exit)", 0);
1751 #endif
1752   prompt_input(": ");
1753
1754 /*  should we deal with tilde and space in file name here ??? */
1755   {
1756     begin_name();
1757     k = first;
1758
1759     while ((buffer[k] == ' ') && (k < last))
1760       incr(k);
1761 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1762     quoted_file_name = 0;         /* 98/March/15 */
1763
1764     if (allow_quoted_names && k < last) /* check whether quoted name */
1765     {
1766       if (buffer[k]== '"')
1767       {
1768         quoted_file_name = 1;
1769         incr(k);
1770       }
1771     }
1772
1773     while (true)
1774     {
1775       if (k == last)
1776         goto lab30;
1777 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1778 /*  convert tilde '~' to pseudo tilde */
1779       if (pseudo_tilde != 0 && buffer[k]== '~')
1780         buffer[k] = pseudo_tilde;
1781 /*  convert space ' ' to pseudo space */
1782       if (pseudo_space != 0 && buffer[k]== ' ')
1783         buffer[k] = pseudo_space;
1784 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1785       if (!more_name(buffer[k]))
1786         goto lab30;
1787
1788       incr(k);
1789     }
1790 lab30:
1791     end_name();
1792   }
1793
1794   if (cur_ext == 335)    /* "" */
1795     cur_ext = e;      /* use default extension */
1796
1797   pack_file_name(cur_name, cur_area, cur_ext);
1798 }
1799 /* sec 0534 */
1800 void open_log_file (void)
1801 {
1802   char old_setting;
1803   integer k;
1804   integer l;
1805   char * months;
1806
1807   old_setting = selector;
1808
1809   if (job_name == 0)
1810     job_name = 790;
1811
1812   pack_job_name(".log");
1813
1814   while (!a_open_out(log_file))
1815   {
1816     selector = term_only;
1817     prompt_file_name("transcript file name", ".log");
1818   }
1819
1820   texmf_log_name = a_make_name_string(log_file);
1821   selector = log_only;
1822   log_opened = true;
1823
1824   {
1825     if (want_version)
1826     {
1827       stamp_it(log_line);
1828       strcat(log_line, "\n");
1829       (void) fputs(log_line, log_file);
1830       stampcopy(log_line);
1831       strcat(log_line, "\n");
1832       (void) fputs(log_line, log_file);
1833     }
1834     
1835     fprintf(log_file, "%s (%s %s)", tex_version, application, yandyversion);
1836
1837     if (format_ident > 0)
1838       slow_print(format_ident);
1839
1840     print_string("  ");
1841
1842     if (civilize_flag)
1843       print_int(year);
1844     else
1845       print_int(day);
1846
1847     print_char(' ');
1848     months = " JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
1849
1850     for (k = 3 * month - 2; k <= 3 * month; k++)
1851       (void) putc(months[k],  log_file);
1852
1853     print_char(' ');
1854
1855     if (civilize_flag)
1856       print_int(day);
1857     else
1858       print_int(year);
1859
1860     print_char(' ');
1861     print_two(tex_time / 60);
1862     print_char(':');
1863     print_two(tex_time % 60);
1864   }
1865
1866   input_stack[input_ptr] = cur_input;
1867   print_nl("**");
1868   l = input_stack[0].limit_field;
1869
1870   if (buffer[l] == end_line_char)
1871     decr(l);
1872
1873   for (k = 1; k <= l; k++)
1874     print(buffer[k]);
1875
1876   print_ln(); 
1877
1878   if (show_fmt_flag)
1879   {
1880     if (format_file != NULL)
1881     {
1882       fprintf(log_file, "(%s)\n", format_file);
1883       free(format_file);
1884       format_file = NULL;
1885     }
1886   }
1887
1888   selector = old_setting + 2;
1889 }
1890
1891 // Attempt to deal with foo.bar.tex given as foo.bar on command line
1892 // Makes copy of job_name with extension
1893
1894 void more_name_copy(ASCII_code c)
1895 {
1896 #ifdef ALLOCATESTRING
1897   if (pool_ptr + 1 > current_pool_size)
1898     str_pool = realloc_str_pool (increment_pool_size);
1899
1900   if (pool_ptr + 1 > current_pool_size)
1901   {
1902     overflow("pool size", current_pool_size - init_pool_ptr);
1903     return;
1904   }
1905 #else
1906   if (pool_ptr + 1 > pool_size)
1907   {
1908     overflow("pool size", pool_size - init_pool_ptr);
1909     return;
1910   }
1911 #endif
1912
1913   str_pool[pool_ptr] = c; 
1914   incr(pool_ptr);
1915 }
1916
1917 int end_name_copy(void)
1918 {
1919 #ifdef ALLOCATESTRING
1920   if (str_ptr + 1 > current_max_strings)
1921     str_start = realloc_str_start(increment_max_strings + 1);
1922
1923   if (str_ptr + 1 > current_max_strings)
1924   {
1925     overflow("number of strings", current_max_strings - init_str_ptr);
1926     return 0;
1927   }
1928 #else
1929   if (str_ptr + 1 > max_strings)
1930   {
1931     overflow("number of strings", max_strings - init_str_ptr);
1932     return 0;
1933   }
1934 #endif
1935
1936   return make_string();
1937 }
1938
1939 void job_name_append (void)
1940
1941   int k, n;
1942
1943   k = str_start[job_name];
1944   n = str_start[job_name + 1];
1945
1946   while (k < n)
1947     more_name_copy(str_pool[k++]);
1948
1949   k = str_start[cur_ext];
1950   n = str_start[cur_ext + 1];
1951
1952   while (k < n)
1953     more_name_copy(str_pool[k++]);
1954
1955   job_name = end_name_copy();
1956 }
1957
1958 /* sec 0537 */
1959 void start_input(void)
1960 {
1961   scan_file_name();
1962   pack_file_name(cur_name, cur_area, cur_ext); 
1963
1964   while (true)
1965   {
1966     begin_file_reading();
1967     
1968     if (a_open_in(cur_file, TEXINPUTPATH))
1969       goto lab30;
1970
1971     end_file_reading();
1972     prompt_file_name("input file name", ".tex");
1973   }
1974
1975 lab30: 
1976   cur_input.name_field = a_make_name_string(cur_file);
1977
1978   if (job_name == 0)
1979   {
1980     job_name = cur_name;
1981     open_log_file();
1982   }
1983
1984   if (term_offset + length(cur_input.name_field) > max_print_line - 2)
1985     print_ln();
1986   else if ((term_offset > 0) || (file_offset > 0))
1987     print_char(' ');
1988
1989   print_char('(');
1990   incr(open_parens);
1991
1992   if (open_parens > max_open_parens)
1993     max_open_parens = open_parens;
1994
1995   slow_print(cur_input.name_field);
1996
1997 #ifndef _WINDOWS
1998   fflush(stdout);
1999 #endif
2000
2001   state = new_line;
2002
2003   {
2004     line = 1;
2005
2006     if (input_ln(cur_file, false));
2007
2008     firm_up_the_line();
2009
2010     if (end_line_char_inactive())
2011       decr(limit);
2012     else
2013       buffer[limit] = end_line_char;
2014
2015     first = limit + 1;
2016     loc = start;
2017   }
2018 }
2019 /* sec 0560 */
2020 internal_font_number read_font_info_(halfword u, str_number nom, str_number aire, scaled s)
2021 {
2022   font_index k;
2023   boolean file_opened;
2024   halfword lf, lh, nw, nh, nd, ni, nl, nk, ne, np;
2025   int bc, ec;
2026   internal_font_number f;
2027   internal_font_number g;
2028   eight_bits a, b, c, d;
2029   four_quarters qw;
2030   scaled sw;
2031   integer bch_label;
2032   short bchar;
2033   scaled z;
2034   integer alpha;
2035   char beta;
2036
2037   g = 0;
2038   file_opened = false;
2039   pack_file_name(nom, aire, 805); /* .tfm */
2040
2041   if (!b_open_in(tfm_file))
2042   {
2043     goto lab11;
2044   } 
2045
2046   file_opened = true; 
2047
2048   {
2049     read_sixteen(lf);
2050     tfm_temp = getc(tfm_file);
2051     read_sixteen(lh);
2052     tfm_temp = getc(tfm_file);
2053     read_sixteen(bc);
2054     tfm_temp = getc(tfm_file);
2055     read_sixteen(ec);
2056
2057     if ((bc > ec + 1) || (ec > 255))
2058       goto lab11;
2059
2060     if (bc > 255)
2061     {
2062       bc = 1;
2063       ec = 0;
2064     }
2065
2066     tfm_temp = getc(tfm_file);
2067     read_sixteen(nw);
2068     tfm_temp = getc(tfm_file);
2069     read_sixteen(nh);
2070     tfm_temp = getc(tfm_file);
2071     read_sixteen(nd);
2072     tfm_temp = getc(tfm_file);
2073     read_sixteen(ni);
2074     tfm_temp = getc(tfm_file);
2075     read_sixteen(nl);
2076     tfm_temp = getc(tfm_file);
2077     read_sixteen(nk);
2078     tfm_temp = getc(tfm_file);
2079     read_sixteen(ne);
2080     tfm_temp = getc(tfm_file);
2081     read_sixteen(np);
2082
2083     if (lf != 6 + lh + (ec - bc + 1) + nw + nh + nd + ni + nl + nk + ne + np)
2084       goto lab11;
2085
2086     if ((nw == 0) || (nh == 0) || (nd == 0) || (ni == 0))
2087       goto lab11;
2088   }
2089
2090   lf = lf - 6 - lh;
2091
2092   if (np < 7)
2093     lf = lf + 7 - np;
2094
2095 #ifdef ALLOCATEFONT
2096   if ((fmem_ptr + lf > current_font_mem_size))
2097     font_info = realloc_font_info (increment_font_mem_size + lf);
2098
2099   if ((font_ptr == font_max) || (fmem_ptr + lf > current_font_mem_size))
2100 #else
2101   if ((font_ptr == font_max) || (fmem_ptr + lf > font_mem_size))
2102 #endif
2103   {
2104     if (trace_flag)
2105     {
2106       sprintf(log_line, "font_ptr %d font_max %d fmem_ptr %d lf %d font_mem_size %d\n",
2107           font_ptr, font_max, fmem_ptr, lf, font_mem_size);
2108       show_line(log_line, 0);
2109     }
2110
2111     print_err("Font ");
2112     sprint_cs(u);
2113     print_char('=');
2114     print_file_name(nom, aire, 335); /* "" */
2115
2116     if (s >= 0)
2117     {
2118       print_string(" at ");
2119       print_scaled(s);
2120       print_string("pt");
2121     }
2122     else if (s != -1000)
2123     {
2124       print_string(" scaled ");
2125       print_int(- (integer) s);
2126     }
2127
2128     print_string(" not loaded: Not enough room left");
2129     help4("I'm afraid I won't be able to make use of this font,",
2130         "because my memory for character-size data is too small.",
2131         "If you're really stuck, ask a wizard to enlarge me.",
2132         "Or maybe try `I\\font<same font id>=<name of loaded font>'.");
2133     error();
2134     goto lab30;
2135   }
2136
2137   f = font_ptr + 1;
2138   char_base[f] = fmem_ptr - bc;
2139   width_base[f] = char_base[f] + ec + 1;
2140   height_base[f] = width_base[f] + nw;
2141   depth_base[f] = height_base[f] + nh;
2142   italic_base[f] = depth_base[f] + nd;
2143   lig_kern_base[f] = italic_base[f] + ni;
2144   kern_base[f] = lig_kern_base[f] + nl - 256 * (128);
2145   exten_base[f] = kern_base[f] + 256 * (128) + nk;
2146   param_base[f] = exten_base[f] + ne;
2147
2148   {
2149     if (lh < 2)
2150       goto lab11;
2151     
2152     store_four_quarters(font_check[f]);
2153     tfm_temp = getc(tfm_file);
2154     read_sixteen(z);
2155     tfm_temp = getc(tfm_file);
2156     z = z * 256 + tfm_temp;
2157     tfm_temp = getc(tfm_file);
2158     z =(z * 16) + (tfm_temp / 16);
2159
2160     if (z < unity)
2161       goto lab11; 
2162
2163     while (lh > 2)
2164     {
2165       tfm_temp = getc(tfm_file);
2166       tfm_temp = getc(tfm_file);
2167       tfm_temp = getc(tfm_file);
2168       tfm_temp = getc(tfm_file);
2169       decr(lh);
2170     }
2171
2172     font_dsize[f] = z;
2173
2174     if (s != -1000)
2175       if (s >= 0)
2176         z = s;
2177       else
2178         z = xn_over_d(z, - (integer) s, 1000);
2179
2180     font_size[f] = z;
2181   }
2182
2183   for (k = fmem_ptr; k <= width_base[f] - 1; k++)
2184   {
2185     store_four_quarters(font_info[k].qqqq);
2186
2187     if ((a >= nw) || (b / 16 >= nh) || (b % 16 >= nd) || (c / 4 >= ni))
2188       goto lab11;
2189
2190     switch (c % 4)
2191     {
2192       case lig_tag:
2193         if (d >= nl)
2194           goto lab11;
2195         break;
2196
2197       case ext_tag:
2198         if (d >= ne)
2199           goto lab11;
2200         break;
2201
2202       case list_tag:
2203         {
2204           {
2205             if ((d < bc) || (d > ec))
2206               goto lab11;
2207           }
2208
2209           while (d < k + bc - fmem_ptr)
2210           {
2211             qw = char_info(f, d);
2212  
2213             if (char_tag(qw) != list_tag)
2214               goto lab45;
2215
2216             d = rem_byte(qw);
2217           }
2218
2219           if (d == k + bc - fmem_ptr)
2220             goto lab11;
2221 lab45:; 
2222         }
2223         break;
2224
2225       default:
2226         break;
2227     }
2228   }
2229
2230   {
2231     {
2232       alpha = 16;
2233
2234       while (z >= 8388608L)   /* 2^23 */
2235       {
2236         z = z / 2;
2237         alpha = alpha + alpha;
2238       }
2239
2240       beta = (char) (256 / alpha);
2241       alpha = alpha * z;
2242     }
2243
2244     for (k = width_base[f]; k <= lig_kern_base[f] - 1; k++)
2245     {
2246       tfm_temp = getc(tfm_file);
2247       a = tfm_temp;
2248       tfm_temp = getc(tfm_file);
2249       b = tfm_temp;
2250       tfm_temp = getc(tfm_file);
2251       c = tfm_temp;
2252       tfm_temp = getc(tfm_file);
2253       d = tfm_temp;
2254       sw = (((((d * z) / 256) + (c * z)) / 256) + (b * z)) / beta;
2255
2256       if (a == 0)
2257         font_info[k].cint = sw;
2258       else if (a == 255)
2259         font_info[k].cint = sw - alpha;
2260       else
2261         goto lab11;
2262     }
2263
2264     if (font_info[width_base[f]].cint != 0)
2265       goto lab11;
2266
2267     if (font_info[height_base[f]].cint != 0)
2268       goto lab11;
2269
2270     if (font_info[depth_base[f]].cint != 0)
2271       goto lab11;
2272
2273     if (font_info[italic_base[f]].cint != 0)
2274       goto lab11;
2275   }
2276
2277   bch_label = 32767;     /* '77777 */
2278   bchar = 256;
2279
2280   if (nl > 0)
2281   {
2282     for (k = lig_kern_base[f]; k <= kern_base[f] + 256 * (128) - 1; k++)
2283     {
2284       store_four_quarters(font_info[k].qqqq);
2285
2286       if (a > 128)
2287       {
2288         if (256 * c + d >= nl)
2289           goto lab11;       /* error in TFM, abort */
2290
2291         if (a == 255)
2292           if (k == lig_kern_base[f])
2293             bchar = b;
2294       }
2295       else
2296       {
2297         if (b != bchar)
2298         {
2299           {
2300             if ((b < bc) || (b > ec))  /* check-existence(b) */
2301               goto lab11;         /* error in TFM, abort */
2302           }
2303
2304           qw = font_info[char_base[f] + b].qqqq;
2305
2306           if (!(qw.b0 > 0))
2307             goto lab11;         /* error in TFM, abort */
2308         }
2309
2310         if (c < 128)
2311         {
2312           {
2313             if ((d < bc) || (d > ec))  /* check-existence(d) */
2314               goto lab11;         /* error in TFM, abort */
2315           }
2316
2317           qw = font_info[char_base[f] + d].qqqq;
2318
2319           if (!(qw.b0 > 0))
2320             goto lab11;         /* error in TFM, abort */
2321         }
2322         else if (256 * (c - 128) + d >= nk)
2323           goto lab11;           /* error in TFM, abort */
2324
2325         if (a < 128)
2326           if (k - lig_kern_base[f] + a + 1 >= nl)
2327             goto lab11;         /* error in TFM, abort */
2328       }
2329     }
2330
2331     if (a == 255)
2332       bch_label = 256 * c + d;
2333   }
2334
2335   for (k = kern_base[f] + 256 * (128); k <= exten_base[f] - 1; k++)
2336   {
2337     tfm_temp = getc(tfm_file);
2338     a = tfm_temp;
2339     tfm_temp = getc(tfm_file);
2340     b = tfm_temp;
2341     tfm_temp = getc(tfm_file);
2342     c = tfm_temp;
2343     tfm_temp = getc(tfm_file);
2344     d = tfm_temp;
2345     sw = (((((d * z) / 256) + (c * z)) / 256) + (b * z)) / beta;
2346
2347     if (a == 0)
2348       font_info[k].cint = sw;
2349     else if (a == 255)
2350       font_info[k].cint = sw - alpha;
2351     else goto lab11;
2352   }
2353
2354   /*  read extensible character recipes */
2355   for (k = exten_base[f]; k <= param_base[f] - 1; k++)
2356   {
2357     store_four_quarters(font_info[k].qqqq);
2358
2359     if (a != 0)
2360     {
2361       {
2362         if ((a < bc) || (a > ec))
2363           goto lab11;
2364       }
2365
2366       qw = font_info[char_base[f] + a].qqqq;
2367
2368       if (!(qw.b0 > 0))
2369         goto lab11;
2370     }
2371
2372     if (b != 0)
2373     {
2374       {
2375         if ((b < bc) || (b > ec))
2376           goto lab11;
2377       }
2378
2379       qw = font_info[char_base[f] + b].qqqq;
2380
2381       if (!(qw.b0 > 0))
2382         goto lab11;
2383     }
2384
2385     if (c != 0)
2386     {
2387       {
2388         if ((c < bc) || (c > ec))
2389           goto lab11;
2390       }
2391
2392       qw = font_info[char_base[f] + c].qqqq;
2393
2394       if (!(qw.b0 > 0))
2395         goto lab11;
2396     }
2397
2398     {
2399       {
2400         if ((d < bc) || (d > ec))
2401           goto lab11;
2402       }
2403
2404       qw = font_info[char_base[f] + d].qqqq;
2405
2406       if (!(qw.b0 > 0))
2407         goto lab11;
2408     }
2409   }
2410
2411   {
2412     for (k = 1; k <= np; k++)
2413       if (k == 1)
2414       {
2415         tfm_temp = getc(tfm_file);
2416         sw = tfm_temp;
2417
2418         if (sw > 127)
2419           sw = sw - 256;
2420
2421         tfm_temp = getc(tfm_file);
2422         sw = sw * 256 + tfm_temp;
2423         tfm_temp = getc(tfm_file);
2424         sw = sw * 256 + tfm_temp;
2425         tfm_temp = getc(tfm_file);
2426         font_info[param_base[f]].cint = (sw * 16) + (tfm_temp / 16);
2427       }
2428       else
2429       {
2430         tfm_temp = getc(tfm_file);
2431         a = tfm_temp;
2432         tfm_temp = getc(tfm_file);
2433         b = tfm_temp;
2434         tfm_temp = getc(tfm_file);
2435         c = tfm_temp;
2436         tfm_temp = getc(tfm_file);
2437         d = tfm_temp;
2438         sw = (((((d * z) / 256) + (c * z)) / 256) + (b * z)) / beta;
2439
2440         if (a == 0)
2441           font_info[param_base[f] + k - 1].cint = sw;
2442         else if (a == 255)
2443           font_info[param_base[f] + k - 1].cint = sw - alpha;
2444         else goto lab11;
2445       }
2446
2447     if (feof(tfm_file))
2448       goto lab11;
2449
2450     for (k = np + 1; k <= 7; k++)
2451       font_info[param_base[f] + k - 1].cint = 0;
2452   }
2453
2454   if (np >= 7)
2455     font_params[f] = np;
2456   else
2457     font_params[f] = 7;
2458
2459   hyphen_char[f] = default_hyphen_char;
2460   skew_char[f] = default_skew_char;
2461
2462   if (bch_label < nl)
2463     bchar_label[f] = bch_label + lig_kern_base[f];
2464   else
2465     bchar_label[f] = non_address;
2466
2467   font_bchar[f] = bchar;
2468   font_false_bchar[f] = bchar;
2469
2470   if (bchar <= ec)
2471     if (bchar >= bc)
2472     {
2473       qw = font_info[char_base[f] + bchar].qqqq;
2474
2475       if ((qw.b0 > 0))
2476         font_false_bchar[f] = 256;
2477     }
2478
2479   font_name[f] = nom;
2480   font_area[f] = aire;
2481   font_bc[f] = bc;
2482   font_ec[f] = ec;
2483   font_glue[f] = 0;
2484   char_base[f] = char_base[f];
2485   width_base[f] = width_base[f];
2486   lig_kern_base[f] = lig_kern_base[f];
2487   kern_base[f] = kern_base[f];
2488   exten_base[f] = exten_base[f];
2489   decr(param_base[f]);
2490   fmem_ptr = fmem_ptr + lf;
2491   font_ptr = f;
2492   g = f;
2493   goto lab30;
2494
2495 lab11:
2496   print_err("Font ");
2497   sprint_cs(u); 
2498   print_char('=');
2499   print_file_name(nom, aire, 335);
2500
2501   if (s >= 0)
2502   {
2503     print_string(" at ");
2504     print_scaled(s);
2505     print_string("pt");
2506   }
2507   else if (s != -1000)
2508   {
2509     print_string("scaled");
2510     print_int(- (integer) s);
2511   } 
2512
2513   if (file_opened)
2514     print_string(" not loadable: Bad metric (TFM) file");
2515   else
2516     print_string(" not loadable: Metric (TFM) file not found");
2517
2518   help5("I wasn't able to read the size data for this font,",
2519       "so I will ignore the font specification.",
2520       "[Wizards can fix TFM files using TFtoPL/PLtoTF.]",
2521       "You might try inserting a different font spec;",
2522       "e.g., type `I\\font<same font id>=<substitute font name>'.");
2523   error();
2524
2525 lab30:
2526   if (file_opened)
2527     b_close(tfm_file);
2528
2529   return g;
2530 }