OSDN Git Service

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