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"
93 #include <mfluadir/mfluaextra.h>
94 #elif defined(MFLuaJIT)
95 #include <mfluajitdir/mfluajitextra.h>
97 #define BANNER "This is Metafont, Version 2.7182818"
98 #define COPYRIGHT_HOLDER "D.E. Knuth"
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"
106 #define DUMP_EXT ".bas"
108 #define DUMP_EXT ".base"
110 #define INPUT_FORMAT kpse_mf_format
111 #define INI_PROGRAM "inimf"
112 #define VIR_PROGRAM "virmf"
114 #define edit_var "MFEDIT"
117 #if !defined(IS_eTeX)
120 #if !defined(IS_pTeX)
123 #if !defined(IS_upTeX)
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)
136 if (!fullnameoffile
) {
140 if (kpse_absolute_p(fullnameoffile
, false)) {
141 return xstrdup(fullnameoffile
);
144 ret
= concat3(pwdbuf
, DIR_SEP_STRING
, fullnameoffile
);
156 #if defined(TeX) || (defined(MF) && defined(WIN32))
160 return (c
== ' ' || c
== '\t');
162 #endif /* TeX || (MF && WIN32) */
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
196 it becomes shellenabledp = 1 and restrictedshell = 0,
197 that is, any command is allowed.
198 (2) In the case where
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
211 static char **cmdlist
= NULL
;
214 mk_shellcmdlist (char *v
)
223 /* analyze the variable shell_escape_commands = foo,bar,...
224 spaces before and after (,) are not allowed. */
226 while ((r
= strchr (q
, ',')) != 0) {
232 cmdlist
= xmalloc (n
* sizeof (char *));
235 while ((r
= strchr (q
, ',')) != 0) {
246 init_shell_escape (void)
248 if (shellenabledp
< 0) { /* --no-shell-escape on cmd line */
252 if (shellenabledp
== 0) { /* no shell options on cmd line, check cnf */
253 char *v1
= kpse_var_value ("shell_escape");
255 if (*v1
== 't' || *v1
== 'y' || *v1
== '1') {
257 } else if (*v1
== 'p') {
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");
269 mk_shellcmdlist (v2
);
284 char_needs_quote (int c
)
286 /* special characters of cmd.exe */
288 return (c
== '&' || c
== '|' || c
== '%' || c
== '<' ||
289 c
== '>' || c
== ';' || c
== ',' || c
== '(' ||
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. */
304 shell_cmd_is_allowed (const char *cmd
, char **safecmd
, char **cmdname
)
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);
321 while (!Isspace(*d
) && *d
)
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
);
332 /* Is *cmdname listed in a texmf.cnf vriable as
333 shell_escape_commands = foo,bar,... ? */
337 if (strcmp (*p
, *cmdname
) == 0) {
338 /* *cmdname is found in the list, so restricted shell escape
348 for (s
= cmd
; *s
; s
++) {
353 /* allocate enough memory (too much?) */
355 *safecmd
= xmalloc (2 * strlen (cmd
) + 3 + 2 * spaces
);
357 *safecmd
= xmalloc (strlen (cmd
) + 3 + 2 * spaces
);
360 /* make a safe command line *safecmd */
365 while (!Isspace (*s
) && *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. */
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.
382 --format="other text files" becomes
383 '--format=''other text files' (Unix)
384 "--format=""other text files" (Windows) */
390 /* output the quotation mark for the quoted argument */
395 /* Illegal use of ', or closing quotation mark is missing */
396 if (*s
== '\'' || *s
== '\0')
399 if (char_needs_quote (*s
))
405 /* Closing quotation mark will be output afterwards, so
406 we do nothing here */
409 /* The character after the closing quotation mark
410 should be a white space or NULL */
411 if (!Isspace (*s
) && *s
)
414 /* Beginning of a usual argument */
415 } else if (pre
== 1 && !Isspace (*s
)) {
419 if (char_needs_quote (*s
))
423 /* Ending of a usual argument */
425 } else if (pre
== 0 && Isspace (*s
)) {
427 /* Closing quotation mark */
431 /* Copy a character from cmd to *safecmd. */
433 if (char_needs_quote (*s
))
439 /* End of the command line */
448 if (strlen (p
) > 2 && p
[1] == ':' && !IS_DIR_SEP (p
[2])) {
449 q
= xmalloc (strlen (p
) + 2);
457 } else if (!IS_DIR_SEP (p
[0]) && !(p
[1] == ':' && IS_DIR_SEP (p
[2]))) {
458 p
= kpse_var_value ("SELFAUTOLOC");
461 while (*r
&& !Isspace(*r
))
464 q
= concatn ("\"", p
, "/", *safecmd
, "\"", NULL
);
468 while (*r
&& Isspace(*r
))
471 q
= concatn ("\"", p
, "/", *safecmd
, "\" ", r
, NULL
);
473 q
= concatn ("\"", p
, "/", *safecmd
, "\"", NULL
);
487 /* We should only be called with shellenabledp == 1.
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
498 #define system fsyscp_system
501 #define popen fsyscp_popen
502 #endif /* ENABLE_PIPES */
506 runsystem (const char *cmd
)
509 char *safecmd
= NULL
;
510 char *cmdname
= NULL
;
512 if (shellenabledp
<= 0) {
516 /* If restrictedshell == 0, any command is allowed. */
517 if (restrictedshell
== 0)
520 allow
= shell_cmd_is_allowed (cmd
, &safecmd
, &cmdname
);
525 (void) system (safecmd
);
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. */
543 runpopen (char *cmd
, const char *mode
)
546 char *safecmd
= NULL
;
547 char *cmdname
= NULL
;
553 for (pp
= cmd
; *pp
; pp
++) {
554 if (*pp
== '\'') *pp
= '"';
558 /* If restrictedshell == 0, any command is allowed. */
559 if (restrictedshell
== 0)
562 allow
= shell_cmd_is_allowed (cmd
, &safecmd
, &cmdname
);
565 f
= popen (cmd
, mode
);
567 f
= popen (safecmd
, mode
);
568 else if (allow
== -1)
569 fprintf (stderr
, "\nrunpopen quotation error in command line: %s\n",
572 fprintf (stderr
, "\nrunpopen command not allowed: %s\n", cmdname
);
580 #endif /* ENABLE_PIPES */
582 /* The main program, etc. */
585 #include "xetexdir/XeTeX_ext.h"
588 /* What we were invoked as and with. */
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
;
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
);
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. */
621 texmf_yesno(const_string var
)
623 string value
= kpse_var_value (var
);
624 return value
&& (*value
== 't' || *value
== 'y' || *value
== '1');
628 const char *ptexbanner
= BANNER
;
632 /* forward declaration */
634 normalize_quotes (const_string name
, const_string mesg
);
636 int srcspecialsp
= 0;
638 /* Support of 8.3-name convention. If *buffer == NULL, nothing is done. */
639 static void change_to_long_name (char **buffer
)
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
);
655 /* The entry point: set up for reading the command line, which will
656 happen in `topenin', then call the main body. */
659 maininit (int ac
, string
*av
)
661 string main_input_file
;
662 #if (IS_upTeX || defined(XeTeX)) && defined(WIN32)
665 /* Save to pass along to topenin. */
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
683 # define SYNCTEX_NO_OPTION INT_MAX
684 synctexoption
= SYNCTEX_NO_OPTION
;
688 kpse_set_program_name (argv
[0], NULL
);
691 #if defined(XeTeX) && defined(WIN32)
692 kpse_set_program_name (argv
[0], NULL
);
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
);
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
);
705 parse_options (ac
, av
);
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);
715 recorder_record_input (p
);
719 /* If -progname was not specified, default to the dump name. */
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))
728 kpse_reset_program_name (user_progname
);
730 kpse_set_program_name (argv
[0], user_progname
);
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");
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");
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();
756 if (main_input_file
== NULL
) {
763 if (name
&& name
[0] != '-' && name
[0] != '&' && name
[0] != '\\') {
764 if (strlen (name
) > 2 && isalpha (name
[0]) && name
[1] == ':' &&
767 for (pp
= name
; *pp
; pp
++) {
770 else if (*pp
== '\\')
775 name
= normalize_quotes(argv
[argc
-1], "argument");
776 main_input_file
= kpse_find_file(argv
[argc
-1], INPUT_FORMAT
, false);
778 change_to_long_name (&main_input_file
);
780 name
= normalize_quotes(main_input_file
, "argument");
784 name
= normalize_quotes(argv
[argc
-1], "argument");
785 quoted
= (name
[0] == '"');
787 /* Overwrite last quote and skip first quote. */
788 name
[strlen(name
)-1] = '\0';
791 main_input_file
= kpse_find_file(name
, INPUT_FORMAT
, false);
793 change_to_long_name (&main_input_file
);
795 /* Undo modifications */
796 name
[strlen(name
)] = '"';
801 name
= normalize_quotes(main_input_file
, "argument");
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) {
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
)) {
841 } else if (FILESTRCASEEQ (kpse_program_name
, VIR_PROGRAM
)) {
844 } else if (FILESTRCASEEQ (kpse_program_name
, "initex")) {
846 } else if (FILESTRCASEEQ (kpse_program_name
, "virtex")) {
849 } else if (FILESTRCASEEQ (kpse_program_name
, "mltex")) {
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
);
863 /* Sanity check: -mltex, -enc, -etex only work in combination with -ini. */
867 fprintf(stderr
, "-mltex only works with -ini\n");
869 #if !defined(XeTeX) && !IS_pTeX
871 fprintf(stderr
, "-enc only works with -ini\n");
877 fprintf(stderr
, "-etex only works with -ini\n");
883 /* If we've set up the fmt/base default in any of the various ways
884 above, also set its length. */
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
;
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);
900 /* For dump_name to be NULL is a bug. */
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. */
908 kpse_set_program_enabled (kpse_mf_format
, MAKE_TEX_MF_BY_DEFAULT
,
910 kpse_set_program_enabled (kpse_base_format
, MAKE_TEX_FMT_BY_DEFAULT
,
915 kpse_set_program_enabled (kpse_ocp_format
, MAKE_OMEGA_OCP_BY_DEFAULT
,
917 kpse_set_program_enabled (kpse_ofm_format
, MAKE_OMEGA_OFM_BY_DEFAULT
,
919 kpse_set_program_enabled (kpse_tfm_format
, false, kpse_src_compile
);
921 kpse_set_program_enabled (kpse_tfm_format
, MAKE_TEX_TFM_BY_DEFAULT
,
924 kpse_set_program_enabled (kpse_tex_format
, MAKE_TEX_TEX_BY_DEFAULT
,
926 kpse_set_program_enabled (kpse_fmt_format
, MAKE_TEX_FMT_BY_DEFAULT
,
929 init_shell_escape ();
931 if (!outputcomment
) {
932 outputcomment
= kpse_var_value ("output_comment");
937 /* The entry point: set up for reading the command line, which will
938 happen in `topenin', then call the main body. */
942 DLLPROC (int ac
, string
*av
)
944 main (int ac
, string
*av
)
948 _wildcard (&ac
, &av
);
949 _response (&ac
, &av
);
953 av
[0] = kpse_program_basename (av
[0]);
955 setmode(fileno(stdin
), _O_BINARY
);
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
++) {
979 /* Call the real main program. */
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
997 static UFILE termin_file
;
999 termin
= &termin_file
;
1001 termin
->savedChar
= -1;
1002 termin
->skipNextLF
= 0;
1003 termin
->encodingMode
= UTF8
;
1004 termin
->conversionData
= 0;
1005 inputfile
[0] = termin
;
1009 buffer
[first
] = 0; /* In case there are no arguments. */
1011 if (optind
< argc
) { /* We have command line arguments. */
1013 for (i
= optind
; i
< argc
; i
++) {
1015 unsigned char *ptr
= (unsigned char *)&(argv
[i
][0]);
1016 /* need to interpret UTF8 from the command line */
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
++);
1028 rval
-= offsetsFromUTF8
[extraBytes
];
1032 char *ptr
= &(argv
[i
][0]);
1033 /* Don't use strcat, since in Aleph the buffer elements aren't
1036 buffer
[k
++] = *(ptr
++);
1041 argc
= 0; /* Don't do this again. */
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
)
1056 /* One more time, this time converting to TeX's internal character
1058 #if !defined(Aleph) && !defined(XeTeX)
1059 for (i
= first
; i
< last
; i
++)
1060 buffer
[i
] = xord
[buffer
[i
]];
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)
1071 #include <winsock2.h>
1073 #include <sys/socket.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
1081 what the fcntl
? cannot implement IPC without equivalent
for O_NONBLOCK
.
1083 #endif /* no O_NONBLOCK */
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
1093 # define IPC_AF AF_UNIX
1094 # ifndef IPC_PIPE_NAME /* $HOME is prepended to this. */
1095 # define IPC_PIPE_NAME "/.TeXview_Pipe"
1098 #ifndef IPC_SERVER_CMD /* Command to run to start the server. */
1100 # define IPC_SERVER_CMD "texview.exe"
1102 # define IPC_SERVER_CMD "open `which TeXview`"
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 */
1115 static struct sockaddr
*ipc_addr
;
1116 static int ipc_addr_len
;
1119 ipc_make_name (void)
1121 if (ipc_addr_len
== 0) {
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
);
1133 string s
= getenv ("HOME");
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;
1145 return ipc_addr_len
;
1148 static int sock
= -1;
1151 # define CLOSE_SOCKET(s) closesocket (s); WSACleanup ()
1153 # define CLOSE_SOCKET(s) close (s)
1163 ipc_open_out (void) {
1165 struct WSAData wsaData
;
1167 unsigned long mode
= 1;
1170 fputs ("tex: Opening socket for IPC output ...\n", stderr
);
1177 if ((nCode
= WSAStartup(MAKEWORD(1, 1), &wsaData
)) != 0) {
1178 fprintf(stderr
,"WSAStartup() returned error code %d.\n", nCode
);
1183 if (ipc_make_name () <= 0)
1186 sock
= socket (IPC_AF
, SOCK_STREAM
, 0);
1189 fprintf(stderr
, "tex: Socket handle is %d\n", sock
);
1191 fprintf(stderr
, "tex: Socket is invalid.\n");
1195 if (connect (sock
, ipc_addr
, ipc_addr_len
) != 0 ||
1197 ioctlsocket (sock
, FIONBIO
, &mode
) < 0
1199 fcntl (sock
, F_SETFL
, O_NONBLOCK
) < 0
1202 CLOSE_SOCKET (sock
);
1205 fputs ("tex: IPC socket cannot be connected.\n", stderr
);
1206 fputs ("tex: Socket is closed.\n", stderr
);
1211 fputs ("tex: Successfully opened IPC socket.\n", stderr
);
1217 ipc_close_out (void)
1220 fputs ("tex: Closing output socket ...\n", stderr
);
1222 if (ipc_is_open ()) {
1223 CLOSE_SOCKET (sock
);
1229 ipc_snd (int n
, int is_eof
, char *data
)
1234 char more_data
[1024];
1237 if (!ipc_is_open ()) {
1242 fprintf(stderr
, "%d\t%d\n", ourmsg
.msg
.namelength
, ourmsg
.msg
.eof
);
1243 fputs ("tex: Sending message to socket ...\n", stderr
);
1245 ourmsg
.msg
.namelength
= n
;
1246 ourmsg
.msg
.eof
= is_eof
;
1248 strcpy (ourmsg
.more_data
, data
);
1250 n
+= sizeof (struct msg
);
1252 fprintf(stderr
, "%d\t%d\n", ourmsg
.msg
.namelength
, ourmsg
.msg
.eof
);
1253 fputs ("tex: Writing to socket...\n", stderr
);
1256 if (send (sock
, (char *)&ourmsg
, n
, 0) != n
) {
1258 if (write (sock
, &ourmsg
, n
) != n
) {
1263 fputs ("tex: IPC message sent.\n", stderr
);
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). */
1273 ipcpage (int is_eof
)
1275 static boolean begun
= false;
1280 string name
; /* Just the filename. */
1281 string cwd
= xgetcwd ();
1285 len
= strstart
[outputfilename
+ 1] - strstart
[outputfilename
];
1287 len
= strstartar
[outputfilename
+ 1 - 65536L] -
1288 strstartar
[outputfilename
- 65536L];
1290 name
= xmalloc (len
+ 1);
1292 strncpy (name
, (string
)&strpool
[strstart
[outputfilename
]], len
);
1296 for (i
=0; i
<len
; i
++)
1297 name
[i
] = strpool
[i
+strstartar
[outputfilename
- 65536L]];
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
1305 p
= concat3 (cwd
, DIR_SEP_STRING
, name
);
1311 for (q
= p
; *q
; q
++) {
1314 else if (IS_KANJI(q
))
1322 ipc_snd (len
, is_eof
, 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
1338 tcx_get_num (int upb
,
1339 unsigned line_count
,
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. */
1348 while (*p
&& ISSPACE (*p
))
1351 fprintf (stderr
, "%s:%d: Expected numeric constant, not `%s'.\n",
1352 translate_filename
, line_count
, start
);
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
);
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. */
1374 string orig_filename
;
1375 if (!find_suffix (translate_filename
)) {
1376 translate_filename
= concat (translate_filename
, ".tcx");
1378 orig_filename
= translate_filename
;
1380 = kpse_find_file (translate_filename
, kpse_web2c_format
, true);
1381 if (translate_filename
) {
1383 unsigned line_count
= 0;
1384 FILE *translate_file
= xfopen (translate_filename
, FOPEN_R_MODE
);
1385 while ((line
= read_line (translate_file
))) {
1388 string comment_loc
= strchr (line
, '%');
1394 first
= tcx_get_num (255, line_count
, line
, &start2
);
1400 second
= tcx_get_num (255, line_count
, start2
, &start3
);
1402 /* I suppose we could check for nonempty junk following the
1403 "printable" code, but let's not bother. */
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)
1414 /* Don't allow the 7bit ASCII set to become unprintable. */
1415 if (32 <= second
&& second
<= 126)
1418 second
= first
; /* else make internal the same as external */
1419 /* If they mention a charcode, call it printable. */
1423 xprn
[second
] = printable
;
1427 xfclose(translate_file
, translate_filename
);
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 */
1437 normalize_quotes (const_string name
, const_string mesg
)
1440 boolean must_quote
= false;
1441 int len
= strlen(name
);
1442 /* Leave room for quotes and NUL. */
1446 for (q
= name
; *q
; q
++) {
1453 else if (*q
== '\"' || *q
== '\'') {
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);
1463 if (quote_char
== 0)
1467 for (q
= name
; *q
; q
++) {
1468 if (*q
== quote_char
) {
1470 quote_char
= '\"' + '\'' - quote_char
;
1475 if (quote_char
!= 0)
1481 /* Normalize quoting of filename -- that is, only quote if there is a space,
1482 and always use the quote-name-quote style. */
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);
1495 for (q
= name
; *q
; q
++) {
1505 fprintf(stderr
, "! Unbalanced quotes in %s %s\n", mesg
, name
);
1512 /* Getting the input filename. */
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. */
1526 if (strlen (argv
[optind
]) > 2 && isalpha (argv
[optind
][0]) &&
1527 argv
[optind
][1] == ':' && argv
[optind
][2] == '\\') {
1529 for (pp
= argv
[optind
]; *pp
; pp
++) {
1532 else if (IS_KANJI(pp
))
1538 name
= normalize_quotes(argv
[optind
], "argument");
1540 input_file_name
= kpse_find_file(argv
[optind
], INPUT_FORMAT
, false);
1543 change_to_long_name (&input_file_name
);
1546 quoted
= (name
[0] == '"');
1548 /* Overwrite last quote and skip first quote. */
1549 name
[strlen(name
)-1] = '\0';
1552 input_file_name
= kpse_find_file(name
, INPUT_FORMAT
, false);
1555 change_to_long_name (&input_file_name
);
1558 /* Undo modifications */
1559 name
[strlen(name
)] = '"';
1564 if (!srcspecialsp
) {
1565 if (input_file_name
)
1566 name
= normalize_quotes (input_file_name
, "argument");
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 },
1585 /* FIXME: Obsolete -- for backward compatibility only. */
1586 { "efmt", 1, 0, 0 },
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 },
1598 { "ipc", 0, &ipcon
, 1 },
1599 { "ipc-start", 0, &ipcon
, 2 },
1602 { "mltex", 0, &mltexp
, 1 },
1603 #if !defined(XeTeX) && !IS_pTeX
1604 { "enc", 0, &enctexp
, 1 },
1608 { "etex", 0, &etexp
, 1 },
1610 { "output-comment", 1, 0, 0 },
1612 { "draftmode", 0, 0, 0 },
1613 { "output-format", 1, 0, 0 },
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 },
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 },
1638 { "translate-file", 1, 0, 0 },
1639 { "default-translate-file", 1, 0, 0 },
1640 { "8bit", 0, &eightbitp
, 1 },
1643 { "no-pdf", 0, &nopdfoutput
, 1 },
1644 { "output-driver", 1, 0, 0 },
1645 { "papersize", 1, 0, 0 },
1647 { "mktex", 1, 0, 0 },
1648 { "no-mktex", 1, 0, 0 },
1649 #endif /* TeX or MF */
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 },
1656 { "kanji", 1, 0, 0 },
1657 { "kanji-internal", 1, 0, 0 },
1658 #endif /* IS_pTeX */
1662 parse_options (int argc
, string
*argv
)
1664 int g
; /* `getopt' return code. */
1668 g
= getopt_long_only (argc
, argv
, "+", long_options
, &option_index
);
1670 if (g
== -1) /* End of arguments, exit the loop. */
1673 if (g
== '?') { /* Unknown option. */
1674 /* FIXME: usage (argv[0]); replaced by continue. */
1678 assert (g
== 0); /* We have no short option names. */
1680 if (ARGUMENT_IS ("kpathsea-debug")) {
1681 kpathsea_debug
|= atoi (optarg
);
1684 } else if (ARGUMENT_IS ("papersize")) {
1686 } else if (ARGUMENT_IS ("output-driver")) {
1687 outputdriver
= optarg
;
1690 } else if (ARGUMENT_IS ("progname")) {
1691 user_progname
= optarg
;
1693 } else if (ARGUMENT_IS ("jobname")) {
1695 c_job_name
= optarg
;
1697 c_job_name
= normalize_quotes (optarg
, "jobname");
1700 } else if (ARGUMENT_IS (DUMP_OPTION
)) {
1705 /* FIXME: Obsolete -- for backward compatibility only. */
1706 } else if (ARGUMENT_IS ("efmt")) {
1711 } else if (ARGUMENT_IS ("output-directory")) {
1712 output_directory
= optarg
;
1715 } else if (ARGUMENT_IS ("output-comment")) {
1716 unsigned len
= strlen (optarg
);
1718 outputcomment
= optarg
;
1720 WARNING2 ("Comment truncated to 255 characters from %d. (%s)",
1722 outputcomment
= xmalloc (256);
1723 strncpy (outputcomment
, optarg
, 255);
1724 outputcomment
[255] = 0;
1728 } else if (ARGUMENT_IS ("ipc-start")) {
1730 /* Try to start up the other end if it's not already. */
1731 if (!ipc_is_open ()) {
1733 if (_spawnlp (_P_NOWAIT
, IPC_SERVER_CMD
, IPC_SERVER_CMD
, NULL
) != -1) {
1735 if (system (IPC_SERVER_CMD
) == 0) {
1738 for (i
= 0; i
< 20 && !ipc_is_open (); i
++) {
1740 Sleep (100); /* 2000ms is too long for a simple w32 example */
1750 } else if (ARGUMENT_IS ("shell-restricted")) {
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;
1763 parse_src_specials_option(optarg
);
1767 } else if (ARGUMENT_IS ("output-format")) {
1768 pdfoutputoption
= 1;
1769 if (strcmp(optarg
, "dvi") == 0) {
1771 } else if (strcmp(optarg
, "pdf") == 0) {
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;
1781 #if defined (TeX) || defined (MF)
1783 } else if (ARGUMENT_IS ("translate-file")) {
1784 translate_filename
= optarg
;
1785 } else if (ARGUMENT_IS ("default-translate-file")) {
1786 default_translate_filename
= optarg
;
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;
1804 WARNING1 ("Ignoring unknown argument `%s' to --interaction", optarg
);
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
);
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);
1826 } else if (ARGUMENT_IS ("version")) {
1828 #if defined (pdfTeX) || defined(XeTeX)
1829 initversionstring(&versions
);
1833 printversionandexit (BANNER
, COPYRIGHT_HOLDER
, AUTHOR
, versions
);
1835 } /* Else it was a flag; getopt has already done the assignment. */
1841 parse_src_specials_option (const_string opt_list
)
1843 char * toklist
= xstrdup(opt_list
);
1845 insertsrcspecialauto
= false;
1846 tok
= strtok (toklist
, ", ");
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;
1878 WARNING1 ("Ignoring unknown argument `%s' to --src-specials", tok
);
1880 tok
= strtok(0, ", ");
1883 srcspecialsp
=insertsrcspecialauto
| insertsrcspecialeverypar
|
1884 insertsrcspecialeveryparend
| insertsrcspecialeverycr
|
1885 insertsrcspecialeverymath
| insertsrcspecialeveryhbox
|
1886 insertsrcspecialeveryvbox
| insertsrcspecialeverydisplay
;
1887 srcspecialsoption
= true;
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
1898 parse_first_line (const_string filename
)
1900 FILE *f
= filename
? fopen (filename
, FOPEN_R_MODE
) : NULL
;
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. */
1915 for (s
= first_line
+2; ISBLANK(*s
); ++s
)
1918 while (*s
&& npart
!= 3) {
1920 while (*s
&& *s
!= ' ') s
++;
1921 while (*s
== ' ') *s
++ = '\0';
1925 /* Look at what we've got. Very crude! */
1926 if (*parse
&& **parse
!= '-') {
1929 /* format already determined, do nothing. */
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... */
1943 /* The tcx stuff, if any. Should we support the -translate-file
1944 form as well as --translate-file? */
1947 if (translate_filename
) {
1948 /* TCX file already set, do nothing. */
1949 } else if (STREQ (*parse
, "--translate-file")) {
1951 } else if (STREQ (*parse
, "-translate-file")) {
1953 } else if (STRNEQ (*parse
, "--translate-file=", 17)) {
1955 } else if (STRNEQ (*parse
, "-translate-file=", 16)) {
1958 /* Just set the name, no sanity checks here. */
1959 /* FIXME: remove trailing spaces. */
1961 translate_filename
= xstrdup(s
);
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().
1981 #define NUM_PIPES 16
1983 static FILE *pipes
[NUM_PIPES
];
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 */
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");
2003 for (i
=0; i
<NUM_PIPES
; i
++) {
2004 if (pipes
[i
]==NULL
) {
2010 setvbuf (*f_ptr
,NULL
,_IONBF
,0);
2015 return *f_ptr
!= NULL
;
2018 return open_input(f_ptr
,filefmt
,fopen_mode
) ;
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;
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");
2045 for (i
=0; i
<NUM_PIPES
; i
++) {
2046 if (pipes
[i
]==NULL
) {
2052 setvbuf ((*f
)->f
,NULL
,_IONBF
,0);
2057 return (*f
)->f
!= NULL
;
2060 return u_open_in(f
, filefmt
, fopen_mode
, mode
, encodingData
);
2065 open_out_or_pipe (FILE **f_ptr
, const_string fopen_mode
)
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
)) = '.';
2088 *f_ptr
= runpopen(fname
+1,"w");
2090 recorder_record_output (fname
+ 1);
2093 for (i
=0; i
<NUM_PIPES
; i
++) {
2094 if (pipes
[i
]==NULL
) {
2101 setvbuf(*f_ptr
,NULL
,_IONBF
,0);
2103 return *f_ptr
!= NULL
;
2106 return open_output(f_ptr
,fopen_mode
);
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
) {
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. */
2137 /* Win32 doesn't set SIGINT ... */
2139 catch_interrupt (DWORD arg
)
2143 case CTRL_BREAK_EVENT
:
2147 /* No need to set interrupt as we are exiting anyway */
2151 #else /* not WIN32 */
2153 catch_interrupt (int arg
)
2157 (void) signal (SIGINT
, SIG_ACK
);
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. */
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;
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 */
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 */
2215 Getting a high resolution time.
2218 get_seconds_and_micros (integer
*seconds
, integer
*micros
)
2220 #if defined (HAVE_GETTIMEOFDAY)
2222 gettimeofday(&tv
, NULL
);
2223 *seconds
= tv
.tv_sec
;
2224 *micros
= tv
.tv_usec
;
2225 #elif defined (HAVE_FTIME)
2229 *micros
= tb
.millitm
*1000;
2231 time_t myclock
= time((time_t*)NULL
);
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 */
2245 input_line (FILE *f
)
2249 /* Recognize either LF or CR as a line terminator. */
2251 last
= input_line2(f
, (unsigned char *)buffer
, first
, bufsize
, &i
);
2254 if (f
!= Poptr
&& fileno (f
) != fileno (stdin
)) {
2255 long position
= ftell (f
);
2257 if (position
== 0L) { /* Detect and skip Byte order marks. */
2260 if (k1
!= 0xff && k1
!= 0xfe && k1
!= 0xef)
2265 if (k2
!= 0xff && k2
!= 0xfe && k2
!= 0xbb)
2267 else if ((k1
== 0xff && k2
== 0xfe) || /* UTF-16(LE) */
2268 (k1
== 0xfe && k2
== 0xff)) /* UTF-16(BE) */
2273 if (k1
== 0xef && k2
== 0xbb && k3
== 0xbf) /* UTF-8 */
2283 while (last
< bufsize
&& (i
= getc (f
)) != EOF
&& i
!= '\n' && i
!= '\r')
2287 if (i
== EOF
&& errno
!= EINTR
&& last
== first
)
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
);
2299 if (last
>= maxbufstack
)
2302 /* If next char is LF of a CRLF, read it. */
2304 while ((i
= getc (f
)) == EOF
&& errno
== EINTR
)
2310 /* Trim trailing whitespace. */
2311 while (last
> first
&& ISBLANK (buffer
[last
- 1]))
2314 /* Don't bother using xord if we don't need to. */
2316 for (i
= first
; i
<= last
; i
++)
2317 buffer
[i
] = xord
[buffer
[i
]];
2321 for (i
= last
+1; (i
< last
+ 5 && i
< bufsize
) ; i
++)
2329 /* This string specifies what the `e' option does in response to an
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. */
2339 calledit (packedASCIIcode
*filename
,
2340 poolpointer fnstart
,
2344 char *temp
, *command
, *fullcmd
;
2346 int sdone
, ddone
, i
;
2349 char *fp
, *ffp
, *env
, editorname
[256], buffer
[256];
2355 filename
+= fnstart
;
2357 /* Close any open input files, since we're going to kill the job. */
2358 for (i
= 1; i
<= inopen
; i
++)
2360 xfclose (inputfile
[i
]->f
, "inputfile");
2362 xfclose (inputfile
[i
], "inputfile");
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
);
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. */
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)))
2389 while ((c
= *edit_value
++) != 0)
2393 switch (c
= *edit_value
++)
2397 FATAL ("call_edit: `%%d' appears twice in editor command");
2398 sprintf (temp
, "%ld", (long int)linenumber
);
2399 while (*temp
!= '\0')
2406 FATAL ("call_edit: `%%s' appears twice in editor command");
2407 for (i
=0; i
< fnlength
; i
++)
2408 *temp
++ = Xchr (filename
[i
]);
2414 /* Back up to the null to force termination. */
2428 else { if(Isspace(c
) && cnt
== 0) {
2433 } else if(!Isspace(c
) && cnt
== 0) {
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
);
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
);
2462 fullcmd
= (char *)xmalloc(strlen(buffer
)+strlen(command
)+5);
2463 strcpy(fullcmd
, "\"");
2464 strcat(fullcmd
, buffer
);
2465 strcat(fullcmd
, "\"");
2466 strcat(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. */
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
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. */
2499 swap_items (char *p
, int nitems
, int size
)
2503 /* Since `size' does not change, we can write a while loop for each
2504 case, and avoid testing `size' for each time. */
2507 /* 16-byte items happen on the DEC Alpha machine when we are not
2508 doing sharable memory dumps. */
2553 /* Nothing to do. */
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
2569 do_dump (char *p
, int item_size
, int nitems
, gzFile out_file
)
2571 do_dump (char *p
, int item_size
, int nitems
, FILE *out_file
)
2574 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2575 swap_items (p
, nitems
, item_size
);
2579 if (gzwrite (out_file
, p
, item_size
* nitems
) != item_size
* nitems
)
2581 if (fwrite (p
, item_size
, nitems
, out_file
) != nitems
)
2584 fprintf (stderr
, "! Could not write %d %d-byte item(s) to %s.\n",
2585 nitems
, item_size
, nameoffile
+1);
2589 /* Have to restore the old contents of memory, since some of it might
2591 #if !defined (WORDS_BIGENDIAN) && !defined (NO_DUMP_SHARE)
2592 swap_items (p
, nitems
, item_size
);
2597 /* Here is the dual of the writing routine. */
2601 do_undump (char *p
, int item_size
, int nitems
, gzFile in_file
)
2603 do_undump (char *p
, int item_size
, int nitems
, FILE *in_file
)
2607 if (gzread (in_file
, p
, item_size
* nitems
) != item_size
* nitems
)
2609 if (fread (p
, item_size
, nitems
, in_file
) != (size_t) nitems
)
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
);
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)
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 */
2632 #ifndef XeTeX /* XeTeX uses this from XeTeX_ext.c */
2636 maketexstring(const_string s
)
2641 const unsigned char *cp
= (const unsigned char *)s
;
2644 if (s
== NULL
|| *s
== 0)
2645 return getnullstr();
2650 checkpoolpointer (poolptr
, len
); /* in the XeTeX case, this may be more than enough */
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
++);
2662 rval
-= offsetsFromUTF8
[extraBytes
];
2663 if (rval
> 0xffff) {
2665 strpool
[poolptr
++] = 0xd800 + rval
/ 0x0400;
2666 strpool
[poolptr
++] = 0xdc00 + rval
% 0x0400;
2669 strpool
[poolptr
++] = rval
;
2673 strpool
[poolptr
++] = *s
++;
2674 #endif /* ! XeTeX */
2676 return makestring();
2678 #endif /* !pdfTeX */
2681 makefullnamestring(void)
2683 return maketexstring(fullnameoffile
);
2686 /* Get the job name to be used, which may have been set from the
2689 getjobname(strnumber name
)
2691 strnumber ret
= name
;
2692 if (c_job_name
!= NULL
)
2693 ret
= maketexstring(c_job_name
);
2700 compare_paths (const_string p1
, const_string p2
)
2704 #ifdef MONOCASE_FILENAMES
2705 (((ret
= (toupper(*p1
) - toupper(*p2
))) == 0) && (*p2
!= 0))
2707 (((ret
= (*p1
- *p2
)) == 0) && (*p2
!= 0))
2709 || (IS_DIR_SEP(*p1
) && IS_DIR_SEP(*p2
))) {
2712 ret
= (ret
< 0 ? -1 : (ret
> 0 ? 1 : 0));
2716 #ifdef XeTeX /* the string pool is UTF-16 but we want a UTF-8 string */
2719 gettexstring (strnumber s
)
2721 unsigned bytesToWrite
= 0;
2722 poolpointer len
, i
, j
;
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;
2740 else if (c
< 0x10000)
2742 else if (c
< 0x110000)
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
]);
2765 gettexstring (strnumber s
)
2770 len
= strstart
[s
+ 1] - strstart
[s
];
2772 len
= strstartar
[s
+ 1 - 65536L] - strstartar
[s
- 65536L];
2774 name
= (string
)xmalloc (len
+ 1);
2776 strncpy (name
, (string
)&strpool
[strstart
[s
]], len
);
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]];
2788 #endif /* not XeTeX */
2791 isnewsource (strnumber srcfilename
, int lineno
)
2793 char *name
= gettexstring(srcfilename
);
2794 return (compare_paths(name
, last_source_name
) != 0 || lineno
!= last_lineno
);
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
;
2807 makesrcspecial (strnumber srcfilename
, int lineno
)
2809 poolpointer oldpoolptr
= poolptr
;
2810 char *filename
= gettexstring(srcfilename
);
2811 /* FIXME: Magic number. */
2815 /* Always put a space after the number, which makes things easier
2818 sprintf (buf
, "src:%d ", lineno
);
2820 if (poolptr
+ strlen(buf
) + strlen(filename
) >= (size_t)poolsize
) {
2821 fprintf (stderr
, "\nstring pool overflow\n"); /* fixme */
2826 strpool
[poolptr
++] = *s
++;
2830 strpool
[poolptr
++] = *s
++;
2832 return (oldpoolptr
);
2835 /* pdfTeX routines also used for e-pTeX, e-upTeX, and XeTeX */
2836 #if defined (pdfTeX) || defined (epTeX) || defined (eupTeX) || defined(XeTeX)
2838 #include <kpathsea/c-stat.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
)
2858 for (c
= str
; *c
; ++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
2868 __attribute__ ((noreturn
, format(printf
, 1, 2)))
2869 void pdftex_fail(const char *fmt
, ...)
2872 va_start(args
, fmt
);
2874 safe_print("!error: ");
2875 vsnprintf(print_buf
, PRINTF_BUF_SIZE
, fmt
, args
);
2876 safe_print(print_buf
);
2879 safe_print(" ==> Fatal error occurred, output file will be damaged!");
2881 if (kpathsea_debug
) {
2882 safe_print("kpathsea_debug enabled, calling abort()...");
2889 #endif /* not pdfTeX */
2892 static time_t start_time
= 0;
2893 #define TIME_STR_SIZE 30
2894 char start_time_str
[TIME_STR_SIZE
];
2895 static char time_str
[TIME_STR_SIZE
];
2896 /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
2898 static void makepdftime(time_t t
, char *time_str
)
2903 int i
, off
, off_hours
, off_mins
;
2906 lt
= *localtime(&t
);
2907 size
= strftime(time_str
, TIME_STR_SIZE
, "D:%Y%m%d%H%M%S", <
);
2908 /* expected format: "YYYYmmddHHMMSS" */
2910 /* unexpected, contents of time_str is undefined */
2915 /* correction for seconds: %S can be in range 00..61,
2916 the PDF reference expects 00..59,
2917 therefore we map "60" and "61" to "59" */
2918 if (time_str
[14] == '6') {
2921 time_str
[16] = '\0'; /* for safety */
2924 /* get the time zone offset */
2927 /* this calculation method was found in exim's tod.c */
2928 off
= 60 * (lt
.tm_hour
- gmt
.tm_hour
) + lt
.tm_min
- gmt
.tm_min
;
2929 if (lt
.tm_year
!= gmt
.tm_year
) {
2930 off
+= (lt
.tm_year
> gmt
.tm_year
) ? 1440 : -1440;
2931 } else if (lt
.tm_yday
!= gmt
.tm_yday
) {
2932 off
+= (lt
.tm_yday
> gmt
.tm_yday
) ? 1440 : -1440;
2936 time_str
[size
++] = 'Z';
2939 off_hours
= off
/ 60;
2940 off_mins
= abs(off
- off_hours
* 60);
2941 i
= snprintf(&time_str
[size
], 9, "%+03d'%02d'", off_hours
, off_mins
);
2942 check_nprintf(i
, 9);
2946 void initstarttime(void)
2948 if (start_time
== 0) {
2949 start_time
= time((time_t *) NULL
);
2950 makepdftime(start_time
, start_time_str
);
2954 char *makecstring(integer s
)
2956 static char *cstrbuf
= NULL
;
2958 static int allocsize
;
2959 int allocgrow
, i
, l
= strstart
[s
+ 1] - strstart
[s
];
2960 check_buf(l
+ 1, MAX_CSTRING_LEN
);
2961 if (cstrbuf
== NULL
) {
2963 cstrbuf
= xmallocarray(char, allocsize
);
2964 } else if (l
+ 1 > allocsize
) {
2965 allocgrow
= allocsize
* 0.2;
2966 if (l
+ 1 - allocgrow
> allocsize
)
2968 else if (allocsize
< MAX_CSTRING_LEN
- allocgrow
)
2969 allocsize
+= allocgrow
;
2971 allocsize
= MAX_CSTRING_LEN
;
2972 cstrbuf
= xreallocarray(cstrbuf
, char, allocsize
);
2975 for (i
= 0; i
< l
; i
++)
2976 *p
++ = strpool
[i
+ strstart
[s
]];
2982 input/ouput same as makecstring:
2983 input: string number
2984 output: C string with quotes removed.
2985 That means, file names that are legal on some operation systems
2986 cannot any more be used since pdfTeX version 1.30.4.
2988 char *makecfilename(integer s
)
2990 char *name
= makecstring(s
);
3003 void getcreationdate(void)
3007 /* put creation date on top of string pool and update poolptr */
3008 len
= strlen(start_time_str
);
3010 /* In e-pTeX, "init len => call initstarttime()" (as pdftexdir/utils.c)
3011 yields unintentional output. */
3013 if ((unsigned) (poolptr
+ len
) >= (unsigned) (poolsize
)) {
3015 /* error by str_toks that calls str_room(1) */
3019 memcpy(&strpool
[poolptr
], start_time_str
, len
);
3023 void getfilemoddate(integer s
)
3025 struct stat file_data
;
3027 char *file_name
= kpse_find_tex(makecfilename(s
));
3028 if (file_name
== NULL
) {
3029 return; /* empty string */
3032 recorder_record_input(file_name
);
3033 /* get file status */
3034 if (stat(file_name
, &file_data
) == 0) {
3037 makepdftime(file_data
.st_mtime
, time_str
);
3038 len
= strlen(time_str
);
3039 if ((unsigned) (poolptr
+ len
) >= (unsigned) (poolsize
)) {
3041 /* error by str_toks that calls str_room(1) */
3043 memcpy(&strpool
[poolptr
], time_str
, len
);
3047 /* else { errno contains error code } */
3052 void getfilesize(integer s
)
3054 struct stat file_data
;
3057 char *file_name
= kpse_find_tex(makecfilename(s
));
3058 if (file_name
== NULL
) {
3059 return; /* empty string */
3062 recorder_record_input(file_name
);
3063 /* get file status */
3064 if (stat(file_name
, &file_data
) == 0) {
3068 /* st_size has type off_t */
3069 i
= snprintf(buf
, sizeof(buf
),
3070 "%lu", (long unsigned int) file_data
.st_size
);
3071 check_nprintf(i
, sizeof(buf
));
3073 if ((unsigned) (poolptr
+ len
) >= (unsigned) (poolsize
)) {
3075 /* error by str_toks that calls str_room(1) */
3077 memcpy(&strpool
[poolptr
], buf
, len
);
3081 /* else { errno contains error code } */
3086 void getfiledump(integer s
, int offset
, int length
)
3090 poolpointer data_ptr
;
3091 poolpointer data_end
;
3095 /* empty result string */
3099 if (poolptr
+ 2 * length
+ 1 >= poolsize
) {
3100 /* no place for result */
3102 /* error by str_toks that calls str_room(1) */
3106 file_name
= kpse_find_tex(makecfilename(s
));
3107 if (file_name
== NULL
) {
3108 return; /* empty string */
3111 /* read file data */
3112 f
= fopen(file_name
, FOPEN_RBIN_MODE
);
3117 recorder_record_input(file_name
);
3118 if (fseek(f
, offset
, SEEK_SET
) != 0) {
3122 /* there is enough space in the string pool, the read
3123 data are put in the upper half of the result, thus
3124 the conversion to hex can be done without overwriting
3125 unconverted bytes. */
3126 data_ptr
= poolptr
+ length
;
3127 read
= fread(&strpool
[data_ptr
], sizeof(char), length
, f
);
3130 /* convert to hex */
3131 data_end
= data_ptr
+ read
;
3132 for (; data_ptr
< data_end
; data_ptr
++) {
3133 i
= snprintf((char *) &strpool
[poolptr
], 3,
3134 "%.2X", (unsigned int) strpool
[data_ptr
]);
3135 check_nprintf(i
, 3);
3140 #endif /* not XeTeX */
3142 /* Converts any given string in into an allowed PDF string which is
3143 * hexadecimal encoded;
3144 * sizeof(out) should be at least lin*2+1.
3146 void convertStringToHexString(const char *in
, char *out
, int lin
)
3151 for (i
= 0; i
< lin
; i
++) {
3152 k
= snprintf(buf
, sizeof(buf
),
3153 "%02X", (unsigned int) (unsigned char) in
[i
]);
3154 check_nprintf(k
, sizeof(buf
));
3161 #define DIGEST_SIZE 16
3162 #define FILE_BUF_SIZE 1024
3164 void getmd5sum(strnumber s
, boolean file
)
3167 md5_byte_t digest
[DIGEST_SIZE
];
3168 char outbuf
[2 * DIGEST_SIZE
+ 1];
3169 int len
= 2 * DIGEST_SIZE
;
3176 char file_buf
[FILE_BUF_SIZE
];
3182 xname
= gettexstring (s
);
3183 file_name
= kpse_find_tex (xname
);
3186 file_name
= kpse_find_tex(makecfilename(s
));
3188 if (file_name
== NULL
) {
3189 return; /* empty string */
3191 /* in case of error the empty string is returned,
3192 no need for xfopen that aborts on error.
3194 f
= fopen(file_name
, FOPEN_RBIN_MODE
);
3199 recorder_record_input(file_name
);
3201 while ((read
= fread(&file_buf
, sizeof(char), FILE_BUF_SIZE
, f
)) > 0) {
3202 md5_append(&state
, (const md5_byte_t
*) file_buf
, read
);
3204 md5_finish(&state
, digest
);
3209 /* s contains the data */
3212 xname
= gettexstring (s
);
3214 (md5_byte_t
*) xname
,
3219 (md5_byte_t
*) &strpool
[strstart
[s
]],
3220 strstart
[s
+ 1] - strstart
[s
]);
3222 md5_finish(&state
, digest
);
3225 if (poolptr
+ len
>= poolsize
) {
3226 /* error by str_toks that calls str_room(1) */
3229 convertStringToHexString((char *) digest
, outbuf
, DIGEST_SIZE
);
3231 for (i
= 0; i
< 2 * DIGEST_SIZE
; i
++)
3232 strpool
[poolptr
++] = (uint16_t)outbuf
[i
];
3234 memcpy(&strpool
[poolptr
], outbuf
, len
);
3239 #endif /* pdfTeX or e-pTeX or e-upTeX or XeTeX */
3242 /* Metafont/MetaPost fraction routines. Replaced either by assembler or C.
3243 The assembler syntax doesn't work on Solaris/x86. */
3245 #if defined (__sun__) || defined (__cplusplus)
3248 /* The assembler code is not PIC safe on i?86 so use C code. */
3249 #if defined (__PIC__) && defined (__i386__)
3252 #if defined(WIN32) && !defined(NO_MF_ASM) && !defined(__MINGW32__)
3253 #include "lib/mfmpw32.c"
3254 #elif defined (__i386__) && defined (__GNUC__) && !defined (NO_MF_ASM)
3255 #include "lib/mfmpi386.asm"
3257 /* Replace fixed-point fraction routines from mf.web and mp.web with
3258 Hobby's floating-point C code. */
3260 /****************************************************************
3261 Copyright 1990 - 1995 by AT&T Bell Laboratories.
3263 Permission to use, copy, modify, and distribute this software
3264 and its documentation for any purpose and without fee is hereby
3265 granted, provided that the above copyright notice appear in all
3266 copies and that both that the copyright notice and this
3267 permission notice and warranty disclaimer appear in supporting
3268 documentation, and that the names of AT&T Bell Laboratories or
3269 any of its entities not be used in advertising or publicity
3270 pertaining to distribution of the software without specific,
3271 written prior permission.
3273 AT&T disclaims all warranties with regard to this software,
3274 including all implied warranties of merchantability and fitness.
3275 In no event shall AT&T be liable for any special, indirect or
3276 consequential damages or any damages whatsoever resulting from
3277 loss of use, data or profits, whether in an action of contract,
3278 negligence or other tortious action, arising out of or in
3279 connection with the use or performance of this software.
3280 ****************************************************************/
3282 /**********************************************************
3283 The following is by John Hobby
3284 **********************************************************/
3288 /* These replacements for takefraction, makefraction, takescaled, makescaled
3289 run about 3 to 11 times faster than the standard versions on modern machines
3290 that have fast hardware for double-precision floating point. They should
3291 produce approximately correct results on all machines and agree exactly
3292 with the standard versions on machines that satisfy the following conditions:
3293 1. Doubles must have at least 46 mantissa bits; i.e., numbers expressible
3294 as n*2^k with abs(n)<2^46 should be representable.
3295 2. The following should hold for addition, subtraction, and multiplcation but
3296 not necessarily for division:
3297 A. If the true answer is between two representable numbers, the computed
3298 answer must be one of them.
3299 B. When the true answer is representable, this must be the computed result.
3300 3. Dividing one double by another should always produce a relative error of
3301 at most one part in 2^46. (This is why the mantissa requirement is
3302 46 bits instead of 45 bits.)
3303 3. In the absence of overflow, double-to-integer conversion should truncate
3304 toward zero and do this in an exact fashion.
3305 4. Integer-to-double convesion should produce exact results.
3306 5. Dividing one power of two by another should yield an exact result.
3307 6. ASCII to double conversion should be exact for integer values.
3308 7. Integer arithmetic must be done in the two's-complement system.
3310 #define ELGORDO 0x7fffffff
3311 #define TWEXP31 2147483648.0
3312 #define TWEXP28 268435456.0
3313 #define TWEXP16 65536.0
3314 #define TWEXP_16 (1.0/65536.0)
3315 #define TWEXP_28 (1.0/268435456.0)
3318 ztakefraction (integer p
, integer q
) /* Approximate p*q/2^28 */
3319 { register double d
;
3321 d
= (double)p
* (double)q
* TWEXP_28
;
3325 if (d
!=TWEXP31
|| (((p
&077777)*(q
&077777))&040000)==0)
3330 if (d
==i
&& (((p
&077777)*(q
&077777))&040000)!=0) --i
;
3334 if (d
!= -TWEXP31
|| ((-(p
&077777)*(q
&077777))&040000)==0)
3339 if (d
==i
&& ((-(p
&077777)*(q
&077777))&040000)!=0) ++i
;
3345 ztakescaled (integer p
, integer q
) /* Approximate p*q/2^16 */
3346 { register double d
;
3348 d
= (double)p
* (double)q
* TWEXP_16
;
3352 if (d
!=TWEXP31
|| (((p
&077777)*(q
&077777))&040000)==0)
3357 if (d
==i
&& (((p
&077777)*(q
&077777))&040000)!=0) --i
;
3361 if (d
!= -TWEXP31
|| ((-(p
&077777)*(q
&077777))&040000)==0)
3366 if (d
==i
&& ((-(p
&077777)*(q
&077777))&040000)!=0) ++i
;
3371 /* Note that d cannot exactly equal TWEXP31 when the overflow test is made
3372 because the exact value of p/q cannot be strictly between (2^31-1)/2^28
3373 and 8/1. No pair of integers less than 2^31 has such a ratio.
3376 zmakefraction (integer p
, integer q
) /* Approximate 2^28*p/q */
3377 { register double d
;
3380 if (q
==0) confusion(47);
3382 d
= TWEXP28
* (double)p
/(double)q
;
3385 if (d
>=TWEXP31
) {aritherror
=true; return ELGORDO
;}
3387 if (d
==i
&& ( ((q
>0 ? -q
: q
)&077777)
3388 * (((i
&037777)<<1)-1) & 04000)!=0) --i
;
3391 if (d
<= -TWEXP31
) {aritherror
=true; return -ELGORDO
;}
3393 if (d
==i
&& ( ((q
>0 ? q
: -q
)&077777)
3394 * (((i
&037777)<<1)+1) & 04000)!=0) ++i
;
3399 /* Note that d cannot exactly equal TWEXP31 when the overflow test is made
3400 because the exact value of p/q cannot be strictly between (2^31-1)/2^16
3401 and 2^15/1. No pair of integers less than 2^31 has such a ratio.
3404 zmakescaled (integer p
, integer q
) /* Approximate 2^16*p/q */
3405 { register double d
;
3408 if (q
==0) confusion(47);
3410 d
= TWEXP16
* (double)p
/(double)q
;
3413 if (d
>=TWEXP31
) {aritherror
=true; return ELGORDO
;}
3415 if (d
==i
&& ( ((q
>0 ? -q
: q
)&077777)
3416 * (((i
&037777)<<1)-1) & 04000)!=0) --i
;
3419 if (d
<= -TWEXP31
) {aritherror
=true; return -ELGORDO
;}
3421 if (d
==i
&& ( ((q
>0 ? q
: -q
)&077777)
3422 * (((i
&037777)<<1)+1) & 04000)!=0) ++i
;
3427 #endif /* not FIXPT */
3428 #endif /* not assembler */
3429 #endif /* not TeX, i.e., MF */
3432 /* On-line display routines for Metafont. Here we use a dispatch table
3433 indexed by the MFTERM or TERM environment variable to select the
3434 graphics routines appropriate to the user's terminal. stdout must be
3435 connected to a terminal for us to do any graphics. */
3451 /* Prototypes for Metafont display routines: mf_XXX_initscreen,
3452 mf_XXX_updatescreen, mf_XXX_blankrectangle, and mf_XXX_paintrow. */
3453 #include <window/mfdisplay.h>
3455 /* This variable, `mfwsw', contains the dispatch tables for each
3456 terminal. We map the Pascal calls to the routines `init_screen',
3457 `update_screen', `blank_rectangle', and `paint_row' into the
3458 appropriate entry point for the specific terminal that MF is being
3463 const char *mfwsw_type
; /* Name of terminal a la TERMCAP. */
3464 int (*mfwsw_initscreen
) (void);
3465 void (*mfwsw_updatescrn
) (void);
3466 void (*mfwsw_blankrect
) (screencol
, screencol
, screenrow
, screenrow
);
3467 void (*mfwsw_paintrow
) (screenrow
, pixelcolor
, transspec
, screencol
);
3471 { "amiterm", mf_amiga_initscreen
, mf_amiga_updatescreen
,
3472 mf_amiga_blankrectangle
, mf_amiga_paintrow
},
3475 { "epsf", mf_epsf_initscreen
, mf_epsf_updatescreen
,
3476 mf_epsf_blankrectangle
, mf_epsf_paintrow
},
3479 { "hp2627", mf_hp2627_initscreen
, mf_hp2627_updatescreen
,
3480 mf_hp2627_blankrectangle
, mf_hp2627_paintrow
},
3483 { "mftalk", mf_mftalk_initscreen
, mf_mftalk_updatescreen
,
3484 mf_mftalk_blankrectangle
, mf_mftalk_paintrow
},
3487 { "next", mf_next_initscreen
, mf_next_updatescreen
,
3488 mf_next_blankrectangle
, mf_next_paintrow
},
3491 { "regis", mf_regis_initscreen
, mf_regis_updatescreen
,
3492 mf_regis_blankrectangle
, mf_regis_paintrow
},
3495 { "sun", mf_sun_initscreen
, mf_sun_updatescreen
,
3496 mf_sun_blankrectangle
, mf_sun_paintrow
},
3499 { "tek", mf_tektronix_initscreen
, mf_tektronix_updatescreen
,
3500 mf_tektronix_blankrectangle
, mf_tektronix_paintrow
},
3503 { "uniterm", mf_uniterm_initscreen
, mf_uniterm_updatescreen
,
3504 mf_uniterm_blankrectangle
, mf_uniterm_paintrow
},
3507 { "win32term", mf_win32_initscreen
, mf_win32_updatescreen
,
3508 mf_win32_blankrectangle
, mf_win32_paintrow
},
3511 { "xterm", mf_x11_initscreen
, mf_x11_updatescreen
,
3512 mf_x11_blankrectangle
, mf_x11_paintrow
},
3515 /* Always support this. */
3516 { "trap", mf_trap_initscreen
, mf_trap_updatescreen
,
3517 mf_trap_blankrectangle
, mf_trap_paintrow
},
3519 /* Finally, we must have an entry with a terminal type of NULL. */
3520 { NULL
, NULL
, NULL
, NULL
, NULL
}
3522 }; /* End of the array initialization. */
3525 /* This is a pointer to the mfwsw[] entry that we find. */
3526 static struct mfwin_sw
*mfwp
;
3529 /* The following are routines that just jump to the correct
3530 terminal-specific graphics code. If none of the routines in the
3531 dispatch table exist, or they fail, we produce trap-compatible
3532 output, i.e., the same words and punctuation that the unchanged
3533 mf.web would produce. */
3536 /* This returns true if we can do window operations, else false. */
3542 /* If MFTERM is set, use it. */
3543 const_string tty_type
= kpse_var_value ("MFTERM");
3545 if (tty_type
== NULL
)
3548 tty_type
= "amiterm";
3549 #elif defined (WIN32)
3550 tty_type
= "win32term";
3551 #elif defined (OS2) || defined (__DJGPP__) /* not AMIGA nor WIN32 */
3552 tty_type
= "mftalk";
3553 #else /* not (OS2 or WIN32 or __DJGPP__ or AMIGA) */
3554 /* If DISPLAY is set, we are X11; otherwise, who knows. */
3555 boolean have_display
= getenv ("DISPLAY") != NULL
;
3556 tty_type
= have_display
? "xterm" : getenv ("TERM");
3558 /* If we don't know what kind of terminal this is, or if Metafont
3559 isn't being run interactively, don't do any online output. */
3560 if (tty_type
== NULL
3561 || (!STREQ (tty_type
, "trap") && !isatty (fileno (stdout
))))
3563 #endif /* not (OS2 or WIN32 or __DJGPP__ or AMIGA) */
3566 /* Test each of the terminals given in `mfwsw' against the terminal
3567 type, and take the first one that matches, or if the user is running
3568 under Emacs, the first one. */
3569 for (mfwp
= mfwsw
; mfwp
->mfwsw_type
!= NULL
; mfwp
++) {
3570 if (!strncmp (mfwp
->mfwsw_type
, tty_type
, strlen (mfwp
->mfwsw_type
))
3571 || STREQ (tty_type
, "emacs")) {
3572 if (mfwp
->mfwsw_initscreen
) {
3573 retval
= (*mfwp
->mfwsw_initscreen
) ();
3575 Sleep(1000); /* Wait for opening a window */
3580 fprintf (stderr
, "mf: Couldn't initialize online display for `%s'.\n",
3587 /* The current terminal type wasn't found in any of the entries, or
3588 initalization failed, so silently give up, assuming that the user
3589 isn't on a terminal that supports graphic output. */
3594 /* Make sure everything is visible. */
3599 if (mfwp
->mfwsw_updatescrn
)
3600 (*mfwp
->mfwsw_updatescrn
) ();
3604 /* This sets the rectangle bounded by ([left,right], [top,bottom]) to
3605 the background color. */
3608 blankrectangle (screencol left
, screencol right
,
3609 screenrow top
, screenrow bottom
)
3611 if (mfwp
->mfwsw_blankrect
)
3612 (*mfwp
->mfwsw_blankrect
) (left
, right
, top
, bottom
);
3616 /* This paints ROW, starting with the color INIT_COLOR.
3617 TRANSITION_VECTOR then specifies the length of the run; then we
3618 switch colors. This goes on for VECTOR_SIZE transitions. */
3621 paintrow (screenrow row
, pixelcolor init_color
,
3622 transspec transition_vector
, screencol vector_size
)
3624 if (mfwp
->mfwsw_paintrow
)
3625 (*mfwp
->mfwsw_paintrow
) (row
, init_color
, transition_vector
, vector_size
);