beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / lua / lkpselib.c
blobe45cda0af6f43edbdee72a05cac716ee94f9d199
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, t;
188 const char *st;
189 unsigned ftype = kpse_tex_format;
190 int mexist = 0;
191 TEST_PROGRAM_NAME_SET;
192 if (lua_type(L, 1) != LUA_TSTRING) {
193 luaL_error(L, "not a file name");
195 st = lua_tostring(L, 1);
196 i = lua_gettop(L);
197 while (i > 1) {
198 t = lua_type(L, i) ;
199 if (t == LUA_TBOOLEAN) {
200 mexist = lua_toboolean(L, i);
201 } else if (t == LUA_TNUMBER) {
202 mexist = (int) lua_tointeger(L, i);
203 } else if (t == LUA_TSTRING) {
204 int op = luaL_checkoption(L, i, NULL, filetypenames);
205 ftype = filetypes[op];
206 } else {
207 /* ignore */
209 i--;
211 if (ftype == kpse_pk_format ||
212 ftype == kpse_gf_format || ftype == kpse_any_glyph_format) {
213 /* ret.format, ret.name, ret.dpi */
214 kpse_glyph_file_type ret;
215 lua_pushstring(L, kpse_find_glyph(st, (unsigned) mexist, ftype, &ret));
216 } else {
217 if (mexist > 0)
218 mexist = 1;
219 if (mexist < 0)
220 mexist = 0;
221 lua_pushstring(L, kpse_find_file(st, ftype, mexist));
223 return 1;
227 static int lua_kpathsea_find_file(lua_State * L)
229 int i, t;
230 unsigned ftype = kpse_tex_format;
231 int mexist = 0;
232 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
233 const char *st = luaL_checkstring(L, 2);
234 i = lua_gettop(L);
235 while (i > 2) {
236 t = lua_type(L, i) ;
237 if (t == LUA_TBOOLEAN) {
238 mexist = (boolean) lua_toboolean(L, i);
239 } else if (t == LUA_TNUMBER) {
240 mexist = (int) lua_tointeger(L, i);
241 } else if (t == LUA_TSTRING) {
242 int op = luaL_checkoption(L, i, NULL, filetypenames);
243 ftype = filetypes[op];
244 } else {
245 /* ignore */
247 i--;
249 if (ftype == kpse_pk_format || ftype == kpse_gf_format || ftype == kpse_any_glyph_format) {
250 /* ret.format, ret.name, ret.dpi */
251 kpse_glyph_file_type ret;
252 lua_pushstring(L, kpathsea_find_glyph(*kp, st, (unsigned) mexist, ftype, &ret));
253 } else {
254 if (mexist > 0)
255 mexist = 1;
256 if (mexist < 0)
257 mexist = 0;
258 lua_pushstring(L, kpathsea_find_file(*kp, st, ftype, mexist));
260 return 1;
264 static int show_texmfcnf(lua_State * L)
266 lua_pushstring(L, DEFAULT_TEXMFCNF);
267 return 1;
270 static int show_path(lua_State * L)
272 int op = luaL_checkoption(L, -1, "tex", filetypenames);
273 unsigned user_format = filetypes[op];
274 TEST_PROGRAM_NAME_SET;
275 if (!kpse_format_info[user_format].type) /* needed if arg was numeric */
276 kpse_init_format(user_format);
277 lua_pushstring(L, kpse_format_info[user_format].path);
278 return 1;
281 static int lua_kpathsea_show_path(lua_State * L)
283 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
284 int op = luaL_checkoption(L, -1, "tex", filetypenames);
285 unsigned user_format = filetypes[op];
286 if (!(*kp)->format_info[user_format].type) /* needed if arg was numeric */
287 kpathsea_init_format(*kp, user_format);
288 lua_pushstring(L, (*kp)->format_info[user_format].path);
289 return 1;
292 static int expand_path(lua_State * L)
294 const char *st = luaL_checkstring(L, 1);
295 TEST_PROGRAM_NAME_SET;
296 lua_pushstring(L, kpse_path_expand(st));
297 return 1;
300 static int lua_kpathsea_expand_path(lua_State * L)
302 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
303 const char *st = luaL_checkstring(L, 2);
304 lua_pushstring(L, kpathsea_path_expand(*kp, st));
305 return 1;
308 static int expand_braces(lua_State * L)
310 const char *st = luaL_checkstring(L, 1);
311 TEST_PROGRAM_NAME_SET;
312 lua_pushstring(L, kpse_brace_expand(st));
313 return 1;
316 static int lua_kpathsea_expand_braces(lua_State * L)
318 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
319 const char *st = luaL_checkstring(L, 2);
320 lua_pushstring(L, kpathsea_brace_expand(*kp, st));
321 return 1;
325 static int expand_var(lua_State * L)
327 const char *st = luaL_checkstring(L, 1);
328 TEST_PROGRAM_NAME_SET;
329 lua_pushstring(L, kpse_var_expand(st));
330 return 1;
333 static int lua_kpathsea_expand_var(lua_State * L)
335 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
336 const char *st = luaL_checkstring(L, 2);
337 lua_pushstring(L, kpathsea_var_expand(*kp, st));
338 return 1;
342 static int var_value(lua_State * L)
344 const char *st = luaL_checkstring(L, 1);
345 TEST_PROGRAM_NAME_SET;
346 lua_pushstring(L, kpse_var_value(st));
347 return 1;
350 static int lua_kpathsea_var_value(lua_State * L)
352 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
353 const char *st = luaL_checkstring(L, 2);
354 lua_pushstring(L, kpathsea_var_value(*kp, st));
355 return 1;
358 static unsigned find_dpi(const_string s)
360 unsigned dpi_number = 0;
361 const_string extension = find_suffix(s);
363 if (extension != NULL)
364 sscanf(extension, "%u", &dpi_number);
366 return dpi_number;
370 Return newly-allocated NULL-terminated list of strings from MATCHES
371 that are prefixed with any of the subdirectories in SUBDIRS. That
372 is, for a string S in MATCHES, its dirname must end with one of the
373 elements in SUBDIRS. For instance, if subdir=foo/bar, that will
374 match a string foo/bar/baz or /some/texmf/foo/bar/baz.
376 We don't reallocate the actual strings, just the list elements.
377 Perhaps later we will implement wildcards or "//" or something.
380 static string *subdir_match(str_list_type subdirs, string * matches)
382 string *ret = XTALLOC1(string);
383 unsigned len = 1;
384 unsigned m;
386 for (m = 0; matches[m]; m++) {
387 size_t loc;
388 unsigned e;
389 string s = xstrdup(matches[m]);
390 for (loc = strlen(s); loc > 0 && !IS_DIR_SEP(s[loc - 1]); loc--);
391 while (loc > 0 && IS_DIR_SEP(s[loc - 1])) {
392 loc--;
394 s[loc] = 0; /* wipe out basename */
396 for (e = 0; e < STR_LIST_LENGTH(subdirs); e++) {
397 string subdir = STR_LIST_ELT(subdirs, e);
398 size_t subdir_len = strlen(subdir);
399 while (subdir_len > 0 && IS_DIR_SEP(subdir[subdir_len - 1])) {
400 subdir_len--;
401 subdir[subdir_len] = 0; /* remove trailing slashes from subdir spec */
403 if (FILESTRCASEEQ(subdir, s + loc - subdir_len)) {
404 /* matched, save this one. */
405 XRETALLOC(ret, len + 1, string);
406 ret[len - 1] = matches[m];
407 len++;
410 free(s);
412 ret[len - 1] = NULL;
413 return ret;
416 /* Use the file type from -format if that was specified (i.e., the
417 user_format global variable), else guess dynamically from NAME.
418 Return kpse_last_format if undeterminable. This function is also
419 used to parse the -format string, a case which we distinguish by
420 setting is_filename to false.
422 A few filenames have been hard-coded for format types that
423 differ from what would be inferred from their extensions. */
425 static kpse_file_format_type
426 find_format(kpathsea kpse, const_string name, boolean is_filename)
428 kpse_file_format_type ret;
430 if (FILESTRCASEEQ(name, "config.ps")) {
431 ret = kpse_dvips_config_format;
432 } else if (FILESTRCASEEQ(name, "dvipdfmx.cfg")) {
433 ret = kpse_program_text_format;
434 } else if (FILESTRCASEEQ(name, "fmtutil.cnf")) {
435 ret = kpse_web2c_format;
436 } else if (FILESTRCASEEQ(name, "glyphlist.txt")) {
437 ret = kpse_fontmap_format;
438 } else if (FILESTRCASEEQ(name, "mktex.cnf")) {
439 ret = kpse_web2c_format;
440 } else if (FILESTRCASEEQ(name, "pdfglyphlist.txt")) {
441 ret = kpse_fontmap_format;
442 } else if (FILESTRCASEEQ(name, "pdftex.cfg")) {
443 ret = kpse_pdftex_config_format;
444 } else if (FILESTRCASEEQ(name, "texmf.cnf")) {
445 ret = kpse_cnf_format;
446 } else if (FILESTRCASEEQ(name, "updmap.cfg")) {
447 ret = kpse_web2c_format;
448 } else if (FILESTRCASEEQ(name, "XDvi")) {
449 ret = kpse_program_text_format;
450 } else {
451 int f = 0; /* kpse_file_format_type */
452 size_t name_len = strlen(name);
454 /* Have to rely on `try_len' being declared here, since we can't assume
455 GNU C and statement expressions. */
456 #define TRY_SUFFIX(ftry) (\
457 try_len = (ftry) ? strlen (ftry) : 0, \
458 (ftry) && try_len <= name_len \
459 && FILESTRCASEEQ (ftry, name + name_len - try_len))
461 while (f != kpse_last_format) {
462 size_t try_len;
463 const_string *ext;
464 const_string ftry;
465 boolean found = false;
467 if (!kpse->format_info[f].type)
468 kpathsea_init_format(kpse, (kpse_file_format_type) f);
470 if (!is_filename) {
471 /* Allow the long name, but only in the -format option. We don't
472 want a filename confused with a format name. */
473 ftry = kpse->format_info[f].type;
474 found = TRY_SUFFIX(ftry);
476 for (ext = kpse->format_info[f].suffix; !found && ext && *ext;
477 ext++) {
478 found = TRY_SUFFIX(*ext);
480 for (ext = kpse->format_info[f].alt_suffix; !found && ext && *ext;
481 ext++) {
482 found = TRY_SUFFIX(*ext);
485 if (found)
486 break;
488 /* Some trickery here: the extensions for kpse_fmt_format can
489 * clash with other extensions in use, and we prefer for those
490 * others to be preferred. And we don't want to change the
491 * integer value of kpse_fmt_format. So skip it when first
492 * enountered, then use it when we've done everything else,
493 * and use it as the end-guard.
495 if (f == kpse_fmt_format) {
496 f = kpse_last_format;
497 } else if (++f == kpse_fmt_format) {
498 f++;
499 } else if (f == kpse_last_format) {
500 f = kpse_fmt_format;
504 /* If there was a match, f will be one past the correct value. */
505 ret = f;
508 return ret;
511 /* kpse:lookup("plain.tex", {}) */
512 static int do_lua_kpathsea_lookup(lua_State * L, kpathsea kpse, int idx)
514 int i;
515 string ret = NULL;
516 string *ret_list = NULL;
517 const_string name = NULL;
518 string user_path = NULL;
519 boolean show_all = false;
520 boolean must_exist = false;
521 kpse_file_format_type user_format = kpse_last_format;
522 int dpi = 600;
523 str_list_type subdir_paths = { 0, NULL };
524 unsigned saved_debug = kpse->debug;
525 int saved_mktexpk = kpse->format_info[kpse_pk_format].program_enabled_p;
526 int saved_mktexmf = kpse->format_info[kpse_mf_format].program_enabled_p;
527 int saved_mktextex = kpse->format_info[kpse_tex_format].program_enabled_p;
528 int saved_mktextfm = kpse->format_info[kpse_tfm_format].program_enabled_p;
529 name = luaL_checkstring(L, idx);
530 /* todo: fetch parameter values */
532 if (lua_type(L, idx + 1) == LUA_TTABLE) {
533 lua_pushstring(L, "format");
534 lua_gettable(L, idx + 1);
535 if (lua_type(L, -1) == LUA_TSTRING) {
536 int op = luaL_checkoption(L, -1, NULL, filetypenames);
537 user_format = filetypes[op];
539 lua_pop(L, 1);
540 lua_pushstring(L, "dpi");
541 lua_gettable(L, idx + 1);
542 if (lua_type(L, -1) == LUA_TNUMBER) {
543 dpi = (int) lua_tointeger(L, -1);
545 lua_pop(L, 1);
546 lua_pushstring(L, "debug");
547 lua_gettable(L, idx + 1);
548 if (lua_type(L, -1) == LUA_TNUMBER) {
549 int d = 0;
550 d = (int) lua_tointeger(L, -1);
551 kpse->debug |= d;
553 lua_pop(L, 1);
554 lua_pushstring(L, "path");
555 lua_gettable(L, idx + 1);
556 if (lua_type(L, -1) == LUA_TSTRING) {
557 user_path = xstrdup(lua_tostring(L, -1));
559 lua_pop(L, 1);
560 lua_pushstring(L, "all");
561 lua_gettable(L, idx + 1);
562 if (lua_type(L, -1) == LUA_TBOOLEAN) {
563 show_all = lua_toboolean(L, -1);
565 lua_pop(L, 1);
567 lua_pushstring(L, "mktexpk");
568 lua_gettable(L, idx + 1);
569 if (lua_type(L, -1) == LUA_TBOOLEAN) {
570 kpathsea_maketex_option(kpse, "pk", lua_toboolean(L, -1));
572 lua_pop(L, 1);
574 lua_pushstring(L, "mktextex");
575 lua_gettable(L, idx + 1);
576 if (lua_type(L, -1) == LUA_TBOOLEAN) {
577 kpathsea_maketex_option(kpse, "tex", lua_toboolean(L, -1));
579 lua_pop(L, 1);
581 lua_pushstring(L, "mktexmf");
582 lua_gettable(L, idx + 1);
583 if (lua_type(L, -1) == LUA_TBOOLEAN) {
584 kpathsea_maketex_option(kpse, "mf", lua_toboolean(L, -1));
586 lua_pop(L, 1);
588 lua_pushstring(L, "mktextfm");
589 lua_gettable(L, idx + 1);
590 if (lua_type(L, -1) == LUA_TBOOLEAN) {
591 kpathsea_maketex_option(kpse, "tfm", lua_toboolean(L, -1));
593 lua_pop(L, 1);
596 lua_pushstring(L, "mustexist");
597 lua_gettable(L, idx + 1);
598 if (lua_type(L, -1) == LUA_TBOOLEAN) {
599 must_exist = lua_toboolean(L, -1);
601 lua_pop(L, 1);
602 lua_pushstring(L, "subdir");
603 lua_gettable(L, idx + 1);
604 if (lua_istable(L, -1)) {
605 lua_pushnil(L);
606 while (lua_next(L, -2) != 0) { /* numeric value */
607 if (lua_type(L, -1) == LUA_TSTRING) {
608 char *s = xstrdup(lua_tostring(L, -1));
609 str_list_add(&subdir_paths, s);
610 xfree(s);
612 lua_pop(L, 1);
614 } else if (lua_type(L, -1) == LUA_TSTRING) {
615 char *s = xstrdup(lua_tostring(L, -1));
616 str_list_add(&subdir_paths, s);
617 xfree(s);
619 lua_pop(L, 1);
620 if (STR_LIST_LENGTH(subdir_paths) > 0) {
621 show_all = 1;
624 if (user_path) {
625 /* Translate ; to : if that's our ENV_SEP. See cnf.c. */
626 if (IS_ENV_SEP(':')) {
627 string loc;
628 for (loc = user_path; *loc; loc++) {
629 if (*loc == ';')
630 *loc = ':';
633 user_path = kpathsea_path_expand(kpse, user_path);
634 if (show_all) {
635 ret_list = kpathsea_all_path_search(kpse, user_path, name);
636 } else {
637 ret = kpathsea_path_search(kpse, user_path, name, must_exist);
639 free(user_path);
640 } else {
641 /* No user-specified search path, check user format or guess from NAME. */
642 kpse_file_format_type fmt;
643 if (user_format != kpse_last_format)
644 fmt = user_format;
645 else
646 fmt = find_format(kpse, name, true);
648 switch (fmt) {
649 case kpse_pk_format:
650 case kpse_gf_format:
651 case kpse_any_glyph_format:
653 kpse_glyph_file_type glyph_ret;
654 string temp = remove_suffix (name);
655 /* Try to extract the resolution from the name. */
656 unsigned local_dpi = find_dpi(name);
657 if (!local_dpi)
658 local_dpi = (unsigned) dpi;
659 ret =
660 kpathsea_find_glyph(kpse, temp, local_dpi,
661 fmt, &glyph_ret);
662 if (temp != name)
663 free (temp);
665 break;
667 case kpse_last_format:
668 /* If the suffix isn't recognized, assume it's a tex file. */
669 fmt = kpse_tex_format;
670 /* fall through */
672 default:
673 if (show_all) {
674 ret_list =
675 kpathsea_find_file_generic(kpse, name, fmt, must_exist,
676 true);
677 } else {
678 ret = kpathsea_find_file(kpse, name, fmt, must_exist);
683 /* Turn single return into a null-terminated list for uniform treatment. */
684 if (ret) {
685 ret_list = XTALLOC(2, string);
686 ret_list[0] = ret;
687 ret_list[1] = NULL;
690 /* Filter by subdirectories, if specified. */
691 if (STR_LIST_LENGTH(subdir_paths) > 0) {
692 string *new_list = subdir_match(subdir_paths, ret_list);
693 free(ret_list);
694 ret_list = new_list;
696 kpse->debug = saved_debug;
697 kpse->format_info[kpse_pk_format].program_enabled_p = saved_mktexpk;
698 kpse->format_info[kpse_mf_format].program_enabled_p = saved_mktexmf;
699 kpse->format_info[kpse_tex_format].program_enabled_p = saved_mktextex;
700 kpse->format_info[kpse_tfm_format].program_enabled_p = saved_mktextfm;
702 /* Print output. */
703 i = 0;
704 if (ret_list) {
705 for (; ret_list[i]; i++) {
706 lua_pushstring(L, ret_list[i]);
708 free(ret_list);
710 if (i == 0) {
711 i++;
712 lua_pushnil(L);
714 return i;
718 static int lua_kpathsea_lookup(lua_State * L)
720 kpathsea *kpsep = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
721 kpathsea kpse = *kpsep;
722 return do_lua_kpathsea_lookup(L, kpse, 2);
725 static int lua_kpse_lookup(lua_State * L)
727 TEST_PROGRAM_NAME_SET;
728 return do_lua_kpathsea_lookup(L, kpse_def, 1);
732 /* Engine support is a bit of a problem, because we do not want
733 * to interfere with the normal format discovery of |luatex|.
734 * Current approach: run |os.setenv()| if you have to.
737 static int set_program_name(lua_State * L)
739 const char *exe_name = luaL_checkstring(L, 1);
740 const char *prog_name = luaL_optstring(L, 2, exe_name);
741 if (!program_name_set) {
742 kpse_set_program_name(exe_name, prog_name);
743 program_name_set = 1;
744 } else {
745 kpse_reset_program_name(prog_name);
747 /* fix up the texconfig entry */
748 lua_checkstack(L, 3);
749 lua_getglobal(L, "texconfig");
750 if (lua_istable(L, -1)) {
751 lua_pushstring(L, "kpse_init");
752 lua_pushboolean(L, 0);
753 lua_rawset(L, -3);
755 lua_pop(L, 1);
756 return 0;
759 static int init_prog(lua_State * L)
761 const char *prefix = luaL_checkstring(L, 1);
762 unsigned dpi = (unsigned) luaL_checkinteger(L, 2);
763 const char *mode = luaL_checkstring(L, 3);
764 const char *fallback = luaL_optstring(L, 4, NULL);
765 TEST_PROGRAM_NAME_SET;
766 kpse_init_prog(prefix, dpi, mode, fallback);
767 return 0;
770 static int lua_kpathsea_init_prog(lua_State * L)
772 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
773 const char *prefix = luaL_checkstring(L, 2);
774 unsigned dpi = (unsigned) luaL_checkinteger(L, 3);
775 const char *mode = luaL_checkstring(L, 4);
776 const char *fallback = luaL_optstring(L, 5, NULL);
777 kpathsea_init_prog(*kp, prefix, dpi, mode, fallback);
778 return 0;
781 static int lua_kpse_version(lua_State * L)
783 lua_pushstring(L, kpathsea_version_string);
784 return 1;
787 static int readable_file(lua_State * L)
789 char *name = xstrdup(luaL_checkstring(L, 1));
790 TEST_PROGRAM_NAME_SET;
791 lua_pushstring(L, kpse_readable_file(name));
792 free(name);
793 return 1;
796 static int lua_kpathsea_readable_file(lua_State * L)
798 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
799 char *name = xstrdup(luaL_checkstring(L, 2));
800 lua_pushstring(L, kpathsea_readable_file(*kp, name));
801 free(name);
802 return 1;
806 static int lua_kpathsea_finish(lua_State * L)
808 kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
809 kpathsea_finish(*kp);
810 return 0;
813 static int lua_kpathsea_new(lua_State * L)
815 kpathsea kpse = NULL;
816 kpathsea *kp = NULL;
817 const char *av = luaL_checkstring(L, 1);
818 const char *liar = luaL_optstring(L, 2, av);
819 kpse = kpathsea_new();
820 kpathsea_set_program_name(kpse, av, liar);
821 kp = (kpathsea *) lua_newuserdata(L, sizeof(kpathsea *));
822 *kp = kpse;
823 luaL_getmetatable(L, KPATHSEA_METATABLE);
824 lua_setmetatable(L, -2);
825 return 1;
828 static const struct luaL_Reg kpselib_m[] = {
829 {"__gc", lua_kpathsea_finish},
830 {"init_prog", lua_kpathsea_init_prog},
831 {"readable_file", lua_kpathsea_readable_file},
832 {"find_file", lua_kpathsea_find_file},
833 {"expand_path", lua_kpathsea_expand_path},
834 {"expand_var", lua_kpathsea_expand_var},
835 {"expand_braces", lua_kpathsea_expand_braces},
836 {"var_value", lua_kpathsea_var_value},
837 {"show_path", lua_kpathsea_show_path},
838 {"lookup", lua_kpathsea_lookup},
839 {"version", lua_kpse_version},
840 {"default_texmfcnf", show_texmfcnf},
841 {NULL, NULL} /* sentinel */
844 static const struct luaL_Reg kpselib_l[] = {
845 {"new", lua_kpathsea_new},
846 {"set_program_name", set_program_name},
847 {"init_prog", init_prog},
848 {"readable_file", readable_file},
849 {"find_file", find_file},
850 {"expand_path", expand_path},
851 {"expand_var", expand_var},
852 {"expand_braces", expand_braces},
853 {"var_value", var_value},
854 {"show_path", show_path},
855 {"lookup", lua_kpse_lookup},
856 {"version", lua_kpse_version},
857 {"default_texmfcnf", show_texmfcnf},
858 {NULL, NULL} /* sentinel */
861 int luaopen_kpse(lua_State * L)
863 luaL_newmetatable(L, KPATHSEA_METATABLE);
864 lua_pushvalue(L, -1);
865 lua_setfield(L, -2, "__index");
866 luaL_register(L, NULL, kpselib_m);
867 luaL_register(L, "kpse", kpselib_l);
868 return 1;