sync with experimental
[luatex.git] / source / texk / web2c / luatexdir / luatex.c
blob7e06c9388857cf10c466010c373f1ecec161b9e4
1 /* luatex.c: Hand-coded routines for TeX or Metafont in C. Originally
2 written by Tim Morgan, drawing from other Unix ports of TeX. This is
3 a collection of miscellany, everything that's easier (or only
4 possible) to do in C.
6 This file is public domain. */
8 /* This file is used to create texextra.c etc., with this line
9 changed to include texd.h or mfd.h. The ?d.h file is what
10 #defines TeX or MF, which avoids the need for a special
11 Makefile rule. */
13 /* We |#define DLLPROC| in order to build LuaTeX and LuajitTeX as DLL
14 for W32TeX. */
15 #if defined LuajitTeX
16 #define DLLPROC dllluajittexmain
17 #else
18 #define DLLPROC dllluatexmain
19 #endif
21 #include "ptexlib.h"
22 #include "luatex.h"
23 #include "lua/luatex-api.h"
25 #include "luatex_svnversion.h"
29 #define TeX
31 int luatex_version = 98; /* \.{\\luatexversion} */
32 int luatex_revision = '4'; /* \.{\\luatexrevision} */
33 int luatex_date_info = 2016090500; /* the compile date is now hardwired */
34 const char *luatex_version_string = "0.98.4";
35 const char *engine_name = my_name; /* the name of this engine */
37 #include <kpathsea/c-ctype.h>
38 #include <kpathsea/line.h>
39 #include <kpathsea/readable.h>
40 #include <kpathsea/variable.h>
41 #include <kpathsea/absolute.h>
42 #ifdef WIN32
43 #include <kpathsea/concatn.h>
44 #endif
46 #ifdef _MSC_VER
47 #undef timezone
48 #endif
50 #include <time.h> /* For `struct tm'. */
51 #if defined (HAVE_SYS_TIME_H)
52 # include <sys/time.h>
53 #elif defined (HAVE_SYS_TIMEB_H)
54 # include <sys/timeb.h>
55 #endif
57 #if defined(__STDC__)
58 # include <locale.h>
59 #endif
61 #include <signal.h> /* Catch interrupts. */
64 /* {tex,mf}d.h defines TeX, MF, INI, and other such symbols.
65 Unfortunately there's no way to get the banner into this code, so
66 just repeat the text. */
67 #define edit_var "TEXEDIT"
69 /* Shell escape.
71 If shellenabledp == 0, all shell escapes are forbidden.
72 If (shellenabledp == 1 && restrictedshell == 0), any command
73 is allowed for a shell escape.
74 If (shellenabledp == 1 && restrictedshell == 1), only commands
75 given in the configuration file as
76 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun,...
77 (no spaces between commands) in texmf.cnf are allowed for a shell
78 escape in a restricted form: command name and arguments should be
79 separated by a white space. The first word should be a command
80 name. The quotation character for an argument with spaces,
81 including a pathname, should be ". ' should not be used.
83 Internally, all arguments are quoted by ' (Unix) or " (Windows)
84 before calling the system() function in order to forbid execution
85 of any embedded command.
87 If the --shell-escape option is given, we set
88 shellenabledp = 1 and restrictedshell = 0, i.e., any command is allowed.
89 If the --shell-restricted option is given, we set
90 shellenabledp = 1 and restrictedshell = 1, i.e., only given cmds allowed.
91 If the --no-shell-escape option is given, we set
92 shellenabledp = -1 (and restrictedshell is irrelevant).
93 If none of these option are given, there are three cases:
94 (1) In the case where
95 shell_escape = y or
96 shell_escape = t or
97 shell_escape = 1
98 it becomes shellenabledp = 1 and restrictedshell = 0,
99 that is, any command is allowed.
100 (2) In the case where
101 shell_escape = p
102 it becomes shellenabledp = 1 and restrictedshell = 1,
103 that is, restricted shell escape is allowed.
104 (3) In all other cases, shellenabledp = 0, that is, shell
105 escape is forbidden. The value of restrictedshell is
106 irrelevant if shellenabledp == 0.
109 #ifdef TeX
111 /* cmdlist is a list of allowed commands which are given like this:
112 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun
113 in texmf.cnf. */
115 static char **cmdlist = NULL;
117 void mk_shellcmdlist(char *v)
119 char **p;
120 char *q, *r;
121 size_t n;
123 q = v;
124 n = 1;
126 /* analyze the variable shell_escape_commands = foo,bar,...
127 spaces before and after (,) are not allowed. */
129 while ((r = strchr(q, ',')) != 0) {
130 n++;
131 q = r + 1;
133 if (*q)
134 n++;
135 cmdlist = (char **) xmalloc(n * sizeof (char *));
136 p = cmdlist;
137 q = v;
138 while ((r = strchr(q, ',')) != 0) {
139 *r = '\0';
140 *p++ = xstrdup (q);
141 q = r + 1;
143 if (*q)
144 *p++ = xstrdup (q);
145 *p = NULL;
148 /* Called from maininit. Not static because also called from
149 luatexdir/lua/luainit.c. */
152 In order to avoid all kind of time code in the backend code we use a function.
153 The start time can be overloaded in several ways:
155 (1) By setting the environmment variable SOURCE_DATE_EPOCH. This will influence
156 the tex parameters, random seed, pdf timestamp and pdf id that is derived
157 from the time. This variable is consulted when the kpse library is enabled
158 which is analogue to other properties.
160 (2) By setting the texconfig.start_time variable (as with other variables
161 we use the internal name there). This has the same effect as (1) and is
162 provided for when kpse is not used to set these variables or when an overloaded
163 is wanted. This is analogue to other properties.
165 When an utc time is needed one can provide the flag --utc. This property is
166 independent of this time hackery. This flag has a corresponding texconfig
167 option use_utc_time.
169 To some extend a cleaner solution would be to have a flag that disables all
170 variable data in one go (like filenames and so) but we just follow the method
171 implemented in pdftex where primitives are used tod disable it.
175 static int start_time = -1;
177 int get_start_time(void) {
178 if (start_time < 0) {
179 start_time = time((time_t *) NULL);
181 return start_time;
185 This one is called as part of the kpse initialization which only happens
186 when this library is enabled.
188 #if defined(_MSC_VER)
189 #define strtoull _strtoui64
190 #endif
192 void init_start_time(void) {
193 if (start_time < 0) {
194 unsigned long long epoch;
195 char *endptr;
197 We don't really care how kpse sets up this variable but we prefer to
198 just use its abstract interface.
200 /* char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); */
201 char *source_date_epoch = kpse_var_value("SOURCE_DATE_EPOCH");
202 if (source_date_epoch && source_date_epoch != '\0' ) {
203 errno = 0;
204 epoch = strtoull(source_date_epoch, &endptr, 10);
205 if (epoch < 0 || *endptr != '\0' || errno != 0) {
206 epoch = 0;
208 #if defined(_MSC_VER)
209 /* We avoid to crash if users test a large value which is not
210 * supported by Visual Studio 2010:
211 * a later time than 3001/01/01 20:59:59.
213 if (epoch > 32535291599ULL)
214 epoch = 32535291599ULL;
215 #endif
216 start_time = epoch;
222 This one is used to fetch a value from texconfig which can also be used to
223 set properties. This might come in handy when one has other ways to get date
224 info in the pdf file.
227 void set_start_time(int s) {
228 if (s >= 0) {
229 start_time = s ;
233 void init_shell_escape(void)
235 if (shellenabledp < 0) { /* --no-shell-escape on cmd line */
236 shellenabledp = 0;
238 } else {
239 if (shellenabledp == 0) { /* no shell options on cmd line, check cnf */
240 char *v1 = kpse_var_value("shell_escape");
241 if (v1) {
242 if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
243 shellenabledp = 1;
244 } else if (*v1 == 'p') {
245 shellenabledp = 1;
246 restrictedshell = 1;
248 free(v1);
252 /* If shell escapes are restricted, get allowed cmds from cnf. */
253 if (shellenabledp && restrictedshell == 1) {
254 char *v2 = kpse_var_value("shell_escape_commands");
255 if (v2) {
256 mk_shellcmdlist(v2);
257 free(v2);
263 # ifdef WIN32
264 # define QUOTE '"'
265 # else
266 # define QUOTE '\''
267 # endif
269 # if 0
270 # ifdef WIN32
271 static int char_needs_quote(int c)
273 /* special characters of cmd.exe */
275 return (c == '&' || c == '|' || c == '%' || c == '<' ||
276 c == '>' || c == ';' || c == ',' || c == '(' || c == ')');
278 # endif
279 # endif
281 static int Isspace(char c)
283 return (c == ' ' || c == '\t');
286 /* return values:
287 -1 : invalid quotation of an argument
288 0 : command is not allowed
289 2 : restricted shell escape, CMD is allowed.
291 We set *SAFECMD to a safely-quoted version of *CMD; this is what
292 should get executed. And we set CMDNAME to its first word; this is
293 what is checked against the shell_escape_commands list. */
295 int shell_cmd_is_allowed(const char *cmd, char **safecmd, char **cmdname)
297 char **p;
298 char *buf;
299 char *c, *d;
300 const char *s;
301 int pre;
302 unsigned spaces;
303 int allow = 0;
305 /* pre == 1 means that the previous character is a white space
306 pre == 0 means that the previous character is not a white space */
307 buf = xmalloc(strlen(cmd) + 1);
308 strcpy(buf, cmd);
309 c = buf;
310 while (Isspace(*c))
311 c++;
312 d = c;
313 while (!Isspace(*d) && *d)
314 d++;
315 *d = '\0';
317 /* *cmdname is the first word of the command line. For example,
318 *cmdname == "kpsewhich" for
319 \write18{kpsewhich --progname=dvipdfm --format="other text files" config}
321 *cmdname = xstrdup(c);
322 free(buf);
324 /* Is *cmdname listed in a texmf.cnf vriable as
325 shell_escape_commands = foo,bar,... ? */
326 p = cmdlist;
327 if (p) {
328 while (*p) {
329 if (strcmp(*p, *cmdname) == 0) {
330 /* *cmdname is found in the list, so restricted shell escape
331 is allowed */
332 allow = 2;
333 break;
335 p++;
338 if (allow == 2) {
339 spaces = 0;
340 for (s = cmd; *s; s++) {
341 if (Isspace(*s))
342 spaces++;
345 /* allocate enough memory (too much?) */
346 # ifdef WIN32
347 *safecmd = xmalloc(2 * strlen(cmd) + 3 + 2 * spaces);
348 # else
349 *safecmd = xmalloc(strlen(cmd) + 3 + 2 * spaces);
350 # endif
352 /* make a safe command line *safecmd */
353 s = cmd;
354 while (Isspace(*s))
355 s++;
356 d = *safecmd;
357 while (!Isspace(*s) && *s)
358 *d++ = *s++;
360 pre = 1;
361 while (*s) {
362 /* Quotation given by a user. " should always be used; we
363 transform it below. On Unix, if ' is used, simply immediately
364 return a quotation error. */
365 if (*s == '\'') {
366 return -1;
369 if (*s == '"') {
370 /* All arguments are quoted as 'foo' (Unix) or "foo" (Windows)
371 before calling system(). Therefore closing QUOTE is necessary
372 if the previous character is not a white space.
373 example:
374 --format="other text files" becomes
375 '--format=''other text files' (Unix)
376 "--format"="other text files" (Windows) */
378 if (pre == 0) {
379 # ifdef WIN32
380 if (*(s-1) == '=') {
381 *(d-1) = QUOTE;
382 *d++ = '=';
383 } else {
384 *d++ = QUOTE;
386 # else
387 *d++ = QUOTE;
388 # endif
391 pre = 0;
392 /* output the quotation mark for the quoted argument */
393 *d++ = QUOTE;
394 s++;
396 while (*s != '"') {
397 /* Illegal use of ', or closing quotation mark is missing */
398 if (*s == '\'' || *s == '\0')
399 return -1;
400 # if 0
401 # ifdef WIN32
402 if (char_needs_quote(*s))
403 *d++ = '^';
404 # endif
405 # endif
406 *d++ = *s++;
409 /* Closing quotation mark will be output afterwards, so
410 we do nothing here */
411 s++;
413 /* The character after the closing quotation mark
414 should be a white space or NULL */
415 if (!Isspace(*s) && *s)
416 return -1;
418 /* Beginning of a usual argument */
419 } else if (pre == 1 && !Isspace(*s)) {
420 pre = 0;
421 *d++ = QUOTE;
422 # if 0
423 # ifdef WIN32
424 if (char_needs_quote(*s))
425 *d++ = '^';
426 # endif
427 # endif
428 *d++ = *s++;
429 /* Ending of a usual argument */
431 } else if (pre == 0 && Isspace(*s)) {
432 pre = 1;
433 /* Closing quotation mark */
434 *d++ = QUOTE;
435 *d++ = *s++;
436 } else {
437 /* Copy a character from cmd to *safecmd. */
438 # if 0
439 # ifdef WIN32
440 if (char_needs_quote(*s))
441 *d++ = '^';
442 # endif
443 # endif
444 *d++ = *s++;
447 /* End of the command line */
448 if (pre == 0) {
449 *d++ = QUOTE;
451 *d = '\0';
452 #ifdef WIN32
454 char *p, *q, *r;
455 p = *safecmd;
456 if (strlen (p) > 2 && p[1] == ':' && !IS_DIR_SEP (p[2])) {
457 q = xmalloc (strlen (p) + 2);
458 q[0] = p[0];
459 q[1] = p[1];
460 q[2] = '/';
461 q[3] = '\0';
462 strcat (q, (p + 2));
463 free (*safecmd);
464 *safecmd = q;
465 } else if (!IS_DIR_SEP (p[0]) && !(p[1] == ':' && IS_DIR_SEP (p[2]))) {
466 p = kpse_var_value ("SELFAUTOLOC");
467 if (p) {
468 r = *safecmd;
469 while (*r && !Isspace(*r))
470 r++;
471 if (*r == '\0')
472 q = concatn ("\"", p, "/", *safecmd, "\"", NULL);
473 else {
474 *r = '\0';
475 r++;
476 while (*r && Isspace(*r))
477 r++;
478 if (*r)
479 q = concatn ("\"", p, "/", *safecmd, "\" ", r, NULL);
480 else
481 q = concatn ("\"", p, "/", *safecmd, "\"", NULL);
483 free (p);
484 free (*safecmd);
485 *safecmd = q;
489 #endif
492 return allow;
495 #endif
498 /* What we were invoked as and with. */
499 char **argv;
500 int argc;
502 /* The C version of what might wind up in |TEX_format_default|. */
503 string dump_name;
505 /* The C version of the jobname, if given. */
506 const_string c_job_name;
508 const char *luatex_banner;
510 #ifdef _MSC_VER
511 /* Invalid parameter handler */
512 static void myInvalidParameterHandler(const wchar_t * expression,
513 const wchar_t * function,
514 const wchar_t * file,
515 unsigned int line,
516 uintptr_t pReserved)
519 printf(L"Invalid parameter detected in function %s."
520 L" File: %s Line: %d\n", function, file, line);
521 printf(L"Expression: %s\n", expression);
524 I return silently to avoid an exit with the error 0xc0000417
525 (invalid parameter) when we use non-embedded fonts in luatex-ja,
526 which works without any problem on Unix systems.
527 I hope it is not dangerous.
529 return;
531 #endif
533 /* The entry point: set up for reading the command line, which will
534 happen in `topenin', then call the main body. */
537 #if defined(DLLPROC)
538 DLLPROC (int ac, string *av)
539 #else
540 main (int ac, string *av)
541 #endif
543 # ifdef __EMX__
544 _wildcard(&ac, &av);
545 _response(&ac, &av);
546 # endif
548 # ifdef WIN32
549 # ifdef _MSC_VER
550 _set_invalid_parameter_handler(myInvalidParameterHandler);
551 # endif
552 av[0] = kpse_program_basename (av[0]);
553 _setmaxstdio(2048);
555 * We choose to crash for fatal errors
556 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
558 setmode(fileno(stdin), _O_BINARY);
559 # endif
561 lua_initialize(ac, av);
563 # ifdef WIN32
564 if (ac > 1) {
565 char *pp;
566 if ((strlen(av[ac-1]) > 2) &&
567 isalpha(av[ac-1][0]) &&
568 (av[ac-1][1] == ':') &&
569 (av[ac-1][2] == '\\')) {
570 for (pp=av[ac-1]+2; *pp; pp++) {
571 if (IS_KANJI(pp)) {
572 pp++;
573 continue;
575 if (*pp == '\\')
576 *pp = '/';
580 # endif
582 /* Call the real main program. */
583 main_body();
585 return EXIT_SUCCESS;
589 /* This is supposed to ``open the terminal for input'', but what we
590 really do is copy command line arguments into TeX's or Metafont's
591 buffer, so they can handle them. If nothing is available, or we've
592 been called already (and hence, argc==0), we return with
593 `last=first'. */
595 void topenin(void)
597 int i;
600 buffer[first] = 0; /* In case there are no arguments. */
602 if (optind < argc) { /* We have command line arguments. */
603 int k = first;
604 for (i = optind; i < argc; i++) {
605 char *ptr = &(argv[i][0]);
606 /* Don't use strcat, since in Aleph the buffer elements aren't
607 single bytes. */
608 while (*ptr) {
609 buffer[k++] = (packed_ASCII_code) * (ptr++);
611 buffer[k++] = ' ';
613 argc = 0; /* Don't do this again. */
614 buffer[k] = 0;
617 /* Find the end of the buffer. */
618 for (last = first; buffer[last]; ++last);
620 /* Make `last' be one past the last non-blank character in `buffer'. */
621 /* ??? The test for '\r' should not be necessary. */
622 for (--last; last >= first
623 && ISBLANK(buffer[last]) && buffer[last] != '\r'; --last);
624 last++;
626 /* One more time, this time converting to TeX's internal character
627 representation. */
630 /* IPC for TeX. By Tom Rokicki for the NeXT; it makes TeX ship out the
631 DVI file in a pipe to TeXView so that the output can be displayed
632 incrementally. Shamim Mohamed adapted it for Web2c. */
633 #if defined (TeX) && defined (IPC)
635 #ifdef WIN32
636 #undef _WINSOCKAPI_
637 #include <winsock2.h>
638 #else
639 #include <sys/socket.h>
640 #include <fcntl.h>
641 #ifndef O_NONBLOCK /* POSIX */
642 #ifdef O_NDELAY /* BSD */
643 #define O_NONBLOCK O_NDELAY
644 #elif defined(O_FNDELAY) /* NeXT */
645 #define O_NONBLOCK O_FNDELAY
646 #else
647 what the fcntl? cannot implement IPC without equivalent for O_NONBLOCK.
648 #endif
649 #endif /* no O_NONBLOCK */
650 #endif /* !WIN32 */
652 #ifdef WIN32
653 # define IPC_AF AF_INET
654 # ifndef IPC_LOCAL_HOST
655 # define IPC_LOCAL_HOST "127.0.0.1"
656 # define FIXED_PORT (unsigned short)4242
657 # endif
658 #else
659 # define IPC_AF AF_UNIX
660 # ifndef IPC_PIPE_NAME /* $HOME is prepended to this. */
661 # define IPC_PIPE_NAME "/.TeXview_Pipe"
662 # endif
663 #endif
664 #ifndef IPC_SERVER_CMD /* Command to run to start the server. */
665 # ifdef WIN32
666 # define IPC_SERVER_CMD "texview.exe"
667 # else
668 # define IPC_SERVER_CMD "open `which TeXview`"
669 # endif
670 #endif
672 struct msg
674 int namelength; /* length of auxiliary data */
675 int eof; /* new eof for dvi file */
676 #if 0 /* see usage of struct msg below */
677 char more_data[0]; /* where the rest of the stuff goes */
678 #endif
681 static struct sockaddr *ipc_addr;
682 static int ipc_addr_len;
684 static int
685 ipc_make_name (void)
687 if (ipc_addr_len == 0) {
688 #ifdef WIN32
689 unsigned long remote_addr = inet_addr(IPC_LOCAL_HOST);
690 if (remote_addr != INADDR_NONE) {
691 struct sockaddr_in *ipc_sin_addr = xmalloc (sizeof (struct sockaddr_in));
692 ipc_sin_addr->sin_family = AF_INET;
693 ipc_sin_addr->sin_addr.s_addr = remote_addr;
694 ipc_sin_addr->sin_port = htons (FIXED_PORT);
695 ipc_addr = ((struct sockaddr *) ipc_sin_addr);
696 ipc_addr_len = sizeof(struct sockaddr_in);
698 #else
699 string s = getenv ("HOME");
700 if (s) {
701 char *ipc_name;
702 ipc_addr = xmalloc (strlen (s) + 40);
703 ipc_addr->sa_family = 0;
704 ipc_name = ipc_addr->sa_data;
705 strcpy (ipc_name, s);
706 strcat (ipc_name, IPC_PIPE_NAME);
707 ipc_addr_len = strlen (ipc_name) + 3;
709 #endif
711 return ipc_addr_len;
714 static int sock = -1;
716 #ifdef WIN32
717 # define CLOSE_SOCKET(s) closesocket (s); WSACleanup ()
718 #else
719 # define CLOSE_SOCKET(s) close (s)
720 #endif
722 static int
723 ipc_is_open (void)
725 return sock != -1;
728 static void
729 ipc_open_out (void) {
730 #ifdef WIN32
731 struct WSAData wsaData;
732 int nCode;
733 unsigned long mode = 1;
734 #endif
735 #ifdef IPC_DEBUG
736 fputs ("tex: Opening socket for IPC output ...\n", stderr);
737 #endif
738 if (sock != -1) {
739 return;
742 #ifdef WIN32
743 if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) {
744 fprintf(stderr,"WSAStartup() returned error code %d.\n", nCode);
745 return;
747 #endif
749 if (ipc_make_name () <= 0)
750 return;
752 sock = socket (IPC_AF, SOCK_STREAM, 0);
753 #ifdef IPC_DEBUG
754 if(sock != -1)
755 fprintf(stderr, "tex: Socket handle is %d\n", sock);
756 else
757 fprintf(stderr, "tex: Socket is invalid.\n");
758 #endif
760 if (sock != -1) {
761 if (connect (sock, ipc_addr, ipc_addr_len) != 0 ||
762 #ifdef WIN32
763 ioctlsocket (sock, FIONBIO, &mode) < 0
764 #else
765 fcntl (sock, F_SETFL, O_NONBLOCK) < 0
766 #endif
768 CLOSE_SOCKET (sock);
769 sock = -1;
770 #ifdef IPC_DEBUG
771 fputs ("tex: IPC socket cannot be connected.\n", stderr);
772 fputs ("tex: Socket is closed.\n", stderr);
773 #endif
774 return;
776 #ifdef IPC_DEBUG
777 fputs ("tex: Successfully opened IPC socket.\n", stderr);
778 #endif
782 static void
783 ipc_close_out (void)
785 #ifdef IPC_DEBUG
786 fputs ("tex: Closing output socket ...\n", stderr);
787 #endif
788 if (ipc_is_open ()) {
789 CLOSE_SOCKET (sock);
790 sock = -1;
794 static void
795 ipc_snd (int n, int is_eof, char *data)
797 struct
799 struct msg msg;
800 char more_data[1024];
801 } ourmsg;
803 if (!ipc_is_open ()) {
804 return;
807 #ifdef IPC_DEBUG
808 fprintf(stderr, "%d\t%d\n", ourmsg.msg.namelength, ourmsg.msg.eof);
809 fputs ("tex: Sending message to socket ...\n", stderr);
810 #endif
811 ourmsg.msg.namelength = n;
812 ourmsg.msg.eof = is_eof;
813 if (n) {
814 strcpy (ourmsg.more_data, data);
816 n += sizeof (struct msg);
817 #ifdef IPC_DEBUG
818 fprintf(stderr, "%d\t%d\n", ourmsg.msg.namelength, ourmsg.msg.eof);
819 fputs ("tex: Writing to socket...\n", stderr);
820 #endif
821 #if defined(WIN32)
822 if (send (sock, (char *)&ourmsg, n, 0) != n) {
823 #else
824 if (write (sock, &ourmsg, n) != n) {
825 #endif
826 ipc_close_out ();
828 #ifdef IPC_DEBUG
829 fputs ("tex: IPC message sent.\n", stderr);
830 #endif
833 /* This routine notifies the server if there is an eof, or the filename
834 if a new DVI file is starting. This is the routine called by TeX.
835 Aleph defines str_start(#) as str_start_ar[# - too_big_char], with
836 too_big_char = biggest_char + 1 = 65536 (omstr.ch). */
838 void
839 ipcpage (int is_eof)
841 static boolean begun = false;
842 unsigned len = 0;
843 string p = NULL;
845 if (!begun) {
846 string name; /* Just the filename. */
847 string cwd = xgetcwd ();
849 ipc_open_out ();
851 /* Have to pass whole filename to the other end, since it may have
852 been started up and running as a daemon, e.g., as with the NeXT
853 preview program. */
854 name = static_pdf->file_name;
855 p = concat3 (cwd, DIR_SEP_STRING, name);
856 free (cwd);
857 free (name);
859 #if defined (WIN32)
860 { char *q;
861 for (q = p; *q; q++) {
862 if (*q == '\\')
863 *q = '/';
864 else if (IS_KANJI(q))
865 q++;
868 #endif
869 len = strlen(p);
870 begun = true;
872 ipc_snd (len, is_eof, p);
874 if (p)
875 free (p);
877 #endif /* TeX && IPC */
879 /* Normalize quoting of filename -- that is, only quote if there is a space,
880 and always use the quote-name-quote style. */
881 string normalize_quotes(const_string name, const_string mesg)
883 boolean quoted = false;
884 boolean must_quote = (strchr(name, ' ') != NULL);
885 /* Leave room for quotes and NUL. */
886 string ret = (string) xmalloc((unsigned) strlen(name) + 3);
887 string p;
888 const_string q;
889 p = ret;
890 if (must_quote)
891 *p++ = '"';
892 for (q = name; *q; q++) {
893 if (*q == '"')
894 quoted = !quoted;
895 else
896 *p++ = *q;
898 if (must_quote)
899 *p++ = '"';
900 *p = '\0';
901 if (quoted) {
902 fprintf(stderr, "! Unbalanced quotes in %s %s\n", mesg, name);
903 uexit(1);
905 return ret;
909 /* All our interrupt handler has to do is set TeX's or Metafont's global
910 variable `interrupt'; then they will do everything needed. */
911 #ifdef WIN32
912 /* Win32 doesn't set SIGINT ... */
913 static BOOL WINAPI catch_interrupt(DWORD arg)
915 switch (arg) {
916 case CTRL_C_EVENT:
917 case CTRL_BREAK_EVENT:
918 interrupt = 1;
919 return TRUE;
920 default:
921 /* No need to set interrupt as we are exiting anyway */
922 return FALSE;
925 #else /* not WIN32 */
926 static RETSIGTYPE catch_interrupt(int arg)
928 (void) arg;
929 interrupt = 1;
930 # ifdef OS2
931 (void) signal(SIGINT, SIG_ACK);
932 # else
933 (void) signal(SIGINT, catch_interrupt);
934 # endif /* not OS2 */
936 #endif /* not WIN32 */
938 /* Besides getting the date and time here, we also set up the interrupt
939 handler, for no particularly good reason. It's just that since the
940 `fix_date_and_time' routine is called early on (section 1337 in TeX,
941 ``Get the first line of input and prepare to start''), this is as
942 good a place as any. */
944 void get_date_and_time(int *minutes, int *day, int *month, int *year)
946 time_t myclock = get_start_time();
947 struct tm *tmptr ;
948 if (utc_option) {
949 tmptr = gmtime(&myclock);
950 } else {
951 tmptr = localtime(&myclock);
954 *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
955 *day = tmptr->tm_mday;
956 *month = tmptr->tm_mon + 1;
957 *year = tmptr->tm_year + 1900;
960 #ifdef SA_INTERRUPT
961 /* Under SunOS 4.1.x, the default action after return from the
962 signal handler is to restart the I/O if nothing has been
963 transferred. The effect on TeX is that interrupts are ignored if
964 we are waiting for input. The following tells the system to
965 return EINTR from read() in this case. From ken@cs.toronto.edu. */
967 struct sigaction a, oa;
969 a.sa_handler = catch_interrupt;
970 sigemptyset(&a.sa_mask);
971 sigaddset(&a.sa_mask, SIGINT);
972 a.sa_flags = SA_INTERRUPT;
973 sigaction(SIGINT, &a, &oa);
974 if (oa.sa_handler != SIG_DFL)
975 sigaction(SIGINT, &oa, (struct sigaction *) 0);
976 #else /* no SA_INTERRUPT */
977 # ifdef WIN32
978 SetConsoleCtrlHandler(catch_interrupt, TRUE);
979 # else /* not WIN32 */
980 RETSIGTYPE(*old_handler) (int);
982 old_handler = signal(SIGINT, catch_interrupt);
983 if (old_handler != SIG_DFL)
984 signal(SIGINT, old_handler);
985 # endif /* not WIN32 */
986 #endif /* no SA_INTERRUPT */
991 Getting a high resolution time.
993 void get_seconds_and_micros(int *seconds, int *micros)
995 #if defined (HAVE_GETTIMEOFDAY)
996 struct timeval tv;
997 gettimeofday(&tv, NULL);
998 *seconds = (int)tv.tv_sec;
999 *micros = (int)tv.tv_usec;
1000 #elif defined (HAVE_FTIME)
1001 struct timeb tb;
1002 ftime(&tb);
1003 *seconds = tb.time;
1004 *micros = tb.millitm * 1000;
1005 #else
1006 time_t myclock = time((time_t *) NULL);
1007 *seconds = (int) myclock;
1008 *micros = 0;
1009 #endif
1013 Generating a better seed numbers
1015 int getrandomseed(void)
1017 #if defined (HAVE_GETTIMEOFDAY)
1018 struct timeval tv;
1019 gettimeofday(&tv, NULL);
1020 return (int)(tv.tv_usec + 1000000 * tv.tv_usec);
1021 #elif defined (HAVE_FTIME)
1022 struct timeb tb;
1023 ftime(&tb);
1024 return (tb.millitm + 1000 * tb.time);
1025 #else
1026 time_t myclock = get_start_time((time_t *) NULL);
1027 struct tm *tmptr ;
1028 if (utc_option) {
1029 tmptr = gmtime(&myclock);
1030 } else {
1031 tmptr = localtime(&myclock);
1033 return (tmptr->tm_sec + 60 * (tmptr->tm_min + 60 * tmptr->tm_hour));
1034 #endif
1037 /* Read a line of input as efficiently as possible while still looking
1038 like Pascal. We set `last' to `first' and return `false' if we get
1039 to eof. Otherwise, we return `true' and set last = first +
1040 length(line except trailing whitespace). */
1042 boolean input_line(FILE * f)
1044 int i = EOF;
1046 #ifdef WIN32
1047 if (f != Poptr && fileno (f) != fileno (stdin)) {
1048 long position = ftell (f);
1050 if (position == 0L) { /* Detect and skip Byte order marks. */
1051 int k1 = getc (f);
1053 if (k1 != 0xff && k1 != 0xfe && k1 != 0xef)
1054 rewind (f);
1055 else {
1056 int k2 = getc (f);
1058 if (k2 != 0xff && k2 != 0xfe && k2 != 0xbb)
1059 rewind (f);
1060 else if ((k1 == 0xff && k2 == 0xfe) || /* UTF-16(LE) */
1061 (k1 == 0xfe && k2 == 0xff)) /* UTF-16(BE) */
1063 else {
1064 int k3 = getc (f);
1066 if (k1 == 0xef && k2 == 0xbb && k3 == 0xbf) /* UTF-8 */
1068 else
1069 rewind (f);
1074 #endif
1075 /* Recognize either LF or CR as a line terminator. */
1076 last = first;
1077 while (last < buf_size && (i = getc(f)) != EOF && i != '\n' && i != '\r')
1078 buffer[last++] = (packed_ASCII_code) i;
1080 if (i == EOF && errno != EINTR && last == first)
1081 return false;
1083 /* We didn't get the whole line because our buffer was too small. */
1084 if (i != EOF && i != '\n' && i != '\r') {
1085 fprintf(stderr, "! Unable to read an entire line---bufsize=%u.\n",
1086 (unsigned) buf_size);
1087 fputs("Please increase buf_size in texmf.cnf.\n", stderr);
1088 uexit(1);
1091 buffer[last] = ' ';
1092 if (last >= max_buf_stack)
1093 max_buf_stack = last;
1095 /* If next char is LF of a CRLF, read it. */
1096 if (i == '\r') {
1097 while ((i = getc(f)) == EOF && errno == EINTR);
1098 if (i != '\n')
1099 ungetc(i, f);
1102 /* Trim trailing whitespace. */
1103 while (last > first && ISBLANK(buffer[last - 1]))
1104 --last;
1106 /* Don't bother using xord if we don't need to. */
1108 return true;
1114 /* Get the job name to be used, which may have been set from the
1115 command line. */
1116 str_number getjobname(str_number name)
1118 str_number ret = name;
1119 if (c_job_name != NULL)
1120 ret = maketexstring(c_job_name);
1121 return ret;