summaryrefslogtreecommitdiff
path: root/source/luametatex/source/luaoptional/lmtkpse.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/luametatex/source/luaoptional/lmtkpse.c')
-rw-r--r--source/luametatex/source/luaoptional/lmtkpse.c311
1 files changed, 311 insertions, 0 deletions
diff --git a/source/luametatex/source/luaoptional/lmtkpse.c b/source/luametatex/source/luaoptional/lmtkpse.c
new file mode 100644
index 000000000..e593f8b9b
--- /dev/null
+++ b/source/luametatex/source/luaoptional/lmtkpse.c
@@ -0,0 +1,311 @@
+/*
+ See license.txt in the root of this project.
+*/
+
+# include "luametatex.h"
+# include "lmtoptional.h"
+
+/*tex
+
+ As part of the lean and mean concept we have no \KPSE\ on board and as with \LUATEX\ the
+ \CONTEXT\ macro package doesn't need it. However, because we might want to play with it being
+ a runner for other engines (as we do with the \LUATEX\ binary in kpse mode), we have at least
+ an interface for it. One problem is to locate the right version of the delayed loaded kpse
+ library (but we can add some clever locating code for that if needed). We keep the interface
+ mostly the same as \LUATEX.
+
+ This is actually a left-over from an experiment, but it works okay, so I moved the code into
+ the source tree and made a proper \CONTEXT\ library wrapper too. We are less clever than in
+ \LUATEX, so there are no additional lookup functions. After all, it is just about locating
+ files and not about writing a searcher in \LUA. So, there no subdir magic either, as one has
+ \LUA\ for that kind of stuff. No \DPI\ related magic either. In \LUATEX\ there are some more
+ functions in the \type {kpse} namespace but these don't really relate to locating files.
+
+ We can actually omit the next two lists and pass numbers but then we need to store that list at
+ the \LUA\ end so we don't save much (but I might do it some day nevertheless). The nect code is
+ rather lightweight which is on purpose. Of course occationally we need to check the \API\ but
+ \KPSE\ pretty stable and we don't need the extra stuff that it provides (keep in mind that it
+ has to serve all kind of programs in the \TEX\ infrastructure so it's a complex beast).
+
+*/
+
+typedef enum kpselib_file_format_type {
+ kpse_gf_format, kpse_pk_format, kpse_any_glyph_format, kpse_tfm_format, kpse_afm_format,
+ kpse_base_format, kpse_bib_format, kpse_bst_format, kpse_cnf_format, kpse_db_format,
+ kpse_fmt_format, kpse_fontmap_format, kpse_mem_format, kpse_mf_format, kpse_mfpool_format,
+ kpse_mft_format, kpse_mp_format, kpse_mppool_format, kpse_mpsupport_format, kpse_ocp_format,
+ kpse_ofm_format, kpse_opl_format, kpse_otp_format, kpse_ovf_format, kpse_ovp_format,
+ kpse_pict_format, kpse_tex_format, kpse_texdoc_format, kpse_texpool_format,
+ kpse_texsource_format, kpse_tex_ps_header_format, kpse_troff_font_format, kpse_type1_format,
+ kpse_vf_format, kpse_dvips_config_format, kpse_ist_format, kpse_truetype_format,
+ kpse_type42_format, kpse_web2c_format, kpse_program_text_format, kpse_program_binary_format,
+ kpse_miscfonts_format, kpse_web_format, kpse_cweb_format, kpse_enc_format, kpse_cmap_format,
+ kpse_sfd_format, kpse_opentype_format, kpse_pdftex_config_format, kpse_lig_format,
+ kpse_texmfscripts_format, kpse_lua_format, kpse_fea_format, kpse_cid_format, kpse_mlbib_format,
+ kpse_mlbst_format, kpse_clua_format, /* kpse_ris_format, */ /* kpse_bltxml_format, */
+ kpse_last_format
+} kpselib_file_format_type;
+
+static const char *const kpselib_file_type_names[] = {
+ "gf", "pk", "bitmap font", "tfm", "afm", "base", "bib", "bst", "cnf", "ls-R", "fmt", "map",
+ "mem", "mf", "mfpool", "mft", "mp", "mppool", "MetaPost support", "ocp", "ofm", "opl", "otp",
+ "ovf", "ovp", "graphic/figure", "tex", "TeX system documentation", "texpool",
+ "TeX system sources", "PostScript header", "Troff fonts", "type1 fonts", "vf", "dvips config",
+ "ist", "truetype fonts", "type42 fonts", "web2c files", "other text files", "other binary files",
+ "misc fonts", "web", "cweb", "enc files", "cmap files", "subfont definition files",
+ "opentype fonts", "pdftex config", "lig files", "texmfscripts", "lua", "font feature files",
+ "cid maps", "mlbib", "mlbst", "clua",
+ NULL
+};
+
+typedef struct kpselib_state_info {
+
+ int initialized;
+ int prognameset;
+
+ void (*lib_kpse_set_program_name) ( const char *prog, const char *name );
+ void (*lib_kpse_reset_program_name) ( const char *name );
+ char * (*lib_kpse_path_expand) ( const char *name );
+ char * (*lib_kpse_brace_expand) ( const char *name );
+ char * (*lib_kpse_var_expand) ( const char *name );
+ char * (*lib_kpse_var_value) ( const char *name );
+ char * (*lib_kpse_readable_file) ( const char *name );
+ char * (*lib_kpse_find_file) ( const char *name, int filetype, int mustexist );
+ char **(*lib_kpse_all_path_search) ( const char *path, const char *name );
+
+} kpselib_state_info;
+
+static kpselib_state_info kpselib_state = {
+
+ .initialized = 0,
+ .prognameset = 0,
+
+ .lib_kpse_set_program_name = NULL,
+ .lib_kpse_reset_program_name = NULL,
+ .lib_kpse_path_expand = NULL,
+ .lib_kpse_brace_expand = NULL,
+ .lib_kpse_var_expand = NULL,
+ .lib_kpse_var_value = NULL,
+ .lib_kpse_readable_file = NULL,
+ .lib_kpse_find_file = NULL,
+ .lib_kpse_all_path_search = NULL,
+
+};
+
+static int kpselib_aux_valid_progname(lua_State *L)
+{
+ (void) L;
+ if (kpselib_state.prognameset) {
+ return 1;
+ } else if (! kpselib_state.initialized) {
+ tex_normal_warning("kpse", "not yet initialized");
+ return 0;
+ } else {
+ tex_normal_warning("kpse", "no program name set");
+ return 0;
+ }
+}
+
+static int kpselib_set_program_name(lua_State *L)
+{
+ (void) L;
+ if (kpselib_state.initialized) {
+ const char *exe_name = luaL_checkstring(L, 1);
+ const char *prog_name = luaL_optstring(L, 2, exe_name);
+ if (kpselib_state.prognameset) {
+ kpselib_state.lib_kpse_reset_program_name(prog_name);
+ } else {
+ kpselib_state.lib_kpse_set_program_name(exe_name, prog_name);
+ kpselib_state.prognameset = 1;
+ }
+ }
+ return 0;
+}
+
+static int kpselib_find_file(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ unsigned filetype = kpse_tex_format;
+ int mustexist = 0;
+ const char *filename = luaL_checkstring(L, 1);
+ int top = lua_gettop(L);
+ for (int i = 2; i <= top; i++) {
+ switch (lua_type(L, i)) {
+ case LUA_TBOOLEAN:
+ mustexist = lua_toboolean(L, i);
+ break;
+ case LUA_TNUMBER:
+ /*tex This is different from \LUATEX: we accept a filetype number. */
+ filetype = (unsigned) lua_tointeger(L, i);
+ break;
+ case LUA_TSTRING:
+ filetype = luaL_checkoption(L, i, NULL, kpselib_file_type_names);
+ break;
+ }
+ if (filetype >= kpse_last_format) {
+ filetype = kpse_tex_format;
+ }
+ }
+ lua_pushstring(L, kpselib_state.lib_kpse_find_file(filename, filetype, mustexist));
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ I'll ask Taco about the free. For now it will do. Currently I only need to do some lookups for
+ checking clashes with other installations (issue reported on context ml).
+*/
+
+static int kpselib_find_files(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ const char *userpath = luaL_checkstring(L, 1);
+ const char *filename = luaL_checkstring(L, 2);
+ char *filepath = kpselib_state.lib_kpse_path_expand(userpath);
+ if (filepath) {
+ char **result = kpselib_state.lib_kpse_all_path_search(filepath, filename);
+ /* free(filepath); */ /* crashes, so it looks like def kpse keeps it */
+ if (result) {
+ lua_Integer r = 0;
+ lua_newtable(L);
+ while (result[r]) {
+ lua_pushstring(L, result[r]);
+ lua_rawseti(L, -2, ++r);
+ }
+ /* free(result); */ /* idem */
+ return 1;
+ }
+ } else {
+ /* free(filepath); */ /* idem */
+ }
+ }
+ return 0;
+}
+
+static int kpselib_expand_path(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ lua_pushstring(L, kpselib_state.lib_kpse_path_expand(luaL_checkstring(L, 1)));
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int kpselib_expand_braces(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ lua_pushstring(L, kpselib_state.lib_kpse_brace_expand(luaL_checkstring(L, 1)));
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int kpselib_expand_var(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ lua_pushstring(L, kpselib_state.lib_kpse_var_expand(luaL_checkstring(L, 1)));
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int kpselib_var_value(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ lua_pushstring(L, kpselib_state.lib_kpse_var_value(luaL_checkstring(L, 1)));
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int kpselib_readable_file(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ /* Why the dup? */
+ char *name = strdup(luaL_checkstring(L, 1));
+ lua_pushstring(L, kpselib_state.lib_kpse_readable_file(name));
+ free(name);
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int kpselib_get_file_types(lua_State *L)
+{
+ if (kpselib_aux_valid_progname(L)) {
+ lua_createtable(L, kpse_last_format, 0);
+ for (lua_Integer i = 0; i < kpse_last_format; i++) {
+ if (kpselib_file_type_names[i]) {
+ lua_pushstring(L, kpselib_file_type_names[i]);
+ lua_rawseti(L, -2, i + 1);
+ } else {
+ break;
+ }
+ }
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int kpselib_initialize(lua_State *L)
+{
+ if (! kpselib_state.initialized) {
+ const char *filename = lua_tostring(L, 1);
+ if (filename) {
+
+ lmt_library lib = lmt_library_load(filename);
+
+ kpselib_state.lib_kpse_set_program_name = lmt_library_find(lib, "kpse_set_program_name");
+ kpselib_state.lib_kpse_reset_program_name = lmt_library_find(lib, "kpse_reset_program_name");
+ kpselib_state.lib_kpse_all_path_search = lmt_library_find(lib, "kpse_all_path_search");
+ kpselib_state.lib_kpse_find_file = lmt_library_find(lib, "kpse_find_file");
+ kpselib_state.lib_kpse_path_expand = lmt_library_find(lib, "kpse_path_expand");
+ kpselib_state.lib_kpse_brace_expand = lmt_library_find(lib, "kpse_brace_expand");
+ kpselib_state.lib_kpse_var_expand = lmt_library_find(lib, "kpse_var_expand");
+ kpselib_state.lib_kpse_var_value = lmt_library_find(lib, "kpse_var_value");
+ kpselib_state.lib_kpse_readable_file = lmt_library_find(lib, "kpse_readable_file");
+
+ kpselib_state.initialized = lmt_library_okay(lib);
+ }
+ }
+ lua_pushboolean(L, kpselib_state.initialized);
+ return 1;
+}
+
+/*tex We use the official names here, with underscores. */
+
+/* init_prog : no need */
+/* show_path : maybe */
+/* lookup : maybe */
+/* default_texmfcnf : not that useful */
+/* record_output_file : makes no sense */
+/* record_input_file : makes no sense */
+/* check_permissions : luatex extra */
+
+static struct luaL_Reg kpselib_function_list[] = {
+ { "initialize", kpselib_initialize },
+ { "set_program_name", kpselib_set_program_name },
+ { "find_file", kpselib_find_file },
+ { "find_files", kpselib_find_files },
+ { "expand_path", kpselib_expand_path },
+ { "expand_var", kpselib_expand_var },
+ { "expand_braces", kpselib_expand_braces },
+ { "var_value", kpselib_var_value },
+ { "readable_file", kpselib_readable_file },
+ { "get_file_types", kpselib_get_file_types },
+ { NULL, NULL },
+};
+
+int luaopen_kpse(lua_State * L)
+{
+ lmt_library_register(L, "kpse", kpselib_function_list);
+ return 0;
+}