fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / luatex.c
blob2b924cac350b4f1c8a1a276c7ce4a35de025a284
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 = 100; /* \.{\\luatexversion} */
32 int luatex_revision = '3'; /* \.{\\luatexrevision} */
33 int luatex_date_info = 2017021514; /* the compile date is now hardwired :YEAR MONTH DAY HOUR*/
34 const char *luatex_version_string = "1.0.3";
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. */
65 /* Shell escape.
67 If shellenabledp == 0, all shell escapes are forbidden.
68 If (shellenabledp == 1 && restrictedshell == 0), any command
69 is allowed for a shell escape.
70 If (shellenabledp == 1 && restrictedshell == 1), only commands
71 given in the configuration file as
72 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun,...
73 (no spaces between commands) in texmf.cnf are allowed for a shell
74 escape in a restricted form: command name and arguments should be
75 separated by a white space. The first word should be a command
76 name. The quotation character for an argument with spaces,
77 including a pathname, should be ". ' should not be used.
79 Internally, all arguments are quoted by ' (Unix) or " (Windows)
80 before calling the system() function in order to forbid execution
81 of any embedded command.
83 If the --shell-escape option is given, we set
84 shellenabledp = 1 and restrictedshell = 0, i.e., any command is allowed.
85 If the --shell-restricted option is given, we set
86 shellenabledp = 1 and restrictedshell = 1, i.e., only given cmds allowed.
87 If the --no-shell-escape option is given, we set
88 shellenabledp = -1 (and restrictedshell is irrelevant).
89 If none of these option are given, there are three cases:
90 (1) In the case where
91 shell_escape = y or
92 shell_escape = t or
93 shell_escape = 1
94 it becomes shellenabledp = 1 and restrictedshell = 0,
95 that is, any command is allowed.
96 (2) In the case where
97 shell_escape = p
98 it becomes shellenabledp = 1 and restrictedshell = 1,
99 that is, restricted shell escape is allowed.
100 (3) In all other cases, shellenabledp = 0, that is, shell
101 escape is forbidden. The value of restrictedshell is
102 irrelevant if shellenabledp == 0.
105 #ifdef TeX
107 /* cmdlist is a list of allowed commands which are given like this:
108 shell_escape_commands = kpsewhich,ebb,extractbb,mpost,metafun
109 in texmf.cnf. */
111 static char **cmdlist = NULL;
113 void mk_shellcmdlist(char *v)
115 char **p;
116 char *q, *r;
117 size_t n;
119 q = v;
120 n = 1;
122 /* analyze the variable shell_escape_commands = foo,bar,...
123 spaces before and after (,) are not allowed. */
125 while ((r = strchr(q, ',')) != 0) {
126 n++;
127 q = r + 1;
129 if (*q)
130 n++;
131 cmdlist = (char **) xmalloc(n * sizeof (char *));
132 p = cmdlist;
133 q = v;
134 while ((r = strchr(q, ',')) != 0) {
135 *r = '\0';
136 *p++ = xstrdup (q);
137 q = r + 1;
139 if (*q)
140 *p++ = xstrdup (q);
141 *p = NULL;
144 /* Called from maininit. Not static because also called from
145 luatexdir/lua/luainit.c. */
148 In order to avoid all kind of time code in the backend code we use a function.
149 The start time can be overloaded in several ways:
151 (1) By setting the environmment variable SOURCE_DATE_EPOCH. This will influence
152 the tex parameters, random seed, pdf timestamp and pdf id that is derived
153 from the time. This variable is consulted when the kpse library is enabled
154 which is analogue to other properties.
156 (2) By setting the texconfig.start_time variable (as with other variables
157 we use the internal name there). This has the same effect as (1) and is
158 provided for when kpse is not used to set these variables or when an overloaded
159 is wanted. This is analogue to other properties.
161 When an utc time is needed one can provide the flag --utc. This property is
162 independent of this time hackery. This flag has a corresponding texconfig
163 option use_utc_time.
165 To some extend a cleaner solution would be to have a flag that disables all
166 variable data in one go (like filenames and so) but we just follow the method
167 implemented in pdftex where primitives are used tod disable it.
171 static int start_time = -1;
173 int get_start_time(void) {
174 if (start_time < 0) {
175 start_time = time((time_t *) NULL);
177 return start_time;
181 This one is called as part of the kpse initialization which only happens
182 when this library is enabled.
184 #if defined(_MSC_VER)
185 #define strtoull _strtoui64
186 #endif
188 void init_start_time(void) {
189 if (start_time < 0) {
190 unsigned long long epoch;
191 char *endptr;
193 We don't really care how kpse sets up this variable but we prefer to
194 just use its abstract interface.
196 /* char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); */
197 char *source_date_epoch = kpse_var_value("SOURCE_DATE_EPOCH");
198 if (source_date_epoch && source_date_epoch != '\0' ) {
199 errno = 0;
200 epoch = strtoull(source_date_epoch, &endptr, 10);
201 if (*endptr != '\0' || errno != 0) {
202 epoch = 0;
204 #if defined(_MSC_VER)
205 /* We avoid to crash if users test a large value which is not
206 * supported by Visual Studio 2010:
207 * a later time than 3001/01/01 20:59:59.
209 if (epoch > 32535291599ULL)
210 epoch = 32535291599ULL;
211 #endif
212 start_time = epoch;
218 This one is used to fetch a value from texconfig which can also be used to
219 set properties. This might come in handy when one has other ways to get date
220 info in the pdf file.
223 void set_start_time(int s) {
224 if (s >= 0) {
225 start_time = s ;
229 void init_shell_escape(void)
231 if (shellenabledp < 0) { /* --no-shell-escape on cmd line */
232 shellenabledp = 0;
234 } else {
235 if (shellenabledp == 0) { /* no shell options on cmd line, check cnf */
236 char *v1 = kpse_var_value("shell_escape");
237 if (v1) {
238 if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
239 shellenabledp = 1;
240 } else if (*v1 == 'p') {
241 shellenabledp = 1;
242 restrictedshell = 1;
244 free(v1);
248 /* If shell escapes are restricted, get allowed cmds from cnf. */
249 if (shellenabledp && restrictedshell == 1) {
250 char *v2 = kpse_var_value("shell_escape_commands");
251 if (v2) {
252 mk_shellcmdlist(v2);
253 free(v2);
259 # ifdef WIN32
260 # define QUOTE '"'
261 # else
262 # define QUOTE '\''
263 # endif
265 # if 0
266 # ifdef WIN32
267 static int char_needs_quote(int c)
269 /* special characters of cmd.exe */
271 return (c == '&' || c == '|' || c == '%' || c == '<' ||
272 c == '>' || c == ';' || c == ',' || c == '(' || c == ')');
274 # endif
275 # endif
277 static int Isspace(char c)
279 return (c == ' ' || c == '\t');
282 /* return values:
283 -1 : invalid quotation of an argument
284 0 : command is not allowed
285 2 : restricted shell escape, CMD is allowed.
287 We set *SAFECMD to a safely-quoted version of *CMD; this is what
288 should get executed. And we set CMDNAME to its first word; this is
289 what is checked against the shell_escape_commands list. */
291 int shell_cmd_is_allowed(const char *cmd, char **safecmd, char **cmdname)
293 char **p;
294 char *buf;
295 char *c, *d;
296 const char *s;
297 int pre;
298 unsigned spaces;
299 int allow = 0;
301 /* pre == 1 means that the previous character is a white space
302 pre == 0 means that the previous character is not a white space */
303 buf = xmalloc(strlen(cmd) + 1);
304 strcpy(buf, cmd);
305 c = buf;
306 while (Isspace(*c))
307 c++;
308 d = c;
309 while (!Isspace(*d) && *d)
310 d++;
311 *d = '\0';
313 /* *cmdname is the first word of the command line. For example,
314 *cmdname == "kpsewhich" for
315 \write18{kpsewhich --progname=dvipdfm --format="other text files" config}
317 *cmdname = xstrdup(c);
318 free(buf);
320 /* Is *cmdname listed in a texmf.cnf vriable as
321 shell_escape_commands = foo,bar,... ? */
322 p = cmdlist;
323 if (p) {
324 while (*p) {
325 if (strcmp(*p, *cmdname) == 0) {
326 /* *cmdname is found in the list, so restricted shell escape
327 is allowed */
328 allow = 2;
329 break;
331 p++;
334 if (allow == 2) {
335 spaces = 0;
336 for (s = cmd; *s; s++) {
337 if (Isspace(*s))
338 spaces++;
341 /* allocate enough memory (too much?) */
342 # ifdef WIN32
343 *safecmd = xmalloc(2 * strlen(cmd) + 3 + 2 * spaces);
344 # else
345 *safecmd = xmalloc(strlen(cmd) + 3 + 2 * spaces);
346 # endif
348 /* make a safe command line *safecmd */
349 s = cmd;
350 while (Isspace(*s))
351 s++;
352 d = *safecmd;
353 while (!Isspace(*s) && *s)
354 *d++ = *s++;
356 pre = 1;
357 while (*s) {
358 /* Quotation given by a user. " should always be used; we
359 transform it below. On Unix, if ' is used, simply immediately
360 return a quotation error. */
361 if (*s == '\'') {
362 return -1;
365 if (*s == '"') {
366 /* All arguments are quoted as 'foo' (Unix) or "foo" (Windows)
367 before calling system(). Therefore closing QUOTE is necessary
368 if the previous character is not a white space.
369 example:
370 --format="other text files" becomes
371 '--format=''other text files' (Unix)
372 "--format"="other text files" (Windows) */
374 if (pre == 0) {
375 # ifdef WIN32
376 if (*(s-1) == '=') {
377 *(d-1) = QUOTE;
378 *d++ = '=';
379 } else {
380 *d++ = QUOTE;
382 # else
383 *d++ = QUOTE;
384 # endif
387 pre = 0;
388 /* output the quotation mark for the quoted argument */
389 *d++ = QUOTE;
390 s++;
392 while (*s != '"') {
393 /* Illegal use of ', or closing quotation mark is missing */
394 if (*s == '\'' || *s == '\0')
395 return -1;
396 # if 0
397 # ifdef WIN32
398 if (char_needs_quote(*s))
399 *d++ = '^';
400 # endif
401 # endif
402 *d++ = *s++;
405 /* Closing quotation mark will be output afterwards, so
406 we do nothing here */
407 s++;
409 /* The character after the closing quotation mark
410 should be a white space or NULL */
411 if (!Isspace(*s) && *s)
412 return -1;
414 /* Beginning of a usual argument */
415 } else if (pre == 1 && !Isspace(*s)) {
416 pre = 0;
417 *d++ = QUOTE;
418 # if 0
419 # ifdef WIN32
420 if (char_needs_quote(*s))
421 *d++ = '^';
422 # endif
423 # endif
424 *d++ = *s++;
425 /* Ending of a usual argument */
427 } else if (pre == 0 && Isspace(*s)) {
428 pre = 1;
429 /* Closing quotation mark */
430 *d++ = QUOTE;
431 *d++ = *s++;
432 } else {
433 /* Copy a character from cmd to *safecmd. */
434 # if 0
435 # ifdef WIN32
436 if (char_needs_quote(*s))
437 *d++ = '^';
438 # endif
439 # endif
440 *d++ = *s++;
443 /* End of the command line */
444 if (pre == 0) {
445 *d++ = QUOTE;
447 *d = '\0';
448 #ifdef WIN32
450 char *p, *q, *r;
451 p = *safecmd;
452 if (strlen (p) > 2 && p[1] == ':' && !IS_DIR_SEP (p[2])) {
453 q = xmalloc (strlen (p) + 2);
454 q[0] = p[0];
455 q[1] = p[1];
456 q[2] = '/';
457 q[3] = '\0';
458 strcat (q, (p + 2));
459 free (*safecmd);
460 *safecmd = q;
461 } else if (!IS_DIR_SEP (p[0]) && !(p[1] == ':' && IS_DIR_SEP (p[2]))) {
462 p = kpse_var_value ("SELFAUTOLOC");
463 if (p) {
464 r = *safecmd;
465 while (*r && !Isspace(*r))
466 r++;
467 if (*r == '\0')
468 q = concatn ("\"", p, "/", *safecmd, "\"", NULL);
469 else {
470 *r = '\0';
471 r++;
472 while (*r && Isspace(*r))
473 r++;
474 if (*r)
475 q = concatn ("\"", p, "/", *safecmd, "\" ", r, NULL);
476 else
477 q = concatn ("\"", p, "/", *safecmd, "\"", NULL);
479 free (p);
480 free (*safecmd);
481 *safecmd = q;
485 #endif
488 return allow;
491 #endif
494 /* What we were invoked as and with. */
495 char **argv;
496 int argc;
498 /* The C version of what might wind up in |TEX_format_default|. */
499 string dump_name;
501 /* The C version of the jobname, if given. */
502 const_string c_job_name;
504 const char *luatex_banner;
506 #ifdef _MSC_VER
507 /* Invalid parameter handler */
508 static void myInvalidParameterHandler(const wchar_t * expression,
509 const wchar_t * function,
510 const wchar_t * file,
511 unsigned int line,
512 uintptr_t pReserved)
515 printf(L"Invalid parameter detected in function %s."
516 L" File: %s Line: %d\n", function, file, line);
517 printf(L"Expression: %s\n", expression);
520 I return silently to avoid an exit with the error 0xc0000417
521 (invalid parameter) when we use non-embedded fonts in luatex-ja,
522 which works without any problem on Unix systems.
523 I hope it is not dangerous.
525 return;
527 #endif
529 /* The entry point: set up for reading the command line, which will
530 happen in `topenin', then call the main body. */
533 #if defined(DLLPROC)
534 DLLPROC (int ac, string *av)
535 #else
536 main (int ac, string *av)
537 #endif
539 # ifdef __EMX__
540 _wildcard(&ac, &av);
541 _response(&ac, &av);
542 # endif
544 # ifdef WIN32
545 # ifdef _MSC_VER
546 _set_invalid_parameter_handler(myInvalidParameterHandler);
547 # endif
548 av[0] = kpse_program_basename (av[0]);
549 _setmaxstdio(2048);
551 * We choose to crash for fatal errors
552 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
554 setmode(fileno(stdin), _O_BINARY);
555 # endif
557 lua_initialize(ac, av);
559 # ifdef WIN32
560 if (ac > 1) {
561 char *pp;
562 if ((strlen(av[ac-1]) > 2) &&
563 isalpha(av[ac-1][0]) &&
564 (av[ac-1][1] == ':') &&
565 (av[ac-1][2] == '\\')) {
566 for (pp=av[ac-1]+2; *pp; pp++) {
567 if (IS_KANJI(pp)) {
568 pp++;
569 continue;
571 if (*pp == '\\')
572 *pp = '/';
576 # endif
578 /* Call the real main program. */
579 main_body();
581 return EXIT_SUCCESS;
585 /* This is supposed to ``open the terminal for input'', but what we
586 really do is copy command line arguments into TeX's or Metafont's
587 buffer, so they can handle them. If nothing is available, or we've
588 been called already (and hence, argc==0), we return with
589 `last=first'. */
591 void topenin(void)
593 int i;
596 buffer[first] = 0; /* In case there are no arguments. */
598 if (optind < argc) { /* We have command line arguments. */
599 int k = first;
600 for (i = optind; i < argc; i++) {
601 char *ptr = &(argv[i][0]);
602 /* Don't use strcat, since in Aleph the buffer elements aren't
603 single bytes. */
604 while (*ptr) {
605 buffer[k++] = (packed_ASCII_code) * (ptr++);
607 buffer[k++] = ' ';
609 argc = 0; /* Don't do this again. */
610 buffer[k] = 0;
613 /* Find the end of the buffer. */
614 for (last = first; buffer[last]; ++last);
616 /* Make `last' be one past the last non-blank character in `buffer'. */
617 /* ??? The test for '\r' should not be necessary. */
618 for (--last; last >= first
619 && ISBLANK(buffer[last]) && buffer[last] != '\r'; --last);
620 last++;
622 /* One more time, this time converting to TeX's internal character
623 representation. */
626 /* IPC for TeX. By Tom Rokicki for the NeXT; it makes TeX ship out the
627 DVI file in a pipe to TeXView so that the output can be displayed
628 incrementally. Shamim Mohamed adapted it for Web2c. */
629 #if defined (TeX) && defined (IPC)
631 #ifdef WIN32
632 #undef _WINSOCKAPI_
633 #include <winsock2.h>
634 #else
635 #include <sys/socket.h>
636 #include <fcntl.h>
637 #ifndef O_NONBLOCK /* POSIX */
638 #ifdef O_NDELAY /* BSD */
639 #define O_NONBLOCK O_NDELAY
640 #elif defined(O_FNDELAY) /* NeXT */
641 #define O_NONBLOCK O_FNDELAY
642 #else
643 what the fcntl? cannot implement IPC without equivalent for O_NONBLOCK.
644 #endif
645 #endif /* no O_NONBLOCK */
646 #endif /* !WIN32 */
648 #ifdef WIN32
649 # define IPC_AF AF_INET
650 # ifndef IPC_LOCAL_HOST
651 # define IPC_LOCAL_HOST "127.0.0.1"
652 # define FIXED_PORT (unsigned short)4242
653 # endif
654 #else
655 # define IPC_AF AF_UNIX
656 # ifndef IPC_PIPE_NAME /* $HOME is prepended to this. */
657 # define IPC_PIPE_NAME "/.TeXview_Pipe"
658 # endif
659 #endif
660 #ifndef IPC_SERVER_CMD /* Command to run to start the server. */
661 # ifdef WIN32
662 # define IPC_SERVER_CMD "texview.exe"
663 # else
664 # define IPC_SERVER_CMD "open `which TeXview`"
665 # endif
666 #endif
668 struct msg
670 int namelength; /* length of auxiliary data */
671 int eof; /* new eof for dvi file */
672 #if 0 /* see usage of struct msg below */
673 char more_data[0]; /* where the rest of the stuff goes */
674 #endif
677 static struct sockaddr *ipc_addr;
678 static int ipc_addr_len;
680 static int
681 ipc_make_name (void)
683 if (ipc_addr_len == 0) {
684 #ifdef WIN32
685 unsigned long remote_addr = inet_addr(IPC_LOCAL_HOST);
686 if (remote_addr != INADDR_NONE) {
687 struct sockaddr_in *ipc_sin_addr = xmalloc (sizeof (struct sockaddr_in));
688 ipc_sin_addr->sin_family = AF_INET;
689 ipc_sin_addr->sin_addr.s_addr = remote_addr;
690 ipc_sin_addr->sin_port = htons (FIXED_PORT);
691 ipc_addr = ((struct sockaddr *) ipc_sin_addr);
692 ipc_addr_len = sizeof(struct sockaddr_in);
694 #else
695 string s = getenv ("HOME");
696 if (s) {
697 char *ipc_name;
698 ipc_addr = xmalloc (strlen (s) + 40);
699 ipc_addr->sa_family = 0;
700 ipc_name = ipc_addr->sa_data;
701 strcpy (ipc_name, s);
702 strcat (ipc_name, IPC_PIPE_NAME);
703 ipc_addr_len = strlen (ipc_name) + 3;
705 #endif
707 return ipc_addr_len;
710 static int sock = -1;
712 #ifdef WIN32
713 # define CLOSE_SOCKET(s) closesocket (s); WSACleanup ()
714 #else
715 # define CLOSE_SOCKET(s) close (s)
716 #endif
718 static int
719 ipc_is_open (void)
721 return sock != -1;
724 static void
725 ipc_open_out (void) {
726 #ifdef WIN32
727 struct WSAData wsaData;
728 int nCode;
729 unsigned long mode = 1;
730 #endif
731 #ifdef IPC_DEBUG
732 fputs ("tex: Opening socket for IPC output ...\n", stderr);
733 #endif
734 if (sock != -1) {
735 return;
738 #ifdef WIN32
739 if ((nCode = WSAStartup(MAKEWORD(1, 1), &wsaData)) != 0) {
740 fprintf(stderr,"WSAStartup() returned error code %d.\n", nCode);
741 return;
743 #endif
745 if (ipc_make_name () <= 0)
746 return;
748 sock = socket (IPC_AF, SOCK_STREAM, 0);
749 #ifdef IPC_DEBUG
750 if(sock != -1)
751 fprintf(stderr, "tex: Socket handle is %d\n", sock);
752 else
753 fprintf(stderr, "tex: Socket is invalid.\n");
754 #endif
756 if (sock != -1) {
757 if (connect (sock, ipc_addr, ipc_addr_len) != 0 ||
758 #ifdef WIN32
759 ioctlsocket (sock, FIONBIO, &mode) < 0
760 #else
761 fcntl (sock, F_SETFL, O_NONBLOCK) < 0
762 #endif
764 CLOSE_SOCKET (sock);
765 sock = -1;
766 #ifdef IPC_DEBUG
767 fputs ("tex: IPC socket cannot be connected.\n", stderr);
768 fputs ("tex: Socket is closed.\n", stderr);
769 #endif
770 return;
772 #ifdef IPC_DEBUG
773 fputs ("tex: Successfully opened IPC socket.\n", stderr);
774 #endif
778 static void
779 ipc_close_out (void)
781 #ifdef IPC_DEBUG
782 fputs ("tex: Closing output socket ...\n", stderr);
783 #endif
784 if (ipc_is_open ()) {
785 CLOSE_SOCKET (sock);
786 sock = -1;
790 static void
791 ipc_snd (int n, int is_eof, char *data)
793 struct
795 struct msg msg;
796 char more_data[1024];
797 } ourmsg;
799 if (!ipc_is_open ()) {
800 return;
803 #ifdef IPC_DEBUG
804 fprintf(stderr, "%d\t%d\n", ourmsg.msg.namelength, ourmsg.msg.eof);
805 fputs ("tex: Sending message to socket ...\n", stderr);
806 #endif
807 ourmsg.msg.namelength = n;
808 ourmsg.msg.eof = is_eof;
809 if (n) {
810 strcpy (ourmsg.more_data, data);
812 n += sizeof (struct msg);
813 #ifdef IPC_DEBUG
814 fprintf(stderr, "%d\t%d\n", ourmsg.msg.namelength, ourmsg.msg.eof);
815 fputs ("tex: Writing to socket...\n", stderr);
816 #endif
817 #if defined(WIN32)
818 if (send (sock, (char *)&ourmsg, n, 0) != n) {
819 #else
820 if (write (sock, &ourmsg, n) != n) {
821 #endif
822 ipc_close_out ();
824 #ifdef IPC_DEBUG
825 fputs ("tex: IPC message sent.\n", stderr);
826 #endif
829 /* This routine notifies the server if there is an eof, or the filename
830 if a new DVI file is starting. This is the routine called by TeX.
831 Aleph defines str_start(#) as str_start_ar[# - too_big_char], with
832 too_big_char = biggest_char + 1 = 65536 (omstr.ch). */
834 void
835 ipcpage (int is_eof)
837 static boolean begun = false;
838 unsigned len = 0;
839 string p = NULL;
841 if (!begun) {
842 string name; /* Just the filename. */
843 string cwd = xgetcwd ();
845 ipc_open_out ();
847 /* Have to pass whole filename to the other end, since it may have
848 been started up and running as a daemon, e.g., as with the NeXT
849 preview program. */
850 name = static_pdf->file_name;
851 p = concat3 (cwd, DIR_SEP_STRING, name);
852 free (cwd);
853 free (name);
855 #if defined (WIN32)
856 { char *q;
857 for (q = p; *q; q++) {
858 if (*q == '\\')
859 *q = '/';
860 else if (IS_KANJI(q))
861 q++;
864 #endif
865 len = strlen(p);
866 begun = true;
868 ipc_snd (len, is_eof, p);
870 if (p)
871 free (p);
873 #endif /* TeX && IPC */
875 /* Normalize quoting of filename -- that is, only quote if there is a space,
876 and always use the quote-name-quote style. */
877 string normalize_quotes(const_string name, const_string mesg)
879 boolean quoted = false;
880 boolean must_quote = (strchr(name, ' ') != NULL);
881 /* Leave room for quotes and NUL. */
882 string ret = (string) xmalloc((unsigned) strlen(name) + 3);
883 string p;
884 const_string q;
885 p = ret;
886 if (must_quote)
887 *p++ = '"';
888 for (q = name; *q; q++) {
889 if (*q == '"')
890 quoted = !quoted;
891 else
892 *p++ = *q;
894 if (must_quote)
895 *p++ = '"';
896 *p = '\0';
897 if (quoted) {
898 fprintf(stderr, "! Unbalanced quotes in %s %s\n", mesg, name);
899 uexit(1);
901 return ret;
905 /* All our interrupt handler has to do is set TeX's or Metafont's global
906 variable `interrupt'; then they will do everything needed. */
907 #ifdef WIN32
908 /* Win32 doesn't set SIGINT ... */
909 static BOOL WINAPI catch_interrupt(DWORD arg)
911 switch (arg) {
912 case CTRL_C_EVENT:
913 case CTRL_BREAK_EVENT:
914 interrupt = 1;
915 return TRUE;
916 default:
917 /* No need to set interrupt as we are exiting anyway */
918 return FALSE;
921 #else /* not WIN32 */
922 static RETSIGTYPE catch_interrupt(int arg)
924 (void) arg;
925 interrupt = 1;
926 # ifdef OS2
927 (void) signal(SIGINT, SIG_ACK);
928 # else
929 (void) signal(SIGINT, catch_interrupt);
930 # endif /* not OS2 */
932 #endif /* not WIN32 */
934 /* Besides getting the date and time here, we also set up the interrupt
935 handler, for no particularly good reason. It's just that since the
936 `fix_date_and_time' routine is called early on (section 1337 in TeX,
937 ``Get the first line of input and prepare to start''), this is as
938 good a place as any. */
940 void get_date_and_time(int *minutes, int *day, int *month, int *year)
942 time_t myclock = get_start_time();
943 struct tm *tmptr ;
944 if (utc_option) {
945 tmptr = gmtime(&myclock);
946 } else {
947 tmptr = localtime(&myclock);
950 *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
951 *day = tmptr->tm_mday;
952 *month = tmptr->tm_mon + 1;
953 *year = tmptr->tm_year + 1900;
956 #ifdef SA_INTERRUPT
957 /* Under SunOS 4.1.x, the default action after return from the
958 signal handler is to restart the I/O if nothing has been
959 transferred. The effect on TeX is that interrupts are ignored if
960 we are waiting for input. The following tells the system to
961 return EINTR from read() in this case. From ken@cs.toronto.edu. */
963 struct sigaction a, oa;
965 a.sa_handler = catch_interrupt;
966 sigemptyset(&a.sa_mask);
967 sigaddset(&a.sa_mask, SIGINT);
968 a.sa_flags = SA_INTERRUPT;
969 sigaction(SIGINT, &a, &oa);
970 if (oa.sa_handler != SIG_DFL)
971 sigaction(SIGINT, &oa, (struct sigaction *) 0);
972 #else /* no SA_INTERRUPT */
973 # ifdef WIN32
974 SetConsoleCtrlHandler(catch_interrupt, TRUE);
975 # else /* not WIN32 */
976 RETSIGTYPE(*old_handler) (int);
978 old_handler = signal(SIGINT, catch_interrupt);
979 if (old_handler != SIG_DFL)
980 signal(SIGINT, old_handler);
981 # endif /* not WIN32 */
982 #endif /* no SA_INTERRUPT */
987 Getting a high resolution time.
989 void get_seconds_and_micros(int *seconds, int *micros)
991 #if defined (HAVE_GETTIMEOFDAY)
992 struct timeval tv;
993 gettimeofday(&tv, NULL);
994 *seconds = (int)tv.tv_sec;
995 *micros = (int)tv.tv_usec;
996 #elif defined (HAVE_FTIME)
997 struct timeb tb;
998 ftime(&tb);
999 *seconds = tb.time;
1000 *micros = tb.millitm * 1000;
1001 #else
1002 time_t myclock = time((time_t *) NULL);
1003 *seconds = (int) myclock;
1004 *micros = 0;
1005 #endif
1009 Generating a better seed numbers
1011 int getrandomseed(void)
1013 #if defined (HAVE_GETTIMEOFDAY)
1014 struct timeval tv;
1015 gettimeofday(&tv, NULL);
1016 return (int)(tv.tv_usec + 1000000 * tv.tv_usec);
1017 #elif defined (HAVE_FTIME)
1018 struct timeb tb;
1019 ftime(&tb);
1020 return (tb.millitm + 1000 * tb.time);
1021 #else
1022 time_t myclock = get_start_time((time_t *) NULL);
1023 struct tm *tmptr ;
1024 if (utc_option) {
1025 tmptr = gmtime(&myclock);
1026 } else {
1027 tmptr = localtime(&myclock);
1029 return (tmptr->tm_sec + 60 * (tmptr->tm_min + 60 * tmptr->tm_hour));
1030 #endif
1033 /* Read a line of input as efficiently as possible while still looking
1034 like Pascal. We set `last' to `first' and return `false' if we get
1035 to eof. Otherwise, we return `true' and set last = first +
1036 length(line except trailing whitespace). */
1038 boolean input_line(FILE * f)
1040 int i = EOF;
1042 #ifdef WIN32
1043 if (f != Poptr && fileno (f) != fileno (stdin)) {
1044 long position = ftell (f);
1046 if (position == 0L) { /* Detect and skip Byte order marks. */
1047 int k1 = getc (f);
1049 if (k1 != 0xff && k1 != 0xfe && k1 != 0xef)
1050 rewind (f);
1051 else {
1052 int k2 = getc (f);
1054 if (k2 != 0xff && k2 != 0xfe && k2 != 0xbb)
1055 rewind (f);
1056 else if ((k1 == 0xff && k2 == 0xfe) || /* UTF-16(LE) */
1057 (k1 == 0xfe && k2 == 0xff)) /* UTF-16(BE) */
1059 else {
1060 int k3 = getc (f);
1062 if (k1 == 0xef && k2 == 0xbb && k3 == 0xbf) /* UTF-8 */
1064 else
1065 rewind (f);
1070 #endif
1071 /* Recognize either LF or CR as a line terminator. */
1072 last = first;
1073 while (last < buf_size && (i = getc(f)) != EOF && i != '\n' && i != '\r')
1074 buffer[last++] = (packed_ASCII_code) i;
1076 if (i == EOF && errno != EINTR && last == first)
1077 return false;
1079 /* We didn't get the whole line because our buffer was too small. */
1080 if (i != EOF && i != '\n' && i != '\r') {
1081 fprintf(stderr, "! Unable to read an entire line---bufsize=%u.\n",
1082 (unsigned) buf_size);
1083 fputs("Please increase buf_size in texmf.cnf.\n", stderr);
1084 uexit(1);
1087 buffer[last] = ' ';
1088 if (last >= max_buf_stack)
1089 max_buf_stack = last;
1091 /* If next char is LF of a CRLF, read it. */
1092 if (i == '\r') {
1093 while ((i = getc(f)) == EOF && errno == EINTR);
1094 if (i != '\n')
1095 ungetc(i, f);
1098 /* Trim trailing whitespace. */
1099 while (last > first && ISBLANK(buffer[last - 1]))
1100 --last;
1102 /* Don't bother using xord if we don't need to. */
1104 return true;
1110 /* Get the job name to be used, which may have been set from the
1111 command line. */
1112 str_number getjobname(str_number name)
1114 str_number ret = name;
1115 if (c_job_name != NULL)
1116 ret = maketexstring(c_job_name);
1117 return ret;