]> git.donarmstrong.com Git - lilypond.git/blob - kpath-guile/kpath.c
(open_library): dlopen libkpathsea.so
[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 #include "guile-compatibility.hh"
14
15 #include <dlfcn.h>
16 #include <stdio.h>
17 #include <string.h>
18
19 /*
20
21 The problem, as far as I can tell, is that MacOS X has its getopt
22 prototype in <unistd.h>, while I think other operating systems have it
23 in other places. <unistd.h> is included by kpathsea.h, so you end up
24 renaming both conflicting prototypes to YAKLUDGE.
25
26 I found a somewhat more elegant patch for this: Just #include
27 <unistd.h> before defining YAKLUDGE.
28
29 */
30
31 #include <unistd.h>     
32
33 #define popen REALLYUGLYKLUDGE
34 #define pclose ANOTHERREALLYUGLYKLUDGE
35 #define getopt YAKLUDGE
36
37 #if HAVE_KPATHSEA_KPATHSEA_H
38 #include <kpathsea/kpathsea.h>
39 #include <kpathsea/tex-file.h>
40 #endif
41
42
43 #if KPATHSEA
44
45
46 #if HAVE_KPATHSEA_KPATHSEA_H
47 static  void *kpathsea_handle = 0;
48 static  char *(*dl_kpse_find_file) (char const*, kpse_file_format_type, boolean) = 0;
49 static  void (*dl_kpse_maketex_option) (char const*, boolean) = 0;
50 static  void (*dl_kpse_set_program_name) (char const*) = 0;
51 static  char const *(*dl_kpse_init_format) (kpse_file_format_type) = 0;
52 static  char *(*dl_kpse_var_expand) (char const*) = 0;
53 static  kpse_format_info_type (*dl_kpse_format_info)[kpse_last_format] = 0;
54
55 kpse_file_format_type
56 kpathsea_find_format (const char* name)
57 {
58   int i;
59   int len = strlen (name);
60   for (i = 0; i < kpse_last_format; i++)
61     {
62        if (!(*dl_kpse_format_info)[i].type)
63         (*dl_kpse_init_format) ((kpse_file_format_type) i);
64
65        char const **suffixes[] = { (*dl_kpse_format_info)[i].suffix,
66                                    (*dl_kpse_format_info)[i].alt_suffix };
67        for (int j = 0; j < 2; j++)
68         for (char const **p = suffixes[j]; p && *p; p++)
69           {
70             int suflen = strlen (*p);
71             
72             if (!strncmp (name + len - suflen, *p, suflen))
73               return (kpse_file_format_type) i;
74           }
75     }
76   return kpse_last_format;
77 }
78 #endif
79
80 //         "Return the absolute file name of @var{name}, "
81 //         "or @code{#f} if not found.")
82 SCM
83 ly_kpathsea_find_file(SCM name)
84 {
85   SCM_ASSERT_TYPE (scm_is_string (name), name, SCM_ARG1, __FUNCTION__, "string");
86
87   char const * nm = scm_i_string_chars (name);
88   char *p = (*dl_kpse_find_file) (nm, kpathsea_find_format (nm),
89                                   true);
90   if (p)
91     return scm_makfrom0str (p);
92   return SCM_BOOL_F;
93 }
94
95 //   "Return the expanded version  @var{var}.")
96 SCM ly_kpathsea_expand_variable(SCM var)
97 {
98   SCM_ASSERT_TYPE (scm_is_string (var), var, SCM_ARG1, __FUNCTION__, "string");
99
100   char const * nm = scm_i_string_chars (var);
101   char *result =  kpse_var_expand (nm);
102   SCM ret =  scm_makfrom0str (result);
103   free (result);
104
105   return ret;
106 }
107
108
109 static char const* LIBKPATHSEA = "libkpathsea.so";
110
111 int
112 open_library ()
113 {
114 #if KPATHSEA && HAVE_KPATHSEA_KPATHSEA_H
115   struct
116   {
117     void **func_pointer;
118     char const *name; 
119   } symbols[] = {
120     {(void*)&dl_kpse_find_file, "kpse_find_file"},
121     {(void*)&dl_kpse_set_program_name, "kpse_set_program_name"},
122     {(void*)&dl_kpse_format_info, "kpse_format_info"},
123     {(void*)&dl_kpse_init_format, "kpse_init_format"},
124     {(void*)&dl_kpse_maketex_option, "kpse_maketex_option"},
125     {(void*)&dl_kpse_var_expand, "kpse_var_expand"},
126     {0,0}
127   };
128
129
130   dlerror ();
131   kpathsea_handle = dlopen (LIBKPATHSEA, RTLD_LAZY);
132   if (!kpathsea_handle)
133     {
134       /*
135         todo i18n.
136        */
137       fprintf (stderr, "can't dlopen: %s: %s", LIBKPATHSEA, dlerror ());
138       fprintf (stderr,"install package: %s or %s",
139                "libkpathsea3 (teTeX 2.x)",
140                "libkpathsea4 (teTeX 3.x)");
141
142       return 1;
143     }
144
145   for (int i = 0; symbols[i].func_pointer; i++)
146     {
147       dlerror ();
148       *symbols[i].func_pointer = dlsym (kpathsea_handle, symbols[i].name);
149       if (!symbols[i].func_pointer)
150         {
151           fprintf(stderr, "no such symbol: %s: %s",
152                   symbols[i].name,
153                   dlerror ());
154           return 1;
155         }
156     }
157
158   return 0;
159 #endif
160 }
161
162 void
163 initialize_kpathsea ()
164 {
165   if (open_library ())
166     {
167       fprintf (stderr, "Error opening kpathsea library. Aborting");
168       exit (1);
169     }
170
171   (*dl_kpse_set_program_name) ("lilypond");
172   (*dl_kpse_maketex_option) ("tfm", TRUE);
173   
174   SCM find = scm_c_define_gsubr ("ly:kpathsea-find-file", 1, 0, 0, ly_kpathsea_find_file);
175   scm_c_export ("ly:kpathsea-find-file", NULL);
176   SCM expand = scm_c_define_gsubr ("ly:kpathsea-expand-variable", 1, 0, 0, ly_kpathsea_find_file);
177   scm_c_export ("ly:kpathsea-expand-variable", NULL);
178 }
179
180 #endif