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
6 This file is public domain. */
8 /* This file is included from, e.g., texextra,c after
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
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>
22 #include <kpathsea/concatn.h>
25 #if defined (HAVE_SYS_TIME_H)
27 #elif defined (HAVE_SYS_TIMEB_H)
28 #include <sys/timeb.h>
30 #include <time.h> /* For `struct tm'. Moved here for Visual Studio 2005. */
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. */
48 #include <xetexdir/xetexextra.h>
51 #include <etexdir/etexextra.h>
52 #elif defined (pdfTeX)
54 #include <pdftexdir/pdftexextra.h>
55 #include <pdftexdir/ptexlib.h>
58 #include <alephdir/alephextra.h>
61 #include <ptexdir/ptexextra.h>
65 #include <eptexdir/eptexextra.h>
69 #include <uptexdir/uptexextra.h>
70 #elif defined (eupTeX)
74 #include <euptexdir/euptexextra.h>
76 #define BANNER "This is TeX, Version 3.14159265"
77 #define COPYRIGHT_HOLDER "D.E. Knuth"
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"
89 #define edit_var "TEXEDIT"
92 #define BANNER "This is Metafont, Version 2.7182818"
93 #define COPYRIGHT_HOLDER "D.E. Knuth"
95 #define PROGRAM_HELP MFHELP
96 #define BUG_ADDRESS "tex-k@tug.org"
97 #define DUMP_VAR MFbasedefault
98 #define DUMP_LENGTH_VAR basedefaultlength
99 #define DUMP_OPTION "base"
101 #define DUMP_EXT ".bas"
103 #define DUMP_EXT ".base"
105 #define INPUT_FORMAT kpse_mf_format
106 #define INI_PROGRAM "inimf"
107 #define VIR_PROGRAM "virmf"
108 #define edit_var "MFEDIT"
111 #if !defined(IS_eTeX)
114 #if !defined(IS_pTeX)
117 #if !defined(IS_upTeX)
121 #if defined(__SyncTeX__)
123 SyncTeX file name should be full path in the case where
124 --output-directory option is given.
125 Borrowed from LuaTeX.
127 char *generic_synctex_get_current_name (void)
130 if (!fullnameoffile
) {
134 if (kpse_absolute_p(fullnameoffile
, false)) {
135 return xstrdup(fullnameoffile
);
138 ret
= concat3(pwdbuf
, DIR_SEP_STRING
, fullnameoffile
);
150 #if defined(TeX) || (defined(MF) && defined(WIN32))
154 return (c
== ' ' || c
== '\t');
156 #endif /* TeX || (MF && WIN32) */
162 If shellenabledp == 0, all shell escapes are forbidden.
163 If (shellenabledp == 1 && restrictedshell == 0), any command
164 is allowed for a shell escape.
165 If (shellenabledp == 1 && restrictedshell == 1), only commands
166 given in the configuration file as
167 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun,...
168 (no spaces between commands) in texmf.cnf are allowed for a shell
169 escape in a restricted form: command name and arguments should be
170 separated by a white space. The first word should be a command
171 name. The quotation character for an argument with spaces,
172 including a pathname, should be ". ' should not be used.
174 Internally, all arguments are quoted by ' (Unix) or " (Windows)
175 before calling the system() function in order to forbid execution
176 of any embedded command. In addition, on Windows, special
177 characters of cmd.exe are escaped by using (^).
179 If the --shell-escape option is given, we set
180 shellenabledp = 1 and restrictedshell = 0, i.e., any command is allowed.
181 If the --shell-restricted option is given, we set
182 shellenabledp = 1 and restrictedshell = 1, i.e., only given cmds allowed.
183 If the --no-shell-escape option is given, we set
184 shellenabledp = -1 (and restrictedshell is irrelevant).
185 If none of these option are given, there are three cases:
186 (1) In the case where
190 it becomes shellenabledp = 1 and restrictedshell = 0,
191 that is, any command is allowed.
192 (2) In the case where
194 it becomes shellenabledp = 1 and restrictedshell = 1,
195 that is, restricted shell escape is allowed.
196 (3) In all other cases, shellenabledp = 0, that is, shell
197 escape is forbidden. The value of restrictedshell is
198 irrelevant if shellenabledp == 0.
201 /* cmdlist is a list of allowed commands which are given like this:
202 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun
205 static char **cmdlist
= NULL
;
208 mk_shellcmdlist (char *v
)
217 /* analyze the variable shell_escape_commands = foo,bar,...
218 spaces before and after (,) are not allowed. */
220 while ((r
= strchr (q
, ',')) != 0) {
226 cmdlist
= xmalloc (n
* sizeof (char *));
229 while ((r
= strchr (q
, ',')) != 0) {
240 init_shell_escape (void)
242 if (shellenabledp
< 0) { /* --no-shell-escape on cmd line */
246 if (shellenabledp
== 0) { /* no shell options on cmd line, check cnf */
247 char *v1
= kpse_var_value ("shell_escape");
249 if (*v1
== 't' || *v1
== 'y' || *v1
== '1') {
251 } else if (*v1
== 'p') {
259 /* If shell escapes are restricted, get allowed cmds from cnf. */
260 if (shellenabledp
&& restrictedshell
== 1) {
261 char *v2
= kpse_var_value ("shell_escape_commands");
263 mk_shellcmdlist (v2
);
278 char_needs_quote (int c
)
280 /* special characters of cmd.exe */
282 return (c
== '&' || c
== '|' || c
== '%' || c
== '<' ||
283 c
== '>' || c
== ';' || c
== ',' || c
== '(' ||
289 -1 : invalid quotation of an argument
290 0 : command is not allowed
291 2 : restricted shell escape, CMD is allowed.
293 We set *SAFECMD to a safely-quoted version of *CMD; this is what
294 should get executed. And we set CMDNAME to its first word; this is
295 what is checked against the shell_escape_commands list. */
298 shell_cmd_is_allowed (const char *cmd
, char **safecmd
, char **cmdname
)
307 /* pre == 1 means that the previous character is a white space
308 pre == 0 means that the previous character is not a white space */
309 buf
= xmalloc (strlen (cmd
) + 1);
315 while (!Isspace(*d
) && *d
)
319 /* *cmdname is the first word of the command line. For example,
320 *cmdname == "kpsewhich" for
321 \write18{kpsewhich --progname=dvipdfm --format="other text files" config}
323 *cmdname
= xstrdup (c
);
326 /* Is *cmdname listed in a texmf.cnf vriable as
327 shell_escape_commands = foo,bar,... ? */
331 if (strcmp (*p
, *cmdname
) == 0) {
332 /* *cmdname is found in the list, so restricted shell escape
342 for (s
= cmd
; *s
; s
++) {
347 /* allocate enough memory (too much?) */
349 *safecmd
= xmalloc (2 * strlen (cmd
) + 3 + 2 * spaces
);
351 *safecmd
= xmalloc (strlen (cmd
) + 3 + 2 * spaces
);
354 /* make a safe command line *safecmd */
359 while (!Isspace (*s
) && *s
)
364 /* Quotation given by a user. " should always be used; we
365 transform it below. If ' is used, simply immediately
366 return a quotation error. */
372 /* All arguments are quoted as 'foo' (Unix) or "foo" (Windows)
373 before calling system(). Therefore closing QUOTE is necessary
374 if the previous character is not a white space.
376 --format="other text files" becomes
377 '--format=''other text files' (Unix)
378 "--format=""other text files" (Windows) */
384 /* output the quotation mark for the quoted argument */
389 /* Illegal use of ', or closing quotation mark is missing */
390 if (*s
== '\'' || *s
== '\0')
393 if (char_needs_quote (*s
))
399 /* Closing quotation mark will be output afterwards, so
400 we do nothing here */
403 /* The character after the closing quotation mark
404 should be a white space or NULL */
405 if (!Isspace (*s
) && *s
)
408 /* Beginning of a usual argument */
409 } else if (pre
== 1 && !Isspace (*s
)) {
413 if (char_needs_quote (*s
))
417 /* Ending of a usual argument */
419 } else if (pre
== 0 && Isspace (*s
)) {
421 /* Closing quotation mark */
425 /* Copy a character from cmd to *safecmd. */
427 if (char_needs_quote (*s
))
433 /* End of the command line */
442 if (strlen (p
) > 2 && p
[1] == ':' && !IS_DIR_SEP (p
[2])) {
443 q
= xmalloc (strlen (p
) + 2);
451 } else if (!IS_DIR_SEP (p
[0]) && !(p
[1] == ':' && IS_DIR_SEP (p
[2]))) {
452 p
= kpse_var_value ("SELFAUTOLOC");
455 while (*r
&& !Isspace(*r
))
458 q
= concatn ("\"", p
, "/", *safecmd
, "\"", NULL
);
462 while (*r
&& Isspace(*r
))
465 q
= concatn ("\"", p
, "/", *safecmd
, "\" ", r
, NULL
);
467 q
= concatn ("\"", p
, "/", *safecmd
, "\"", NULL
);
481 /* We should only be called with shellenabledp == 1.
483 -1 if a quotation syntax error.
484 0 if CMD is not allowed; given shellenabledp==1, this is because
485 shell escapes are restricted and CMD is not allowed.
486 1 if shell escapes are not restricted, hence any command is allowed.
487 2 if shell escapes are restricted and CMD is allowed (possibly after
492 #define system fsyscp_system
495 #define popen fsyscp_popen
496 #endif /* ENABLE_PIPES */
500 runsystem (const char *cmd
)
503 char *safecmd
= NULL
;
504 char *cmdname
= NULL
;
506 if (shellenabledp
<= 0) {
510 /* If restrictedshell == 0, any command is allowed. */
511 if (restrictedshell
== 0)
514 allow
= shell_cmd_is_allowed (cmd
, &safecmd
, &cmdname
);
519 (void) system (safecmd
);
531 /* Like runsystem(), the runpopen() function is called only when
532 shellenabledp == 1. Unlike runsystem(), here we write errors to
533 stderr, since we have nowhere better to use; and of course we return
534 a file handle (or NULL) instead of a status indicator. */
537 runpopen (char *cmd
, const char *mode
)
540 char *safecmd
= NULL
;
541 char *cmdname
= NULL
;
547 for (pp
= cmd
; *pp
; pp
++) {
548 if (*pp
== '\'') *pp
= '"';
552 /* If restrictedshell == 0, any command is allowed. */
553 if (restrictedshell
== 0)
556 allow
= shell_cmd_is_allowed (cmd
, &safecmd
, &cmdname
);
559 f
= popen (cmd
, mode
);
561 f
= popen (safecmd
, mode
);
562 else if (allow
== -1)
563 fprintf (stderr
, "\nrunpopen quotation error in command line: %s\n",
566 fprintf (stderr
, "\nrunpopen command not allowed: %s\n", cmdname
);
574 #endif /* ENABLE_PIPES */
576 /* The main program, etc. */
579 #include "xetexdir/XeTeX_ext.h"
582 /* What we were invoked as and with. */
586 /* If the user overrides argv[0] with -progname. */
587 static const_string user_progname
;
589 /* The C version of the jobname, if given. */
590 static const_string c_job_name
;
592 /* The filename for dynamic character translation, or NULL. */
593 string translate_filename
;
594 string default_translate_filename
;
597 /* Needed for --src-specials option. */
598 static char *last_source_name
;
599 static int last_lineno
;
600 static boolean srcspecialsoption
= false;
601 static void parse_src_specials_option (const_string
);
604 /* Parsing a first %&-line in the input file. */
605 static void parse_first_line (const_string
);
607 /* Parse option flags. */
608 static void parse_options (int, string
*);
610 /* Try to figure out if we have been given a filename. */
611 static string
get_input_file_name (void);
613 /* Get a true/false value for a variable from texmf.cnf and the environment. */
615 texmf_yesno(const_string var
)
617 string value
= kpse_var_value (var
);
618 return value
&& (*value
== 't' || *value
== 'y' || *value
== '1');
622 const char *ptexbanner
= BANNER
;
626 /* forward declaration */
628 normalize_quotes (const_string name
, const_string mesg
);
630 int srcspecialsp
= 0;
632 /* Support of 8.3-name convention. If *buffer == NULL, nothing is done. */
633 static void change_to_long_name (char **buffer
)
639 memset (outbuf
, 0, 260);
640 strcpy (inbuf
, *buffer
);
641 if (GetLongPathName (inbuf
, outbuf
, 260)) {
642 *buffer
= (char *)realloc(*buffer
, strlen(outbuf
) + 1);
643 strcpy (*buffer
, outbuf
);
649 /* The entry point: set up for reading the command line, which will
650 happen in `topenin', then call the main body. */
653 maininit (int ac
, string
*av
)
655 string main_input_file
;
656 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
659 /* Save to pass along to topenin. */
663 /* Must be initialized before options are parsed. */
664 interactionoption
= 4;
666 /* Have things to record as we go along. */
667 kpse_record_input
= recorder_record_input
;
668 kpse_record_output
= recorder_record_output
;
670 #if defined(__SyncTeX__)
671 /* 0 means "disable Synchronize TeXnology".
672 synctexoption is a *.web variable.
673 We initialize it to a weird value to catch the -synctex command line flag.
674 At runtime, if synctexoption is not INT_MAX, then it contains the
675 command line option provided; otherwise, no such option was given
677 # define SYNCTEX_NO_OPTION INT_MAX
678 synctexoption
= SYNCTEX_NO_OPTION
;
682 kpse_set_program_name (argv
[0], NULL
);
685 #if defined(XeTeX) && defined(WIN32)
686 kpse_set_program_name (argv
[0], NULL
);
688 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
689 enc
= kpse_var_value("command_line_encoding");
690 get_command_line_args_utf8(enc
, &argc
, &argv
);
693 /* If the user says --help or --version, we need to notice early. And
694 since we want the --ini option, have to do it before getting into
695 the web (which would read the base file, etc.). */
696 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
697 parse_options (argc
, argv
);
699 parse_options (ac
, av
);
703 /* In pTeX and friends, texmf.cnf is not recorded in the case of --recorder,
704 because parse_options() is executed after the start of kpathsea due to
705 special initializations. Therefore we record texmf.cnf here. */
706 if (recorder_enabled
) {
707 string p
= kpse_find_file ("texmf.cnf", kpse_cnf_format
, 0);
709 recorder_record_input (p
);
713 /* If -progname was not specified, default to the dump name. */
715 user_progname
= dump_name
;
717 /* Do this early so we can inspect kpse_invocation_name and
718 kpse_program_name below, and because we have to do this before
719 any path searching. */
720 #if IS_pTeX || (defined(XeTeX) && defined(WIN32))
722 kpse_reset_program_name (user_progname
);
724 kpse_set_program_name (argv
[0], user_progname
);
727 /* If the program name is "mf-nowin", then reset the name as "mf". */
728 if (strncasecmp (kpse_invocation_name
, "mf-nowin", 8) == 0)
729 kpse_reset_program_name ("mf");
731 /* FIXME: gather engine names in a single spot. */
732 xputenv ("engine", TEXMFENGINENAME
);
734 /* Were we given a simple filename? */
735 main_input_file
= get_input_file_name();
738 if (main_input_file
== NULL
) {
745 if (name
&& name
[0] != '-' && name
[0] != '&' && name
[0] != '\\') {
746 if (strlen (name
) > 2 && isalpha (name
[0]) && name
[1] == ':' &&
749 for (pp
= name
; *pp
; pp
++) {
752 else if (*pp
== '\\')
757 name
= normalize_quotes(argv
[argc
-1], "argument");
758 main_input_file
= kpse_find_file(argv
[argc
-1], INPUT_FORMAT
, false);
760 change_to_long_name (&main_input_file
);
762 name
= normalize_quotes(main_input_file
, "argument");
766 name
= normalize_quotes(argv
[argc
-1], "argument");
767 quoted
= (name
[0] == '"');
769 /* Overwrite last quote and skip first quote. */
770 name
[strlen(name
)-1] = '\0';
773 main_input_file
= kpse_find_file(name
, INPUT_FORMAT
, false);
775 change_to_long_name (&main_input_file
);
777 /* Undo modifications */
778 name
[strlen(name
)] = '"';
783 name
= normalize_quotes(main_input_file
, "argument");
791 /* Second chance to activate file:line:error style messages, this
792 time from texmf.cnf. */
793 if (filelineerrorstylep
< 0) {
794 filelineerrorstylep
= 0;
795 } else if (!filelineerrorstylep
) {
796 filelineerrorstylep
= texmf_yesno ("file_line_error_style");
799 /* If no dump default yet, and we're not doing anything special on
800 this run, we may want to look at the first line of the main input
801 file for a %&<dumpname> specifier. */
802 if (parsefirstlinep
< 0) {
804 } else if (!parsefirstlinep
) {
805 parsefirstlinep
= texmf_yesno ("parse_first_line");
807 if (parsefirstlinep
&& (!dump_name
|| !translate_filename
)) {
808 parse_first_line (main_input_file
);
810 /* Check whether there still is no translate_filename known. If so,
811 use the default_translate_filename. */
812 /* FIXME: deprecated. */
813 if (!translate_filename
) {
814 translate_filename
= default_translate_filename
;
816 /* If we're preloaded, I guess everything is set up. I don't really
817 know any more, it's been so long since anyone preloaded. */
818 if (readyalready
!= 314159) {
819 /* The `ini_version' variable is declared/used in the change files. */
820 boolean virversion
= false;
821 if (FILESTRCASEEQ (kpse_program_name
, INI_PROGRAM
)) {
823 } else if (FILESTRCASEEQ (kpse_program_name
, VIR_PROGRAM
)) {
826 } else if (FILESTRCASEEQ (kpse_program_name
, "initex")) {
828 } else if (FILESTRCASEEQ (kpse_program_name
, "virtex")) {
831 } else if (FILESTRCASEEQ (kpse_program_name
, "mltex")) {
838 /* If called as *vir{mf,tex,mpost} use `plain'. Otherwise, use the
839 name we were invoked under. */
840 dump_name
= (virversion
? "plain" : kpse_program_name
);
845 /* Sanity check: -mltex, -enc, -etex only work in combination with -ini. */
849 fprintf(stderr
, "-mltex only works with -ini\n");
851 #if !defined(XeTeX) && !IS_pTeX
853 fprintf(stderr
, "-enc only works with -ini\n");
859 fprintf(stderr
, "-etex only works with -ini\n");
865 /* If we've set up the fmt/base default in any of the various ways
866 above, also set its length. */
868 const_string with_ext
= NULL
;
869 unsigned name_len
= strlen (dump_name
);
870 unsigned ext_len
= strlen (DUMP_EXT
);
872 /* Provide extension if not there already. */
873 if (name_len
> ext_len
874 && FILESTRCASEEQ (dump_name
+ name_len
- ext_len
, DUMP_EXT
)) {
875 with_ext
= dump_name
;
877 with_ext
= concat (dump_name
, DUMP_EXT
);
879 DUMP_VAR
= concat (" ", with_ext
); /* adjust array for Pascal */
880 DUMP_LENGTH_VAR
= strlen (DUMP_VAR
+ 1);
882 /* For dump_name to be NULL is a bug. */
886 /* Additional initializations. No particular reason for doing them
887 here instead of first thing in the change file; less symbols to
888 propagate through Webc, that's all. */
890 kpse_set_program_enabled (kpse_mf_format
, MAKE_TEX_MF_BY_DEFAULT
,
892 kpse_set_program_enabled (kpse_base_format
, MAKE_TEX_FMT_BY_DEFAULT
,
897 kpse_set_program_enabled (kpse_ocp_format
, MAKE_OMEGA_OCP_BY_DEFAULT
,
899 kpse_set_program_enabled (kpse_ofm_format
, MAKE_OMEGA_OFM_BY_DEFAULT
,
901 kpse_set_program_enabled (kpse_tfm_format
, false, kpse_src_compile
);
903 kpse_set_program_enabled (kpse_tfm_format
, MAKE_TEX_TFM_BY_DEFAULT
,
906 kpse_set_program_enabled (kpse_tex_format
, MAKE_TEX_TEX_BY_DEFAULT
,
908 kpse_set_program_enabled (kpse_fmt_format
, MAKE_TEX_FMT_BY_DEFAULT
,
911 init_shell_escape ();
913 if (!outputcomment
) {
914 outputcomment
= kpse_var_value ("output_comment");
919 /* The entry point: set up for reading the command line, which will
920 happen in `topenin', then call the main body. */
924 DLLPROC (int ac
, string
*av
)
926 main (int ac
, string
*av
)
930 _wildcard (&ac
, &av
);
931 _response (&ac
, &av
);
935 av
[0] = kpse_program_basename (av
[0]);
937 setmode(fileno(stdin
), _O_BINARY
);
945 if ((strlen(av
[ac
-1]) > 2) &&
946 isalpha(av
[ac
-1][0]) &&
947 (av
[ac
-1][1] == ':') &&
948 (av
[ac
-1][2] == '\\')) {
949 for (pp
=av
[ac
-1]+2; *pp
; pp
++) {
961 /* Call the real main program. */
967 /* This is supposed to ``open the terminal for input'', but what we
968 really do is copy command line arguments into TeX's or Metafont's
969 buffer, so they can handle them. If nothing is available, or we've
970 been called already (and hence, argc==0), we return with
979 static UFILE termin_file
;
981 termin
= &termin_file
;
983 termin
->savedChar
= -1;
984 termin
->skipNextLF
= 0;
985 termin
->encodingMode
= UTF8
;
986 termin
->conversionData
= 0;
987 inputfile
[0] = termin
;
991 buffer
[first
] = 0; /* In case there are no arguments. */
993 if (optind
< argc
) { /* We have command line arguments. */
995 for (i
= optind
; i
< argc
; i
++) {
997 unsigned char *ptr
= (unsigned char *)&(argv
[i
][0]);
998 /* need to interpret UTF8 from the command line */
1000 while ((rval
= *(ptr
++)) != 0) {
1001 UInt16 extraBytes
= bytesFromUTF8
[rval
];
1002 switch (extraBytes
) { /* note: code falls through cases! */
1003 case 5: rval
<<= 6; if (*ptr
) rval
+= *(ptr
++);
1004 case 4: rval
<<= 6; if (*ptr
) rval
+= *(ptr
++);
1005 case 3: rval
<<= 6; if (*ptr
) rval
+= *(ptr
++);
1006 case 2: rval
<<= 6; if (*ptr
) rval
+= *(ptr
++);
1007 case 1: rval
<<= 6; if (*ptr
) rval
+= *(ptr
++);
1010 rval
-= offsetsFromUTF8
[extraBytes
];
1014 char *ptr
= &(argv
[i
][0]);
1015 /* Don't use strcat, since in Aleph the buffer elements aren't
1018 buffer
[k
++] = *(ptr
++);
1023 argc
= 0; /* Don't do this again. */
1027 /* Find the end of the buffer. */
1028 for (last
= first
; buffer
[last
]; ++last
)
1031 /* Make `last' be one past the last non-blank character in `buffer'. */
1032 /* ??? The test for '\r' should not be necessary. */
1033 for (--last
; last
>= first
1034 && ISBLANK (buffer
[last
]) && buffer
[last
] != '\r'; --last
)
1038 /* One more time, this time converting to TeX's internal character
1040 #if !defined(Aleph) && !defined(XeTeX)
1041 for (i
= first
; i
< last
; i
++)
1042 buffer
[i
] = xord
[buffer
[i
]];
1046 /* IPC for TeX. By Tom Rokicki for the NeXT; it makes TeX ship out the
1047 DVI file in a pipe to TeXView so that the output can be displayed
1048 incrementally. Shamim Mohamed adapted it for Web2c. */
1049 #if defined (TeX) && defined (IPC)
1053 #include <winsock2.h>
1055 #include <sys/socket.h>
1057 #ifndef O_NONBLOCK /* POSIX */
1058 #ifdef O_NDELAY /* BSD */
1059 #define O_NONBLOCK O_NDELAY
1060 #elif defined(O_FNDELAY) /* NeXT */
1061 #define O_NONBLOCK O_FNDELAY
1063 what the fcntl
? cannot implement IPC without equivalent
for O_NONBLOCK
.
1065 #endif /* no O_NONBLOCK */
1069 # define IPC_AF AF_INET
1070 # ifndef IPC_LOCAL_HOST
1071 # define IPC_LOCAL_HOST "127.0.0.1"
1072 # define FIXED_PORT (unsigned short)4242
1075 # define IPC_AF AF_UNIX
1076 # ifndef IPC_PIPE_NAME /* $HOME is prepended to this. */
1077 # define IPC_PIPE_NAME "/.TeXview_Pipe"
1080 #ifndef IPC_SERVER_CMD /* Command to run to start the server. */
1082 # define IPC_SERVER_CMD "texview.exe"
1084 # define IPC_SERVER_CMD "open `which TeXview`"
1090 int namelength
; /* length of auxiliary data */
1091 int eof
; /* new eof for dvi file */
1092 #if 0 /* see usage of struct msg below */
1093 char more_data
[0]; /* where the rest of the stuff goes */
1097 static struct sockaddr
*ipc_addr
;
1098 static int ipc_addr_len
;
1101 ipc_make_name (void)
1103 if (ipc_addr_len
== 0) {
1105 unsigned long remote_addr
= inet_addr(IPC_LOCAL_HOST
);
1106 if (remote_addr
!= INADDR_NONE
) {
1107 struct sockaddr_in
*ipc_sin_addr
= xmalloc (sizeof (struct sockaddr_in
));
1108 ipc_sin_addr
->sin_family
= AF_INET
;
1109 ipc_sin_addr
->sin_addr
.s_addr
= remote_addr
;
1110 ipc_sin_addr
->sin_port
= htons (FIXED_PORT
);
1111 ipc_addr
= ((struct sockaddr
*) ipc_sin_addr
);
1112 ipc_addr_len
= sizeof(struct sockaddr_in
);
1115 string s
= getenv ("HOME");
1118 ipc_addr
= xmalloc (strlen (s
) + 40);
1119 ipc_addr
->sa_family
= 0;
1120 ipc_name
= ipc_addr
->sa_data
;
1121 strcpy (ipc_name
, s
);
1122 strcat (ipc_name
, IPC_PIPE_NAME
);
1123 ipc_addr_len
= strlen (ipc_name
) + 3;
1127 return ipc_addr_len
;
1130 static int sock
= -1;
1133 # define CLOSE_SOCKET(s) closesocket (s); WSACleanup ()
1135 # define CLOSE_SOCKET(s) close (s)
1145 ipc_open_out (void) {
1147 struct WSAData wsaData
;
1149 unsigned long mode
= 1;
1152 fputs ("tex: Opening socket for IPC output ...\n", stderr
);
1159 if ((nCode
= WSAStartup(MAKEWORD(1, 1), &wsaData
)) != 0) {
1160 fprintf(stderr
,"WSAStartup() returned error code %d.\n", nCode
);
1165 if (ipc_make_name () <= 0)
1168 sock
= socket (IPC_AF
, SOCK_STREAM
, 0);
1171 fprintf(stderr
, "tex: Socket handle is %d\n", sock
);
1173 fprintf(stderr
, "tex: Socket is invalid.\n");
1177 if (connect (sock
, ipc_addr
, ipc_addr_len
) != 0 ||
1179 ioctlsocket (sock
, FIONBIO
, &mode
) < 0
1181 fcntl (sock
, F_SETFL
, O_NONBLOCK
) < 0
1184 CLOSE_SOCKET (sock
);
1187 fputs ("tex: IPC socket cannot be connected.\n", stderr
);
1188 fputs ("tex: Socket is closed.\n", stderr
);
1193 fputs ("tex: Successfully opened IPC socket.\n", stderr
);
1199 ipc_close_out (void)
1202 fputs ("tex: Closing output socket ...\n", stderr
);
1204 if (ipc_is_open ()) {
1205 CLOSE_SOCKET (sock
);
1211 ipc_snd (int n
, int is_eof
, char *data
)
1216 char more_data
[1024];
1219 if (!ipc_is_open ()) {
1224 fprintf(stderr
, "%d\t%d\n", ourmsg
.msg
.namelength
, ourmsg
.msg
.eof
);
1225 fputs ("tex: Sending message to socket ...\n", stderr
);
1227 ourmsg
.msg
.namelength
= n
;
1228 ourmsg
.msg
.eof
= is_eof
;
1230 strcpy (ourmsg
.more_data
, data
);
1232 n
+= sizeof (struct msg
);
1234 fprintf(stderr
, "%d\t%d\n", ourmsg
.msg
.namelength
, ourmsg
.msg
.eof
);
1235 fputs ("tex: Writing to socket...\n", stderr
);
1238 if (send (sock
, (char *)&ourmsg
, n
, 0) != n
) {
1240 if (write (sock
, &ourmsg
, n
) != n
) {
1245 fputs ("tex: IPC message sent.\n", stderr
);
1249 /* This routine notifies the server if there is an eof, or the filename
1250 if a new DVI file is starting. This is the routine called by TeX.
1251 Aleph defines str_start(#) as str_start_ar[# - too_big_char], with
1252 too_big_char = biggest_char + 1 = 65536 (omstr.ch). */
1255 ipcpage (int is_eof
)
1257 static boolean begun
= false;
1262 string name
; /* Just the filename. */
1263 string cwd
= xgetcwd ();
1267 len
= strstart
[outputfilename
+ 1] - strstart
[outputfilename
];
1269 len
= strstartar
[outputfilename
+ 1 - 65536L] -
1270 strstartar
[outputfilename
- 65536L];
1272 name
= xmalloc (len
+ 1);
1274 strncpy (name
, (string
)&strpool
[strstart
[outputfilename
]], len
);
1278 for (i
=0; i
<len
; i
++)
1279 name
[i
] = strpool
[i
+strstartar
[outputfilename
- 65536L]];
1284 /* Have to pass whole filename to the other end, since it may have
1285 been started up and running as a daemon, e.g., as with the NeXT
1287 p
= concat3 (cwd
, DIR_SEP_STRING
, name
);
1293 for (q
= p
; *q
; q
++) {
1296 else if (IS_KANJI(q
))
1304 ipc_snd (len
, is_eof
, p
);
1309 #endif /* TeX && IPC */
1311 #if defined (TeX) || defined (MF)
1312 /* TCX and Aleph&Co get along like sparks and gunpowder. */
1313 #if !defined(Aleph) && !defined(XeTeX)
1315 /* Return the next number following START, setting POST to the following
1316 character, as in strtol. Issue a warning and return -1 if no number
1320 tcx_get_num (int upb
,
1321 unsigned line_count
,
1325 int num
= strtol (start
, post
, 0);
1326 assert (post
&& *post
);
1327 if (*post
== start
) {
1328 /* Could not get a number. If blank line, fine. Else complain. */
1330 while (*p
&& ISSPACE (*p
))
1333 fprintf (stderr
, "%s:%d: Expected numeric constant, not `%s'.\n",
1334 translate_filename
, line_count
, start
);
1336 } else if (num
< 0 || num
> upb
) {
1337 fprintf (stderr
, "%s:%d: Destination charcode %d <0 or >%d.\n",
1338 translate_filename
, line_count
, num
, upb
);
1345 /* Update the xchr, xord, and xprn arrays for TeX, allowing a
1346 translation table specified at runtime via an external file.
1347 Look for the character translation file FNAME along the same path as
1348 tex.pool. If no suffix in FNAME, use .tcx (don't bother trying to
1349 support extension-less names for these files). */
1351 /* FIXME: A new format ought to be introduced for these files. */
1356 string orig_filename
;
1357 if (!find_suffix (translate_filename
)) {
1358 translate_filename
= concat (translate_filename
, ".tcx");
1360 orig_filename
= translate_filename
;
1362 = kpse_find_file (translate_filename
, kpse_web2c_format
, true);
1363 if (translate_filename
) {
1365 unsigned line_count
= 0;
1366 FILE *translate_file
= xfopen (translate_filename
, FOPEN_R_MODE
);
1367 while ((line
= read_line (translate_file
))) {
1370 string comment_loc
= strchr (line
, '%');
1376 first
= tcx_get_num (255, line_count
, line
, &start2
);
1382 second
= tcx_get_num (255, line_count
, start2
, &start3
);
1384 /* I suppose we could check for nonempty junk following the
1385 "printable" code, but let's not bother. */
1388 /* If they mention a second code, make that the internal number. */
1389 xord
[first
] = second
;
1390 xchr
[second
] = first
;
1392 printable
= tcx_get_num (1, line_count
, start3
, &extra
);
1393 /* Not-a-number, may be a comment. */
1394 if (printable
== -1)
1396 /* Don't allow the 7bit ASCII set to become unprintable. */
1397 if (32 <= second
&& second
<= 126)
1400 second
= first
; /* else make internal the same as external */
1401 /* If they mention a charcode, call it printable. */
1405 xprn
[second
] = printable
;
1409 xfclose(translate_file
, translate_filename
);
1411 WARNING1 ("Could not open char translation file `%s'", orig_filename
);
1414 #endif /* !Aleph && !XeTeX */
1415 #endif /* TeX || MF [character translation] */
1417 #ifdef XeTeX /* XeTeX handles this differently, and allows odd quotes within names */
1419 normalize_quotes (const_string name
, const_string mesg
)
1422 boolean must_quote
= false;
1423 int len
= strlen(name
);
1424 /* Leave room for quotes and NUL. */
1428 for (q
= name
; *q
; q
++) {
1435 else if (*q
== '\"' || *q
== '\'') {
1437 if (quote_char
== 0)
1438 quote_char
= '\"' + '\'' - *q
;
1439 len
+= 2; /* this could sometimes add length we don't need */
1442 ret
= xmalloc(len
+ 1);
1445 if (quote_char
== 0)
1449 for (q
= name
; *q
; q
++) {
1450 if (*q
== quote_char
) {
1452 quote_char
= '\"' + '\'' - quote_char
;
1457 if (quote_char
!= 0)
1463 /* Normalize quoting of filename -- that is, only quote if there is a space,
1464 and always use the quote-name-quote style. */
1466 normalize_quotes (const_string name
, const_string mesg
)
1468 boolean quoted
= false;
1469 boolean must_quote
= (strchr(name
, ' ') != NULL
);
1470 /* Leave room for quotes and NUL. */
1471 string ret
= xmalloc(strlen(name
)+3);
1477 for (q
= name
; *q
; q
++) {
1487 fprintf(stderr
, "! Unbalanced quotes in %s %s\n", mesg
, name
);
1494 /* Getting the input filename. */
1496 get_input_file_name (void)
1498 string input_file_name
= NULL
;
1500 if (argv
[optind
] && argv
[optind
][0] != '&' && argv
[optind
][0] != '\\') {
1501 /* Not &format, not \input, so assume simple filename. */
1508 if (strlen (argv
[optind
]) > 2 && isalpha (argv
[optind
][0]) &&
1509 argv
[optind
][1] == ':' && argv
[optind
][2] == '\\') {
1511 for (pp
= argv
[optind
]; *pp
; pp
++) {
1514 else if (IS_KANJI(pp
))
1520 name
= normalize_quotes(argv
[optind
], "argument");
1522 input_file_name
= kpse_find_file(argv
[optind
], INPUT_FORMAT
, false);
1525 change_to_long_name (&input_file_name
);
1528 quoted
= (name
[0] == '"');
1530 /* Overwrite last quote and skip first quote. */
1531 name
[strlen(name
)-1] = '\0';
1534 input_file_name
= kpse_find_file(name
, INPUT_FORMAT
, false);
1537 change_to_long_name (&input_file_name
);
1540 /* Undo modifications */
1541 name
[strlen(name
)] = '"';
1546 if (!srcspecialsp
) {
1547 if (input_file_name
)
1548 name
= normalize_quotes (input_file_name
, "argument");
1551 argv
[optind
] = name
;
1553 return input_file_name
;
1556 /* Reading the options. */
1558 /* Test whether getopt found an option ``A''.
1559 Assumes the option index is in the variable `option_index', and the
1560 option table in a variable `long_options'. */
1561 #define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
1563 /* SunOS cc can't initialize automatic structs, so make this static. */
1564 static struct option long_options
[]
1565 = { { DUMP_OPTION
, 1, 0, 0 },
1567 /* FIXME: Obsolete -- for backward compatibility only. */
1568 { "efmt", 1, 0, 0 },
1570 { "help", 0, 0, 0 },
1571 { "ini", 0, &iniversion
, 1 },
1572 { "interaction", 1, 0, 0 },
1573 { "halt-on-error", 0, &haltonerrorp
, 1 },
1574 { "kpathsea-debug", 1, 0, 0 },
1575 { "progname", 1, 0, 0 },
1576 { "version", 0, 0, 0 },
1577 { "recorder", 0, &recorder_enabled
, 1 },
1580 { "ipc", 0, &ipcon
, 1 },
1581 { "ipc-start", 0, &ipcon
, 2 },
1584 { "mltex", 0, &mltexp
, 1 },
1585 #if !defined(XeTeX) && !IS_pTeX
1586 { "enc", 0, &enctexp
, 1 },
1590 { "etex", 0, &etexp
, 1 },
1592 { "output-comment", 1, 0, 0 },
1594 { "draftmode", 0, 0, 0 },
1595 { "output-format", 1, 0, 0 },
1597 { "shell-escape", 0, &shellenabledp
, 1 },
1598 { "no-shell-escape", 0, &shellenabledp
, -1 },
1599 { "enable-write18", 0, &shellenabledp
, 1 },
1600 { "disable-write18", 0, &shellenabledp
, -1 },
1601 { "shell-restricted", 0, 0, 0 },
1602 { "debug-format", 0, &debugformatfile
, 1 },
1603 { "src-specials", 2, 0, 0 },
1604 #if defined(__SyncTeX__)
1605 /* Synchronization: just like "interaction" above */
1606 { "synctex", 1, 0, 0 },
1609 #if defined (TeX) || defined (MF)
1610 { "file-line-error-style", 0, &filelineerrorstylep
, 1 },
1611 { "no-file-line-error-style", 0, &filelineerrorstylep
, -1 },
1612 /* Shorter option names for the above. */
1613 { "file-line-error", 0, &filelineerrorstylep
, 1 },
1614 { "no-file-line-error", 0, &filelineerrorstylep
, -1 },
1615 { "jobname", 1, 0, 0 },
1616 { "output-directory", 1, 0, 0 },
1617 { "parse-first-line", 0, &parsefirstlinep
, 1 },
1618 { "no-parse-first-line", 0, &parsefirstlinep
, -1 },
1620 { "translate-file", 1, 0, 0 },
1621 { "default-translate-file", 1, 0, 0 },
1622 { "8bit", 0, &eightbitp
, 1 },
1625 { "no-pdf", 0, &nopdfoutput
, 1 },
1626 { "output-driver", 1, 0, 0 },
1627 { "papersize", 1, 0, 0 },
1629 { "mktex", 1, 0, 0 },
1630 { "no-mktex", 1, 0, 0 },
1631 #endif /* TeX or MF */
1634 { "sjis-terminal", 0, &sjisterminal
, 1 },
1635 { "guess-input-enc", 0, &infile_enc_auto
, 1 },
1636 { "no-guess-input-enc", 0, &infile_enc_auto
, 0 },
1638 { "kanji", 1, 0, 0 },
1639 { "kanji-internal", 1, 0, 0 },
1640 #endif /* IS_pTeX */
1644 parse_options (int argc
, string
*argv
)
1646 int g
; /* `getopt' return code. */
1650 g
= getopt_long_only (argc
, argv
, "+", long_options
, &option_index
);
1652 if (g
== -1) /* End of arguments, exit the loop. */
1655 if (g
== '?') { /* Unknown option. */
1656 /* FIXME: usage (argv[0]); replaced by continue. */
1660 assert (g
== 0); /* We have no short option names. */
1662 if (ARGUMENT_IS ("kpathsea-debug")) {
1663 kpathsea_debug
|= atoi (optarg
);
1666 } else if (ARGUMENT_IS ("papersize")) {
1668 } else if (ARGUMENT_IS ("output-driver")) {
1669 outputdriver
= optarg
;
1672 } else if (ARGUMENT_IS ("progname")) {
1673 user_progname
= optarg
;
1675 } else if (ARGUMENT_IS ("jobname")) {
1677 c_job_name
= optarg
;
1679 c_job_name
= normalize_quotes (optarg
, "jobname");
1682 } else if (ARGUMENT_IS (DUMP_OPTION
)) {
1687 /* FIXME: Obsolete -- for backward compatibility only. */
1688 } else if (ARGUMENT_IS ("efmt")) {
1693 } else if (ARGUMENT_IS ("output-directory")) {
1694 output_directory
= optarg
;
1697 } else if (ARGUMENT_IS ("output-comment")) {
1698 unsigned len
= strlen (optarg
);
1700 outputcomment
= optarg
;
1702 WARNING2 ("Comment truncated to 255 characters from %d. (%s)",
1704 outputcomment
= xmalloc (256);
1705 strncpy (outputcomment
, optarg
, 255);
1706 outputcomment
[255] = 0;
1710 } else if (ARGUMENT_IS ("ipc-start")) {
1712 /* Try to start up the other end if it's not already. */
1713 if (!ipc_is_open ()) {
1715 if (_spawnlp (_P_NOWAIT
, IPC_SERVER_CMD
, IPC_SERVER_CMD
, NULL
) != -1) {
1717 if (system (IPC_SERVER_CMD
) == 0) {
1720 for (i
= 0; i
< 20 && !ipc_is_open (); i
++) {
1722 Sleep (100); /* 2000ms is too long for a simple w32 example */
1732 } else if (ARGUMENT_IS ("shell-restricted")) {
1734 restrictedshell
= 1;
1736 } else if (ARGUMENT_IS ("src-specials")) {
1737 last_source_name
= xstrdup("");
1738 /* Option `--src" without any value means `auto' mode. */
1739 if (optarg
== NULL
) {
1740 insertsrcspecialeverypar
= true;
1741 insertsrcspecialauto
= true;
1742 srcspecialsoption
= true;
1743 srcspecialsp
= true;
1745 parse_src_specials_option(optarg
);
1749 } else if (ARGUMENT_IS ("output-format")) {
1750 pdfoutputoption
= 1;
1751 if (strcmp(optarg
, "dvi") == 0) {
1753 } else if (strcmp(optarg
, "pdf") == 0) {
1756 WARNING1 ("Ignoring unknown value `%s' for --output-format", optarg
);
1757 pdfoutputoption
= 0;
1759 } else if (ARGUMENT_IS ("draftmode")) {
1760 pdfdraftmodeoption
= 1;
1761 pdfdraftmodevalue
= 1;
1763 #if defined (TeX) || defined (MF)
1765 } else if (ARGUMENT_IS ("translate-file")) {
1766 translate_filename
= optarg
;
1767 } else if (ARGUMENT_IS ("default-translate-file")) {
1768 default_translate_filename
= optarg
;
1770 } else if (ARGUMENT_IS ("mktex")) {
1771 kpse_maketex_option (optarg
, true);
1772 } else if (ARGUMENT_IS ("no-mktex")) {
1773 kpse_maketex_option (optarg
, false);
1774 #endif /* TeX or MF */
1775 } else if (ARGUMENT_IS ("interaction")) {
1776 /* These numbers match @d's in *.ch */
1777 if (STREQ (optarg
, "batchmode")) {
1778 interactionoption
= 0;
1779 } else if (STREQ (optarg
, "nonstopmode")) {
1780 interactionoption
= 1;
1781 } else if (STREQ (optarg
, "scrollmode")) {
1782 interactionoption
= 2;
1783 } else if (STREQ (optarg
, "errorstopmode")) {
1784 interactionoption
= 3;
1786 WARNING1 ("Ignoring unknown argument `%s' to --interaction", optarg
);
1789 } else if (ARGUMENT_IS ("kanji")) {
1790 if (!set_enc_string (optarg
, NULL
)) {
1791 WARNING1 ("Ignoring unknown argument `%s' to --kanji", optarg
);
1793 } else if (ARGUMENT_IS ("kanji-internal")) {
1794 if (!set_enc_string (NULL
, optarg
)) {
1795 WARNING1 ("Ignoring unknown argument `%s' to --kanji-internal", optarg
);
1799 } else if (ARGUMENT_IS ("help")) {
1800 usagehelp (PROGRAM_HELP
, BUG_ADDRESS
);
1802 #if defined(__SyncTeX__)
1803 } else if (ARGUMENT_IS ("synctex")) {
1804 /* Synchronize TeXnology: catching the command line option as a long */
1805 synctexoption
= (int) strtol(optarg
, NULL
, 0);
1808 } else if (ARGUMENT_IS ("version")) {
1810 #if defined (pdfTeX) || defined(XeTeX)
1811 initversionstring(&versions
);
1815 printversionandexit (BANNER
, COPYRIGHT_HOLDER
, AUTHOR
, versions
);
1817 } /* Else it was a flag; getopt has already done the assignment. */
1823 parse_src_specials_option (const_string opt_list
)
1825 char * toklist
= xstrdup(opt_list
);
1827 insertsrcspecialauto
= false;
1828 tok
= strtok (toklist
, ", ");
1830 if (strcmp (tok
, "everypar") == 0
1831 || strcmp (tok
, "par") == 0
1832 || strcmp (tok
, "auto") == 0) {
1833 insertsrcspecialauto
= true;
1834 insertsrcspecialeverypar
= true;
1835 } else if (strcmp (tok
, "everyparend") == 0
1836 || strcmp (tok
, "parend") == 0)
1837 insertsrcspecialeveryparend
= true;
1838 else if (strcmp (tok
, "everycr") == 0
1839 || strcmp (tok
, "cr") == 0)
1840 insertsrcspecialeverycr
= true;
1841 else if (strcmp (tok
, "everymath") == 0
1842 || strcmp (tok
, "math") == 0)
1843 insertsrcspecialeverymath
= true;
1844 else if (strcmp (tok
, "everyhbox") == 0
1845 || strcmp (tok
, "hbox") == 0)
1846 insertsrcspecialeveryhbox
= true;
1847 else if (strcmp (tok
, "everyvbox") == 0
1848 || strcmp (tok
, "vbox") == 0)
1849 insertsrcspecialeveryvbox
= true;
1850 else if (strcmp (tok
, "everydisplay") == 0
1851 || strcmp (tok
, "display") == 0)
1852 insertsrcspecialeverydisplay
= true;
1853 else if (strcmp (tok
, "none") == 0) {
1854 /* This one allows to reset an option that could appear in texmf.cnf */
1855 insertsrcspecialauto
= insertsrcspecialeverypar
=
1856 insertsrcspecialeveryparend
= insertsrcspecialeverycr
=
1857 insertsrcspecialeverymath
= insertsrcspecialeveryhbox
=
1858 insertsrcspecialeveryvbox
= insertsrcspecialeverydisplay
= false;
1860 WARNING1 ("Ignoring unknown argument `%s' to --src-specials", tok
);
1862 tok
= strtok(0, ", ");
1865 srcspecialsp
=insertsrcspecialauto
| insertsrcspecialeverypar
|
1866 insertsrcspecialeveryparend
| insertsrcspecialeverycr
|
1867 insertsrcspecialeverymath
| insertsrcspecialeveryhbox
|
1868 insertsrcspecialeveryvbox
| insertsrcspecialeverydisplay
;
1869 srcspecialsoption
= true;
1873 /* If the first thing on the command line (we use the globals `argv' and
1874 `optind') is a normal filename (i.e., does not start with `&' or
1875 `\'), and if we can open it, and if its first line is %&FORMAT, and
1876 FORMAT is a readable dump file, then set DUMP_VAR to FORMAT.
1877 Also call kpse_reset_program_name to ensure the correct paths for the
1880 parse_first_line (const_string filename
)
1882 FILE *f
= filename
? fopen (filename
, FOPEN_R_MODE
) : NULL
;
1884 string first_line
= read_line (f
);
1885 xfclose (f
, filename
);
1887 /* We deal with the general format "%&fmt --translate-file=tcx" */
1888 /* The idea of using this format came from Wlodzimierz Bzyl
1889 <matwb@monika.univ.gda.pl> */
1890 if (first_line
&& first_line
[0] == '%' && first_line
[1] == '&') {
1891 /* Parse the first line into at most three space-separated parts. */
1897 for (s
= first_line
+2; ISBLANK(*s
); ++s
)
1900 while (*s
&& npart
!= 3) {
1902 while (*s
&& *s
!= ' ') s
++;
1903 while (*s
== ' ') *s
++ = '\0';
1907 /* Look at what we've got. Very crude! */
1908 if (*parse
&& **parse
!= '-') {
1911 /* format already determined, do nothing. */
1913 string f_name
= concat (part
[0], DUMP_EXT
);
1914 string d_name
= kpse_find_file (f_name
, DUMP_FORMAT
, false);
1915 if (d_name
&& kpse_readable_file (d_name
)) {
1916 dump_name
= xstrdup (part
[0]);
1917 kpse_reset_program_name (dump_name
);
1918 /* Tell TeX/MF/MP we have a %&name line... */
1925 /* The tcx stuff, if any. Should we support the -translate-file
1926 form as well as --translate-file? */
1929 if (translate_filename
) {
1930 /* TCX file already set, do nothing. */
1931 } else if (STREQ (*parse
, "--translate-file")) {
1933 } else if (STREQ (*parse
, "-translate-file")) {
1935 } else if (STRNEQ (*parse
, "--translate-file=", 17)) {
1937 } else if (STRNEQ (*parse
, "-translate-file=", 16)) {
1940 /* Just set the name, no sanity checks here. */
1941 /* FIXME: remove trailing spaces. */
1943 translate_filename
= xstrdup(s
);
1956 /* The code that implements popen() needs an array for tracking
1957 possible pipe file pointers, because these need to be
1958 closed using pclose().
1963 #define NUM_PIPES 16
1965 static FILE *pipes
[NUM_PIPES
];
1968 open_in_or_pipe (FILE **f_ptr
, int filefmt
, const_string fopen_mode
)
1970 string fname
= NULL
;
1971 int i
; /* iterator */
1973 /* opening a read pipe is straightforward, only have to
1974 skip past the pipe symbol in the file name. filename
1975 quoting is assumed to happen elsewhere (it does :-)) */
1977 if (shellenabledp
&& *(nameoffile
+1) == '|') {
1978 /* the user requested a pipe */
1980 fname
= xmalloc(strlen((const_string
)(nameoffile
+1))+1);
1981 strcpy(fname
,(const_string
)(nameoffile
+1));
1982 recorder_record_input (fname
+ 1);
1983 *f_ptr
= runpopen(fname
+1,"r");
1985 for (i
=0; i
<NUM_PIPES
; i
++) {
1986 if (pipes
[i
]==NULL
) {
1992 setvbuf (*f_ptr
,NULL
,_IONBF
,0);
1997 return *f_ptr
!= NULL
;
2000 return open_input(f_ptr
,filefmt
,fopen_mode
) ;
2005 u_open_in_or_pipe(unicodefile
* f
, integer filefmt
, const_string fopen_mode
, integer mode
, integer encodingData
)
2007 string fname
= NULL
;
2008 int i
; /* iterator */
2010 /* opening a read pipe is straightforward, only have to
2011 skip past the pipe symbol in the file name. filename
2012 quoting is assumed to happen elsewhere (it does :-)) */
2014 if (shellenabledp
&& *(nameoffile
+1) == '|') {
2015 /* the user requested a pipe */
2016 *f
= malloc(sizeof(UFILE
));
2017 (*f
)->encodingMode
= (mode
== AUTO
) ? UTF8
: mode
;
2018 (*f
)->conversionData
= 0;
2019 (*f
)->savedChar
= -1;
2020 (*f
)->skipNextLF
= 0;
2022 fname
= xmalloc(strlen((const_string
)(nameoffile
+1))+1);
2023 strcpy(fname
,(const_string
)(nameoffile
+1));
2024 recorder_record_input (fname
+ 1);
2025 (*f
)->f
= runpopen(fname
+1,"r");
2027 for (i
=0; i
<NUM_PIPES
; i
++) {
2028 if (pipes
[i
]==NULL
) {
2034 setvbuf ((*f
)->f
,NULL
,_IONBF
,0);
2039 return (*f
)->f
!= NULL
;
2042 return u_open_in(f
, filefmt
, fopen_mode
, mode
, encodingData
);
2047 open_out_or_pipe (FILE **f_ptr
, const_string fopen_mode
)
2050 int i
; /* iterator */
2052 /* opening a write pipe takes a little bit more work, because TeX
2053 will perhaps have appended ".tex". To avoid user confusion as
2054 much as possible, this extension is stripped only when the command
2055 is a bare word. Some small string trickery is needed to make
2056 sure the correct number of bytes is free()-d afterwards */
2058 if (shellenabledp
&& *(nameoffile
+1) == '|') {
2059 /* the user requested a pipe */
2060 fname
= xmalloc(strlen((const_string
)(nameoffile
+1))+1);
2061 strcpy(fname
,(const_string
)(nameoffile
+1));
2062 if (strchr (fname
,' ')==NULL
&& strchr(fname
,'>')==NULL
) {
2063 /* mp and mf currently do not use this code, but it
2064 is better to be prepared */
2065 if (STREQ((fname
+strlen(fname
)-4),".tex"))
2066 *(fname
+strlen(fname
)-4) = 0;
2067 *f_ptr
= runpopen(fname
+1,"w");
2068 *(fname
+strlen(fname
)) = '.';
2070 *f_ptr
= runpopen(fname
+1,"w");
2072 recorder_record_output (fname
+ 1);
2075 for (i
=0; i
<NUM_PIPES
; i
++) {
2076 if (pipes
[i
]==NULL
) {
2083 setvbuf(*f_ptr
,NULL
,_IONBF
,0);
2085 return *f_ptr
!= NULL
;
2088 return open_output(f_ptr
,fopen_mode
);
2093 close_file_or_pipe (FILE *f
)
2095 int i
; /* iterator */
2097 if (shellenabledp
) {
2098 /* if this file was a pipe, pclose() it and return */
2099 for (i
=0; i
<NUM_PIPES
; i
++) {
2100 if (pipes
[i
] == f
) {
2114 #endif /* ENABLE_PIPES */
2116 /* All our interrupt handler has to do is set TeX's or Metafont's global
2117 variable `interrupt'; then they will do everything needed. */
2119 /* Win32 doesn't set SIGINT ... */
2121 catch_interrupt (DWORD arg
)
2125 case CTRL_BREAK_EVENT
:
2129 /* No need to set interrupt as we are exiting anyway */
2133 #else /* not WIN32 */
2135 catch_interrupt (int arg
)
2139 (void) signal (SIGINT
, SIG_ACK
);
2141 (void) signal (SIGINT
, catch_interrupt
);
2142 #endif /* not OS2 */
2144 #endif /* not WIN32 */
2146 /* Besides getting the date and time here, we also set up the interrupt
2147 handler, for no particularly good reason. It's just that since the
2148 `fix_date_and_time' routine is called early on (section 1337 in TeX,
2149 ``Get the first line of input and prepare to start''), this is as
2150 good a place as any. */
2153 get_date_and_time (integer
*minutes
, integer
*day
,
2154 integer
*month
, integer
*year
)
2156 time_t myclock
= time ((time_t *) 0);
2157 struct tm
*tmptr
= localtime (&myclock
);
2159 *minutes
= tmptr
->tm_hour
* 60 + tmptr
->tm_min
;
2160 *day
= tmptr
->tm_mday
;
2161 *month
= tmptr
->tm_mon
+ 1;
2162 *year
= tmptr
->tm_year
+ 1900;
2166 /* Under SunOS 4.1.x, the default action after return from the
2167 signal handler is to restart the I/O if nothing has been
2168 transferred. The effect on TeX is that interrupts are ignored if
2169 we are waiting for input. The following tells the system to
2170 return EINTR from read() in this case. From ken@cs.toronto.edu. */
2172 struct sigaction a
, oa
;
2174 a
.sa_handler
= catch_interrupt
;
2175 sigemptyset (&a
.sa_mask
);
2176 sigaddset (&a
.sa_mask
, SIGINT
);
2177 a
.sa_flags
= SA_INTERRUPT
;
2178 sigaction (SIGINT
, &a
, &oa
);
2179 if (oa
.sa_handler
!= SIG_DFL
)
2180 sigaction (SIGINT
, &oa
, (struct sigaction
*) 0);
2181 #else /* no SA_INTERRUPT */
2183 SetConsoleCtrlHandler(catch_interrupt
, TRUE
);
2184 #else /* not WIN32 */
2185 RETSIGTYPE (*old_handler
)(int);
2187 old_handler
= signal (SIGINT
, catch_interrupt
);
2188 if (old_handler
!= SIG_DFL
)
2189 signal (SIGINT
, old_handler
);
2190 #endif /* not WIN32 */
2191 #endif /* no SA_INTERRUPT */
2197 Getting a high resolution time.
2200 get_seconds_and_micros (integer
*seconds
, integer
*micros
)
2202 #if defined (HAVE_GETTIMEOFDAY)
2204 gettimeofday(&tv
, NULL
);
2205 *seconds
= tv
.tv_sec
;
2206 *micros
= tv
.tv_usec
;
2207 #elif defined (HAVE_FTIME)
2211 *micros
= tb
.millitm
*1000;
2213 time_t myclock
= time((time_t*)NULL
);
2220 /* Read a line of input as efficiently as possible while still looking
2221 like Pascal. We set `last' to `first' and return `false' if we get
2222 to eof. Otherwise, we return `true' and set last = first +
2223 length(line except trailing whitespace). */
2225 #ifndef XeTeX /* for XeTeX, we have a replacement function in XeTeX_ext.c */
2227 input_line (FILE *f
)
2231 /* Recognize either LF or CR as a line terminator. */
2233 last
= input_line2(f
, (unsigned char *)buffer
, first
, bufsize
, &i
);
2236 if (f
!= Poptr
&& fileno (f
) != fileno (stdin
)) {
2237 long position
= ftell (f
);
2239 if (position
== 0L) { /* Detect and skip Byte order marks. */
2242 if (k1
!= 0xff && k1
!= 0xfe && k1
!= 0xef)
2247 if (k2
!= 0xff && k2
!= 0xfe && k2
!= 0xbb)
2249 else if ((k1
== 0xff && k2
== 0xfe) || /* UTF-16(LE) */
2250 (k1
== 0xfe && k2
== 0xff)) /* UTF-16(BE) */
2255 if (k1
== 0xef && k2
== 0xbb && k3
== 0xbf) /* UTF-8 */
2265 while (last
< bufsize
&& (i
= getc (f
)) != EOF
&& i
!= '\n' && i
!= '\r')
2269 if (i
== EOF
&& errno
!= EINTR
&& last
== first
)
2272 /* We didn't get the whole line because our buffer was too small. */
2273 if (i
!= EOF
&& i
!= '\n' && i
!= '\r') {
2274 fprintf (stderr
, "! Unable to read an entire line---bufsize=%u.\n",
2275 (unsigned) bufsize
);
2276 fputs ("Please increase buf_size in texmf.cnf.\n", stderr
);
2281 if (last
>= maxbufstack
)
2284 /* If next char is LF of a CRLF, read it. */
2286 while ((i
= getc (f
)) == EOF
&& errno
== EINTR
)
2292 /* Trim trailing whitespace. */
2293 while (last
> first
&& ISBLANK (buffer
[last
- 1]))
2296 /* Don't bother using xord if we don't need to. */
2298 for (i
= first
; i
<= last
; i
++)
2299 buffer
[i
] = xord
[buffer
[i
]];
2303 for (i
= last
+1; (i
< last
+ 5 && i
< bufsize
) ; i
++)
2311 /* This string specifies what the `e' option does in response to an
2313 static const_string edit_value
= EDITOR
;
2315 /* This procedure originally due to sjc@s1-c. TeX & Metafont call it when
2316 the user types `e' in response to an error, invoking a text editor on
2317 the erroneous source file. FNSTART is how far into FILENAME the
2318 actual filename starts; FNLENGTH is how long the filename is. */
2321 calledit (packedASCIIcode
*filename
,
2322 poolpointer fnstart
,
2326 char *temp
, *command
, *fullcmd
;
2328 int sdone
, ddone
, i
;
2331 char *fp
, *ffp
, *env
, editorname
[256], buffer
[256];
2337 filename
+= fnstart
;
2339 /* Close any open input files, since we're going to kill the job. */
2340 for (i
= 1; i
<= inopen
; i
++)
2342 xfclose (inputfile
[i
]->f
, "inputfile");
2344 xfclose (inputfile
[i
], "inputfile");
2347 /* Replace the default with the value of the appropriate environment
2348 variable or config file value, if it's set. */
2349 temp
= kpse_var_value (edit_var
);
2353 /* Construct the command string. The `11' is the maximum length an
2354 integer might be. */
2355 command
= xmalloc (strlen (edit_value
) + fnlength
+ 11);
2357 /* So we can construct it as we go. */
2362 if ((isalpha(*edit_value
) && *(edit_value
+ 1) == ':'
2363 && IS_DIR_SEP (*(edit_value
+ 2)))
2364 || (*edit_value
== '"' && isalpha(*(edit_value
+ 1))
2365 && *(edit_value
+ 2) == ':'
2366 && IS_DIR_SEP (*(edit_value
+ 3)))
2371 while ((c
= *edit_value
++) != 0)
2375 switch (c
= *edit_value
++)
2379 FATAL ("call_edit: `%%d' appears twice in editor command");
2380 sprintf (temp
, "%ld", (long int)linenumber
);
2381 while (*temp
!= '\0')
2388 FATAL ("call_edit: `%%s' appears twice in editor command");
2389 for (i
=0; i
< fnlength
; i
++)
2390 *temp
++ = Xchr (filename
[i
]);
2396 /* Back up to the null to force termination. */
2410 else { if(Isspace(c
) && cnt
== 0) {
2415 } else if(!Isspace(c
) && cnt
== 0) {
2430 if (dontchange
== 0) {
2431 if(editorname
[0] == '.' ||
2432 editorname
[0] == '/' ||
2433 editorname
[0] == '\\') {
2434 fprintf(stderr
, "%s is not allowed to execute.\n", editorname
);
2437 env
= (char *)getenv("PATH");
2438 if(SearchPath(env
, editorname
, ".exe", 256, buffer
, &ffp
)==0) {
2439 if(SearchPath(env
, editorname
, ".bat", 256, buffer
, &ffp
)==0) {
2440 fprintf(stderr
, "I cannot find %s in the PATH.\n", editorname
);
2444 fullcmd
= (char *)xmalloc(strlen(buffer
)+strlen(command
)+5);
2445 strcpy(fullcmd
, "\"");
2446 strcat(fullcmd
, buffer
);
2447 strcat(fullcmd
, "\"");
2448 strcat(fullcmd
, command
);
2453 /* Execute the command. */
2454 if (system (fullcmd
) != 0)
2455 fprintf (stderr
, "! Trouble executing `%s'.\n", command
);
2457 /* Quit, since we found an error. */
2461 /* Read and write dump files. As distributed, these files are
2462 architecture dependent; specifically, BigEndian and LittleEndian
2463 architectures produce different files. These routines always output
2464 BigEndian files. This still does not guarantee them to be
2465 architecture-independent, because it is possible to make a format
2466 that dumps a glue ratio, i.e., a floating-point number. Fortunately,
2467 none of the standard formats do that. */
2469 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE) /* this fn */
2471 /* This macro is always invoked as a statement. It assumes a variable
2474 #define SWAP(x, y) temp = (x); (x) = (y); (y) = temp
2477 /* Make the NITEMS items pointed at by P, each of size SIZE, be the
2478 opposite-endianness of whatever they are now. */
2481 swap_items (char *p
, int nitems
, int size
)
2485 /* Since `size' does not change, we can write a while loop for each
2486 case, and avoid testing `size' for each time. */
2489 /* 16-byte items happen on the DEC Alpha machine when we are not
2490 doing sharable memory dumps. */
2535 /* Nothing to do. */
2539 FATAL1 ("Can't swap a %d-byte item for (un)dumping", size
);
2542 #endif /* not WORDS_BIGENDIAN and not NO_DUMP_SHARE */
2545 /* Here we write NITEMS items, each item being ITEM_SIZE bytes long.
2546 The pointer to the stuff to write is P, and we write to the file
2551 do_dump (char *p
, int item_size
, int nitems
, gzFile out_file
)
2553 do_dump (char *p
, int item_size
, int nitems
, FILE *out_file
)
2556 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2557 swap_items (p
, nitems
, item_size
);
2561 if (gzwrite (out_file
, p
, item_size
* nitems
) != item_size
* nitems
)
2563 if (fwrite (p
, item_size
, nitems
, out_file
) != nitems
)
2566 fprintf (stderr
, "! Could not write %d %d-byte item(s) to %s.\n",
2567 nitems
, item_size
, nameoffile
+1);
2571 /* Have to restore the old contents of memory, since some of it might
2573 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2574 swap_items (p
, nitems
, item_size
);
2579 /* Here is the dual of the writing routine. */
2583 do_undump (char *p
, int item_size
, int nitems
, gzFile in_file
)
2585 do_undump (char *p
, int item_size
, int nitems
, FILE *in_file
)
2589 if (gzread (in_file
, p
, item_size
* nitems
) != item_size
* nitems
)
2591 if (fread (p
, item_size
, nitems
, in_file
) != (size_t) nitems
)
2593 FATAL3 ("Could not undump %d %d-byte item(s) from %s",
2594 nitems
, item_size
, nameoffile
+1);
2596 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2597 swap_items (p
, nitems
, item_size
);
2601 /* FIXME -- some (most?) of this can/should be moved to the Pascal/WEB side. */
2602 #if defined(TeX) || defined(MF)
2603 #if !defined(pdfTeX)
2605 checkpoolpointer (poolpointer poolptr
, size_t len
)
2607 if (poolptr
+ len
>= poolsize
) {
2608 fprintf (stderr
, "\nstring pool overflow [%i bytes]\n",
2609 (int)poolsize
); /* fixme */
2614 #ifndef XeTeX /* XeTeX uses this from XeTeX_ext.c */
2618 maketexstring(const_string s
)
2623 const unsigned char *cp
= (const unsigned char *)s
;
2626 if (s
== NULL
|| *s
== 0)
2627 return getnullstr();
2632 checkpoolpointer (poolptr
, len
); /* in the XeTeX case, this may be more than enough */
2634 while ((rval
= *(cp
++)) != 0) {
2635 UInt16 extraBytes
= bytesFromUTF8
[rval
];
2636 switch (extraBytes
) { /* note: code falls through cases! */
2637 case 5: rval
<<= 6; if (*cp
) rval
+= *(cp
++);
2638 case 4: rval
<<= 6; if (*cp
) rval
+= *(cp
++);
2639 case 3: rval
<<= 6; if (*cp
) rval
+= *(cp
++);
2640 case 2: rval
<<= 6; if (*cp
) rval
+= *(cp
++);
2641 case 1: rval
<<= 6; if (*cp
) rval
+= *(cp
++);
2644 rval
-= offsetsFromUTF8
[extraBytes
];
2645 if (rval
> 0xffff) {
2647 strpool
[poolptr
++] = 0xd800 + rval
/ 0x0400;
2648 strpool
[poolptr
++] = 0xdc00 + rval
% 0x0400;
2651 strpool
[poolptr
++] = rval
;
2655 strpool
[poolptr
++] = *s
++;
2656 #endif /* ! XeTeX */
2658 return makestring();
2660 #endif /* !pdfTeX */
2663 makefullnamestring(void)
2665 return maketexstring(fullnameoffile
);
2668 /* Get the job name to be used, which may have been set from the
2671 getjobname(strnumber name
)
2673 strnumber ret
= name
;
2674 if (c_job_name
!= NULL
)
2675 ret
= maketexstring(c_job_name
);
2682 compare_paths (const_string p1
, const_string p2
)
2686 #ifdef MONOCASE_FILENAMES
2687 (((ret
= (toupper(*p1
) - toupper(*p2
))) == 0) && (*p2
!= 0))
2689 (((ret
= (*p1
- *p2
)) == 0) && (*p2
!= 0))
2691 || (IS_DIR_SEP(*p1
) && IS_DIR_SEP(*p2
))) {
2694 ret
= (ret
< 0 ? -1 : (ret
> 0 ? 1 : 0));
2698 #ifdef XeTeX /* the string pool is UTF-16 but we want a UTF-8 string */
2701 gettexstring (strnumber s
)
2703 unsigned bytesToWrite
= 0;
2704 poolpointer len
, i
, j
;
2706 len
= strstart
[s
+ 1 - 65536L] - strstart
[s
- 65536L];
2707 name
= xmalloc(len
* 3 + 1); /* max UTF16->UTF8 expansion
2708 (code units, not bytes) */
2709 for (i
= 0, j
= 0; i
< len
; i
++) {
2710 unsigned c
= strpool
[i
+ strstart
[s
- 65536L]];
2711 if (c
>= 0xD800 && c
<= 0xDBFF) {
2712 unsigned lo
= strpool
[++i
+ strstart
[s
- 65536L]];
2713 if (lo
>= 0xDC00 && lo
<= 0xDFFF)
2714 c
= (c
- 0xD800) * 0x0400 + lo
- 0xDC00;
2722 else if (c
< 0x10000)
2724 else if (c
< 0x110000)
2732 switch (bytesToWrite
) { /* note: everything falls through. */
2733 case 4: name
[--j
] = ((c
| 0x80) & 0xBF); c
>>= 6;
2734 case 3: name
[--j
] = ((c
| 0x80) & 0xBF); c
>>= 6;
2735 case 2: name
[--j
] = ((c
| 0x80) & 0xBF); c
>>= 6;
2736 case 1: name
[--j
] = (c
| firstByteMark
[bytesToWrite
]);
2747 gettexstring (strnumber s
)
2752 len
= strstart
[s
+ 1] - strstart
[s
];
2754 len
= strstartar
[s
+ 1 - 65536L] - strstartar
[s
- 65536L];
2756 name
= (string
)xmalloc (len
+ 1);
2758 strncpy (name
, (string
)&strpool
[strstart
[s
]], len
);
2762 /* Don't use strncpy. The strpool is not made up of chars. */
2763 for (i
=0; i
<len
; i
++) name
[i
] = strpool
[i
+strstartar
[s
- 65536L]];
2770 #endif /* not XeTeX */
2773 isnewsource (strnumber srcfilename
, int lineno
)
2775 char *name
= gettexstring(srcfilename
);
2776 return (compare_paths(name
, last_source_name
) != 0 || lineno
!= last_lineno
);
2780 remembersourceinfo (strnumber srcfilename
, int lineno
)
2782 if (last_source_name
)
2783 free(last_source_name
);
2784 last_source_name
= gettexstring(srcfilename
);
2785 last_lineno
= lineno
;
2789 makesrcspecial (strnumber srcfilename
, int lineno
)
2791 poolpointer oldpoolptr
= poolptr
;
2792 char *filename
= gettexstring(srcfilename
);
2793 /* FIXME: Magic number. */
2797 /* Always put a space after the number, which makes things easier
2800 sprintf (buf
, "src:%d ", lineno
);
2802 if (poolptr
+ strlen(buf
) + strlen(filename
) >= (size_t)poolsize
) {
2803 fprintf (stderr
, "\nstring pool overflow\n"); /* fixme */
2808 strpool
[poolptr
++] = *s
++;
2812 strpool
[poolptr
++] = *s
++;
2814 return (oldpoolptr
);
2817 /* pdfTeX routines also used for e-pTeX and e-upTeX */
2818 #if defined (pdfTeX) || defined (epTeX) || defined (eupTeX)
2820 #include <kpathsea/c-stat.h>
2822 #define check_nprintf(size_get, size_want) \
2823 if ((unsigned)(size_get) >= (unsigned)(size_want)) \
2824 pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
2825 # define check_buf(size, buf_size) \
2826 if ((unsigned)(size) > (unsigned)(buf_size)) \
2827 pdftex_fail("buffer overflow at file %s, line %d", __FILE__, __LINE__ )
2828 # define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0)
2829 # define MAX_CSTRING_LEN 1024 * 1024
2831 #if !defined (pdfTeX)
2832 # define PRINTF_BUF_SIZE 1024
2833 static char print_buf
[PRINTF_BUF_SIZE
];
2835 /* Helper for pdftex_fail. */
2836 static void safe_print(const char *str
)
2839 for (c
= str
; *c
; ++c
)
2842 /* pdftex_fail may be called when a buffer overflow has happened/is
2843 happening, therefore may not call mktexstring. However, with the
2844 current implementation it appears that error messages are misleading,
2845 possibly because pool overflows are detected too late.
2847 The output format of this fuction must be the same as pdf_error in
2849 __attribute__ ((noreturn
, format(printf
, 1, 2)))
2850 void pdftex_fail(const char *fmt
, ...)
2853 va_start(args
, fmt
);
2855 safe_print("!error: ");
2856 vsnprintf(print_buf
, PRINTF_BUF_SIZE
, fmt
, args
);
2857 safe_print(print_buf
);
2860 safe_print(" ==> Fatal error occurred, output file will be damaged!");
2862 if (kpathsea_debug
) {
2863 safe_print("kpathsea_debug enabled, calling abort()...");
2870 #endif /* not pdfTeX */
2872 static time_t start_time
= 0;
2873 #define TIME_STR_SIZE 30
2874 char start_time_str
[TIME_STR_SIZE
];
2875 static char time_str
[TIME_STR_SIZE
];
2876 /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
2878 static void makepdftime(time_t t
, char *time_str
)
2883 int i
, off
, off_hours
, off_mins
;
2886 lt
= *localtime(&t
);
2887 size
= strftime(time_str
, TIME_STR_SIZE
, "D:%Y%m%d%H%M%S", <
);
2888 /* expected format: "YYYYmmddHHMMSS" */
2890 /* unexpected, contents of time_str is undefined */
2895 /* correction for seconds: %S can be in range 00..61,
2896 the PDF reference expects 00..59,
2897 therefore we map "60" and "61" to "59" */
2898 if (time_str
[14] == '6') {
2901 time_str
[16] = '\0'; /* for safety */
2904 /* get the time zone offset */
2907 /* this calculation method was found in exim's tod.c */
2908 off
= 60 * (lt
.tm_hour
- gmt
.tm_hour
) + lt
.tm_min
- gmt
.tm_min
;
2909 if (lt
.tm_year
!= gmt
.tm_year
) {
2910 off
+= (lt
.tm_year
> gmt
.tm_year
) ? 1440 : -1440;
2911 } else if (lt
.tm_yday
!= gmt
.tm_yday
) {
2912 off
+= (lt
.tm_yday
> gmt
.tm_yday
) ? 1440 : -1440;
2916 time_str
[size
++] = 'Z';
2919 off_hours
= off
/ 60;
2920 off_mins
= abs(off
- off_hours
* 60);
2921 i
= snprintf(&time_str
[size
], 9, "%+03d'%02d'", off_hours
, off_mins
);
2922 check_nprintf(i
, 9);
2926 void initstarttime(void)
2928 if (start_time
== 0) {
2929 start_time
= time((time_t *) NULL
);
2930 makepdftime(start_time
, start_time_str
);
2934 char *makecstring(integer s
)
2936 static char *cstrbuf
= NULL
;
2938 static int allocsize
;
2939 int allocgrow
, i
, l
= strstart
[s
+ 1] - strstart
[s
];
2940 check_buf(l
+ 1, MAX_CSTRING_LEN
);
2941 if (cstrbuf
== NULL
) {
2943 cstrbuf
= xmallocarray(char, allocsize
);
2944 } else if (l
+ 1 > allocsize
) {
2945 allocgrow
= allocsize
* 0.2;
2946 if (l
+ 1 - allocgrow
> allocsize
)
2948 else if (allocsize
< MAX_CSTRING_LEN
- allocgrow
)
2949 allocsize
+= allocgrow
;
2951 allocsize
= MAX_CSTRING_LEN
;
2952 cstrbuf
= xreallocarray(cstrbuf
, char, allocsize
);
2955 for (i
= 0; i
< l
; i
++)
2956 *p
++ = strpool
[i
+ strstart
[s
]];
2962 input/ouput same as makecstring:
2963 input: string number
2964 output: C string with quotes removed.
2965 That means, file names that are legal on some operation systems
2966 cannot any more be used since pdfTeX version 1.30.4.
2968 char *makecfilename(integer s
)
2970 char *name
= makecstring(s
);
2983 void getcreationdate(void)
2987 /* put creation date on top of string pool and update poolptr */
2988 len
= strlen(start_time_str
);
2990 /* In e-pTeX, "init len => call initstarttime()" (as pdftexdir/utils.c)
2991 yields unintentional output. */
2993 if ((unsigned) (poolptr
+ len
) >= (unsigned) (poolsize
)) {
2995 /* error by str_toks that calls str_room(1) */
2999 memcpy(&strpool
[poolptr
], start_time_str
, len
);
3003 void getfilemoddate(integer s
)
3005 struct stat file_data
;
3007 char *file_name
= kpse_find_tex(makecfilename(s
));
3008 if (file_name
== NULL
) {
3009 return; /* empty string */
3012 recorder_record_input(file_name
);
3013 /* get file status */
3014 if (stat(file_name
, &file_data
) == 0) {
3017 makepdftime(file_data
.st_mtime
, time_str
);
3018 len
= strlen(time_str
);
3019 if ((unsigned) (poolptr
+ len
) >= (unsigned) (poolsize
)) {
3021 /* error by str_toks that calls str_room(1) */
3023 memcpy(&strpool
[poolptr
], time_str
, len
);
3027 /* else { errno contains error code } */
3032 void getfilesize(integer s
)
3034 struct stat file_data
;
3037 char *file_name
= kpse_find_tex(makecfilename(s
));
3038 if (file_name
== NULL
) {
3039 return; /* empty string */
3042 recorder_record_input(file_name
);
3043 /* get file status */
3044 if (stat(file_name
, &file_data
) == 0) {
3048 /* st_size has type off_t */
3049 i
= snprintf(buf
, sizeof(buf
),
3050 "%lu", (long unsigned int) file_data
.st_size
);
3051 check_nprintf(i
, sizeof(buf
));
3053 if ((unsigned) (poolptr
+ len
) >= (unsigned) (poolsize
)) {
3055 /* error by str_toks that calls str_room(1) */
3057 memcpy(&strpool
[poolptr
], buf
, len
);
3061 /* else { errno contains error code } */
3066 void getfiledump(integer s
, int offset
, int length
)
3070 poolpointer data_ptr
;
3071 poolpointer data_end
;
3075 /* empty result string */
3079 if (poolptr
+ 2 * length
+ 1 >= poolsize
) {
3080 /* no place for result */
3082 /* error by str_toks that calls str_room(1) */
3086 file_name
= kpse_find_tex(makecfilename(s
));
3087 if (file_name
== NULL
) {
3088 return; /* empty string */
3091 /* read file data */
3092 f
= fopen(file_name
, FOPEN_RBIN_MODE
);
3097 recorder_record_input(file_name
);
3098 if (fseek(f
, offset
, SEEK_SET
) != 0) {
3102 /* there is enough space in the string pool, the read
3103 data are put in the upper half of the result, thus
3104 the conversion to hex can be done without overwriting
3105 unconverted bytes. */
3106 data_ptr
= poolptr
+ length
;
3107 read
= fread(&strpool
[data_ptr
], sizeof(char), length
, f
);
3110 /* convert to hex */
3111 data_end
= data_ptr
+ read
;
3112 for (; data_ptr
< data_end
; data_ptr
++) {
3113 i
= snprintf((char *) &strpool
[poolptr
], 3,
3114 "%.2X", (unsigned int) strpool
[data_ptr
]);
3115 check_nprintf(i
, 3);
3120 #endif /* e-pTeX or e-upTeX */
3123 /* Metafont/MetaPost fraction routines. Replaced either by assembler or C.
3124 The assembler syntax doesn't work on Solaris/x86. */
3126 #if defined (__sun__) || defined (__cplusplus)
3129 /* The assembler code is not PIC safe on i?86 so use C code. */
3130 #if defined (__PIC__) && defined (__i386__)
3133 #if defined(WIN32) && !defined(NO_MF_ASM) && !defined(__MINGW32__)
3134 #include "lib/mfmpw32.c"
3135 #elif defined (__i386__) && defined (__GNUC__) && !defined (NO_MF_ASM)
3136 #include "lib/mfmpi386.asm"
3138 /* Replace fixed-point fraction routines from mf.web and mp.web with
3139 Hobby's floating-point C code. */
3141 /****************************************************************
3142 Copyright 1990 - 1995 by AT&T Bell Laboratories.
3144 Permission to use, copy, modify, and distribute this software
3145 and its documentation for any purpose and without fee is hereby
3146 granted, provided that the above copyright notice appear in all
3147 copies and that both that the copyright notice and this
3148 permission notice and warranty disclaimer appear in supporting
3149 documentation, and that the names of AT&T Bell Laboratories or
3150 any of its entities not be used in advertising or publicity
3151 pertaining to distribution of the software without specific,
3152 written prior permission.
3154 AT&T disclaims all warranties with regard to this software,
3155 including all implied warranties of merchantability and fitness.
3156 In no event shall AT&T be liable for any special, indirect or
3157 consequential damages or any damages whatsoever resulting from
3158 loss of use, data or profits, whether in an action of contract,
3159 negligence or other tortious action, arising out of or in
3160 connection with the use or performance of this software.
3161 ****************************************************************/
3163 /**********************************************************
3164 The following is by John Hobby
3165 **********************************************************/
3169 /* These replacements for takefraction, makefraction, takescaled, makescaled
3170 run about 3 to 11 times faster than the standard versions on modern machines
3171 that have fast hardware for double-precision floating point. They should
3172 produce approximately correct results on all machines and agree exactly
3173 with the standard versions on machines that satisfy the following conditions:
3174 1. Doubles must have at least 46 mantissa bits; i.e., numbers expressible
3175 as n*2^k with abs(n)<2^46 should be representable.
3176 2. The following should hold for addition, subtraction, and multiplcation but
3177 not necessarily for division:
3178 A. If the true answer is between two representable numbers, the computed
3179 answer must be one of them.
3180 B. When the true answer is representable, this must be the computed result.
3181 3. Dividing one double by another should always produce a relative error of
3182 at most one part in 2^46. (This is why the mantissa requirement is
3183 46 bits instead of 45 bits.)
3184 3. In the absence of overflow, double-to-integer conversion should truncate
3185 toward zero and do this in an exact fashion.
3186 4. Integer-to-double convesion should produce exact results.
3187 5. Dividing one power of two by another should yield an exact result.
3188 6. ASCII to double conversion should be exact for integer values.
3189 7. Integer arithmetic must be done in the two's-complement system.
3191 #define ELGORDO 0x7fffffff
3192 #define TWEXP31 2147483648.0
3193 #define TWEXP28 268435456.0
3194 #define TWEXP16 65536.0
3195 #define TWEXP_16 (1.0/65536.0)
3196 #define TWEXP_28 (1.0/268435456.0)
3199 ztakefraction (integer p
, integer q
) /* Approximate p*q/2^28 */
3200 { register double d
;
3202 d
= (double)p
* (double)q
* TWEXP_28
;
3206 if (d
!=TWEXP31
|| (((p
&077777)*(q
&077777))&040000)==0)
3211 if (d
==i
&& (((p
&077777)*(q
&077777))&040000)!=0) --i
;
3215 if (d
!= -TWEXP31
|| ((-(p
&077777)*(q
&077777))&040000)==0)
3220 if (d
==i
&& ((-(p
&077777)*(q
&077777))&040000)!=0) ++i
;
3226 ztakescaled (integer p
, integer q
) /* Approximate p*q/2^16 */
3227 { register double d
;
3229 d
= (double)p
* (double)q
* TWEXP_16
;
3233 if (d
!=TWEXP31
|| (((p
&077777)*(q
&077777))&040000)==0)
3238 if (d
==i
&& (((p
&077777)*(q
&077777))&040000)!=0) --i
;
3242 if (d
!= -TWEXP31
|| ((-(p
&077777)*(q
&077777))&040000)==0)
3247 if (d
==i
&& ((-(p
&077777)*(q
&077777))&040000)!=0) ++i
;
3252 /* Note that d cannot exactly equal TWEXP31 when the overflow test is made
3253 because the exact value of p/q cannot be strictly between (2^31-1)/2^28
3254 and 8/1. No pair of integers less than 2^31 has such a ratio.
3257 zmakefraction (integer p
, integer q
) /* Approximate 2^28*p/q */
3258 { register double d
;
3261 if (q
==0) confusion(47);
3263 d
= TWEXP28
* (double)p
/(double)q
;
3266 if (d
>=TWEXP31
) {aritherror
=true; return ELGORDO
;}
3268 if (d
==i
&& ( ((q
>0 ? -q
: q
)&077777)
3269 * (((i
&037777)<<1)-1) & 04000)!=0) --i
;
3272 if (d
<= -TWEXP31
) {aritherror
=true; return -ELGORDO
;}
3274 if (d
==i
&& ( ((q
>0 ? q
: -q
)&077777)
3275 * (((i
&037777)<<1)+1) & 04000)!=0) ++i
;
3280 /* Note that d cannot exactly equal TWEXP31 when the overflow test is made
3281 because the exact value of p/q cannot be strictly between (2^31-1)/2^16
3282 and 2^15/1. No pair of integers less than 2^31 has such a ratio.
3285 zmakescaled (integer p
, integer q
) /* Approximate 2^16*p/q */
3286 { register double d
;
3289 if (q
==0) confusion(47);
3291 d
= TWEXP16
* (double)p
/(double)q
;
3294 if (d
>=TWEXP31
) {aritherror
=true; return ELGORDO
;}
3296 if (d
==i
&& ( ((q
>0 ? -q
: q
)&077777)
3297 * (((i
&037777)<<1)-1) & 04000)!=0) --i
;
3300 if (d
<= -TWEXP31
) {aritherror
=true; return -ELGORDO
;}
3302 if (d
==i
&& ( ((q
>0 ? q
: -q
)&077777)
3303 * (((i
&037777)<<1)+1) & 04000)!=0) ++i
;
3308 #endif /* not FIXPT */
3309 #endif /* not assembler */
3310 #endif /* not TeX, i.e., MF */
3313 /* On-line display routines for Metafont. Here we use a dispatch table
3314 indexed by the MFTERM or TERM environment variable to select the
3315 graphics routines appropriate to the user's terminal. stdout must be
3316 connected to a terminal for us to do any graphics. */
3332 /* Prototypes for Metafont display routines: mf_XXX_initscreen,
3333 mf_XXX_updatescreen, mf_XXX_blankrectangle, and mf_XXX_paintrow. */
3334 #include <window/mfdisplay.h>
3336 /* This variable, `mfwsw', contains the dispatch tables for each
3337 terminal. We map the Pascal calls to the routines `init_screen',
3338 `update_screen', `blank_rectangle', and `paint_row' into the
3339 appropriate entry point for the specific terminal that MF is being
3344 const char *mfwsw_type
; /* Name of terminal a la TERMCAP. */
3345 int (*mfwsw_initscreen
) (void);
3346 void (*mfwsw_updatescrn
) (void);
3347 void (*mfwsw_blankrect
) (screencol
, screencol
, screenrow
, screenrow
);
3348 void (*mfwsw_paintrow
) (screenrow
, pixelcolor
, transspec
, screencol
);
3352 { "amiterm", mf_amiga_initscreen
, mf_amiga_updatescreen
,
3353 mf_amiga_blankrectangle
, mf_amiga_paintrow
},
3356 { "epsf", mf_epsf_initscreen
, mf_epsf_updatescreen
,
3357 mf_epsf_blankrectangle
, mf_epsf_paintrow
},
3360 { "hp2627", mf_hp2627_initscreen
, mf_hp2627_updatescreen
,
3361 mf_hp2627_blankrectangle
, mf_hp2627_paintrow
},
3364 { "mftalk", mf_mftalk_initscreen
, mf_mftalk_updatescreen
,
3365 mf_mftalk_blankrectangle
, mf_mftalk_paintrow
},
3368 { "next", mf_next_initscreen
, mf_next_updatescreen
,
3369 mf_next_blankrectangle
, mf_next_paintrow
},
3372 { "regis", mf_regis_initscreen
, mf_regis_updatescreen
,
3373 mf_regis_blankrectangle
, mf_regis_paintrow
},
3376 { "sun", mf_sun_initscreen
, mf_sun_updatescreen
,
3377 mf_sun_blankrectangle
, mf_sun_paintrow
},
3380 { "tek", mf_tektronix_initscreen
, mf_tektronix_updatescreen
,
3381 mf_tektronix_blankrectangle
, mf_tektronix_paintrow
},
3384 { "uniterm", mf_uniterm_initscreen
, mf_uniterm_updatescreen
,
3385 mf_uniterm_blankrectangle
, mf_uniterm_paintrow
},
3388 { "win32term", mf_win32_initscreen
, mf_win32_updatescreen
,
3389 mf_win32_blankrectangle
, mf_win32_paintrow
},
3392 { "xterm", mf_x11_initscreen
, mf_x11_updatescreen
,
3393 mf_x11_blankrectangle
, mf_x11_paintrow
},
3396 /* Always support this. */
3397 { "trap", mf_trap_initscreen
, mf_trap_updatescreen
,
3398 mf_trap_blankrectangle
, mf_trap_paintrow
},
3400 /* Finally, we must have an entry with a terminal type of NULL. */
3401 { NULL
, NULL
, NULL
, NULL
, NULL
}
3403 }; /* End of the array initialization. */
3406 /* This is a pointer to the mfwsw[] entry that we find. */
3407 static struct mfwin_sw
*mfwp
;
3410 /* The following are routines that just jump to the correct
3411 terminal-specific graphics code. If none of the routines in the
3412 dispatch table exist, or they fail, we produce trap-compatible
3413 output, i.e., the same words and punctuation that the unchanged
3414 mf.web would produce. */
3417 /* This returns true if we can do window operations, else false. */
3423 /* If MFTERM is set, use it. */
3424 const_string tty_type
= kpse_var_value ("MFTERM");
3426 if (tty_type
== NULL
)
3429 tty_type
= "amiterm";
3430 #elif defined (WIN32)
3431 tty_type
= "win32term";
3432 #elif defined (OS2) || defined (__DJGPP__) /* not AMIGA nor WIN32 */
3433 tty_type
= "mftalk";
3434 #else /* not (OS2 or WIN32 or __DJGPP__ or AMIGA) */
3435 /* If DISPLAY is set, we are X11; otherwise, who knows. */
3436 boolean have_display
= getenv ("DISPLAY") != NULL
;
3437 tty_type
= have_display
? "xterm" : getenv ("TERM");
3439 /* If we don't know what kind of terminal this is, or if Metafont
3440 isn't being run interactively, don't do any online output. */
3441 if (tty_type
== NULL
3442 || (!STREQ (tty_type
, "trap") && !isatty (fileno (stdout
))))
3444 #endif /* not (OS2 or WIN32 or __DJGPP__ or AMIGA) */
3447 /* Test each of the terminals given in `mfwsw' against the terminal
3448 type, and take the first one that matches, or if the user is running
3449 under Emacs, the first one. */
3450 for (mfwp
= mfwsw
; mfwp
->mfwsw_type
!= NULL
; mfwp
++) {
3451 if (!strncmp (mfwp
->mfwsw_type
, tty_type
, strlen (mfwp
->mfwsw_type
))
3452 || STREQ (tty_type
, "emacs")) {
3453 if (mfwp
->mfwsw_initscreen
) {
3454 retval
= (*mfwp
->mfwsw_initscreen
) ();
3456 Sleep(1000); /* Wait for opening a window */
3461 fprintf (stderr
, "mf: Couldn't initialize online display for `%s'.\n",
3468 /* The current terminal type wasn't found in any of the entries, or
3469 initalization failed, so silently give up, assuming that the user
3470 isn't on a terminal that supports graphic output. */
3475 /* Make sure everything is visible. */
3480 if (mfwp
->mfwsw_updatescrn
)
3481 (*mfwp
->mfwsw_updatescrn
) ();
3485 /* This sets the rectangle bounded by ([left,right], [top,bottom]) to
3486 the background color. */
3489 blankrectangle (screencol left
, screencol right
,
3490 screenrow top
, screenrow bottom
)
3492 if (mfwp
->mfwsw_blankrect
)
3493 (*mfwp
->mfwsw_blankrect
) (left
, right
, top
, bottom
);
3497 /* This paints ROW, starting with the color INIT_COLOR.
3498 TRANSITION_VECTOR then specifies the length of the run; then we
3499 switch colors. This goes on for VECTOR_SIZE transitions. */
3502 paintrow (screenrow row
, pixelcolor init_color
,
3503 transspec transition_vector
, screencol vector_size
)
3505 if (mfwp
->mfwsw_paintrow
)
3506 (*mfwp
->mfwsw_paintrow
) (row
, init_color
, transition_vector
, vector_size
);