summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/lua/lkpselib.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/lkpselib.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lkpselib.c427
1 files changed, 405 insertions, 22 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/lkpselib.c b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c
index 71c772eb732..16c6a4ba23a 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lkpselib.c
+++ b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c
@@ -17,17 +17,20 @@
You should have received a copy of the GNU General Public License along
with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
-#include "luatex-api.h"
-#include <ptexlib.h>
+#include "lua/luatex-api.h"
+#include "ptexlib.h"
#include <kpathsea/expand.h>
#include <kpathsea/variable.h>
#include <kpathsea/tex-glyph.h>
#include <kpathsea/readable.h>
+#include <kpathsea/pathsearch.h>
+#include <kpathsea/str-list.h>
+#include <kpathsea/tex-file.h>
static const char _svn_version[] =
- "$Id: lkpselib.c 2414 2009-06-03 12:57:01Z taco $ $URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/lua/lkpselib.c $";
+ "$Id: lkpselib.c 3551 2010-03-26 14:43:50Z taco $ $URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/lua/lkpselib.c $";
-static const int filetypes[] = {
+static const unsigned filetypes[] = {
kpse_gf_format,
kpse_pk_format,
kpse_any_glyph_format,
@@ -83,7 +86,8 @@ static const int filetypes[] = {
kpse_fea_format,
kpse_cid_format,
kpse_mlbib_format,
- kpse_mlbst_format
+ kpse_mlbst_format,
+ kpse_clua_format
};
static const char *const filetypenames[] = {
@@ -143,6 +147,7 @@ static const char *const filetypenames[] = {
"cid maps",
"mlbib",
"mlbst",
+ "clua",
NULL
};
@@ -155,8 +160,7 @@ int program_name_set = 0;
#define TEST_PROGRAM_NAME_SET do { \
if (! program_name_set) { \
- lua_pushstring(L, "Please call kpse.set_program_name() before using the library"); \
- return lua_error(L); \
+ return luaL_error(L, "Please call kpse.set_program_name() before using the library"); \
} \
} while (0)
@@ -164,12 +168,11 @@ static int find_file(lua_State * L)
{
int i;
const char *st;
- int ftype = kpse_tex_format;
+ unsigned ftype = kpse_tex_format;
int mexist = 0;
TEST_PROGRAM_NAME_SET;
if (!lua_isstring(L, 1)) {
- lua_pushstring(L, "not a file name");
- lua_error(L);
+ luaL_error(L, "not a file name");
}
st = lua_tostring(L, 1);
i = lua_gettop(L);
@@ -177,7 +180,7 @@ static int find_file(lua_State * L)
if (lua_isboolean(L, i)) {
mexist = lua_toboolean(L, i);
} else if (lua_isnumber(L, i)) {
- mexist = lua_tonumber(L, i);
+ lua_number2int(mexist, lua_tonumber(L, i));
} else if (lua_isstring(L, i)) {
int op = luaL_checkoption(L, i, NULL, filetypenames);
ftype = filetypes[op];
@@ -188,7 +191,7 @@ static int find_file(lua_State * L)
ftype == kpse_gf_format || ftype == kpse_any_glyph_format) {
/* ret.format, ret.name, ret.dpi */
kpse_glyph_file_type ret;
- lua_pushstring(L, kpse_find_glyph(st, mexist, ftype, &ret));
+ lua_pushstring(L, kpse_find_glyph(st, (unsigned) mexist, ftype, &ret));
} else {
if (mexist > 0)
mexist = 1;
@@ -203,16 +206,16 @@ static int find_file(lua_State * L)
static int lua_kpathsea_find_file(lua_State * L)
{
int i;
- int ftype = kpse_tex_format;
+ unsigned ftype = kpse_tex_format;
int mexist = 0;
kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
const char *st = luaL_checkstring(L, 2);
i = lua_gettop(L);
while (i > 2) {
if (lua_isboolean(L, i)) {
- mexist = lua_toboolean(L, i);
+ mexist = (boolean) lua_toboolean(L, i);
} else if (lua_isnumber(L, i)) {
- mexist = lua_tonumber(L, i);
+ lua_number2int(mexist, lua_tonumber(L, i));
} else if (lua_isstring(L, i)) {
int op = luaL_checkoption(L, i, NULL, filetypenames);
ftype = filetypes[op];
@@ -223,7 +226,9 @@ static int lua_kpathsea_find_file(lua_State * L)
ftype == kpse_gf_format || ftype == kpse_any_glyph_format) {
/* ret.format, ret.name, ret.dpi */
kpse_glyph_file_type ret;
- lua_pushstring(L, kpathsea_find_glyph(*kp, st, mexist, ftype, &ret));
+ lua_pushstring(L,
+ kpathsea_find_glyph(*kp, st, (unsigned) mexist, ftype,
+ &ret));
} else {
if (mexist > 0)
mexist = 1;
@@ -238,7 +243,7 @@ static int lua_kpathsea_find_file(lua_State * L)
static int show_path(lua_State * L)
{
int op = luaL_checkoption(L, -1, "tex", filetypenames);
- int user_format = filetypes[op];
+ unsigned user_format = filetypes[op];
TEST_PROGRAM_NAME_SET;
if (!kpse_format_info[user_format].type) /* needed if arg was numeric */
kpse_init_format(user_format);
@@ -250,7 +255,7 @@ static int lua_kpathsea_show_path(lua_State * L)
{
kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
int op = luaL_checkoption(L, -1, "tex", filetypenames);
- int user_format = filetypes[op];
+ unsigned user_format = filetypes[op];
if (!(*kp)->format_info[user_format].type) /* needed if arg was numeric */
kpathsea_init_format(*kp, user_format);
lua_pushstring(L, (*kp)->format_info[user_format].path);
@@ -323,6 +328,374 @@ static int lua_kpathsea_var_value(lua_State * L)
return 1;
}
+static unsigned find_dpi(const_string s)
+{
+ unsigned dpi_number = 0;
+ string extension = find_suffix(s);
+
+ if (extension != NULL)
+ sscanf(extension, "%u", &dpi_number);
+
+ return dpi_number;
+}
+
+/* Return newly-allocated NULL-terminated list of strings from MATCHES
+ that are prefixed with any of the subdirectories in SUBDIRS. That
+ is, for a string S in MATCHES, its dirname must end with one of the
+ elements in SUBDIRS. For instance, if subdir=foo/bar, that will
+ match a string foo/bar/baz or /some/texmf/foo/bar/baz.
+
+ We don't reallocate the actual strings, just the list elements.
+ Perhaps later we will implement wildcards or // or something. */
+
+static string *subdir_match(str_list_type subdirs, string * matches)
+{
+ string *ret = XTALLOC1(string);
+ unsigned len = 1;
+ unsigned m;
+
+ for (m = 0; matches[m]; m++) {
+ size_t loc;
+ unsigned e;
+ string s = xstrdup(matches[m]);
+ for (loc = strlen(s); loc > 0 && !IS_DIR_SEP(s[loc - 1]); loc--);
+ while (loc > 0 && IS_DIR_SEP(s[loc - 1])) {
+ loc--;
+ }
+ s[loc] = 0; /* wipe out basename */
+
+ for (e = 0; e < STR_LIST_LENGTH(subdirs); e++) {
+ string subdir = STR_LIST_ELT(subdirs, e);
+ size_t subdir_len = strlen(subdir);
+ while (subdir_len > 0 && IS_DIR_SEP(subdir[subdir_len - 1])) {
+ subdir_len--;
+ subdir[subdir_len] = 0; /* remove trailing slashes from subdir spec */
+ }
+ if (FILESTRCASEEQ(subdir, s + loc - subdir_len)) {
+ /* matched, save this one. */
+ XRETALLOC(ret, len + 1, string);
+ ret[len - 1] = matches[m];
+ len++;
+ }
+ }
+ free(s);
+ }
+ ret[len - 1] = NULL;
+ return ret;
+}
+
+/* Use the file type from -format if that was specified (i.e., the
+ user_format global variable), else guess dynamically from NAME.
+ Return kpse_last_format if undeterminable. This function is also
+ used to parse the -format string, a case which we distinguish by
+ setting is_filename to false.
+
+ A few filenames have been hard-coded for format types that
+ differ from what would be inferred from their extensions. */
+
+static kpse_file_format_type
+find_format(kpathsea kpse, const_string name, boolean is_filename)
+{
+ kpse_file_format_type ret;
+
+ if (FILESTRCASEEQ(name, "config.ps")) {
+ ret = kpse_dvips_config_format;
+ } else if (FILESTRCASEEQ(name, "dvipdfmx.cfg")) {
+ ret = kpse_program_text_format;
+ } else if (FILESTRCASEEQ(name, "fmtutil.cnf")) {
+ ret = kpse_web2c_format;
+ } else if (FILESTRCASEEQ(name, "glyphlist.txt")) {
+ ret = kpse_fontmap_format;
+ } else if (FILESTRCASEEQ(name, "mktex.cnf")) {
+ ret = kpse_web2c_format;
+ } else if (FILESTRCASEEQ(name, "pdfglyphlist.txt")) {
+ ret = kpse_fontmap_format;
+ } else if (FILESTRCASEEQ(name, "pdftex.cfg")) {
+ ret = kpse_pdftex_config_format;
+ } else if (FILESTRCASEEQ(name, "texmf.cnf")) {
+ ret = kpse_cnf_format;
+ } else if (FILESTRCASEEQ(name, "updmap.cfg")) {
+ ret = kpse_web2c_format;
+ } else if (FILESTRCASEEQ(name, "XDvi")) {
+ ret = kpse_program_text_format;
+ } else {
+ int f = 0; /* kpse_file_format_type */
+ size_t name_len = strlen(name);
+
+/* Have to rely on `try_len' being declared here, since we can't assume
+ GNU C and statement expressions. */
+#define TRY_SUFFIX(ftry) (\
+ try_len = (ftry) ? strlen (ftry) : 0, \
+ (ftry) && try_len <= name_len \
+ && FILESTRCASEEQ (ftry, name + name_len - try_len))
+
+ while (f != kpse_last_format) {
+ size_t try_len;
+ const_string *ext;
+ const_string ftry;
+ boolean found = false;
+
+ if (!kpse->format_info[f].type)
+ kpathsea_init_format(kpse, (kpse_file_format_type) f);
+
+ if (!is_filename) {
+ /* Allow the long name, but only in the -format option. We don't
+ want a filename confused with a format name. */
+ ftry = kpse->format_info[f].type;
+ found = TRY_SUFFIX(ftry);
+ }
+ for (ext = kpse->format_info[f].suffix; !found && ext && *ext;
+ ext++) {
+ found = TRY_SUFFIX(*ext);
+ }
+ for (ext = kpse->format_info[f].alt_suffix; !found && ext && *ext;
+ ext++) {
+ found = TRY_SUFFIX(*ext);
+ }
+
+ if (found)
+ break;
+
+ /* Some trickery here: the extensions for kpse_fmt_format can
+ * clash with other extensions in use, and we prefer for those
+ * others to be preferred. And we don't want to change the
+ * integer value of kpse_fmt_format. So skip it when first
+ * enountered, then use it when we've done everything else,
+ * and use it as the end-guard.
+ */
+ if (f == kpse_fmt_format) {
+ f = kpse_last_format;
+ } else if (++f == kpse_fmt_format) {
+ f++;
+ } else if (f == kpse_last_format) {
+ f = kpse_fmt_format;
+ }
+ }
+
+ /* If there was a match, f will be one past the correct value. */
+ ret = f;
+ }
+
+ return ret;
+}
+
+/* kpse:lookup("plain.tex", {}) */
+static int do_lua_kpathsea_lookup(lua_State * L, kpathsea kpse, int idx)
+{
+ int i;
+ string ret = NULL;
+ string *ret_list = NULL;
+ const_string name = NULL;
+ string user_path = NULL;
+ boolean show_all = false;
+ boolean must_exist = false;
+ kpse_file_format_type user_format = kpse_last_format;
+ int dpi = 600;
+ str_list_type subdir_paths = { 0, NULL };
+ unsigned saved_debug = kpse->debug;
+ int saved_mktexpk = kpse->format_info[kpse_pk_format].program_enabled_p;
+ int saved_mktexmf = kpse->format_info[kpse_mf_format].program_enabled_p;
+ int saved_mktextex = kpse->format_info[kpse_tex_format].program_enabled_p;
+ int saved_mktextfm = kpse->format_info[kpse_tfm_format].program_enabled_p;
+ name = luaL_checkstring(L, idx);
+ /* todo: fetch parameter values */
+
+ if (lua_type(L, idx + 1) == LUA_TTABLE) {
+ lua_pushstring(L, "format");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ int op = luaL_checkoption(L, -1, NULL, filetypenames);
+ user_format = filetypes[op];
+ }
+ lua_pop(L, 1);
+ lua_pushstring(L, "dpi");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ lua_number2int(dpi, lua_tonumber(L, -1));
+ }
+ lua_pop(L, 1);
+ lua_pushstring(L, "debug");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ int d = 0;
+ lua_number2int(d, lua_tonumber(L, -1));
+ kpse->debug |= d;
+ }
+ lua_pop(L, 1);
+ lua_pushstring(L, "path");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ user_path = xstrdup(lua_tostring(L, -1));
+ }
+ lua_pop(L, 1);
+ lua_pushstring(L, "all");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ show_all = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "mktexpk");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ kpathsea_maketex_option(kpse, "pk", lua_toboolean(L, -1));
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "mktextex");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ kpathsea_maketex_option(kpse, "tex", lua_toboolean(L, -1));
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "mktexmf");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ kpathsea_maketex_option(kpse, "mf", lua_toboolean(L, -1));
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "mktextfm");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ kpathsea_maketex_option(kpse, "tfm", lua_toboolean(L, -1));
+ }
+ lua_pop(L, 1);
+
+
+ lua_pushstring(L, "must-exist");
+ lua_gettable(L, idx + 1);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ must_exist = lua_toboolean(L, -1);
+ }
+ lua_pop(L, 1);
+ lua_pushstring(L, "subdir");
+ lua_gettable(L, idx + 1);
+ if (lua_istable(L, -1)) {
+ lua_pushnil(L);
+ while (lua_next(L, -2) != 0) { /* numeric value */
+ if (lua_isstring(L, -1)) {
+ char *s = xstrdup(lua_tostring(L, -1));
+ str_list_add(&subdir_paths, s);
+ xfree(s);
+ }
+ lua_pop(L, 1);
+ }
+ } else if (lua_isstring(L, -1)) {
+ char *s = xstrdup(lua_tostring(L, -1));
+ str_list_add(&subdir_paths, s);
+ xfree(s);
+ }
+ lua_pop(L, 1);
+ if (STR_LIST_LENGTH(subdir_paths) > 0) {
+ show_all = 1;
+ }
+ }
+ if (user_path) {
+ /* Translate ; to : if that's our ENV_SEP. See cnf.c. */
+ if (IS_ENV_SEP(':')) {
+ string loc;
+ for (loc = user_path; *loc; loc++) {
+ if (*loc == ';')
+ *loc = ':';
+ }
+ }
+ user_path = kpathsea_path_expand(kpse, user_path);
+ if (show_all) {
+ ret_list = kpathsea_all_path_search(kpse, user_path, name);
+ } else {
+ ret = kpathsea_path_search(kpse, user_path, name, must_exist);
+ }
+ free(user_path);
+ } else {
+ /* No user-specified search path, check user format or guess from NAME. */
+ kpse_file_format_type fmt;
+ if (user_format != kpse_last_format)
+ fmt = user_format;
+ else
+ fmt = find_format(kpse, name, true);
+
+ switch (fmt) {
+ case kpse_pk_format:
+ case kpse_gf_format:
+ case kpse_any_glyph_format:
+ {
+ kpse_glyph_file_type glyph_ret;
+ /* Try to extract the resolution from the name. */
+ unsigned local_dpi = find_dpi(name);
+ if (!local_dpi)
+ local_dpi = (unsigned) dpi;
+ ret =
+ kpathsea_find_glyph(kpse, remove_suffix(name), local_dpi,
+ fmt, &glyph_ret);
+ }
+ break;
+
+ case kpse_last_format:
+ /* If the suffix isn't recognized, assume it's a tex file. */
+ fmt = kpse_tex_format;
+ /* fall through */
+
+ default:
+ if (show_all) {
+ ret_list =
+ kpathsea_find_file_generic(kpse, name, fmt, must_exist,
+ true);
+ } else {
+ ret = kpathsea_find_file(kpse, name, fmt, must_exist);
+ }
+ }
+ }
+
+ /* Turn single return into a null-terminated list for uniform treatment. */
+ if (ret) {
+ ret_list = XTALLOC(2, string);
+ ret_list[0] = ret;
+ ret_list[1] = NULL;
+ }
+
+ /* Filter by subdirectories, if specified. */
+ if (STR_LIST_LENGTH(subdir_paths) > 0) {
+ string *new_list = subdir_match(subdir_paths, ret_list);
+ free(ret_list);
+ ret_list = new_list;
+ }
+ kpse->debug = saved_debug;
+ kpse->format_info[kpse_pk_format].program_enabled_p = saved_mktexpk;
+ kpse->format_info[kpse_mf_format].program_enabled_p = saved_mktexmf;
+ kpse->format_info[kpse_tex_format].program_enabled_p = saved_mktextex;
+ kpse->format_info[kpse_tfm_format].program_enabled_p = saved_mktextfm;
+
+ /* Print output. */
+ i = 0;
+ if (ret_list) {
+ for (; ret_list[i]; i++) {
+ lua_pushstring(L, ret_list[i]);
+ }
+ free(ret_list);
+ }
+ if (i == 0) {
+ i++;
+ lua_pushnil(L);
+ }
+ return i;
+}
+
+
+static int lua_kpathsea_lookup(lua_State * L)
+{
+ kpathsea *kpsep = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
+ kpathsea kpse = *kpsep;
+ return do_lua_kpathsea_lookup(L, kpse, 2);
+}
+
+static int lua_kpse_lookup(lua_State * L)
+{
+ TEST_PROGRAM_NAME_SET;
+ return do_lua_kpathsea_lookup(L, kpse_def, 1);
+}
+
/* Engine support is a bit of a problem, because we do not want
* to interfere with the normal format discovery of |luatex|.
@@ -354,7 +727,7 @@ static int set_program_name(lua_State * L)
static int init_prog(lua_State * L)
{
const char *prefix = luaL_checkstring(L, 1);
- unsigned dpi = luaL_checkinteger(L, 2);
+ unsigned dpi = (unsigned) luaL_checkinteger(L, 2);
const char *mode = luaL_checkstring(L, 3);
const char *fallback = luaL_optstring(L, 4, NULL);
TEST_PROGRAM_NAME_SET;
@@ -366,18 +739,24 @@ static int lua_kpathsea_init_prog(lua_State * L)
{
kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
const char *prefix = luaL_checkstring(L, 2);
- unsigned dpi = luaL_checkinteger(L, 3);
+ unsigned dpi = (unsigned) luaL_checkinteger(L, 3);
const char *mode = luaL_checkstring(L, 4);
const char *fallback = luaL_optstring(L, 5, NULL);
kpathsea_init_prog(*kp, prefix, dpi, mode, fallback);
return 0;
}
+static int lua_kpse_version(lua_State * L)
+{
+ lua_pushstring(L, kpathsea_version_string);
+ return 1;
+}
+
static int readable_file(lua_State * L)
{
const char *name = luaL_checkstring(L, 1);
TEST_PROGRAM_NAME_SET;
- lua_pushstring(L, kpse_readable_file(name));
+ lua_pushstring(L, (char *) kpse_readable_file(name));
return 1;
}
@@ -385,7 +764,7 @@ static int lua_kpathsea_readable_file(lua_State * L)
{
kpathsea *kp = (kpathsea *) luaL_checkudata(L, 1, KPATHSEA_METATABLE);
const char *name = luaL_checkstring(L, 2);
- lua_pushstring(L, kpathsea_readable_file(*kp, name));
+ lua_pushstring(L, (char *) kpathsea_readable_file(*kp, name));
return 1;
}
@@ -422,6 +801,8 @@ static const struct luaL_reg kpselib_m[] = {
{"expand_braces", lua_kpathsea_expand_braces},
{"var_value", lua_kpathsea_var_value},
{"show_path", lua_kpathsea_show_path},
+ {"lookup", lua_kpathsea_lookup},
+ {"version", lua_kpse_version},
{NULL, NULL} /* sentinel */
};
@@ -436,6 +817,8 @@ static const struct luaL_reg kpselib_l[] = {
{"expand_braces", expand_braces},
{"var_value", var_value},
{"show_path", show_path},
+ {"lookup", lua_kpse_lookup},
+ {"version", lua_kpse_version},
{NULL, NULL} /* sentinel */
};