~ubuntu-branches/ubuntu/wily/luatex/wily

« back to all changes in this revision

Viewing changes to source/texk/web2c/luatexdir/lua/luainit.w

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2010-04-29 00:47:19 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100429004719-o42etkqe90n97b9e
Tags: 0.60.1-1
* new upstream release, adapt build-script patch
* disable patch: upstream-epstopdf_cc_no_xpdf_patching, included upstream
* disable patch: libpoppler-0.12, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
% luainit.w
 
2
 
3
% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
 
4
 
 
5
% This file is part of LuaTeX.
 
6
 
 
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.
 
11
 
 
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.
 
16
 
 
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/>. 
 
19
 
 
20
@ @c
 
21
#include "openbsd-compat.h"
 
22
#ifdef HAVE_ASPRINTF            /* asprintf is not defined in openbsd-compat.h, but in stdio.h */
 
23
#  include <stdio.h>
 
24
#endif
 
25
#include <kpathsea/c-stat.h>
 
26
 
 
27
#include "lua/luatex-api.h"
 
28
#include "ptexlib.h"
 
29
 
 
30
static const char _svn_version[] =
 
31
    "$Id: luainit.w 3621 2010-04-15 16:08:22Z taco $ $URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.1/source/texk/web2c/luatexdir/lua/luainit.w $";
 
32
 
 
33
 
34
TH: TODO
 
35
 
 
36
This file is getting a bit messy, but it is not simple to fix unilaterally.
 
37
 
 
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. 
 
43
 
 
44
In fact, it sets three C variables:
 
45
 
 
46
  |program_invocation_name|  |program_invocation_short_name|  |kpse->program_name|
 
47
 
 
48
and four environment variables:
 
49
 
 
50
  SELFAUTOLOC  SELFAUTODIR  SELFAUTOPARENT  progname
 
51
 
 
52
@c
 
53
const_string LUATEX_IHELP[] = {
 
54
    "Usage: luatex --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]",
 
55
    "   or: luatex --lua=FILE [OPTION]... \\FIRST-LINE",
 
56
    "   or: luatex --lua=FILE [OPTION]... &FMT ARGS",
 
57
    "  Run LuaTeX on TEXNAME, usually creating TEXNAME.pdf.",
 
58
    "  Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.",
 
59
    "",
 
60
    "  Alternatively, if the first non-option argument begins with a backslash,",
 
61
    "  luatex interprets all non-option arguments as an input line.",
 
62
    "",
 
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.",
 
66
    "",
 
67
    "  If no arguments or options are specified, prompt for input.",
 
68
    "",
 
69
    "  The following regular options are understood: ",
 
70
    "",
 
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 iniluatex, 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 DIR as the directory to write files to",
 
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",
 
103
    "",
 
104
    "Alternate behaviour models can be obtained by special switches",
 
105
    "",
 
106
    "  --luaonly                run a lua file, then exit",
 
107
    "  --luaconly               byte-compile a lua file, then exit",
 
108
    "",
 
109
    "See the reference manual for more information about the startup process.",
 
110
    NULL
 
111
};
 
112
 
 
113
@ The return value will be the directory of the executable, e.g.: \.{c:/TeX/bin}
 
114
@c
 
115
static char *ex_selfdir(char *argv0)
 
116
{
 
117
#if defined(WIN32)
 
118
    char path[PATH_MAX], *fp;
 
119
 
 
120
    /* SearchPath() always gives back an absolute directory */
 
121
    if (SearchPath(NULL, argv0, ".exe", PATH_MAX, path, NULL) == 0)
 
122
        FATAL1("Can't determine where the executable %s is.\n", argv0);
 
123
    /* slashify the dirname */
 
124
    for (fp = path; fp && *fp; fp++)
 
125
        if (IS_DIR_SEP(*fp))
 
126
            *fp = DIR_SEP;
 
127
    return xdirname(path);
 
128
#else
 
129
    return kpse_selfdir(argv0);
 
130
#endif
 
131
}
 
132
 
 
133
@ @c
 
134
static void
 
135
prepare_cmdline(lua_State * L, char **argv, int argc, int zero_offset)
 
136
{
 
137
    int i;
 
138
    char *s;
 
139
    luaL_checkstack(L, argc + 3, "too many arguments to script");
 
140
    lua_createtable(L, 0, 0);
 
141
    for (i = 0; i < argc; i++) {
 
142
        lua_pushstring(L, argv[i]);
 
143
        lua_rawseti(L, -2, (i - zero_offset));
 
144
    }
 
145
    lua_setglobal(L, "arg");
 
146
    lua_getglobal(L, "os");
 
147
    s = ex_selfdir(argv[0]);
 
148
    lua_pushstring(L, s);
 
149
    xfree(s);
 
150
    lua_setfield(L, -2, "selfdir");
 
151
    return;
 
152
}
 
153
 
 
154
@ @c
 
155
string input_name = NULL;
 
156
 
 
157
static string user_progname = NULL;
 
158
 
 
159
char *startup_filename = NULL;
 
160
int lua_only = 0;
 
161
int lua_offset = 0;
 
162
 
 
163
int safer_option = 0;
 
164
int nosocket_option = 0;
 
165
 
 
166
@ Reading the options.  
 
167
 
 
168
@ Test whether getopt found an option ``A''.
 
169
Assumes the option index is in the variable |option_index|, and the
 
170
option table in a variable |long_options|.  
 
171
 
 
172
@c
 
173
#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
 
174
 
 
175
/* SunOS cc can't initialize automatic structs, so make this static.  */
 
176
static struct option long_options[]
 
177
= { {"fmt", 1, 0, 0},
 
178
{"lua", 1, 0, 0},
 
179
{"luaonly", 0, 0, 0},
 
180
{"safer", 0, &safer_option, 1},
 
181
{"nosocket", 0, &nosocket_option, 1},
 
182
{"help", 0, 0, 0},
 
183
{"ini", 0, &ini_version, 1},
 
184
{"interaction", 1, 0, 0},
 
185
{"halt-on-error", 0, &haltonerrorp, 1},
 
186
{"kpathsea-debug", 1, 0, 0},
 
187
{"progname", 1, 0, 0},
 
188
{"version", 0, 0, 0},
 
189
{"credits", 0, 0, 0},
 
190
{"recorder", 0, &recorder_enabled, 1},
 
191
{"etex", 0, 0, 0},
 
192
{"output-comment", 1, 0, 0},
 
193
{"output-directory", 1, 0, 0},
 
194
{"draftmode", 0, 0, 0},
 
195
{"output-format", 1, 0, 0},
 
196
{"shell-escape", 0, &shellenabledp, 1},
 
197
{"no-shell-escape", 0, &shellenabledp, -1},
 
198
{"enable-write18", 0, &shellenabledp, 1},
 
199
{"disable-write18", 0, &shellenabledp, -1},
 
200
{"shell-restricted", 0, 0, 0},
 
201
{"debug-format", 0, &debug_format_file, 1},
 
202
{"file-line-error-style", 0, &filelineerrorstylep, 1},
 
203
{"no-file-line-error-style", 0, &filelineerrorstylep, -1},
 
204
      /* Shorter option names for the above. */
 
205
{"file-line-error", 0, &filelineerrorstylep, 1},
 
206
{"no-file-line-error", 0, &filelineerrorstylep, -1},
 
207
{"jobname", 1, 0, 0},
 
208
{"parse-first-line", 0, &parsefirstlinep, 1},
 
209
{"no-parse-first-line", 0, &parsefirstlinep, -1},
 
210
{"translate-file", 1, 0, 0},
 
211
{"default-translate-file", 1, 0, 0},
 
212
{"8bit", 0, 0, 0},
 
213
{"mktex", 1, 0, 0},
 
214
{"no-mktex", 1, 0, 0},
 
215
/* Synchronization: just like "interaction" above */
 
216
{"synctex", 1, 0, 0},
 
217
{0, 0, 0, 0}
 
218
};
 
219
 
 
220
@ @c
 
221
static void parse_options(int argc, char **argv)
 
222
{
 
223
    int g;                      /* `getopt' return code.  */
 
224
    int option_index;
 
225
    char *firstfile = NULL;
 
226
    opterr = 0;                 /* dont whine */
 
227
    if ((strstr(argv[0], "luatexlua") != NULL) ||
 
228
        (strstr(argv[0], "texlua") != NULL)) {
 
229
        lua_only = 1;
 
230
        luainit = 1;
 
231
    }
 
232
    for (;;) {
 
233
        g = getopt_long_only(argc, argv, "+", long_options, &option_index);
 
234
 
 
235
        if (g == -1)            /* End of arguments, exit the loop.  */
 
236
            break;
 
237
        if (g == '?')           /* Unknown option.  */
 
238
            continue;
 
239
 
 
240
        assert(g == 0);         /* We have no short option names.  */
 
241
 
 
242
        if (ARGUMENT_IS("luaonly")) {
 
243
            lua_only = 1;
 
244
            lua_offset = optind;
 
245
            luainit = 1;
 
246
        } else if (ARGUMENT_IS("lua")) {
 
247
            startup_filename = optarg;
 
248
            lua_offset = (optind - 1);
 
249
            luainit = 1;
 
250
 
 
251
        } else if (ARGUMENT_IS("kpathsea-debug")) {
 
252
            kpathsea_debug |= atoi(optarg);
 
253
 
 
254
        } else if (ARGUMENT_IS("progname")) {
 
255
            user_progname = optarg;
 
256
 
 
257
        } else if (ARGUMENT_IS("jobname")) {
 
258
            c_job_name = optarg;
 
259
 
 
260
        } else if (ARGUMENT_IS("fmt")) {
 
261
            dump_name = optarg;
 
262
 
 
263
        } else if (ARGUMENT_IS("output-directory")) {
 
264
            output_directory = optarg;
 
265
 
 
266
        } else if (ARGUMENT_IS("output-comment")) {
 
267
            size_t len = strlen(optarg);
 
268
            if (len < 256) {
 
269
                output_comment = optarg;
 
270
            } else {
 
271
                WARNING2("Comment truncated to 255 characters from %d. (%s)",
 
272
                         (int) len, optarg);
 
273
                output_comment = (string) xmalloc(256);
 
274
                strncpy(output_comment, optarg, 255);
 
275
                output_comment[255] = 0;
 
276
            }
 
277
 
 
278
        } else if (ARGUMENT_IS("shell-restricted")) {
 
279
            shellenabledp = 1;
 
280
            restrictedshell = 1;
 
281
 
 
282
        } else if (ARGUMENT_IS("output-format")) {
 
283
            pdf_output_option = 1;
 
284
            if (strcmp(optarg, "dvi") == 0) {
 
285
                pdf_output_value = 0;
 
286
            } else if (strcmp(optarg, "pdf") == 0) {
 
287
                pdf_output_value = 2;
 
288
            } else {
 
289
                WARNING1("Ignoring unknown value `%s' for --output-format",
 
290
                         optarg);
 
291
                pdf_output_option = 0;
 
292
            }
 
293
 
 
294
        } else if (ARGUMENT_IS("draftmode")) {
 
295
            pdf_draftmode_option = 1;
 
296
            pdf_draftmode_value = 1;
 
297
 
 
298
        } else if (ARGUMENT_IS("mktex")) {
 
299
            kpse_maketex_option(optarg, true);
 
300
 
 
301
        } else if (ARGUMENT_IS("no-mktex")) {
 
302
            kpse_maketex_option(optarg, false);
 
303
 
 
304
        } else if (ARGUMENT_IS("interaction")) {
 
305
            /* These numbers match CPP defines */
 
306
            if (STREQ(optarg, "batchmode")) {
 
307
                interactionoption = 0;
 
308
            } else if (STREQ(optarg, "nonstopmode")) {
 
309
                interactionoption = 1;
 
310
            } else if (STREQ(optarg, "scrollmode")) {
 
311
                interactionoption = 2;
 
312
            } else if (STREQ(optarg, "errorstopmode")) {
 
313
                interactionoption = 3;
 
314
            } else {
 
315
                WARNING1("Ignoring unknown argument `%s' to --interaction",
 
316
                         optarg);
 
317
            }
 
318
 
 
319
        } else if (ARGUMENT_IS("synctex")) {
 
320
            /* Synchronize TeXnology: catching the command line option as a long  */
 
321
            synctexoption = (int) strtol(optarg, NULL, 0);
 
322
 
 
323
        } else if (ARGUMENT_IS("help")) {
 
324
            usagehelp(LUATEX_IHELP, BUG_ADDRESS);
 
325
 
 
326
        } else if (ARGUMENT_IS("version")) {
 
327
            print_version_banner();
 
328
            /* *INDENT-OFF* */
 
329
            puts("\n\nExecute  'luatex --credits'  for credits and version details.\n\n"
 
330
                 "There is NO warranty. Redistribution of this software is covered by\n"
 
331
                 "the terms of the GNU General Public License, version 2. For more\n"
 
332
                 "information about these matters, see the file named COPYING and\n"
 
333
                 "the LuaTeX source.\n\n" 
 
334
                 "Copyright 2009 Taco Hoekwater, the LuaTeX Team.\n");
 
335
            /* *INDENT-ON* */
 
336
            uexit(0);
 
337
        } else if (ARGUMENT_IS("credits")) {
 
338
            char *versions;
 
339
            initversionstring(&versions);
 
340
            print_version_banner();
 
341
            /* *INDENT-OFF* */
 
342
            puts("\n\nThe LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater.\n" 
 
343
                 "LuaTeX merges and builds upon (parts of) the code from these projects:\n\n" 
 
344
                 "tex       by Donald Knuth\n" 
 
345
                 "etex      by Peter Breitenlohner, Phil Taylor and friends\n" 
 
346
                 "omega     by John Plaice and Yannis Haralambous\n" 
 
347
                 "aleph     by Giuseppe Bilotta\n" 
 
348
                 "pdftex    by Han The Thanh and friends\n" 
 
349
                 "kpathsea  by Karl Berry, Olaf Weber and others\n" 
 
350
                 "lua       by Roberto Ierusalimschy, Waldemar Celes,\n" 
 
351
                 "             Luiz Henrique de Figueiredo\n" 
 
352
                 "metapost  by John Hobby, Taco Hoekwater and friends.\n" 
 
353
                 "xpdf      by Derek Noonburg (partial)\n" 
 
354
                 "fontforge by George Williams (partial)\n\n" 
 
355
                 "Some extensions to lua and additional lua libraries are used, as well as\n" 
 
356
                 "libraries for graphic inclusion. More details can be found in the source.\n" 
 
357
                 "Code development was sponsored by a grant from Colorado State University\n" 
 
358
                 "via the 'oriental tex' project, the TeX User Groups, and donations.\n");
 
359
            /* *INDENT-ON* */
 
360
            puts(versions);
 
361
            uexit(0);
 
362
        }
 
363
    }
 
364
    /* attempt to find |input_name| / |dump_name| */
 
365
    if (lua_only) {
 
366
        if (argv[optind]) {
 
367
           startup_filename = strdup(argv[optind]);
 
368
           lua_offset = optind;
 
369
        }
 
370
    } else if (argv[optind] && argv[optind][0] == '&') {
 
371
        dump_name = strdup(argv[optind] + 1);
 
372
    } else if (argv[optind] && argv[optind][0] != '\\') {
 
373
        if (argv[optind][0] == '*') {
 
374
            input_name = strdup(argv[optind] + 1);
 
375
        } else {
 
376
            firstfile = strdup(argv[optind]);
 
377
            if ((strstr(firstfile, ".lua") ==
 
378
                 firstfile + strlen(firstfile) - 4)
 
379
                || (strstr(firstfile, ".luc") ==
 
380
                    firstfile + strlen(firstfile) - 4)
 
381
                || (strstr(firstfile, ".LUA") ==
 
382
                    firstfile + strlen(firstfile) - 4)
 
383
                || (strstr(firstfile, ".LUC") ==
 
384
                    firstfile + strlen(firstfile) - 4)) {
 
385
                if (startup_filename == NULL) {
 
386
                   startup_filename = firstfile;
 
387
                   lua_offset = optind;
 
388
                   lua_only = 1;
 
389
                   luainit = 1;
 
390
                }
 
391
            } else {
 
392
                input_name = firstfile;
 
393
            }
 
394
        }
 
395
    }
 
396
    if (safer_option)           /* --safer implies --nosocket */
 
397
        nosocket_option = 1;
 
398
 
 
399
    /* Finalize the input filename. */
 
400
    if (input_name != NULL) {
 
401
        argv[optind] = normalize_quotes(input_name, "argument");
 
402
    }
 
403
}
 
404
 
 
405
@ test for readability 
 
406
@c
 
407
#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) &&  \
 
408
  (f=fopen(a,"r")) != NULL && !fclose(f)
 
409
 
 
410
@ @c
 
411
static char *find_filename(char *name, const char *envkey)
 
412
{
 
413
    struct stat finfo;
 
414
    char *dirname = NULL;
 
415
    char *filename = NULL;
 
416
    FILE *f;
 
417
    if (is_readable(name)) {
 
418
        return name;
 
419
    } else {
 
420
        dirname = getenv(envkey);
 
421
        if ((dirname != NULL) && strlen(dirname)) {
 
422
            dirname = strdup(getenv(envkey));
 
423
            if (*(dirname + strlen(dirname) - 1) == '/') {
 
424
                *(dirname + strlen(dirname) - 1) = 0;
 
425
            }
 
426
            filename = xmalloc((unsigned) (strlen(dirname) + strlen(name) + 2));
 
427
            filename = concat3(dirname, "/", name);
 
428
            if (is_readable(filename)) {
 
429
                xfree(dirname);
 
430
                return filename;
 
431
            }
 
432
            xfree(filename);
 
433
        }
 
434
    }
 
435
    return NULL;
 
436
}
 
437
 
 
438
 
 
439
@ @c
 
440
static char *cleaned_invocation_name(char *arg)
 
441
{
 
442
    char *ret, *dot;
 
443
    const char *start = xbasename(arg);
 
444
    ret = xstrdup(start);
 
445
    dot = index(ret, '.');
 
446
    if (dot != NULL) {
 
447
        *dot = 0;               /* chop */
 
448
    }
 
449
    return ret;
 
450
}
 
451
 
 
452
@ @c
 
453
static void init_kpse(void)
 
454
{
 
455
 
 
456
    if (!user_progname) {
 
457
        user_progname = dump_name;
 
458
    } else if (!dump_name) {
 
459
        dump_name = user_progname;
 
460
    }
 
461
    if (!user_progname) {
 
462
        if (ini_version) {
 
463
            user_progname = input_name;
 
464
            if (!user_progname) {
 
465
                user_progname = cleaned_invocation_name(argv[0]);
 
466
            }
 
467
        } else {
 
468
            if (!dump_name) {
 
469
                dump_name = cleaned_invocation_name(argv[0]);
 
470
            }
 
471
            user_progname = dump_name;
 
472
        }
 
473
    }
 
474
    kpse_set_program_enabled(kpse_fmt_format, MAKE_TEX_FMT_BY_DEFAULT,
 
475
                             kpse_src_compile);
 
476
 
 
477
    kpse_set_program_name(argv[0], user_progname);
 
478
    init_shell_escape();        /* set up 'restrictedshell' */
 
479
    program_name_set = 1;
 
480
}
 
481
 
 
482
@ @c
 
483
static void fix_dumpname(void)
 
484
{
 
485
    int dist;
 
486
    if (dump_name) {
 
487
        /* adjust array for Pascal and provide extension, if needed */
 
488
        dist = (int) (strlen(dump_name) - strlen(DUMP_EXT));
 
489
        if (strstr(dump_name, DUMP_EXT) == dump_name + dist)
 
490
            TEX_format_default = dump_name;
 
491
        else
 
492
            TEX_format_default = concat(dump_name, DUMP_EXT);
 
493
    } else {
 
494
        /* For |dump_name| to be NULL is a bug.  */
 
495
        if (!ini_version)
 
496
            abort();
 
497
    }
 
498
}
 
499
 
 
500
@ lua require patch
 
501
 
 
502
@ Auxiliary function for kpse search
 
503
 
 
504
@c
 
505
static const char *luatex_kpse_find_aux(lua_State *L, const char *name,
 
506
        kpse_file_format_type format, const char *errname)
 
507
{
 
508
    const char *filename;
 
509
    const char *altname;
 
510
    altname = luaL_gsub(L, name, ".", "/"); /* Lua convention */
 
511
    filename = kpse_find_file(altname, format, false);
 
512
    if (filename == NULL) {
 
513
        filename = kpse_find_file(name, format, false);
 
514
    }
 
515
    if (filename == NULL) {
 
516
        lua_pushfstring(L, "\n\t[kpse %s searcher] file not found: " LUA_QS,
 
517
                        errname, name);
 
518
    }
 
519
    return filename;
 
520
}
 
521
 
 
522
@ The lua search function.
 
523
 
 
524
When kpathsea is not initialized, then it runs the
 
525
normal lua function that is saved in the registry, otherwise
 
526
it uses kpathsea.
 
527
 
 
528
two registry ref variables are needed: one for the actual lua 
 
529
function, the other for its environment .
 
530
 
 
531
@c
 
532
static int lua_loader_function = 0;
 
533
static int lua_loader_env = 0;
 
534
 
 
535
static int luatex_kpse_lua_find(lua_State * L)
 
536
{
 
537
    const char *filename;
 
538
    const char *name;
 
539
    name = luaL_checkstring(L, 1);
 
540
    if (program_name_set == 0) {
 
541
        lua_CFunction orig_func;
 
542
        lua_rawgeti(L, LUA_REGISTRYINDEX, lua_loader_function);
 
543
        lua_rawgeti(L, LUA_REGISTRYINDEX, lua_loader_env);
 
544
        lua_replace(L, LUA_ENVIRONINDEX);
 
545
        orig_func = lua_tocfunction(L, -1);
 
546
        lua_pop(L, 1);
 
547
        return (orig_func) (L);
 
548
    }
 
549
    filename = luatex_kpse_find_aux(L, name, kpse_lua_format, "lua");
 
550
    if (filename == NULL)
 
551
        return 1;               /* library not found in this path */
 
552
    if (luaL_loadfile(L, filename) != 0) {
 
553
        luaL_error(L, "error loading module %s from file %s:\n\t%s",
 
554
                   lua_tostring(L, 1), filename, lua_tostring(L, -1));
 
555
    }
 
556
    return 1;                   /* library loaded successfully */
 
557
}
 
558
 
 
559
@ @c
 
560
static int clua_loader_function = 0;
 
561
static int clua_loader_env = 0;
 
562
 
 
563
static int luatex_kpse_clua_find(lua_State * L)
 
564
{
 
565
    const char *filename;
 
566
    const char *name;
 
567
    if (safer_option) {
 
568
        lua_pushliteral(L, "\n\t[C searcher disabled in safer mode]");
 
569
        return 1;               /* library not found in this path */
 
570
    }
 
571
    name = luaL_checkstring(L, 1);
 
572
    if (program_name_set == 0) {
 
573
        lua_CFunction orig_func;
 
574
        lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
 
575
        lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_env);
 
576
        lua_replace(L, LUA_ENVIRONINDEX);
 
577
        orig_func = lua_tocfunction(L, -1);
 
578
        lua_pop(L, 1);
 
579
        return (orig_func) (L);
 
580
    }
 
581
    filename = luatex_kpse_find_aux(L, name, kpse_clua_format, "C");
 
582
    if (filename == NULL)
 
583
        return 1;               /* library not found in this path */
 
584
    return loader_C_luatex(L, name, filename);
 
585
}
 
586
 
 
587
@ @c
 
588
static int clua_loadall_function = 0;
 
589
static int clua_loadall_env = 0;
 
590
 
 
591
static int luatex_kpse_cluaall_find(lua_State * L)
 
592
{
 
593
    const char *filename;
 
594
    const char *name;
 
595
    char *fixedname;
 
596
    const char *p = NULL;
 
597
    if (safer_option) {
 
598
        lua_pushliteral(L, "\n\t[All-in-one searcher disabled in safer mode]");
 
599
        return 1;               /* library not found in this path */
 
600
    }
 
601
    name = luaL_checkstring(L, 1);
 
602
    p = strchr(name, '.');
 
603
    if (program_name_set == 0) {
 
604
        lua_CFunction orig_func;
 
605
        lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loadall_function);
 
606
        lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loadall_env);
 
607
        lua_replace(L, LUA_ENVIRONINDEX);
 
608
        orig_func = lua_tocfunction(L, -1);
 
609
        lua_pop(L, 1);
 
610
        return (orig_func) (L);
 
611
    }
 
612
    if (p == NULL) return 0;  /* is root */
 
613
    fixedname = xmalloc((size_t)(p - name)+1);
 
614
    memcpy(fixedname,name,(size_t)(p - name));
 
615
    fixedname[(p - name)] = '\0';
 
616
    filename = luatex_kpse_find_aux(L, fixedname, kpse_clua_format, "All-in-one");
 
617
    free(fixedname);
 
618
    if (filename == NULL)
 
619
        return 1;               /* library not found in this path */
 
620
    return loader_Call_luatex(L, name, filename);
 
621
}
 
622
 
 
623
@ Setting up the new search functions. 
 
624
 
 
625
 This replaces package.loaders[2] with the function defined above.
 
626
 
 
627
@c
 
628
static void setup_lua_path(lua_State * L)
 
629
{
 
630
    lua_getglobal(L, "package");
 
631
    lua_getfield(L, -1, "loaders");
 
632
    lua_rawgeti(L, -1, 2);      /* package.loaders[2] */
 
633
    lua_getfenv(L, -1);
 
634
    lua_loader_env = luaL_ref(L, LUA_REGISTRYINDEX);
 
635
    lua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
 
636
    lua_pushcfunction(L, luatex_kpse_lua_find);
 
637
    lua_rawseti(L, -2, 2);      /* replace the normal lua loader */
 
638
 
 
639
    lua_rawgeti(L, -1, 3);      /* package.loaders[3] */
 
640
    lua_getfenv(L, -1);
 
641
    clua_loader_env = luaL_ref(L, LUA_REGISTRYINDEX);
 
642
    clua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
 
643
    lua_pushcfunction(L, luatex_kpse_clua_find);
 
644
    lua_rawseti(L, -2, 3);      /* replace the normal lua lib loader */
 
645
 
 
646
    lua_rawgeti(L, -1, 4);      /* package.loaders[4] */
 
647
    lua_getfenv(L, -1);
 
648
    clua_loadall_env = luaL_ref(L, LUA_REGISTRYINDEX);
 
649
    clua_loadall_function = luaL_ref(L, LUA_REGISTRYINDEX);
 
650
    lua_pushcfunction(L, luatex_kpse_cluaall_find);
 
651
    lua_rawseti(L, -2, 4);      /* replace the normal lua lib loader */
 
652
 
 
653
    lua_pop(L, 2);              /* pop the array and table */
 
654
}
 
655
 
 
656
@ helper variables for the safe keeping of table ids
 
657
 
 
658
@c
 
659
int tex_table_id;
 
660
int pdf_table_id;
 
661
int token_table_id;
 
662
int node_table_id;
 
663
 
 
664
 
 
665
#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
 
666
char **suffixlist;
 
667
 
 
668
#  define EXE_SUFFIXES ".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.ws;.tcl;.py;.pyw"
 
669
 
 
670
@ @c
 
671
static void mk_suffixlist(void)
 
672
{
 
673
    char **p;
 
674
    char *q, *r, *v;
 
675
    int n;
 
676
 
 
677
#  if defined(__CYGWIN__)
 
678
    v = xstrdup(EXE_SUFFIXES);
 
679
#  else
 
680
    v = (char *) getenv("PATHEXT");
 
681
    if (v)                      /* strlwr() exists also in MingW */
 
682
        v = (char *) strlwr(xstrdup(v));
 
683
    else
 
684
        v = xstrdup(EXE_SUFFIXES);
 
685
#  endif
 
686
 
 
687
    q = v;
 
688
    n = 0;
 
689
 
 
690
    while ((r = strchr(q, ';')) != NULL) {
 
691
        n++;
 
692
        r++;
 
693
        q = r;
 
694
    }
 
695
    if (*q)
 
696
        n++;
 
697
    suffixlist = (char **) xmalloc((n + 2) * sizeof(char *));
 
698
    p = suffixlist;
 
699
    *p = xstrdup(".dll");
 
700
    p++;
 
701
    q = v;
 
702
    while ((r = strchr(q, ';')) != NULL) {
 
703
        *r = '\0';
 
704
        *p = xstrdup(q);
 
705
        p++;
 
706
        r++;
 
707
        q = r;
 
708
    }
 
709
    if (*q) {
 
710
        *p = xstrdup(q);
 
711
        p++;
 
712
    }
 
713
    *p = NULL;
 
714
    free(v);
 
715
}
 
716
#endif
 
717
 
 
718
@ @c
 
719
void lua_initialize(int ac, char **av)
 
720
{
 
721
 
 
722
    char *given_file = NULL;
 
723
    char *banner;
 
724
    int kpse_init;
 
725
    static char LC_CTYPE_C[] = "LC_CTYPE=C";
 
726
    static char LC_COLLATE_C[] = "LC_COLLATE=C";
 
727
    static char LC_NUMERIC_C[] = "LC_NUMERIC=C";
 
728
    static char engine_luatex[] = "engine=luatex";
 
729
    /* Save to pass along to topenin.  */
 
730
    argc = ac;
 
731
    argv = av;
 
732
 
 
733
    if (luatex_svn < 0) {
 
734
        if (asprintf(&banner, "This is LuaTeX, Version %s-%d",
 
735
                     luatex_version_string, luatex_date_info) < 0) {
 
736
            exit(EXIT_FAILURE);
 
737
        }
 
738
    } else {
 
739
        if (asprintf(&banner, "This is LuaTeX, Version %s-%d (rev %d)",
 
740
                     luatex_version_string, luatex_date_info, luatex_svn) < 0) {
 
741
            exit(EXIT_FAILURE);
 
742
        }
 
743
    }
 
744
    ptexbanner = banner;
 
745
 
 
746
    program_invocation_name = cleaned_invocation_name(argv[0]);
 
747
 
 
748
    /* be 'luac' */
 
749
    if (argc > 1 &&
 
750
        (STREQ(program_invocation_name, "texluac") ||
 
751
         STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac"))) {
 
752
        exit(luac_main(ac, av));
 
753
    }
 
754
#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
 
755
    mk_suffixlist();
 
756
#endif
 
757
 
 
758
    /* Must be initialized before options are parsed.  */
 
759
    interactionoption = 4;
 
760
    dump_name = NULL;
 
761
 
 
762
    /* 0 means "disable Synchronize TeXnology".
 
763
     synctexoption is a *.web variable.
 
764
     We initialize it to a weird value to catch the -synctex command line flag
 
765
     At runtime, if synctexoption is not |INT_MAX|, then it contains the command line option provided,
 
766
     otherwise no such option was given by the user. */
 
767
#define SYNCTEX_NO_OPTION INT_MAX
 
768
    synctexoption = SYNCTEX_NO_OPTION;
 
769
 
 
770
    /* parse commandline */
 
771
    parse_options(ac, av);
 
772
    if (lua_only)
 
773
        shellenabledp = true;
 
774
 
 
775
    /* make sure that the locale is 'sane' (for lua) */
 
776
 
 
777
    putenv(LC_CTYPE_C);
 
778
    putenv(LC_COLLATE_C);
 
779
    putenv(LC_NUMERIC_C);
 
780
 
 
781
    /* this is sometimes needed */
 
782
    putenv(engine_luatex);
 
783
 
 
784
    luainterpreter();
 
785
 
 
786
    prepare_cmdline(Luas, argv, argc, lua_offset);      /* collect arguments */
 
787
    setup_lua_path(Luas);
 
788
 
 
789
    if (startup_filename != NULL) {
 
790
        given_file = xstrdup(startup_filename);
 
791
        startup_filename = find_filename(startup_filename, "LUATEXDIR");
 
792
    }
 
793
    /* now run the file */
 
794
    if (startup_filename != NULL) {
 
795
        char *v1;
 
796
        /* hide the 'tex' and 'pdf' table */
 
797
        tex_table_id = hide_lua_table(Luas, "tex");
 
798
        token_table_id = hide_lua_table(Luas, "token");
 
799
        node_table_id = hide_lua_table(Luas, "node");
 
800
        pdf_table_id = hide_lua_table(Luas, "pdf");
 
801
 
 
802
        if (luaL_loadfile(Luas, startup_filename)) {
 
803
            fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
 
804
            exit(1);
 
805
        }
 
806
        /* */
 
807
        init_tex_table(Luas);
 
808
        if (lua_pcall(Luas, 0, 0, 0)) {
 
809
            fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
 
810
            exit(1);
 
811
        }
 
812
        /* no filename? quit now! */
 
813
        if (!input_name) {
 
814
            get_lua_string("texconfig", "jobname", &input_name);
 
815
        }
 
816
        if (!dump_name) {
 
817
            get_lua_string("texconfig", "formatname", &dump_name);
 
818
        }
 
819
        if ((lua_only) || ((!input_name) && (!dump_name))) {
 
820
            if (given_file)
 
821
                free(given_file);
 
822
            /* this is not strictly needed but it pleases valgrind */
 
823
            lua_close(Luas);
 
824
            exit(0);
 
825
        }
 
826
        /* unhide the 'tex' and 'pdf' table */
 
827
        unhide_lua_table(Luas, "tex", tex_table_id);
 
828
        unhide_lua_table(Luas, "pdf", pdf_table_id);
 
829
        unhide_lua_table(Luas, "token", token_table_id);
 
830
        unhide_lua_table(Luas, "node", node_table_id);
 
831
 
 
832
        /* |kpse_init| */
 
833
        kpse_init = -1;
 
834
        get_lua_boolean("texconfig", "kpse_init", &kpse_init);
 
835
 
 
836
        if (kpse_init != 0) {
 
837
            luainit = 0;        /* re-enable loading of texmf.cnf values, see luatex.ch */
 
838
            init_kpse();
 
839
        }
 
840
        /* |prohibit_file_trace| (boolean) */
 
841
        tracefilenames = 1;
 
842
        get_lua_boolean("texconfig", "trace_file_names", &tracefilenames);
 
843
 
 
844
        /* |file_line_error| */
 
845
        filelineerrorstylep = false;
 
846
        get_lua_boolean("texconfig", "file_line_error", &filelineerrorstylep);
 
847
 
 
848
        /* |halt_on_error| */
 
849
        haltonerrorp = false;
 
850
        get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp);
 
851
 
 
852
        /* |restrictedshell| */
 
853
        v1 = NULL;
 
854
        get_lua_string("texconfig", "shell_escape", &v1);
 
855
        if (v1) {
 
856
            if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
 
857
                shellenabledp = 1;
 
858
            } else if (*v1 == 'p') {
 
859
                shellenabledp = 1;
 
860
                restrictedshell = 1;
 
861
            }
 
862
        }
 
863
        /* If shell escapes are restricted, get allowed cmds from cnf.  */
 
864
        if (shellenabledp && restrictedshell == 1) {
 
865
            v1 = NULL;
 
866
            get_lua_string("texconfig", "shell_escape_commands", &v1);
 
867
            if (v1) {
 
868
                mk_shellcmdlist(v1);
 
869
            }
 
870
        }
 
871
 
 
872
        fix_dumpname();
 
873
 
 
874
    } else {
 
875
        if (luainit) {
 
876
            if (given_file) {
 
877
                fprintf(stdout, "%s file %s not found\n",
 
878
                        (lua_only ? "Script" : "Configuration"), given_file);
 
879
                free(given_file);
 
880
            } else {
 
881
                fprintf(stdout, "No %s file given\n",
 
882
                        (lua_only ? "script" : "configuration"));
 
883
            }
 
884
            exit(1);
 
885
        } else {
 
886
            /* init */
 
887
            init_kpse();
 
888
            fix_dumpname();
 
889
        }
 
890
    }
 
891
}
 
892
 
 
893
@ @c
 
894
void check_texconfig_init(void)
 
895
{
 
896
    if (Luas != NULL) {
 
897
        lua_getglobal(Luas, "texconfig");
 
898
        if (lua_istable(Luas, -1)) {
 
899
            lua_getfield(Luas, -1, "init");
 
900
            if (lua_isfunction(Luas, -1)) {
 
901
                int i = lua_pcall(Luas, 0, 0, 0);
 
902
                if (i != 0) {
 
903
                    /* Can't be more precise here, called before TeX initialization  */
 
904
                    fprintf(stderr, "This went wrong: %s\n",
 
905
                            lua_tostring(Luas, -1));
 
906
                    error();
 
907
                }
 
908
            }
 
909
        }
 
910
    }
 
911
}
 
912
 
 
913
@ @c
 
914
void write_svnversion(char *v)
 
915
{
 
916
    char *a_head, *n;
 
917
    char *a = strdup(v);
 
918
    size_t l = strlen("$Id: luatex.web ");
 
919
    if (a != NULL) {
 
920
        a_head = a;
 
921
        if (strlen(a) > l)
 
922
            a += l;
 
923
        n = a;
 
924
        while (*n != '\0' && *n != ' ')
 
925
            n++;
 
926
        *n = '\0';
 
927
        fprintf(stdout, " luatex.web >= v%s", a);
 
928
        free(a_head);
 
929
    }
 
930
}