]> git.donarmstrong.com Git - lilypond.git/blob - kpath-guile/kpath.c
(local-uninstall): remove
[lilypond.git] / kpath-guile / kpath.c
1 /*
2   kpath.c --  implement kpathsea bindings
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 2005 Han-Wen Nienhuys <hanwen@xs4all.nl>
7 */
8
9
10 #include <libguile.h>
11
12 #include "config.hh"
13
14 #if KPATHSEA
15
16 #include "guile-compatibility.hh"
17
18 #if !HAVE_GETTEXT
19 inline char *
20 gettext (char const *s)
21 {
22   return (char *)s;
23 }
24 #else
25 #include <libintl.h>
26 #endif
27
28 #define _(x) gettext (x)
29
30 #include <dlfcn.h>
31 #include <stdio.h>
32 #include <string.h>
33
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.
39
40    I (?) found a somewhat more elegant patch for this: Just #include
41    <unistd.h> before defining KPATHSEA_HAS_GETOPT_PROTOTYPE_PROBLEM.  */
42
43 #include <unistd.h>     
44
45 #define popen KPATHSEA_HAS_POPEN_PROTOTYPE_PROBLEM
46 #define pclose KPATHSEA_HAS_PCLOSE_PROTOTYPE_PROBLEM
47 #define getopt KPATHSEA_HAS_GETOPT_PROTOTYPE_PROBLEM
48
49 #if HAVE_KPATHSEA_KPATHSEA_H
50 #include <kpathsea/kpathsea.h>
51 #include <kpathsea/tex-file.h>
52 #endif
53
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;
61
62 kpse_file_format_type
63 kpathsea_find_format (char const* name)
64 {
65   int i;
66   int len = strlen (name);
67   for (i = 0; i < kpse_last_format; i++)
68     {
69        if (!(*dl_kpse_format_info)[i].type)
70         (*dl_kpse_init_format) ((kpse_file_format_type) i);
71
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++)
76           {
77             int suflen = strlen (*p);
78             
79             if (!strncmp (name + len - suflen, *p, suflen))
80               return (kpse_file_format_type) i;
81           }
82     }
83   return kpse_last_format;
84 }
85
86 //         "Return the absolute file name of @var{name}, "
87 //         "or @code{#f} if not found.")
88 SCM
89 ly_kpathsea_find_file (SCM name)
90 {
91   SCM_ASSERT_TYPE (scm_is_string (name), name, SCM_ARG1, __FUNCTION__, "string");
92
93   char const *nm = scm_i_string_chars (name);
94   char *p = (*dl_kpse_find_file) (nm, kpathsea_find_format (nm), true);
95   if (p)
96     return scm_makfrom0str (p);
97   return SCM_BOOL_F;
98 }
99
100 //   "Return the expanded version  @var{var}.")
101 SCM ly_kpathsea_expand_variable (SCM var)
102 {
103   SCM_ASSERT_TYPE (scm_is_string (var), var, SCM_ARG1, __FUNCTION__, "string");
104
105   char const *nm = scm_i_string_chars (var);
106   char *result = (*dl_kpse_var_expand) (nm);
107   SCM ret = scm_makfrom0str (result);
108   free (result);
109
110   return ret;
111 }
112
113 #ifndef DYNAMIC_OBJECT_EXTENSION
114 #define DYNAMIC_OBJECT_EXTENSION ".so"
115 #endif
116
117
118 static char const* LIBKPATHSEA = "libkpathsea" DYNAMIC_OBJECT_EXTENSION;
119
120 int
121 open_library ()
122 {
123 #if HAVE_LIBKPATHSEA_SO
124   struct
125   {
126     void **func_pointer;
127     char const *name; 
128   } symbols[] = {
129     {(void*)&dl_kpse_find_file, "kpse_find_file"},
130     {(void*)&dl_kpse_set_program_name, "kpse_set_program_name"},
131     {(void*)&dl_kpse_format_info, "kpse_format_info"},
132     {(void*)&dl_kpse_init_format, "kpse_init_format"},
133     {(void*)&dl_kpse_maketex_option, "kpse_maketex_option"},
134     {(void*)&dl_kpse_var_expand, "kpse_var_expand"},
135     {0,0}
136   };
137
138
139   dlerror ();
140   kpathsea_handle = dlopen (LIBKPATHSEA, RTLD_LAZY);
141   if (!kpathsea_handle)
142     {
143       /*
144         todo i18n.
145        */
146       fprintf (stderr, _ ("can't dlopen: %s: %s"), LIBKPATHSEA, dlerror ());
147       fprintf (stderr, _ ("install package: %s or %s"),
148                "libkpathsea3 (teTeX 2.x)",
149                "libkpathsea4 (teTeX 3.x)");
150
151       return 1;
152     }
153
154   for (int i = 0; symbols[i].func_pointer; i++)
155     {
156       dlerror ();
157       *symbols[i].func_pointer = dlsym (kpathsea_handle, symbols[i].name);
158       if (!symbols[i].func_pointer)
159         {
160           fprintf (stderr, _ ("no such symbol: %s: %s"),
161                    symbols[i].name,
162                    dlerror ());
163           return 1;
164         }
165     }
166   return 0;
167 #else
168   dl_kpse_find_file = &kpse_find_file;
169   dl_kpse_set_program_name = &kpse_set_program_name;
170   dl_kpse_format_info = &kpse_format_info;
171   dl_kpse_init_format = &kpse_init_format;
172   dl_kpse_maketex_option = &kpse_maketex_option;
173   dl_kpse_var_expand = &kpse_var_expand;
174   return 0;
175 #endif
176 }
177
178 void
179 initialize_kpathsea ()
180 {
181   if (open_library ())
182     {
183       fprintf (stderr, _ ("error opening kpathsea library"));
184       fprintf (stderr, _ ("aborting"));
185       exit (1);
186     }
187
188   (*dl_kpse_set_program_name) ("lilypond", "lilypond");
189   (*dl_kpse_maketex_option) ("tfm", TRUE);
190   
191   SCM find = scm_c_define_gsubr ("ly:kpathsea-find-file", 1, 0, 0,
192                                  ly_kpathsea_find_file);
193   scm_c_export ("ly:kpathsea-find-file", NULL);
194   SCM expand = scm_c_define_gsubr ("ly:kpathsea-expand-variable", 1, 0, 0,
195                                    ly_kpathsea_expand_variable);
196   scm_c_export ("ly:kpathsea-expand-variable", NULL);
197 }
198
199 #endif