]> git.donarmstrong.com Git - lilypond.git/commitdiff
* scripts/lilypond-book.py (Compile_error.process_include): catch
authorHan-Wen Nienhuys <hanwen@xs4all.nl>
Fri, 24 Sep 2004 10:42:47 +0000 (10:42 +0000)
committerHan-Wen Nienhuys <hanwen@xs4all.nl>
Fri, 24 Sep 2004 10:42:47 +0000 (10:42 +0000)
Compile_error exception, and remove output .texi.

* scm/define-music-properties.scm (all-music-properties): add
error-found

* lily/parser.yy (Music_list): add error-found to music with errors.

* lily/lily-parser.cc (LY_DEFINE): ignore scores with errors.

* lily/book.cc (process): ignore books with errors

* lily/include/score.hh (class Score): add error_found_ member.

12 files changed:
ChangeLog
Documentation/topdocs/NEWS.texi
lily/book.cc
lily/include/score.hh
lily/lily-parser.cc
lily/parser.yy
lily/score.cc
ly/music-functions-init.ly
make/ly-rules.make
scm/define-music-properties.scm
scm/music-functions.scm
scripts/lilypond-book.py

index b6f84d3789c231cd7400f2ab0bcc4a0a4365ab91..7f6b37bda39b055dda4da504dd1455ef4de4c016 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2004-09-24  Han-Wen Nienhuys   <hanwen@xs4all.nl>
 
+       * scripts/lilypond-book.py (Compile_error.process_include): catch
+       Compile_error exception, and remove output .texi.
+
+       * scm/define-music-properties.scm (all-music-properties): add
+       error-found
+
+       * lily/parser.yy (Music_list): add error-found to music with errors.
+
+       * lily/lily-parser.cc (LY_DEFINE): ignore scores with errors.
+
+       * lily/book.cc (process): ignore books with errors
+
+       * lily/include/score.hh (class Score): add error_found_ member.
+
        * lily/drum-note-engraver.cc (try_music): idem.
 
        * lily/note-heads-engraver.cc: remove start-playing-event.
@@ -7,8 +21,8 @@
        * lily/part-combine-iterator.cc (Part_combine_iterator): use
        BusyPlayingEvent to determine which voice was active last.
        (unisono): use last active to where to get unisono information
-       from.
-
+       from. This fixes: partcombine-rest.ly (again).
+v/v
        * scm/part-combiner.scm (determine-split-list): cleanups
 
 2004-09-23  Han-Wen Nienhuys   <hanwen@xs4all.nl>
index fccb0325bf1605ff0fea5a95144ca120e87d9b34..71512df1fda727e55c808ba4d9c16c9a587a8d74 100644 (file)
@@ -8,6 +8,12 @@
 
 @itemize @bullet
 
+@item LilyPond does not try to produce output for files that
+have a parse error.
+
+@item @code{lilypond-book} will now remove any output  files that
+contain failed music snippets.
+
 @item The mode changing commands  (@code{\chords}, @code{\lyrics}, etc.)
 have been renamed to @code{\chordmode}, @code{\lyricmode}, etc. The
 command @code{\chords} is an abbreviation for
index 0eff1b511710ad0cdc2af80a39b9d7e0926c2f9d..af4ecae8fe3cbce636a81e24f99251be883571ff 100644 (file)
@@ -64,6 +64,13 @@ Book::print_smob (SCM, SCM p, scm_print_state*)
 Paper_book *
 Book::process (String outname, Output_def *default_def)
 {
+  bool error = false;
+  for (int i = 0; i < scores_.size(); i++)
+    error |= scores_[i]->error_found_;
+
+  if (error)
+    return 0;
+    
   Paper_book *paper_book = new Paper_book ();
   Real scale = scm_to_double (bookpaper_->c_variable ("outputscale"));
   
index 31a2e1483dee932b08cb7af0485aa63a130eb650..3705d16be5914b91084bb34c9ce22dcfe3a5a8b6 100644 (file)
@@ -24,7 +24,8 @@ class Score : public Input
 public:
   Link_array<Output_def> defs_;
   SCM header_;
-
+  bool error_found_;
+  
   SCM get_music () const;
   void set_music (SCM music, SCM parser);
   Score ();
index fc40c51e9687c437c3051a4a05c83a67d6998330..6f3c510906d9c8ef8ae15b243a68d9465697c060 100644 (file)
@@ -418,6 +418,9 @@ LY_DEFINE (ly_parser_print_score, "ly:parser-print-score",
   Lily_parser *parser = unsmob_my_lily_parser (parser_smob);
   Score *score = unsmob_score (score_smob);
 
+  if (score->error_found_)
+    return SCM_UNSPECIFIED;
+  
   SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "parser");
   SCM_ASSERT_TYPE (score, score_smob, SCM_ARG2, __FUNCTION__, "score");
 
@@ -490,12 +493,13 @@ LY_DEFINE (ly_parser_print_book, "ly:parser-print-book",
   Output_def *paper = get_paper (parser);
 
   Paper_book* pb = book->process (outname.to_string (), paper);
+  if (pb)
+    {
+      pb->output (outname.to_string ());
+      scm_gc_unprotect_object (pb->self_scm ());
+    }
 
-  pb->output (outname.to_string ());
-  
   scm_gc_unprotect_object (paper->self_scm ());
-  scm_gc_unprotect_object (pb->self_scm ());
-
   return SCM_UNSPECIFIED;
 }
 
index 0ab0b2f65c9110c3edae8e40158875e8062dd2f8..c8ce21774888a5a9efbd84eaac5750562f58d5c9 100644 (file)
@@ -660,7 +660,8 @@ book_body:
                $$->header_ = $2;
        }
        | book_body error {
-
+               $$->bookpaper_ = 0;
+               $$->scores_.clear();
        }
        ;
 
@@ -705,7 +706,7 @@ score_body:
                scm_gc_unprotect_object ($2->self_scm ());
        }
        | score_body error {
-
+               $$->error_found_ = true;
        }
        ;
 
@@ -804,8 +805,8 @@ The representation of a  list is the
 
   (LIST . LAST-CONS)
 
- to have  efficient append.
-*/
+ to have efficient append.  */
+
 Music_list:
        /* empty */ {
                $$ = scm_cons (SCM_EOL, SCM_EOL);
@@ -814,6 +815,7 @@ Music_list:
                SCM s = $$;
                SCM c = scm_cons ($2->self_scm (), SCM_EOL);
                scm_gc_unprotect_object ($2->self_scm ()); /* UGH */
+
                if (ly_c_pair_p (ly_cdr (s)))
                        scm_set_cdr_x (ly_cdr (s), c); /* append */
                else
@@ -821,12 +823,24 @@ Music_list:
                scm_set_cdr_x (s, c);  /* remember last cell */
        }
        | Music_list embedded_scm {
+
        }
        | Music_list error {
+               Music * m = MY_MAKE_MUSIC("Music");
+               // ugh. code dup 
+               m->set_property ("error-found", SCM_BOOL_T);
+               SCM s = $$;
+               SCM c = scm_cons (m->self_scm (), SCM_EOL);
+               scm_gc_unprotect_object (m->self_scm ()); /* UGH */
+
+               if (ly_c_pair_p (ly_cdr (s)))
+                       scm_set_cdr_x (ly_cdr (s), c); /* append */
+               else
+                       scm_set_car_x (s, c); /* set first cons */
+               scm_set_cdr_x (s, c);  /* remember last cell */
        }
        ;
 
-
 Music:
        Simple_music
        | Composite_music
index ecdddb64a8d87851039f0e32c235bc52f5ba0c2f..0e9564758c0dcb406cb5ce854156bb0a2eca8b3d 100644 (file)
@@ -31,6 +31,7 @@ Score::Score ()
 {
   header_ = SCM_EOL;
   music_ = SCM_EOL;
+  error_found_ = false;
   smobify_self ();
 }
 
@@ -221,6 +222,9 @@ Score::book_rendering (String outname,
                       Output_def *paperbook,
                       Output_def *default_def)
 {
+  if (error_found_)
+    return SCM_EOL;
+   
   SCM scaled_bookdef = SCM_EOL;
   Real scale = 1.0;
 
@@ -270,6 +274,11 @@ LY_DEFINE (ly_score_embedded_format, "ly:score-embedded-format",
   Score * sc = unsmob_score (score);
   Output_def *od = unsmob_output_def (paper);
 
+  if (sc->error_found_)
+    {
+      return SCM_EOL;
+    }
+  
   SCM_ASSERT_TYPE (sc, score, SCM_ARG1, __FUNCTION__, "Score");
   SCM_ASSERT_TYPE (od, paper, SCM_ARG2, __FUNCTION__, "Output_def");
 
@@ -312,8 +321,18 @@ Score::set_music (SCM music, SCM parser)
       unsmob_music (music)->origin ()->error (_("Already have music in score"));
       unsmob_music (music_)->origin ()->error (_("This is the previous music"));
     }
-       
+
+  if (Music * m = unsmob_music (music))
+    {
+      m->origin()->error (_("Error found in this music expression. Ignoring it"));
+      
+      this->error_found_ = this->error_found_ || to_boolean (m->get_property ("error-found"));
+      
+    }
+
   this->music_ = music;
+  if (this->error_found_)
+    this->music_ = SCM_EOL; 
 }
 
 SCM
index 0410976cbb522ec1d64af34914776a7c03ba7cb2..70755dff3b2dbc8408f63a47a743483706b751f4 100644 (file)
@@ -63,7 +63,7 @@ keepWithTag =
   (music-filter
    (lambda (m)
     (let* ((tags (ly:music-property m 'tags))
-           (res (memq tag tags)))
+          (res (memq tag tags)))
        (or
        (eq? tags '())
        (memq tag tags))))
index 0e899a77719fc1e72edad6e38e1724590684e6e2..0ab32491c1c750d57bec34a96e66a404cdfcde98 100644 (file)
@@ -2,31 +2,24 @@
 
 
 $(outdir)/%.latex: %.doc
-       if [ -f $@ ]; then chmod a+w $@; fi
        $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --verbose $(LILYPOND_BOOK_FLAGS) $<
-       chmod -w $@
 
 # don't do ``cd $(outdir)'', and assume that $(outdir)/.. is the src dir.
 # it is not, for --srcdir builds
 $(outdir)/%.texi: %.tely
-       if [ -f $@ ]; then chmod a+w $@; fi
        rm -f $$(grep -LF '\lilypondend' $(outdir)/lily-*.tex 2>/dev/null)
        $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) $<
-       chmod -w $@
 
 $(outdir)/%.texi: $(outdir)/%.tely
-       if [ -f $@ ]; then chmod a+w $@; fi
        rm -f $$(grep -LF '\lilypondend' $(outdir)/lily-*.tex 2>/dev/null)
        $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --process='$(LILYPOND) $(LILYPOND_BOOK_INCLUDES)' --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) $<
 #
 # DON'T REMOVE SOURCE FILES, otherwise the .TEXI ALWAYS OUT OF DATE.
 #      rm -f $<
-       chmod -w $@
 
 # nexi: n[o-lilypond t]exi
 # for plain info doco: don't run lilypond
 $(outdir)/%.nexi: %.tely
-       if [ -f $@ ]; then chmod a+w $@; fi
        rm -f $(outdir)/$*.texi
        $(PYTHON) $(LILYPOND_BOOK) $(LILYPOND_BOOK_INCLUDES) --output=$(outdir) --format=$(LILYPOND_BOOK_FORMAT) --verbose $(LILYPOND_BOOK_FLAGS) --process='true' $<
        mv $(outdir)/$*.texinfo $@ 2>/dev/null || mv $(outdir)/$*.texi $@
@@ -35,7 +28,6 @@ $(outdir)/%.nexi: %.tely
                (cd $(outdir) && \
                ls -1 lily-*.ly | sed 's/.ly$$/.txt/' | xargs touch) || true; \
        fi
-       chmod -w $@
 
 $(outdir)/%.info: $(outdir)/%.nexi
        $(MAKEINFO) -I $(outdir) --output=$(outdir)/$(*F).info $<
index 66977251db7fde7d0da8651e2faa587ef29ef25b..f4d852363f0406df1d6ff89cd1c150cd1edd4b67 100644 (file)
@@ -56,6 +56,7 @@ e.g. @code{\\tag #'part ...} could tag a piece of music as only being active in
      (text-type ,symbol? "Particular type of text script (e.g. finger, dynamic).")
      (tempo-unit ,ly:duration? "The unit for the metronome count.")
      (tonic ,ly:pitch? "Base of the scale")
+     (error-found ,boolean? "If true, a parsing error was found in this expression")
      (element ,ly:music? "The single child of a Music_wrapper music object, or the body of a repeat.")
      (elements ,ly:music-list? "A list of elements for sequential of simultaneous music, or the alternatives of repeated music. ")
      (force-accidental ,boolean? "If set, a cautionary accidental should always be printed on this note")
index 20b88d111c118d8a443bb8d15b6b6f9b7c388dda..3212e52159be43c33c41cda1b55401a3e10d9b43 100644 (file)
@@ -623,11 +623,26 @@ Syntax:
       (set-debug-cell-accesses! 15000))
   m)
 
+(define (music-check-error music)
+  (define found #f)
+  (define (signal m)
+    (if (and (ly:music? m)
+            (eq? (ly:music-property m 'error-found) #t))
+       (set! found #t)))
+  
+  (for-each signal (ly:music-property music 'elements))
+  (signal (ly:music-property music 'element))
+
+  (if found
+      (set! (ly:music-property music 'error-found) #t))
+  music)
+
 (define-public toplevel-music-functions
   (list
    ;; check-start-chords ; ; no longer needed with chord syntax. 
    (lambda (music parser) (voicify-music music))
    (lambda (x parser) (music-map glue-mm-rest-texts x))
+   (lambda (x parser) (music-map music-check-error x))
    (lambda (music parser)
 
      (music-map (quote-substitute (ly:parser-lookup parser 'musicQuotes))  music))
index fce5bb106d3755bfecc54ee7b3ffde2d58e32fd7..25b185abda07126010506cda480717bbe69b0c9c 100644 (file)
@@ -839,8 +839,14 @@ def process_snippets (cmd, ly_snippets, png_snippets):
        
        status = 0
        if ly_names:
-               status = ly.system (string.join ([cmd] + ly_names), progress_p = 1)
+               status = ly.system (string.join ([cmd] + ly_names),
+                                   ignore_error = 1, progress_p = 1)
 
+
+       if status:
+               ly.error( 'Process %s exited unsuccessfully.' % cmd )
+               raise Compile_error
+               
        if format == HTML or format == TEXINFO:
                for i in png_names:
                        if not os.path.exists (i + '.eps') and os.path.exists (i + '.tex'):
@@ -903,6 +909,27 @@ format2ext = {
        LATEX: '.tex',
        }
        
+class Compile_error:
+       pass
+
+def do_process_cmd (chunks):
+       ly_outdated = filter (lambda x: is_derived_class (x.__class__, Lilypond_snippet) \
+                          and x.ly_is_outdated (), chunks)
+       png_outdated = filter (lambda x: is_derived_class (x.__class__, Lilypond_snippet) \
+                          and x.png_is_outdated (), chunks)
+
+       ly.progress (_ ("Writing snippets..."))
+       map (Lilypond_snippet.write_ly, ly_outdated)
+       ly.progress ('\n')
+
+       if ly_outdated:
+               ly.progress (_ ("Processing..."))
+               process_snippets (process_cmd, ly_outdated, png_outdated)
+       else:
+               ly.progress (_ ("All snippets are up to date..."))
+       ly.progress ('\n')
+
+
 def do_file (input_filename):
        #ugh
        global format
@@ -914,7 +941,8 @@ def do_file (input_filename):
                else:
                        ly.error (_ ("cannot determine format for: %s" \
                                     % input_filename))
-
+                       ly.exit (1) 
+               
        if not input_filename or input_filename == '-':
                in_handle = sys.stdin
                input_fullname = '<stdin>'
@@ -954,82 +982,75 @@ def do_file (input_filename):
                    os.path.exists (output_filename) and 
                    os.path.samefile (output_filename, input_fullname)):
                        ly.error (_("Output would overwrite input file; use --output."))
-                       sys.exit (2)
+                       ly.exit (2)
 
                output_file = open (output_filename, 'w')
                if output_name:
                        os.chdir (output_name)
-
-       ly.progress (_ ("Reading %s...") % input_fullname)
-       source = in_handle.read ()
-       ly.progress ('\n')
-
-       # FIXME: containing blocks must be first, see find_toplevel_snippets
-       snippet_types = (
-               'multiline_comment',
-               'verbatim',
-               'lilypond_block',
-#              'verb',
-               'singleline_comment',
-               'lilypond_file',
-               'include',
-               'lilypond', )
-       ly.progress (_ ("Dissecting..."))
-       chunks = find_toplevel_snippets (source, snippet_types)
-       ly.progress ('\n')
-
-       global default_ly_options
-       textwidth = 0
-       if not default_ly_options.has_key (LINEWIDTH):
-               if format == LATEX:
-                       textwidth = get_latex_textwidth (source)
-                       default_ly_options[LINEWIDTH] = '''%.0f\\pt''' \
-                                                       % textwidth
-               elif format == TEXINFO:
-                       for (k, v) in texinfo_linewidths.items ():
-                               # FIXME: @paper is usually not in chunk #0:
-                               #        \input texinfo @c -*-texinfo-*-
-                               # bluntly search first K of source
-                               # s = chunks[0].replacement_text ()
-                               if re.search (k, source[:1024]):
-                                       default_ly_options[LINEWIDTH] = v
-                                       break
-
-       if filter_cmd:
-               output_file.writelines ([c.filter_text () for c in chunks])
-               
-               
-       elif process_cmd:
-               ly_outdated = filter (lambda x: is_derived_class (x.__class__, Lilypond_snippet) \
-                                  and x.ly_is_outdated (), chunks)
-               png_outdated = filter (lambda x: is_derived_class (x.__class__, Lilypond_snippet) \
-                                  and x.png_is_outdated (), chunks)
-               
-               ly.progress (_ ("Writing snippets..."))
-               map (Lilypond_snippet.write_ly, ly_outdated)
-               ly.progress ('\n')
-
-               if ly_outdated:
-                       ly.progress (_ ("Processing..."))
-                       process_snippets (process_cmd, ly_outdated, png_outdated)
-               else:
-                       ly.progress (_ ("All snippets are up to date..."))
+       try:
+               ly.progress (_ ("Reading %s...") % input_fullname)
+               source = in_handle.read ()
                ly.progress ('\n')
 
-               ly.progress (_ ("Compiling %s...") % output_filename)
-               output_file.writelines ([s.replacement_text () \
-                                        for s in chunks])
+               # FIXME: containing blocks must be first, see find_toplevel_snippets
+               snippet_types = (
+                       'multiline_comment',
+                       'verbatim',
+                       'lilypond_block',
+       #               'verb',
+                       'singleline_comment',
+                       'lilypond_file',
+                       'include',
+                       'lilypond', )
+               ly.progress (_ ("Dissecting..."))
+               chunks = find_toplevel_snippets (source, snippet_types)
                ly.progress ('\n')
 
-       def process_include (snippet):
+               global default_ly_options
+               textwidth = 0
+               if not default_ly_options.has_key (LINEWIDTH):
+                       if format == LATEX:
+                               textwidth = get_latex_textwidth (source)
+                               default_ly_options[LINEWIDTH] = '''%.0f\\pt''' \
+                                                               % textwidth
+                       elif format == TEXINFO:
+                               for (k, v) in texinfo_linewidths.items ():
+                                       # FIXME: @paper is usually not in chunk #0:
+                                       #        \input texinfo @c -*-texinfo-*-
+                                       # bluntly search first K of source
+                                       # s = chunks[0].replacement_text ()
+                                       if re.search (k, source[:1024]):
+                                               default_ly_options[LINEWIDTH] = v
+                                               break
+
+               if filter_cmd:
+                       output_file.writelines ([c.filter_text () for c in chunks])
+
+
+               elif process_cmd:
+                       do_process_cmd (chunks)
+                       ly.progress (_ ("Compiling %s...") % output_filename)
+                       output_file.writelines ([s.replacement_text () \
+                                                for s in chunks])
+                       ly.progress ('\n')
+
+               def process_include (snippet):
+                       os.chdir (original_dir)
+                       name = snippet.substring ('filename')
+                       ly.progress (_ ('Processing include: %s') % name)
+                       ly.progress ('\n')
+                       do_file (name)
+
+               map (process_include,
+                    filter (lambda x: is_derived_class (x.__class__, Include_snippet), chunks))
+       except Compile_error:
                os.chdir (original_dir)
-               name = snippet.substring ('filename')
-               ly.progress (_ ('Processing include: %s') % name)
+               ly.progress (_('Removing `%s\'') % output_filename)
                ly.progress ('\n')
-               do_file (name)
                
-       map (process_include,
-            filter (lambda x: is_derived_class (x.__class__, Include_snippet), chunks))
+               os.unlink (output_filename)
+               raise Compile_error
+       
 
 def do_options ():
        global format, output_name
@@ -1095,7 +1116,10 @@ def main ():
        ly.identify (sys.stderr)
        ly.setup_environment ()
        if files:
-               do_file (files[0])
-
+               try:
+                       do_file (files[0])
+               except Compile_error:
+                       ly.exit (1)
+                       
 if __name__ == '__main__':
        main ()