synch with TL 37803
[luatex.git] / source / texk / web2c / luatexdir / lua / lkpselib.c
blobd53c50426e448600ea1844a23e6490f35cb76436
1 /* lkpselib.c
3 Copyright 2006-2008 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/>. */
20 #ifdef MF_LUA
21 #define EXTERN extern
22 #if defined(JIT)
23 #include "mfluajitd.h"
24 #else
25 #include "mfluad.h"
26 #endif
27 #include <kpathsea/version.h>
28 #define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0)
29 #else
30 #include "ptexlib.h"
31 #include "lua/luatex-api.h"
32 #endif
33 #include <kpathsea/expand.h>
34 #include <kpathsea/variable.h>
35 #include <kpathsea/tex-glyph.h>
36 #include <kpathsea/readable.h>
37 #include <kpathsea/pathsearch.h>
38 #include <kpathsea/str-list.h>
39 #include <kpathsea/tex-file.h>
40 #include <kpathsea/paths.h>
43 static const unsigned filetypes[] = {
44 kpse_gf_format,
45 kpse_pk_format,
46 kpse_any_glyph_format,
47 kpse_tfm_format,
48 kpse_afm_format,
49 kpse_base_format,
50 kpse_bib_format,
51 kpse_bst_format,
52 kpse_cnf_format,
53 kpse_db_format,
54 kpse_fmt_format,
55 kpse_fontmap_format,
56 kpse_mem_format,
57 kpse_mf_format,
58 kpse_mfpool_format,
59 kpse_mft_format,
60 kpse_mp_format,
61 kpse_mppool_format,
62 kpse_mpsupport_format,
63 kpse_ocp_format,
64 kpse_ofm_format,
65 kpse_opl_format,
66 kpse_otp_format,
67 kpse_ovf_format,
68 kpse_ovp_format,
69 kpse_pict_format,
70 kpse_tex_format,
71 kpse_texdoc_format,
72 kpse_texpool_format,
73 kpse_texsource_format,
74 kpse_tex_ps_header_format,
75 kpse_troff_font_format,
76 kpse_type1_format,
77 kpse_vf_format,
78 kpse_dvips_config_format,
79 kpse_ist_format,
80 kpse_truetype_format,
81 kpse_type42_format,
82 kpse_web2c_format,
83 kpse_program_text_format,
84 kpse_program_binary_format,
85 kpse_miscfonts_format,
86 kpse_web_format,
87 kpse_cweb_format,
88 kpse_enc_format,
89 kpse_cmap_format,
90 kpse_sfd_format,
91 kpse_opentype_format,
92 kpse_pdftex_config_format,
93 kpse_lig_format,
94 kpse_texmfscripts_format,
95 kpse_lua_format,
96 kpse_fea_format,
97 kpse_cid_format,
98 kpse_mlbib_format,
99 kpse_mlbst_format,
100 kpse_clua_format
103 static const char *const filetypenames[] = {
104 "gf",
105 "pk",
106 "bitmap font",
107 "tfm",
108 "afm",
109 "base",
110 "bib",
111 "bst",
112 "cnf",
113 "ls-R",
114 "fmt",
115 "map",
116 "mem",
117 "mf",
118 "mfpool",
119 "mft",
120 "mp",
121 "mppool",
122 "MetaPost support",
123 "ocp",
124 "ofm",
125 "opl",
126 "otp",
127 "ovf",
128 "ovp",
129 "graphic/figure",
130 "tex",
131 "TeX system documentation",
132 "texpool",
133 "TeX system sources",
134 "PostScript header",
135 "Troff fonts",
136 "type1 fonts",
137 "vf",
138 "dvips config",
139 "ist",
140 "truetype fonts",
141 "type42 fonts",
142 "web2c files",
143 "other text files",
144 "other binary files",
145 "misc fonts",
146 "web",
147 "cweb",
148 "enc files",
149 "cmap files",
150 "subfont definition files",
151 "opentype fonts",
152 "pdftex config",
153 "lig files",
154 "texmfscripts",
155 "lua",
156 "font feature files",
157 "cid maps",
158 "mlbib",
159 "mlbst",
160 "clua",
161 NULL
165 #ifdef MF
166 #define KPATHSEA_METATABLE "mflua.kpathsea"
167 #else
168 #define KPATHSEA_METATABLE "luatex.kpathsea"
169 #endif
171 /* set to 1 by the |program_name| function */
173 #ifdef MF
174 int program_name_set = 1;
175 #else
176 int program_name_set = 0;
177 #endif
179 #define TEST_PROGRAM_NAME_SET do { \
180 if (! program_name_set) { \
181 return luaL_error(L, "Please call kpse.set_program_name() before using the library"); \
183 } while (0)
185 static int find_file(lua_State * L)
187 int i;
188 const char *st;
189 unsigned ftype = kpse_tex_format;
190 int mexist = 0;
191 TEST_PROGRAM_NAME_SET;
192 if (!lua_isstring(L, 1)) {
193 luaL_error(L, "not a file name");
195 st = lua_tostring(L, 1);
196 i = lua_gettop(L);
197 while (i > 1) {
198 if (lua_isboolean(L, i)) {
199 mexist = lua_toboolean(L, i);
200 } else if (lua_isnumber(L, i)) {
201 mexist=(int)lua_tonumber(L, i);
202 } else if (lua_isstring(L, i)) {
203 int op = luaL_checkoption(L, i, NULL, filetypenames);
204 ftype = filetypes[op];
206 i--;
208 if (ftype == kpse_pk_format ||
209 ftype == kpse_gf_format || ftype == kpse_any_glyph_format) {
210 /* ret.format, ret.name, ret.dpi */
211 kpse_glyph_file_type ret;
212 lua_pushstring(L, kpse_find_glyph(st, (unsigned) mexist, ftype, &ret));
213 } else {
214 if (mexist > 0)
215 mexist = 1;
216 if (mexist < 0)
217 mexist = 0;
218 lua_pushstring(L, kpse_find_file(st, ftype, mexist));
220 return 1;
224 static int lua_kpathsea_find_file(lua_State * L)
226 int i;
227 unsigned ftype = kpse_tex_format;
228 int mexist = 0;
229 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
230 const char *st = luaL_checkstring(L, 2);
231 i = lua_gettop(L);
232 while (i > 2) {
233 if (lua_isboolean(L, i)) {
234 mexist = (boolean) lua_toboolean(L, i);
235 } else if (lua_isnumber(L, i)) {
236 mexist=(int)lua_tonumber(L, i);
237 } else if (lua_isstring(L, i)) {
238 int op = luaL_checkoption(L, i, NULL, filetypenames);
239 ftype = filetypes[op];
241 i--;
243 if (ftype == kpse_pk_format ||
244 ftype == kpse_gf_format || ftype == kpse_any_glyph_format) {
245 /* ret.format, ret.name, ret.dpi */
246 kpse_glyph_file_type ret;
247 lua_pushstring(L,
248 kpathsea_find_glyph(*kp, st, (unsigned) mexist, ftype,
249 &ret));
250 } else {
251 if (mexist > 0)
252 mexist = 1;
253 if (mexist < 0)
254 mexist = 0;
255 lua_pushstring(L, kpathsea_find_file(*kp, st, ftype, mexist));
257 return 1;
261 static int show_texmfcnf(lua_State * L)
263 lua_pushstring(L, DEFAULT_TEXMFCNF);
264 return 1;
267 static int show_path(lua_State * L)
269 int op = luaL_checkoption(L, -1, "tex", filetypenames);
270 unsigned user_format = filetypes[op];
271 TEST_PROGRAM_NAME_SET;
272 if (!kpse_format_info[user_format].type) /* needed if arg was numeric */
273 kpse_init_format(user_format);
274 lua_pushstring(L, kpse_format_info[user_format].path);
275 return 1;
278 static int lua_kpathsea_show_path(lua_State * L)
280 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
281 int op = luaL_checkoption(L, -1, "tex", filetypenames);
282 unsigned user_format = filetypes[op];
283 if (!(*kp)->format_info[user_format].type) /* needed if arg was numeric */
284 kpathsea_init_format(*kp, user_format);
285 lua_pushstring(L, (*kp)->format_info[user_format].path);
286 return 1;
289 static int expand_path(lua_State * L)
291 const char *st = luaL_checkstring(L, 1);
292 TEST_PROGRAM_NAME_SET;
293 lua_pushstring(L, kpse_path_expand(st));
294 return 1;
297 static int lua_kpathsea_expand_path(lua_State * L)
299 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
300 const char *st = luaL_checkstring(L, 2);
301 lua_pushstring(L, kpathsea_path_expand(*kp, st));
302 return 1;
305 static int expand_braces(lua_State * L)
307 const char *st = luaL_checkstring(L, 1);
308 TEST_PROGRAM_NAME_SET;
309 lua_pushstring(L, kpse_brace_expand(st));
310 return 1;
313 static int lua_kpathsea_expand_braces(lua_State * L)
315 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
316 const char *st = luaL_checkstring(L, 2);
317 lua_pushstring(L, kpathsea_brace_expand(*kp, st));
318 return 1;
322 static int expand_var(lua_State * L)
324 const char *st = luaL_checkstring(L, 1);
325 TEST_PROGRAM_NAME_SET;
326 lua_pushstring(L, kpse_var_expand(st));
327 return 1;
330 static int lua_kpathsea_expand_var(lua_State * L)
332 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
333 const char *st = luaL_checkstring(L, 2);
334 lua_pushstring(L, kpathsea_var_expand(*kp, st));
335 return 1;
339 static int var_value(lua_State * L)
341 const char *st = luaL_checkstring(L, 1);
342 TEST_PROGRAM_NAME_SET;
343 lua_pushstring(L, kpse_var_value(st));
344 return 1;
347 static int lua_kpathsea_var_value(lua_State * L)
349 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
350 const char *st = luaL_checkstring(L, 2);
351 lua_pushstring(L, kpathsea_var_value(*kp, st));
352 return 1;
355 static unsigned find_dpi(const_string s)
357 unsigned dpi_number = 0;
358 const_string extension = find_suffix(s);
360 if (extension != NULL)
361 sscanf(extension, "%u", &dpi_number);
363 return dpi_number;
366 /* Return newly-allocated NULL-terminated list of strings from MATCHES
367 that are prefixed with any of the subdirectories in SUBDIRS. That
368 is, for a string S in MATCHES, its dirname must end with one of the
369 elements in SUBDIRS. For instance, if subdir=foo/bar, that will
370 match a string foo/bar/baz or /some/texmf/foo/bar/baz.
372 We don't reallocate the actual strings, just the list elements.
373 Perhaps later we will implement wildcards or // or something. */
375 static string *subdir_match(str_list_type subdirs, string * matches)
377 string *ret = XTALLOC1(string);
378 unsigned len = 1;
379 unsigned m;
381 for (m = 0; matches[m]; m++) {
382 size_t loc;
383 unsigned e;
384 string s = xstrdup(matches[m]);
385 for (loc = strlen(s); loc > 0 && !IS_DIR_SEP(s[loc - 1]); loc--);
386 while (loc > 0 && IS_DIR_SEP(s[loc - 1])) {
387 loc--;
389 s[loc] = 0; /* wipe out basename */
391 for (e = 0; e < STR_LIST_LENGTH(subdirs); e++) {
392 string subdir = STR_LIST_ELT(subdirs, e);
393 size_t subdir_len = strlen(subdir);
394 while (subdir_len > 0 && IS_DIR_SEP(subdir[subdir_len - 1])) {
395 subdir_len--;
396 subdir[subdir_len] = 0; /* remove trailing slashes from subdir spec */
398 if (FILESTRCASEEQ(subdir, s + loc - subdir_len)) {
399 /* matched, save this one. */
400 XRETALLOC(ret, len + 1, string);
401 ret[len - 1] = matches[m];
402 len++;
405 free(s);
407 ret[len - 1] = NULL;
408 return ret;
411 /* Use the file type from -format if that was specified (i.e., the
412 user_format global variable), else guess dynamically from NAME.
413 Return kpse_last_format if undeterminable. This function is also
414 used to parse the -format string, a case which we distinguish by
415 setting is_filename to false.
417 A few filenames have been hard-coded for format types that
418 differ from what would be inferred from their extensions. */
420 static kpse_file_format_type
421 find_format(kpathsea kpse, const_string name, boolean is_filename)
423 kpse_file_format_type ret;
425 if (FILESTRCASEEQ(name, "config.ps")) {
426 ret = kpse_dvips_config_format;
427 } else if (FILESTRCASEEQ(name, "dvipdfmx.cfg")) {
428 ret = kpse_program_text_format;
429 } else if (FILESTRCASEEQ(name, "fmtutil.cnf")) {
430 ret = kpse_web2c_format;
431 } else if (FILESTRCASEEQ(name, "glyphlist.txt")) {
432 ret = kpse_fontmap_format;
433 } else if (FILESTRCASEEQ(name, "mktex.cnf")) {
434 ret = kpse_web2c_format;
435 } else if (FILESTRCASEEQ(name, "pdfglyphlist.txt")) {
436 ret = kpse_fontmap_format;
437 } else if (FILESTRCASEEQ(name, "pdftex.cfg")) {
438 ret = kpse_pdftex_config_format;
439 } else if (FILESTRCASEEQ(name, "texmf.cnf")) {
440 ret = kpse_cnf_format;
441 } else if (FILESTRCASEEQ(name, "updmap.cfg")) {
442 ret = kpse_web2c_format;
443 } else if (FILESTRCASEEQ(name, "XDvi")) {
444 ret = kpse_program_text_format;
445 } else {
446 int f = 0; /* kpse_file_format_type */
447 size_t name_len = strlen(name);
449 /* Have to rely on `try_len' being declared here, since we can't assume
450 GNU C and statement expressions. */
451 #define TRY_SUFFIX(ftry) (\
452 try_len = (ftry) ? strlen (ftry) : 0, \
453 (ftry) && try_len <= name_len \
454 && FILESTRCASEEQ (ftry, name + name_len - try_len))
456 while (f != kpse_last_format) {
457 size_t try_len;
458 const_string *ext;
459 const_string ftry;
460 boolean found = false;
462 if (!kpse->format_info[f].type)
463 kpathsea_init_format(kpse, (kpse_file_format_type) f);
465 if (!is_filename) {
466 /* Allow the long name, but only in the -format option. We don't
467 want a filename confused with a format name. */
468 ftry = kpse->format_info[f].type;
469 found = TRY_SUFFIX(ftry);
471 for (ext = kpse->format_info[f].suffix; !found && ext && *ext;
472 ext++) {
473 found = TRY_SUFFIX(*ext);
475 for (ext = kpse->format_info[f].alt_suffix; !found && ext && *ext;
476 ext++) {
477 found = TRY_SUFFIX(*ext);
480 if (found)
481 break;
483 /* Some trickery here: the extensions for kpse_fmt_format can
484 * clash with other extensions in use, and we prefer for those
485 * others to be preferred. And we don't want to change the
486 * integer value of kpse_fmt_format. So skip it when first
487 * enountered, then use it when we've done everything else,
488 * and use it as the end-guard.
490 if (f == kpse_fmt_format) {
491 f = kpse_last_format;
492 } else if (++f == kpse_fmt_format) {
493 f++;
494 } else if (f == kpse_last_format) {
495 f = kpse_fmt_format;
499 /* If there was a match, f will be one past the correct value. */
500 ret = f;
503 return ret;
506 /* kpse:lookup("plain.tex", {}) */
507 static int do_lua_kpathsea_lookup(lua_State * L, kpathsea kpse, int idx)
509 int i;
510 string ret = NULL;
511 string *ret_list = NULL;
512 const_string name = NULL;
513 string user_path = NULL;
514 boolean show_all = false;
515 boolean must_exist = false;
516 kpse_file_format_type user_format = kpse_last_format;
517 int dpi = 600;
518 str_list_type subdir_paths = { 0, NULL };
519 unsigned saved_debug = kpse->debug;
520 int saved_mktexpk = kpse->format_info[kpse_pk_format].program_enabled_p;
521 int saved_mktexmf = kpse->format_info[kpse_mf_format].program_enabled_p;
522 int saved_mktextex = kpse->format_info[kpse_tex_format].program_enabled_p;
523 int saved_mktextfm = kpse->format_info[kpse_tfm_format].program_enabled_p;
524 name = luaL_checkstring(L, idx);
525 /* todo: fetch parameter values */
527 if (lua_type(L, idx + 1) == LUA_TTABLE) {
528 lua_pushstring(L, "format");
529 lua_gettable(L, idx + 1);
530 if (lua_type(L, -1) == LUA_TSTRING) {
531 int op = luaL_checkoption(L, -1, NULL, filetypenames);
532 user_format = filetypes[op];
534 lua_pop(L, 1);
535 lua_pushstring(L, "dpi");
536 lua_gettable(L, idx + 1);
537 if (lua_type(L, -1) == LUA_TNUMBER) {
538 dpi=(int)lua_tonumber(L, -1);
540 lua_pop(L, 1);
541 lua_pushstring(L, "debug");
542 lua_gettable(L, idx + 1);
543 if (lua_type(L, -1) == LUA_TNUMBER) {
544 int d = 0;
545 d=(int)lua_tonumber(L, -1);
546 kpse->debug |= d;
548 lua_pop(L, 1);
549 lua_pushstring(L, "path");
550 lua_gettable(L, idx + 1);
551 if (lua_type(L, -1) == LUA_TSTRING) {
552 user_path = xstrdup(lua_tostring(L, -1));
554 lua_pop(L, 1);
555 lua_pushstring(L, "all");
556 lua_gettable(L, idx + 1);
557 if (lua_type(L, -1) == LUA_TBOOLEAN) {
558 show_all = lua_toboolean(L, -1);
560 lua_pop(L, 1);
562 lua_pushstring(L, "mktexpk");
563 lua_gettable(L, idx + 1);
564 if (lua_type(L, -1) == LUA_TBOOLEAN) {
565 kpathsea_maketex_option(kpse, "pk", lua_toboolean(L, -1));
567 lua_pop(L, 1);
569 lua_pushstring(L, "mktextex");
570 lua_gettable(L, idx + 1);
571 if (lua_type(L, -1) == LUA_TBOOLEAN) {
572 kpathsea_maketex_option(kpse, "tex", lua_toboolean(L, -1));
574 lua_pop(L, 1);
576 lua_pushstring(L, "mktexmf");
577 lua_gettable(L, idx + 1);
578 if (lua_type(L, -1) == LUA_TBOOLEAN) {
579 kpathsea_maketex_option(kpse, "mf", lua_toboolean(L, -1));
581 lua_pop(L, 1);
583 lua_pushstring(L, "mktextfm");
584 lua_gettable(L, idx + 1);
585 if (lua_type(L, -1) == LUA_TBOOLEAN) {
586 kpathsea_maketex_option(kpse, "tfm", lua_toboolean(L, -1));
588 lua_pop(L, 1);
591 lua_pushstring(L, "mustexist");
592 lua_gettable(L, idx + 1);
593 if (lua_type(L, -1) == LUA_TBOOLEAN) {
594 must_exist = lua_toboolean(L, -1);
596 lua_pop(L, 1);
597 lua_pushstring(L, "subdir");
598 lua_gettable(L, idx + 1);
599 if (lua_istable(L, -1)) {
600 lua_pushnil(L);
601 while (lua_next(L, -2) != 0) { /* numeric value */
602 if (lua_isstring(L, -1)) {
603 char *s = xstrdup(lua_tostring(L, -1));
604 str_list_add(&subdir_paths, s);
605 xfree(s);
607 lua_pop(L, 1);
609 } else if (lua_isstring(L, -1)) {
610 char *s = xstrdup(lua_tostring(L, -1));
611 str_list_add(&subdir_paths, s);
612 xfree(s);
614 lua_pop(L, 1);
615 if (STR_LIST_LENGTH(subdir_paths) > 0) {
616 show_all = 1;
619 if (user_path) {
620 /* Translate ; to : if that's our ENV_SEP. See cnf.c. */
621 if (IS_ENV_SEP(':')) {
622 string loc;
623 for (loc = user_path; *loc; loc++) {
624 if (*loc == ';')
625 *loc = ':';
628 user_path = kpathsea_path_expand(kpse, user_path);
629 if (show_all) {
630 ret_list = kpathsea_all_path_search(kpse, user_path, name);
631 } else {
632 ret = kpathsea_path_search(kpse, user_path, name, must_exist);
634 free(user_path);
635 } else {
636 /* No user-specified search path, check user format or guess from NAME. */
637 kpse_file_format_type fmt;
638 if (user_format != kpse_last_format)
639 fmt = user_format;
640 else
641 fmt = find_format(kpse, name, true);
643 switch (fmt) {
644 case kpse_pk_format:
645 case kpse_gf_format:
646 case kpse_any_glyph_format:
648 kpse_glyph_file_type glyph_ret;
649 string temp = remove_suffix (name);
650 /* Try to extract the resolution from the name. */
651 unsigned local_dpi = find_dpi(name);
652 if (!local_dpi)
653 local_dpi = (unsigned) dpi;
654 ret =
655 kpathsea_find_glyph(kpse, temp, local_dpi,
656 fmt, &glyph_ret);
657 if (temp != name)
658 free (temp);
660 break;
662 case kpse_last_format:
663 /* If the suffix isn't recognized, assume it's a tex file. */
664 fmt = kpse_tex_format;
665 /* fall through */
667 default:
668 if (show_all) {
669 ret_list =
670 kpathsea_find_file_generic(kpse, name, fmt, must_exist,
671 true);
672 } else {
673 ret = kpathsea_find_file(kpse, name, fmt, must_exist);
678 /* Turn single return into a null-terminated list for uniform treatment. */
679 if (ret) {
680 ret_list = XTALLOC(2, string);
681 ret_list[0] = ret;
682 ret_list[1] = NULL;
685 /* Filter by subdirectories, if specified. */
686 if (STR_LIST_LENGTH(subdir_paths) > 0) {
687 string *new_list = subdir_match(subdir_paths, ret_list);
688 free(ret_list);
689 ret_list = new_list;
691 kpse->debug = saved_debug;
692 kpse->format_info[kpse_pk_format].program_enabled_p = saved_mktexpk;
693 kpse->format_info[kpse_mf_format].program_enabled_p = saved_mktexmf;
694 kpse->format_info[kpse_tex_format].program_enabled_p = saved_mktextex;
695 kpse->format_info[kpse_tfm_format].program_enabled_p = saved_mktextfm;
697 /* Print output. */
698 i = 0;
699 if (ret_list) {
700 for (; ret_list[i]; i++) {
701 lua_pushstring(L, ret_list[i]);
703 free(ret_list);
705 if (i == 0) {
706 i++;
707 lua_pushnil(L);
709 return i;
713 static int lua_kpathsea_lookup(lua_State * L)
715 kpathsea *kpsep = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
716 kpathsea kpse = *kpsep;
717 return do_lua_kpathsea_lookup(L, kpse, 2);
720 static int lua_kpse_lookup(lua_State * L)
722 TEST_PROGRAM_NAME_SET;
723 return do_lua_kpathsea_lookup(L, kpse_def, 1);
727 /* Engine support is a bit of a problem, because we do not want
728 * to interfere with the normal format discovery of |luatex|.
729 * Current approach: run |os.setenv()| if you have to.
732 static int set_program_name(lua_State * L)
734 const char *exe_name = luaL_checkstring(L, 1);
735 const char *prog_name = luaL_optstring(L, 2, exe_name);
736 if (!program_name_set) {
737 kpse_set_program_name(exe_name, prog_name);
738 program_name_set = 1;
739 } else {
740 kpse_reset_program_name(prog_name);
742 /* fix up the texconfig entry */
743 lua_checkstack(L, 3);
744 lua_getglobal(L, "texconfig");
745 if (lua_istable(L, -1)) {
746 lua_pushstring(L, "kpse_init");
747 lua_pushboolean(L, 0);
748 lua_rawset(L, -3);
750 lua_pop(L, 1);
751 return 0;
754 static int init_prog(lua_State * L)
756 const char *prefix = luaL_checkstring(L, 1);
757 unsigned dpi = (unsigned) luaL_checkinteger(L, 2);
758 const char *mode = luaL_checkstring(L, 3);
759 const char *fallback = luaL_optstring(L, 4, NULL);
760 TEST_PROGRAM_NAME_SET;
761 kpse_init_prog(prefix, dpi, mode, fallback);
762 return 0;
765 static int lua_kpathsea_init_prog(lua_State * L)
767 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
768 const char *prefix = luaL_checkstring(L, 2);
769 unsigned dpi = (unsigned) luaL_checkinteger(L, 3);
770 const char *mode = luaL_checkstring(L, 4);
771 const char *fallback = luaL_optstring(L, 5, NULL);
772 kpathsea_init_prog(*kp, prefix, dpi, mode, fallback);
773 return 0;
776 static int lua_kpse_version(lua_State * L)
778 lua_pushstring(L, kpathsea_version_string);
779 return 1;
782 static int readable_file(lua_State * L)
784 char *name = xstrdup(luaL_checkstring(L, 1));
785 TEST_PROGRAM_NAME_SET;
786 lua_pushstring(L, kpse_readable_file(name));
787 free(name);
788 return 1;
791 static int lua_kpathsea_readable_file(lua_State * L)
793 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
794 char *name = xstrdup(luaL_checkstring(L, 2));
795 lua_pushstring(L, kpathsea_readable_file(*kp, name));
796 free(name);
797 return 1;
801 static int lua_kpathsea_finish(lua_State * L)
803 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
804 kpathsea_finish(*kp);
805 return 0;
808 static int lua_kpathsea_new(lua_State * L)
810 kpathsea kpse = NULL;
811 kpathsea *kp = NULL;
812 const char *av = luaL_checkstring(L, 1);
813 const char *liar = luaL_optstring(L, 2, av);
814 kpse = kpathsea_new();
815 kpathsea_set_program_name(kpse, av, liar);
816 kp = (kpathsea *) lua_newuserdata(L, sizeof(kpathsea *));
817 *kp = kpse;
818 luaL_getmetatable(L, KPATHSEA_METATABLE);
819 lua_setmetatable(L, -2);
820 return 1;
823 static const struct luaL_Reg kpselib_m[] = {
824 {"__gc", lua_kpathsea_finish},
825 {"init_prog", lua_kpathsea_init_prog},
826 {"readable_file", lua_kpathsea_readable_file},
827 {"find_file", lua_kpathsea_find_file},
828 {"expand_path", lua_kpathsea_expand_path},
829 {"expand_var", lua_kpathsea_expand_var},
830 {"expand_braces", lua_kpathsea_expand_braces},
831 {"var_value", lua_kpathsea_var_value},
832 {"show_path", lua_kpathsea_show_path},
833 {"lookup", lua_kpathsea_lookup},
834 {"version", lua_kpse_version},
835 {"default_texmfcnf", show_texmfcnf},
836 {NULL, NULL} /* sentinel */
839 static const struct luaL_Reg kpselib_l[] = {
840 {"new", lua_kpathsea_new},
841 {"set_program_name", set_program_name},
842 {"init_prog", init_prog},
843 {"readable_file", readable_file},
844 {"find_file", find_file},
845 {"expand_path", expand_path},
846 {"expand_var", expand_var},
847 {"expand_braces", expand_braces},
848 {"var_value", var_value},
849 {"show_path", show_path},
850 {"lookup", lua_kpse_lookup},
851 {"version", lua_kpse_version},
852 {"default_texmfcnf", show_texmfcnf},
853 {NULL, NULL} /* sentinel */
856 int luaopen_kpse(lua_State * L)
858 luaL_newmetatable(L, KPATHSEA_METATABLE);
859 lua_pushvalue(L, -1);
860 lua_setfield(L, -2, "__index");
861 luaL_register(L, NULL, kpselib_m);
862 luaL_register(L, "kpse", kpselib_l);
863 return 1;