2 kpath.c -- implement kpathsea bindings
4 source file of the GNU LilyPond music typesetter
6 (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
16 #include "guile-compatibility.hh"
20 gettext (char const *s)
28 #define _(x) gettext (x)
34 /* The (?) problem, as far as I (?) can tell, is that MacOS X has its
35 getopt prototype in <unistd.h>, while I think other operating
36 systems have it in other places. <unistd.h> is included by
37 kpathsea.h, so you end up renaming both conflicting prototypes to
38 KPATHSEA_HAS_GETOPT_PROTOTYPE_PROBLEM.
40 I (?) found a somewhat more elegant patch for this: Just #include
41 <unistd.h> before defining KPATHSEA_HAS_GETOPT_PROTOTYPE_PROBLEM. */
45 #define popen KPATHSEA_HAS_POPEN_PROTOTYPE_PROBLEM
46 #define pclose KPATHSEA_HAS_PCLOSE_PROTOTYPE_PROBLEM
47 #define getopt KPATHSEA_HAS_GETOPT_PROTOTYPE_PROBLEM
49 #if HAVE_KPATHSEA_KPATHSEA_H
50 #include <kpathsea/kpathsea.h>
51 #include <kpathsea/tex-file.h>
54 static void *kpathsea_handle = 0;
55 static char *(*dl_kpse_find_file) (char const*, kpse_file_format_type, boolean) = 0;
56 static void (*dl_kpse_maketex_option) (char const*, boolean) = 0;
57 static void (*dl_kpse_set_program_name) (char const*, char const*) = 0;
58 static char const *(*dl_kpse_init_format) (kpse_file_format_type) = 0;
59 static char *(*dl_kpse_var_expand) (char const*) = 0;
60 static kpse_format_info_type (*dl_kpse_format_info)[kpse_last_format] = 0;
63 kpathsea_find_format (char const* name)
66 int len = strlen (name);
67 for (i = 0; i < kpse_last_format; i++)
69 if (!(*dl_kpse_format_info)[i].type)
70 (*dl_kpse_init_format) ((kpse_file_format_type) i);
72 char const **suffixes[] = { (*dl_kpse_format_info)[i].suffix,
73 (*dl_kpse_format_info)[i].alt_suffix };
74 for (int j = 0; j < 2; j++)
75 for (char const **p = suffixes[j]; p && *p; p++)
77 int suflen = strlen (*p);
79 if (!strncmp (name + len - suflen, *p, suflen))
80 return (kpse_file_format_type) i;
83 return kpse_last_format;
86 // "Return the absolute file name of @var{name}, "
87 // "or @code{#f} if not found.")
89 ly_kpathsea_find_file (SCM name)
91 SCM_ASSERT_TYPE (scm_is_string (name), name, SCM_ARG1, __FUNCTION__, "string");
93 char const *nm = scm_i_string_chars (name);
94 char *p = (*dl_kpse_find_file) (nm, kpathsea_find_format (nm), true);
96 return scm_makfrom0str (p);
100 // "Return the expanded version @var{var}.")
101 SCM ly_kpathsea_expand_variable (SCM var)
103 SCM_ASSERT_TYPE (scm_is_string (var), var, SCM_ARG1, __FUNCTION__, "string");
105 char const *nm = scm_i_string_chars (var);
106 char *result = (*dl_kpse_var_expand) (nm);
107 SCM ret = scm_makfrom0str (result);
114 static char const* LIBKPATHSEA = "libkpathsea.so";
119 #if HAVE_LIBKPATHSEA_SO
125 {(void*)&dl_kpse_find_file, "kpse_find_file"},
126 {(void*)&dl_kpse_set_program_name, "kpse_set_program_name"},
127 {(void*)&dl_kpse_format_info, "kpse_format_info"},
128 {(void*)&dl_kpse_init_format, "kpse_init_format"},
129 {(void*)&dl_kpse_maketex_option, "kpse_maketex_option"},
130 {(void*)&dl_kpse_var_expand, "kpse_var_expand"},
136 kpathsea_handle = dlopen (LIBKPATHSEA, RTLD_LAZY);
137 if (!kpathsea_handle)
142 fprintf (stderr, _ ("can't dlopen: %s: %s"), LIBKPATHSEA, dlerror ());
143 fprintf (stderr, _ ("install package: %s or %s"),
144 "libkpathsea3 (teTeX 2.x)",
145 "libkpathsea4 (teTeX 3.x)");
150 for (int i = 0; symbols[i].func_pointer; i++)
153 *symbols[i].func_pointer = dlsym (kpathsea_handle, symbols[i].name);
154 if (!symbols[i].func_pointer)
156 fprintf (stderr, _ ("no such symbol: %s: %s"),
164 dl_kpse_find_file = &kpse_find_file;
165 dl_kpse_set_program_name = &kpse_set_program_name;
166 dl_kpse_format_info = &kpse_format_info;
167 dl_kpse_init_format = &kpse_init_format;
168 dl_kpse_maketex_option = &kpse_maketex_option;
169 dl_kpse_var_expand = &kpse_var_expand;
175 initialize_kpathsea ()
179 fprintf (stderr, _ ("error opening kpathsea library"));
180 fprintf (stderr, _ ("aborting"));
184 (*dl_kpse_set_program_name) ("lilypond", "lilypond");
185 (*dl_kpse_maketex_option) ("tfm", TRUE);
187 SCM find = scm_c_define_gsubr ("ly:kpathsea-find-file", 1, 0, 0,
188 ly_kpathsea_find_file);
189 scm_c_export ("ly:kpathsea-find-file", NULL);
190 SCM expand = scm_c_define_gsubr ("ly:kpathsea-expand-variable", 1, 0, 0,
191 ly_kpathsea_expand_variable);
192 scm_c_export ("ly:kpathsea-expand-variable", NULL);