OSDN Git Service

PATH_MAX -> file_name_size
[putex/putex.git] / src / texsourc / yandytex.c
1 /* Copyright 1992 Karl Berry
2    Copyright 2007 TeX Users Group
3    Copyright 2014 Clerk Ma
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 2 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program; if not, write to the Free Software
17    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18    02110-1301 USA.  */
19
20 #define EXTERN
21
22 #include "texd.h"
23
24 #define dump_default_var    TEX_format_default
25 #define dump_default        " plain.fmt"
26 #define dump_ext_length     4
27 #define dump_default_length format_default_length
28 #define edit_value          tex_edit_value
29
30 extern char * replacement[];
31 static char * program_name = NULL;
32 int    gargc;   /* number of args - set to zero after initialization */
33 char **gargv;
34
35 /* The entry point: set up for reading the command line, which will
36    happen in `t_open_in', then call the main body.  */
37
38 int jump_used = 0;
39
40 jmp_buf jumpbuffer;
41
42 int main (int ac, char *av[])
43 {
44   int flag = 0, ret = 0;
45
46 #ifdef WIN32
47   _setmaxstdio(2048);
48 #endif
49
50   gargc = ac;
51   gargv = av;
52
53   if (main_init(gargc, gargv))
54     return -1; // failure
55
56   dump_default_var = dump_default;
57   dump_default_length = strlen(dump_default_var + 1);
58
59   jump_used = 0;
60
61   ret = setjmp(jumpbuffer);
62
63   if (ret == 0)
64   {
65     flag = main_program();
66
67     if (trace_flag)
68     {
69       sprintf(log_line, "EXITING at %s: flag = %d, ret = %d, jump_used = %d\n", "main", flag, ret, jump_used);
70       show_line(log_line, 0);
71     }
72   }
73   else
74   {
75     if (trace_flag)
76     {
77       sprintf(log_line, "EXITING at %s: flag = %d, ret = %d, jump_used =  %d\n", "jump_out", flag, ret, jump_used);
78       show_line(log_line, 0);
79     }
80   }
81
82   if (endit(flag) != 0)
83     flag = 1; /* do final clean up in local.c */
84
85   if (flag == 0)
86     return 0;
87   else
88     exit (flag);
89 }
90
91 /* texk/web2c/lib/texmfmp.c */
92 void t_open_in (void)
93 {
94   int i;
95
96   buffer[first] = 0;  /* In case there are no arguments.  */
97
98 #ifdef MSDOS
99   if (gargc > optind && optind > 0)
100   {
101     for (i = optind; i < gargc; i++)
102 #else
103   if (gargc > 1)
104   {
105     for (i = 1; i < gargc; i++)
106 #endif
107     {
108       if (allow_quoted_names && strchr(gargv[i], ' ') != NULL)
109       {
110         (void) strcat ((char *) &buffer[first], "\"");
111         (void) strcat ((char *) &buffer[first], gargv[i]);
112         (void) strcat ((char *) &buffer[first], "\"");
113       }
114       else
115         (void) strcat ((char *) &buffer[first], gargv[i]);
116
117       (void) strcat ((char *) &buffer[first], " ");
118     }
119     
120     gargc = 0;
121   }
122
123   /* Find the end of the buffer.  */
124   for (last = first; buffer[last]; ++last)
125     ;
126
127   for (--last; last >= first && ISBLANK (buffer[last]) && buffer[last] != '\r'; --last)
128     ;
129
130   last++;
131
132 /* One more time, this time converting to TeX's internal character
133    representation.  */ /* for command line input in this case */
134   if (non_ascii)
135   {
136     for (i = first; i < last; i++)
137       buffer[i] = xord[buffer[i]];
138   }
139 }
140
141 /* All our interrupt handler has to do is set TeX's or Metafont's global
142    variable `interrupt'; then they will do everything needed.  */
143
144 static void catch_interrupt (int err)
145 {
146   (void) signal (SIGINT, SIG_IGN);
147
148   if (interrupt++ >= 3)
149     exit(1);
150
151   (void) signal (SIGINT, catch_interrupt);
152 }
153
154 /* Besides getting the date and time here, we also set up the interrupt
155    handler, for no particularly good reason.  It's just that since the
156    `fix_date_and_time' routine is called early on (section 1337 in TeX,
157    ``Get the first line of input and prepare to start''), this is as
158    good a place as any.  */
159
160 void get_date_and_time (integer *sys_minutes,
161                         integer *sys_day,
162                         integer *sys_month,
163                         integer *sys_year)
164 {
165   time_t clock;
166   struct tm *tmptr;
167
168   (void) time (&clock);  /* - seconds since 1970 */ 
169
170   if (trace_flag)
171   {
172     sprintf(log_line, "The time is %u\n", clock);
173     show_line(log_line, 0);   
174   }
175
176   if (clock < 0)
177     puts("Time not available!\n");
178
179   tmptr = localtime (&clock);
180
181   if (tmptr == NULL)
182   {
183     sprintf(log_line, "Cannot convert time (%0ld)!\n", clock);
184     show_line(log_line, 1);
185     *sys_year    = 2038;
186     *sys_month   = 1;
187     *sys_day     = 18;
188     *sys_minutes = 22 * 60 + 14;
189   }
190   else
191   {
192     *sys_minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
193     *sys_day     = tmptr->tm_mday;
194     *sys_month   = tmptr->tm_mon + 1;
195     *sys_year    = tmptr->tm_year + 1900;
196
197     if (trace_flag)
198     {
199       sprintf(log_line, "%d-%d-%d %d:%d\n",
200         tmptr->tm_year + 1900,
201         tmptr->tm_mon + 1,
202         tmptr->tm_mday,
203         tmptr->tm_hour,
204         tmptr->tm_min);
205       show_line(log_line, 0);
206     }
207   }
208
209   {
210 #ifdef MSDOS
211     if (!no_interrupts)
212     {
213       if (signal(SIGINT, catch_interrupt) == SIG_ERR)
214       {
215         puts(" CTRL-C handler not installed\n");
216 #ifndef _WINDOWS
217         uexit(EXIT_FAILURE);  /* do we care when run as DLL ? */
218 #endif
219       }
220     }
221 #else
222     void (*old_handler)();
223
224     if ((old_handler = signal (SIGINT, catch_interrupt)) != SIG_DFL)
225       (void) signal (SIGINT, old_handler);
226 #endif
227   }
228 }
229
230 /* I/O for TeX and Metafont.  */
231 void complain_line (FILE *output)
232 {
233   show_line("\n", 0);
234
235 #ifdef ALLOCATEBUFFER
236   sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", current_buf_size);
237 #else
238   sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", buf_size);
239 #endif
240
241   if (output == stderr)
242     show_line(log_line, 1);
243   else if (output == stdout)
244     show_line(log_line, 0);
245   else
246     fputs(log_line, output); // never
247
248   puts("  (File may have a line termination problem.)");
249 }
250
251 void show_bad_line (FILE *output, int first, int last)
252 {
253   int i, c, d, ch;
254   char *s = log_line;
255
256   for (i = first; i <= last; i++)
257   {
258     ch = buffer[i];
259
260     if ((show_in_hex && ch > 127))
261     {
262       c = ch >> 4;
263       d = ch & 15; 
264       if (c > 9)
265         c = c + 'a' - 10;
266       else
267         c = c + '0';
268       if (d > 9)
269         d = d + 'a' - 10;
270       else
271         d = d + '0';
272 /* putc('^', output); putc('^', output); */
273       *s++ = '^';
274       *s++ = '^';
275 /* putc (c, output); putc (d, output); */
276       *s++ = (char) c;
277       *s++ = (char) d;
278     }
279     else
280       if (ch < 32)
281       {
282 /* putc('^', output); putc('^', output); */
283         *s++ = '^';
284         *s++ = '^';
285 /* putc (ch + 64, output); */
286         *s++ = (char) (ch + 64);
287       }
288       else
289         if (ch == 127)
290         {
291 /* putc('^', output); putc('^', output); */
292           *s++ = '^';
293           *s++ = '^';
294 /* putc (ch - 64, output); */
295           *s++ = (char) (ch - 64);
296         }
297         else
298         {
299 /* putc(ch, output); */
300           *s++ = (char) ch;
301         }
302   }
303 //  putc(' ', output);    /*  putc('\n', output); */
304   *s++ = ' ';
305   *s++ = '\0';
306   if (output == stderr)
307     show_line(log_line, 1);
308   else
309     if (output == stdout)
310       show_line(log_line, 0);
311     else
312       fputs(log_line, output);   // log_file
313 }
314
315 // split off for convenience and use in ConsoleInput
316 boolean input_line_finish (void)
317 {
318   int i = '\0';
319   int ch, flag;
320   
321 /*  if last line in file does not end with \n - never happens ? */
322 /*  if (i == EOF && buffer[last] != '\n') buffer[last++] = '\n'; */
323
324   buffer[last] = ' ';           /* space terminate */
325   if (last >= max_buf_stack)
326     max_buf_stack = last; /* remember longest line */
327
328 /* Trim trailing whitespace.  */ 
329 /* #define isblank(c) ((c) == ' ' || (c) == '\t') */
330 /* What about \n ?  Can't get in here ?- bkph */
331 /* What about control-Z that gets read in binary mode ? - bkph */
332 // #ifdef MYDEBUG
333 /*  while (last > first && buffer[last - 1] <= ' ')  --last; */
334   while (last > first)
335   {
336     i = buffer[last - 1];
337
338     if (i == ' ' || i == '\t')
339       --last;
340 /*    else if (trimeof && i == 26) --last;   */   /* 93/Nov/24 */
341     else
342       break;
343   }
344 /*  if (trimeof != 0 && i == EOF && last == first)  
345       return false; */              /* EOF and line empty */
346 // #else
347 //   while (last > first
348 //         && isblank (buffer[last - 1]) && buffer[last - 1] != '\r')
349 //    --last;
350 // #endif
351
352 /* following added to check source file integrity ASCII 32 - 127 */
353 /* allow space, tab, new-page - also allow return, newline ? */
354   if (restrict_to_ascii)
355   {
356     flag = 0;
357     for (i = first; i <= last; i++)
358     {
359       ch = buffer[i];
360 /*      if (ch > 127 || (ch < ' ' && ch != '\t' && ch != '\f')) */
361 /*      1 -- 8, 11, 14 -- 31 are not good ASCII characters */
362       if (ch > 126 ||  (ch < ' ' && ch != '\t' && ch != '\f' && ch != '\r' && ch != '\n'))
363       {
364         sprintf(log_line, "\n! non ASCII char (%d) in line: ", ch);
365         show_line(log_line, 1);
366         if (log_opened)
367           fprintf(log_file, "\n! non ASCII char (%d) in line: ", ch);
368 /*        buffer[i]= 127; */ /* not defined - invalid char */
369         flag = 1;
370         break;
371       }
372     }
373     if (flag)
374     {
375       show_bad_line(errout, first, last);
376       if (log_opened)
377         show_bad_line(log_file, first, last);
378     }
379   }
380 /* Don't bother using xord if we don't need to. */ /* for input line */
381 /* #ifdef NONASCII */ /* has been turned into command line flag - bkph */
382   if (non_ascii)
383   {
384     for (i = first; i <= last; i++)
385       buffer[i] = xord[buffer[i]];
386   }
387 /* #endif */
388   return true;
389 }
390
391 /* Read a line of input into buffer as efficiently as possible (ha ha)
392    while still looking like Pascal.
393    We set `last' to `first' and return `false' if we get to eof.
394    Otherwise, we return `true' and set last = first +
395    length(line except trailing whitespace).  */
396 /* texmfmp.c */
397
398 boolean input_line (FILE *f)
399 {
400 //  int ch, flag;         /* for restrict_to_ascii case 94/Jan/21 */
401   char *u;            /* 1994/July/3 for key_replace */
402   int i = '\0';
403
404 /*  and here is the long way of doing this */
405   last = first;
406 /*  following is new version with tab expansion and key replacement */
407 /*  may want to expand out separately for speed 1994/July/3 */
408 /*  different versions depending on return_flag / tabexpand / key_replace */
409 /*  while (last < buf_size && (i = getc (f)) != EOF)  */
410 #ifdef ALLOCATEBUFFER
411   for ( ; ; ) 
412 #else
413   while (last < buf_size) 
414 #endif
415   {
416     i = getc(f);
417
418     if (i < ' ')
419     {
420       if (i == EOF || i == '\n' || (i == '\r' && return_flag))
421         break;
422       else if (i == '\t' && tab_step != 0)
423       {
424         buffer[last++] = (ASCII_code) ' ';
425
426 #ifdef ALLOCATEBUFFER
427         if (last >= current_buf_size)
428         {
429           buffer = realloc_buffer(increment_buf_size);  
430
431           if (last >= current_buf_size)
432             break;
433         }
434 #endif
435
436 #ifdef ALLOCATEBUFFER
437         while ((last - first) % tab_step != 0) 
438 #else
439         while (last < buf_size && (last - first) % tab_step != 0)
440 #endif
441         {
442
443           buffer[last++] = (ASCII_code) ' ';
444
445 #ifdef ALLOCATEBUFFER
446           if (last >= current_buf_size)
447           {
448             buffer = realloc_buffer(increment_buf_size);
449
450             if (last >= current_buf_size)
451               break;
452           }
453 #endif
454         }
455
456         continue;
457       }
458     }
459
460     if (key_replace && (u = replacement[i]) != NULL)
461     {
462 #ifdef ALLOCATEBUFFER
463       while (*u != '\0') 
464 #else
465       while (last < buf_size && *u != '\0')  
466 #endif
467       {
468         buffer[last++] = (ASCII_code) *u++;
469 #ifdef ALLOCATEBUFFER
470         if (last >= current_buf_size)
471         {
472           buffer = realloc_buffer(increment_buf_size);
473
474           if (last >= current_buf_size)
475             break;
476         }
477 #endif
478       }
479     }
480     else       /* normal case */
481     {
482       buffer[last++] = (ASCII_code) i;
483
484 #ifdef ALLOCATEBUFFER
485       if (last >= current_buf_size)
486       {
487         buffer = realloc_buffer(increment_buf_size);
488
489         if (last >= current_buf_size)
490           break;
491       }
492 #endif
493     }
494   }
495
496   if (return_flag)    /* let return terminate line as well as newline */
497   {
498     if (i == '\r')      /* see whether return followed by newline */
499     {
500       i = getc (f);       /* in which case throw away the newline */
501
502       if (i != '\n')
503       {
504         ungetc (i, f);
505         i = '\r';
506       }
507 /*      else  buffer[last-1] = (ASCII_code) i; */
508     }
509   }
510
511   //  Turn Ctrl-Z at end of file into newline 2000 June 22
512   if (i == EOF && trimeof && buffer[last - 1] == 26)
513   {
514     last--;
515   }
516
517   if (i == EOF && last == first)
518     return false;
519
520 /*  Didn't get the whole line because buffer was too small?  */
521 /*  This shouldn't happen anymore 99/Jan/23 */
522   if (i != EOF && i != '\n' && i != '\r')
523   {
524     complain_line(errout);
525
526     if (log_opened)
527       complain_line(log_file);
528
529     /* This may no longer be needed ... now that we grow it */
530     if (truncate_long_lines)
531     {
532       while (i != EOF && i != '\n' && i != '\r')
533       {
534         i = getc (f);     // discard rest of line
535       }
536
537       last--;       /* just in case */
538     }
539     else
540       uexit(EXIT_FAILURE);      /* line too long */
541   }
542
543   return input_line_finish();
544 }
545
546 /* This string specifies what the `e' option does in response to an
547    error message.  */
548
549 static char *edit_value = "c:\\yandy\\WinEdt\\WinEdt.exe [Open('%s');SelLine(%d,7)]";
550
551 /* This procedure is due to sjc@s1-c.  TeX (or Metafont) calls it when
552    the user types `e' in response to an error, invoking a text editor on
553    the erroneous source file.  FNSTART is how far into STRINGPOOL the
554    actual filename starts; FNLENGTH is how long the filename is.
555    
556    See ../site.h for how to set the default, and how to override it.  */
557
558 /* called from close_files_and_terminate in  tex9.c */
559
560 void call_edit (ASCII_code *stringpool, pool_pointer fnstart, integer fnlength, integer linenumber)
561 {
562   char *command, *s, *t, *u;
563   char c;
564   int sdone, ddone, ldone;
565   int i, n;
566   unsigned int commandlen;
567   ASCII_code *texfilename;
568   ASCII_code *log_file_name;
569   pool_pointer lgstart;
570   integer lglength;
571
572   if (log_opened)
573   {
574     lgstart = str_start[texmf_log_name];
575     lglength = length(texmf_log_name);
576     log_file_name = stringpool + lgstart;
577   }
578   else
579   {
580     lglength = 0;
581     log_file_name = (unsigned char *) "";
582   }
583
584   sdone = ddone = ldone = 0;
585   texfilename = stringpool + fnstart;
586
587   for (i = 1; i <= in_open; i++)
588     (void) fclose (input_file[i]);
589
590   n = fcloseall();
591
592   if (n > 0 && verbose_flag)
593   {
594     sprintf(log_line, "Closed %d streams\n", n);
595     show_line(log_line, 0);
596   }
597
598   s = kpse_var_value(edit_value);  
599
600   if (s != NULL)
601     edit_value = s;
602
603   commandlen = strlen (edit_value) + fnlength + lglength + 10 + 1 + 2;
604   command = (string) xmalloc (commandlen); 
605
606   s = command;
607
608   u = edit_value;
609
610   while ((c = *u++) != 0)
611   {
612     if (c == '%')
613     {
614       switch (c = *u++)
615       {
616         case 'd':
617           if (ddone)
618           {
619 #ifdef _WIN32
620             sprintf(log_line, "! bad command syntax (%c).\n", 'd');
621             show_line(log_line, 1);
622 #else
623             sprintf(log_line, "! `%%d' cannot appear twice in editor command.\n");
624             show_line(log_line, 1);
625 #endif
626             uexit(EXIT_FAILURE); 
627           }
628
629           (void) sprintf (s, "%d", linenumber);
630
631           while (*s != '\0')
632             s++;
633
634           ddone = 1;
635           break;
636
637         case 's':
638           if (sdone)
639           {
640 #ifdef __WIN32
641             sprintf(log_line, "! bad command syntax (%c).\n", 's'); 
642             show_line(log_line, 1);
643 #else
644             sprintf(log_line, "! `%%s' cannot appear twice in editor command.\n");
645             show_line(log_line, 1);
646 #endif
647             uexit(EXIT_FAILURE); 
648           }
649
650           t = (char *) texfilename;
651           n = fnlength;
652
653           if (non_ascii)
654             for (i = 0; i < n; i++)
655               *s++ = xchr [*t++];
656           else
657             for (i = 0; i < n; i++)
658               *s++ = (char) *t++;
659
660           sdone = 1;
661           break;
662
663         case 'l':
664           if (ldone)
665           {
666 #ifdef __WIN32
667             sprintf(log_line, "! bad command syntax (%c).\n", 'l'); 
668             show_line(log_line, 1);
669 #else
670             sprintf(log_line, "! `%%l' cannot appear twice in editor command.\n");
671             show_line(log_line, 1);
672 #endif
673             uexit(EXIT_FAILURE); 
674           }
675
676           t = (char *) log_file_name;
677           n = lglength;
678
679           if (non_ascii)
680             for (i = 0; i < n; i++)
681               *s++ = xchr [*t++];
682           else
683             for (i = 0; i < n; i++)
684               *s++ = (char) *t++;
685
686           ldone = 1;
687           break;
688
689         case '\0':
690           *s++ = '%'; 
691           u--;
692           break;
693
694         default:
695           *s++ = '%';
696           *s++ = c;
697           break;
698       }
699     }
700     else
701       *s++ = c;
702   }
703
704   *s = 0; /* terminate the command string */
705
706   if (strlen(command) + 1 >= commandlen)
707   {
708     sprintf(log_line, "Command too long (%d > %d)\n", strlen(command) + 1, commandlen);
709     show_line(log_line, 1);
710     uexit(EXIT_FAILURE);
711   }
712
713   //flushall();
714   fflush(NULL);
715
716   if (system (command) != 0)
717   {
718     show_line("\n", 0);
719     sprintf(log_line, "! Error in call: %s\n", command);
720     show_line(log_line, 1);
721
722 #ifdef __WIN32
723     if (errno != 0)
724       perrormod("! DOS says");
725 #endif
726
727     sprintf(log_line, "  (TEXEDIT=%s)\n", edit_value);
728     show_line(log_line, 0);
729     puts("  (Editor specified may be missing or path may be wrong)\n");
730     puts("  (or there may be missing -- or extraneous -- quotation signs)\n");
731   }
732
733   uexit(EXIT_FAILURE);
734 }
735
736 /* Read and write format (for TeX) or base (for Metafont) files.  In
737    tex.web, these files are architecture dependent; specifically,
738    BigEndian and LittleEndian architectures produce different files.
739    These routines always output BigEndian files.  This still does not
740    make the dump files architecture-independent, because it is possible
741    to make a format file that dumps a glue ratio, i.e., a floating-point
742    number.  Fortunately, none of the standard formats do that.  */
743
744 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP) /* this fn */
745
746 /* We don't REALLY care what `endian' the machine is after all ! */
747 /* But we do care about speed - so check exe file for following - bkph */
748
749 // #ifdef MYDEBUG
750 // char swapmarkerstring="ERROR: SWAPPING - NOT BigEndian AND NOT NoFmtBaseSwap";
751 // #endif
752
753 /* This macro is always invoked as a statement.  It assumes a variable
754    `temp'.  */
755    
756 #define SWAP(x, y) temp = (x); (x) = (y); (y) = temp;
757
758
759 /* Make the NITEMS items pointed at by P, each of size SIZE, be the
760    opposite-endianness of whatever they are now.  */
761
762 static int swap_items (char *p, int nitems, int size)
763 {
764   char temp;
765
766   /* Since `size' does not change, we can write a while loop for each
767      case, and avoid testing `size' for each time.  */
768   switch (size)
769   {
770     case 8:
771       while (nitems--)
772       {
773         SWAP (p[0], p[7]);
774         SWAP (p[1], p[6]);
775         SWAP (p[2], p[5]);
776         SWAP (p[3], p[4]);
777         p += size;
778       }
779       break;
780
781     case 4:
782       while (nitems--)
783       {
784         SWAP (p[0], p[3]);
785         SWAP (p[1], p[2]);
786         p += size;
787       }
788       break;
789
790     case 2:
791       while (nitems--)
792       {
793         SWAP (p[0], p[1]);
794         p += size;
795       }
796       break;
797
798     case 1:
799     /* Nothing to do.  */
800       break;
801
802     default:
803       show_line("\n", 0);
804       sprintf(log_line, "! I can't (un)dump a %d byte item.\n", size);
805       show_line(log_line, 1);
806       uexit(EXIT_FAILURE);
807   }
808   return 0;
809 }
810 #endif /* not WORDS_BIGENDIAN and not NO_FMTBASE_SWAP */
811
812 /* Hmm, this could benefit from some on the fly compression - bkph */
813 /* and complementary decompression on input - bkph */
814
815 /* Here we write NITEMS items, each item being ITEM_SIZE bytes long.
816    The pointer to the stuff to write is P, and we write to the file
817    OUT_FILE.  */
818
819 int do_dump (char *p, int item_size, int nitems, FILE *out_file)
820 {
821 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
822   swap_items (p, nitems, item_size);
823 #endif
824
825 #ifdef COMPACTFORMAT
826   if (gzwrite(gz_fmt_file, p, (item_size * nitems)) != (item_size * nitems))
827 #else
828   if ((int) fwrite (p, item_size, nitems, out_file) != nitems)
829 #endif
830   {
831     show_line("\n", 0);
832     sprintf(log_line, "! Could not write %d %d-byte item%s.\n",
833                nitems, item_size, (nitems > 1) ? "s" : "");
834     show_line(log_line, 1);
835     uexit(EXIT_FAILURE);
836   }
837
838 /* Have to restore the old contents of memory, since some of it might get used again.  */
839 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
840   swap_items (p, nitems, item_size);
841 #endif
842
843   return 0;
844 }
845
846 /* Hmm, this could benefit from some on the fly decompression - bkph */
847
848 /* Here is the dual of the writing routine.  */
849 int do_undump (char *p, int item_size, int nitems, FILE *in_file)
850 {
851 #ifdef COMPACTFORMAT
852   if (gzread(gz_fmt_file, (void *) p, (unsigned int) (item_size * nitems)) <= 0)
853 #else
854   if ((int) fread((void *) p, item_size, nitems, in_file) != nitems)
855 #endif
856   {
857     show_line("\n", 0);
858     sprintf(log_line, "! Could not read %d %d-byte item%s.\n",
859                nitems, item_size, (nitems > 1) ? "s" : "");
860     show_line(log_line, 1);
861     uexit(EXIT_FAILURE);
862   }
863
864 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
865   swap_items (p, nitems, item_size);
866 #endif
867
868   return 0;
869 }
870
871 #ifdef FUNNY_CORE_DUMP
872 /* This procedure is due to chris@mimsy.umd.edu.  It makes a core dump
873    without any sort of error status (abort(2) does return an error status,
874    so we don't want to use that).  It is used only when making a preloaded
875    TeX from virtex, and is triggered by a magic file name requested as
876    input (see `open_input', above).  */
877
878 void funny_core_dump (void)
879 {
880   int pid, w;
881   union wait status;
882
883   switch (pid = vfork ())
884   {
885     case -1:
886       perrormod ("vfork");
887       exit (-1);
888
889     case 0:
890        (void) signal (SIGQUIT, SIG_DFL);
891        (void) kill (getpid (), SIGQUIT);
892        (void) write (2, "how did we get here?\n", 21);
893        exit (1);
894
895     default:
896       while ((w = wait (&status)) != pid && w != -1)
897         ;
898
899       if (status.w_coredump)
900         exit (0);
901
902       (void) write (2, "attempt to dump core failed\n", 28);
903       exit (1);
904   }
905 }
906 #endif /* FUNNY_CORE_DUMP */
907 /*
908 #include <tex0.c>
909 #include <tex1.c>
910 #include <tex2.c>
911 #include <tex3.c>
912 #include <tex4.c>
913 #include <tex5.c>
914 #include <tex6.c>
915 #include <tex7.c>
916 #include <tex8.c>
917 #include <tex9.c>
918 */