3
% Copyright 2006-2014 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/>.
25
#include <kpathsea/c-stat.h>
27
#include "lua/luatex-api.h"
29
/* internalized strings: see luatex-api.h */
36
This file is getting a bit messy, but it is not simple to fix unilaterally.
38
Better to wait until Karl has some time (after texlive 2008) so we can
39
synchronize with kpathsea. One problem, for instance, is that I would
40
like to resolve the full executable path. |kpse_set_program_name()| does
41
that, indirectly (by setting SELFAUTOLOC in the environment), but it
42
does much more, making it hard to use for our purpose.
44
In fact, it sets three C variables:
46
|kpse_invocation_name| |kpse_invocation_short_name| |kpse->program_name|
48
and five environment variables:
50
SELFAUTOLOC SELFAUTODIR SELFAUTOPARENT SELFAUTOGRANDPARENT progname
53
const_string LUATEX_IHELP[] = {
54
"Usage: " my_name " --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]",
55
" or: " my_name " --lua=FILE [OPTION]... \\FIRST-LINE",
56
" or: " my_name " --lua=FILE [OPTION]... &FMT ARGS",
57
" Run " MyName " on TEXNAME, usually creating TEXNAME.pdf.",
58
" Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.",
60
" Alternatively, if the first non-option argument begins with a backslash,",
61
" " my_name " interprets all non-option arguments as an input line.",
63
" Alternatively, if the first non-option argument begins with a &, the",
64
" next word is taken as the FMT to read, overriding all else. Any",
65
" remaining arguments are processed as above.",
67
" If no arguments or options are specified, prompt for input.",
69
" The following regular options are understood: ",
71
" --8bit ignored, input is assumed to be in UTF-8 encoding",
72
" --credits display credits and exit",
73
" --debug-format enable format debugging",
74
" --default-translate-file= ignored, input is assumed to be in UTF-8 encoding",
75
" --disable-write18 disable \\write18{SHELL COMMAND}",
76
" --draftmode switch on draft mode (generates no output PDF)",
77
" --enable-write18 enable \\write18{SHELL COMMAND}",
78
" --etex ignored, the etex extensions are always active",
79
" --[no-]file-line-error disable/enable file:line:error style messages",
80
" --[no-]file-line-error-style aliases of --[no-]file-line-error",
81
" --fmt=FORMAT load the format file FORMAT",
82
" --halt-on-error stop processing at the first error",
83
" --help display help and exit",
84
" --ini be ini" my_name ", for dumping formats",
85
" --interaction=STRING set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)",
86
" --jobname=STRING set the job name to STRING",
87
" --kpathsea-debug=NUMBER set path searching debugging flags according to the bits of NUMBER",
88
" --lua=s load and execute a lua initialization script",
89
" --[no-]mktex=FMT disable/enable mktexFMT generation (FMT=tex/tfm)",
90
" --nosocket disable the lua socket library",
91
" --output-comment=STRING use STRING for DVI file comment instead of date (no effect for PDF)",
92
" --output-directory=DIR use existing DIR as the directory to write files in",
93
" --output-format=FORMAT use FORMAT for job output; FORMAT is 'dvi' or 'pdf'",
94
" --[no-]parse-first-line disable/enable parsing of the first line of the input file",
95
" --progname=STRING set the program name to STRING",
96
" --recorder enable filename recorder",
97
" --safer disable easily exploitable lua commands",
98
" --[no-]shell-escape disable/enable \\write18{SHELL COMMAND}",
99
" --shell-restricted restrict \\write18 to a list of commands given in texmf.cnf",
100
" --synctex=NUMBER enable synctex",
101
" --translate-file= ignored, input is assumed to be in UTF-8 encoding",
102
" --version display version and exit",
104
"Alternate behaviour models can be obtained by special switches",
106
" --luaonly run a lua file, then exit",
107
" --luaconly byte-compile a lua file, then exit",
108
" --luahashchars the bits used by current Lua interpreter for strings hashing",
110
" --jiton turns the JIT compiler on (default off)",
111
" --jithash=STRING choose the hash function for the lua strings (lua51|luajit20: default lua51)",
114
"See the reference manual for more information about the startup process.",
118
@ The return value will be the directory of the executable, e.g.: \.{c:/TeX/bin}
120
static char *ex_selfdir(char *argv0)
123
#if defined(__MINGW32__)
124
char path[PATH_MAX], *fp;
126
/* SearchPath() always gives back an absolute directory */
127
if (SearchPath(NULL, argv0, ".exe", PATH_MAX, path, NULL) == 0)
128
FATAL1("Can't determine where the executable %s is.\n", argv0);
129
/* slashify the dirname */
130
for (fp = path; fp && *fp; fp++)
133
#else /* __MINGW32__ */
135
char short_path[PATH_MAX], path[PATH_MAX], *fp;
137
/* SearchPath() always gives back an absolute directory */
138
if (SearchPath(NULL, argv0, ".exe", PATH_MAX, short_path, &fp) == 0)
139
FATAL1("Can't determine where the executable %s is.\n", argv0);
140
if (getlongpath(path, short_path, sizeof(path)) == 0) {
141
FATAL1("This path points to an invalid file : %s\n", short_path);
143
#endif /* __MINGW32__ */
144
return xdirname(path);
146
return kpse_selfdir(argv0);
155
prepare_cmdline(lua_State * L, char **av, int ac, int zero_offset)
159
luaL_checkstack(L, ac + 3, "too many arguments to script");
160
lua_createtable(L, 0, 0);
161
for (i = 0; i < ac; i++) {
162
lua_pushstring(L, av[i]);
163
lua_rawseti(L, -2, (i - zero_offset));
165
lua_setglobal(L, "arg");
166
lua_getglobal(L, "os");
167
s = ex_selfdir(argv[0]);
168
lua_pushstring(L, s);
170
lua_setfield(L, -2, "selfdir");
175
string input_name = NULL;
177
static string user_progname = NULL;
179
char *startup_filename = NULL;
182
unsigned char show_luahashchars = 0;
186
char *jithash_hashname = NULL;
189
int safer_option = 0;
190
int nosocket_option = 0;
192
@ Reading the options.
194
@ Test whether getopt found an option ``A''.
195
Assumes the option index is in the variable |option_index|, and the
196
option table in a variable |long_options|.
199
#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
201
/* SunOS cc can't initialize automatic structs, so make this static. */
202
static struct option long_options[]
203
= { {"fmt", 1, 0, 0},
205
{"luaonly", 0, 0, 0},
206
{"luahashchars", 0, 0, 0},
209
{"jithash", 1, 0, 0},
211
{"safer", 0, &safer_option, 1},
212
{"nosocket", 0, &nosocket_option, 1},
214
{"ini", 0, &ini_version, 1},
215
{"interaction", 1, 0, 0},
216
{"halt-on-error", 0, &haltonerrorp, 1},
217
{"kpathsea-debug", 1, 0, 0},
218
{"progname", 1, 0, 0},
219
{"version", 0, 0, 0},
220
{"credits", 0, 0, 0},
221
{"recorder", 0, &recorder_enabled, 1},
223
{"output-comment", 1, 0, 0},
224
{"output-directory", 1, 0, 0},
225
{"draftmode", 0, 0, 0},
226
{"output-format", 1, 0, 0},
227
{"shell-escape", 0, &shellenabledp, 1},
228
{"no-shell-escape", 0, &shellenabledp, -1},
229
{"enable-write18", 0, &shellenabledp, 1},
230
{"disable-write18", 0, &shellenabledp, -1},
231
{"shell-restricted", 0, 0, 0},
232
{"debug-format", 0, &debug_format_file, 1},
233
{"file-line-error-style", 0, &filelineerrorstylep, 1},
234
{"no-file-line-error-style", 0, &filelineerrorstylep, -1},
235
/* Shorter option names for the above. */
236
{"file-line-error", 0, &filelineerrorstylep, 1},
237
{"no-file-line-error", 0, &filelineerrorstylep, -1},
238
{"jobname", 1, 0, 0},
239
{"parse-first-line", 0, &parsefirstlinep, 1},
240
{"no-parse-first-line", 0, &parsefirstlinep, -1},
241
{"translate-file", 1, 0, 0},
242
{"default-translate-file", 1, 0, 0},
245
{"no-mktex", 1, 0, 0},
246
/* Synchronization: just like "interaction" above */
247
{"synctex", 1, 0, 0},
252
int lua_numeric_field_by_index(lua_State * L, int name_index, int dflt)
254
register int i = dflt;
255
lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
257
if (lua_type(L, -1) == LUA_TNUMBER) {
258
i = lua_roundnumber(L, -1);
265
unsigned int lua_unsigned_numeric_field_by_index(lua_State * L, int name_index, int dflt)
267
register unsigned int i = dflt;
268
lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
270
if (lua_type(L, -1) == LUA_TNUMBER) {
271
i = lua_uroundnumber(L, -1);
280
static void parse_options(int ac, char **av)
283
/* save argc and argv */
287
int g; /* `getopt' return code. */
289
char *firstfile = NULL;
290
opterr = 0; /* dont whine */
292
if ((strstr(argv[0], "luajittexlua") != NULL) ||
293
(strstr(argv[0], "texluajit") != NULL)) {
295
if ((strstr(argv[0], "luatexlua") != NULL) ||
296
(strstr(argv[0], "texlua") != NULL)) {
302
g = getopt_long_only(ac, av, "+", long_options, &option_index);
304
if (g == -1) /* End of arguments, exit the loop. */
306
if (g == '?') { /* Unknown option. */
308
fprintf(stderr,"%s: unrecognized option '%s'\n", argv[0], argv[optind-1]);
312
assert(g == 0); /* We have no short option names. */
314
if (ARGUMENT_IS("luaonly")) {
318
} else if (ARGUMENT_IS("lua")) {
319
startup_filename = optarg;
320
lua_offset = (optind - 1);
323
} else if (ARGUMENT_IS("jiton")) {
325
} else if (ARGUMENT_IS("jithash")) {
326
size_t len = strlen(optarg);
328
jithash_hashname = optarg;
330
WARNING2("hash name truncated to 15 characters from %d. (%s)",
332
jithash_hashname = (string) xmalloc(16);
333
strncpy(jithash_hashname, optarg, 15);
334
jithash_hashname[15] = 0;
338
} else if (ARGUMENT_IS("luahashchars")) {
339
show_luahashchars = 1;
341
} else if (ARGUMENT_IS("kpathsea-debug")) {
342
kpathsea_debug |= atoi(optarg);
344
} else if (ARGUMENT_IS("progname")) {
345
user_progname = optarg;
347
} else if (ARGUMENT_IS("jobname")) {
350
} else if (ARGUMENT_IS("fmt")) {
353
} else if (ARGUMENT_IS("output-directory")) {
354
output_directory = optarg;
356
} else if (ARGUMENT_IS("output-comment")) {
357
size_t len = strlen(optarg);
359
output_comment = optarg;
361
WARNING2("Comment truncated to 255 characters from %d. (%s)",
363
output_comment = (string) xmalloc(256);
364
strncpy(output_comment, optarg, 255);
365
output_comment[255] = 0;
368
} else if (ARGUMENT_IS("shell-restricted")) {
372
} else if (ARGUMENT_IS("output-format")) {
373
pdf_output_option = 1;
374
if (strcmp(optarg, "dvi") == 0) {
375
pdf_output_value = 0;
376
} else if (strcmp(optarg, "pdf") == 0) {
377
pdf_output_value = 2;
379
WARNING1("Ignoring unknown value `%s' for --output-format",
381
pdf_output_option = 0;
384
} else if (ARGUMENT_IS("draftmode")) {
385
pdf_draftmode_option = 1;
386
pdf_draftmode_value = 1;
388
} else if (ARGUMENT_IS("mktex")) {
389
kpse_maketex_option(optarg, true);
391
} else if (ARGUMENT_IS("no-mktex")) {
392
kpse_maketex_option(optarg, false);
394
} else if (ARGUMENT_IS("interaction")) {
395
/* These numbers match CPP defines */
396
if (STREQ(optarg, "batchmode")) {
397
interactionoption = 0;
398
} else if (STREQ(optarg, "nonstopmode")) {
399
interactionoption = 1;
400
} else if (STREQ(optarg, "scrollmode")) {
401
interactionoption = 2;
402
} else if (STREQ(optarg, "errorstopmode")) {
403
interactionoption = 3;
405
WARNING1("Ignoring unknown argument `%s' to --interaction",
409
} else if (ARGUMENT_IS("synctex")) {
410
/* Synchronize TeXnology: catching the command line option as a long */
411
synctexoption = (int) strtol(optarg, NULL, 0);
413
} else if (ARGUMENT_IS("help")) {
414
usagehelp(LUATEX_IHELP, BUG_ADDRESS);
416
} else if (ARGUMENT_IS("version")) {
417
print_version_banner();
419
puts("\n\nExecute '" my_name " --credits' for credits and version details.\n\n"
420
"There is NO warranty. Redistribution of this software is covered by\n"
421
"the terms of the GNU General Public License, version 2 or (at your option)\n"
422
"any later version. For more information about these matters, see the file\n"
423
"named COPYING and the LuaTeX source.\n\n"
425
"LuaTeX is Copyright 2014 Taco Hoekwater, the LuaTeX Team.\n"
426
"Libraries and JIT extensions by Luigi Scarso, the LuaTeX SwigLib team.\n");
428
"Copyright 2014 Taco Hoekwater, the LuaTeX Team.\n");
432
} else if (ARGUMENT_IS("credits")) {
434
initversionstring(&versions);
435
print_version_banner();
437
puts("\n\nThe LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater.\n"
438
MyName " merges and builds upon (parts of) the code from these projects:\n\n"
439
"tex by Donald Knuth\n"
440
"etex by Peter Breitenlohner, Phil Taylor and friends\n"
441
"omega by John Plaice and Yannis Haralambous\n"
442
"aleph by Giuseppe Bilotta\n"
443
"pdftex by Han The Thanh and friends\n"
444
"kpathsea by Karl Berry, Olaf Weber and others\n"
445
"lua by Roberto Ierusalimschy, Waldemar Celes\n"
446
" and Luiz Henrique de Figueiredo\n"
447
"metapost by John Hobby, Taco Hoekwater and friends.\n"
448
"poppler by Derek Noonburg, Kristian H\\ogsberg (partial)\n"
450
"fontforge by George Williams (partial)\n"
451
"luajit by Mike Pall\n\n"
453
"fontforge by George Williams (partial)\n\n"
455
"Some extensions to lua and additional lua libraries are used, as well as\n"
456
"libraries for graphic inclusion. More details can be found in the source.\n"
457
"Code development was sponsored by a grant from Colorado State University\n"
459
"via the 'oriental tex' project, the TeX User Groups, and donations.\n"
460
"The additional libraries and the LuaJIT extensions are provided by the LuaTeX SwigLib project.\n");
462
"via the 'oriental tex' project, the TeX User Groups, and donations.\n");
469
/* attempt to find |input_name| / |dump_name| */
472
startup_filename = xstrdup(argv[optind]);
475
} else if (argv[optind] && argv[optind][0] == '&') {
476
dump_name = xstrdup(argv[optind] + 1);
477
} else if (argv[optind] && argv[optind][0] != '\\') {
478
if (argv[optind][0] == '*') {
479
input_name = xstrdup(argv[optind] + 1);
481
firstfile = xstrdup(argv[optind]);
482
if ((strstr(firstfile, ".lua") ==
483
firstfile + strlen(firstfile) - 4)
484
|| (strstr(firstfile, ".luc") ==
485
firstfile + strlen(firstfile) - 4)
486
|| (strstr(firstfile, ".LUA") ==
487
firstfile + strlen(firstfile) - 4)
488
|| (strstr(firstfile, ".LUC") ==
489
firstfile + strlen(firstfile) - 4)) {
490
if (startup_filename == NULL) {
491
startup_filename = firstfile;
497
input_name = firstfile;
501
} else if (sargv[sargc-1] && sargv[sargc-1][0] != '-' &&
502
sargv[sargc-1][0] != '\\') {
503
if (sargv[sargc-1][0] == '&')
504
dump_name = xstrdup(sargv[sargc-1] + 1);
507
if (sargv[sargc-1][0] == '*')
508
input_name = xstrdup(sargv[sargc-1] + 1);
510
input_name = xstrdup(sargv[sargc-1]);
511
sargv[sargc-1] = normalize_quotes(input_name, "argument");
513
input_name = (char *)xbasename(input_name);
514
but without cast const => non-const. */
515
input_name += xbasename(input_name) - input_name;
516
p = strrchr(input_name, '.');
517
if (p != NULL && strcasecmp(p, ".tex") == 0)
520
c_job_name = normalize_quotes(input_name, "jobname");
522
if (safer_option) /* --safer implies --nosocket */
527
if (safer_option) /* --safer implies --nosocket */
530
/* Finalize the input filename. */
531
if (input_name != NULL) {
532
argv[optind] = normalize_quotes(input_name, "argument");
536
@ test for readability
538
#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) && \
539
(f=fopen(a,"r")) != NULL && !fclose(f)
542
static char *find_filename(char *name, const char *envkey)
545
char *dirname = NULL;
546
char *filename = NULL;
548
if (is_readable(name)) {
551
dirname = getenv(envkey);
552
if ((dirname != NULL) && strlen(dirname)) {
553
dirname = xstrdup(getenv(envkey));
554
if (*(dirname + strlen(dirname) - 1) == '/') {
555
*(dirname + strlen(dirname) - 1) = 0;
557
filename = xmalloc((unsigned) (strlen(dirname) + strlen(name) + 2));
558
filename = concat3(dirname, "/", name);
559
if (is_readable(filename)) {
571
static void init_kpse(void)
574
if (!user_progname) {
575
user_progname = dump_name;
576
} else if (!dump_name) {
577
dump_name = user_progname;
579
if (!user_progname) {
582
char *p = input_name + strlen(input_name) - 1;
583
while (p >= input_name) {
584
if (IS_DIR_SEP (*p)) {
591
user_progname = remove_suffix (input_name);
593
if (!user_progname) {
594
user_progname = kpse_program_basename(argv[0]);
598
dump_name = kpse_program_basename(argv[0]);
600
user_progname = dump_name;
603
kpse_set_program_enabled(kpse_fmt_format, MAKE_TEX_FMT_BY_DEFAULT,
606
kpse_set_program_name(argv[0], user_progname);
607
init_shell_escape(); /* set up 'restrictedshell' */
608
program_name_set = 1;
612
static void fix_dumpname(void)
616
/* adjust array for Pascal and provide extension, if needed */
617
dist = (int) (strlen(dump_name) - strlen(DUMP_EXT));
618
if (strstr(dump_name, DUMP_EXT) == dump_name + dist)
619
TEX_format_default = dump_name;
621
TEX_format_default = concat(dump_name, DUMP_EXT);
623
/* For |dump_name| to be NULL is a bug. */
631
@ Auxiliary function for kpse search
634
static const char *luatex_kpse_find_aux(lua_State *L, const char *name,
635
kpse_file_format_type format, const char *errname)
637
const char *filename;
639
altname = luaL_gsub(L, name, ".", "/"); /* Lua convention */
640
filename = kpse_find_file(altname, format, false);
641
if (filename == NULL) {
642
filename = kpse_find_file(name, format, false);
644
if (filename == NULL) {
645
lua_pushfstring(L, "\n\t[kpse %s searcher] file not found: " LUA_QS,
651
@ The lua search function.
653
When kpathsea is not initialized, then it runs the
654
normal lua function that is saved in the registry, otherwise
657
two registry ref variables are needed: one for the actual lua
658
function, the other for its environment .
661
static int lua_loader_function = 0;
663
static int luatex_kpse_lua_find(lua_State * L)
665
const char *filename;
667
name = luaL_checkstring(L, 1);
668
if (program_name_set == 0) {
669
lua_rawgeti(L, LUA_REGISTRYINDEX, lua_loader_function);
670
lua_pushvalue(L, -2);
674
filename = luatex_kpse_find_aux(L, name, kpse_lua_format, "lua");
675
if (filename == NULL)
676
return 1; /* library not found in this path */
677
if (luaL_loadfile(L, filename) != 0) {
678
luaL_error(L, "error loading module %s from file %s:\n\t%s",
679
lua_tostring(L, 1), filename, lua_tostring(L, -1));
681
return 1; /* library loaded successfully */
685
static int clua_loader_function = 0;
686
extern int searcher_C_luatex (lua_State *L, const char *name, const char *filename);
688
static int luatex_kpse_clua_find(lua_State * L)
690
const char *filename;
693
lua_pushliteral(L, "\n\t[C searcher disabled in safer mode]");
694
return 1; /* library not found in this path */
696
name = luaL_checkstring(L, 1);
697
if (program_name_set == 0) {
698
lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
699
lua_pushvalue(L, -2);
703
const char *path_saved;
704
char *prefix, *postfix, *p, *total;
708
filename = luatex_kpse_find_aux(L, name, kpse_clua_format, "C");
709
if (filename == NULL)
710
return 1; /* library not found in this path */
711
extensionless = strdup(filename);
712
if (!extensionless) return 1; /* allocation failure */
713
/* Fix Issue 850: replace '.' with LUA_DIRSEP */
714
temp_name = strdup(name);
716
if ((unsigned char)temp_name[j]=='\0') {
719
if ((unsigned char)temp_name[j]=='.'){
720
temp_name[j]=LUA_DIRSEP[0];
723
p = strstr(extensionless, temp_name);
724
if (!p) return 1; /* this would be exceedingly weird */
726
prefix = strdup(extensionless);
727
if (!prefix) return 1; /* allocation failure */
728
postfix = strdup(p+strlen(name));
729
if (!postfix) return 1; /* allocation failure */
730
total = malloc(strlen(prefix)+strlen(postfix)+2);
731
if (!total) return 1; /* allocation failure */
732
snprintf(total,strlen(prefix)+strlen(postfix)+2, "%s?%s", prefix, postfix);
733
/* save package.path */
734
lua_getglobal(L,"package");
735
lua_getfield(L,-1,"cpath");
736
path_saved = lua_tostring(L,-1);
738
/* set package.path = "?" */
739
lua_pushstring(L,total);
740
lua_setfield(L,-2,"cpath");
741
lua_pop(L,1); /* pop "package" */
743
lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
744
lua_pushstring(L, name);
746
/* restore package.path */
747
lua_getglobal(L,"package");
748
lua_pushstring(L,path_saved);
749
lua_setfield(L,-2,"cpath");
750
lua_pop(L,1); /* pop "package" */
758
@ Setting up the new search functions.
760
This replaces package.searchers[2] and package.searchers[3] with the
761
functions defined above.
764
static void setup_lua_path(lua_State * L)
766
lua_getglobal(L, "package");
768
lua_getfield(L, -1, "loaders");
770
lua_getfield(L, -1, "searchers");
772
lua_rawgeti(L, -1, 2); /* package.searchers[2] */
773
lua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
774
lua_pushcfunction(L, luatex_kpse_lua_find);
775
lua_rawseti(L, -2, 2); /* replace the normal lua loader */
777
lua_rawgeti(L, -1, 3); /* package.searchers[3] */
778
clua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
779
lua_pushcfunction(L, luatex_kpse_clua_find);
780
lua_rawseti(L, -2, 3); /* replace the normal lua lib loader */
782
lua_pop(L, 2); /* pop the array and table */
785
@ helper variables for the safe keeping of table ids
790
int newtoken_table_id;
795
int l_pack_type_index [PACK_TYPE_SIZE] ;
796
int l_group_code_index [GROUP_CODE_SIZE];
797
int l_math_style_name_index [MATH_STYLE_NAME_SIZE];
798
int l_dir_par_index [DIR_PAR_SIZE];
799
int l_dir_text_index [DIR_TEXT_SIZE];
802
#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
805
# define EXE_SUFFIXES ".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.ws;.tcl;.py;.pyw"
808
static void mk_suffixlist(void)
814
# if defined(__CYGWIN__)
815
v = xstrdup(EXE_SUFFIXES);
817
v = (char *) getenv("PATHEXT");
818
if (v) /* strlwr() exists also in MingW */
819
v = (char *) strlwr(xstrdup(v));
821
v = xstrdup(EXE_SUFFIXES);
827
while ((r = strchr(q, ';')) != NULL) {
834
suffixlist = (char **) xmalloc((n + 2) * sizeof(char *));
836
*p = xstrdup(".dll");
839
while ((r = strchr(q, ';')) != NULL) {
857
void lua_initialize(int ac, char **av)
860
char *given_file = NULL;
863
static char LC_CTYPE_C[] = "LC_CTYPE=C";
864
static char LC_COLLATE_C[] = "LC_COLLATE=C";
865
static char LC_NUMERIC_C[] = "LC_NUMERIC=C";
866
static char engine_luatex[] = "engine=" my_name;
867
/* Save to pass along to topenin. */
872
if (luatex_svn < 0) {
873
const char *fmt = "This is " MyName ", Version %s" WEB2CVERSION;
875
len = strlen(fmt) + strlen(luatex_version_string) ;
877
banner = xmalloc(len);
878
sprintf(banner, fmt, luatex_version_string);
880
const char *fmt = "This is " MyName ", Version %s" WEB2CVERSION " (rev %d)";
882
len = strlen(fmt) + strlen(luatex_version_string) + 6;
883
banner = xmalloc(len);
884
sprintf(banner, fmt, luatex_version_string, luatex_svn);
886
luatex_banner = banner;
887
kpse_invocation_name = kpse_program_basename(argv[0]);
892
if (FILESTRCASEEQ(kpse_invocation_name, "texluajitc"))
893
exit(luac_main(ac, av));
894
if (STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac")) {
895
char *argv1 = xmalloc (strlen ("luajittex") + 1);
897
strcpy (av[1], "luajittex");
898
exit(luac_main(--ac, ++av));
901
if (FILESTRCASEEQ(kpse_invocation_name, "texluac"))
902
exit(luac_main(ac, av));
903
if (STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac")) {
904
strcpy(av[1], "luatex");
905
exit(luac_main(--ac, ++av));
909
#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
913
/* Must be initialized before options are parsed. */
914
interactionoption = 4;
917
/* 0 means "disable Synchronize TeXnology".
918
synctexoption is a *.web variable.
919
We initialize it to a weird value to catch the -synctex command line flag
920
At runtime, if synctexoption is not |INT_MAX|, then it contains the command line option provided,
921
otherwise no such option was given by the user. */
922
#define SYNCTEX_NO_OPTION INT_MAX
923
synctexoption = SYNCTEX_NO_OPTION;
925
/* parse commandline */
926
parse_options(ac, av);
928
shellenabledp = true;
930
/* make sure that the locale is 'sane' (for lua) */
933
putenv(LC_COLLATE_C);
934
putenv(LC_NUMERIC_C);
936
/* this is sometimes needed */
937
putenv(engine_luatex);
941
/* init internalized strings */
944
lua_pushstring(Luas,"lua.functions");
946
lua_settable(Luas,LUA_REGISTRYINDEX);
948
/* here start the key definitions */
950
set_l_group_code_index;
951
set_l_math_style_name_index;
953
set_l_dir_text_index;
955
prepare_cmdline(Luas, argv, argc, lua_offset); /* collect arguments */
956
setup_lua_path(Luas);
958
if (startup_filename != NULL) {
959
given_file = xstrdup(startup_filename);
960
startup_filename = find_filename(startup_filename, "LUATEXDIR");
962
/* now run the file */
963
if (startup_filename != NULL) {
965
/* hide the 'tex' and 'pdf' table */
966
tex_table_id = hide_lua_table(Luas, "tex");
967
newtoken_table_id = hide_lua_table(Luas, "newtoken");
968
token_table_id = hide_lua_table(Luas, "token");
969
node_table_id = hide_lua_table(Luas, "node");
970
pdf_table_id = hide_lua_table(Luas, "pdf");
972
if (luaL_loadfile(Luas, startup_filename)) {
973
fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
977
init_tex_table(Luas);
978
if (lua_pcall(Luas, 0, 0, 0)) {
979
fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
983
/* no filename? quit now! */
985
get_lua_string("texconfig", "jobname", &input_name);
988
get_lua_string("texconfig", "formatname", &dump_name);
993
/* this is not strictly needed but it pleases valgrind */
997
/* unhide the 'tex' and 'pdf' table */
998
unhide_lua_table(Luas, "tex", tex_table_id);
999
unhide_lua_table(Luas, "pdf", pdf_table_id);
1000
unhide_lua_table(Luas, "newtoken", newtoken_table_id);
1001
unhide_lua_table(Luas, "token", token_table_id);
1002
unhide_lua_table(Luas, "node", node_table_id);
1006
get_lua_boolean("texconfig", "kpse_init", &kpse_init);
1008
if (kpse_init != 0) {
1009
luainit = 0; /* re-enable loading of texmf.cnf values, see luatex.ch */
1012
/* |prohibit_file_trace| (boolean) */
1014
get_lua_boolean("texconfig", "trace_file_names", &tracefilenames);
1016
/* |file_line_error| */
1017
filelineerrorstylep = false;
1018
get_lua_boolean("texconfig", "file_line_error", &filelineerrorstylep);
1020
/* |halt_on_error| */
1021
haltonerrorp = false;
1022
get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp);
1024
/* |restrictedshell| */
1026
get_lua_string("texconfig", "shell_escape", &v1);
1028
if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
1030
} else if (*v1 == 'p') {
1032
restrictedshell = 1;
1036
/* If shell escapes are restricted, get allowed cmds from cnf. */
1037
if (shellenabledp && restrictedshell == 1) {
1039
get_lua_string("texconfig", "shell_escape_commands", &v1);
1041
mk_shellcmdlist(v1);
1051
fprintf(stdout, "%s file %s not found\n",
1052
(lua_only ? "Script" : "Configuration"), given_file);
1055
fprintf(stdout, "No %s file given\n",
1056
(lua_only ? "script" : "configuration"));
1068
void check_texconfig_init(void)
1071
lua_getglobal(Luas, "texconfig");
1072
if (lua_istable(Luas, -1)) {
1073
lua_getfield(Luas, -1, "init");
1074
if (lua_isfunction(Luas, -1)) {
1075
int i = lua_pcall(Luas, 0, 0, 0);
1077
/* Can't be more precise here, called before TeX initialization */
1078
fprintf(stderr, "This went wrong: %s\n",
1079
lua_tostring(Luas, -1));
1088
void write_svnversion(char *v)
1091
char *a = xstrdup(v);
1092
size_t l = strlen("$Id: luatex.web ");
1098
while (*n != '\0' && *n != ' ')
1101
fprintf(stdout, " luatex.web >= v%s", a);