]> git.donarmstrong.com Git - lilypond.git/blob - scm/lily.scm
b420e3152cd989cc284b1aa5be304448546bda82
[lilypond.git] / scm / lily.scm
1 ;;;; lily.scm -- toplevel Scheme stuff
2 ;;;;
3 ;;;;  source file of the GNU LilyPond music typesetter
4 ;;;; 
5 ;;;; (c) 1998--2005 Jan Nieuwenhuizen <janneke@gnu.org>
6 ;;;; Han-Wen Nienhuys <hanwen@cs.uu.nl>
7
8
9 (if (defined? 'set-debug-cell-accesses!)
10     (set-debug-cell-accesses! #f))
11
12 ;(set-debug-cell-accesses! 1000)
13
14 (use-modules (ice-9 regex)
15              (ice-9 safe)
16              (ice-9 optargs)
17              (oop goops)
18              (srfi srfi-1)  ; lists
19              (srfi srfi-13)) ; strings
20
21
22 ;; my display
23 (define-public (myd k v) (display k) (display ": ") (display v) (display ", "))
24
25 (define-public (print . args)
26   (apply format (cons (current-output-port) args)))
27
28
29 ;;; General settings
30 ;;; debugging evaluator is slower.  This should
31 ;;; have a more sensible default.
32
33 (if (ly:get-option 'verbose)
34     (begin
35       (debug-enable 'debug)
36       (debug-enable 'backtrace)
37       (read-enable 'positions)))
38
39 ;; initialize defaults. 
40 (ly:set-option 'command-line-settings
41                '((resolution . 90)
42                  (preview-include-book-title . #t)
43                  ))
44
45 (define-public tex-backend?
46   (member (ly:output-backend) '("texstr" "tex")))
47
48 (define-public parser #f)
49
50 (define-public (lilypond-version)
51   (string-join
52    (map (lambda (x) (if (symbol? x)
53                         (symbol->string x)
54                         (number->string x)))
55         (ly:version))
56    "."))
57
58
59
60 ;; cpp hack to get useful error message
61 (define ifdef "First run this through cpp.")
62 (define ifndef "First run this through cpp.")
63
64 ;; gettext wrapper for guile < 1.7.2
65 (if (defined? 'gettext)
66     (define-public _ gettext)
67     (define-public _ ly:gettext))
68
69 (define-public (ly:load x)
70   (let* ((file-name (%search-load-path x)))
71     (if (ly:get-option 'verbose)
72         (ly:progress "[~A" file-name))
73     (primitive-load file-name)
74     (if (ly:get-option 'verbose)
75         (ly:progress "]"))))
76
77 (define-public TEX_STRING_HASHLIMIT 10000000)
78
79 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
80
81 (define (type-check-list location signature arguments)
82   "Typecheck a list of arguments against a list of type
83 predicates. Print a message at LOCATION if any predicate failed."
84   (define (recursion-helper signature arguments count) 
85     (define (helper pred? arg count) 
86       (if (not (pred? arg))
87
88           (begin
89             (ly:input-message
90              location
91              (format
92               #f (_ "wrong type for argument ~a.  Expecting ~a, found ~s")
93               count (type-name pred?) arg))
94             #f)
95           #t))
96
97     (if (null? signature)
98         #t
99         (and (helper (car signature) (car arguments) count)
100              (recursion-helper (cdr signature) (cdr arguments) (1+ count)))))
101   (recursion-helper signature arguments 1))
102
103 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
104 ;;  output
105
106
107 ;;(define-public (output-framework) (write "hello\n"))
108
109 (define output-tex-module
110   (make-module 1021 (list (resolve-interface '(scm output-tex)))))
111 (define output-ps-module
112   (make-module 1021 (list (resolve-interface '(scm output-ps)))))
113
114 (define-public (ps-output-expression expr port)
115   (display (eval expr output-ps-module) port))
116
117 ;; TODO: generate this list by registering the stencil expressions
118 ;;       stencil expressions should have docstrings.
119 (define-public (ly:all-stencil-expressions)
120   "Return list of stencil expressions."
121   '(beam
122     bezier-sandwich
123     blank
124     bracket
125     char
126     circle
127     dashed-line
128     dashed-slur
129     dot
130     draw-line
131     ez-ball
132     filledbox
133     glyph-string
134     horizontal-line
135     named-glyph
136     polygon
137     repeat-slash
138     round-filled-box
139     text
140     url-link
141     utf8-string
142     white-dot
143     white-text
144     embedded-ps
145     zigzag-line))
146
147 ;; TODO:
148 ;;  - generate this list by registering the output-backend-commands
149 ;;    output-backend-commands should have docstrings.
150 ;;  - remove hard copies in output-ps output-tex
151 (define-public (ly:all-output-backend-commands)
152   "Return list of output backend commands."
153   '(
154     comment
155     grob-cause
156     no-origin
157     placebox
158     unknown))
159
160 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
161 ;; Safe definitions utility
162 (define safe-objects (list))
163
164 (define-macro (define-safe-public arglist . body)
165   "Define a variable, export it, and mark it as safe, ie usable in LilyPond safe mode.
166 The syntax is the same as `define*-public'."
167   (define (get-symbol arg)
168     (if (pair? arg)
169         (get-symbol (car arg))
170         arg))
171   (let ((safe-symbol (get-symbol arglist)))
172     `(begin
173        (define*-public ,arglist
174          ,@body)
175        (set! safe-objects (cons (cons ',safe-symbol ,safe-symbol)
176                                 safe-objects))
177        ,safe-symbol)))
178
179
180 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
181 ;; other files.
182
183 (for-each ly:load
184           ;; load-from-path
185           '("lily-library.scm"
186             "file-cache.scm"
187             "define-music-types.scm"
188             "output-lib.scm"
189             "c++.scm"
190             "chord-ignatzek-names.scm"
191             "chord-entry.scm"
192             "chord-generic-names.scm"
193             "stencil.scm"
194             "markup.scm"
195             "bass-figure.scm"
196             "music-functions.scm"
197             "part-combiner.scm"
198             "define-music-properties.scm"
199             "auto-beam.scm"
200             "chord-name.scm"
201
202             "ly-from-scheme.scm"
203             
204             "define-context-properties.scm"
205             "translation-functions.scm"
206             "script.scm"
207             "midi.scm"
208             "beam.scm"
209             "clef.scm"
210             "slur.scm"
211             "font.scm"
212             "encoding.scm"
213             
214             "fret-diagrams.scm"
215             "define-markup-commands.scm"
216             "define-grob-properties.scm"
217             "define-grobs.scm"
218             "define-grob-interfaces.scm"
219             "page-layout.scm"
220             "titling.scm"
221             
222             "paper.scm"
223             "backend-library.scm"
224             "x11-color.scm"
225
226             ;; must be after everything has been defined
227             "safe-lily.scm"))
228
229
230 (set! type-p-name-alist
231       `(
232         (,boolean-or-symbol? . "boolean or symbol")
233         (,boolean? . "boolean")
234         (,char? . "char")
235         (,grob-list? . "list of grobs")
236         (,hash-table? . "hash table")
237         (,input-port? . "input port")
238         (,integer? . "integer")
239         (,list? . "list")
240         (,ly:context? . "context")
241         (,ly:dimension? . "dimension, in staff space")
242         (,ly:dir? . "direction")
243         (,ly:duration? . "duration")
244         (,ly:grob? . "layout object")
245         (,ly:input-location? . "input location")
246         (,ly:moment? . "moment")
247         (,ly:music? . "music")
248         (,ly:pitch? . "pitch")
249         (,ly:translator? . "translator")
250         (,ly:font-metric? . "font metric")
251         (,markup-list? . "list of markups")
252         (,markup? . "markup")
253         (,ly:music-list? . "list of music")
254         (,number-or-grob? . "number or grob")
255         (,number-or-string? . "number or string")
256         (,number-pair? . "pair of numbers")
257         (,number? . "number")
258         (,output-port? . "output port")   
259         (,pair? . "pair")
260         (,procedure? . "procedure") 
261         (,scheme? . "any type")
262         (,string? . "string")
263         (,symbol? . "symbol")
264         (,vector? . "vector")))
265
266
267 ;; debug mem leaks
268
269 (define gc-protect-stat-count 0)
270 (define-public (dump-gc-protects)
271   (set! gc-protect-stat-count (1+ gc-protect-stat-count))
272   (let* ((protects (sort
273                     (hash-table->alist (ly:protects))
274                     (lambda (a b)
275                       (< (object-address (car a))
276                          (object-address (car b))))))
277          (out-file-name (string-append
278                          "gcstat-" (number->string gc-protect-stat-count)
279                          ".scm"))
280          (outfile    (open-file  out-file-name  "w")))
281
282     (display "Dumping gc protected objs to ...\n")
283     (display
284      (filter
285       (lambda (x) (not (symbol? x))) 
286       (map (lambda (y)
287              (let ((x (car y))
288                    (c (cdr y)))
289
290                (string-append
291                 (string-join
292                  (map object->string (list (object-address x) c x))
293                  " ")
294                 "\n")))
295            protects))
296      outfile)))
297
298
299 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
300
301 (define (no-files-handler)
302   (ly:usage)
303   (exit 2))
304
305 (define-public (lilypond-main files)
306   "Entry point for LilyPond."
307
308   (if (null? files)
309       (no-files-handler))
310
311   (let* ((failed '())
312          (handler (lambda (key failed-file)
313              (set! failed (append (list failed-file) failed)))))
314          ;;(handler (lambda (key . arg) (set! failed (append arg failed)))))
315     (for-each
316      (lambda (f)
317        (catch 'ly-file-failed
318               (lambda () (ly:parse-file f))
319               (lambda (x . args) (handler x f)))
320               ;;(lambda (x) (handler x f)))
321        (if #f
322            (dump-gc-protects)))
323      files)
324     
325     (if (pair? failed)
326         (begin
327           (ly:error (_ "failed files: ~S") (string-join failed))
328           (exit 1))
329         (begin
330           ;; HACK: be sure to exit with single newline
331           (ly:message "")
332           (exit 0)))))
333
334 (define-public (tweak-grob-property grob sym val)
335   (set! (ly:grob-property grob sym) val))