X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmy-lily-parser.cc;h=f5a54cc8853ca72426183ad6f97a0e0b4b50a027;hb=46ef5daa401f06c6beeb996a00854e1310501dc1;hp=5dbe0e69c2e6c4846181692df1d6296e64155a0b;hpb=dca1986050e88c5117fc88ff2855fb209c96a5b8;p=lilypond.git diff --git a/lily/my-lily-parser.cc b/lily/my-lily-parser.cc index 5dbe0e69c2..f5a54cc885 100644 --- a/lily/my-lily-parser.cc +++ b/lily/my-lily-parser.cc @@ -3,450 +3,477 @@ source file of the GNU LilyPond music typesetter - (c) 1997--1998 Han-Wen Nienhuys + (c) 1997--2004 Han-Wen Nienhuys Jan Nieuwenhuizen */ -#include "my-lily-parser.hh" -#include "my-lily-lexer.hh" -#include "debug.hh" +#include "book.hh" + +#include "file-name.hh" +#include "file-path.hh" +#include "lily-version.hh" +#include "ly-module.hh" #include "main.hh" -#include "music-list.hh" -#include "musical-request.hh" -#include "command-request.hh" +#include "my-lily-lexer.hh" +#include "my-lily-parser.hh" +#include "output-def.hh" +#include "paper-book.hh" #include "parser.hh" -#include "scope.hh" -#include "file-results.hh" -#include "midi-def.hh" -#include "paper-def.hh" -#include "identifier.hh" +#include "score.hh" +#include "source.hh" +#include "warn.hh" + +#include "ly-smobs.icc" + -My_lily_parser::My_lily_parser (Sources * source_l) +My_lily_parser::My_lily_parser (Sources *sources) { - first_b_ = true; - source_l_ = source_l; - lexer_p_ = 0; - abbrev_beam_type_i_ = 0; - default_duration_.durlog_i_ = 2; - default_abbrev_i_ = 0; - error_level_i_ = 0; - extender_req = 0; - fatal_error_i_ = 0; - default_header_p_ =0; + book_count_ = 0; + score_count_ = 0; + lexer_ = 0; + sources_ = sources; + default_duration_ = Duration (2,0); + error_level_ = 0; + last_beam_start_ = SCM_EOL; + + smobify_self (); } -My_lily_parser::~My_lily_parser() +My_lily_parser::My_lily_parser (My_lily_parser const &src) { - delete lexer_p_; - delete default_header_p_; + book_count_ = src.book_count_; + score_count_ = src.score_count_; + lexer_ = 0; + sources_ = src.sources_; + default_duration_ = src.default_duration_; + error_level_ = src.error_level_; + last_beam_start_ = src.last_beam_start_; + + smobify_self (); + lexer_ = new My_lily_lexer (*src.lexer_); } +My_lily_parser::~My_lily_parser () +{ + // FIXME: Memleak: del lexer +} +IMPLEMENT_SMOBS (My_lily_parser); +IMPLEMENT_TYPE_P (My_lily_parser, "ly:my-lily-parser?"); +IMPLEMENT_DEFAULT_EQUAL_P (My_lily_parser); -void -My_lily_parser::set_version_check (bool ig) +SCM +My_lily_parser::mark_smob (SCM s) +{ + My_lily_parser *parser = (My_lily_parser*) ly_cdr (s); + return SCM_EOL; +} + +int +My_lily_parser::print_smob (SCM s, SCM port, scm_print_state*) { - ignore_version_b_ = ig; + scm_puts ("#", port); + return 1; } + +/* Process one .ly file, or book. */ void -My_lily_parser::parse_file (String init, String s) +My_lily_parser::parse_file (String init, String name, String out_name) { - lexer_p_ = new My_lily_lexer; - init_str_ = init; - lexer_p_->main_input_str_ = s; + lexer_ = new My_lily_lexer (sources_); + output_basename_ = out_name; + + lexer_->main_input_name_ = name; - *mlog << _ ("Parsing..."); + progress_indication (_ ("Parsing...")); + progress_indication ("\n"); - init_parse_b_ = false; - set_yydebug (!monitor->silent_b ("Parser") && check_debug); - lexer_p_->new_input (init, source_l_); - do_yyparse (); + set_yydebug (0); + lexer_->new_input (init, sources_); - if (!define_spot_array_.empty()) + /* Read .ly IN_FILE, lex, parse, write \score blocks from IN_FILE to + OUT_FILE (unless IN_FILE redefines output file name). */ + do_yyparse (); + + if (!define_spots_.is_empty ()) { - warning (_ ("braces don't match")); - error_level_i_ = 1; + define_spots_.top ().warning (_ ("Braces don't match")); + error_level_ = 1; } - inclusion_global_array = lexer_p_->filename_str_arr_; + error_level_ = error_level_ | lexer_->error_level_; + delete lexer_; + lexer_ = 0; } void -My_lily_parser::remember_spot() +My_lily_parser::parse_string (String ly_code) { - define_spot_array_.push (here_input()); -} + My_lily_lexer *parent = lexer_; + lexer_ = (parent == 0 ? new My_lily_lexer (sources_) + : new My_lily_lexer (*parent)); -char const * -My_lily_parser::here_ch_C() const -{ - return lexer_p_->here_ch_C(); + lexer_->main_input_name_ = ""; + lexer_->main_input_b_ = true; + + set_yydebug (0); + lexer_->new_input (lexer_->main_input_name_, ly_code, sources_); + do_yyparse (); + + if (!define_spots_.is_empty ()) + { + define_spots_.top ().warning (_ ("Braces don't match")); + error_level_ = 1; + } + + error_level_ = error_level_ | lexer_->error_level_; + + if (parent != 0) + { + parent->keytable_ = lexer_->keytable_; + parent->encoding_ = lexer_->encoding_; + parent->chordmodifier_tab_ = lexer_->chordmodifier_tab_; + parent->pitchname_tab_stack_ = lexer_->pitchname_tab_stack_; + parent->sources_ = lexer_->sources_; + parent->scopes_ = lexer_->scopes_; + parent->error_level_ = lexer_->error_level_; + parent->main_input_b_ = lexer_->main_input_b_; + } } void -My_lily_parser::parser_error (String s) +My_lily_parser::push_spot () { - here_input().error (s); - if (fatal_error_i_) - exit (fatal_error_i_); - error_level_i_ = 1; - exit_status_i_ = 1; + define_spots_.push (here_input ()); } -void -My_lily_parser::set_abbrev_beam (int type_i) +char const * +My_lily_parser::here_str0 () const { - abbrev_beam_type_i_ = type_i; + return lexer_->here_str0 (); } - void -My_lily_parser::set_last_duration (Duration const *d) +My_lily_parser::parser_error (String s) { - default_duration_ = *d; + here_input ().error (s); + error_level_ = 1; } - -Simultaneous_music* -My_lily_parser::get_word_element (String s, Duration * duration_p) +Input +My_lily_parser::pop_spot () { - Simultaneous_music* velt_p = new Request_chord; - - Lyric_req* lreq_p = new Lyric_req; - lreq_p ->text_str_ = s; - lreq_p->duration_ = *duration_p; - lreq_p->set_spot (here_input()); - - velt_p->add_music (lreq_p); - - delete duration_p; - return velt_p; + return define_spots_.pop (); } - -Simultaneous_music * -My_lily_parser::get_rest_element (String s, Duration * duration_p) +Input +My_lily_parser::here_input () const { - Simultaneous_music* velt_p = new Request_chord; - velt_p->set_spot (here_input()); + /* + Parsing looks ahead , so we really want the previous location of the + lexer, not lexer_->here_input (). + */ + + /* + Actually, that gets very icky when there are white space, because + the line-numbers are all wrong. Let's try the character before + the current token. That gets the right result for note/duration + stuff, but doesn't mess up for errors in the 1st token of the + line. + */ + Input hi (lexer_->here_input ()); + + char const * bla = hi.defined_str0_; + if (hi.line_number () > 1 + || hi.column_number () > 1) + bla --; + + return Input (hi.source_file_, bla); +} - if (s=="s") - { /* Space */ - Skip_req * skip_p = new Skip_req; - skip_p->duration_ = *duration_p; - skip_p->set_spot (here_input()); - velt_p->add_music (skip_p); - } - else - { - Rest_req * rest_req_p = new Rest_req; - rest_req_p->duration_ = *duration_p; - rest_req_p->set_spot (here_input()); +/****************************************************************/ - velt_p->add_music (rest_req_p); - } - delete duration_p; - return velt_p; +/* + junkme? + */ +bool store_locations_global_b; + +/* Do not append `!' suffix, since 1st argument is not modified. */ +LY_DEFINE (ly_set_point_and_click, "ly:set-point-and-click", 1, 0, 0, + (SCM what), + "Set the options for Point-and-click source specials output. The\n" +"argument is a symbol. Possible options are @code{none} (no source specials),\n" +"@code{line} and @code{line-column}") +{ + /* UGH. */ + SCM val = SCM_BOOL_F; + if (ly_symbol2scm ("line-column") == what) + val = ly_scheme_function ("line-column-location"); + else if (what == ly_symbol2scm ("line")) + val = ly_scheme_function ("line-location"); + + scm_module_define (global_lily_module, ly_symbol2scm ("point-and-click"), + val); + store_locations_global_b = ly_c_procedure_p (val); + return SCM_UNSPECIFIED; } -Simultaneous_music * -My_lily_parser::get_chord (Musical_pitch tonic, Array* add_arr_p, Array* sub_arr_p, Musical_pitch* inversion_p, Duration d) +LY_DEFINE (ly_parse_file, "ly:parse-file", + 1, 0, 0, + (SCM name), + "Parse a single @code{.ly} file. " + "Upon failure, throw @code{ly-file-failed} key.") { - Simultaneous_music*v = new Request_chord; - v->set_spot (here_input ()); - - for (int i = 0; i < add_arr_p->size (); i++) - { - Musical_pitch p = tonic; - Musical_pitch q = (*add_arr_p)[i]; - // duh, c7 should mean - if (q.notename_i_ == 6) - q.accidental_i_--; - p.transpose (q); - (*add_arr_p)[i] = p; - } - add_arr_p->sort (Musical_pitch::compare); - for (int i = 0; i < sub_arr_p->size (); i++) - { - Musical_pitch p = tonic; - Musical_pitch q = (*add_arr_p)[i]; - // duh, c7 should mean - if (q.notename_i_ == 6) - q.accidental_i_--; - p.transpose (q); - (*sub_arr_p)[i] = p; - } - sub_arr_p->sort (Musical_pitch::compare); - - Musical_pitch third (2); - Musical_pitch mthird (2, -1); - Musical_pitch missing; - missing = tonic; - missing.transpose (third); - - Musical_pitch p; - p = tonic; - p.transpose (third); - p.transpose (mthird); - - /* - must have minimum at 5 (3 is added automatically as missing) - */ - if (!add_arr_p->size ()) - add_arr_p->push (p); - else if ((add_arr_p->top () < p) && (add_arr_p->top ().notename_i_ != p.notename_i_)) - add_arr_p->push (p); - add_arr_p->sort (Musical_pitch::compare); - - Array triads; - triads.push (third); // c e - triads.push (mthird); // d f - triads.push (mthird); // e g - triads.push (third); // f a - triads.push (third); // g b - triads.push (mthird); // a c - triads.push (mthird); // b d + SCM_ASSERT_TYPE (ly_c_string_p (name), name, SCM_ARG1, __FUNCTION__, "string"); + char const *file = SCM_STRING_CHARS (name); + char const *extensions[] = {"ly", "", 0}; + String file_name = global_path.find (file, extensions); + + /* By default, use base name of input file for output file name, + write output to cwd; do not use root and directory parts of input + file name. */ + File_name out_file_name (file_name); + out_file_name.ext_ = ""; + out_file_name.root_ = ""; + out_file_name.dir_ = ""; + + if (!output_name_global.is_empty ()) + out_file_name = File_name (output_name_global); + + String init; + if (!init_name_global.is_empty ()) + init = init_name_global; + else + init = "init.ly"; - /* - if first addition is 4, assume sus4 and don't add third implicitely - */ - Musical_pitch sus (3); - sus.transpose (tonic); - if (add_arr_p->size ()) - if ((*add_arr_p)[0] == sus) - missing.transpose (mthird); + String out_file = out_file_name.to_string (); - /* - add missing triads - */ - for (int i = 0; i < add_arr_p->size (); i++) + if (init.length () && global_path.find (init).is_empty ()) { - Musical_pitch p = (*add_arr_p)[i]; - if (p > missing) - while (p > missing) - { - if (p.notename_i_ != missing.notename_i_) - { - if ((missing.notename_i_ - tonic.notename_i_ + 7) % 7 == 6) - { - Musical_pitch special_seven = missing; - Musical_pitch lower (0, -1); - special_seven.transpose (lower); - add_arr_p->insert (special_seven, i++); - } - else - add_arr_p->insert (missing, i++); - } - missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]); - } - else if (p.notename_i_ == missing.notename_i_) - missing.transpose (triads[(missing.notename_i_ - tonic.notename_i_ + 7) % 7]); - else - i++; + warning (_f ("can't find init file: `%s'", init)); + warning (_f ("(search path: `%s')", + global_path.to_string ().to_str0 ())); + exit (2); } - /* - add tonic - */ - if (!add_arr_p->size () || ((*add_arr_p)[0] != tonic)) - add_arr_p->insert (tonic, 0); - - Array pitch_arr; - /* - add all that aren't subtracted - */ - for (int i = 0; i < add_arr_p->size (); i++) + if ((file_name != "-") && global_path.find (file_name).is_empty ()) { - Musical_pitch p = (*add_arr_p)[i]; - int j = 0; - for (; j < sub_arr_p->size (); j++) - if (p == (*sub_arr_p)[j]) - break; - if (j == sub_arr_p->size ()) - pitch_arr.push (p); + warning (_f ("can't find file: `%s'", file_name)); + scm_throw (ly_symbol2scm ("ly-file-failed"), + scm_list_1 (scm_makfrom0str (file_name.to_str0 ()))); } - - if (inversion_p) + else { - int i = 0; - for (; i < pitch_arr.size (); i++) - if ((pitch_arr[i].notename_i_ == inversion_p->notename_i_) - && (pitch_arr[i].accidental_i_ == inversion_p->accidental_i_)) - break; - if (i == pitch_arr.size ()) - warning (_ ("invalid inversion pitch (not part of chord)")); - else - { - Array pitches; - Musical_pitch last (0, 0, -5); - for (int j = 0; j < pitch_arr.size (); j++) - { - Musical_pitch p = pitch_arr[(j + i) % pitch_arr.size ()]; - if (p < last) - { - p.octave_i_ = last.octave_i_; - if (p < last) - p.octave_i_++; - } - pitches.push (p); - last = p; - } - pitch_arr = pitches; - } - delete inversion_p; + Sources sources; + sources.set_path (&global_path); + + progress_indication (_f ("Now processing `%s'", file_name.to_str0 ())); + progress_indication ("\n"); + + My_lily_parser *parser = new My_lily_parser (&sources); + scm_module_define (global_lily_module, ly_symbol2scm ("parser"), + parser->self_scm ()); + parser->parse_file (init, file_name, out_file); + + bool error = parser->error_level_; + parser = 0; + if (error) + /* TODO: pass renamed input file too. */ + scm_throw (ly_symbol2scm ("ly-file-failed"), + scm_list_1 (scm_makfrom0str (file_name.to_str0 ()))); } + return SCM_UNSPECIFIED; +} - for (int i = 0; i < pitch_arr.size (); i++) - { - Musical_pitch p = pitch_arr[i]; - Note_req* n = new Note_req; - n->pitch_ = p; - n->duration_ = d; - v->add_music (n); - } +LY_DEFINE (ly_parse_string, "ly:parse-string", + 1, 0, 0, + (SCM ly_code), + "Parse the string LY_CODE. " + "Upon failure, throw @code{ly-file-failed} key.") +{ + SCM_ASSERT_TYPE (ly_c_string_p (ly_code), ly_code, SCM_ARG1, __FUNCTION__, "string"); + + Sources sources; + sources.set_path (&global_path); + My_lily_parser *parser = new My_lily_parser (&sources); + scm_module_define (global_lily_module, ly_symbol2scm ("parser"), + parser->self_scm ()); + parser->parse_string (ly_scm2string (ly_code)); + parser = 0; + + return SCM_UNSPECIFIED; +} - v->set_spot (here_input ()); - return v; +LY_DEFINE (ly_clone_parser, "ly:clone-parser", + 1, 0, 0, + (SCM parser_smob), + "Return a clone of PARSER_SMOB.") +{ + My_lily_parser *parser = unsmob_my_lily_parser (parser_smob); + My_lily_parser *clone = new My_lily_parser (*parser); + return scm_gc_unprotect_object (clone->self_scm ()); } -Simultaneous_music * -My_lily_parser::get_note_element (Note_req *rq, Duration * duration_p) +LY_DEFINE(ly_parser_define, "ly:parser-define", + 3, 0, 0, + (SCM parser_smob, SCM symbol, SCM val), + "Bind SYMBOL to VAL in PARSER_SMOB's module.") { - Simultaneous_music*v = new Request_chord; - v->set_spot (here_input ()); + My_lily_parser *parser = unsmob_my_lily_parser (parser_smob); + SCM_ASSERT_TYPE (ly_c_symbol_p (symbol), symbol, SCM_ARG2, __FUNCTION__, "symbol"); + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG2, __FUNCTION__, "parser"); - v->add_music (rq); - rq->duration_ = *duration_p; - rq->set_spot (here_input ()); - delete duration_p ; - return v; + parser->lexer_->set_identifier (scm_symbol_to_string (symbol), val); + return SCM_UNSPECIFIED; } +LY_DEFINE(ly_parser_lookup, "ly:parser-lookup", + 2, 0, 0, + (SCM parser_smob, SCM symbol), + "Lookup @var{symbol} in @var{parser_smob}'s module. Undefined is '().") +{ + My_lily_parser *parser = unsmob_my_lily_parser (parser_smob); + SCM_ASSERT_TYPE (ly_c_symbol_p (symbol), symbol, SCM_ARG2, __FUNCTION__, "symbol"); + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG2, __FUNCTION__, "parser"); -/* - UGH. - */ -Array* -My_lily_parser::get_parens_request (int t) -{ - Array& reqs = *new Array; - switch (t) - { - case '~': - reqs.push (new Tie_req); - break; - - /* fall through */ - case '[': - case ']': - { - if (!abbrev_beam_type_i_) - { - reqs.push (new Beam_req); - } - else - { - Abbreviation_beam_req* a = new Abbreviation_beam_req; - a->type_i_ = abbrev_beam_type_i_; - if (t==']') - abbrev_beam_type_i_ = 0; - reqs.push (a); - } - } - break; - - case '>': - case '!': - case '<': - reqs.push (new Span_dynamic_req); - break; - - case ')': - case '(': - { - reqs.push (new Slur_req); - } - break; - default: - assert (false); - break; - } + SCM val= parser->lexer_->lookup_identifier (ly_scm2string (scm_symbol_to_string (symbol))); + if (val != SCM_UNDEFINED) + return val; + else + return SCM_EOL; +} - switch (t) - { - case '<': - case '>': - case '(': - case '[': - dynamic_cast (reqs[0])->spantype_ = START; - break; - - case '!': - case ')': - case ']': - dynamic_cast (reqs[0])->spantype_ = STOP; - break; - - default: - break; - } +LY_DEFINE (ly_parser_parse_string, "ly:parser-parse-string", + 2, 0, 0, + (SCM parser_smob, SCM ly_code), + "Parse the string LY_CODE with PARSER_SMOB." + "Upon failure, throw @code{ly-file-failed} key.") +{ - for (int i = 0; i < reqs.size (); i++) - if (dynamic_cast (reqs[i])) - { - Span_dynamic_req* s_l= dynamic_cast (reqs[i]); - s_l->dynamic_dir_ = (t == '<') ? UP:DOWN; - } + My_lily_parser *parser = unsmob_my_lily_parser (parser_smob); - // ugh? don't we do this in the parser too? - reqs[0]->set_spot (here_input()); - return &reqs; + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "parser"); + SCM_ASSERT_TYPE (ly_c_string_p (ly_code), ly_code, SCM_ARG2, __FUNCTION__, "string"); + + parser->parse_string (ly_scm2string (ly_code)); + + return SCM_UNSPECIFIED; } -void -My_lily_parser::add_requests (Simultaneous_music*v) +Output_def* +get_paper (My_lily_parser *parser) { - for (int i = 0; i < pre_reqs.size(); i++) - { - v->add_music (pre_reqs[i]); - } - pre_reqs.clear(); - for (int i = 0; i add_music (post_reqs[i]); - } + SCM id = parser->lexer_->lookup_identifier ("$defaultpaper"); + Output_def *paper = unsmob_output_def (id); + paper = paper ? paper->clone () : new Output_def; + paper->set_variable (ly_symbol2scm ("is-paper"), SCM_BOOL_T); - post_reqs.clear(); + paper->parent_ =unsmob_output_def (parser->lexer_->lookup_identifier ("$defaultbookpaper")); + return paper; } -Input -My_lily_parser::pop_spot() + +Output_def* +get_midi (My_lily_parser *parser) { - return define_spot_array_.pop(); + SCM id = parser->lexer_->lookup_identifier ("$defaultmidi"); + Output_def *paper = unsmob_output_def (id); + paper = paper ? paper->clone () : new Output_def; + paper->set_variable (ly_symbol2scm ("is-midi"), SCM_BOOL_T); + return paper; } -Input -My_lily_parser::here_input() const + +Output_def* +get_bookpaper (My_lily_parser *parser) { - Source_file * f_l= lexer_p_->source_file_l(); - return Input (f_l, here_ch_C()); + SCM id = parser->lexer_->lookup_identifier ("$defaultbookpaper"); + Output_def *paper = unsmob_output_def (id); + + paper = paper ? dynamic_cast (paper->clone ()) : new Output_def; + paper->set_variable (ly_symbol2scm ("is-bookpaper"), SCM_BOOL_T); + return paper; } -Paper_def* -My_lily_parser::default_paper_p () + +/* + TODO: move this to Scheme? Why take the parser arg, and all the back + & forth between scm and c++? + */ +LY_DEFINE (ly_parser_print_score, "ly:parser-print-score", + 2, 0, 0, + (SCM parser_smob, SCM score_smob), + "Print score, i.e., the classic way.") { - Identifier *id = lexer_p_->lookup_identifier ("$defaultpaper"); - return id ? id->access_content_Paper_def (true) : new Paper_def ; + My_lily_parser *parser = unsmob_my_lily_parser (parser_smob); + Score *score = unsmob_score (score_smob); + + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "parser"); + SCM_ASSERT_TYPE (score, score_smob, SCM_ARG2, __FUNCTION__, "score"); + + SCM header = ly_c_module_p (score->header_) ? score->header_ + : parser->lexer_->lookup_identifier ("$globalheader"); + + File_name outname (parser->output_basename_); + int *c = &parser->book_count_; + if (*c) + outname.base_ += "-" + to_string (*c); + (*c)++; + + SCM os = scm_makfrom0str (outname.to_string ().to_str0 ()); + SCM bookpaper = get_bookpaper (parser)->self_scm (); + for (int i = 0; i < score->defs_.size (); i++) + default_rendering (score->music_, score->defs_[i]->self_scm (), + bookpaper, + header, os); + + if (score->defs_.is_empty ()) + { + Output_def *paper = get_paper (parser); + default_rendering (score->music_, paper->self_scm (), + get_bookpaper (parser)->self_scm (), + header, os); + scm_gc_unprotect_object (paper->self_scm ()); + } + return SCM_UNDEFINED; } -Midi_def* -My_lily_parser::default_midi_p () +LY_DEFINE (ly_parser_print_book, "ly:parser-print-book", + 2, 0, 0, + (SCM parser_smob, SCM book_smob), + "Print book.") { - Identifier *id = lexer_p_->lookup_identifier ("$defaultmidi"); - return id ? id->access_content_Midi_def (true) : new Midi_def ; + My_lily_parser *parser = unsmob_my_lily_parser (parser_smob); + Book *book = unsmob_book (book_smob); + Output_def *bp = unsmob_output_def (parser->lexer_->lookup_identifier ("$defaultbookpaper")); + + SCM_ASSERT_TYPE (parser, parser_smob, SCM_ARG1, __FUNCTION__, "Lilypond parser"); + SCM_ASSERT_TYPE (book, book_smob, SCM_ARG2, __FUNCTION__, "Book"); + + /* ugh. changing argument.*/ + book->bookpaper_ = bp; + + File_name outname (parser->output_basename_); + int *c = &parser->book_count_; + if (*c) + outname.base_ += "-" + to_string (*c); + (*c)++; + + Output_def *paper = get_paper (parser); + + Paper_book* pb = book->process (outname.to_string (), paper); + + pb->output (outname.to_string ()); + + scm_gc_unprotect_object (paper->self_scm ()); + scm_gc_unprotect_object (pb->self_scm ()); + + return SCM_UNDEFINED; } -