OSDN Git Service

redesigning header.
[putex/putex.git] / src / texsourc / tex0.c
1
2 #pragma warning(disable:4996)
3 #pragma warning(disable:4131) // old style declarator
4 #pragma warning(disable:4135) // conversion between different integral types 
5 #pragma warning(disable:4127) // conditional expression is constant
6
7 #define EXTERN extern
8
9 #include "texd.h"
10
11 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
12 void synch_h(void)
13 {
14   if (cur_h != dvi_h)
15   {
16     movement(cur_h - dvi_h, right1);
17     dvi_h = cur_h;
18   }
19 }
20 void synch_v(void)
21 {
22   if (cur_v != dvi_v)
23   {
24     movement(cur_v - dvi_v, down1);
25     dvi_v = cur_v;
26   }
27 }
28 void set_cur_lang(void)
29 {
30   if (language <= 0)
31     cur_lang = 0;
32   else if (language > 255)
33     cur_lang = 0;
34   else
35     cur_lang = language;
36 }
37 INLINE void free_avail_(halfword p)
38 {
39   link(p) = avail;
40   avail = p;
41 #ifdef STAT
42   decr(dyn_used);
43 #endif /* STAT */
44 }
45 INLINE void dvi_out_(ASCII_code op)
46 {
47   dvi_buf[dvi_ptr] = op;
48   incr(dvi_ptr);
49   if (dvi_ptr == dvi_limit)
50     dvi_swap();
51 }
52 INLINE void succumb (void)
53 {
54   if (interaction == error_stop_mode)
55     interaction = scroll_mode;
56
57   if (log_opened)
58   {
59     error();
60   }
61 #ifdef DEBUG
62   if (interaction > 0)
63     debug_help();
64 #endif
65   history = 3;
66   jump_out();
67 }
68 INLINE void flush_string (void)
69 {
70   decr(str_ptr);
71   pool_ptr = str_start[str_ptr];
72 }
73 INLINE void append_char (ASCII_code c)
74 {
75   str_pool[pool_ptr] = c;
76   incr(pool_ptr);
77 }
78 INLINE void append_lc_hex (ASCII_code c)
79 {
80   if (c < 10)
81     append_char(c + '0');
82   else
83     append_char(c - 10 + 'a');
84 }
85 INLINE void print_err (const char * s)
86 {
87   if (interaction == error_stop_mode);
88     print_nl("! ");
89   print_string(s);
90 }
91 INLINE void tex_help (unsigned int n, ...)
92 {
93   int i;
94   va_list help_arg;
95
96   if (n > 6)
97     n = 6;
98
99   help_ptr = n;
100   va_start(help_arg, n);
101
102   for (i = n - 1; i > -1; --i)
103     help_line[i] = va_arg(help_arg, char *);
104
105   va_end(help_arg);
106 }
107 INLINE void str_room_ (int val)
108 {
109 #ifdef ALLOCATESTRING
110   if (pool_ptr + val > current_pool_size)
111     str_pool = realloc_str_pool(increment_pool_size);
112
113   if (pool_ptr + val > current_pool_size)
114   {
115     overflow("pool size", current_pool_size - init_pool_ptr);
116   }
117 #else
118   if (pool_ptr + val > pool_size)
119   {
120     overflow("pool size", pool_size - init_pool_ptr);
121   }
122 #endif
123 }
124 INLINE void tail_append_ (pointer val)
125 {
126   link(tail) = val;
127   tail = link(tail);
128 }
129 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
130
131 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
132 /* sec 0058 */
133 void print_ln (void)
134 {
135   switch (selector)
136   {
137     case term_and_log:
138       show_char('\n');
139       term_offset = 0;
140       (void) putc ('\n', log_file);
141       file_offset = 0;
142       break;
143
144     case log_only:
145       (void) putc ('\n',  log_file);
146       file_offset = 0;
147       break;
148
149     case term_only:
150       show_char('\n');
151       term_offset = 0;
152       break;
153
154     case no_print:
155     case pseudo:
156     case new_string:
157       break;
158
159     default:
160       (void) putc ('\n', write_file[selector]);
161       break;
162   }
163 }
164 /* sec 0058 */
165 void print_char_ (ASCII_code s)
166 {
167   if (s == new_line_char)
168   {
169     if (selector < pseudo)
170     {
171       print_ln();
172       return;
173     }
174   }
175
176   switch (selector)
177   {
178     case term_and_log:
179       (void) show_char(Xchr(s));
180       incr(term_offset);
181       (void) putc(Xchr(s), log_file);
182       incr(file_offset);
183
184       if (term_offset == max_print_line)
185       {
186         show_char('\n');
187         term_offset = 0;
188       }
189       
190       if (file_offset == max_print_line)
191       {
192         (void) putc ('\n', log_file);
193         file_offset = 0;
194       }
195
196       break;
197
198     case log_only:
199       (void) putc(Xchr(s), log_file);
200       incr(file_offset);
201
202       if (file_offset == max_print_line)
203         print_ln();
204
205       break;
206
207     case term_only:
208       (void) show_char(Xchr(s));
209       incr(term_offset);
210
211       if (term_offset == max_print_line)
212         print_ln();
213
214       break;
215
216     case no_print:
217       break;
218
219     case pseudo:
220       if (tally < trick_count)
221         trick_buf[tally % error_line] = s;
222
223       break;
224
225     case new_string:
226 #ifdef ALLOCATESTRING
227       if (pool_ptr + 1 > current_pool_size)
228       {
229         str_pool = realloc_str_pool (increment_pool_size);
230       }
231       
232       if (pool_ptr < current_pool_size)
233       {
234         str_pool[pool_ptr]= s;
235         incr(pool_ptr);
236       }
237 #else
238       if (pool_ptr < pool_size)
239       {
240         str_pool[pool_ptr]= s;
241         incr(pool_ptr);
242       }
243 #endif
244       break;
245
246     default:
247       (void) putc(Xchr(s), write_file[selector]);
248       break;
249   }
250
251   incr(tally);
252 }
253 /* sec 0059 */
254 void print_ (integer s)
255 {
256   pool_pointer j;
257   integer nl;
258
259   if (s >= str_ptr)
260     s = 259; /* ??? */
261   else 
262   {
263     if (s < 256)
264     {
265       if (s < 0)
266         s = 259; /* ??? */
267       else
268       {
269         if (selector > pseudo)
270         {
271           print_char(s);
272           return;
273         }
274
275         if ((s == new_line_char))
276           if (selector < pseudo)
277           {
278             print_ln();
279             return;
280           }
281           
282           nl = new_line_char;
283           new_line_char = -1;
284 /* translate ansi to dos 850 */
285           if (!show_in_hex && s < 256 && s >= 32)
286           {
287             if (show_in_dos && s > 127)
288             {
289               if (wintodos[s - 128] > 0)
290               {
291                 print_char (wintodos[s - 128]);
292               }
293               else
294               {
295                 j = str_start[s];
296
297                 while (j < str_start[s + 1])
298                 {
299                   print_char(str_pool[j]);
300                   incr(j);
301                 }
302               }
303             }
304             else
305             {
306               print_char(s);       /* don't translate to hex */
307             }
308           }
309           else
310           {                       /* not just a character */
311             j = str_start[s];
312
313             while (j < str_start[s + 1])
314             {
315               print_char(str_pool[j]);
316               incr(j);
317             }
318           }
319           new_line_char = nl; /* restore eol */
320           return;
321       }
322     }
323   }
324 /*  we get here with s > 256 - i.e. not a single character */
325   j = str_start[s];
326
327   while (j < str_start[s + 1])
328   {
329     print_char(str_pool[j]);
330     incr(j);
331   }
332 }
333 /* string version print. */
334 void print_string_ (unsigned char *s)
335 {
336   while (*s > 0)
337     print_char(*s++);
338 }
339 /* sec 0060 */
340 // print string number s from string pool by calling print_
341 void slow_print_ (integer s)
342 {
343   pool_pointer j;
344
345   if ((s >= str_ptr) || (s < 256))
346   {
347     print(s);
348   }
349   else
350   {
351     j = str_start[s];
352
353     while (j < str_start[s + 1])
354     {
355       print(str_pool[j]);
356       incr(j);
357     }
358   }
359 }
360 /* sec 0062 */
361 // print newline followed by string number s (unless at start of line)
362 void print_nl_ (const char * s)
363 {
364   if (((term_offset > 0) && (odd(selector))) ||
365       ((file_offset > 0) && (selector >= log_only)))
366     print_ln();
367
368   print_string(s);
369 }
370 /* sec 0063 */
371 // print string number s preceded by escape character
372 void print_esc_ (const char * s)
373 {
374   integer c;
375
376   c = escape_char;
377
378   if (c >= 0)
379     if (c < 256)
380       print(c);
381
382   print_string(s);
383 }
384 /* sec 0064 */
385 void print_the_digs_ (eight_bits k)
386 {
387   while (k > 0)
388   {
389     decr(k);
390
391     if (dig[k] < 10)
392       print_char('0' + dig[k]);
393     else
394       print_char('A' + dig[k]);
395   }
396 }
397 /* sec 0065 */
398 void print_int_ (integer n)
399 {
400   char k;
401   integer m;
402
403   k = 0;
404
405   if (n < 0)
406   {
407     print_char('-');
408
409     if (n > -100000000L)
410       n = - (integer) n;
411     else
412     {
413       m = -1 - n;
414       n = m / 10;
415       m = (m % 10) + 1;
416       k = 1;
417
418       if (m < 10)
419         dig[0] = (char) m;
420       else
421       {
422         dig[0] = 0;
423         incr(n);
424       }
425     }
426   }
427
428   do
429     {
430       dig[k] = (char) (n % 10);
431       n = n / 10;
432       incr(k);
433     }
434   while (!(n == 0));
435
436   print_the_digs(k);
437 }
438 /* sec 0262 */
439 void print_cs_ (integer p)
440 {
441   if (p < hash_base)
442     if (p >= single_base)
443       if (p == null_cs)
444       {
445         print_esc("csname");
446         print_esc("endcsname");
447         print_char(' ');
448       }
449       else
450       {
451         print_esc(""); print(p - single_base);
452
453         if (cat_code(p - single_base) == letter)
454           print_char(' ');
455       }
456     else if (p < active_base)
457       print_esc("IMPOSSIBLE.");
458     else print(p - active_base);
459   else if (p >= undefined_control_sequence)
460     print_esc("IMPOSSIBLE.");
461   else if ((text(p) >= str_ptr))
462     print_esc("NONEXISTENT.");
463   else
464   {
465     print_esc(""); print(text(p));
466     print_char(' ');
467   }
468 }
469 /* sec 0263 */
470 void sprint_cs_(halfword p)
471
472   if (p < hash_base)
473     if (p < single_base)
474       print(p - active_base);
475     else if (p < null_cs)
476     {
477       print_esc(""); print(p - single_base);
478     }
479     else
480     {
481       print_esc("csname");
482       print_esc("endcsname");
483     }
484   else
485   {
486     print_esc(""); print(text(p));
487   }
488 }
489 /* sec 0518 */
490 /* ! I can't find file `  c:/foo/  accents  .tex  '. */
491 void print_file_name_(integer n, integer a, integer e)
492 {
493   slow_print(a);
494   slow_print(n);
495   slow_print(e);
496 }
497 /* sec 0699 */
498 void print_size_ (integer s)
499
500   if (s == 0)
501     print_esc("textfont");
502   else if (s == 16)
503     print_esc("scriptfont");
504   else
505     print_esc("scriptscriptfont");
506
507 /* sec 1355 */
508 void print_write_whatsit_(str_number s, halfword p)
509 {
510   print_esc(""); print(s);
511   if (write_stream(p) < 16)
512     print_int(write_stream(p)); 
513   else if (write_stream(p) == 16)
514     print_char('*');
515   else print_char('-');
516 }
517 /* sec 0081 */
518 // called from itex.c and tex0.c only  NASTY NASTY!
519 // now uses uses non-local goto (longjmp) 1999/Nov/7
520 void jump_out (void) 
521 {
522   close_files_and_terminate();
523
524   {
525     int code;
526
527 #ifndef _WINDOWS
528     fflush(stdout); 
529 #endif
530
531     ready_already = 0;
532
533     if (trace_flag)
534       show_line("EXITING at JUMPOUT\n", 0);
535
536     if ((history != 0) && (history != 1))
537       code = 1;
538     else
539       code = 0;
540
541     uexit(code);
542   }
543 }
544 /* sec 0082 */
545 // deal with error by asking for user response 0-9, D, E, H, I, X, Q, R, S
546 // NOTE: this may JUMPOUT either via X, or because of too many errors
547 void error (void)
548 {
549   ASCII_code c;
550   integer s1, s2, s3, s4;
551
552   if (history < error_message_issued)
553     history = error_message_issued;
554
555   print_char('.');
556   show_context();
557
558   if (interaction == error_stop_mode)
559     while (true)
560     {
561 lab22:
562       clear_for_error_prompt();
563
564       { /* prompt_input */
565         print_string("? ");
566         term_input("? ", help_ptr);
567       }
568
569       if (last == first)
570         return; // no input
571
572       c = buffer[first];   // analyze first letter typed
573
574       if (c >= 'a')         // uppercase letter first
575         c = (unsigned char) (c + 'A' - 'a'); 
576
577       switch (c)
578       {
579         case '0':
580         case '1':
581         case '2':
582         case '3':
583         case '4':
584         case '5':
585         case '6':
586         case '7':
587         case '8':
588         case '9':
589           if (deletions_allowed)
590           {
591             s1 = cur_tok;
592             s2 = cur_cmd;
593             s3 = cur_chr;
594             s4 = align_state;
595             align_state = 1000000L;
596             OK_to_interrupt = false;
597
598             if ((last > first + 1) && (buffer[first + 1] >= '0') && (buffer[first + 1] <= '9'))
599               c = (unsigned char) (c * 10 + buffer[first + 1] - '0' * 11);
600             else
601               c = (unsigned char) (c - 48);
602             
603             while (c > 0)
604             {
605               get_token();
606               decr(c);
607             }
608
609             cur_tok = s1;
610             cur_cmd = s2;
611             cur_chr = s3;
612             align_state = s4;
613             OK_to_interrupt = true;
614             help2("I have just deleted some text, as you asked.",
615                 "You can now delete more, or insert, or whatever.");
616             show_context();
617             goto lab22;     /* loop again */
618           }
619           break;
620
621 #ifdef DEBUG
622         case 'D':
623           {
624             debug_help();
625             goto lab22;       /* loop again */
626           }
627           break;
628 #endif /* DEBUG */
629         case 'E':
630           if (base_ptr > 0)
631           {
632             edit_name_start = str_start[input_stack[base_ptr].name_field];
633             edit_name_length = length(input_stack[base_ptr].name_field);
634             edit_line = line;
635             jump_out();
636           }
637           break;
638
639         case 'H':
640           {
641             if (use_err_help)
642             {
643               give_err_help();
644               use_err_help = false;
645             }
646             else
647             {
648               if (help_ptr == 0)
649                 help2("Sorry, I don't know how to help in this situation.",
650                     "Maybe you should try asking a human?");
651               do {
652                 decr(help_ptr);
653                 print_string(help_line[help_ptr]);
654                 print_ln();
655               } while (!(help_ptr == 0));
656             }
657
658             help4("Sorry, I already gave what help I could...",
659                 "Maybe you should try asking a human?",
660                 "An error might have occurred before I noticed any problems.",
661                 "``If all else fails, read the instructions.''");
662             goto lab22; /* loop again */
663           }
664           break;
665
666         case 'I':
667           {
668             begin_file_reading();
669
670             if (last > first + 1)
671             {
672               cur_input.loc_field = first + 1;
673               buffer[first] = 32;
674             }
675             else
676             {
677               { /* prompt_input */
678                 print_string("insert>");
679                 term_input("insert>", 0);
680               }
681               cur_input.loc_field = first;
682             }
683             first = last;
684             cur_input.limit_field = last - 1;
685             return;
686           }
687           break;
688
689         case 'Q':
690         case 'R':
691         case 'S':
692           {
693             error_count = 0; 
694             interaction = 0 + c - 81; /* Q = 0, R = 1, S = 2, T = 3 */
695             print_string("OK, entering ");
696
697             switch (c)
698             {
699               case 'Q':
700                 print_esc("batchmode");
701                 decr(selector);
702                 break;
703               case 'R':
704                 print_esc("nonstopmode");
705                 break;
706               case 'S':
707                 print_esc("scrollmode");
708                 break;
709             }
710
711             print_string("...");
712             print_ln();
713 #ifndef _WINDOWS
714             fflush(stdout);
715 #endif
716             return;
717           }
718           break;
719
720         case 'X':
721           {
722             interaction = 2;
723             jump_out();
724           }
725           break;
726
727         default:
728           break;
729       }           /* end of switch analysing response character */
730
731       {
732         print_string("Type <return> to proceed, S to scroll future error messages,");
733         print_nl("R to run without stopping, Q to run quietly,");
734         print_nl("I to insert something, ");
735
736         if (base_ptr > 0)
737           print_string("E to edit your file,");
738
739         if (deletions_allowed)
740           print_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
741
742         print_nl("H for help, X to quit.");
743       }
744     } /* end of while(true) loop */
745
746   incr(error_count);
747
748   if (error_count == 100)
749   {
750     print_nl("(That makes 100 errors; please try again.)");
751     history = 3;
752     jump_out();
753   }
754
755   if (interaction > batch_mode)
756     decr(selector);
757
758   if (use_err_help)
759   {
760     print_ln();
761     give_err_help();
762   }
763   else while(help_ptr > 0)
764   {
765     decr(help_ptr);
766     print_nl(help_line[help_ptr] == NULL ? "" : help_line[help_ptr]);
767   }
768
769   print_ln();
770
771   if (interaction > batch_mode)
772     incr(selector);
773   
774   print_ln();
775 }
776 /* sec 0093 */
777 void fatal_error_(char * s)
778 {
779   normalize_selector();
780   print_err("Emergency stop");
781   help1(s);
782   succumb();
783 }
784 /* sec 0094 */
785 void overflow_(char * s, integer n)
786 {
787   normalize_selector();
788   print_err("TeX capacity exceeded, sorry [");
789   print_string(s);
790   print_char('=');
791   print_int(n);
792   print_char(']');
793   help2("If you really absolutely need more capacity,",
794       "you can ask a wizard to enlarge me.");
795
796   if (!knuth_flag)
797   {
798     if (!strcmp(s, "pattern memory") && n == trie_size)
799     {
800       sprintf(log_line, "\n  (Maybe use -h=... on command line in ini-TeX)\n");
801       show_line(log_line, 0);
802     }
803     else if (!strcmp(s, "exception dictionary") && n == hyphen_prime)
804     {
805       sprintf(log_line, "\n  (Maybe use -e=... on command line in ini-TeX)\n");
806       show_line(log_line, 0);
807     }
808   }
809
810   succumb();
811 }
812 /* sec 0095 */
813 void confusion_(char * s)
814 {
815   normalize_selector();
816
817   if (history < error_message_issued)
818   {
819     print_err("This can't happen (");
820     print_string(s);
821     print_char(')');
822     help1("I'm broken. Please show this to someone who can fix can fix");
823   }
824   else
825   {
826     print_err("I can't go on meeting you like this");
827     help2("One of your faux pas seems to have wounded me deeply...",
828         "in fact, I'm barely conscious. Please fix it and try again.");
829   }
830
831   succumb();
832 }
833 /* sec 0037 */
834 bool init_terminal (void)
835 {
836   int flag;
837
838   t_open_in();
839
840   if (last > first)
841   {
842     cur_input.loc_field = first;
843
844     while((cur_input.loc_field < last) && (buffer[cur_input.loc_field]== ' '))
845       incr(cur_input.loc_field);    // step over initial white space
846
847     if (cur_input.loc_field < last)
848       return true;
849   }
850
851 // failed to find input file name
852   while (true)
853   {
854 #ifdef _WINDOWS
855     flag = ConsoleInput("**", "Please type a file name or a control sequence\r\n(or ^z to exit)", (char *) &buffer[first]);
856     last = first + strlen((char *) &buffer[first]); /* -1 ? */
857 //    may need to be more elaborate see input_line in texmf.c
858 #else
859     (void) fputs("**", stdout);
860     fflush(stdout);
861     flag = input_ln(stdin, true);
862 #endif
863
864     if (!flag)
865     {
866       show_char('\n');
867       show_line("! End of file on the terminal... why?\n", 1);
868       return false;
869     }
870
871     cur_input.loc_field = first;
872
873     while ((cur_input.loc_field < last) && (buffer[cur_input.loc_field]== ' '))
874       incr(cur_input.loc_field);    // step over intial white space
875
876     if (cur_input.loc_field < last)
877       return true;
878
879     sprintf(log_line, "%s\n", "Please type the name of your input file.");
880     show_line(log_line, 1);
881   }
882 }
883 /* sec 0043 */
884 // Make string from str_start[str_ptr] to pool_ptr
885 str_number make_string (void)
886 {
887 #ifdef ALLOCATESTRING
888   if (str_ptr == current_max_strings)
889     str_start = realloc_str_start(increment_max_strings);
890
891   if (str_ptr == current_max_strings)
892   {
893     overflow("number of strings", current_max_strings - init_str_ptr); /* 97/Mar/9 */
894     return 0;     // abort_flag set
895   }
896 #else
897   if (str_ptr == max_strings)
898   {
899     overflow("number of strings", max_strings - init_str_ptr);
900     return 0;     // abort_flag set
901   }
902 #endif
903   incr(str_ptr);
904   str_start[str_ptr] = pool_ptr;
905
906   return (str_ptr - 1);
907 }
908 /* sec 0044 */
909 bool str_eq_buf_ (str_number s, integer k)
910 {
911   register bool Result;
912   pool_pointer j;
913   bool result;
914
915   j = str_start[s];
916
917   while (j < str_start[s + 1])
918   {
919     if (str_pool[j] != buffer[k])
920     {
921       result = false;
922       goto lab45;
923     }
924
925     incr(j);
926     incr(k);
927   }
928   result = true;
929 lab45:
930   Result = result;
931   return Result;
932 }
933 /* sec 0045 */
934 bool str_eq_str_ (str_number s, str_number t)
935 {
936   register bool Result;
937   pool_pointer j, k;
938   bool result;
939
940   result = false;
941
942   if (length(s) != length(t))
943     goto lab45;
944
945   j = str_start[s];
946   k = str_start[t];
947
948   while (j < str_start[s + 1])
949   {
950     if (str_pool[j] != str_pool[k])
951       goto lab45;
952
953     incr(j);
954     incr(k);
955   }
956   result = true;
957 lab45:
958   Result = result;
959   return Result;
960 }
961 /* sec 0066 */
962 void print_two_(integer n)
963
964   n = abs(n) % 100;
965   print_char('0' + (n / 10));
966   print_char('0' + (n % 10));
967
968 /* sec 0067 */
969 void print_hex_(integer n)
970 {
971   char k;
972
973   k = 0;
974   print_char('"');
975
976   do
977     {
978       dig[k] = (unsigned char) (n % 16);
979       n = n / 16;
980       incr(k);
981     }
982   while (!(n == 0));
983
984   print_the_digs(k);
985 }
986 /* sec 0069 */
987 void print_roman_int_(integer n)
988 {
989   pool_pointer j, k;
990   nonnegative_integer u, v;
991
992   j = str_start[260]; /*  m2d5c2l5x2v5i */
993   v = 1000;
994
995   while (true)
996   {
997     while (n >= v)
998     {
999       print_char(str_pool[j]);
1000       n = n - v;
1001     }
1002
1003     if (n <= 0)
1004       return;
1005
1006     k = j + 2;
1007     u = v / (str_pool[k - 1] - '0');
1008
1009     if (str_pool[k - 1] == 50)
1010     {
1011       k = k + 2;
1012       u = u / (str_pool[k - 1] - '0');
1013     }
1014
1015     if (n + u >= v)
1016     {
1017       print_char(str_pool[k]);
1018       n = n + u;
1019     }
1020     else
1021     {
1022       j = j + 2;
1023       v = v / (str_pool[j - 1] - '0');
1024     }
1025   }
1026 }
1027 /* sec 0070 */
1028 void print_current_string (void)
1029 {
1030   pool_pointer j;
1031
1032   j = str_start[str_ptr];
1033
1034   while (j < pool_ptr)
1035   {
1036     print_char(str_pool[j]);
1037     incr(j);
1038   }
1039 }
1040
1041 int stringlength (int str_ptr)
1042 {
1043   return (str_start[str_ptr + 1] - str_start[str_ptr]) + 2;
1044 }
1045
1046 char * add_string (char *s, char * str_string)
1047 {
1048   int n;
1049
1050   n = strlen(str_string);
1051   memcpy(s, &str_string, n);
1052   s += n;
1053   strcpy(s, "\r\n");
1054   s += 2;
1055   return s;
1056 }
1057
1058 int addextrahelp = 1;
1059
1060 // make one long \r\n separated string out of help lines 
1061 // str_pool is packed_ASCII_code *
1062
1063 char * make_up_help_string (int nhelplines)
1064 {
1065   char * helpstring, *s;
1066   int k, nlen = 0;
1067   
1068 //  get length of help for this specific message
1069   for (k = nhelplines - 1; k >= 0; k--)
1070   {
1071     nlen += strlen(help_line[k]);
1072   }
1073
1074   nlen += 2; // for blank line separator: "\r\n"
1075
1076   if (addextrahelp)
1077   {
1078     nlen += stringlength(265);
1079     nlen += stringlength(266);
1080     nlen += stringlength(267);
1081
1082     if (base_ptr > 0)
1083       nlen += stringlength(268);
1084
1085     if (deletions_allowed)
1086       nlen += stringlength(269);
1087
1088     nlen += stringlength(270);
1089   }
1090
1091   helpstring = (char *) malloc(nlen + 1); // +1 = '\0'
1092   s = helpstring;
1093
1094   for (k = nhelplines-1; k >= 0; k--)
1095   {
1096     s = add_string(s, help_line[k]);
1097   }
1098
1099   if (addextrahelp)
1100   {
1101     strcpy(s, "\r\n");
1102     s += 2;
1103     s = add_string(s, "Type <return> to proceed, S to scroll future error messages,");
1104     s = add_string(s, "R to run without stopping, Q to run quietly,");
1105     s = add_string(s, "I to insert something, ");
1106
1107     if (base_ptr > 0)
1108       s = add_string(s, "E to edit your file, ");
1109
1110     if (deletions_allowed)
1111       s = add_string(s, "1 or ... or 9 to ignore the next 1 to 9 tokens of input,");
1112
1113     s = add_string(s, "H for help, X to quit.");
1114   }
1115
1116   return helpstring;
1117 }
1118
1119 char * make_up_query_string (int promptstr)
1120 {
1121   char *querystr;
1122   int nstart, nnext, n;
1123   char *s;
1124
1125   nstart = str_start[ promptstr];
1126   nnext = str_start[ promptstr + 1];
1127   n = nnext - nstart;
1128   querystr = (char *) malloc(n + 1);
1129   s = querystr;
1130   memcpy(s, &str_pool[nstart], n);  
1131   s += n;
1132   *s = '\0';
1133
1134   return querystr;
1135 }
1136
1137 // abort_flag set if input_line / ConsoleInput returns non-zero
1138 // should set interrupt instead ???
1139 // called from tex0.c, tex2.c, tex3.c
1140 /* sec 0071 */
1141 // void term_input(void)
1142 void term_input (char * term_str, int term_help_lines)
1143
1144   integer k;
1145   int flag;
1146   char * helpstring = NULL;
1147 #ifdef _WINDOWS
1148   char * querystring = NULL;
1149 #endif
1150 //  if (nhelplines != 0) {
1151 //    helpstring = make_up_help_string (nhelplines);
1152 //    printf(helpstring);
1153 //    free(helpstring);
1154 //  }
1155   show_line("\n", 0);    // force it to show what may be buffered up ???
1156   helpstring = NULL;
1157
1158 #ifdef _WINDOWS
1159   if (term_str != NULL)
1160     querystring = term_str;
1161
1162   if (term_help_lines != NULL)
1163     helpstring = make_up_help_string(term_help_lines);
1164
1165   if (helpstring == NULL && querystring != NULL)
1166   {
1167     if (strcmp(querystring, ": ") == 0)
1168       helpstring = xstrdup("Please type another file name (or ^z to exit):");
1169     else if (strcmp(querystring, "=>") == 0)    // from firm_up_the_line
1170       helpstring = xstrdup("Please type <enter> to accept this line\r\nor type a replacement line");
1171     else if (strcmp(querystring, "insert>") == 0) // from error() after "I"
1172       helpstring = xstrdup("Please type something to insert here");
1173     else if (strcmp(querystring, "") == 0)      // from read_toks
1174       helpstring = xstrdup("Please type a control sequence");
1175     else if (strcmp(querystring, "= ") == 0)    // from read_toks
1176       helpstring = xstrdup("Please type a token");
1177     else if (strcmp(querystring, "*") == 0)   // get_next
1178       helpstring = xstrdup("Please type a control sequence\r\n(or ^z to exit)");
1179   }
1180
1181   flag = ConsoleInput(querystring, helpstring, (char *) &buffer[first]);  // ???
1182 //  flag == 0 means trouble --- EOF on terminal
1183   if (querystring != NULL)
1184     free(querystring);
1185
1186   if (helpstring != NULL)
1187     free(helpstring);
1188
1189   helpstring = querystring = NULL;
1190
1191   last = first + strlen((char *) &buffer[first]); /* -1 ? */
1192 //  flag = (last > first);
1193 //  may need to be more elaborate see input_line in texmf.c ???
1194 //  sprintf(log_line, "first %d last %d flag %d - %s",
1195 //      first, last, flag, (char *) &buffer[first]);
1196 //  winerror(log_line);
1197 #else
1198   fflush(stdout);
1199   flag = input_ln(stdin, true);
1200 #endif
1201   if (!flag)
1202   {
1203     fatal_error("End of file on the terminal!");
1204     return;         // abort_flag set
1205   }
1206   term_offset = 0;
1207 #ifdef _WINDOWS
1208 // echo what was typed into Console buffer also
1209   if (last != first)
1210     for (k = first; k <= last - 1; k++)
1211       print(buffer[k]);
1212   print_ln();
1213 #else
1214   decr(selector);     // shut off echo
1215
1216   if (last != first)
1217     for (k = first; k <= last - 1; k++)
1218       print(buffer[k]);
1219
1220   print_ln();
1221   incr(selector);     // reset selector again
1222 #endif
1223 }
1224 /* sec 0091 */
1225 void int_error_ (integer n)
1226 {
1227   print_string(" (");
1228   print_int(n);
1229   print_char(')');
1230   error();
1231 }
1232 /* sec 0092 */
1233 void normalize_selector (void)
1234 {
1235   if (log_opened)
1236     selector = term_and_log;
1237   else
1238     selector = term_only;
1239
1240   if (job_name == 0)
1241     open_log_file();
1242
1243   if (interaction == batch_mode)
1244     decr(selector);
1245 }
1246 /* sec 0098 */
1247 void pause_for_instructions (void)
1248 {
1249    if (OK_to_interrupt)
1250    {
1251     interaction = error_stop_mode;
1252
1253     if ((selector == log_only) || (selector == no_print))
1254       incr(selector);
1255
1256     print_err("Interruption");
1257     help3("You rang?",
1258         "Try to insert some instructions for me (e.g.,`I\\showlists'),",
1259         "unless you just want to quit by typing `X'.");
1260     deletions_allowed = false;
1261     error();
1262     deletions_allowed = true;
1263     interrupt = 0;
1264   }
1265 }
1266 /* sec 0100 */
1267 integer half_(integer x)
1268 {
1269   if (odd(x))
1270     return ((x + 1) / 2);
1271   else
1272     return (x / 2);
1273 }
1274 /* sec 0102 */
1275 scaled round_decimals_(small_number k)
1276 {
1277   integer a;
1278
1279   a = 0;
1280
1281   while (k > 0)
1282   {
1283     decr(k);
1284     a = (a + dig[k] * 131072L) / 10; /* 2^17 */
1285   }
1286   
1287   return ((a + 1) / 2);
1288 }
1289 /* sec 0103 */
1290 /* This has some minor speedup changes - no real advantage probably ... */
1291 void print_scaled_(scaled s)
1292 {
1293   scaled delta;
1294
1295   if (s < 0)
1296   {
1297     print_char('-');
1298     s = - (integer) s;
1299   }
1300
1301   print_int(s / 65536L);
1302   print_char('.');
1303   s = 10 * (s % 65536L) + 5;
1304   delta = 10;
1305
1306   do
1307     {
1308       if (delta > 65536L)
1309         s = s - 17232; /* 2^15 - 50000 - rounding */
1310       print_char('0' + (s / 65536L));
1311       s = 10 * (s % 65536L);
1312       delta = delta * 10;
1313     }
1314   while (!(s <= delta));
1315 }
1316 /* sec 0105 */
1317 scaled mult_and_add_(integer n, scaled x, scaled y, scaled maxanswer)
1318 {
1319   if (n < 0)
1320   {
1321     x = - (integer) x;
1322     n = - (integer) n;
1323   }
1324
1325   if (n == 0)
1326     return y;
1327   else if (((x <= (maxanswer - y) / n) && (- (integer) x <= (maxanswer + y) / n)))
1328     return (n * x + y); 
1329   else
1330   {
1331     arith_error = true;
1332     return 0;
1333   }
1334 }
1335 /* sec 0106 */
1336 scaled x_over_n_(scaled x, integer n)
1337 {
1338   register scaled Result;
1339   bool negative;
1340
1341   negative = false;
1342
1343   if (n == 0)
1344   {
1345     arith_error = true;
1346     Result = 0;
1347     tex_remainder = x;
1348   }
1349   else
1350   {
1351     if (n < 0)
1352     {
1353       x = - (integer) x;
1354       n = - (integer) n;
1355       negative = true;
1356     }
1357
1358     if (x >= 0)
1359     {
1360       Result = x / n;
1361       tex_remainder = x % n;
1362     }
1363     else
1364     {
1365       Result = - (integer) ((- (integer) x)/ n);
1366       tex_remainder = - (integer) ((- (integer) x)% n);
1367     }
1368   }
1369
1370   if (negative)
1371     tex_remainder = - (integer) tex_remainder;
1372
1373   return Result;
1374 }
1375 /* sec 0107 */
1376 scaled xn_over_d_(scaled x, integer n, integer d)
1377 {
1378   register scaled Result;
1379   bool positive;
1380   nonnegative_integer t, u, v;
1381
1382   if (x >= 0)
1383     positive = true; 
1384   else
1385   {
1386     x = - (integer) x;
1387     positive = false;
1388   }
1389
1390   t =(x % 32767L) * n;
1391   u =(x / 32768L)* n +(t / 32768L);
1392   v =(u % d)* 32768L +(t % 32768L); 
1393
1394   if (u / d >= 32768L)
1395     arith_error = true; 
1396   else
1397     u = 32768L * (u / d) + (v / d);
1398
1399   if (positive)
1400   {
1401     Result = u;
1402     tex_remainder = v % d;
1403   }
1404   else
1405   {
1406     Result = - (integer) u;
1407     tex_remainder = - (integer)(v % d);
1408   }
1409
1410   return Result;
1411 }
1412 /* sec 0108 */
1413 halfword badness_(scaled t, scaled s)
1414 {
1415   integer r;
1416
1417   if (t == 0)
1418     return 0;
1419   else if (s <= 0)
1420     return 10000;
1421   else
1422   {
1423     if (t <= 7230584L)
1424       r = (t * 297) / s;
1425     else if (s >= 1663497L)
1426       r = t / (s / 297);
1427     else
1428       r = t;
1429
1430     if (r > 1290)
1431       return 10000; 
1432     else
1433       return (r * r * r + 131072L) / 262144L;  /* 2^17 */
1434   }
1435 }
1436 /* sec 0114 */
1437 #ifdef DEBUG
1438 void print_word_(memory_word w)
1439
1440   print_int(w.cint); 
1441   print_char(' ');
1442   print_scaled(w.cint); 
1443   print_char(' ');
1444   print_scaled(round(65536L * w.gr));
1445   print_ln();
1446   print_int(w.hh.v.LH);
1447   print_char('=');
1448   print_int(w.hh.b0);
1449   print_char(':');
1450   print_int(w.hh.b1);
1451   print_char(';');
1452   print_int(w.hh.v.RH);
1453   print_char(' ');
1454   print_int(w.qqqq.b0); 
1455   print_char(':');
1456   print_int(w.qqqq.b1); 
1457   print_char(':');
1458   print_int(w.qqqq.b2); 
1459   print_char(':');
1460   print_int(w.qqqq.b3);
1461
1462 /* need this version only if SHORTFONTINFO defined */
1463 void zprintfword(fmemoryword w)
1464 {
1465   print_int(w.cint);
1466   print_char(' ');
1467   print_scaled(w.cint);
1468   print_char(' ');
1469   print_scaled(round(65536L * w.gr));
1470   print_ln();
1471   print_int(w.hh.v.LH);
1472   print_char('=');
1473   print_int(w.hh.b0);
1474   print_char(':');
1475   print_int(w .hh.b1);
1476   print_char(';');
1477   print_int(w.hh.v.RH);
1478   print_char(' ');
1479   print_int(w.qqqq.b0);
1480   print_char(':');
1481   print_int(w.qqqq.b1);
1482   print_char(':');
1483   print_int(w.qqqq.b2);
1484   print_char(':');
1485   print_int(w.qqqq.b3);
1486 }
1487 #endif
1488 /* sec 0292 */
1489 void show_token_list_(integer p, integer q, integer l)
1490 {
1491   integer m, c;
1492   ASCII_code match_chr;
1493   ASCII_code n;
1494
1495   match_chr = '#';
1496   n = '0';
1497   tally = 0;
1498
1499   while ((p != 0) && (tally < l))
1500   {
1501     if (p == q)
1502     {
1503       first_count = tally;
1504       trick_count = tally + 1 + error_line - half_error_line;
1505
1506       if (trick_count < error_line)
1507         trick_count = error_line;
1508     }
1509
1510     if ((p < hi_mem_min) || (p > mem_end))
1511     {
1512       print_esc("CLOBBERED.");
1513       return;
1514     }
1515
1516     if (info(p) >= cs_token_flag)
1517       print_cs(info(p) - cs_token_flag);
1518     else
1519     {
1520       m = info(p) / 256;
1521       c = info(p) % 256;
1522
1523       if (info(p) < 0)
1524         print_esc("BAD.");
1525       else
1526         switch (m)
1527         {
1528           case left_brace:
1529           case right_brace:
1530           case math_shift:
1531           case tab_mark:
1532           case sup_mark:
1533           case sub_mark:
1534           case spacer:
1535           case letter:
1536           case other_char:
1537             print(c);
1538             break;
1539
1540           case mac_param:
1541             print(c);
1542             print(c);
1543             break;
1544
1545           case out_param:
1546             print(match_chr);
1547
1548             if (c <= 9)
1549               print_char(c + '0');
1550             else
1551             {
1552               print_char('!');
1553               return;
1554             }
1555             break;
1556
1557           case match:
1558             match_chr = (ASCII_code) c;
1559             print(c);
1560             incr(n);
1561             print_char(n);
1562
1563             if (n > '9')
1564               return;
1565             break;
1566
1567           case end_match:
1568             print_string("->");
1569             break;
1570
1571           default:
1572             print_esc("BAD.");
1573             break;
1574         }
1575     }
1576     p = link(p);
1577   }
1578
1579   if (p != 0)
1580     print_esc("ETC.");
1581 }
1582 /* sec 0306 */
1583 void runaway (void)
1584 {
1585   halfword p;
1586
1587   if (scanner_status > 1)
1588   {
1589     print_nl("Runaway ");
1590
1591     switch (scanner_status)
1592     {
1593       case defining:
1594         print_string("definition");
1595         p = def_ref;
1596         break;
1597
1598       case matching:
1599         print_string("argument");
1600         p = temp_head;
1601         break;
1602
1603       case aligning:
1604         print_string("preamble");
1605         p = hold_head;
1606         break;
1607
1608       case absorbing:
1609         print_string("text");
1610         p = def_ref;
1611         break;
1612     }
1613
1614     print_char('?');
1615     print_ln();
1616     show_token_list(link(p), 0, error_line - 10); 
1617   }
1618 }
1619 /* sec 0120 */
1620 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1621 /* first try list of available nodes (avail != NULL)                   */
1622 /* then see if can go upwards (mem_end < mem_max)                      */
1623 /* then see if can go downwards (hi_mem_min > lo_mem_max)              */
1624 /* if not, extend memory at the top and grab from there --- new        */
1625 /* else fail ! paragraph 120                                           */
1626 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1627 halfword get_avail (void)
1628 {
1629   halfword p;
1630
1631   p = avail;
1632
1633   if (p != 0)
1634     avail = link(avail);
1635   else if (mem_end < mem_max)
1636   {
1637     incr(mem_end);
1638     p = mem_end;
1639   }
1640   else
1641   {
1642     decr(hi_mem_min);
1643     p = hi_mem_min;
1644
1645     if (hi_mem_min <= lo_mem_max) /* have we run out in middle ? */
1646     {
1647       incr(hi_mem_min);
1648       mem = realloc_main (0, mem_top / 2);  /* zzzaa = zmem = mem */
1649
1650       if (mem == NULL)
1651         return 0;
1652
1653       if (mem_end >= mem_max)
1654       {
1655         runaway();
1656         overflow("main memory size", mem_max + 1 - mem_min);
1657         return 0;           // abort_flag set
1658       }
1659       incr(mem_end);        /* then grab from new area */
1660       p = mem_end;          /* 1993/Dec/14 */
1661     }
1662   }
1663
1664   link(p) = 0;       /* link(p) = null !!! */
1665
1666 #ifdef STAT
1667   incr(dyn_used); 
1668 #endif /* STAT */
1669
1670   return p; 
1671
1672 /* sec 0123 */
1673 void flush_list_(halfword p)          /* paragraph 123 */
1674
1675   halfword q, r;
1676
1677   if (p != 0)              /* null !!! */
1678   {
1679     r = p;
1680
1681     do
1682       {
1683         q = r;
1684         r = link(r);
1685 #ifdef STAT
1686         decr(dyn_used);
1687 #endif /* STAT */
1688       }
1689     while (!(r == 0));     /* r != null */
1690
1691     link(q) = avail;
1692     avail = p;
1693   }
1694 }
1695 /* sec 0125 */
1696 halfword get_node_(integer s)
1697 {
1698   register halfword Result;
1699   halfword p;
1700   halfword q;
1701   integer r;
1702   integer t;
1703 lab20:
1704
1705   p = rover;
1706
1707   do
1708     {
1709       q = p + node_size(p);
1710
1711       while ((mem[q].hh.v.RH == empty_flag))
1712       {
1713         t = rlink(q);
1714
1715         if (q == rover)
1716           rover = t;
1717
1718         llink(t) = llink(q);
1719         rlink(llink(q)) = t;
1720         q = q + node_size(q);
1721       }
1722
1723       r = q - s;
1724
1725       if (r > toint(p + 1)) 
1726       {
1727         node_size(p) = r - p;
1728         rover = p;
1729         goto lab40;
1730       }
1731
1732       if (r == p)
1733         if (rlink(p) != p)
1734         {
1735           rover = rlink(p);
1736           t = llink(p);
1737           llink(rover) = t;
1738           rlink(t) = rover;
1739           goto lab40;
1740         }
1741
1742       node_size(p) = q - p;
1743       p = rlink(p);
1744     }
1745   while (!(p == rover));
1746
1747   if (s == 1073741824L)    /* 2^30 - special case - merge adjacent */
1748   {
1749     Result = max_halfword;
1750
1751     if (trace_flag)
1752       show_line("Merged adjacent multi-word nodes\n", 0);
1753
1754     return Result;
1755   }
1756
1757 /*  maybe try downward epxansion first instead ? */
1758   if (lo_mem_max + 2 < hi_mem_min)
1759     if (lo_mem_max + 2 <= mem_bot + max_halfword)  /* silly ? flush 93/Dec/16 */
1760     {
1761       /* if (hi_mem_min - lo_mem_max >= 1998) */
1762       if (hi_mem_min - lo_mem_max >= (block_size + block_size - 2))
1763         /* t = lo_mem_max + 1000; */
1764         t = lo_mem_max + block_size;
1765       else
1766         t = lo_mem_max + 1 + (hi_mem_min - lo_mem_max) / 2;
1767
1768       p = llink(rover);
1769       q = lo_mem_max;
1770       rlink(p) = q;
1771       llink(rover) = q;
1772
1773       if (t > mem_bot + max_halfword)
1774         t = mem_bot + max_halfword;     /* silly ? flush 93/Dec/16 */
1775
1776       rlink(q) = rover;
1777       llink(q) = p;
1778       link(q) = empty_flag;
1779       node_size(q) = t - lo_mem_max; /* block size */
1780       lo_mem_max = t;
1781       link(lo_mem_max) = 0;
1782       info(lo_mem_max) = 0;
1783       rover = q;
1784       goto lab20;
1785     }
1786
1787 /* *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** */
1788 /* we've run out of space in the middle for variable length blocks */
1789 /* try and add new block from below mem_bot *//* first check if space ! */
1790   if (mem_min - (block_size + 1) <= mem_start) /* extend lower memory downwards */
1791   {
1792     mem = realloc_main (mem_top/2 + block_size, 0);  /* zzzaa = zmem = mem */
1793
1794     if (mem == NULL)
1795     {
1796       return 0;
1797     }
1798   }
1799
1800   if (mem_min - (block_size + 1) <= mem_start) /* check again */
1801   {
1802     if (trace_flag)
1803     {
1804       sprintf(log_line, "mem_min %d, mem_start %d, block_size %d\n", mem_min, mem_start, block_size);
1805       show_line(log_line, 0);
1806     }
1807
1808     overflow("main memory size", mem_max + 1 - mem_min); /* darn: allocation failed ! */
1809     return 0;     // abort_flag set
1810   }
1811 /* avoid function call in following ? */
1812   add_variable_space (block_size); /* now to be found in itex.c */
1813   goto lab20;         /* go try get_node again */
1814
1815 lab40:
1816   link(r) = 0;
1817
1818 #ifdef STAT
1819   var_used = var_used + s; 
1820 #endif /* STAT */
1821
1822   Result = r; 
1823   return Result; 
1824
1825 /* sec 0130 */
1826 void free_node_(halfword p, halfword s)
1827
1828   halfword q;
1829
1830   node_size(p) = s;
1831   link(p) = empty_flag;
1832   q = llink(rover);
1833   llink(p) = q;
1834   rlink(p) = rover;
1835   llink(rover) = p;
1836   rlink(q) = p;
1837 #ifdef STAT
1838   var_used = var_used - s; 
1839 #endif /* STAT */
1840 }
1841 /* sec 0136 */
1842 halfword new_null_box (void) 
1843 {
1844   halfword p;
1845
1846   p = get_node(box_node_size);
1847   type(p) = hlist_node;
1848   subtype(p) = min_quarterword;
1849   width(p) = 0;
1850   depth(p) = 0;
1851   height(p) = 0;
1852   shift_amount(p) = 0;
1853   list_ptr(p) = 0;
1854   glue_sign(p) = normal;
1855   glue_order(p) = normal;
1856   glue_set(p) = 0.0;
1857
1858   return p;
1859 }
1860 /* sec 0139 */
1861 halfword new_rule (void) 
1862 {
1863   halfword p;
1864
1865   p = get_node(rule_node_size);
1866   type(p) = rule_node;
1867   subtype(p) = 0;
1868   width(p) = null_flag;
1869   depth(p) = null_flag;
1870   height(p) = null_flag;
1871
1872   return p;
1873 }
1874 /* sec 0144 */
1875 halfword new_ligature_(quarterword f, quarterword c, halfword q)
1876 {
1877   halfword p;
1878
1879   p = get_node(small_node_size);
1880   type(p) = ligature_node;
1881   font(lig_char(p)) = f;
1882   character(lig_char(p)) = c;
1883   lig_ptr(p) = q;
1884   subtype(p) = 0;
1885
1886   return p;
1887 }
1888 /* sec 0144 */
1889 halfword new_lig_item_(quarterword c)
1890 {
1891   halfword p;
1892
1893   p = get_node(small_node_size);
1894   character(p) = c;
1895   lig_ptr(p) = 0;
1896
1897   return p;
1898 }
1899 /* sec 0145 */
1900 halfword new_disc (void) 
1901 {
1902   halfword p;
1903
1904   p = get_node(small_node_size);
1905   type(p) = disc_node;
1906   replace_count(p) = 0;
1907   pre_break(p) = 0;
1908   post_break(p) = 0;
1909
1910   return p;
1911 }
1912 /* sec 0147 */
1913 halfword new_math_(scaled w, small_number s)
1914 {
1915   halfword p;
1916
1917   p = get_node(small_node_size);
1918   type(p) = math_node;
1919   subtype(p) = s;
1920   width(p) = w;
1921
1922   return p;
1923 }
1924 /* sec 0151 */
1925 halfword new_spec_(halfword p)
1926 {
1927   halfword q;
1928
1929   q = get_node(glue_spec_size);
1930   mem[q] = mem[p];
1931   glue_ref_count(q) = 0;
1932   width(q) = width(p);
1933   stretch(q) = stretch(p);
1934   shrink(q) = shrink(p);
1935
1936   return q;
1937 }
1938 /* se 0152 */
1939 halfword new_param_glue_(small_number n)
1940 {
1941   halfword p;
1942   halfword q;
1943
1944   p = get_node(small_node_size);
1945   type(p) = glue_node;
1946   subtype(p) = n + 1;
1947   leader_ptr(p) = 0;
1948   q = glue_par(n);
1949   glue_ptr(p) = q;
1950   incr(glue_ref_count(q));
1951
1952   return p;
1953 }
1954 /* sec 0153 */
1955 halfword new_glue_(halfword q)
1956 {
1957   halfword p;
1958
1959   p = get_node(small_node_size);
1960   type(p) = glue_node;
1961   subtype(p) = normal;
1962   leader_ptr(p) = 0; 
1963   glue_ptr(p) = q;
1964   incr(glue_ref_count(q));
1965
1966   return p;
1967 }
1968 /* sec 0154 */
1969 halfword new_skip_param_(small_number n)
1970 {
1971   halfword p;
1972
1973   temp_ptr = new_spec(glue_par(n));
1974   p = new_glue(temp_ptr); 
1975   glue_ref_count(temp_ptr) = 0;
1976   subtype(p) = n + 1;
1977
1978   return p;
1979 }
1980 /* sec 0155 */
1981 halfword new_kern_(scaled w)
1982 {
1983   halfword p;
1984
1985   p = get_node(small_node_size);
1986   type(p) = kern_node;
1987   subtype(p) = normal;
1988   width(p) = w;
1989
1990   return p;
1991 }
1992 /* sec 0158 */
1993 halfword new_penalty_(integer m)
1994 {
1995   halfword p;
1996
1997   p = get_node(small_node_size);
1998   type(p) = penalty_node;
1999   subtype(p) = 0;
2000   penalty(p) = m;
2001
2002   return p;
2003 }
2004
2005 #ifdef DEBUG
2006 /* sec 0167 */
2007 void check_mem_(bool printlocs)
2008 {
2009   halfword p, q;
2010   bool clobbered;
2011
2012   for (p = mem_min; p <= lo_mem_max; p++) freearr[p] = false;
2013   for (p = hi_mem_min; p <= mem_end; p++) freearr[p] = false;
2014   p = avail;
2015   q = 0;
2016   clobbered = false;
2017   while (p != 0) {
2018     if ((p > mem_end) || (p < hi_mem_min))
2019       clobbered = true;
2020     else if (freearr[p])
2021       clobbered = true;
2022
2023     if (clobbered)
2024     {
2025       print_nl("AVAIL list clobbered at ");
2026       print_int(q);
2027       goto lab31;
2028     }
2029     freearr[p] = true;
2030     q = p;
2031     p = link(q);
2032   }
2033 lab31:;
2034   p = rover;
2035   q = 0;
2036   clobbered = false;
2037   do {
2038       if ((p >= lo_mem_max) || (p < mem_min))
2039         clobbered = true;
2040       else if ((rlink(p) >= lo_mem_max) || (rlink(p) < mem_min))
2041         clobbered = true;
2042       else if (!(is_empty(p)) || (node_size(p) < 2) ||
2043           (p + node_size(p) > lo_mem_max) || (llink(rlink(p)) != p))
2044         clobbered = true;
2045       
2046       if (clobbered)
2047       {
2048         print_nl("Double-AVAIL list clobbered at ");
2049         print_int(q);
2050         goto lab32;
2051       }
2052
2053       for (q = p; q <= p + node_size(p) - 1; q++)
2054       {
2055         if (freearr[q])
2056         {
2057           print_nl("Doubly free location at ");
2058           print_int(q);
2059           goto lab32;
2060         }
2061         freearr[q]= true;
2062       }
2063       q = p;
2064       p = rlink(p);
2065   } while (!(p == rover));
2066 lab32:;
2067   p = mem_min;
2068   while (p <= lo_mem_max) {
2069     if (is_empty(p))
2070     {
2071       print_nl("Bad flag at ");
2072       print_int(p);
2073     }
2074     while ((p <= lo_mem_max) && !freearr[p]) incr(p);
2075     while ((p <= lo_mem_max) && freearr[p]) incr(p);
2076   }
2077
2078   if (printlocs)
2079   {
2080     print_nl("New busy locs:");
2081
2082     for (p = mem_min; p <= lo_mem_max; p++)
2083       if (!freearr[p] && ((p > was_lo_max) || wasfree[p]))
2084       {
2085         print_char(' ');
2086         print_int(p);
2087       }
2088
2089     for (p = hi_mem_min; p <= mem_end; p++)
2090       if (!freearr[p] && ((p < was_hi_min) || (p > was_mem_end) || wasfree[p]))
2091       {
2092         print_char(' ');
2093         print_int(p);
2094       }
2095   }
2096
2097   for (p = mem_min; p <= lo_mem_max; p++) wasfree[p] = freearr[p];
2098   for (p = hi_mem_min; p <= mem_end; p++) wasfree[p] = freearr[p];
2099
2100   was_mem_end = mem_end;
2101   was_lo_max = lo_mem_max;
2102   was_hi_min = hi_mem_min;
2103 }
2104 #endif /* DEBUG */
2105
2106 #ifdef DEBUG
2107 /* sec 0172 */
2108 void search_mem_(halfword p)
2109 {
2110   integer q;
2111
2112   for (q = mem_min; q <= lo_mem_max; q++)
2113   {
2114     if (link(q) == p)
2115     {
2116       print_nl("LINK(");
2117       print_int(q);
2118       print_char(')');
2119     }
2120     if (info(q) == p)
2121     {
2122       print_nl("INFO(");
2123       print_int(q);
2124       print_char(')');
2125     }
2126   }
2127
2128   for (q = hi_mem_min; q <= mem_end; q++)
2129   {
2130     if (link(q) == p)
2131     {
2132       print_nl("LINK(");
2133       print_int(q);
2134       print_char(')');
2135     }
2136     if (info(q) == p)
2137     {
2138       print_nl("INFO(");
2139       print_int(q);
2140       print_char(')');
2141     }
2142   }
2143
2144   for (q = active_base; q <= box_base + 255; q++)
2145     if (equiv(q) == p)
2146     {
2147       print_nl("EQUIV(");
2148       print_int(q);
2149       print_char(')');
2150     }
2151
2152   if (save_ptr > 0)
2153     for (q = 0; q <= save_ptr - 1; q++)
2154     {
2155       if (equiv_field(save_stack[q]) == p)
2156       {
2157         print_nl("SAVE(");
2158         print_int(q);
2159         print_char(')');
2160       }
2161     }
2162
2163   for (q = 0; q <= hyphen_prime; q++)
2164     if (hyph_list[q] == p)
2165     {
2166       print_nl("HYPH(");
2167       print_int(q);
2168       print_char(')');
2169     }
2170 }
2171 #endif /* DEBUG */
2172 /* sec 0174 */
2173 void short_display_(integer p)
2174 {
2175   integer n; 
2176
2177   while (p != 0) {      /* want p != null here bkph 93/Dec/15 !!! NOTE: still not fixed in 3.14159 ! */
2178      if (is_char_node(p))
2179      {
2180        if (p <= mem_end)
2181        {
2182          if (font(p) != font_in_short_display)
2183          {
2184            if ((font(p) > font_max))
2185              print_char('*');
2186            else
2187            {
2188              print_esc("");
2189              print(font_id_text(font(p)));
2190            }
2191            print_char(' ');
2192            font_in_short_display = font(p);
2193          }
2194          print(character(p));
2195        }
2196      }
2197      else switch (mem[p].hh.b0)
2198      {
2199       case hlist_node:
2200       case vlist_node:
2201       case ins_node:
2202       case whatsit_node:
2203       case mark_node:
2204       case adjust_node:
2205       case unset_node:
2206         print_string("[]");
2207         break;
2208       case rule_node:
2209         print_char('|');
2210         break;
2211       case glue_node:
2212         if (glue_ptr(p) != 0)
2213           print_char(' ');
2214         break;
2215       case math_node:
2216         print_char('$');
2217         break;
2218       case ligature_node:
2219         short_display(lig_ptr(p));
2220         break;
2221       case disc_node:
2222         short_display(pre_break(p));
2223         short_display(post_break(p));
2224         n = replace_count(p);
2225
2226         while (n > 0) {
2227           if (link(p) != 0) /* if link(p)<>null then */
2228             p = link(p);
2229           decr(n);
2230         }
2231         break;
2232       default:
2233         break;
2234     }
2235     p = link(p);
2236   }
2237 }
2238 /* sec 0176 */
2239 void print_font_and_char_ (integer p)
2240 {
2241   if (p > mem_end)
2242     print_esc("CLOBBERED.");
2243   else
2244   {
2245     if ((font(p) > font_max))
2246       print_char('*');
2247     else
2248     {
2249       print_esc("");
2250       print(font_id_text(font(p)));
2251     }
2252
2253     print_char(' ');
2254     print(character(p));
2255   }
2256 }
2257 /* sec 0176 */
2258 void print_mark_ (integer p)
2259
2260   print_char('{');
2261
2262   if ((p < hi_mem_min)||(p > mem_end))
2263     print_esc("CLOBBERED.");
2264   else
2265     show_token_list(link(p), 0, max_print_line - 10);
2266
2267   print_char('}');
2268 }
2269 /* sec 0176 */
2270 void print_rule_dimen_ (scaled d)
2271 {
2272   if ((d == -1073741824L)) /* - 2^30 */
2273     print_char('*');
2274   else
2275     print_scaled(d);
2276 }
2277 /* sec 0177 */
2278 void print_glue_(scaled d, integer order, char * s)
2279 {
2280   print_scaled(d); 
2281
2282   if ((order < normal) || (order > filll))
2283     print_string("foul");
2284   else if (order > 0)
2285   {
2286     print_string("fil");
2287
2288     while (order > 1) {
2289       print_char('l');
2290       decr(order);
2291     }
2292   } else if (*s != '\0')
2293     print_string(s);
2294 }
2295 /* sec 0178 */
2296 void print_spec_(integer p, char * s)
2297 {
2298   if ((p < mem_min)||(p >= lo_mem_max)) 
2299     print_char('*');
2300   else
2301   {
2302     print_scaled(width(p));
2303
2304     if (*s != '\0')
2305       print_string(s);
2306
2307     if (stretch(p) != 0)
2308     {
2309       print_string("plus");
2310       print_glue(stretch(p), stretch_order(p), s);
2311     }
2312
2313     if (shrink(p) != 0)
2314     {
2315       print_string("minus");
2316       print_glue(shrink(p), shrink_order(p), s);
2317     }
2318   }
2319 }
2320 /* sec 0691 */
2321 void print_fam_and_char_(halfword p)
2322 {
2323   print_esc("fam");
2324   print_int(fam(p));
2325   print_char(' ');
2326   print(character(p));
2327 }
2328 /* sec 0691 */
2329 void print_delimiter_(halfword p)
2330 {
2331   integer a;
2332
2333   a = small_fam(p) * 256 + small_char(p);
2334   a = a * 4096 + large_fam(p) * 256 + large_char(p);
2335
2336   if (a < 0)
2337     print_int(a);
2338   else
2339     print_hex(a);
2340 }
2341 /* sec 0692 */
2342 void print_subsidiary_data_(halfword p, ASCII_code c)
2343 {
2344   if ((pool_ptr - str_start[str_ptr]) >= depth_threshold)
2345   {
2346     if (math_type(p) != 0)
2347       print_string(" []");
2348   }
2349   else
2350   {
2351     append_char(c);
2352     temp_ptr = p;
2353
2354     switch (math_type(p))
2355     {
2356       case math_char:
2357         print_ln();
2358         print_current_string();
2359         print_fam_and_char(p);
2360         break;
2361
2362       case sub_box:
2363         show_info();
2364         break;
2365
2366       case sub_mlist:
2367         if (info(p) == 0)
2368         {
2369           print_ln();
2370           print_current_string();
2371           print_string("{}");
2372         }
2373         else
2374           show_info();
2375         break;
2376
2377       default:
2378         break;
2379     }
2380
2381     decr(pool_ptr);
2382   }
2383 }
2384 /* sec 0694 */
2385 void print_style_(integer c)
2386 {
2387   switch (c / 2)
2388   {
2389     case 0:
2390       print_esc("displaystyle");
2391       break;
2392     case 1:
2393       print_esc("textstyle");
2394       break;
2395     case 2:
2396       print_esc("scriptstyle");
2397       break;
2398     case 3:
2399       print_esc("scriptscriptstyle");
2400       break;
2401     default:
2402       print_string("Unknown style!");
2403       break;
2404   }
2405 }
2406 /* sec 0225 */
2407 void print_skip_param_(integer n)
2408 {
2409   switch(n)
2410   {
2411     case line_skip_code:
2412       print_esc("lineskip");
2413       break;
2414
2415     case baseline_skip_code:
2416       print_esc("baselineskip");
2417       break; 
2418
2419     case par_skip_code:
2420       print_esc("parskip");
2421       break;
2422
2423     case above_display_skip_code:
2424       print_esc("abovedisplayskip");
2425       break;
2426
2427     case below_display_skip_code:
2428       print_esc("belowdisplayskip");
2429       break;
2430
2431     case above_display_short_skip_code:
2432       print_esc("abovedisplayshortskip");
2433       break;
2434
2435     case below_display_short_skip_code:
2436       print_esc("belowdisplayshortskip");
2437       break;
2438
2439     case left_skip_code:
2440       print_esc("leftskip");
2441       break;
2442
2443     case right_skip_code:
2444       print_esc("rightskip");
2445       break;
2446
2447     case top_skip_code:
2448       print_esc("topskip");
2449       break;
2450
2451     case split_top_skip_code:
2452       print_esc("splittopskip");
2453       break;
2454
2455     case tab_skip_code:
2456       print_esc("tabskip");
2457       break;
2458
2459     case space_skip_code:
2460       print_esc("spaceskip");
2461       break;
2462
2463     case xspace_skip_code:
2464       print_esc("xspaceskip");
2465       break;
2466
2467     case par_fill_skip_code:
2468       print_esc("parfillskip");
2469       break;
2470
2471     case thin_mu_skip_code:
2472       print_esc("thinmuskip");
2473       break;
2474
2475     case med_mu_skip_code:
2476       print_esc("medmuskip");
2477       break; 
2478
2479     case thick_mu_skip_code:
2480       print_esc("thickmuskip");
2481       break;
2482
2483     default:
2484       print_string("[unknown glue parameter!]");
2485       break;
2486   }
2487 }
2488 /* sec 0182 */
2489 void show_node_list_(integer p)
2490 {
2491   integer n;
2492   real g;
2493
2494   if (cur_length > depth_threshold)
2495   {
2496 /*  if (p > 0) */  /* was p>null !!! line 3662 in tex.web */
2497     if (p != 0)    /* fixed 94/Mar/23 BUG FIX NOTE: still not fixed in 3.14159 ! */
2498     print_string(" []");
2499     return; 
2500   }
2501
2502   n = 0; 
2503
2504   while (p != 0) {      /* want p != null - bkph 93/Dec/15 NOTE: still not fixed in 3.14159 ! */
2505     print_ln(); 
2506     print_current_string(); 
2507
2508     if (p > mem_end)
2509     {
2510       print_string("Bad link, display aborted.");
2511       return;
2512     }
2513
2514     incr(n);
2515
2516     if (n > breadth_max)
2517     {
2518       print_string("etc.");
2519       return;
2520     }
2521
2522     if ((p >= hi_mem_min))
2523       print_font_and_char(p);
2524     else switch (type(p))
2525     {
2526       case hlist_node:
2527       case vlist_node:
2528       case unset_node:
2529         {
2530           if (type(p) == hlist_node)
2531             print_esc("h");
2532           else if (type(p) == vlist_node)
2533             print_esc("v");
2534           else print_esc("unset");
2535
2536           print_string("box(");
2537           print_scaled(height(p));
2538           print_char('+');
2539           print_scaled(depth(p));
2540           print_string(")x");
2541           print_scaled(width(p));
2542
2543           if (type(p) == unset_node)
2544           {
2545             if (span_count(p) != 0)
2546             {
2547               print_string(" (");
2548               print_int(span_count(p) + 1);
2549               print_string(" columns)");
2550             }
2551
2552             if (glue_stretch(p) != 0)
2553             {
2554               print_string(", stretch ");
2555               print_glue(glue_stretch(p), glue_order(p), "");
2556             }
2557
2558             if (glue_shrink(p) != 0)
2559             {
2560               print_string(", shrink ");
2561               print_glue(glue_shrink(p), glue_sign(p), "");
2562             }
2563           }
2564           else
2565           {
2566             g = glue_set(p);
2567
2568             if ((g != 0.0) && (glue_sign(p) != 0))
2569             {
2570               print_string(", glue set ");
2571
2572               if (glue_sign(p) == shrinking)
2573                 print_string("- ");
2574
2575               if (fabs(g)> 20000.0)
2576               {
2577                 if (g > 0.0)
2578                   print_char('>');
2579                 else
2580                   print_string("< -");
2581
2582                 print_glue(20000 * 65536L, glue_order(p), "");
2583               }
2584               else
2585                 print_glue(round(65536L * g), glue_order(p), "");
2586             }
2587
2588             if (shift_amount(p) != 0)
2589             {
2590               print_string(", shifted ");
2591               print_scaled(shift_amount(p));
2592             }
2593           }
2594
2595           {
2596             {
2597               str_pool[pool_ptr] = 46;
2598               incr(pool_ptr);
2599             }
2600             show_node_list(mem[p + 5].hh.v.RH);
2601             decr(pool_ptr);
2602           }
2603         }
2604         break;
2605
2606       case rule_node:
2607         {
2608           print_esc("rule(");
2609           print_rule_dimen(height(p));
2610           print_char('+');
2611           print_rule_dimen(depth(p));
2612           print_string(")x");
2613           print_rule_dimen(width(p));
2614         }
2615         break;
2616
2617       case ins_node:
2618         {
2619           print_esc("insert");
2620           print_int(subtype(p));
2621           print_string(", natural size ");
2622           print_scaled(height(p));
2623           print_string("; split(");
2624           print_spec(split_top_ptr(p), "");
2625           print_char(',');
2626           print_scaled(depth(p));
2627           print_string("); float cost ");
2628           print_int(float_cost(p));
2629           {
2630             {
2631               str_pool[pool_ptr] = 46;
2632               incr(pool_ptr);
2633             }
2634             show_node_list(mem[p + 4].hh.v.LH);
2635             decr(pool_ptr);
2636           }
2637         }
2638         break;
2639       case 8:
2640         switch (subtype(p))
2641         {
2642           case open_node:
2643             {
2644               print_write_whatsit(1279, p);   /* debug # (-1 to exit): */
2645               print_char('=');
2646               print_file_name(open_name(p), open_area(p), open_ext(p));
2647             }
2648             break;
2649
2650           case write_node:
2651             {
2652               print_write_whatsit(591, p);  /* write */
2653               print_mark(write_tokens(p));
2654             }
2655             break;
2656
2657           case close_node:
2658             print_write_whatsit(1280, p); /* closeout */
2659             break;
2660
2661           case special_node:
2662             {
2663               print_esc("special");
2664               print_mark(write_tokens(p));
2665             }
2666             break;
2667
2668           case language_node:
2669             {
2670               print_esc("setlanguage");
2671               print_int(what_lang(p));
2672               print_string(" (hyphenmin ");
2673               print_int(what_lhm(p));
2674               print_char(',');
2675               print_int(what_rhm(p));
2676               print_char(')');
2677             }
2678             break;
2679
2680           default:
2681             print_string("whatsit?");
2682             break;
2683         }
2684         break;
2685
2686       case glue_node:
2687         if (subtype(p) >= a_leaders)
2688         {
2689           print_esc("");
2690
2691           if (subtype(p) == c_leaders)
2692             print_char('c');
2693           else if (subtype(p) == x_leaders)
2694             print_char('x');
2695
2696           print_string("leaders ");
2697
2698           print_spec(glue_ptr(p), "");
2699           {
2700             {
2701               str_pool[pool_ptr] = 46;
2702               incr(pool_ptr);
2703             }
2704             show_node_list(mem[p + 1].hh.v.RH);
2705             decr(pool_ptr);
2706           }
2707         }
2708         else
2709         {
2710           print_esc("glue");
2711
2712           if (subtype(p) != normal)
2713           {
2714             print_char('(');
2715
2716             if (subtype(p) < cond_math_glue)
2717               print_skip_param(subtype(p) - 1);
2718             else if (subtype(p) == cond_math_glue)
2719               print_esc("nonscript");
2720             else print_esc("mskip");
2721
2722             print_char(')');
2723           }
2724
2725           if (subtype(p) != cond_math_glue)
2726           {
2727             print_char(' ');
2728
2729             if (subtype(p) < cond_math_glue)
2730               print_spec(glue_ptr(p), "");
2731             else
2732               print_spec(glue_ptr(p), "mu");
2733           }
2734         }
2735         break;
2736
2737       case kern_node:
2738         if (subtype(p) != mu_glue)
2739         {
2740           print_esc("kern");
2741
2742           if (subtype(p) != normal)
2743             print_char(' ');
2744
2745           print_scaled(width(p));
2746
2747           if (subtype(p) == acc_kern)
2748             print_string(" (for accent)");
2749         }
2750         else
2751         {
2752           print_esc("mkern");
2753           print_scaled(width(p));
2754           print_string("mu");
2755         }
2756         break;
2757
2758       case math_node:
2759         {
2760           print_esc("math");
2761
2762           if (subtype(p) == before)
2763             print_string("on");
2764           else
2765             print_string("off");
2766
2767           if (width(p) != 0)
2768           {
2769             print_string(", surrounded ");
2770             print_scaled(width(p));
2771           }
2772         }
2773         break;
2774
2775       case ligature_node:
2776         {
2777           print_font_and_char(lig_char(p));
2778           print_string("(ligature ");
2779
2780           if (subtype(p) > 1)
2781             print_char('|');
2782
2783           font_in_short_display = font(lig_char(p)); 
2784           short_display(lig_ptr(p));
2785
2786           if (odd(subtype(p)))
2787             print_char('|');
2788
2789           print_char(')');
2790         }
2791         break;
2792
2793       case penalty_node:
2794         {
2795           print_esc("penalty ");
2796           print_int(penalty(p));
2797         }
2798         break;
2799
2800       case disc_node:
2801         {
2802           print_esc("discretionary");
2803
2804           if (replace_count(p) > 0)
2805           {
2806             print_string(" replacing ");
2807             print_int(replace_count(p));
2808           }
2809
2810           {
2811             {
2812               str_pool[pool_ptr] = 46;
2813               incr(pool_ptr);
2814             }
2815             show_node_list(mem[p + 1].hh.v.LH);
2816             decr(pool_ptr);
2817           }
2818           {
2819             str_pool[pool_ptr]= 124;
2820             incr(pool_ptr);
2821           }
2822           show_node_list(mem[p + 1].hh.v.RH);
2823           decr(pool_ptr);
2824         }
2825         break;
2826
2827       case mark_node:
2828         {
2829           print_esc("mark");
2830           print_mark(mark_ptr(p));
2831         }
2832         break;
2833
2834       case adjust_node:
2835         {
2836           print_esc("vadjust");
2837           {
2838             {
2839               str_pool[pool_ptr] = 46;
2840               incr(pool_ptr);
2841             }
2842             show_node_list(mem[p + 1].cint);
2843             decr(pool_ptr);
2844           }
2845         }
2846         break;
2847
2848       case style_node:
2849         print_style(subtype(p));
2850         break;
2851
2852       case choice_node:
2853         {
2854           print_esc("mathchoice");
2855           append_char('D');
2856           show_node_list(display_mlist(p));
2857           decr(pool_ptr);
2858           append_char('T');
2859           show_node_list(text_mlist(p));
2860           decr(pool_ptr);
2861           append_char('S');
2862           show_node_list(script_mlist(p));
2863           decr(pool_ptr);
2864           append_char('s');
2865           show_node_list(script_script_mlist(p)); 
2866           decr(pool_ptr); 
2867         } 
2868         break;
2869
2870       case ord_noad:
2871       case op_noad:
2872       case bin_noad:
2873       case rel_noad:
2874       case open_noad:
2875       case close_noad:
2876       case punct_noad:
2877       case inner_noad:
2878       case radical_noad:
2879       case over_noad:
2880       case under_noad:
2881       case vcenter_noad:
2882       case accent_noad:
2883       case left_noad:
2884       case right_noad:
2885         {
2886           switch (type(p))
2887           {
2888             case ord_noad:
2889               print_esc("mathord");
2890               break;
2891
2892             case op_noad:
2893               print_esc("mathop");
2894               break;
2895
2896             case bin_noad:
2897               print_esc("mathbin");
2898               break;
2899
2900             case rel_noad:
2901               print_esc("mathrel");
2902               break;
2903
2904             case open_noad:
2905               print_esc("mathopen");
2906               break;
2907
2908             case close_noad:
2909               print_esc("mathclose");
2910               break;
2911
2912             case punct_noad:
2913               print_esc("mathpunct");
2914               break;
2915
2916             case inner_noad:
2917               print_esc("mathinner");
2918               break;
2919
2920             case over_noad:
2921               print_esc("overline");
2922               break;
2923
2924             case under_noad:
2925               print_esc("underline");
2926               break;
2927
2928             case vcenter_noad:
2929               print_esc("vcenter");
2930               break;
2931
2932             case radical_noad:
2933               {
2934                 print_esc("radical");
2935                 print_delimiter(left_delimiter(p));
2936               }
2937               break;
2938
2939             case accent_noad:
2940               {
2941                 print_esc("accent");
2942                 print_fam_and_char(accent_chr(p));
2943               }
2944               break;
2945
2946             case left_noad:
2947               {
2948                 print_esc("left");
2949                 print_delimiter(delimiter(p));
2950               }
2951               break;
2952
2953             case right_noad:
2954               {
2955                 print_esc("right");
2956                 print_delimiter(delimiter(p));
2957               }
2958               break;
2959           }
2960
2961           if (subtype(p) != normal)
2962             if (subtype(p) == limits)
2963               print_esc("limits");
2964             else
2965               print_esc("nolimits");
2966
2967           if (type(p) < left_noad)
2968             print_subsidiary_data(nucleus(p), '.');
2969
2970           print_subsidiary_data(supscr(p), '^');
2971           print_subsidiary_data(subscr(p), '_');
2972         }
2973         break;
2974
2975       case fraction_noad:
2976         {
2977           print_esc("fraction, thickness ");
2978
2979           if (thickness(p) == 1073741824L)  /* 2^30 */
2980             print_string("= default");
2981           else
2982             print_scaled(thickness(p));
2983
2984           if ((small_fam(left_delimiter(p)) != 0) || (small_char(left_delimiter(p)) != 0) ||
2985               (large_fam(left_delimiter(p)) != 0) || (large_char(left_delimiter(p)) != 0))
2986           {
2987             print_string(", left-delimiter ");
2988             print_delimiter(left_delimiter(p));
2989           }
2990
2991           if ((small_fam(right_delimiter(p)) != 0) || (small_char(right_delimiter(p)) != 0) ||
2992               (large_fam(right_delimiter(p)) != 0)||(large_char(right_delimiter(p)) != 0))
2993           {
2994             print_string(", right-delimiter ");
2995             print_delimiter(right_delimiter(p));
2996           }
2997
2998           print_subsidiary_data(numerator(p), '\\');
2999           print_subsidiary_data(denominator(p), '/');
3000         }
3001         break;
3002
3003       default:
3004         print_string("Unknown node type!");
3005         break;
3006     }
3007     p = link(p);
3008   }
3009 }