synch with TL 37803
[luatex.git] / source / texk / web2c / lib / texmfmp.c
blobbbe10eb376addf643a98646ab1c6ba54e840ed4d
1 /* texmfmp.c: Hand-coded routines for TeX or Metafont in C. Originally
2 written by Tim Morgan, drawing from other Unix ports of TeX. This is
3 a collection of miscellany, everything that's easier (or only
4 possible) to do in C.
6 This file is public domain. */
8 /* This file is included from, e.g., texextra,c after
9 #define EXTERN
10 #include <texd.h>
11 to instantiate data from texd.h here. The ?d.h file is what
12 #defines TeX or MF, which avoids the need for a special
13 Makefile rule. */
15 #include <kpathsea/config.h>
16 #include <kpathsea/c-ctype.h>
17 #include <kpathsea/line.h>
18 #include <kpathsea/readable.h>
19 #include <kpathsea/variable.h>
20 #include <kpathsea/absolute.h>
21 #ifdef WIN32
22 #include <kpathsea/concatn.h>
23 #endif
25 #if defined (HAVE_SYS_TIME_H)
26 #include <sys/time.h>
27 #elif defined (HAVE_SYS_TIMEB_H)
28 #include <sys/timeb.h>
29 #endif
30 #include <time.h> /* For `struct tm'. Moved here for Visual Studio 2005. */
32 #if defined(__STDC__)
33 #include <locale.h>
34 #endif
36 #include <signal.h> /* Catch interrupts. */
38 #include <texmfmp-help.h>
40 /* {tex,mf}d.h defines TeX, MF, INI, and other such symbols.
41 Unfortunately there's no way to get the banner into this code, so
42 just repeat the text. */
43 /* We also define predicates, e.g., IS_eTeX for all e-TeX like engines, so
44 the rest of this file can remain unchanged when adding a new engine. */
45 #ifdef TeX
46 #if defined(XeTeX)
47 #define IS_eTeX 1
48 #include <xetexdir/xetexextra.h>
49 #elif defined (eTeX)
50 #define IS_eTeX 1
51 #include <etexdir/etexextra.h>
52 #elif defined (pdfTeX)
53 #define IS_eTeX 1
54 #include <pdftexdir/pdftexextra.h>
55 #include <pdftexdir/ptexlib.h>
56 #elif defined (Aleph)
57 #define IS_eTeX 1
58 #include <alephdir/alephextra.h>
59 #elif defined (pTeX)
60 #define IS_pTeX 1
61 #include <ptexdir/ptexextra.h>
62 #elif defined (epTeX)
63 #define IS_eTeX 1
64 #define IS_pTeX 1
65 #include <eptexdir/eptexextra.h>
66 #elif defined (upTeX)
67 #define IS_pTeX 1
68 #define IS_upTeX 1
69 #include <uptexdir/uptexextra.h>
70 #elif defined (eupTeX)
71 #define IS_eTeX 1
72 #define IS_pTeX 1
73 #define IS_upTeX 1
74 #include <euptexdir/euptexextra.h>
75 #else
76 #define BANNER "This is TeX, Version 3.14159265"
77 #define COPYRIGHT_HOLDER "D.E. Knuth"
78 #define AUTHOR NULL
79 #define PROGRAM_HELP TEXHELP
80 #define BUG_ADDRESS "tex-k@tug.org"
81 #define DUMP_VAR TEXformatdefault
82 #define DUMP_LENGTH_VAR formatdefaultlength
83 #define DUMP_OPTION "fmt"
84 #define DUMP_EXT ".fmt"
85 #define INPUT_FORMAT kpse_tex_format
86 #define INI_PROGRAM "initex"
87 #define VIR_PROGRAM "virtex"
88 #endif
89 #define edit_var "TEXEDIT"
90 #endif /* TeX */
91 #ifdef MF
92 #if defined(MFLua)
93 #include <mfluadir/mfluaextra.h>
94 #elif defined(MFLuaJIT)
95 #include <mfluajitdir/mfluajitextra.h>
96 #else
97 #define BANNER "This is Metafont, Version 2.7182818"
98 #define COPYRIGHT_HOLDER "D.E. Knuth"
99 #define AUTHOR NULL
100 #define PROGRAM_HELP MFHELP
101 #define BUG_ADDRESS "tex-k@tug.org"
102 #define DUMP_VAR MFbasedefault
103 #define DUMP_LENGTH_VAR basedefaultlength
104 #define DUMP_OPTION "base"
105 #ifdef DOS
106 #define DUMP_EXT ".bas"
107 #else
108 #define DUMP_EXT ".base"
109 #endif
110 #define INPUT_FORMAT kpse_mf_format
111 #define INI_PROGRAM "inimf"
112 #define VIR_PROGRAM "virmf"
113 #endif
114 #define edit_var "MFEDIT"
115 #endif /* MF */
117 #if !defined(IS_eTeX)
118 # define IS_eTeX 0
119 #endif
120 #if !defined(IS_pTeX)
121 # define IS_pTeX 0
122 #endif
123 #if !defined(IS_upTeX)
124 # define IS_upTeX 0
125 #endif
127 #if defined(__SyncTeX__)
129 SyncTeX file name should be full path in the case where
130 --output-directory option is given.
131 Borrowed from LuaTeX.
133 char *generic_synctex_get_current_name (void)
135 char *pwdbuf, *ret;
136 if (!fullnameoffile) {
137 ret = xstrdup("");
138 return ret;
140 if (kpse_absolute_p(fullnameoffile, false)) {
141 return xstrdup(fullnameoffile);
143 pwdbuf = xgetcwd();
144 ret = concat3(pwdbuf, DIR_SEP_STRING, fullnameoffile);
145 free(pwdbuf) ;
146 return ret;
148 #endif
150 #ifdef WIN32
151 #if !IS_pTeX
152 FILE *Poptr;
153 #endif
154 #endif
156 #if defined(TeX) || (defined(MF) && defined(WIN32))
157 static int
158 Isspace (char c)
160 return (c == ' ' || c == '\t');
162 #endif /* TeX || (MF && WIN32) */
164 #ifdef TeX
166 /* Shell escape.
168 If shellenabledp == 0, all shell escapes are forbidden.
169 If (shellenabledp == 1 && restrictedshell == 0), any command
170 is allowed for a shell escape.
171 If (shellenabledp == 1 && restrictedshell == 1), only commands
172 given in the configuration file as
173 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun,...
174 (no spaces between commands) in texmf.cnf are allowed for a shell
175 escape in a restricted form: command name and arguments should be
176 separated by a white space. The first word should be a command
177 name. The quotation character for an argument with spaces,
178 including a pathname, should be ". ' should not be used.
180 Internally, all arguments are quoted by ' (Unix) or " (Windows)
181 before calling the system() function in order to forbid execution
182 of any embedded command. In addition, on Windows, special
183 characters of cmd.exe are escaped by using (^).
185 If the --shell-escape option is given, we set
186 shellenabledp = 1 and restrictedshell = 0, i.e., any command is allowed.
187 If the --shell-restricted option is given, we set
188 shellenabledp = 1 and restrictedshell = 1, i.e., only given cmds allowed.
189 If the --no-shell-escape option is given, we set
190 shellenabledp = -1 (and restrictedshell is irrelevant).
191 If none of these option are given, there are three cases:
192 (1) In the case where
193 shell_escape = y or
194 shell_escape = t or
195 shell_escape = 1
196 it becomes shellenabledp = 1 and restrictedshell = 0,
197 that is, any command is allowed.
198 (2) In the case where
199 shell_escape = p
200 it becomes shellenabledp = 1 and restrictedshell = 1,
201 that is, restricted shell escape is allowed.
202 (3) In all other cases, shellenabledp = 0, that is, shell
203 escape is forbidden. The value of restrictedshell is
204 irrelevant if shellenabledp == 0.
207 /* cmdlist is a list of allowed commands which are given like this:
208 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun
209 in texmf.cnf. */
211 static char **cmdlist = NULL;
213 static void
214 mk_shellcmdlist (char *v)
216 char **p;
217 char *q, *r;
218 size_t n;
220 q = v;
221 n = 1;
223 /* analyze the variable shell_escape_commands = foo,bar,...
224 spaces before and after (,) are not allowed. */
226 while ((r = strchr (q, ',')) != 0) {
227 n++;
228 q = r + 1;
230 if (*q)
231 n++;
232 cmdlist = xmalloc (n * sizeof (char *));
233 p = cmdlist;
234 q = v;
235 while ((r = strchr (q, ',')) != 0) {
236 *r = '\0';
237 *p++ = xstrdup (q);
238 q = r + 1;
240 if (*q)
241 *p++ = xstrdup (q);
242 *p = NULL;
245 static void
246 init_shell_escape (void)
248 if (shellenabledp < 0) { /* --no-shell-escape on cmd line */
249 shellenabledp = 0;
251 } else {
252 if (shellenabledp == 0) { /* no shell options on cmd line, check cnf */
253 char *v1 = kpse_var_value ("shell_escape");
254 if (v1) {
255 if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
256 shellenabledp = 1;
257 } else if (*v1 == 'p') {
258 shellenabledp = 1;
259 restrictedshell = 1;
261 free (v1);
265 /* If shell escapes are restricted, get allowed cmds from cnf. */
266 if (shellenabledp && restrictedshell == 1) {
267 char *v2 = kpse_var_value ("shell_escape_commands");
268 if (v2) {
269 mk_shellcmdlist (v2);
270 free (v2);
276 #ifdef WIN32
277 #define QUOTE '"'
278 #else
279 #define QUOTE '\''
280 #endif
282 #ifdef WIN32
283 static int
284 char_needs_quote (int c)
286 /* special characters of cmd.exe */
288 return (c == '&' || c == '|' || c == '%' || c == '<' ||
289 c == '>' || c == ';' || c == ',' || c == '(' ||
290 c == ')');
292 #endif
294 /* return values:
295 -1 : invalid quotation of an argument
296 0 : command is not allowed
297 2 : restricted shell escape, CMD is allowed.
299 We set *SAFECMD to a safely-quoted version of *CMD; this is what
300 should get executed. And we set CMDNAME to its first word; this is
301 what is checked against the shell_escape_commands list. */
303 static int
304 shell_cmd_is_allowed (const char *cmd, char **safecmd, char **cmdname)
306 char **p;
307 char *buf;
308 char *c, *d;
309 const char *s;
310 int pre, spaces;
311 int allow = 0;
313 /* pre == 1 means that the previous character is a white space
314 pre == 0 means that the previous character is not a white space */
315 buf = xmalloc (strlen (cmd) + 1);
316 strcpy (buf, cmd);
317 c = buf;
318 while (Isspace (*c))
319 c++;
320 d = c;
321 while (!Isspace(*d) && *d)
322 d++;
323 *d = '\0';
325 /* *cmdname is the first word of the command line. For example,
326 *cmdname == "kpsewhich" for
327 \write18{kpsewhich --progname=dvipdfm --format="other text files" config}
329 *cmdname = xstrdup (c);
330 free (buf);
332 /* Is *cmdname listed in a texmf.cnf vriable as
333 shell_escape_commands = foo,bar,... ? */
334 p = cmdlist;
335 if (p) {
336 while (*p) {
337 if (strcmp (*p, *cmdname) == 0) {
338 /* *cmdname is found in the list, so restricted shell escape
339 is allowed */
340 allow = 2;
341 break;
343 p++;
346 if (allow == 2) {
347 spaces = 0;
348 for (s = cmd; *s; s++) {
349 if (Isspace (*s))
350 spaces++;
353 /* allocate enough memory (too much?) */
354 #ifdef WIN32
355 *safecmd = xmalloc (2 * strlen (cmd) + 3 + 2 * spaces);
356 #else
357 *safecmd = xmalloc (strlen (cmd) + 3 + 2 * spaces);
358 #endif
360 /* make a safe command line *safecmd */
361 s = cmd;
362 while (Isspace (*s))
363 s++;
364 d = *safecmd;
365 while (!Isspace (*s) && *s)
366 *d++ = *s++;
368 pre = 1;
369 while (*s) {
370 /* Quotation given by a user. " should always be used; we
371 transform it below. If ' is used, simply immediately
372 return a quotation error. */
373 if (*s == '\'') {
374 return -1;
377 if (*s == '"') {
378 /* All arguments are quoted as 'foo' (Unix) or "foo" (Windows)
379 before calling system(). Therefore closing QUOTE is necessary
380 if the previous character is not a white space.
381 example:
382 --format="other text files" becomes
383 '--format=''other text files' (Unix)
384 "--format=""other text files" (Windows) */
386 if (pre == 0)
387 *d++ = QUOTE;
389 pre = 0;
390 /* output the quotation mark for the quoted argument */
391 *d++ = QUOTE;
392 s++;
394 while (*s != '"') {
395 /* Illegal use of ', or closing quotation mark is missing */
396 if (*s == '\'' || *s == '\0')
397 return -1;
398 #ifdef WIN32
399 if (char_needs_quote (*s))
400 *d++ = '^';
401 #endif
402 *d++ = *s++;
405 /* Closing quotation mark will be output afterwards, so
406 we do nothing here */
407 s++;
409 /* The character after the closing quotation mark
410 should be a white space or NULL */
411 if (!Isspace (*s) && *s)
412 return -1;
414 /* Beginning of a usual argument */
415 } else if (pre == 1 && !Isspace (*s)) {
416 pre = 0;
417 *d++ = QUOTE;
418 #ifdef WIN32
419 if (char_needs_quote (*s))
420 *d++ = '^';
421 #endif
422 *d++ = *s++;
423 /* Ending of a usual argument */
425 } else if (pre == 0 && Isspace (*s)) {
426 pre = 1;
427 /* Closing quotation mark */
428 *d++ = QUOTE;
429 *d++ = *s++;
430 } else {
431 /* Copy a character from cmd to *safecmd. */
432 #ifdef WIN32
433 if (char_needs_quote (*s))
434 *d++ = '^';
435 #endif
436 *d++ = *s++;
439 /* End of the command line */
440 if (pre == 0) {
441 *d++ = QUOTE;
443 *d = '\0';
444 #ifdef WIN32
446 char *p, *q, *r;
447 p = *safecmd;
448 if (strlen (p) > 2 && p[1] == ':' && !IS_DIR_SEP (p[2])) {
449 q = xmalloc (strlen (p) + 2);
450 q[0] = p[0];
451 q[1] = p[1];
452 q[2] = '/';
453 q[3] = '\0';
454 strcat (q, (p + 2));
455 free (*safecmd);
456 *safecmd = q;
457 } else if (!IS_DIR_SEP (p[0]) && !(p[1] == ':' && IS_DIR_SEP (p[2]))) {
458 p = kpse_var_value ("SELFAUTOLOC");
459 if (p) {
460 r = *safecmd;
461 while (*r && !Isspace(*r))
462 r++;
463 if (*r == '\0')
464 q = concatn ("\"", p, "/", *safecmd, "\"", NULL);
465 else {
466 *r = '\0';
467 r++;
468 while (*r && Isspace(*r))
469 r++;
470 if (*r)
471 q = concatn ("\"", p, "/", *safecmd, "\" ", r, NULL);
472 else
473 q = concatn ("\"", p, "/", *safecmd, "\"", NULL);
475 free (p);
476 free (*safecmd);
477 *safecmd = q;
481 #endif
484 return allow;
487 /* We should only be called with shellenabledp == 1.
488 Return value:
489 -1 if a quotation syntax error.
490 0 if CMD is not allowed; given shellenabledp==1, this is because
491 shell escapes are restricted and CMD is not allowed.
492 1 if shell escapes are not restricted, hence any command is allowed.
493 2 if shell escapes are restricted and CMD is allowed (possibly after
494 quoting). */
496 #ifdef WIN32
497 #undef system
498 #define system fsyscp_system
499 #if ENABLE_PIPES
500 #undef popen
501 #define popen fsyscp_popen
502 #endif /* ENABLE_PIPES */
503 #endif /* WIN32 */
506 runsystem (const char *cmd)
508 int allow = 0;
509 char *safecmd = NULL;
510 char *cmdname = NULL;
512 if (shellenabledp <= 0) {
513 return 0;
516 /* If restrictedshell == 0, any command is allowed. */
517 if (restrictedshell == 0)
518 allow = 1;
519 else
520 allow = shell_cmd_is_allowed (cmd, &safecmd, &cmdname);
522 if (allow == 1)
523 (void) system (cmd);
524 else if (allow == 2)
525 (void) system (safecmd);
527 if (safecmd)
528 free (safecmd);
529 if (cmdname)
530 free (cmdname);
532 return allow;
534 #endif /* TeX */
536 #if ENABLE_PIPES
537 /* Like runsystem(), the runpopen() function is called only when
538 shellenabledp == 1. Unlike runsystem(), here we write errors to
539 stderr, since we have nowhere better to use; and of course we return
540 a file handle (or NULL) instead of a status indicator. */
542 static FILE *
543 runpopen (char *cmd, const char *mode)
545 FILE *f = NULL;
546 char *safecmd = NULL;
547 char *cmdname = NULL;
548 int allow;
550 #ifdef WIN32
551 char *pp;
553 for (pp = cmd; *pp; pp++) {
554 if (*pp == '\'') *pp = '"';
556 #endif
558 /* If restrictedshell == 0, any command is allowed. */
559 if (restrictedshell == 0)
560 allow = 1;
561 else
562 allow = shell_cmd_is_allowed (cmd, &safecmd, &cmdname);
564 if (allow == 1)
565 f = popen (cmd, mode);
566 else if (allow == 2)
567 f = popen (safecmd, mode);
568 else if (allow == -1)
569 fprintf (stderr, "\nrunpopen quotation error in command line: %s\n",
570 cmd);
571 else
572 fprintf (stderr, "\nrunpopen command not allowed: %s\n", cmdname);
574 if (safecmd)
575 free (safecmd);
576 if (cmdname)
577 free (cmdname);
578 return f;
580 #endif /* ENABLE_PIPES */
582 /* The main program, etc. */
584 #ifdef XeTeX
585 #include "xetexdir/XeTeX_ext.h"
586 #endif
588 /* What we were invoked as and with. */
589 char **argv;
590 int argc;
592 /* If the user overrides argv[0] with -progname. */
593 static const_string user_progname;
595 /* The C version of the jobname, if given. */
596 static const_string c_job_name;
598 /* The filename for dynamic character translation, or NULL. */
599 string translate_filename;
600 string default_translate_filename;
602 #if defined(TeX)
603 /* Needed for --src-specials option. */
604 static char *last_source_name;
605 static int last_lineno;
606 static boolean srcspecialsoption = false;
607 static void parse_src_specials_option (const_string);
608 #endif
610 /* Parsing a first %&-line in the input file. */
611 static void parse_first_line (const_string);
613 /* Parse option flags. */
614 static void parse_options (int, string *);
616 /* Try to figure out if we have been given a filename. */
617 static string get_input_file_name (void);
619 /* Get a true/false value for a variable from texmf.cnf and the environment. */
620 static boolean
621 texmf_yesno(const_string var)
623 string value = kpse_var_value (var);
624 return value && (*value == 't' || *value == 'y' || *value == '1');
627 #ifdef pdfTeX
628 const char *ptexbanner = BANNER;
629 #endif
631 #ifdef WIN32
632 /* forward declaration */
633 static string
634 normalize_quotes (const_string name, const_string mesg);
635 #ifndef TeX
636 int srcspecialsp = 0;
637 #endif
638 /* Support of 8.3-name convention. If *buffer == NULL, nothing is done. */
639 static void change_to_long_name (char **buffer)
641 if (*buffer) {
642 char inbuf[260];
643 char outbuf[260];
645 memset (outbuf, 0, 260);
646 strcpy (inbuf, *buffer);
647 if (GetLongPathName (inbuf, outbuf, 260)) {
648 *buffer = (char *)realloc(*buffer, strlen(outbuf) + 1);
649 strcpy (*buffer, outbuf);
653 #endif /* WIN32 */
655 /* The entry point: set up for reading the command line, which will
656 happen in `topenin', then call the main body. */
658 void
659 maininit (int ac, string *av)
661 string main_input_file;
662 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
663 string enc;
664 #endif
665 /* Save to pass along to topenin. */
666 argc = ac;
667 argv = av;
669 /* Must be initialized before options are parsed. */
670 interactionoption = 4;
672 /* Have things to record as we go along. */
673 kpse_record_input = recorder_record_input;
674 kpse_record_output = recorder_record_output;
676 #if defined(__SyncTeX__)
677 /* 0 means "disable Synchronize TeXnology".
678 synctexoption is a *.web variable.
679 We initialize it to a weird value to catch the -synctex command line flag.
680 At runtime, if synctexoption is not INT_MAX, then it contains the
681 command line option provided; otherwise, no such option was given
682 by the user. */
683 # define SYNCTEX_NO_OPTION INT_MAX
684 synctexoption = SYNCTEX_NO_OPTION;
685 #endif
687 #if IS_pTeX
688 kpse_set_program_name (argv[0], NULL);
689 initkanji ();
690 #endif
691 #if defined(XeTeX) && defined(WIN32)
692 kpse_set_program_name (argv[0], NULL);
693 #endif
694 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
695 enc = kpse_var_value("command_line_encoding");
696 get_command_line_args_utf8(enc, &argc, &argv);
697 #endif
699 /* If the user says --help or --version, we need to notice early. And
700 since we want the --ini option, have to do it before getting into
701 the web (which would read the base file, etc.). */
702 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
703 parse_options (argc, argv);
704 #else
705 parse_options (ac, av);
706 #endif
708 #if IS_pTeX
709 /* In pTeX and friends, texmf.cnf is not recorded in the case of --recorder,
710 because parse_options() is executed after the start of kpathsea due to
711 special initializations. Therefore we record texmf.cnf here. */
712 if (recorder_enabled) {
713 string p = kpse_find_file ("texmf.cnf", kpse_cnf_format, 0);
714 if (p)
715 recorder_record_input (p);
717 #endif
719 /* If -progname was not specified, default to the dump name. */
720 if (!user_progname)
721 user_progname = dump_name;
723 /* Do this early so we can inspect kpse_invocation_name and
724 kpse_program_name below, and because we have to do this before
725 any path searching. */
726 #if IS_pTeX || (defined(XeTeX) && defined(WIN32))
727 if (user_progname)
728 kpse_reset_program_name (user_progname);
729 #else
730 kpse_set_program_name (argv[0], user_progname);
731 #endif
733 #if defined(MF)
734 #if defined(MFLua)
735 /* If the program name is "mflua-nowin", then reset the name as "mflua". */
736 if (strncasecmp (kpse_invocation_name, "mflua-nowin", 11) == 0)
737 kpse_reset_program_name ("mflua");
738 #elif defined(MFLuaJIT)
739 /* If the program name is "mfluajit-nowin", then reset the name as "mfluajit". */
740 if (strncasecmp (kpse_invocation_name, "mfluajit-nowin", 14) == 0)
741 kpse_reset_program_name ("mfluajit");
742 #else
743 /* If the program name is "mf-nowin", then reset the name as "mf". */
744 if (strncasecmp (kpse_invocation_name, "mf-nowin", 8) == 0)
745 kpse_reset_program_name ("mf");
746 #endif
747 #endif
749 /* FIXME: gather engine names in a single spot. */
750 xputenv ("engine", TEXMFENGINENAME);
752 /* Were we given a simple filename? */
753 main_input_file = get_input_file_name();
755 #ifdef WIN32
756 if (main_input_file == NULL) {
757 string name;
758 #ifndef XeTeX
759 boolean quoted;
760 #endif
762 name = argv[argc-1];
763 if (name && name[0] != '-' && name[0] != '&' && name[0] != '\\') {
764 if (strlen (name) > 2 && isalpha (name[0]) && name[1] == ':' &&
765 name[2] == '\\') {
766 string pp;
767 for (pp = name; *pp; pp++) {
768 if (IS_KANJI (pp))
769 pp++;
770 else if (*pp == '\\')
771 *pp = '/';
774 #ifdef XeTeX
775 name = normalize_quotes(argv[argc-1], "argument");
776 main_input_file = kpse_find_file(argv[argc-1], INPUT_FORMAT, false);
777 if (!srcspecialsp) {
778 change_to_long_name (&main_input_file);
779 if (main_input_file)
780 name = normalize_quotes(main_input_file, "argument");
782 argv[argc-1] = name;
783 #else
784 name = normalize_quotes(argv[argc-1], "argument");
785 quoted = (name[0] == '"');
786 if (quoted) {
787 /* Overwrite last quote and skip first quote. */
788 name[strlen(name)-1] = '\0';
789 name++;
791 main_input_file = kpse_find_file(name, INPUT_FORMAT, false);
792 if (!srcspecialsp)
793 change_to_long_name (&main_input_file);
794 if (quoted) {
795 /* Undo modifications */
796 name[strlen(name)] = '"';
797 name--;
799 if (!srcspecialsp) {
800 if (main_input_file)
801 name = normalize_quotes(main_input_file, "argument");
803 argv[argc-1] = name;
804 #endif
807 #endif /* WIN32 */
809 /* Second chance to activate file:line:error style messages, this
810 time from texmf.cnf. */
811 if (filelineerrorstylep < 0) {
812 filelineerrorstylep = 0;
813 } else if (!filelineerrorstylep) {
814 filelineerrorstylep = texmf_yesno ("file_line_error_style");
817 /* If no dump default yet, and we're not doing anything special on
818 this run, we may want to look at the first line of the main input
819 file for a %&<dumpname> specifier. */
820 if (parsefirstlinep < 0) {
821 parsefirstlinep = 0;
822 } else if (!parsefirstlinep) {
823 parsefirstlinep = texmf_yesno ("parse_first_line");
825 if (parsefirstlinep && (!dump_name || !translate_filename)) {
826 parse_first_line (main_input_file);
828 /* Check whether there still is no translate_filename known. If so,
829 use the default_translate_filename. */
830 /* FIXME: deprecated. */
831 if (!translate_filename) {
832 translate_filename = default_translate_filename;
834 /* If we're preloaded, I guess everything is set up. I don't really
835 know any more, it's been so long since anyone preloaded. */
836 if (readyalready != 314159) {
837 /* The `ini_version' variable is declared/used in the change files. */
838 boolean virversion = false;
839 if (FILESTRCASEEQ (kpse_program_name, INI_PROGRAM)) {
840 iniversion = true;
841 } else if (FILESTRCASEEQ (kpse_program_name, VIR_PROGRAM)) {
842 virversion = true;
843 #ifdef TeX
844 } else if (FILESTRCASEEQ (kpse_program_name, "initex")) {
845 iniversion = true;
846 } else if (FILESTRCASEEQ (kpse_program_name, "virtex")) {
847 virversion = true;
848 #ifndef Aleph
849 } else if (FILESTRCASEEQ (kpse_program_name, "mltex")) {
850 mltexp = true;
851 #endif /* !Aleph */
852 #endif /* TeX */
855 if (!dump_name) {
856 /* If called as *vir{mf,tex,mpost} use `plain'. Otherwise, use the
857 name we were invoked under. */
858 dump_name = (virversion ? "plain" : kpse_program_name);
862 #ifdef TeX
863 /* Sanity check: -mltex, -enc, -etex only work in combination with -ini. */
864 if (!iniversion) {
865 #if !defined(Aleph)
866 if (mltexp) {
867 fprintf(stderr, "-mltex only works with -ini\n");
869 #if !defined(XeTeX) && !IS_pTeX
870 if (enctexp) {
871 fprintf(stderr, "-enc only works with -ini\n");
873 #endif
874 #endif
875 #if IS_eTeX
876 if (etexp) {
877 fprintf(stderr, "-etex only works with -ini\n");
879 #endif
881 #endif
883 /* If we've set up the fmt/base default in any of the various ways
884 above, also set its length. */
885 if (dump_name) {
886 const_string with_ext = NULL;
887 unsigned name_len = strlen (dump_name);
888 unsigned ext_len = strlen (DUMP_EXT);
890 /* Provide extension if not there already. */
891 if (name_len > ext_len
892 && FILESTRCASEEQ (dump_name + name_len - ext_len, DUMP_EXT)) {
893 with_ext = dump_name;
894 } else {
895 with_ext = concat (dump_name, DUMP_EXT);
897 DUMP_VAR = concat (" ", with_ext); /* adjust array for Pascal */
898 DUMP_LENGTH_VAR = strlen (DUMP_VAR + 1);
899 } else {
900 /* For dump_name to be NULL is a bug. */
901 abort();
904 /* Additional initializations. No particular reason for doing them
905 here instead of first thing in the change file; less symbols to
906 propagate through Webc, that's all. */
907 #ifdef MF
908 kpse_set_program_enabled (kpse_mf_format, MAKE_TEX_MF_BY_DEFAULT,
909 kpse_src_compile);
910 kpse_set_program_enabled (kpse_base_format, MAKE_TEX_FMT_BY_DEFAULT,
911 kpse_src_compile);
912 #endif /* MF */
913 #ifdef TeX
914 #if defined (Aleph)
915 kpse_set_program_enabled (kpse_ocp_format, MAKE_OMEGA_OCP_BY_DEFAULT,
916 kpse_src_compile);
917 kpse_set_program_enabled (kpse_ofm_format, MAKE_OMEGA_OFM_BY_DEFAULT,
918 kpse_src_compile);
919 kpse_set_program_enabled (kpse_tfm_format, false, kpse_src_compile);
920 #else /* !Aleph */
921 kpse_set_program_enabled (kpse_tfm_format, MAKE_TEX_TFM_BY_DEFAULT,
922 kpse_src_compile);
923 #endif /* !Aleph */
924 kpse_set_program_enabled (kpse_tex_format, MAKE_TEX_TEX_BY_DEFAULT,
925 kpse_src_compile);
926 kpse_set_program_enabled (kpse_fmt_format, MAKE_TEX_FMT_BY_DEFAULT,
927 kpse_src_compile);
929 init_shell_escape ();
931 if (!outputcomment) {
932 outputcomment = kpse_var_value ("output_comment");
934 #endif /* TeX */
937 /* The entry point: set up for reading the command line, which will
938 happen in `topenin', then call the main body. */
941 #if defined(DLLPROC)
942 DLLPROC (int ac, string *av)
943 #else
944 main (int ac, string *av)
945 #endif
947 #ifdef __EMX__
948 _wildcard (&ac, &av);
949 _response (&ac, &av);
950 #endif
952 #ifdef WIN32
953 av[0] = kpse_program_basename (av[0]);
954 _setmaxstdio(2048);
955 setmode(fileno(stdin), _O_BINARY);
956 #endif
958 maininit (ac, av);
960 #ifdef WIN32
961 if (ac > 1) {
962 char *pp;
963 if ((strlen(av[ac-1]) > 2) &&
964 isalpha(av[ac-1][0]) &&
965 (av[ac-1][1] == ':') &&
966 (av[ac-1][2] == '\\')) {
967 for (pp=av[ac-1]+2; *pp; pp++) {
968 if (IS_KANJI(pp)) {
969 pp++;
970 continue;
972 if (*pp == '\\')
973 *pp = '/';
977 #endif
979 /* Call the real main program. */
980 mainbody ();
982 return EXIT_SUCCESS;
985 /* This is supposed to ``open the terminal for input'', but what we
986 really do is copy command line arguments into TeX's or Metafont's
987 buffer, so they can handle them. If nothing is available, or we've
988 been called already (and hence, argc==0), we return with
989 `last=first'. */
991 void
992 topenin (void)
994 int i;
996 #ifdef XeTeX
997 static UFILE termin_file;
998 if (termin == 0) {
999 termin = &termin_file;
1000 termin->f = stdin;
1001 termin->savedChar = -1;
1002 termin->skipNextLF = 0;
1003 termin->encodingMode = UTF8;
1004 termin->conversionData = 0;
1005 inputfile[0] = termin;
1007 #endif
1009 buffer[first] = 0; /* In case there are no arguments. */
1011 if (optind < argc) { /* We have command line arguments. */
1012 int k = first;
1013 for (i = optind; i < argc; i++) {
1014 #ifdef XeTeX
1015 unsigned char *ptr = (unsigned char *)&(argv[i][0]);
1016 /* need to interpret UTF8 from the command line */
1017 UInt32 rval;
1018 while ((rval = *(ptr++)) != 0) {
1019 UInt16 extraBytes = bytesFromUTF8[rval];
1020 switch (extraBytes) { /* note: code falls through cases! */
1021 case 5: rval <<= 6; if (*ptr) rval += *(ptr++);
1022 case 4: rval <<= 6; if (*ptr) rval += *(ptr++);
1023 case 3: rval <<= 6; if (*ptr) rval += *(ptr++);
1024 case 2: rval <<= 6; if (*ptr) rval += *(ptr++);
1025 case 1: rval <<= 6; if (*ptr) rval += *(ptr++);
1026 case 0: ;
1028 rval -= offsetsFromUTF8[extraBytes];
1029 buffer[k++] = rval;
1031 #else
1032 char *ptr = &(argv[i][0]);
1033 /* Don't use strcat, since in Aleph the buffer elements aren't
1034 single bytes. */
1035 while (*ptr) {
1036 buffer[k++] = *(ptr++);
1038 #endif
1039 buffer[k++] = ' ';
1041 argc = 0; /* Don't do this again. */
1042 buffer[k] = 0;
1045 /* Find the end of the buffer. */
1046 for (last = first; buffer[last]; ++last)
1049 /* Make `last' be one past the last non-blank character in `buffer'. */
1050 /* ??? The test for '\r' should not be necessary. */
1051 for (--last; last >= first
1052 && ISBLANK (buffer[last]) && buffer[last] != '\r'; --last)
1054 last++;
1056 /* One more time, this time converting to TeX's internal character
1057 representation. */
1058 #if !defined(Aleph) && !defined(XeTeX)
1059 for (i = first; i < last; i++)
1060 buffer[i] = xord[buffer[i]];
1061 #endif
1064 /* IPC for TeX. By Tom Rokicki for the NeXT; it makes TeX ship out the
1065 DVI file in a pipe to TeXView so that the output can be displayed
1066 incrementally. Shamim Mohamed adapted it for Web2c. */
1067 #if defined (TeX) && defined (IPC)
1069 #ifdef WIN32
1070 #undef _WINSOCKAPI_
1071 #include <winsock2.h>
1072 #else
1073 #include <sys/socket.h>
1074 #include <fcntl.h>
1075 #ifndef O_NONBLOCK /* POSIX */
1076 #ifdef O_NDELAY /* BSD */
1077 #define O_NONBLOCK O_NDELAY
1078 #elif defined(O_FNDELAY) /* NeXT */
1079 #define O_NONBLOCK O_FNDELAY
1080 #else
1081 what the fcntl? cannot implement IPC without equivalent for O_NONBLOCK.
1082 #endif
1083 #endif /* no O_NONBLOCK */
1084 #endif /* !WIN32 */
1086 #ifdef WIN32
1087 # define IPC_AF AF_INET
1088 # ifndef IPC_LOCAL_HOST
1089 # define IPC_LOCAL_HOST "127.0.0.1"
1090 # define FIXED_PORT (unsigned short)4242
1091 # endif
1092 #else
1093 # define IPC_AF AF_UNIX
1094 # ifndef IPC_PIPE_NAME /* $HOME is prepended to this. */
1095 # define IPC_PIPE_NAME "/.TeXview_Pipe"
1096 # endif
1097 #endif
1098 #ifndef IPC_SERVER_CMD /* Command to run to start the server. */
1099 # ifdef WIN32
1100 # define IPC_SERVER_CMD "texview.exe"
1101 # else
1102 # define IPC_SERVER_CMD "open `which TeXview`"
1103 # endif
1104 #endif
1106 struct msg
1108 int namelength; /* length of auxiliary data */
1109 int eof; /* new eof for dvi file */
1110 #if 0 /* see usage of struct msg below */
1111 char more_data[0]; /* where the rest of the stuff goes */
1112 #endif
1115 static struct sockaddr *ipc_addr;
1116 static int ipc_addr_len;
1118 static int
1119 ipc_make_name (void)
1121 if (ipc_addr_len == 0) {
1122 #ifdef WIN32
1123 unsigned long remote_addr = inet_addr(IPC_LOCAL_HOST);
1124 if (remote_addr != INADDR_NONE) {
1125 struct sockaddr_in *ipc_sin_addr = xmalloc (sizeof (struct sockaddr_in));
1126 ipc_sin_addr->sin_family = AF_INET;
1127 ipc_sin_addr->sin_addr.s_addr = remote_addr;
1128 ipc_sin_addr->sin_port = htons (FIXED_PORT);
1129 ipc_addr = ((struct sockaddr *) ipc_sin_addr);
1130 ipc_addr_len = sizeof(struct sockaddr_in);
1132 #else
1133 string s = getenv ("HOME");
1134 if (s) {
1135 char *ipc_name;
1136 ipc_addr = xmalloc (strlen (s) + 40);
1137 ipc_addr->sa_family = 0;
1138 ipc_name = ipc_addr->sa_data;
1139 strcpy (ipc_name, s);
1140 strcat (ipc_name, IPC_PIPE_NAME);
1141 ipc_addr_len = strlen (ipc_name) + 3;
1143 #endif
1145 return ipc_addr_len;
1148 static int sock = -1;
1150 #ifdef WIN32
1151 # define CLOSE_SOCKET(s) closesocket (s); WSACleanup ()
1152 #else
1153 # define CLOSE_SOCKET(s) close (s)
1154 #endif
1156 static int
1157 ipc_is_open (void)
1159 return sock != -1;
1162 static void
1163 ipc_open_out (void) {
1164 #ifdef WIN32
1165 struct WSAData wsaData;
1166 int nCode;
1167 unsigned long mode = 1;
1168 #endif
1169 #ifdef IPC_DEBUG
1170 fputs ("tex: Opening socket for IPC output ...\n", stderr);
1171 #endif
1172 if (sock != -1) {
1173 return;
1176 #ifdef WIN32
1177 if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) {
1178 fprintf(stderr,"WSAStartup() returned error code %d.\n", nCode);
1179 return;
1181 #endif
1183 if (ipc_make_name () <= 0)
1184 return;
1186 sock = socket (IPC_AF, SOCK_STREAM, 0);
1187 #ifdef IPC_DEBUG
1188 if(sock != -1)
1189 fprintf(stderr, "tex: Socket handle is %d\n", sock);
1190 else
1191 fprintf(stderr, "tex: Socket is invalid.\n");
1192 #endif
1194 if (sock != -1) {
1195 if (connect (sock, ipc_addr, ipc_addr_len) != 0 ||
1196 #ifdef WIN32
1197 ioctlsocket (sock, FIONBIO, &mode) < 0
1198 #else
1199 fcntl (sock, F_SETFL, O_NONBLOCK) < 0
1200 #endif
1202 CLOSE_SOCKET (sock);
1203 sock = -1;
1204 #ifdef IPC_DEBUG
1205 fputs ("tex: IPC socket cannot be connected.\n", stderr);
1206 fputs ("tex: Socket is closed.\n", stderr);
1207 #endif
1208 return;
1210 #ifdef IPC_DEBUG
1211 fputs ("tex: Successfully opened IPC socket.\n", stderr);
1212 #endif
1216 static void
1217 ipc_close_out (void)
1219 #ifdef IPC_DEBUG
1220 fputs ("tex: Closing output socket ...\n", stderr);
1221 #endif
1222 if (ipc_is_open ()) {
1223 CLOSE_SOCKET (sock);
1224 sock = -1;
1228 static void
1229 ipc_snd (int n, int is_eof, char *data)
1231 struct
1233 struct msg msg;
1234 char more_data[1024];
1235 } ourmsg;
1237 if (!ipc_is_open ()) {
1238 return;
1241 #ifdef IPC_DEBUG
1242 fprintf(stderr, "%d\t%d\n", ourmsg.msg.namelength, ourmsg.msg.eof);
1243 fputs ("tex: Sending message to socket ...\n", stderr);
1244 #endif
1245 ourmsg.msg.namelength = n;
1246 ourmsg.msg.eof = is_eof;
1247 if (n) {
1248 strcpy (ourmsg.more_data, data);
1250 n += sizeof (struct msg);
1251 #ifdef IPC_DEBUG
1252 fprintf(stderr, "%d\t%d\n", ourmsg.msg.namelength, ourmsg.msg.eof);
1253 fputs ("tex: Writing to socket...\n", stderr);
1254 #endif
1255 #if defined(WIN32)
1256 if (send (sock, (char *)&ourmsg, n, 0) != n) {
1257 #else
1258 if (write (sock, &ourmsg, n) != n) {
1259 #endif
1260 ipc_close_out ();
1262 #ifdef IPC_DEBUG
1263 fputs ("tex: IPC message sent.\n", stderr);
1264 #endif
1267 /* This routine notifies the server if there is an eof, or the filename
1268 if a new DVI file is starting. This is the routine called by TeX.
1269 Aleph defines str_start(#) as str_start_ar[# - too_big_char], with
1270 too_big_char = biggest_char + 1 = 65536 (omstr.ch). */
1272 void
1273 ipcpage (int is_eof)
1275 static boolean begun = false;
1276 unsigned len = 0;
1277 string p = NULL;
1279 if (!begun) {
1280 string name; /* Just the filename. */
1281 string cwd = xgetcwd ();
1283 ipc_open_out ();
1284 #if !defined(Aleph)
1285 len = strstart[outputfilename + 1] - strstart[outputfilename];
1286 #else
1287 len = strstartar[outputfilename + 1 - 65536L] -
1288 strstartar[outputfilename - 65536L];
1289 #endif
1290 name = xmalloc (len + 1);
1291 #if !defined(Aleph)
1292 strncpy (name, (string)&strpool[strstart[outputfilename]], len);
1293 #else
1295 unsigned i;
1296 for (i=0; i<len; i++)
1297 name[i] = strpool[i+strstartar[outputfilename - 65536L]];
1299 #endif
1300 name[len] = 0;
1302 /* Have to pass whole filename to the other end, since it may have
1303 been started up and running as a daemon, e.g., as with the NeXT
1304 preview program. */
1305 p = concat3 (cwd, DIR_SEP_STRING, name);
1306 free (cwd);
1307 free (name);
1309 #if defined (WIN32)
1310 { char *q;
1311 for (q = p; *q; q++) {
1312 if (*q == '\\')
1313 *q = '/';
1314 else if (IS_KANJI(q))
1315 q++;
1318 #endif
1319 len = strlen(p);
1320 begun = true;
1322 ipc_snd (len, is_eof, p);
1324 if (p)
1325 free (p);
1327 #endif /* TeX && IPC */
1329 #if defined (TeX) || defined (MF)
1330 /* TCX and Aleph&Co get along like sparks and gunpowder. */
1331 #if !defined(Aleph) && !defined(XeTeX)
1333 /* Return the next number following START, setting POST to the following
1334 character, as in strtol. Issue a warning and return -1 if no number
1335 can be parsed. */
1337 static int
1338 tcx_get_num (int upb,
1339 unsigned line_count,
1340 string start,
1341 string *post)
1343 int num = strtol (start, post, 0);
1344 assert (post && *post);
1345 if (*post == start) {
1346 /* Could not get a number. If blank line, fine. Else complain. */
1347 string p = start;
1348 while (*p && ISSPACE (*p))
1349 p++;
1350 if (*p != 0)
1351 fprintf (stderr, "%s:%d: Expected numeric constant, not `%s'.\n",
1352 translate_filename, line_count, start);
1353 num = -1;
1354 } else if (num < 0 || num > upb) {
1355 fprintf (stderr, "%s:%d: Destination charcode %d <0 or >%d.\n",
1356 translate_filename, line_count, num, upb);
1357 num = -1;
1360 return num;
1363 /* Update the xchr, xord, and xprn arrays for TeX, allowing a
1364 translation table specified at runtime via an external file.
1365 Look for the character translation file FNAME along the same path as
1366 tex.pool. If no suffix in FNAME, use .tcx (don't bother trying to
1367 support extension-less names for these files). */
1369 /* FIXME: A new format ought to be introduced for these files. */
1371 void
1372 readtcxfile (void)
1374 string orig_filename;
1375 if (!find_suffix (translate_filename)) {
1376 translate_filename = concat (translate_filename, ".tcx");
1378 orig_filename = translate_filename;
1379 translate_filename
1380 = kpse_find_file (translate_filename, kpse_web2c_format, true);
1381 if (translate_filename) {
1382 string line;
1383 unsigned line_count = 0;
1384 FILE *translate_file = xfopen (translate_filename, FOPEN_R_MODE);
1385 while ((line = read_line (translate_file))) {
1386 int first;
1387 string start2;
1388 string comment_loc = strchr (line, '%');
1389 if (comment_loc)
1390 *comment_loc = 0;
1392 line_count++;
1394 first = tcx_get_num (255, line_count, line, &start2);
1395 if (first >= 0) {
1396 string start3;
1397 int second;
1398 int printable;
1400 second = tcx_get_num (255, line_count, start2, &start3);
1401 if (second >= 0) {
1402 /* I suppose we could check for nonempty junk following the
1403 "printable" code, but let's not bother. */
1404 string extra;
1406 /* If they mention a second code, make that the internal number. */
1407 xord[first] = second;
1408 xchr[second] = first;
1410 printable = tcx_get_num (1, line_count, start3, &extra);
1411 /* Not-a-number, may be a comment. */
1412 if (printable == -1)
1413 printable = 1;
1414 /* Don't allow the 7bit ASCII set to become unprintable. */
1415 if (32 <= second && second <= 126)
1416 printable = 1;
1417 } else {
1418 second = first; /* else make internal the same as external */
1419 /* If they mention a charcode, call it printable. */
1420 printable = 1;
1423 xprn[second] = printable;
1425 free (line);
1427 xfclose(translate_file, translate_filename);
1428 } else {
1429 WARNING1 ("Could not open char translation file `%s'", orig_filename);
1432 #endif /* !Aleph && !XeTeX */
1433 #endif /* TeX || MF [character translation] */
1435 #ifdef XeTeX /* XeTeX handles this differently, and allows odd quotes within names */
1436 static string
1437 normalize_quotes (const_string name, const_string mesg)
1439 int quote_char = 0;
1440 boolean must_quote = false;
1441 int len = strlen(name);
1442 /* Leave room for quotes and NUL. */
1443 string ret;
1444 string p;
1445 const_string q;
1446 for (q = name; *q; q++) {
1447 if (*q == ' ') {
1448 if (!must_quote) {
1449 len += 2;
1450 must_quote = true;
1453 else if (*q == '\"' || *q == '\'') {
1454 must_quote = true;
1455 if (quote_char == 0)
1456 quote_char = '\"' + '\'' - *q;
1457 len += 2; /* this could sometimes add length we don't need */
1460 ret = xmalloc(len + 1);
1461 p = ret;
1462 if (must_quote) {
1463 if (quote_char == 0)
1464 quote_char = '\"';
1465 *p++ = quote_char;
1467 for (q = name; *q; q++) {
1468 if (*q == quote_char) {
1469 *p++ = quote_char;
1470 quote_char = '\"' + '\'' - quote_char;
1471 *p++ = quote_char;
1473 *p++ = *q;
1475 if (quote_char != 0)
1476 *p++ = quote_char;
1477 *p = '\0';
1478 return ret;
1480 #else
1481 /* Normalize quoting of filename -- that is, only quote if there is a space,
1482 and always use the quote-name-quote style. */
1483 static string
1484 normalize_quotes (const_string name, const_string mesg)
1486 boolean quoted = false;
1487 boolean must_quote = (strchr(name, ' ') != NULL);
1488 /* Leave room for quotes and NUL. */
1489 string ret = xmalloc(strlen(name)+3);
1490 string p;
1491 const_string q;
1492 p = ret;
1493 if (must_quote)
1494 *p++ = '"';
1495 for (q = name; *q; q++) {
1496 if (*q == '"')
1497 quoted = !quoted;
1498 else
1499 *p++ = *q;
1501 if (must_quote)
1502 *p++ = '"';
1503 *p = '\0';
1504 if (quoted) {
1505 fprintf(stderr, "! Unbalanced quotes in %s %s\n", mesg, name);
1506 uexit(1);
1508 return ret;
1510 #endif
1512 /* Getting the input filename. */
1513 string
1514 get_input_file_name (void)
1516 string input_file_name = NULL;
1518 if (argv[optind] && argv[optind][0] != '&' && argv[optind][0] != '\\') {
1519 /* Not &format, not \input, so assume simple filename. */
1520 string name;
1521 #ifndef XeTeX
1522 boolean quoted;
1523 #endif
1525 #ifdef WIN32
1526 if (strlen (argv[optind]) > 2 && isalpha (argv[optind][0]) &&
1527 argv[optind][1] == ':' && argv[optind][2] == '\\') {
1528 char *pp;
1529 for (pp = argv[optind]; *pp; pp++) {
1530 if (*pp == '\\')
1531 *pp = '/';
1532 else if (IS_KANJI(pp))
1533 pp++;
1536 #endif
1538 name = normalize_quotes(argv[optind], "argument");
1539 #ifdef XeTeX
1540 input_file_name = kpse_find_file(argv[optind], INPUT_FORMAT, false);
1541 #ifdef WIN32
1542 if (!srcspecialsp)
1543 change_to_long_name (&input_file_name);
1544 #endif
1545 #else
1546 quoted = (name[0] == '"');
1547 if (quoted) {
1548 /* Overwrite last quote and skip first quote. */
1549 name[strlen(name)-1] = '\0';
1550 name++;
1552 input_file_name = kpse_find_file(name, INPUT_FORMAT, false);
1553 #ifdef WIN32
1554 if (!srcspecialsp)
1555 change_to_long_name (&input_file_name);
1556 #endif
1557 if (quoted) {
1558 /* Undo modifications */
1559 name[strlen(name)] = '"';
1560 name--;
1562 #endif
1563 #ifdef WIN32
1564 if (!srcspecialsp) {
1565 if (input_file_name)
1566 name = normalize_quotes (input_file_name, "argument");
1568 #endif
1569 argv[optind] = name;
1571 return input_file_name;
1574 /* Reading the options. */
1576 /* Test whether getopt found an option ``A''.
1577 Assumes the option index is in the variable `option_index', and the
1578 option table in a variable `long_options'. */
1579 #define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
1581 /* SunOS cc can't initialize automatic structs, so make this static. */
1582 static struct option long_options[]
1583 = { { DUMP_OPTION, 1, 0, 0 },
1584 #ifdef TeX
1585 /* FIXME: Obsolete -- for backward compatibility only. */
1586 { "efmt", 1, 0, 0 },
1587 #endif
1588 { "help", 0, 0, 0 },
1589 { "ini", 0, &iniversion, 1 },
1590 { "interaction", 1, 0, 0 },
1591 { "halt-on-error", 0, &haltonerrorp, 1 },
1592 { "kpathsea-debug", 1, 0, 0 },
1593 { "progname", 1, 0, 0 },
1594 { "version", 0, 0, 0 },
1595 { "recorder", 0, &recorder_enabled, 1 },
1596 #ifdef TeX
1597 #ifdef IPC
1598 { "ipc", 0, &ipcon, 1 },
1599 { "ipc-start", 0, &ipcon, 2 },
1600 #endif /* IPC */
1601 #if !defined(Aleph)
1602 { "mltex", 0, &mltexp, 1 },
1603 #if !defined(XeTeX) && !IS_pTeX
1604 { "enc", 0, &enctexp, 1 },
1605 #endif
1606 #endif /* !Aleph */
1607 #if IS_eTeX
1608 { "etex", 0, &etexp, 1 },
1609 #endif
1610 { "output-comment", 1, 0, 0 },
1611 #if defined(pdfTeX)
1612 { "draftmode", 0, 0, 0 },
1613 { "output-format", 1, 0, 0 },
1614 #endif /* pdfTeX */
1615 { "shell-escape", 0, &shellenabledp, 1 },
1616 { "no-shell-escape", 0, &shellenabledp, -1 },
1617 { "enable-write18", 0, &shellenabledp, 1 },
1618 { "disable-write18", 0, &shellenabledp, -1 },
1619 { "shell-restricted", 0, 0, 0 },
1620 { "debug-format", 0, &debugformatfile, 1 },
1621 { "src-specials", 2, 0, 0 },
1622 #if defined(__SyncTeX__)
1623 /* Synchronization: just like "interaction" above */
1624 { "synctex", 1, 0, 0 },
1625 #endif
1626 #endif /* TeX */
1627 #if defined (TeX) || defined (MF)
1628 { "file-line-error-style", 0, &filelineerrorstylep, 1 },
1629 { "no-file-line-error-style", 0, &filelineerrorstylep, -1 },
1630 /* Shorter option names for the above. */
1631 { "file-line-error", 0, &filelineerrorstylep, 1 },
1632 { "no-file-line-error", 0, &filelineerrorstylep, -1 },
1633 { "jobname", 1, 0, 0 },
1634 { "output-directory", 1, 0, 0 },
1635 { "parse-first-line", 0, &parsefirstlinep, 1 },
1636 { "no-parse-first-line", 0, &parsefirstlinep, -1 },
1637 #if !defined(Aleph)
1638 { "translate-file", 1, 0, 0 },
1639 { "default-translate-file", 1, 0, 0 },
1640 { "8bit", 0, &eightbitp, 1 },
1641 #endif /* !Aleph */
1642 #if defined(XeTeX)
1643 { "no-pdf", 0, &nopdfoutput, 1 },
1644 { "output-driver", 1, 0, 0 },
1645 { "papersize", 1, 0, 0 },
1646 #endif /* XeTeX */
1647 { "mktex", 1, 0, 0 },
1648 { "no-mktex", 1, 0, 0 },
1649 #endif /* TeX or MF */
1650 #if IS_pTeX
1651 #ifdef WIN32
1652 { "sjis-terminal", 0, &sjisterminal, 1 },
1653 { "guess-input-enc", 0, &infile_enc_auto, 1 },
1654 { "no-guess-input-enc", 0, &infile_enc_auto, 0 },
1655 #endif
1656 { "kanji", 1, 0, 0 },
1657 { "kanji-internal", 1, 0, 0 },
1658 #endif /* IS_pTeX */
1659 { 0, 0, 0, 0 } };
1661 static void
1662 parse_options (int argc, string *argv)
1664 int g; /* `getopt' return code. */
1665 int option_index;
1667 for (;;) {
1668 g = getopt_long_only (argc, argv, "+", long_options, &option_index);
1670 if (g == -1) /* End of arguments, exit the loop. */
1671 break;
1673 if (g == '?') { /* Unknown option. */
1674 /* FIXME: usage (argv[0]); replaced by continue. */
1675 continue;
1678 assert (g == 0); /* We have no short option names. */
1680 if (ARGUMENT_IS ("kpathsea-debug")) {
1681 kpathsea_debug |= atoi (optarg);
1683 #ifdef XeTeX
1684 } else if (ARGUMENT_IS ("papersize")) {
1685 papersize = optarg;
1686 } else if (ARGUMENT_IS ("output-driver")) {
1687 outputdriver = optarg;
1688 #endif
1690 } else if (ARGUMENT_IS ("progname")) {
1691 user_progname = optarg;
1693 } else if (ARGUMENT_IS ("jobname")) {
1694 #ifdef XeTeX
1695 c_job_name = optarg;
1696 #else
1697 c_job_name = normalize_quotes (optarg, "jobname");
1698 #endif
1700 } else if (ARGUMENT_IS (DUMP_OPTION)) {
1701 dump_name = optarg;
1702 dumpoption = true;
1704 #ifdef TeX
1705 /* FIXME: Obsolete -- for backward compatibility only. */
1706 } else if (ARGUMENT_IS ("efmt")) {
1707 dump_name = optarg;
1708 dumpoption = true;
1709 #endif
1711 } else if (ARGUMENT_IS ("output-directory")) {
1712 output_directory = optarg;
1714 #ifdef TeX
1715 } else if (ARGUMENT_IS ("output-comment")) {
1716 unsigned len = strlen (optarg);
1717 if (len < 256) {
1718 outputcomment = optarg;
1719 } else {
1720 WARNING2 ("Comment truncated to 255 characters from %d. (%s)",
1721 len, optarg);
1722 outputcomment = xmalloc (256);
1723 strncpy (outputcomment, optarg, 255);
1724 outputcomment[255] = 0;
1727 #ifdef IPC
1728 } else if (ARGUMENT_IS ("ipc-start")) {
1729 ipc_open_out ();
1730 /* Try to start up the other end if it's not already. */
1731 if (!ipc_is_open ()) {
1732 #ifdef WIN32
1733 if (_spawnlp (_P_NOWAIT, IPC_SERVER_CMD, IPC_SERVER_CMD, NULL) != -1) {
1734 #else
1735 if (system (IPC_SERVER_CMD) == 0) {
1736 #endif
1737 unsigned i;
1738 for (i = 0; i < 20 && !ipc_is_open (); i++) {
1739 #ifdef WIN32
1740 Sleep (100); /* 2000ms is too long for a simple w32 example */
1741 #else
1742 sleep (2);
1743 #endif
1744 ipc_open_out ();
1748 #endif /* IPC */
1750 } else if (ARGUMENT_IS ("shell-restricted")) {
1751 shellenabledp = 1;
1752 restrictedshell = 1;
1754 } else if (ARGUMENT_IS ("src-specials")) {
1755 last_source_name = xstrdup("");
1756 /* Option `--src" without any value means `auto' mode. */
1757 if (optarg == NULL) {
1758 insertsrcspecialeverypar = true;
1759 insertsrcspecialauto = true;
1760 srcspecialsoption = true;
1761 srcspecialsp = true;
1762 } else {
1763 parse_src_specials_option(optarg);
1765 #endif /* TeX */
1766 #if defined(pdfTeX)
1767 } else if (ARGUMENT_IS ("output-format")) {
1768 pdfoutputoption = 1;
1769 if (strcmp(optarg, "dvi") == 0) {
1770 pdfoutputvalue = 0;
1771 } else if (strcmp(optarg, "pdf") == 0) {
1772 pdfoutputvalue = 2;
1773 } else {
1774 WARNING1 ("Ignoring unknown value `%s' for --output-format", optarg);
1775 pdfoutputoption = 0;
1777 } else if (ARGUMENT_IS ("draftmode")) {
1778 pdfdraftmodeoption = 1;
1779 pdfdraftmodevalue = 1;
1780 #endif /* pdfTeX */
1781 #if defined (TeX) || defined (MF)
1782 #if !defined(Aleph)
1783 } else if (ARGUMENT_IS ("translate-file")) {
1784 translate_filename = optarg;
1785 } else if (ARGUMENT_IS ("default-translate-file")) {
1786 default_translate_filename = optarg;
1787 #endif /* !Aleph */
1788 } else if (ARGUMENT_IS ("mktex")) {
1789 kpse_maketex_option (optarg, true);
1790 } else if (ARGUMENT_IS ("no-mktex")) {
1791 kpse_maketex_option (optarg, false);
1792 #endif /* TeX or MF */
1793 } else if (ARGUMENT_IS ("interaction")) {
1794 /* These numbers match @d's in *.ch */
1795 if (STREQ (optarg, "batchmode")) {
1796 interactionoption = 0;
1797 } else if (STREQ (optarg, "nonstopmode")) {
1798 interactionoption = 1;
1799 } else if (STREQ (optarg, "scrollmode")) {
1800 interactionoption = 2;
1801 } else if (STREQ (optarg, "errorstopmode")) {
1802 interactionoption = 3;
1803 } else {
1804 WARNING1 ("Ignoring unknown argument `%s' to --interaction", optarg);
1806 #if IS_pTeX
1807 } else if (ARGUMENT_IS ("kanji")) {
1808 if (!set_enc_string (optarg, NULL)) {
1809 WARNING1 ("Ignoring unknown argument `%s' to --kanji", optarg);
1811 } else if (ARGUMENT_IS ("kanji-internal")) {
1812 if (!set_enc_string (NULL, optarg)) {
1813 WARNING1 ("Ignoring unknown argument `%s' to --kanji-internal", optarg);
1815 #endif
1817 } else if (ARGUMENT_IS ("help")) {
1818 usagehelp (PROGRAM_HELP, BUG_ADDRESS);
1820 #if defined(__SyncTeX__)
1821 } else if (ARGUMENT_IS ("synctex")) {
1822 /* Synchronize TeXnology: catching the command line option as a long */
1823 synctexoption = (int) strtol(optarg, NULL, 0);
1824 #endif
1826 } else if (ARGUMENT_IS ("version")) {
1827 char *versions;
1828 #if defined (pdfTeX) || defined(XeTeX)
1829 initversionstring(&versions);
1830 #else
1831 versions = NULL;
1832 #endif
1833 printversionandexit (BANNER, COPYRIGHT_HOLDER, AUTHOR, versions);
1835 } /* Else it was a flag; getopt has already done the assignment. */
1839 #if defined(TeX)
1840 void
1841 parse_src_specials_option (const_string opt_list)
1843 char * toklist = xstrdup(opt_list);
1844 char * tok;
1845 insertsrcspecialauto = false;
1846 tok = strtok (toklist, ", ");
1847 while (tok) {
1848 if (strcmp (tok, "everypar") == 0
1849 || strcmp (tok, "par") == 0
1850 || strcmp (tok, "auto") == 0) {
1851 insertsrcspecialauto = true;
1852 insertsrcspecialeverypar = true;
1853 } else if (strcmp (tok, "everyparend") == 0
1854 || strcmp (tok, "parend") == 0)
1855 insertsrcspecialeveryparend = true;
1856 else if (strcmp (tok, "everycr") == 0
1857 || strcmp (tok, "cr") == 0)
1858 insertsrcspecialeverycr = true;
1859 else if (strcmp (tok, "everymath") == 0
1860 || strcmp (tok, "math") == 0)
1861 insertsrcspecialeverymath = true;
1862 else if (strcmp (tok, "everyhbox") == 0
1863 || strcmp (tok, "hbox") == 0)
1864 insertsrcspecialeveryhbox = true;
1865 else if (strcmp (tok, "everyvbox") == 0
1866 || strcmp (tok, "vbox") == 0)
1867 insertsrcspecialeveryvbox = true;
1868 else if (strcmp (tok, "everydisplay") == 0
1869 || strcmp (tok, "display") == 0)
1870 insertsrcspecialeverydisplay = true;
1871 else if (strcmp (tok, "none") == 0) {
1872 /* This one allows to reset an option that could appear in texmf.cnf */
1873 insertsrcspecialauto = insertsrcspecialeverypar =
1874 insertsrcspecialeveryparend = insertsrcspecialeverycr =
1875 insertsrcspecialeverymath = insertsrcspecialeveryhbox =
1876 insertsrcspecialeveryvbox = insertsrcspecialeverydisplay = false;
1877 } else {
1878 WARNING1 ("Ignoring unknown argument `%s' to --src-specials", tok);
1880 tok = strtok(0, ", ");
1882 free(toklist);
1883 srcspecialsp=insertsrcspecialauto | insertsrcspecialeverypar |
1884 insertsrcspecialeveryparend | insertsrcspecialeverycr |
1885 insertsrcspecialeverymath | insertsrcspecialeveryhbox |
1886 insertsrcspecialeveryvbox | insertsrcspecialeverydisplay;
1887 srcspecialsoption = true;
1889 #endif
1891 /* If the first thing on the command line (we use the globals `argv' and
1892 `optind') is a normal filename (i.e., does not start with `&' or
1893 `\'), and if we can open it, and if its first line is %&FORMAT, and
1894 FORMAT is a readable dump file, then set DUMP_VAR to FORMAT.
1895 Also call kpse_reset_program_name to ensure the correct paths for the
1896 format are used. */
1897 static void
1898 parse_first_line (const_string filename)
1900 FILE *f = filename ? fopen (filename, FOPEN_R_MODE) : NULL;
1901 if (f) {
1902 string first_line = read_line (f);
1903 xfclose (f, filename);
1905 /* We deal with the general format "%&fmt --translate-file=tcx" */
1906 /* The idea of using this format came from Wlodzimierz Bzyl
1907 <matwb@monika.univ.gda.pl> */
1908 if (first_line && first_line[0] == '%' && first_line[1] == '&') {
1909 /* Parse the first line into at most three space-separated parts. */
1910 char *s;
1911 char *part[4];
1912 int npart;
1913 char **parse;
1915 for (s = first_line+2; ISBLANK(*s); ++s)
1917 npart = 0;
1918 while (*s && npart != 3) {
1919 part[npart++] = s;
1920 while (*s && *s != ' ') s++;
1921 while (*s == ' ') *s++ = '\0';
1923 part[npart] = NULL;
1924 parse = part;
1925 /* Look at what we've got. Very crude! */
1926 if (*parse && **parse != '-') {
1927 /* A format name */
1928 if (dump_name) {
1929 /* format already determined, do nothing. */
1930 } else {
1931 string f_name = concat (part[0], DUMP_EXT);
1932 string d_name = kpse_find_file (f_name, DUMP_FORMAT, false);
1933 if (d_name && kpse_readable_file (d_name)) {
1934 dump_name = xstrdup (part[0]);
1935 kpse_reset_program_name (dump_name);
1936 /* Tell TeX/MF/MP we have a %&name line... */
1937 dumpline = true;
1939 free (f_name);
1941 parse++;
1943 /* The tcx stuff, if any. Should we support the -translate-file
1944 form as well as --translate-file? */
1945 if (*parse) {
1946 s = NULL;
1947 if (translate_filename) {
1948 /* TCX file already set, do nothing. */
1949 } else if (STREQ (*parse, "--translate-file")) {
1950 s = *(parse+1);
1951 } else if (STREQ (*parse, "-translate-file")) {
1952 s = *(parse+1);
1953 } else if (STRNEQ (*parse, "--translate-file=", 17)) {
1954 s = *parse+17;
1955 } else if (STRNEQ (*parse, "-translate-file=", 16)) {
1956 s = *parse+16;
1958 /* Just set the name, no sanity checks here. */
1959 /* FIXME: remove trailing spaces. */
1960 if (s && *s) {
1961 translate_filename = xstrdup(s);
1965 if (first_line)
1966 free (first_line);
1971 piped I/O
1974 /* The code that implements popen() needs an array for tracking
1975 possible pipe file pointers, because these need to be
1976 closed using pclose().
1979 #if ENABLE_PIPES
1981 #define NUM_PIPES 16
1983 static FILE *pipes [NUM_PIPES];
1985 boolean
1986 open_in_or_pipe (FILE **f_ptr, int filefmt, const_string fopen_mode)
1988 string fname = NULL;
1989 int i; /* iterator */
1991 /* opening a read pipe is straightforward, only have to
1992 skip past the pipe symbol in the file name. filename
1993 quoting is assumed to happen elsewhere (it does :-)) */
1995 if (shellenabledp && *(nameoffile+1) == '|') {
1996 /* the user requested a pipe */
1997 *f_ptr = NULL;
1998 fname = xmalloc(strlen((const_string)(nameoffile+1))+1);
1999 strcpy(fname,(const_string)(nameoffile+1));
2000 recorder_record_input (fname + 1);
2001 *f_ptr = runpopen(fname+1,"r");
2002 free(fname);
2003 for (i=0; i<NUM_PIPES; i++) {
2004 if (pipes[i]==NULL) {
2005 pipes[i] = *f_ptr;
2006 break;
2009 if (*f_ptr)
2010 setvbuf (*f_ptr,NULL,_IONBF,0);
2011 #ifdef WIN32
2012 Poptr = *f_ptr;
2013 #endif
2015 return *f_ptr != NULL;
2018 return open_input(f_ptr,filefmt,fopen_mode) ;
2021 #ifdef XeTeX
2022 boolean
2023 u_open_in_or_pipe(unicodefile* f, integer filefmt, const_string fopen_mode, integer mode, integer encodingData)
2025 string fname = NULL;
2026 int i; /* iterator */
2028 /* opening a read pipe is straightforward, only have to
2029 skip past the pipe symbol in the file name. filename
2030 quoting is assumed to happen elsewhere (it does :-)) */
2032 if (shellenabledp && *(nameoffile+1) == '|') {
2033 /* the user requested a pipe */
2034 *f = malloc(sizeof(UFILE));
2035 (*f)->encodingMode = (mode == AUTO) ? UTF8 : mode;
2036 (*f)->conversionData = 0;
2037 (*f)->savedChar = -1;
2038 (*f)->skipNextLF = 0;
2039 (*f)->f = NULL;
2040 fname = xmalloc(strlen((const_string)(nameoffile+1))+1);
2041 strcpy(fname,(const_string)(nameoffile+1));
2042 recorder_record_input (fname + 1);
2043 (*f)->f = runpopen(fname+1,"r");
2044 free(fname);
2045 for (i=0; i<NUM_PIPES; i++) {
2046 if (pipes[i]==NULL) {
2047 pipes[i] = (*f)->f;
2048 break;
2051 if ((*f)->f)
2052 setvbuf ((*f)->f,NULL,_IONBF,0);
2053 #ifdef WIN32
2054 Poptr = (*f)->f;
2055 #endif
2057 return (*f)->f != NULL;
2060 return u_open_in(f, filefmt, fopen_mode, mode, encodingData);
2062 #endif
2064 boolean
2065 open_out_or_pipe (FILE **f_ptr, const_string fopen_mode)
2067 string fname;
2068 int i; /* iterator */
2070 /* opening a write pipe takes a little bit more work, because TeX
2071 will perhaps have appended ".tex". To avoid user confusion as
2072 much as possible, this extension is stripped only when the command
2073 is a bare word. Some small string trickery is needed to make
2074 sure the correct number of bytes is free()-d afterwards */
2076 if (shellenabledp && *(nameoffile+1) == '|') {
2077 /* the user requested a pipe */
2078 fname = xmalloc(strlen((const_string)(nameoffile+1))+1);
2079 strcpy(fname,(const_string)(nameoffile+1));
2080 if (strchr (fname,' ')==NULL && strchr(fname,'>')==NULL) {
2081 /* mp and mf currently do not use this code, but it
2082 is better to be prepared */
2083 if (STREQ((fname+strlen(fname)-4),".tex"))
2084 *(fname+strlen(fname)-4) = 0;
2085 *f_ptr = runpopen(fname+1,"w");
2086 *(fname+strlen(fname)) = '.';
2087 } else {
2088 *f_ptr = runpopen(fname+1,"w");
2090 recorder_record_output (fname + 1);
2091 free(fname);
2093 for (i=0; i<NUM_PIPES; i++) {
2094 if (pipes[i]==NULL) {
2095 pipes[i] = *f_ptr;
2096 break;
2100 if (*f_ptr)
2101 setvbuf(*f_ptr,NULL,_IONBF,0);
2103 return *f_ptr != NULL;
2106 return open_output(f_ptr,fopen_mode);
2110 void
2111 close_file_or_pipe (FILE *f)
2113 int i; /* iterator */
2115 if (shellenabledp) {
2116 /* if this file was a pipe, pclose() it and return */
2117 for (i=0; i<NUM_PIPES; i++) {
2118 if (pipes[i] == f) {
2119 if (f) {
2120 pclose (f);
2121 #ifdef WIN32
2122 Poptr = NULL;
2123 #endif
2125 pipes[i] = NULL;
2126 return;
2130 close_file(f);
2132 #endif /* ENABLE_PIPES */
2134 /* All our interrupt handler has to do is set TeX's or Metafont's global
2135 variable `interrupt'; then they will do everything needed. */
2136 #ifdef WIN32
2137 /* Win32 doesn't set SIGINT ... */
2138 static BOOL WINAPI
2139 catch_interrupt (DWORD arg)
2141 switch (arg) {
2142 case CTRL_C_EVENT:
2143 case CTRL_BREAK_EVENT:
2144 interrupt = 1;
2145 return TRUE;
2146 default:
2147 /* No need to set interrupt as we are exiting anyway */
2148 return FALSE;
2151 #else /* not WIN32 */
2152 static RETSIGTYPE
2153 catch_interrupt (int arg)
2155 interrupt = 1;
2156 #ifdef OS2
2157 (void) signal (SIGINT, SIG_ACK);
2158 #else
2159 (void) signal (SIGINT, catch_interrupt);
2160 #endif /* not OS2 */
2162 #endif /* not WIN32 */
2164 /* Besides getting the date and time here, we also set up the interrupt
2165 handler, for no particularly good reason. It's just that since the
2166 `fix_date_and_time' routine is called early on (section 1337 in TeX,
2167 ``Get the first line of input and prepare to start''), this is as
2168 good a place as any. */
2170 void
2171 get_date_and_time (integer *minutes, integer *day,
2172 integer *month, integer *year)
2174 time_t myclock = time ((time_t *) 0);
2175 struct tm *tmptr = localtime (&myclock);
2177 *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
2178 *day = tmptr->tm_mday;
2179 *month = tmptr->tm_mon + 1;
2180 *year = tmptr->tm_year + 1900;
2183 #ifdef SA_INTERRUPT
2184 /* Under SunOS 4.1.x, the default action after return from the
2185 signal handler is to restart the I/O if nothing has been
2186 transferred. The effect on TeX is that interrupts are ignored if
2187 we are waiting for input. The following tells the system to
2188 return EINTR from read() in this case. From ken@cs.toronto.edu. */
2190 struct sigaction a, oa;
2192 a.sa_handler = catch_interrupt;
2193 sigemptyset (&a.sa_mask);
2194 sigaddset (&a.sa_mask, SIGINT);
2195 a.sa_flags = SA_INTERRUPT;
2196 sigaction (SIGINT, &a, &oa);
2197 if (oa.sa_handler != SIG_DFL)
2198 sigaction (SIGINT, &oa, (struct sigaction *) 0);
2199 #else /* no SA_INTERRUPT */
2200 #ifdef WIN32
2201 SetConsoleCtrlHandler(catch_interrupt, TRUE);
2202 #else /* not WIN32 */
2203 RETSIGTYPE (*old_handler)(int);
2205 old_handler = signal (SIGINT, catch_interrupt);
2206 if (old_handler != SIG_DFL)
2207 signal (SIGINT, old_handler);
2208 #endif /* not WIN32 */
2209 #endif /* no SA_INTERRUPT */
2213 #if defined(pdfTeX)
2215 Getting a high resolution time.
2217 void
2218 get_seconds_and_micros (integer *seconds, integer *micros)
2220 #if defined (HAVE_GETTIMEOFDAY)
2221 struct timeval tv;
2222 gettimeofday(&tv, NULL);
2223 *seconds = tv.tv_sec;
2224 *micros = tv.tv_usec;
2225 #elif defined (HAVE_FTIME)
2226 struct timeb tb;
2227 ftime(&tb);
2228 *seconds = tb.time;
2229 *micros = tb.millitm*1000;
2230 #else
2231 time_t myclock = time((time_t*)NULL);
2232 *seconds = myclock;
2233 *micros = 0;
2234 #endif
2236 #endif
2238 /* Read a line of input as efficiently as possible while still looking
2239 like Pascal. We set `last' to `first' and return `false' if we get
2240 to eof. Otherwise, we return `true' and set last = first +
2241 length(line except trailing whitespace). */
2243 #ifndef XeTeX /* for XeTeX, we have a replacement function in XeTeX_ext.c */
2244 boolean
2245 input_line (FILE *f)
2247 int i = EOF;
2249 /* Recognize either LF or CR as a line terminator. */
2250 #if IS_pTeX
2251 last = input_line2(f, (unsigned char *)buffer, first, bufsize, &i);
2252 #else
2253 #ifdef WIN32
2254 if (f != Poptr && fileno (f) != fileno (stdin)) {
2255 long position = ftell (f);
2257 if (position == 0L) { /* Detect and skip Byte order marks. */
2258 int k1 = getc (f);
2260 if (k1 != 0xff && k1 != 0xfe && k1 != 0xef)
2261 rewind (f);
2262 else {
2263 int k2 = getc (f);
2265 if (k2 != 0xff && k2 != 0xfe && k2 != 0xbb)
2266 rewind (f);
2267 else if ((k1 == 0xff && k2 == 0xfe) || /* UTF-16(LE) */
2268 (k1 == 0xfe && k2 == 0xff)) /* UTF-16(BE) */
2270 else {
2271 int k3 = getc (f);
2273 if (k1 == 0xef && k2 == 0xbb && k3 == 0xbf) /* UTF-8 */
2275 else
2276 rewind (f);
2281 #endif
2282 last = first;
2283 while (last < bufsize && (i = getc (f)) != EOF && i != '\n' && i != '\r')
2284 buffer[last++] = i;
2285 #endif
2287 if (i == EOF && errno != EINTR && last == first)
2288 return false;
2290 /* We didn't get the whole line because our buffer was too small. */
2291 if (i != EOF && i != '\n' && i != '\r') {
2292 fprintf (stderr, "! Unable to read an entire line---bufsize=%u.\n",
2293 (unsigned) bufsize);
2294 fputs ("Please increase buf_size in texmf.cnf.\n", stderr);
2295 uexit (1);
2298 buffer[last] = ' ';
2299 if (last >= maxbufstack)
2300 maxbufstack = last;
2302 /* If next char is LF of a CRLF, read it. */
2303 if (i == '\r') {
2304 while ((i = getc (f)) == EOF && errno == EINTR)
2306 if (i != '\n')
2307 ungetc (i, f);
2310 /* Trim trailing whitespace. */
2311 while (last > first && ISBLANK (buffer[last - 1]))
2312 --last;
2314 /* Don't bother using xord if we don't need to. */
2315 #if !defined(Aleph)
2316 for (i = first; i <= last; i++)
2317 buffer[i] = xord[buffer[i]];
2318 #endif
2320 #if IS_pTeX
2321 for (i = last+1; (i < last + 5 && i < bufsize) ; i++)
2322 buffer[i] = '\0';
2323 #endif
2325 return true;
2327 #endif /* !XeTeX */
2329 /* This string specifies what the `e' option does in response to an
2330 error message. */
2331 static const_string edit_value = EDITOR;
2333 /* This procedure originally due to sjc@s1-c. TeX & Metafont call it when
2334 the user types `e' in response to an error, invoking a text editor on
2335 the erroneous source file. FNSTART is how far into FILENAME the
2336 actual filename starts; FNLENGTH is how long the filename is. */
2338 void
2339 calledit (packedASCIIcode *filename,
2340 poolpointer fnstart,
2341 integer fnlength,
2342 integer linenumber)
2344 char *temp, *command, *fullcmd;
2345 char c;
2346 int sdone, ddone, i;
2348 #ifdef WIN32
2349 char *fp, *ffp, *env, editorname[256], buffer[256];
2350 int cnt = 0;
2351 int dontchange = 0;
2352 #endif
2354 sdone = ddone = 0;
2355 filename += fnstart;
2357 /* Close any open input files, since we're going to kill the job. */
2358 for (i = 1; i <= inopen; i++)
2359 #ifdef XeTeX
2360 xfclose (inputfile[i]->f, "inputfile");
2361 #else
2362 xfclose (inputfile[i], "inputfile");
2363 #endif
2365 /* Replace the default with the value of the appropriate environment
2366 variable or config file value, if it's set. */
2367 temp = kpse_var_value (edit_var);
2368 if (temp != NULL)
2369 edit_value = temp;
2371 /* Construct the command string. The `11' is the maximum length an
2372 integer might be. */
2373 command = xmalloc (strlen (edit_value) + fnlength + 11);
2375 /* So we can construct it as we go. */
2376 temp = command;
2378 #ifdef WIN32
2379 fp = editorname;
2380 if ((isalpha(*edit_value) && *(edit_value + 1) == ':'
2381 && IS_DIR_SEP (*(edit_value + 2)))
2382 || (*edit_value == '"' && isalpha(*(edit_value + 1))
2383 && *(edit_value + 2) == ':'
2384 && IS_DIR_SEP (*(edit_value + 3)))
2386 dontchange = 1;
2387 #endif
2389 while ((c = *edit_value++) != 0)
2391 if (c == '%')
2393 switch (c = *edit_value++)
2395 case 'd':
2396 if (ddone)
2397 FATAL ("call_edit: `%%d' appears twice in editor command");
2398 sprintf (temp, "%ld", (long int)linenumber);
2399 while (*temp != '\0')
2400 temp++;
2401 ddone = 1;
2402 break;
2404 case 's':
2405 if (sdone)
2406 FATAL ("call_edit: `%%s' appears twice in editor command");
2407 for (i =0; i < fnlength; i++)
2408 *temp++ = Xchr (filename[i]);
2409 sdone = 1;
2410 break;
2412 case '\0':
2413 *temp++ = '%';
2414 /* Back up to the null to force termination. */
2415 edit_value--;
2416 break;
2418 default:
2419 *temp++ = '%';
2420 *temp++ = c;
2421 break;
2424 else {
2425 #ifdef WIN32
2426 if (dontchange)
2427 *temp++ = c;
2428 else { if(Isspace(c) && cnt == 0) {
2429 cnt++;
2430 temp = command;
2431 *temp++ = c;
2432 *fp = '\0';
2433 } else if(!Isspace(c) && cnt == 0) {
2434 *fp++ = c;
2435 } else {
2436 *temp++ = c;
2439 #else
2440 *temp++ = c;
2441 #endif
2445 *temp = 0;
2447 #ifdef WIN32
2448 if (dontchange == 0) {
2449 if(editorname[0] == '.' ||
2450 editorname[0] == '/' ||
2451 editorname[0] == '\\') {
2452 fprintf(stderr, "%s is not allowed to execute.\n", editorname);
2453 uexit(1);
2455 env = (char *)getenv("PATH");
2456 if(SearchPath(env, editorname, ".exe", 256, buffer, &ffp)==0) {
2457 if(SearchPath(env, editorname, ".bat", 256, buffer, &ffp)==0) {
2458 fprintf(stderr, "I cannot find %s in the PATH.\n", editorname);
2459 uexit(1);
2462 fullcmd = (char *)xmalloc(strlen(buffer)+strlen(command)+5);
2463 strcpy(fullcmd, "\"");
2464 strcat(fullcmd, buffer);
2465 strcat(fullcmd, "\"");
2466 strcat(fullcmd, command);
2467 } else
2468 #endif
2469 fullcmd = command;
2471 /* Execute the command. */
2472 if (system (fullcmd) != 0)
2473 fprintf (stderr, "! Trouble executing `%s'.\n", command);
2475 /* Quit, since we found an error. */
2476 uexit (1);
2479 /* Read and write dump files. As distributed, these files are
2480 architecture dependent; specifically, BigEndian and LittleEndian
2481 architectures produce different files. These routines always output
2482 BigEndian files. This still does not guarantee them to be
2483 architecture-independent, because it is possible to make a format
2484 that dumps a glue ratio, i.e., a floating-point number. Fortunately,
2485 none of the standard formats do that. */
2487 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) /* this fn */
2489 /* This macro is always invoked as a statement. It assumes a variable
2490 `temp'. */
2492 #define SWAP(x, y) temp = (x); (x) = (y); (y) = temp
2495 /* Make the NITEMS items pointed at by P, each of size SIZE, be the
2496 opposite-endianness of whatever they are now. */
2498 static void
2499 swap_items (char *p, int nitems, int size)
2501 char temp;
2503 /* Since `size' does not change, we can write a while loop for each
2504 case, and avoid testing `size' for each time. */
2505 switch (size)
2507 /* 16-byte items happen on the DEC Alpha machine when we are not
2508 doing sharable memory dumps. */
2509 case 16:
2510 while (nitems--)
2512 SWAP (p[0], p[15]);
2513 SWAP (p[1], p[14]);
2514 SWAP (p[2], p[13]);
2515 SWAP (p[3], p[12]);
2516 SWAP (p[4], p[11]);
2517 SWAP (p[5], p[10]);
2518 SWAP (p[6], p[9]);
2519 SWAP (p[7], p[8]);
2520 p += size;
2522 break;
2524 case 8:
2525 while (nitems--)
2527 SWAP (p[0], p[7]);
2528 SWAP (p[1], p[6]);
2529 SWAP (p[2], p[5]);
2530 SWAP (p[3], p[4]);
2531 p += size;
2533 break;
2535 case 4:
2536 while (nitems--)
2538 SWAP (p[0], p[3]);
2539 SWAP (p[1], p[2]);
2540 p += size;
2542 break;
2544 case 2:
2545 while (nitems--)
2547 SWAP (p[0], p[1]);
2548 p += size;
2550 break;
2552 case 1:
2553 /* Nothing to do. */
2554 break;
2556 default:
2557 FATAL1 ("Can't swap a %d-byte item for (un)dumping", size);
2560 #endif /* not WORDS_BIGENDIAN and not NO_DUMP_SHARE */
2563 /* Here we write NITEMS items, each item being ITEM_SIZE bytes long.
2564 The pointer to the stuff to write is P, and we write to the file
2565 OUT_FILE. */
2567 void
2568 #ifdef XeTeX
2569 do_dump (char *p, int item_size, int nitems, gzFile out_file)
2570 #else
2571 do_dump (char *p, int item_size, int nitems, FILE *out_file)
2572 #endif
2574 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2575 swap_items (p, nitems, item_size);
2576 #endif
2578 #ifdef XeTeX
2579 if (gzwrite (out_file, p, item_size * nitems) != item_size * nitems)
2580 #else
2581 if (fwrite (p, item_size, nitems, out_file) != nitems)
2582 #endif
2584 fprintf (stderr, "! Could not write %d %d-byte item(s) to %s.\n",
2585 nitems, item_size, nameoffile+1);
2586 uexit (1);
2589 /* Have to restore the old contents of memory, since some of it might
2590 get used again. */
2591 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2592 swap_items (p, nitems, item_size);
2593 #endif
2597 /* Here is the dual of the writing routine. */
2599 void
2600 #ifdef XeTeX
2601 do_undump (char *p, int item_size, int nitems, gzFile in_file)
2602 #else
2603 do_undump (char *p, int item_size, int nitems, FILE *in_file)
2604 #endif
2606 #ifdef XeTeX
2607 if (gzread (in_file, p, item_size * nitems) != item_size * nitems)
2608 #else
2609 if (fread (p, item_size, nitems, in_file) != (size_t) nitems)
2610 #endif
2611 FATAL3 ("Could not undump %d %d-byte item(s) from %s",
2612 nitems, item_size, nameoffile+1);
2614 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2615 swap_items (p, nitems, item_size);
2616 #endif
2619 /* FIXME -- some (most?) of this can/should be moved to the Pascal/WEB side. */
2620 #if defined(TeX) || defined(MF)
2621 #if !defined(pdfTeX)
2622 static void
2623 checkpoolpointer (poolpointer poolptr, size_t len)
2625 if (poolptr + len >= poolsize) {
2626 fprintf (stderr, "\nstring pool overflow [%i bytes]\n",
2627 (int)poolsize); /* fixme */
2628 exit(1);
2632 #ifndef XeTeX /* XeTeX uses this from XeTeX_ext.c */
2633 static
2634 #endif
2636 maketexstring(const_string s)
2638 size_t len;
2639 #ifdef XeTeX
2640 UInt32 rval;
2641 const unsigned char *cp = (const unsigned char *)s;
2642 #endif
2643 #if defined(TeX)
2644 if (s == NULL || *s == 0)
2645 return getnullstr();
2646 #else
2647 assert (s != 0);
2648 #endif
2649 len = strlen(s);
2650 checkpoolpointer (poolptr, len); /* in the XeTeX case, this may be more than enough */
2651 #ifdef XeTeX
2652 while ((rval = *(cp++)) != 0) {
2653 UInt16 extraBytes = bytesFromUTF8[rval];
2654 switch (extraBytes) { /* note: code falls through cases! */
2655 case 5: rval <<= 6; if (*cp) rval += *(cp++);
2656 case 4: rval <<= 6; if (*cp) rval += *(cp++);
2657 case 3: rval <<= 6; if (*cp) rval += *(cp++);
2658 case 2: rval <<= 6; if (*cp) rval += *(cp++);
2659 case 1: rval <<= 6; if (*cp) rval += *(cp++);
2660 case 0: ;
2662 rval -= offsetsFromUTF8[extraBytes];
2663 if (rval > 0xffff) {
2664 rval -= 0x10000;
2665 strpool[poolptr++] = 0xd800 + rval / 0x0400;
2666 strpool[poolptr++] = 0xdc00 + rval % 0x0400;
2668 else
2669 strpool[poolptr++] = rval;
2671 #else /* ! XeTeX */
2672 while (len-- > 0)
2673 strpool[poolptr++] = *s++;
2674 #endif /* ! XeTeX */
2676 return makestring();
2678 #endif /* !pdfTeX */
2680 strnumber
2681 makefullnamestring(void)
2683 return maketexstring(fullnameoffile);
2686 /* Get the job name to be used, which may have been set from the
2687 command line. */
2688 strnumber
2689 getjobname(strnumber name)
2691 strnumber ret = name;
2692 if (c_job_name != NULL)
2693 ret = maketexstring(c_job_name);
2694 return ret;
2696 #endif
2698 #if defined(TeX)
2699 static int
2700 compare_paths (const_string p1, const_string p2)
2702 int ret;
2703 while (
2704 #ifdef MONOCASE_FILENAMES
2705 (((ret = (toupper(*p1) - toupper(*p2))) == 0) && (*p2 != 0))
2706 #else
2707 (((ret = (*p1 - *p2)) == 0) && (*p2 != 0))
2708 #endif
2709 || (IS_DIR_SEP(*p1) && IS_DIR_SEP(*p2))) {
2710 p1++, p2++;
2712 ret = (ret < 0 ? -1 : (ret > 0 ? 1 : 0));
2713 return ret;
2716 #ifdef XeTeX /* the string pool is UTF-16 but we want a UTF-8 string */
2718 string
2719 gettexstring (strnumber s)
2721 unsigned bytesToWrite = 0;
2722 poolpointer len, i, j;
2723 string name;
2724 len = strstart[s + 1 - 65536L] - strstart[s - 65536L];
2725 name = xmalloc(len * 3 + 1); /* max UTF16->UTF8 expansion
2726 (code units, not bytes) */
2727 for (i = 0, j = 0; i < len; i++) {
2728 unsigned c = strpool[i + strstart[s - 65536L]];
2729 if (c >= 0xD800 && c <= 0xDBFF) {
2730 unsigned lo = strpool[++i + strstart[s - 65536L]];
2731 if (lo >= 0xDC00 && lo <= 0xDFFF)
2732 c = (c - 0xD800) * 0x0400 + lo - 0xDC00;
2733 else
2734 c = 0xFFFD;
2736 if (c < 0x80)
2737 bytesToWrite = 1;
2738 else if (c < 0x800)
2739 bytesToWrite = 2;
2740 else if (c < 0x10000)
2741 bytesToWrite = 3;
2742 else if (c < 0x110000)
2743 bytesToWrite = 4;
2744 else {
2745 bytesToWrite = 3;
2746 c = 0xFFFD;
2749 j += bytesToWrite;
2750 switch (bytesToWrite) { /* note: everything falls through. */
2751 case 4: name[--j] = ((c | 0x80) & 0xBF); c >>= 6;
2752 case 3: name[--j] = ((c | 0x80) & 0xBF); c >>= 6;
2753 case 2: name[--j] = ((c | 0x80) & 0xBF); c >>= 6;
2754 case 1: name[--j] = (c | firstByteMark[bytesToWrite]);
2756 j += bytesToWrite;
2758 name[j] = 0;
2759 return name;
2762 #else
2764 string
2765 gettexstring (strnumber s)
2767 poolpointer len;
2768 string name;
2769 #if !defined(Aleph)
2770 len = strstart[s + 1] - strstart[s];
2771 #else
2772 len = strstartar[s + 1 - 65536L] - strstartar[s - 65536L];
2773 #endif
2774 name = (string)xmalloc (len + 1);
2775 #if !defined(Aleph)
2776 strncpy (name, (string)&strpool[strstart[s]], len);
2777 #else
2779 poolpointer i;
2780 /* Don't use strncpy. The strpool is not made up of chars. */
2781 for (i=0; i<len; i++) name[i] = strpool[i+strstartar[s - 65536L]];
2783 #endif
2784 name[len] = 0;
2785 return name;
2788 #endif /* not XeTeX */
2790 boolean
2791 isnewsource (strnumber srcfilename, int lineno)
2793 char *name = gettexstring(srcfilename);
2794 return (compare_paths(name, last_source_name) != 0 || lineno != last_lineno);
2797 void
2798 remembersourceinfo (strnumber srcfilename, int lineno)
2800 if (last_source_name)
2801 free(last_source_name);
2802 last_source_name = gettexstring(srcfilename);
2803 last_lineno = lineno;
2806 poolpointer
2807 makesrcspecial (strnumber srcfilename, int lineno)
2809 poolpointer oldpoolptr = poolptr;
2810 char *filename = gettexstring(srcfilename);
2811 /* FIXME: Magic number. */
2812 char buf[40];
2813 char *s = buf;
2815 /* Always put a space after the number, which makes things easier
2816 * to parse.
2818 sprintf (buf, "src:%d ", lineno);
2820 if (poolptr + strlen(buf) + strlen(filename) >= (size_t)poolsize) {
2821 fprintf (stderr, "\nstring pool overflow\n"); /* fixme */
2822 exit (1);
2824 s = buf;
2825 while (*s)
2826 strpool[poolptr++] = *s++;
2828 s = filename;
2829 while (*s)
2830 strpool[poolptr++] = *s++;
2832 return (oldpoolptr);
2835 /* pdfTeX routines also used for e-pTeX and e-upTeX */
2836 #if defined (pdfTeX) || defined (epTeX) || defined (eupTeX)
2838 #include <kpathsea/c-stat.h>
2839 #include "md5.h"
2841 #define check_nprintf(size_get, size_want) \
2842 if ((unsigned)(size_get) >= (unsigned)(size_want)) \
2843 pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
2844 # define check_buf(size, buf_size) \
2845 if ((unsigned)(size) > (unsigned)(buf_size)) \
2846 pdftex_fail("buffer overflow at file %s, line %d", __FILE__, __LINE__ )
2847 # define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0)
2848 # define MAX_CSTRING_LEN 1024 * 1024
2850 #if !defined (pdfTeX)
2851 # define PRINTF_BUF_SIZE 1024
2852 static char print_buf[PRINTF_BUF_SIZE];
2854 /* Helper for pdftex_fail. */
2855 static void safe_print(const char *str)
2857 const char *c;
2858 for (c = str; *c; ++c)
2859 print(*c);
2861 /* pdftex_fail may be called when a buffer overflow has happened/is
2862 happening, therefore may not call mktexstring. However, with the
2863 current implementation it appears that error messages are misleading,
2864 possibly because pool overflows are detected too late.
2866 The output format of this fuction must be the same as pdf_error in
2867 pdftex.web! */
2868 __attribute__ ((noreturn, format(printf, 1, 2)))
2869 void pdftex_fail(const char *fmt, ...)
2871 va_list args;
2872 va_start(args, fmt);
2873 println();
2874 safe_print("!error: ");
2875 vsnprintf(print_buf, PRINTF_BUF_SIZE, fmt, args);
2876 safe_print(print_buf);
2877 va_end(args);
2878 println();
2879 safe_print(" ==> Fatal error occurred, output file will be damaged!");
2880 println();
2881 if (kpathsea_debug) {
2882 safe_print("kpathsea_debug enabled, calling abort()...");
2883 println();
2884 abort();
2885 } else {
2886 exit(EXIT_FAILURE);
2889 #endif /* not pdfTeX */
2891 static time_t start_time = 0;
2892 #define TIME_STR_SIZE 30
2893 char start_time_str[TIME_STR_SIZE];
2894 static char time_str[TIME_STR_SIZE];
2895 /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
2897 static void makepdftime(time_t t, char *time_str)
2900 struct tm lt, gmt;
2901 size_t size;
2902 int i, off, off_hours, off_mins;
2904 /* get the time */
2905 lt = *localtime(&t);
2906 size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
2907 /* expected format: "YYYYmmddHHMMSS" */
2908 if (size == 0) {
2909 /* unexpected, contents of time_str is undefined */
2910 time_str[0] = '\0';
2911 return;
2914 /* correction for seconds: %S can be in range 00..61,
2915 the PDF reference expects 00..59,
2916 therefore we map "60" and "61" to "59" */
2917 if (time_str[14] == '6') {
2918 time_str[14] = '5';
2919 time_str[15] = '9';
2920 time_str[16] = '\0'; /* for safety */
2923 /* get the time zone offset */
2924 gmt = *gmtime(&t);
2926 /* this calculation method was found in exim's tod.c */
2927 off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
2928 if (lt.tm_year != gmt.tm_year) {
2929 off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
2930 } else if (lt.tm_yday != gmt.tm_yday) {
2931 off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
2934 if (off == 0) {
2935 time_str[size++] = 'Z';
2936 time_str[size] = 0;
2937 } else {
2938 off_hours = off / 60;
2939 off_mins = abs(off - off_hours * 60);
2940 i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
2941 check_nprintf(i, 9);
2945 void initstarttime(void)
2947 if (start_time == 0) {
2948 start_time = time((time_t *) NULL);
2949 makepdftime(start_time, start_time_str);
2953 char *makecstring(integer s)
2955 static char *cstrbuf = NULL;
2956 char *p;
2957 static int allocsize;
2958 int allocgrow, i, l = strstart[s + 1] - strstart[s];
2959 check_buf(l + 1, MAX_CSTRING_LEN);
2960 if (cstrbuf == NULL) {
2961 allocsize = l + 1;
2962 cstrbuf = xmallocarray(char, allocsize);
2963 } else if (l + 1 > allocsize) {
2964 allocgrow = allocsize * 0.2;
2965 if (l + 1 - allocgrow > allocsize)
2966 allocsize = l + 1;
2967 else if (allocsize < MAX_CSTRING_LEN - allocgrow)
2968 allocsize += allocgrow;
2969 else
2970 allocsize = MAX_CSTRING_LEN;
2971 cstrbuf = xreallocarray(cstrbuf, char, allocsize);
2973 p = cstrbuf;
2974 for (i = 0; i < l; i++)
2975 *p++ = strpool[i + strstart[s]];
2976 *p = 0;
2977 return cstrbuf;
2980 /* makecfilename
2981 input/ouput same as makecstring:
2982 input: string number
2983 output: C string with quotes removed.
2984 That means, file names that are legal on some operation systems
2985 cannot any more be used since pdfTeX version 1.30.4.
2987 char *makecfilename(integer s)
2989 char *name = makecstring(s);
2990 char *p = name;
2991 char *q = name;
2993 while (*p) {
2994 if (*p != '"')
2995 *q++ = *p;
2996 p++;
2998 *q = '\0';
2999 return name;
3002 void getcreationdate(void)
3004 size_t len;
3005 initstarttime();
3006 /* put creation date on top of string pool and update poolptr */
3007 len = strlen(start_time_str);
3009 /* In e-pTeX, "init len => call initstarttime()" (as pdftexdir/utils.c)
3010 yields unintentional output. */
3012 if ((unsigned) (poolptr + len) >= (unsigned) (poolsize)) {
3013 poolptr = poolsize;
3014 /* error by str_toks that calls str_room(1) */
3015 return;
3018 memcpy(&strpool[poolptr], start_time_str, len);
3019 poolptr += len;
3022 void getfilemoddate(integer s)
3024 struct stat file_data;
3026 char *file_name = kpse_find_tex(makecfilename(s));
3027 if (file_name == NULL) {
3028 return; /* empty string */
3031 recorder_record_input(file_name);
3032 /* get file status */
3033 if (stat(file_name, &file_data) == 0) {
3034 size_t len;
3036 makepdftime(file_data.st_mtime, time_str);
3037 len = strlen(time_str);
3038 if ((unsigned) (poolptr + len) >= (unsigned) (poolsize)) {
3039 poolptr = poolsize;
3040 /* error by str_toks that calls str_room(1) */
3041 } else {
3042 memcpy(&strpool[poolptr], time_str, len);
3043 poolptr += len;
3046 /* else { errno contains error code } */
3048 xfree(file_name);
3051 void getfilesize(integer s)
3053 struct stat file_data;
3054 int i;
3056 char *file_name = kpse_find_tex(makecfilename(s));
3057 if (file_name == NULL) {
3058 return; /* empty string */
3061 recorder_record_input(file_name);
3062 /* get file status */
3063 if (stat(file_name, &file_data) == 0) {
3064 size_t len;
3065 char buf[20];
3067 /* st_size has type off_t */
3068 i = snprintf(buf, sizeof(buf),
3069 "%lu", (long unsigned int) file_data.st_size);
3070 check_nprintf(i, sizeof(buf));
3071 len = strlen(buf);
3072 if ((unsigned) (poolptr + len) >= (unsigned) (poolsize)) {
3073 poolptr = poolsize;
3074 /* error by str_toks that calls str_room(1) */
3075 } else {
3076 memcpy(&strpool[poolptr], buf, len);
3077 poolptr += len;
3080 /* else { errno contains error code } */
3082 xfree(file_name);
3085 void getfiledump(integer s, int offset, int length)
3087 FILE *f;
3088 int read, i;
3089 poolpointer data_ptr;
3090 poolpointer data_end;
3091 char *file_name;
3093 if (length == 0) {
3094 /* empty result string */
3095 return;
3098 if (poolptr + 2 * length + 1 >= poolsize) {
3099 /* no place for result */
3100 poolptr = poolsize;
3101 /* error by str_toks that calls str_room(1) */
3102 return;
3105 file_name = kpse_find_tex(makecfilename(s));
3106 if (file_name == NULL) {
3107 return; /* empty string */
3110 /* read file data */
3111 f = fopen(file_name, FOPEN_RBIN_MODE);
3112 if (f == NULL) {
3113 xfree(file_name);
3114 return;
3116 recorder_record_input(file_name);
3117 if (fseek(f, offset, SEEK_SET) != 0) {
3118 xfree(file_name);
3119 return;
3121 /* there is enough space in the string pool, the read
3122 data are put in the upper half of the result, thus
3123 the conversion to hex can be done without overwriting
3124 unconverted bytes. */
3125 data_ptr = poolptr + length;
3126 read = fread(&strpool[data_ptr], sizeof(char), length, f);
3127 fclose(f);
3129 /* convert to hex */
3130 data_end = data_ptr + read;
3131 for (; data_ptr < data_end; data_ptr++) {
3132 i = snprintf((char *) &strpool[poolptr], 3,
3133 "%.2X", (unsigned int) strpool[data_ptr]);
3134 check_nprintf(i, 3);
3135 poolptr += i;
3137 xfree(file_name);
3141 /* Converts any given string in into an allowed PDF string which is
3142 * hexadecimal encoded;
3143 * sizeof(out) should be at least lin*2+1.
3145 void convertStringToHexString(const char *in, char *out, int lin)
3147 int i, j, k;
3148 char buf[3];
3149 j = 0;
3150 for (i = 0; i < lin; i++) {
3151 k = snprintf(buf, sizeof(buf),
3152 "%02X", (unsigned int) (unsigned char) in[i]);
3153 check_nprintf(k, sizeof(buf));
3154 out[j++] = buf[0];
3155 out[j++] = buf[1];
3157 out[j] = '\0';
3160 #define DIGEST_SIZE 16
3161 #define FILE_BUF_SIZE 1024
3163 void getmd5sum(strnumber s, boolean file)
3165 md5_state_t state;
3166 md5_byte_t digest[DIGEST_SIZE];
3167 char outbuf[2 * DIGEST_SIZE + 1];
3168 int len = 2 * DIGEST_SIZE;
3170 if (file) {
3171 char file_buf[FILE_BUF_SIZE];
3172 int read = 0;
3173 FILE *f;
3175 char *file_name = kpse_find_tex(makecfilename(s));
3176 if (file_name == NULL) {
3177 return; /* empty string */
3179 /* in case of error the empty string is returned,
3180 no need for xfopen that aborts on error.
3182 f = fopen(file_name, FOPEN_RBIN_MODE);
3183 if (f == NULL) {
3184 xfree(file_name);
3185 return;
3187 recorder_record_input(file_name);
3188 md5_init(&state);
3189 while ((read = fread(&file_buf, sizeof(char), FILE_BUF_SIZE, f)) > 0) {
3190 md5_append(&state, (const md5_byte_t *) file_buf, read);
3192 md5_finish(&state, digest);
3193 fclose(f);
3195 xfree(file_name);
3196 } else {
3197 /* s contains the data */
3198 md5_init(&state);
3199 md5_append(&state,
3200 (const md5_byte_t *) &strpool[strstart[s]],
3201 strstart[s + 1] - strstart[s]);
3202 md5_finish(&state, digest);
3205 if (poolptr + len >= poolsize) {
3206 /* error by str_toks that calls str_room(1) */
3207 return;
3209 convertStringToHexString((char *) digest, outbuf, DIGEST_SIZE);
3210 memcpy(&strpool[poolptr], outbuf, len);
3211 poolptr += len;
3214 #endif /* pdfTeX or e-pTeX or e-upTeX */
3215 #endif /* TeX */
3217 /* Metafont/MetaPost fraction routines. Replaced either by assembler or C.
3218 The assembler syntax doesn't work on Solaris/x86. */
3219 #ifndef TeX
3220 #if defined (__sun__) || defined (__cplusplus)
3221 #define NO_MF_ASM
3222 #endif
3223 /* The assembler code is not PIC safe on i?86 so use C code. */
3224 #if defined (__PIC__) && defined (__i386__)
3225 #define NO_MF_ASM
3226 #endif
3227 #if defined(WIN32) && !defined(NO_MF_ASM) && !defined(__MINGW32__)
3228 #include "lib/mfmpw32.c"
3229 #elif defined (__i386__) && defined (__GNUC__) && !defined (NO_MF_ASM)
3230 #include "lib/mfmpi386.asm"
3231 #else
3232 /* Replace fixed-point fraction routines from mf.web and mp.web with
3233 Hobby's floating-point C code. */
3235 /****************************************************************
3236 Copyright 1990 - 1995 by AT&T Bell Laboratories.
3238 Permission to use, copy, modify, and distribute this software
3239 and its documentation for any purpose and without fee is hereby
3240 granted, provided that the above copyright notice appear in all
3241 copies and that both that the copyright notice and this
3242 permission notice and warranty disclaimer appear in supporting
3243 documentation, and that the names of AT&T Bell Laboratories or
3244 any of its entities not be used in advertising or publicity
3245 pertaining to distribution of the software without specific,
3246 written prior permission.
3248 AT&T disclaims all warranties with regard to this software,
3249 including all implied warranties of merchantability and fitness.
3250 In no event shall AT&T be liable for any special, indirect or
3251 consequential damages or any damages whatsoever resulting from
3252 loss of use, data or profits, whether in an action of contract,
3253 negligence or other tortious action, arising out of or in
3254 connection with the use or performance of this software.
3255 ****************************************************************/
3257 /**********************************************************
3258 The following is by John Hobby
3259 **********************************************************/
3261 #ifndef FIXPT
3263 /* These replacements for takefraction, makefraction, takescaled, makescaled
3264 run about 3 to 11 times faster than the standard versions on modern machines
3265 that have fast hardware for double-precision floating point. They should
3266 produce approximately correct results on all machines and agree exactly
3267 with the standard versions on machines that satisfy the following conditions:
3268 1. Doubles must have at least 46 mantissa bits; i.e., numbers expressible
3269 as n*2^k with abs(n)<2^46 should be representable.
3270 2. The following should hold for addition, subtraction, and multiplcation but
3271 not necessarily for division:
3272 A. If the true answer is between two representable numbers, the computed
3273 answer must be one of them.
3274 B. When the true answer is representable, this must be the computed result.
3275 3. Dividing one double by another should always produce a relative error of
3276 at most one part in 2^46. (This is why the mantissa requirement is
3277 46 bits instead of 45 bits.)
3278 3. In the absence of overflow, double-to-integer conversion should truncate
3279 toward zero and do this in an exact fashion.
3280 4. Integer-to-double convesion should produce exact results.
3281 5. Dividing one power of two by another should yield an exact result.
3282 6. ASCII to double conversion should be exact for integer values.
3283 7. Integer arithmetic must be done in the two's-complement system.
3285 #define ELGORDO 0x7fffffff
3286 #define TWEXP31 2147483648.0
3287 #define TWEXP28 268435456.0
3288 #define TWEXP16 65536.0
3289 #define TWEXP_16 (1.0/65536.0)
3290 #define TWEXP_28 (1.0/268435456.0)
3292 integer
3293 ztakefraction (integer p, integer q) /* Approximate p*q/2^28 */
3294 { register double d;
3295 register integer i;
3296 d = (double)p * (double)q * TWEXP_28;
3297 if ((p^q) >= 0) {
3298 d += 0.5;
3299 if (d>=TWEXP31) {
3300 if (d!=TWEXP31 || (((p&077777)*(q&077777))&040000)==0)
3301 aritherror = true;
3302 return ELGORDO;
3304 i = (integer) d;
3305 if (d==i && (((p&077777)*(q&077777))&040000)!=0) --i;
3306 } else {
3307 d -= 0.5;
3308 if (d<= -TWEXP31) {
3309 if (d!= -TWEXP31 || ((-(p&077777)*(q&077777))&040000)==0)
3310 aritherror = true;
3311 return -ELGORDO;
3313 i = (integer) d;
3314 if (d==i && ((-(p&077777)*(q&077777))&040000)!=0) ++i;
3316 return i;
3319 integer
3320 ztakescaled (integer p, integer q) /* Approximate p*q/2^16 */
3321 { register double d;
3322 register integer i;
3323 d = (double)p * (double)q * TWEXP_16;
3324 if ((p^q) >= 0) {
3325 d += 0.5;
3326 if (d>=TWEXP31) {
3327 if (d!=TWEXP31 || (((p&077777)*(q&077777))&040000)==0)
3328 aritherror = true;
3329 return ELGORDO;
3331 i = (integer) d;
3332 if (d==i && (((p&077777)*(q&077777))&040000)!=0) --i;
3333 } else {
3334 d -= 0.5;
3335 if (d<= -TWEXP31) {
3336 if (d!= -TWEXP31 || ((-(p&077777)*(q&077777))&040000)==0)
3337 aritherror = true;
3338 return -ELGORDO;
3340 i = (integer) d;
3341 if (d==i && ((-(p&077777)*(q&077777))&040000)!=0) ++i;
3343 return i;
3346 /* Note that d cannot exactly equal TWEXP31 when the overflow test is made
3347 because the exact value of p/q cannot be strictly between (2^31-1)/2^28
3348 and 8/1. No pair of integers less than 2^31 has such a ratio.
3350 integer
3351 zmakefraction (integer p, integer q) /* Approximate 2^28*p/q */
3352 { register double d;
3353 register integer i;
3354 #ifdef DEBUG
3355 if (q==0) confusion(47);
3356 #endif /* DEBUG */
3357 d = TWEXP28 * (double)p /(double)q;
3358 if ((p^q) >= 0) {
3359 d += 0.5;
3360 if (d>=TWEXP31) {aritherror=true; return ELGORDO;}
3361 i = (integer) d;
3362 if (d==i && ( ((q>0 ? -q : q)&077777)
3363 * (((i&037777)<<1)-1) & 04000)!=0) --i;
3364 } else {
3365 d -= 0.5;
3366 if (d<= -TWEXP31) {aritherror=true; return -ELGORDO;}
3367 i = (integer) d;
3368 if (d==i && ( ((q>0 ? q : -q)&077777)
3369 * (((i&037777)<<1)+1) & 04000)!=0) ++i;
3371 return i;
3374 /* Note that d cannot exactly equal TWEXP31 when the overflow test is made
3375 because the exact value of p/q cannot be strictly between (2^31-1)/2^16
3376 and 2^15/1. No pair of integers less than 2^31 has such a ratio.
3378 integer
3379 zmakescaled (integer p, integer q) /* Approximate 2^16*p/q */
3380 { register double d;
3381 register integer i;
3382 #ifdef DEBUG
3383 if (q==0) confusion(47);
3384 #endif /* DEBUG */
3385 d = TWEXP16 * (double)p /(double)q;
3386 if ((p^q) >= 0) {
3387 d += 0.5;
3388 if (d>=TWEXP31) {aritherror=true; return ELGORDO;}
3389 i = (integer) d;
3390 if (d==i && ( ((q>0 ? -q : q)&077777)
3391 * (((i&037777)<<1)-1) & 04000)!=0) --i;
3392 } else {
3393 d -= 0.5;
3394 if (d<= -TWEXP31) {aritherror=true; return -ELGORDO;}
3395 i = (integer) d;
3396 if (d==i && ( ((q>0 ? q : -q)&077777)
3397 * (((i&037777)<<1)+1) & 04000)!=0) ++i;
3399 return i;
3402 #endif /* not FIXPT */
3403 #endif /* not assembler */
3404 #endif /* not TeX, i.e., MF */
3406 #ifdef MF
3407 /* On-line display routines for Metafont. Here we use a dispatch table
3408 indexed by the MFTERM or TERM environment variable to select the
3409 graphics routines appropriate to the user's terminal. stdout must be
3410 connected to a terminal for us to do any graphics. */
3412 #ifdef MFNOWIN
3413 #undef AMIGAWIN
3414 #undef EPSFWIN
3415 #undef HP2627WIN
3416 #undef MFTALKWIN
3417 #undef NEXTWIN
3418 #undef REGISWIN
3419 #undef SUNWIN
3420 #undef TEKTRONIXWIN
3421 #undef UNITERMWIN
3422 #undef WIN32WIN
3423 #undef X11WIN
3424 #endif
3426 /* Prototypes for Metafont display routines: mf_XXX_initscreen,
3427 mf_XXX_updatescreen, mf_XXX_blankrectangle, and mf_XXX_paintrow. */
3428 #include <window/mfdisplay.h>
3430 /* This variable, `mfwsw', contains the dispatch tables for each
3431 terminal. We map the Pascal calls to the routines `init_screen',
3432 `update_screen', `blank_rectangle', and `paint_row' into the
3433 appropriate entry point for the specific terminal that MF is being
3434 run on. */
3436 struct mfwin_sw
3438 const char *mfwsw_type; /* Name of terminal a la TERMCAP. */
3439 int (*mfwsw_initscreen) (void);
3440 void (*mfwsw_updatescrn) (void);
3441 void (*mfwsw_blankrect) (screencol, screencol, screenrow, screenrow);
3442 void (*mfwsw_paintrow) (screenrow, pixelcolor, transspec, screencol);
3443 } mfwsw[] =
3445 #ifdef AMIGAWIN
3446 { "amiterm", mf_amiga_initscreen, mf_amiga_updatescreen,
3447 mf_amiga_blankrectangle, mf_amiga_paintrow },
3448 #endif
3449 #ifdef EPSFWIN
3450 { "epsf", mf_epsf_initscreen, mf_epsf_updatescreen,
3451 mf_epsf_blankrectangle, mf_epsf_paintrow },
3452 #endif
3453 #ifdef HP2627WIN
3454 { "hp2627", mf_hp2627_initscreen, mf_hp2627_updatescreen,
3455 mf_hp2627_blankrectangle, mf_hp2627_paintrow },
3456 #endif
3457 #ifdef MFTALKWIN
3458 { "mftalk", mf_mftalk_initscreen, mf_mftalk_updatescreen,
3459 mf_mftalk_blankrectangle, mf_mftalk_paintrow },
3460 #endif
3461 #ifdef NEXTWIN
3462 { "next", mf_next_initscreen, mf_next_updatescreen,
3463 mf_next_blankrectangle, mf_next_paintrow },
3464 #endif
3465 #ifdef REGISWIN
3466 { "regis", mf_regis_initscreen, mf_regis_updatescreen,
3467 mf_regis_blankrectangle, mf_regis_paintrow },
3468 #endif
3469 #ifdef SUNWIN
3470 { "sun", mf_sun_initscreen, mf_sun_updatescreen,
3471 mf_sun_blankrectangle, mf_sun_paintrow },
3472 #endif
3473 #ifdef TEKTRONIXWIN
3474 { "tek", mf_tektronix_initscreen, mf_tektronix_updatescreen,
3475 mf_tektronix_blankrectangle, mf_tektronix_paintrow },
3476 #endif
3477 #ifdef UNITERMWIN
3478 { "uniterm", mf_uniterm_initscreen, mf_uniterm_updatescreen,
3479 mf_uniterm_blankrectangle, mf_uniterm_paintrow },
3480 #endif
3481 #ifdef WIN32WIN
3482 { "win32term", mf_win32_initscreen, mf_win32_updatescreen,
3483 mf_win32_blankrectangle, mf_win32_paintrow },
3484 #endif
3485 #ifdef X11WIN
3486 { "xterm", mf_x11_initscreen, mf_x11_updatescreen,
3487 mf_x11_blankrectangle, mf_x11_paintrow },
3488 #endif
3490 /* Always support this. */
3491 { "trap", mf_trap_initscreen, mf_trap_updatescreen,
3492 mf_trap_blankrectangle, mf_trap_paintrow },
3494 /* Finally, we must have an entry with a terminal type of NULL. */
3495 { NULL, NULL, NULL, NULL, NULL }
3497 }; /* End of the array initialization. */
3500 /* This is a pointer to the mfwsw[] entry that we find. */
3501 static struct mfwin_sw *mfwp;
3504 /* The following are routines that just jump to the correct
3505 terminal-specific graphics code. If none of the routines in the
3506 dispatch table exist, or they fail, we produce trap-compatible
3507 output, i.e., the same words and punctuation that the unchanged
3508 mf.web would produce. */
3511 /* This returns true if we can do window operations, else false. */
3513 boolean
3514 initscreen (void)
3516 int retval;
3517 /* If MFTERM is set, use it. */
3518 const_string tty_type = kpse_var_value ("MFTERM");
3520 if (tty_type == NULL)
3522 #if defined (AMIGA)
3523 tty_type = "amiterm";
3524 #elif defined (WIN32)
3525 tty_type = "win32term";
3526 #elif defined (OS2) || defined (__DJGPP__) /* not AMIGA nor WIN32 */
3527 tty_type = "mftalk";
3528 #else /* not (OS2 or WIN32 or __DJGPP__ or AMIGA) */
3529 /* If DISPLAY is set, we are X11; otherwise, who knows. */
3530 boolean have_display = getenv ("DISPLAY") != NULL;
3531 tty_type = have_display ? "xterm" : getenv ("TERM");
3533 /* If we don't know what kind of terminal this is, or if Metafont
3534 isn't being run interactively, don't do any online output. */
3535 if (tty_type == NULL
3536 || (!STREQ (tty_type, "trap") && !isatty (fileno (stdout))))
3537 return 0;
3538 #endif /* not (OS2 or WIN32 or __DJGPP__ or AMIGA) */
3541 /* Test each of the terminals given in `mfwsw' against the terminal
3542 type, and take the first one that matches, or if the user is running
3543 under Emacs, the first one. */
3544 for (mfwp = mfwsw; mfwp->mfwsw_type != NULL; mfwp++) {
3545 if (!strncmp (mfwp->mfwsw_type, tty_type, strlen (mfwp->mfwsw_type))
3546 || STREQ (tty_type, "emacs")) {
3547 if (mfwp->mfwsw_initscreen) {
3548 retval = (*mfwp->mfwsw_initscreen) ();
3549 #ifdef WIN32
3550 Sleep(1000); /* Wait for opening a window */
3551 #endif
3552 return retval;
3554 else {
3555 fprintf (stderr, "mf: Couldn't initialize online display for `%s'.\n",
3556 tty_type);
3557 break;
3562 /* The current terminal type wasn't found in any of the entries, or
3563 initalization failed, so silently give up, assuming that the user
3564 isn't on a terminal that supports graphic output. */
3565 return 0;
3569 /* Make sure everything is visible. */
3571 void
3572 updatescreen (void)
3574 if (mfwp->mfwsw_updatescrn)
3575 (*mfwp->mfwsw_updatescrn) ();
3579 /* This sets the rectangle bounded by ([left,right], [top,bottom]) to
3580 the background color. */
3582 void
3583 blankrectangle (screencol left, screencol right,
3584 screenrow top, screenrow bottom)
3586 if (mfwp->mfwsw_blankrect)
3587 (*mfwp->mfwsw_blankrect) (left, right, top, bottom);
3591 /* This paints ROW, starting with the color INIT_COLOR.
3592 TRANSITION_VECTOR then specifies the length of the run; then we
3593 switch colors. This goes on for VECTOR_SIZE transitions. */
3595 void
3596 paintrow (screenrow row, pixelcolor init_color,
3597 transspec transition_vector, screencol vector_size)
3599 if (mfwp->mfwsw_paintrow)
3600 (*mfwp->mfwsw_paintrow) (row, init_color, transition_vector, vector_size);
3602 #endif /* MF */