1 /* Copyright 1992 Karl Berry
2 Copyright 2007 TeX Users Group
3 Copyright 2014 Clerk Ma
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.
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.
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
24 #define dump_ext_length 4
25 #define edit_value tex_edit_value
27 extern char * replacement[];
28 int gargc; /* number of args - set to zero after initialization */
35 int main (int ac, char *av[])
37 int flag = 0, ret = 0;
42 if (main_init(gargc, gargv))
45 TEX_format_default = " plain.fmt";
46 format_default_length = strlen(TEX_format_default + 1);
50 ret = setjmp(jumpbuffer);
54 flag = main_program();
57 printf("EXITING at %s: flag = %d, ret = %d, jump_used = %d\n", "main", flag, ret, jump_used);
62 printf("EXITING at %s: flag = %d, ret = %d, jump_used = %d\n", "jump_out", flag, ret, jump_used);
66 flag = 1; /* do final clean up in local.c */
74 /* texk/web2c/lib/texmfmp.c */
79 buffer[first] = 0; /* In case there are no arguments. */
82 if (gargc > optind && optind > 0)
84 for (i = optind; i < gargc; i++)
88 for (i = 1; i < gargc; i++)
91 if (allow_quoted_names && strchr(gargv[i], ' ') != NULL)
93 (void) strcat ((char *) &buffer[first], "\"");
94 (void) strcat ((char *) &buffer[first], gargv[i]);
95 (void) strcat ((char *) &buffer[first], "\"");
98 (void) strcat ((char *) &buffer[first], gargv[i]);
100 (void) strcat ((char *) &buffer[first], " ");
106 /* Find the end of the buffer. */
107 for (last = first; buffer[last]; ++last)
110 for (--last; last >= first && ISBLANK (buffer[last]) && buffer[last] != '\r'; --last)
115 /* One more time, this time converting to TeX's internal character
116 representation. */ /* for command line input in this case */
119 for (i = first; i < last; i++)
120 buffer[i] = xord[buffer[i]];
124 static void catch_interrupt(int err)
127 (void) signal(SIGINT, SIG_IGN);
129 if (interrupt++ >= 3)
132 (void) signal(SIGINT, catch_interrupt);
135 void fix_date_and_time (void)
143 printf("The time is %lld\n", clock);
146 puts("Time not available!");
148 tmptr = localtime (&clock);
152 printf("Cannot convert time (%0lld)!\n", clock);
156 tex_time = 22 * 60 + 14;
160 tex_time = tmptr->tm_hour * 60 + tmptr->tm_min;
161 day = tmptr->tm_mday;
162 month = tmptr->tm_mon + 1;
163 year = tmptr->tm_year + 1900;
166 printf("%d-%d-%d %d:%d\n",
167 tmptr->tm_year + 1900,
178 if (signal(SIGINT, catch_interrupt) == SIG_ERR)
180 puts(" CTRL-C handler not installed\n");
182 uexit(EXIT_FAILURE); /* do we care when run as DLL ? */
187 void (*old_handler)();
189 if ((old_handler = signal (SIGINT, catch_interrupt)) != SIG_DFL)
190 (void) signal (SIGINT, old_handler);
195 /* I/O for TeX and Metafont. */
196 void complain_line (FILE *output)
200 #ifdef ALLOCATEBUFFER
201 sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", current_buf_size);
203 sprintf(log_line, "! Unable to read an entire line---buf_size=%d.\n", buf_size);
206 fputs(log_line, output);
207 puts(" (File may have a line termination problem.)");
210 void show_bad_line (FILE *output, int first, int last)
215 for (i = first; i <= last; i++)
219 if (show_in_hex && (ch > 127))
244 *s++ = (char) (ch + 64);
250 *s++ = (char) (ch - 64);
261 fputs(log_line, output); // log_file
264 boolean input_line_finish (void)
271 if (last >= max_buf_stack)
272 max_buf_stack = last;
276 i = buffer[last - 1];
278 if (i == ' ' || i == '\t')
284 if (restrict_to_ascii)
288 for (i = first; i <= last; i++)
292 if (ch > 126 || (ch < ' ' && ch != '\t' && ch != '\f' && ch != '\r' && ch != '\n'))
294 sprintf(log_line, "\n! non ASCII char (%d) in line: ", ch);
295 show_line(log_line, 1);
298 fprintf(log_file, "\n! non ASCII char (%d) in line: ", ch);
307 show_bad_line(errout, first, last);
310 show_bad_line(log_file, first, last);
316 for (i = first; i <= last; i++)
317 buffer[i] = xord[buffer[i]];
323 /* Read a line of input into buffer as efficiently as possible (ha ha)
324 while still looking like Pascal.
325 We set `last' to `first' and return `false' if we get to eof.
326 Otherwise, we return `true' and set last = first +
327 length(line except trailing whitespace). */
330 boolean input_line (FILE *f)
332 // int ch, flag; /* for restrict_to_ascii case 94/Jan/21 */
333 char *u; /* 1994/July/3 for key_replace */
336 /* and here is the long way of doing this */
338 /* following is new version with tab expansion and key replacement */
339 /* may want to expand out separately for speed 1994/July/3 */
340 /* different versions depending on return_flag / tabexpand / key_replace */
341 /* while (last < buf_size && (i = getc (f)) != EOF) */
342 #ifdef ALLOCATEBUFFER
345 while (last < buf_size)
352 if (i == EOF || i == '\n' || (i == '\r' && return_flag))
354 else if (i == '\t' && tab_step != 0)
356 buffer[last++] = (ASCII_code) ' ';
358 #ifdef ALLOCATEBUFFER
359 if (last >= current_buf_size)
361 buffer = realloc_buffer(increment_buf_size);
363 if (last >= current_buf_size)
368 #ifdef ALLOCATEBUFFER
369 while ((last - first) % tab_step != 0)
371 while (last < buf_size && (last - first) % tab_step != 0)
375 buffer[last++] = (ASCII_code) ' ';
377 #ifdef ALLOCATEBUFFER
378 if (last >= current_buf_size)
380 buffer = realloc_buffer(increment_buf_size);
382 if (last >= current_buf_size)
392 if (key_replace && (u = replacement[i]) != NULL)
394 #ifdef ALLOCATEBUFFER
397 while (last < buf_size && *u != '\0')
400 buffer[last++] = (ASCII_code) *u++;
401 #ifdef ALLOCATEBUFFER
402 if (last >= current_buf_size)
404 buffer = realloc_buffer(increment_buf_size);
406 if (last >= current_buf_size)
412 else /* normal case */
414 buffer[last++] = (ASCII_code) i;
416 #ifdef ALLOCATEBUFFER
417 if (last >= current_buf_size)
419 buffer = realloc_buffer(increment_buf_size);
421 if (last >= current_buf_size)
428 if (return_flag) /* let return terminate line as well as newline */
430 if (i == '\r') /* see whether return followed by newline */
432 i = getc (f); /* in which case throw away the newline */
439 /* else buffer[last-1] = (ASCII_code) i; */
443 // Turn Ctrl-Z at end of file into newline 2000 June 22
444 if (i == EOF && trimeof && buffer[last - 1] == 26)
449 if (i == EOF && last == first)
452 /* Didn't get the whole line because buffer was too small? */
453 /* This shouldn't happen anymore 99/Jan/23 */
454 if (i != EOF && i != '\n' && i != '\r')
456 complain_line(errout);
459 complain_line(log_file);
461 /* This may no longer be needed ... now that we grow it */
462 if (truncate_long_lines)
464 while (i != EOF && i != '\n' && i != '\r')
466 i = getc (f); // discard rest of line
469 last--; /* just in case */
472 uexit(EXIT_FAILURE); /* line too long */
475 return input_line_finish();
478 /* This string specifies what the `e' option does in response to an
481 static char *edit_value = "c:\\yandy\\WinEdt\\WinEdt.exe [Open('%s');SelLine(%d,7)]";
483 /* This procedure is due to sjc@s1-c. TeX (or Metafont) calls it when
484 the user types `e' in response to an error, invoking a text editor on
485 the erroneous source file. FNSTART is how far into STRINGPOOL the
486 actual filename starts; FNLENGTH is how long the filename is.
488 See ../site.h for how to set the default, and how to override it. */
490 /* called from close_files_and_terminate in tex9.c */
492 void call_edit (ASCII_code *stringpool, pool_pointer fnstart, integer fnlength, integer linenumber)
494 char *command, *s, *t, *u;
496 int sdone, ddone, ldone;
498 unsigned int commandlen;
499 ASCII_code *texfilename;
500 ASCII_code *log_file_name;
501 pool_pointer lgstart;
506 lgstart = str_start[texmf_log_name];
507 lglength = length(texmf_log_name);
508 log_file_name = stringpool + lgstart;
513 log_file_name = (unsigned char *) "";
516 sdone = ddone = ldone = 0;
517 texfilename = stringpool + fnstart;
519 for (i = 1; i <= in_open; i++)
520 (void) fclose (input_file[i]);
524 if (n > 0 && verbose_flag)
526 sprintf(log_line, "Closed %d streams\n", n);
527 show_line(log_line, 0);
530 s = kpse_var_value(edit_value);
535 commandlen = strlen (edit_value) + fnlength + lglength + 10 + 1 + 2;
536 command = (string) xmalloc (commandlen);
542 while ((c = *u++) != 0)
552 sprintf(log_line, "! bad command syntax (%c).\n", 'd');
553 show_line(log_line, 1);
555 sprintf(log_line, "! `%%d' cannot appear twice in editor command.\n");
556 show_line(log_line, 1);
561 (void) sprintf (s, "%lld", linenumber);
573 sprintf(log_line, "! bad command syntax (%c).\n", 's');
574 show_line(log_line, 1);
576 sprintf(log_line, "! `%%s' cannot appear twice in editor command.\n");
577 show_line(log_line, 1);
582 t = (char *) texfilename;
586 for (i = 0; i < n; i++)
589 for (i = 0; i < n; i++)
599 sprintf(log_line, "! bad command syntax (%c).\n", 'l');
600 show_line(log_line, 1);
602 sprintf(log_line, "! `%%l' cannot appear twice in editor command.\n");
603 show_line(log_line, 1);
608 t = (char *) log_file_name;
612 for (i = 0; i < n; i++)
615 for (i = 0; i < n; i++)
636 *s = 0; /* terminate the command string */
638 if (strlen(command) + 1 >= commandlen)
640 sprintf(log_line, "Command too long (%d > %d)\n", strlen(command) + 1, commandlen);
641 show_line(log_line, 1);
648 if (system (command) != 0)
651 sprintf(log_line, "! Error in call: %s\n", command);
652 show_line(log_line, 1);
656 perrormod("! DOS says");
659 sprintf(log_line, " (TEXEDIT=%s)\n", edit_value);
660 show_line(log_line, 0);
661 puts(" (Editor specified may be missing or path may be wrong)\n");
662 puts(" (or there may be missing -- or extraneous -- quotation signs)\n");
669 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
671 /* We don't REALLY care what `endian' the machine is after all ! */
672 /* But we do care about speed - so check exe file for following - bkph */
675 // char swapmarkerstring="ERROR: SWAPPING - NOT BigEndian AND NOT NoFmtBaseSwap";
678 /* This macro is always invoked as a statement. It assumes a variable
681 #define SWAP(x, y) temp = (x); (x) = (y); (y) = temp;
684 /* Make the NITEMS items pointed at by P, each of size SIZE, be the
685 opposite-endianness of whatever they are now. */
687 static int swap_items (char *p, int nitems, int size)
691 /* Since `size' does not change, we can write a while loop for each
692 case, and avoid testing `size' for each time. */
729 sprintf(log_line, "! I can't (un)dump a %d byte item.\n", size);
730 show_line(log_line, 1);
735 #endif /* not WORDS_BIGENDIAN and not NO_FMTBASE_SWAP */
738 int do_dump(char *p, int item_size, int nitems, gzFile out_file)
740 int do_dump(char *p, int item_size, int nitems, FILE *out_file)
743 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
744 swap_items (p, nitems, item_size);
748 if (gzwrite(out_file, p, (item_size * nitems)) != (item_size * nitems))
750 if ((int) fwrite(p, item_size, nitems, out_file) != nitems)
754 sprintf(log_line, "! Could not write %d %d-byte item%s.\n",
755 nitems, item_size, (nitems > 1) ? "s" : "");
756 show_line(log_line, 1);
760 /* Have to restore the old contents of memory, since some of it might get used again. */
761 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
762 swap_items (p, nitems, item_size);
769 int do_undump(char *p, int item_size, int nitems, gzFile in_file)
771 int do_undump(char *p, int item_size, int nitems, FILE *in_file)
775 if (gzread(in_file, (void *) p, (unsigned int) (item_size * nitems)) <= 0)
777 if ((int) fread((void *) p, item_size, nitems, in_file) != nitems)
781 sprintf(log_line, "! Could not read %d %d-byte item%s.\n",
782 nitems, item_size, (nitems > 1) ? "s" : "");
783 show_line(log_line, 1);
787 #if !defined (WORDS_BIGENDIAN) && !defined (NO_FMTBASE_SWAP)
788 swap_items (p, nitems, item_size);
794 #ifdef FUNNY_CORE_DUMP
796 void funny_core_dump (void)
801 switch (pid = vfork ())
808 (void) signal (SIGQUIT, SIG_DFL);
809 (void) kill (getpid (), SIGQUIT);
810 (void) write (2, "how did we get here?\n", 21);
814 while ((w = wait (&status)) != pid && w != -1)
817 if (status.w_coredump)
820 (void) write (2, "attempt to dump core failed\n", 28);
824 #endif /* FUNNY_CORE_DUMP */