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/>. */
23 #include "mfluajitd.h"
27 #include <kpathsea/version.h>
28 #define xfree(p) do { if (p != NULL) free(p); p = NULL; } while (0)
31 #include "lua/luatex-api.h"
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
[] = {
46 kpse_any_glyph_format
,
62 kpse_mpsupport_format
,
73 kpse_texsource_format
,
74 kpse_tex_ps_header_format
,
75 kpse_troff_font_format
,
78 kpse_dvips_config_format
,
83 kpse_program_text_format
,
84 kpse_program_binary_format
,
85 kpse_miscfonts_format
,
92 kpse_pdftex_config_format
,
94 kpse_texmfscripts_format
,
103 static const char *const filetypenames
[] = {
131 "TeX system documentation",
133 "TeX system sources",
144 "other binary files",
150 "subfont definition files",
156 "font feature files",
166 #define KPATHSEA_METATABLE "mflua.kpathsea"
168 #define KPATHSEA_METATABLE "luatex.kpathsea"
171 /* set to 1 by the |program_name| function */
174 int program_name_set
= 1;
176 int program_name_set
= 0;
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"); \
185 static int find_file(lua_State
* L
)
189 unsigned ftype
= kpse_tex_format
;
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);
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
];
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
));
218 lua_pushstring(L
, kpse_find_file(st
, ftype
, mexist
));
224 static int lua_kpathsea_find_file(lua_State
* L
)
227 unsigned ftype
= kpse_tex_format
;
229 kpathsea
*kp
= (kpathsea
*) luaL_checkudata(L
, 1, KPATHSEA_METATABLE
);
230 const char *st
= luaL_checkstring(L
, 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
];
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
;
248 kpathsea_find_glyph(*kp
, st
, (unsigned) mexist
, ftype
,
255 lua_pushstring(L
, kpathsea_find_file(*kp
, st
, ftype
, mexist
));
261 static int show_texmfcnf(lua_State
* L
)
263 lua_pushstring(L
, DEFAULT_TEXMFCNF
);
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
);
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
);
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
));
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
);
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
);
381 for (m
= 0; matches
[m
]; m
++) {
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])) {
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])) {
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
];
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
;
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
) {
460 boolean found
= false;
462 if (!kpse
->format_info
[f
].type
)
463 kpathsea_init_format(kpse
, (kpse_file_format_type
) f
);
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
;
473 found
= TRY_SUFFIX(*ext
);
475 for (ext
= kpse
->format_info
[f
].alt_suffix
; !found
&& ext
&& *ext
;
477 found
= TRY_SUFFIX(*ext
);
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
) {
494 } else if (f
== kpse_last_format
) {
499 /* If there was a match, f will be one past the correct value. */
506 /* kpse:lookup("plain.tex", {}) */
507 static int do_lua_kpathsea_lookup(lua_State
* L
, kpathsea kpse
, int idx
)
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
;
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
];
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);
541 lua_pushstring(L
, "debug");
542 lua_gettable(L
, idx
+ 1);
543 if (lua_type(L
, -1) == LUA_TNUMBER
) {
545 d
=(int)lua_tonumber(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));
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);
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));
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));
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));
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));
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);
597 lua_pushstring(L
, "subdir");
598 lua_gettable(L
, idx
+ 1);
599 if (lua_istable(L
, -1)) {
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
);
609 } else if (lua_isstring(L
, -1)) {
610 char *s
= xstrdup(lua_tostring(L
, -1));
611 str_list_add(&subdir_paths
, s
);
615 if (STR_LIST_LENGTH(subdir_paths
) > 0) {
620 /* Translate ; to : if that's our ENV_SEP. See cnf.c. */
621 if (IS_ENV_SEP(':')) {
623 for (loc
= user_path
; *loc
; loc
++) {
628 user_path
= kpathsea_path_expand(kpse
, user_path
);
630 ret_list
= kpathsea_all_path_search(kpse
, user_path
, name
);
632 ret
= kpathsea_path_search(kpse
, user_path
, name
, must_exist
);
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
)
641 fmt
= find_format(kpse
, name
, true);
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
);
653 local_dpi
= (unsigned) dpi
;
655 kpathsea_find_glyph(kpse
, temp
, local_dpi
,
662 case kpse_last_format
:
663 /* If the suffix isn't recognized, assume it's a tex file. */
664 fmt
= kpse_tex_format
;
670 kpathsea_find_file_generic(kpse
, name
, fmt
, must_exist
,
673 ret
= kpathsea_find_file(kpse
, name
, fmt
, must_exist
);
678 /* Turn single return into a null-terminated list for uniform treatment. */
680 ret_list
= XTALLOC(2, string
);
685 /* Filter by subdirectories, if specified. */
686 if (STR_LIST_LENGTH(subdir_paths
) > 0) {
687 string
*new_list
= subdir_match(subdir_paths
, ret_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
;
700 for (; ret_list
[i
]; i
++) {
701 lua_pushstring(L
, ret_list
[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;
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);
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
);
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
);
776 static int lua_kpse_version(lua_State
* L
)
778 lua_pushstring(L
, kpathsea_version_string
);
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
));
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
));
801 static int lua_kpathsea_finish(lua_State
* L
)
803 kpathsea
*kp
= (kpathsea
*) luaL_checkudata(L
, 1, KPATHSEA_METATABLE
);
804 kpathsea_finish(*kp
);
808 static int lua_kpathsea_new(lua_State
* L
)
810 kpathsea kpse
= 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
*));
818 luaL_getmetatable(L
, KPATHSEA_METATABLE
);
819 lua_setmetatable(L
, -2);
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
);