3 % Copyright
2006-2016 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software
; you can redistribute it and
/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation
; either version
2 of the License
, or
(at your
10 % option
) any later version.
12 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
13 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
24 #include
<kpathsea
/c-stat.h
>
26 #include
"lua/luatex-api.h"
28 /* internalized strings
: see luatex-api.h
*/
32 This file is getting a bit messy
, but it is not simple to fix unilaterally.
34 Better to wait until Karl has some time
(after texlive
2008) so we can
35 synchronize with kpathsea. One problem
, for instance
, is that I would
36 like to resolve the full executable path. |kpse_set_program_name
()| does
37 that
, indirectly
(by setting SELFAUTOLOC in the environment
), but it
38 does much more
, making it hard to use for our purpose.
40 In fact
, it sets three C variables
:
42 |kpse_invocation_name| |kpse_invocation_short_name| |kpse-
>program_name|
44 and five environment variables
:
46 SELFAUTOLOC SELFAUTODIR SELFAUTOPARENT SELFAUTOGRANDPARENT progname
49 const_string LUATEX_IHELP
[] = {
50 "Usage: " my_name
" --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]",
51 " or: " my_name
" --lua=FILE [OPTION]... \\FIRST-LINE",
52 " or: " my_name
" --lua=FILE [OPTION]... &FMT ARGS",
53 " Run " MyName
" on TEXNAME, usually creating TEXNAME.pdf.",
54 " Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.",
56 " Alternatively, if the first non-option argument begins with a backslash,",
57 " " my_name
" interprets all non-option arguments as an input line.",
59 " Alternatively, if the first non-option argument begins with a &, the",
60 " next word is taken as the FMT to read, overriding all else. Any",
61 " remaining arguments are processed as above.",
63 " If no arguments or options are specified, prompt for input.",
65 " The following regular options are understood: ",
67 " --credits display credits and exit",
68 " --debug-format enable format debugging",
69 " --draftmode switch on draft mode (generates no output PDF)",
70 " --[no-]file-line-error disable/enable file:line:error style messages",
71 " --[no-]file-line-error-style aliases of --[no-]file-line-error",
72 " --fmt=FORMAT load the format file FORMAT",
73 " --halt-on-error stop processing at the first error",
74 " --help display help and exit",
75 " --ini be ini" my_name
", for dumping formats",
76 " --interaction=STRING set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)",
77 " --jobname=STRING set the job name to STRING",
78 " --kpathsea-debug=NUMBER set path searching debugging flags according to the bits of NUMBER",
79 " --lua=FILE load and execute a lua initialization script",
80 " --[no-]mktex=FMT disable/enable mktexFMT generation (FMT=tex/tfm)",
81 " --nosocket disable the lua socket library",
82 " --output-comment=STRING use STRING for DVI file comment instead of date (no effect for PDF)",
83 " --output-directory=DIR use existing DIR as the directory to write files in",
84 " --output-format=FORMAT use FORMAT for job output; FORMAT is 'dvi' or 'pdf'",
85 " --progname=STRING set the program name to STRING",
86 " --recorder enable filename recorder",
87 " --safer disable easily exploitable lua commands",
88 " --[no-]shell-escape disable/enable system commands",
89 " --shell-restricted restrict system commands to a list of commands given in texmf.cnf",
90 " --synctex=NUMBER enable synctex",
91 " --version display version and exit",
93 "Alternate behaviour models can be obtained by special switches",
95 " --luaonly run a lua file, then exit",
96 " --luaconly byte-compile a lua file, then exit",
97 " --luahashchars the bits used by current Lua interpreter for strings hashing",
99 " --jiton turns the JIT compiler on (default off)",
100 " --jithash=STRING choose the hash function for the lua strings (lua51|luajit20: default lua51)",
103 "See the reference manual for more information about the startup process.",
108 " --8bit ignored, input is assumed to be in UTF-8 encoding",
109 " --default-translate-file=FILE ignored, input is assumed to be in UTF-8 encoding",
110 " --etex ignored, the etex extensions are always active",
111 " --disable-write18 disable \\write18{SHELL COMMAND}",
112 " --enable-write18 enable \\write18{SHELL COMMAND}",
113 " --[no-]parse-first-line ignored",
114 " --translate-file=FILE ignored, input is assumed to be in UTF-8 encoding",
117 @ The return value will be the directory of the executable
, e.g.
: \.
{c
:/TeX
/bin
}
119 static char
*ex_selfdir
(char
*argv0
)
122 #if defined
(__MINGW32__
)
123 char path
[PATH_MAX
], *fp
;
125 /* SearchPath
() always gives back an absolute directory
*/
126 if
(SearchPath
(NULL, argv0
, ".exe", PATH_MAX
, path
, NULL) == 0)
127 FATAL1
("Can't determine where the executable %s is.\n", argv0
);
128 /* slashify the dirname
*/
129 for
(fp
= path
; fp
&& *fp; fp++)
132 #else
/* __MINGW32__
*/
134 char short_path
[PATH_MAX
], path
[PATH_MAX
], *fp
;
136 /* SearchPath
() always gives back an absolute directory
*/
137 if
(SearchPath
(NULL, argv0
, ".exe", PATH_MAX
, short_path
, &fp) == 0)
138 FATAL1
("Can't determine where the executable %s is.\n", argv0
);
139 if
(getlongpath
(path
, short_path
, sizeof
(path
)) == 0) {
140 FATAL1
("This path points to an invalid file : %s\n", short_path
);
142 #endif
/* __MINGW32__
*/
143 return xdirname
(path
);
145 return kpse_selfdir
(argv0
);
150 static void prepare_cmdline
(lua_State
* L
, char
**av
, int ac
, int zero_offset
)
154 luaL_checkstack
(L
, ac
+ 3, "too many arguments to script");
155 lua_createtable
(L
, 0, 0);
156 for
(i
= 0; i
< ac
; i
++) {
157 lua_pushstring
(L
, av
[i
]);
158 lua_rawseti
(L
, -2, (i
- zero_offset
));
160 lua_setglobal
(L
, "arg");
161 lua_getglobal
(L
, "os");
162 s
= ex_selfdir
(argv
[0]);
163 lua_pushstring
(L
, s
);
165 lua_setfield
(L
, -2, "selfdir");
170 string input_name
= NULL;
172 static string user_progname
= NULL;
174 char
*startup_filename
= NULL;
177 unsigned char show_luahashchars
= 0;
181 char
*jithash_hashname
= NULL;
184 int safer_option
= 0;
185 int nosocket_option
= 0;
187 @ Reading the options.
189 @ Test whether getopt found an option ``A''.
190 Assumes the option index is in the variable |option_index|
, and the
191 option table in a variable |long_options|.
194 #define ARGUMENT_IS
(a
) STREQ
(long_options
[option_index
].name
, a
)
197 SunOS cc can't initialize automatic structs
, so make this static.
201 Nota Bene
: we still intercept some options that other engines handle
202 so that existing scripted usage will not fail.
205 static struct option long_options
[] = {
208 {"luaonly", 0, 0, 0},
209 {"luahashchars", 0, 0, 0},
212 {"jithash", 1, 0, 0},
214 {"safer", 0, &safer_option, 1},
215 {"nosocket", 0, &nosocket_option, 1},
217 {"ini", 0, &ini_version, 1},
218 {"interaction", 1, 0, 0},
219 {"halt-on-error", 0, &haltonerrorp, 1},
220 {"kpathsea-debug", 1, 0, 0},
221 {"progname", 1, 0, 0},
222 {"version", 0, 0, 0},
223 {"credits", 0, 0, 0},
224 {"recorder", 0, 0, 0},
226 {"output-comment", 1, 0, 0},
227 {"output-directory", 1, 0, 0},
228 {"draftmode", 0, 0, 0},
229 {"output-format", 1, 0, 0},
230 {"shell-escape", 0, &shellenabledp, 1},
231 {"no-shell-escape", 0, &shellenabledp, -1},
232 {"enable-write18", 0, &shellenabledp, 1},
233 {"disable-write18", 0, &shellenabledp, -1},
234 {"shell-restricted", 0, 0, 0},
235 {"debug-format", 0, &debug_format_file, 1},
236 {"file-line-error-style", 0, &filelineerrorstylep, 1},
237 {"no-file-line-error-style", 0, &filelineerrorstylep, -1},
239 /* Shorter option names for the above.
*/
241 {"file-line-error", 0, &filelineerrorstylep, 1},
242 {"no-file-line-error", 0, &filelineerrorstylep, -1},
243 {"jobname", 1, 0, 0},
244 {"parse-first-line", 0, &parsefirstlinep, 1},
245 {"no-parse-first-line", 0, &parsefirstlinep, -1},
246 {"translate-file", 1, 0, 0},
247 {"default-translate-file", 1, 0, 0},
250 {"no-mktex", 1, 0, 0},
252 /* Synchronization
: just like
"interaction" above
*/
254 {"synctex", 1, 0, 0},
259 int lua_numeric_field_by_index
(lua_State
* L
, int name_index
, int dflt
)
261 register int i
= dflt
;
262 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
264 if
(lua_type
(L
, -1) == LUA_TNUMBER
) {
265 i
= lua_roundnumber
(L
, -1);
272 unsigned int lua_unsigned_numeric_field_by_index
(lua_State
* L
, int name_index
, int dflt
)
274 register unsigned int i
= dflt
;
275 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, name_index
); /* fetch the stringptr
*/
277 if
(lua_type
(L
, -1) == LUA_TNUMBER
) {
278 i
= lua_uroundnumber
(L
, -1);
285 static int recorderoption
= 0;
287 static void parse_options
(int ac
, char
**av
)
290 /* save argc and argv
*/
294 int g
; /* `getopt' return code.
*/
296 char
*firstfile
= NULL;
297 opterr
= 0; /* dont whine
*/
299 if
((strstr
(argv
[0], "luajittexlua") != NULL) ||
300 (strstr
(argv
[0], "texluajit") != NULL)) {
302 if
((strstr
(argv
[0], "luatexlua") != NULL) ||
303 (strstr
(argv
[0], "texlua") != NULL)) {
309 g
= getopt_long_only
(ac
, av
, "+", long_options
, &option_index);
311 if
(g
== -1) /* End of arguments
, exit the loop.
*/
313 if
(g
== '?'
) { /* Unknown option.
*/
315 fprintf
(stderr
,"%s: unrecognized option '%s'\n", argv
[0], argv
[optind-1
]);
319 assert
(g
== 0); /* We have no short option names.
*/
321 if
(ARGUMENT_IS
("luaonly")) {
325 } else if
(ARGUMENT_IS
("lua")) {
326 startup_filename
= optarg
;
327 lua_offset
= (optind
- 1);
330 } else if
(ARGUMENT_IS
("jiton")) {
332 } else if
(ARGUMENT_IS
("jithash")) {
333 size_t len
= strlen
(optarg
);
335 jithash_hashname
= optarg
;
337 WARNING2
("hash name truncated to 15 characters from %d. (%s)", (int
) len
, optarg
);
338 jithash_hashname
= (string
) xmalloc
(16);
339 strncpy
(jithash_hashname
, optarg
, 15);
340 jithash_hashname
[15] = 0;
343 } else if
(ARGUMENT_IS
("luahashchars")) {
344 show_luahashchars
= 1;
345 } else if
(ARGUMENT_IS
("kpathsea-debug")) {
346 kpathsea_debug |
= atoi
(optarg
);
347 } else if
(ARGUMENT_IS
("progname")) {
348 user_progname
= optarg
;
349 } else if
(ARGUMENT_IS
("jobname")) {
351 } else if
(ARGUMENT_IS
("fmt")) {
353 } else if
(ARGUMENT_IS
("output-directory")) {
354 output_directory
= optarg
;
355 } else if
(ARGUMENT_IS
("output-comment")) {
356 size_t len
= strlen
(optarg
);
358 output_comment
= optarg
;
360 WARNING2
("Comment truncated to 255 characters from %d. (%s)", (int
) len
, optarg
);
361 output_comment
= (string
) xmalloc
(256);
362 strncpy
(output_comment
, optarg
, 255);
363 output_comment
[255] = 0;
365 } else if
(ARGUMENT_IS
("shell-restricted")) {
368 } else if
(ARGUMENT_IS
("output-format")) {
369 output_mode_option
= 1;
370 if
(strcmp
(optarg
, "dvi") == 0) {
371 output_mode_value
= 0;
372 } else if
(strcmp
(optarg
, "pdf") == 0) {
373 output_mode_value
= 1;
375 WARNING1
("Ignoring unknown value `%s' for --output-format",optarg
);
376 output_mode_option
= 0;
378 } else if
(ARGUMENT_IS
("draftmode")) {
379 draft_mode_option
= 1;
380 draft_mode_value
= 1;
381 } else if
(ARGUMENT_IS
("mktex")) {
382 kpse_maketex_option
(optarg
, true
);
383 } else if
(ARGUMENT_IS
("no-mktex")) {
384 kpse_maketex_option
(optarg
, false
);
385 } else if
(ARGUMENT_IS
("interaction")) {
386 /* These numbers match CPP defines
*/
387 if
(STREQ
(optarg
, "batchmode")) {
388 interactionoption
= 0;
389 } else if
(STREQ
(optarg
, "nonstopmode")) {
390 interactionoption
= 1;
391 } else if
(STREQ
(optarg
, "scrollmode")) {
392 interactionoption
= 2;
393 } else if
(STREQ
(optarg
, "errorstopmode")) {
394 interactionoption
= 3;
396 WARNING1
("Ignoring unknown argument `%s' to --interaction", optarg
);
398 } else if
(ARGUMENT_IS
("synctex")) {
399 /* Synchronize TeXnology
: catching the command line option as a long
*/
400 synctexoption
= (int
) strtol
(optarg
, NULL, 0);
401 } else if
(ARGUMENT_IS
("recorder")) {
403 } else if
(ARGUMENT_IS
("help")) {
404 usagehelp
(LUATEX_IHELP
, BUG_ADDRESS
);
405 } else if
(ARGUMENT_IS
("version")) {
406 print_version_banner
();
408 puts
("\n\nExecute '" my_name
" --credits' for credits and version details.\n\n"
409 "There is NO warranty. Redistribution of this software is covered by\n"
410 "the terms of the GNU General Public License, version 2 or (at your option)\n"
411 "any later version. For more information about these matters, see the file\n"
412 "named COPYING and the LuaTeX source.\n\n"
413 "LuaTeX is Copyright 2016 Taco Hoekwater and the LuaTeX Team.\n");
416 } else if
(ARGUMENT_IS
("credits")) {
418 initversionstring
(&versions);
419 print_version_banner
();
421 puts
("\n\nThe LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater, Luigi Scarso.\n\n"
422 MyName
" merges and builds upon (parts of) the code from these projects:\n\n"
423 "tex : Donald Knuth\n"
424 "etex : Peter Breitenlohner, Phil Taylor and friends\n"
425 "omega : John Plaice and Yannis Haralambous\n"
426 "aleph : Giuseppe Bilotta\n"
427 "pdftex : Han The Thanh and friends\n"
428 "kpathsea : Karl Berry, Olaf Weber and others\n"
429 "lua : Roberto Ierusalimschy, Waldemar Celes and Luiz Henrique de Figueiredo\n"
430 "metapost : John Hobby, Taco Hoekwater and friends.\n"
431 "poppler : Derek Noonburg, Kristian H\\ogsberg (partial)\n"
432 "fontforge : George Williams (partial)\n"
433 "luajit : Mike Pall (used in LuajitTeX)\n");
439 /* attempt to find |input_name|
/ |dump_name|
*/
442 startup_filename
= xstrdup
(argv
[optind
]);
445 } else if
(argv
[optind
] && argv[optind][0] == '&') {
446 dump_name
= xstrdup
(argv
[optind
] + 1);
447 } else if
(argv
[optind
] && argv[optind][0] != '\\') {
448 if
(argv
[optind
][0] == '
*'
) {
449 input_name
= xstrdup
(argv
[optind
] + 1);
451 firstfile
= xstrdup
(argv
[optind
]);
452 if
((strstr
(firstfile
, ".lua") ==
453 firstfile
+ strlen
(firstfile
) - 4)
454 ||
(strstr
(firstfile
, ".luc") ==
455 firstfile
+ strlen
(firstfile
) - 4)
456 ||
(strstr
(firstfile
, ".LUA") ==
457 firstfile
+ strlen
(firstfile
) - 4)
458 ||
(strstr
(firstfile
, ".LUC") ==
459 firstfile
+ strlen
(firstfile
) - 4)) {
460 if
(startup_filename
== NULL) {
461 startup_filename
= firstfile
;
467 input_name
= firstfile
;
471 } else if
(sargv
[sargc-1
] && sargv[sargc-1][0] != '-' &&
472 sargv
[sargc-1
][0] != '\\'
) {
473 if
(sargv
[sargc-1
][0] == '
&')
474 dump_name
= xstrdup
(sargv
[sargc-1
] + 1);
477 if
(sargv
[sargc-1
][0] == '
*'
)
478 input_name
= xstrdup
(sargv
[sargc-1
] + 1);
480 input_name
= xstrdup
(sargv
[sargc-1
]);
481 sargv
[sargc-1
] = normalize_quotes
(input_name
, "argument");
483 input_name
= (char
*)xbasename
(input_name
);
484 but without cast const
=> non-const.
*/
485 input_name
+= xbasename
(input_name
) - input_name
;
486 p
= strrchr
(input_name
, '.'
);
487 if
(p
!= NULL && strcasecmp(p, ".tex") == 0)
490 c_job_name
= normalize_quotes
(input_name
, "jobname");
492 if
(safer_option
) /* --safer implies
--nosocket
*/
497 if
(safer_option
) /* --safer implies
--nosocket
*/
499 /* Finalize the input filename.
*/
500 if
(input_name
!= NULL) {
501 argv
[optind
] = normalize_quotes
(input_name
, "argument");
505 @ test for readability
507 #define is_readable
(a
) (stat
(a
,&finfo)==0) && S_ISREG(finfo.st_mode) && \
508 (f
=fopen
(a
,"r")) != NULL && !fclose(f)
511 static char
*find_filename
(char
*name
, const char
*envkey
)
514 char
*dirname
= NULL;
515 char
*filename
= NULL;
517 if
(is_readable
(name
)) {
520 dirname
= getenv
(envkey
);
521 if
((dirname
!= NULL) && strlen(dirname)) {
522 dirname
= xstrdup
(getenv
(envkey
));
523 if
(*(dirname
+ strlen
(dirname
) - 1) == '
/'
) {
524 *(dirname
+ strlen
(dirname
) - 1) = 0;
526 filename
= xmalloc
((unsigned
) (strlen
(dirname
) + strlen
(name
) + 2));
527 filename
= concat3
(dirname
, "/", name
);
529 if
(is_readable
(filename
)) {
540 static void init_kpse
(void
)
542 if
(!user_progname
) {
543 user_progname
= dump_name
;
544 } else if
(!dump_name
) {
545 dump_name
= user_progname
;
547 if
(!user_progname
) {
550 char
*p
= input_name
+ strlen
(input_name
) - 1;
551 while
(p
>= input_name
) {
552 if
(IS_DIR_SEP
(*p
)) {
559 user_progname
= remove_suffix
(input_name
);
561 if
(!user_progname
) {
562 user_progname
= kpse_program_basename
(argv
[0]);
566 dump_name
= kpse_program_basename
(argv
[0]);
568 user_progname
= dump_name
;
571 kpse_set_program_enabled
(kpse_fmt_format
, MAKE_TEX_FMT_BY_DEFAULT
,
574 kpse_set_program_name
(argv
[0], user_progname
);
575 init_shell_escape
(); /* set up 'restrictedshell'
*/
576 program_name_set
= 1 ;
577 if
(recorderoption
) {
578 recorder_enabled
= 1;
583 static void fix_dumpname
(void
)
587 /* adjust array for Pascal and provide extension
, if needed
*/
588 dist
= (int
) (strlen
(dump_name
) - strlen
(DUMP_EXT
));
589 if
(strstr
(dump_name
, DUMP_EXT
) == dump_name
+ dist
)
590 TEX_format_default
= dump_name
;
592 TEX_format_default
= concat
(dump_name
, DUMP_EXT
);
594 /* For |dump_name| to be
NULL is a bug.
*/
596 normal_error
("luatex","no format given");
602 @ Auxiliary function for kpse search
605 static const char
*luatex_kpse_find_aux
(lua_State
*L
, const char
*name
,
606 kpse_file_format_type format
, const char
*errname
)
608 const char
*filename
;
610 altname
= luaL_gsub
(L
, name
, ".", "/"); /* Lua convention
*/
611 filename
= kpse_find_file
(altname
, format
, false
);
612 if
(filename
== NULL) {
613 filename
= kpse_find_file
(name
, format
, false
);
615 if
(filename
== NULL) {
616 lua_pushfstring
(L
, "\n\t[kpse %s searcher] file not found: " LUA_QS
, errname
, name
);
621 @ The lua search function.
623 When kpathsea is not initialized
, then it runs the
624 normal lua function that is saved in the registry
, otherwise
627 two registry ref variables are needed
: one for the actual lua
628 function
, the other for its environment .
631 static int lua_loader_function
= 0;
633 static int luatex_kpse_lua_find
(lua_State
* L
)
635 const char
*filename
;
637 name
= luaL_checkstring
(L
, 1);
638 if
(program_name_set
== 0) {
639 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, lua_loader_function
);
640 lua_pushvalue
(L
, -2);
644 filename
= luatex_kpse_find_aux
(L
, name
, kpse_lua_format
, "lua");
645 if
(filename
== NULL)
646 return
1; /* library not found in this path
*/
647 if
(luaL_loadfile
(L
, filename
) != 0) {
648 luaL_error
(L
, "error loading module %s from file %s:\n\t%s",
649 lua_tostring
(L
, 1), filename
, lua_tostring
(L
, -1));
651 return
1; /* library loaded successfully
*/
655 static int clua_loader_function
= 0;
656 extern int searcher_C_luatex
(lua_State
*L
, const char
*name
, const char
*filename
);
658 static int luatex_kpse_clua_find
(lua_State
* L
)
660 const char
*filename
;
663 lua_pushliteral
(L
, "\n\t[C searcher disabled in safer mode]");
664 return
1; /* library not found in this path
*/
666 name
= luaL_checkstring
(L
, 1);
667 if
(program_name_set
== 0) {
668 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, clua_loader_function
);
669 lua_pushvalue
(L
, -2);
673 const char
*path_saved
;
674 char
*prefix
, *postfix
, *p
, *total
;
678 filename
= luatex_kpse_find_aux
(L
, name
, kpse_clua_format
, "C");
679 if
(filename
== NULL)
680 return
1; /* library not found in this path
*/
681 extensionless
= strdup
(filename
);
683 return
1; /* allocation failure
*/
684 /* Fix Issue
850: replace '.' with LUA_DIRSEP
*/
685 temp_name
= strdup
(name
);
687 if
((unsigned char
)temp_name
[j
]=='\
0'
) {
690 if
((unsigned char
)temp_name
[j
]=='.'
){
691 temp_name
[j
]=LUA_DIRSEP
[0];
694 p
= strstr
(extensionless
, temp_name
);
695 if
(!p
) return
1; /* this would be exceedingly weird
*/
697 prefix
= strdup
(extensionless
);
698 if
(!prefix
) return
1; /* allocation failure
*/
699 postfix
= strdup
(p
+strlen
(name
));
700 if
(!postfix
) return
1; /* allocation failure
*/
701 total
= malloc
(strlen
(prefix
)+strlen
(postfix
)+2);
702 if
(!total
) return
1; /* allocation failure
*/
703 snprintf
(total
,strlen
(prefix
)+strlen
(postfix
)+2, "%s?%s", prefix
, postfix
);
704 /* save package.path
*/
705 lua_getglobal
(L
,"package");
706 lua_getfield
(L
,-1,"cpath");
707 path_saved
= lua_tostring
(L
,-1);
709 /* set package.path
= "?" */
710 lua_pushstring
(L
,total
);
711 lua_setfield
(L
,-2,"cpath");
712 lua_pop
(L
,1); /* pop
"package" */
714 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, clua_loader_function
);
715 lua_pushstring
(L
, name
);
717 /* restore package.path
*/
718 lua_getglobal
(L
,"package");
719 lua_pushstring
(L
,path_saved
);
720 lua_setfield
(L
,-2,"cpath");
721 lua_pop
(L
,1); /* pop
"package" */
729 @ Setting up the new search functions.
731 This replaces package.searchers
[2] and package.searchers
[3] with the
732 functions defined above.
735 static void setup_lua_path
(lua_State
* L
)
737 lua_getglobal
(L
, "package");
739 lua_getfield
(L
, -1, "loaders");
741 lua_getfield
(L
, -1, "searchers");
743 lua_rawgeti
(L
, -1, 2); /* package.searchers
[2] */
744 lua_loader_function
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
745 lua_pushcfunction
(L
, luatex_kpse_lua_find
);
746 lua_rawseti
(L
, -2, 2); /* replace the normal lua loader
*/
748 lua_rawgeti
(L
, -1, 3); /* package.searchers
[3] */
749 clua_loader_function
= luaL_ref
(L
, LUA_REGISTRYINDEX
);
750 lua_pushcfunction
(L
, luatex_kpse_clua_find
);
751 lua_rawseti
(L
, -2, 3); /* replace the normal lua lib loader
*/
753 lua_pop
(L
, 2); /* pop the array and table
*/
756 @ helper variables for the safe keeping of table ids
762 int oldtoken_table_id
;
766 int l_pack_type_index
[PACK_TYPE_SIZE
] ;
767 int l_group_code_index
[GROUP_CODE_SIZE
];
768 int l_math_style_name_index
[MATH_STYLE_NAME_SIZE
];
769 int l_dir_par_index
[DIR_PAR_SIZE
];
770 int l_dir_text_index
[DIR_TEXT_SIZE
];
772 int img_parms
[img_parms_max
];
773 int img_pageboxes
[img_pageboxes_max
];
775 int lua_show_valid_list
(lua_State
*L
, const char
**list
, int max
)
779 for
(i
= 0; i
< max
; i
++) {
780 lua_pushinteger
(L
,i
+1);
781 lua_pushstring
(L
, list
[i
]);
787 int lua_show_valid_keys
(lua_State
*L
, int
*list
, int max
)
791 for
(i
= 0; i
< max
; i
++) {
792 lua_pushinteger
(L
,i
+1);
793 lua_rawgeti
(L
, LUA_REGISTRYINDEX
, list
[i
]);
799 #if defined
(WIN32
) || defined
(__MINGW32__
) || defined
(__CYGWIN__
)
802 # define EXE_SUFFIXES
".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.ws;.tcl;.py;.pyw"
805 static void mk_suffixlist
(void
)
811 # if defined
(__CYGWIN__
)
812 v
= xstrdup
(EXE_SUFFIXES
);
814 v
= (char
*) getenv
("PATHEXT");
815 if
(v
) /* strlwr
() exists also in MingW
*/
816 v
= (char
*) strlwr
(xstrdup
(v
));
818 v
= xstrdup
(EXE_SUFFIXES
);
824 while
((r
= strchr
(q
, '
;'
)) != NULL) {
831 suffixlist
= (char
**) xmalloc
((n
+ 2) * sizeof
(char
*));
833 *p
= xstrdup
(".dll");
836 while
((r
= strchr
(q
, '
;'
)) != NULL) {
853 void lua_initialize
(int ac
, char
**av
)
855 char
*given_file
= NULL;
859 static char LC_CTYPE_C
[] = "LC_CTYPE=C";
860 static char LC_COLLATE_C
[] = "LC_COLLATE=C";
861 static char LC_NUMERIC_C
[] = "LC_NUMERIC=C";
862 static char engine_luatex
[] = "engine=" my_name
;
863 /* Save to pass along to topenin.
*/
864 const char
*fmt
= "This is " MyName
", Version %s" WEB2CVERSION
;
867 len
= strlen
(fmt
) + strlen
(luatex_version_string
) ;
868 banner
= xmalloc
(len
);
869 sprintf
(banner
, fmt
, luatex_version_string
);
870 luatex_banner
= banner
;
871 kpse_invocation_name
= kpse_program_basename
(argv
[0]);
876 if
(FILESTRCASEEQ
(kpse_invocation_name
, "texluajitc"))
877 exit
(luac_main
(ac
, av
));
878 if
(STREQ
(argv
[1], "--luaconly") || STREQ
(argv
[1], "--luac")) {
879 char
*argv1
= xmalloc
(strlen
("luajittex") + 1);
881 strcpy
(av
[1], "luajittex");
882 exit
(luac_main
(--ac
, ++av
));
885 if
(FILESTRCASEEQ
(kpse_invocation_name
, "texluac"))
886 exit
(luac_main
(ac
, av
));
887 if
(STREQ
(argv
[1], "--luaconly") || STREQ
(argv
[1], "--luac")) {
888 strcpy
(av
[1], "luatex");
889 exit
(luac_main
(--ac
, ++av
));
893 #if defined
(WIN32
) || defined
(__MINGW32__
) || defined
(__CYGWIN__
)
897 /* Must be initialized before options are parsed.
*/
898 interactionoption
= 4;
901 /* 0 means
"disable Synchronize TeXnology".
902 synctexoption is a
*.web variable.
903 We initialize it to a weird value to catch the
-synctex command line flag
904 At runtime
, if synctexoption is not |INT_MAX|
, then it contains the command line option provided
,
905 otherwise no such option was given by the user.
*/
906 #define SYNCTEX_NO_OPTION INT_MAX
907 synctexoption
= SYNCTEX_NO_OPTION
;
909 /* parse commandline
*/
910 parse_options
(ac
, av
);
912 shellenabledp
= true
;
914 /* make sure that the locale is 'sane'
(for lua
) */
917 putenv
(LC_COLLATE_C
);
918 putenv
(LC_NUMERIC_C
);
920 /* this is sometimes needed
*/
921 putenv
(engine_luatex
);
925 /* init internalized strings
*/
928 lua_pushstring
(Luas
,"lua.functions");
930 lua_settable
(Luas
,LUA_REGISTRYINDEX
);
932 /* here start the key definitions
*/
933 set_l_pack_type_index
;
934 set_l_group_code_index
;
935 set_l_math_style_name_index
;
937 set_l_dir_text_index
;
939 set_l_img_keys_index
;
940 set_l_img_pageboxes_index
;
942 prepare_cmdline
(Luas
, argv
, argc
, lua_offset
); /* collect arguments
*/
943 setup_lua_path
(Luas
);
945 if
(startup_filename
!= NULL) {
946 given_file
= xstrdup
(startup_filename
);
948 xfree
(startup_filename
);
950 startup_filename
= find_filename
(given_file
, "LUATEXDIR");
952 /* now run the file
*/
953 if
(startup_filename
!= NULL) {
955 /* hide the 'tex' and 'pdf' table
*/
956 tex_table_id
= hide_lua_table
(Luas
, "tex");
957 token_table_id
= hide_lua_table
(Luas
, "token");
958 oldtoken_table_id
= hide_lua_table
(Luas
, "oldtoken");
959 node_table_id
= hide_lua_table
(Luas
, "node");
960 pdf_table_id
= hide_lua_table
(Luas
, "pdf");
962 if
(luaL_loadfile
(Luas
, startup_filename
)) {
963 fprintf
(stdout
, "%s\n", lua_tostring
(Luas
, -1));
967 init_tex_table
(Luas
);
968 if
(lua_pcall
(Luas
, 0, 0, 0)) {
969 fprintf
(stdout
, "%s\n", lua_tostring
(Luas
, -1));
973 /* no filename? quit now
! */
975 get_lua_string
("texconfig", "jobname", &input_name);
978 get_lua_string
("texconfig", "formatname", &dump_name);
983 /* this is not strictly needed but it pleases valgrind
*/
987 /* unhide the 'tex' and 'pdf' table
*/
988 unhide_lua_table
(Luas
, "tex", tex_table_id
);
989 unhide_lua_table
(Luas
, "pdf", pdf_table_id
);
990 unhide_lua_table
(Luas
, "token", token_table_id
);
991 unhide_lua_table
(Luas
, "oldtoken", oldtoken_table_id
);
992 unhide_lua_table
(Luas
, "node", node_table_id
);
996 get_lua_boolean
("texconfig", "kpse_init", &kpse_init);
998 if
(kpse_init
!= 0) {
999 luainit
= 0; /* re-enable loading of texmf.cnf values
, see luatex.ch
*/
1002 /* |prohibit_file_trace|
(boolean
) */
1004 get_lua_boolean
("texconfig", "trace_file_names", &tracefilenames);
1006 /* |file_line_error|
*/
1007 filelineerrorstylep
= false
;
1008 get_lua_boolean
("texconfig", "file_line_error", &filelineerrorstylep);
1010 /* |halt_on_error|
*/
1011 haltonerrorp
= false
;
1012 get_lua_boolean
("texconfig", "halt_on_error", &haltonerrorp);
1014 /* |restrictedshell|
*/
1016 get_lua_string
("texconfig", "shell_escape", &v1);
1018 if
(*v1
== 't' ||
*v1
== 'y' ||
*v1
== '
1'
) {
1020 } else if
(*v1
== 'p'
) {
1022 restrictedshell
= 1;
1026 /* If shell escapes are restricted
, get allowed cmds from cnf.
*/
1027 if
(shellenabledp
&& restrictedshell == 1) {
1029 get_lua_string
("texconfig", "shell_escape_commands", &v1);
1031 mk_shellcmdlist
(v1
);
1040 fprintf
(stdout
, "%s file %s not found\n", (lua_only ?
"Script" : "Configuration"), given_file
);
1043 fprintf
(stdout
, "No %s file given\n", (lua_only ?
"script" : "configuration"));
1055 void check_texconfig_init
(void
)
1058 lua_getglobal
(Luas
, "texconfig");
1059 if
(lua_istable
(Luas
, -1)) {
1060 lua_getfield
(Luas
, -1, "init");
1061 if
(lua_isfunction
(Luas
, -1)) {
1062 int i
= lua_pcall
(Luas
, 0, 0, 0);
1064 /* Can't be more precise here
, called before TeX initialization
*/
1065 fprintf
(stderr
, "This went wrong: %s\n", lua_tostring
(Luas
, -1));