]> git.donarmstrong.com Git - lilypond.git/blob - lily/lily-guile.cc
036bd19039bfe4614ba41f1a2f6291c56d9802f8
[lilypond.git] / lily / lily-guile.cc
1 /*
2   lily-guile.cc -- implement assorted guile functions
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1998--2000 Jan Nieuwenhuizen <janneke@gnu.org>
7
8   Han-Wen Nienhuys <hanwen@cs.uu.nl>
9 */
10
11
12 #include <stdio.h>
13 #include <stdlib.h>
14
15 #include "libc-extension.hh"
16 #include "lily-guile.hh"
17 #include "main.hh"
18 #include "simple-file-storage.hh"
19 #include "file-path.hh"
20 #include "debug.hh"
21 #include "direction.hh"
22 #include "offset.hh"
23
24 SCM
25 ly_str02scm (char const*c)
26 {
27   // this all really sucks, guile should take char const* arguments!
28   return gh_str02scm ((char*)c);
29 }
30
31 SCM
32 ly_eval_str (String s)
33 {
34   // this all really sucks, guile should take char const* arguments!
35   return gh_eval_str ((char*)s.ch_C ());
36 }
37
38   
39 /*
40   Pass string to scm parser, evaluate one expression.
41   Return result value and #chars read.
42
43   Thanks to Gary Houston <ghouston@freewire.co.uk>
44
45   Need guile-1.3.4 (>1.3 anyway) for ftell on str ports -- jcn
46 */
47 SCM
48 ly_parse_scm (char const* s, int* n)
49 {
50   SCM str = gh_str02scm ((char*)s);
51   SCM port = scm_mkstrport (SCM_INUM0, str, SCM_OPN | SCM_RDNG,
52                             "scm_eval_0str");
53   SCM from = scm_ftell (port);
54
55   SCM form;
56   SCM answer = SCM_UNSPECIFIED;
57
58   /* Read expression from port */
59   if (!SCM_EOF_OBJECT_P (form = scm_read (port)))
60     answer = scm_eval_x (form);
61
62   /*
63    After parsing
64
65        (begin (foo 1 2))
66
67    all seems fine, but after parsing
68
69        (foo 1 2)
70
71    read_buf has been advanced to read_pos - 1,
72    so that scm_ftell returns 1, instead of #parsed chars
73    */
74   
75   /*
76     urg: reset read_buf for scm_ftell
77     shouldn't scm_read () do this for us?
78   */
79   scm_fill_input (port);
80   SCM to = scm_ftell (port);
81   *n = gh_scm2int (to) - gh_scm2int (from);
82
83   /* Don't close the port here; if we re-enter this function via a
84      continuation, then the next time we enter it, we'll get an error.
85      It's a string port anyway, so there's no advantage to closing it
86      early.
87
88      scm_close_port (port);
89   */
90
91   return answer;
92 }
93
94 /*
95   scm_m_quote doesn't use any env, but needs one for a good signature in GUILE.
96 */
97 SCM
98 ly_quote_scm (SCM s)
99 {
100   return gh_list (ly_symbol2scm ("quote"), s, SCM_UNDEFINED);
101 }
102
103
104 SCM
105 ly_symbol2scm(const char *s)
106 {
107   return gh_symbol2scm ((char *)s);
108 }
109
110 String
111 ly_symbol2string (SCM s)
112 {
113   assert (gh_symbol_p (s));
114   return String((Byte*)SCM_CHARS (s), (int) SCM_LENGTH(s));
115 }
116
117
118 /**
119    Read a file, and shove it down GUILE.  GUILE also has file read
120    functions, but you can't fiddle with the path of those.
121  */
122 void
123 read_lily_scm_file (String fn)
124 {
125   String s = global_path.find (fn);
126   if (s == "")
127     {
128       String e = _f ("Can't find file: `%s'", fn);
129       e += " ";
130       e += _f ("(load path: `%s')", global_path.str ());
131       error (e);
132     }
133   else
134     progress_indication ("[" + s);
135
136
137   Simple_file_storage f(s);
138   
139   ly_eval_str ((char *) f.ch_C());
140   progress_indication ("]");
141 }
142
143
144 SCM
145 ly_gulp_file (SCM name)
146 {
147   String fn (ly_scm2string (name));
148  String s = global_path.find (fn);
149   if (s == "")
150     {
151       String e = _f ("Can't find file: `%s'", fn);
152       e += " ";
153       e += _f ("(load path: `%s')", global_path.str ());
154       error (e);
155     }
156   else
157     progress_indication ("[" + s );
158
159
160   Simple_file_storage f(s);
161   SCM result = ly_str02scm (f.ch_C());
162   progress_indication ("]");
163   return result;
164 }
165
166 void
167 ly_display_scm (SCM s)
168 {
169   gh_display (s);
170   gh_newline ();
171 }
172
173 String
174 ly_scm2string (SCM s)
175 {
176   assert (gh_string_p (s));
177   int len; 
178   char * p = gh_scm2newstr (s , &len);
179   
180   String r (p);
181
182   free (p);
183   return r;
184 }
185
186 SCM
187 index_cell (SCM s, Direction d)
188 {
189   assert (d);
190   return (d == LEFT) ? gh_car  (s) : gh_cdr (s);
191 }
192
193 SCM
194 index_set_cell (SCM s, Direction d, SCM v)
195 {
196   if (d == LEFT)
197     gh_set_car_x (s, v);
198   else if (d == RIGHT)
199     gh_set_cdr_x (s, v);
200   return s;
201 }
202   
203 SCM
204 ly_warning (SCM str)
205 {
206   assert (gh_string_p (str));
207   warning ("lily-guile: " + ly_scm2string (str));
208   return SCM_BOOL_T;
209 }
210
211 SCM
212 ly_isdir_p (SCM s)
213 {
214   if (gh_number_p (s))
215     {
216       int i = gh_scm2int (s);
217       return (i>= -1 && i <= 1)  ? SCM_BOOL_T : SCM_BOOL_F; 
218     }
219   return SCM_BOOL_F;
220 }
221
222
223 static void
224 init_functions ()
225 {
226   scm_make_gsubr ("ly-warn", 1, 0, 0, (SCM(*)(...))ly_warning);
227   scm_make_gsubr ("ly-gulp-file", 1,0, 0, (SCM(*)(...))ly_gulp_file);
228   scm_make_gsubr ("dir?", 1,0, 0, (SCM(*)(...))ly_isdir_p);  
229 }
230
231 ADD_SCM_INIT_FUNC(funcs, init_functions);
232
233
234 typedef void (*Void_fptr)();
235 Array<Void_fptr> *scm_init_funcs_;
236
237 void add_scm_init_func (void (*f)())
238 {
239   if (!scm_init_funcs_)
240     scm_init_funcs_ = new Array<Void_fptr>;
241
242   scm_init_funcs_->push (f);
243 }
244
245 void
246 init_lily_guile ()
247 {
248   for (int i=scm_init_funcs_->size() ; i--;)
249     (scm_init_funcs_->elem (i)) ();
250 }
251
252 unsigned int ly_scm_hash (SCM s)
253 {
254   return scm_ihashv (s, ~1u);
255 }
256
257
258
259 bool
260 isdir_b (SCM s)
261 {
262   if (gh_number_p (s))
263     {
264       int i = gh_scm2int (s);
265       return i>= -1 && i <= 1; 
266     }
267   return false;
268 }
269
270 Direction
271 to_dir (SCM s)
272 {
273   return (Direction) gh_scm2int (s);
274 }
275
276
277 SCM
278 to_scm (int i)
279 {
280   return gh_int2scm (i);
281 }
282
283 /*
284   UGR. junkme.
285  */
286 int
287 scm_to (SCM s, int* )
288 {
289   return gh_number_p (s) ? gh_scm2int (s) : 0;
290 }
291
292 SCM
293 to_scm (Real r)
294 {
295   return gh_double2scm (r);
296 }
297
298 Real
299 scm_to (SCM s, Real* )
300 {
301   return gh_number_p (s) ? gh_scm2double (s) : 0;
302 }
303
304 bool
305 to_boolean (SCM s)
306 {
307   return gh_boolean_p (s) && gh_scm2bool (s);
308 }
309
310 /*
311   Appendable list L: the cdr contains the list, the car the last cons
312   in the list.
313  */
314 SCM
315 appendable_list ()
316 {
317   SCM s = gh_cons (SCM_EOL, SCM_EOL);
318   gh_set_car_x (s, s);
319   
320   return s;
321 }
322
323 void
324 appendable_list_append (SCM l, SCM elt)
325 {
326   SCM newcons = gh_cons (elt, SCM_EOL);
327   
328   gh_set_cdr_x (gh_car (l), newcons);      
329   gh_set_car_x (l, newcons);
330 }
331
332
333 SCM
334 ly_offset2scm (Offset o)
335 {
336   return gh_cons (gh_double2scm (o[X_AXIS]), gh_double2scm(o[Y_AXIS]));
337 }