2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
21 #include "lily-guile.hh"
31 #include <sys/types.h>
44 #include "all-font-metrics.hh"
45 #include "file-name.hh"
46 #include "freetype.hh"
47 #include "getopt-long.hh"
48 #include "global-ctor.hh"
49 #include "international.hh"
50 #include "lily-version.hh"
52 #include "output-def.hh"
53 #include "program-option.hh"
54 #include "relocate.hh"
55 #include "string-convert.hh"
58 #include "lily-imports.hh"
61 * Global options that can be overridden through command line.
64 /* Names of header fields to be dumped to a separate file. */
65 //vector<string> dump_header_fieldnames_global; // moved to global-data.cc
67 /* Name of initialisation file. */
68 //string init_name_global; // moved to global-data.cc
70 /* Output formats to generate. */
71 //string output_format_global = ""; // moved to global-data.cc
73 /* Current output name. */
74 //string output_name_global; // moved to global-data.cc
76 /* Run in safe mode? */
77 //bool be_safe_global = false; // moved to global-data.cc
79 /* Provide URI links to the original file */
80 bool point_and_click_global = true;
82 /* Scheme code to execute before parsing, after .scm init.
83 This is where -e arguments are appended to. */
84 //string init_scheme_code_global; // moved to global-data.cc
85 //string init_scheme_variables_global; // moved to global-data.cc
87 //bool relocate_binary = true; // moved to global-data.cc
90 * Miscellaneous global stuff.
92 //File_path global_path; // moved to global-data.cc
98 static char const *AUTHORS
99 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
100 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
102 static char const *PROGRAM_NAME = "lilypond";
103 static char const *PROGRAM_URL = "http://lilypond.org";
105 static char const *NOTICE
106 = _i ("This program is free software. It is covered by the GNU General Public\n"
107 "License and you are welcome to change it and/or distribute copies of it\n"
108 "under certain conditions. Invoke as `%s --warranty' for more\n"
111 static char const *WARRANTY
112 = _i (" This program is free software; you can redistribute it and/or\n"
113 "modify it under the terms of the GNU General Public License as \n"
114 "published by the Free Software Foundation, either version 3 of\n"
115 "the License, or (at your option) any later version.\n"
117 " This program is distributed in the hope that it will be useful,\n"
118 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
119 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
120 "General Public License for more details.\n"
122 " You should have received a copy of the\n"
123 "GNU General Public License along with this program; if not, write to\n"
124 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
125 "Boston, MA 02111-1307, USA.\n");
127 /* Where the init files live. Typically:
128 LILYPOND_DATADIR = /usr/share/lilypond
130 //string lilypond_datadir; // moved to global-data.cc
132 /* The jail specification: USER, GROUP, JAIL, DIR. */
133 std::string jail_spec;
135 /* The option parser */
136 static Getopt_long *option_parser = 0;
138 /* Internationalisation kludge in two steps:
139 * use _i () to get entry in POT file
140 * call gettext () explicitly for actual "translation" */
143 Data to be used to display when
144 -h command line option is detected.
146 static Long_option_init options_static[]
150 _i ("SYM[=VAL]"), "define-default", 'd',
151 _i ("set Scheme option SYM to VAL (default: #t).\n"
152 "Use -dhelp for help.")
155 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
156 /* Bug in option parser: --output =foe is taken as an abbreviation
157 for --output-format. */
158 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
159 {0, "pdf", 0, _i ("generate PDF (default)")},
160 {0, "png", 0, _i ("generate PNG")},
161 {0, "ps", 0, _i ("generate PostScript")},
162 {0, "bigpdfs", 'b', _i("generate big PDF files")},
163 {0, "help", 'h', _i ("show this help and exit")},
165 _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
166 "named BASENAME.FIELD")
168 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
169 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
172 _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
177 _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
178 " LOGLEVEL. Possible values are:\n"
179 "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
181 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
182 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
183 {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
184 {0, "version", 'v', _i ("show version number and exit")},
185 {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
186 {0, "warranty", 'w', _i ("show warranty and copyright")},
190 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
192 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
193 problems because the truncation from 80 bits to 64 bits can occur in
194 unpredictable places. To get around this, we tell the x87 FPU to use only
195 double precision. Note that this is not needed for x86_64 because that uses
196 the SSE unit by default instead of the x87 FPU. */
197 #if ((defined (__x86__) || defined (__i386__)) \
198 && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
200 #include <fpu_control.h>
204 fpu_control_t fpu_control = 0x027f;
205 _FPU_SETCW (fpu_control);
215 #endif /* defined(__x86__) || defined(__i386__) */
222 env_var_info (FILE *out, char const *key)
224 * Retrieve value of an OS environment variable.
226 * key, the name of an environment variable.
229 if (char const *value = getenv (key))
230 fprintf (out, "%s=\"%s\"\n", key, value);
236 * Print out information re directories being used by LilyPond
241 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
242 env_var_info (out, "LILYPONDPREFIX");
243 env_var_info (out, "LILYPOND_DATADIR");
244 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
246 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
250 env_var_info (out, "FONTCONFIG_FILE");
251 env_var_info (out, "FONTCONFIG_PATH");
252 env_var_info (out, "GS_FONTPATH");
253 env_var_info (out, "GS_LIB");
254 env_var_info (out, "GUILE_LOAD_PATH");
255 env_var_info (out, "PANGO_RC_FILE");
256 env_var_info (out, "PANGO_PREFIX");
257 env_var_info (out, "PATH");
264 * Print out LilyPond copyright info.
267 /* Do not update the copyright years here, run `make grand-replace' */
268 printf ("%s", (_f ("Copyright (c) %s by\n%s and others.", "1996--2015",
276 * Print out LilyPond version string.
279 fputs (gnu_lilypond_version_string ().c_str (), out);
285 * Print copyright and program name
293 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
296 LY_DEFINE (ly_usage, "ly:usage",
298 "Print usage message.")
300 * ly_usage: Routine to output standard information when LilyPond is run without a
301 * source file to compile.
302 * Also callable as ly:usage from Scheme.
305 /* No version number or newline here. It confuses help2man. */
306 printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
308 printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
310 printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
312 printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
314 printf ("%s", (_ ("Options:").c_str ()));
316 printf ("%s", Long_option_init::table_string (options_static).c_str ());
318 /* Translators, please translate this string as
319 "Report bugs in English via %s",
320 or if there is a LilyPond users list or forum in your language
321 "Report bugs in English via %s or in YOUR_LANG via URI" */
322 printf ("%s", (_f ("Report bugs via %s",
323 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
327 return SCM_UNSPECIFIED;
333 * Prints out LilyPond warranty information
340 printf ("%s", (_ (WARRANTY).c_str ()));
344 prepend_scheme_list (const string &dir, const string &scmlist)
346 * Inserts an item at the front of a Scheme list, e.g. %load-path
348 * dir: The directory to add to the front of the list
349 * scmlist: The Scheme list onto which to prepend the directory
352 SCM var = scm_c_lookup (scmlist.c_str());
353 scm_variable_set_x (var, scm_cons (scm_from_locale_string (dir.c_str()),
354 scm_variable_ref (var)));
356 "(set! " + scmlist + " (cons \"" + dir + "\" " + scmlist +"))";
357 scm_c_eval_string (setcmd.c_str());*/
360 void init_global_tweak_registry ();
361 void init_fontconfig ();
367 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
368 we exit (this is a security-sensitive area). First we split
369 jail_spec into its components, then we retrieve the user/group id
370 (necessarily *before* chroot'ing) and finally we perform the
375 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
378 vector<string> components = string_split (jail_spec, ',');
379 if (components.size () != JAIL_MAX)
381 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
382 (unsigned) components.size ()));
390 if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
391 uid = passwd->pw_uid;
395 error (_f ("no such user: %s", components[USER_NAME]));
397 error (_f ("cannot get user id from user name: %s: %s",
398 components[USER_NAME],
407 if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
412 error (_f ("no such group: %s", components[GROUP_NAME]));
414 error (_f ("cannot get group id from group name: %s: %s",
415 components[GROUP_NAME],
420 if (chroot (components[JAIL].c_str ()))
422 error (_f ("cannot chroot to: %s: %s", components[JAIL],
429 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
435 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
439 if (chdir (components[DIR].c_str ()))
441 error (_f ("cannot change working directory to: %s: %s", components[DIR],
449 main_with_guile (void *, int, char **)
451 * main-with-guile is invoked as a callback via scm_boot_guile from
453 * scm_boot_guile will have passed its data, argc and argv parameters
454 * to main_with_guile.
457 /* Engravers use lily.scm contents, so we need to make Guile find it.
458 Prepend onto GUILE %load-path.
459 %load-path is the symbol Guile searches for .scm files
460 %load-compiled-path is the symbol Guile V2 searches for .go files
462 string scm_pct_load_path = "%load-path";
463 string scm_pct_load_compiled_path = "%load-compiled-path";
465 prepend_scheme_list (lilypond_datadir, scm_pct_load_path );
466 prepend_scheme_list (lilypond_datadir + "/scm", scm_pct_load_path);
470 Just as ughy - prepend "/scm/out" onto GUILE V2+Â %load-compiled-path
471 and set %compile-fallback-path to our scm/out directory
474 %load-compiled-path is the symbol Guile V2 searches for .go files
476 prepend_scheme_list (lilypond_datadir + "/scm/out",
477 scm_pct_load_compiled_path);
479 %compile-fallback-path is the guile cache root for auto-compiled files
482 string scm_pct_fallback_path = "%compile-fallback-path";
483 string ly_scm_go_dir = lilypond_datadir + "/scm/out";
484 //string scm_pct_set_fallback = "(set! " + scm_pct_fallback_path +
485 // " \"" + lilypond_datadir + "/scm/out\")";
486 //scm_c_eval_string (scm_pct_set_fallback.c_str() );
488 (scm_list_3 (scm_from_latin1_symbol ("set!"),
489 scm_from_latin1_symbol ("%compile-fallback-path"),
490 scm_from_locale_string (ly_scm_go_dir.c_str())));
493 if (is_loglevel (LOG_DEBUG))
496 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
497 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
500 call_constructors ();
504 ly_reset_all_fonts ();
507 We accept multiple independent music files on the command line to
508 reduce compile time when processing lots of small files.
509 This way we don't have to start the Guile/Scheme interpreter more than once, as
510 starting the GUILE engine is very time consuming.
515 while (char const *arg = option_parser->get_next_arg ())
517 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
518 tail = SCM_CDRLOC (*tail);
521 delete option_parser;
525 if (!jail_spec.empty ())
529 Now execute the Scheme entry-point declared in
530 lily.scm (lilypond-main)
532 // These commands moved to lily_guile_v2.scm
533 // SCM rep_mod = scm_c_resolve_module ("system repl repl");
534 // scm_c_use_module ("system repl repl");
535 // SCM err_handling_mod = scm_c_resolve_module ("system repl error-handling");
536 // SCM call_with_error_handling = scm_c_module_lookup (err_handling_mod, "call-with-error-handling");
537 // SCM result = scm_call_1 (
538 // scm_variable_ref (call_with_error_handling),
539 // scm_call_1 (ly_lily_module_constant ("lilypond-main"), files));
541 Lily::lilypond_main (files);
548 setup_localisation ()
550 * Set up local language text locale (if available from configure)
552 * HAVE_GETTEXT: Internationalization available for a local language.
557 setlocale (LC_ALL, "");
559 /* FIXME: check if this is still true.
560 Disable localisation of float values. */
561 setlocale (LC_NUMERIC, "C");
564 // In order not to have this porting aid backfire to GUILE1 usage,
565 // this is only compiled in the GUILEV2 version. It should
566 // eventually be replaced with proper multibyte communication with
567 // GUILE2, but in the mean time it seems that this is the least
568 // invasive path to get comparable results between the
569 // not-really-multibyte-supporting GUILE1 and GUILE2
571 /* Disable character sets */
572 setlocale (LC_CTYPE, "C");
573 /* But our text domain is in UTF-8 */
574 bind_textdomain_codeset ("lilypond", "UTF-8");
577 string localedir = LOCALEDIR;
578 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
581 bindtextdomain ("lilypond", localedir.c_str ());
582 textdomain ("lilypond");
587 add_output_format (const string &format)
589 * Capture information internally from command-line options
594 if (output_format_global != "")
595 output_format_global += ",";
596 output_format_global += format;
600 parse_argv (int argc, char **argv)
602 * Parse command-line options
603 * also, if -h (help), -v (version) or -w (warranty) is detected,
604 * output the usage information and exit.
607 bool show_help = false;
608 option_parser = new Getopt_long (argc, argv, options_static);
609 while (Long_option_init const *opt = (*option_parser) ())
611 switch (opt->shortname_char_)
614 if (string (opt->longname_str0_) == "pdf"
615 || string (opt->longname_str0_) == "png"
616 || string (opt->longname_str0_) == "ps")
617 add_output_format (opt->longname_str0_);
618 else if (string (opt->longname_str0_) == "relocate")
619 relocate_binary = true;
628 string arg (option_parser->optional_argument_str0_);
629 ssize eq = arg.find ('=');
636 key = arg.substr (0, eq);
637 val = arg.substr (eq + 1, arg.length () - 1);
640 init_scheme_variables_global
641 += "(cons \'" + key + " '" + val + ")\n";
651 string s = option_parser->optional_argument_str0_;
652 File_name file_name (s);
653 output_name_global = file_name.to_string ();
657 jail_spec = option_parser->optional_argument_str0_;
661 init_scheme_code_global
662 += option_parser->optional_argument_str0_ + string (" ");
671 vector<string> components
672 = string_split (option_parser->optional_argument_str0_, ',');
673 for (vsize i = 0; i < components.size (); i++)
674 add_output_format (components[i]);
679 dump_header_fieldnames_global
680 .push_back (option_parser->optional_argument_str0_);
683 global_path.append (option_parser->optional_argument_str0_);
686 init_name_global = option_parser->optional_argument_str0_;
692 set_loglevel (LOGLEVEL_DEBUG);
695 set_loglevel (LOGLEVEL_ERROR);
698 set_loglevel (option_parser->optional_argument_str0_);
701 programming_error (to_string ("unhandled short option: %c",
702 opt->shortname_char_));
708 if (output_format_global == "")
709 output_format_global = "pdf";
714 if (is_loglevel (LOG_DEBUG))
721 T1686 Add two new routines called by setup_guile_env
725 setup_guile_gc_env ()
727 * Set up environment variables relevant to the
731 char const *yield = getenv ("LILYPOND_GC_YIELD");
732 bool overwrite = true;
739 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
740 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
741 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
743 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
744 "10485760", overwrite);
745 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
746 "104857600", overwrite);
751 setup_guile_v2_env ()
753 * Set up environment variables relevant to compiling
754 * Scheme files for Guile V2.
757 sane_putenv("GUILE_AUTO_COMPILE", "0", true); // disable auto-compile
758 sane_putenv("GUILE_WARN_DEPRECATED",
759 "detailed", "true"); // set Guile to info re deprecation
761 Set root for Guile %compile-fallback to
762 Lilypond root for its data.
764 sane_putenv("XDG_CACHE_HOME",
765 lilypond_datadir, true);
771 * Set up environment variables relevant to Scheme
775 setup_guile_gc_env (); // configure garbage collector
777 setup_guile_v2_env (); // configure Guile V2 behaviour
781 //vector<string> start_environment_global;
784 main (int argc, char **argv, char **envp)
786 * Main entry-point for LilyPond executable image
788 * argc: Count of arguments on the command line
789 * argv: Vector of string arguments on command line
790 * envp: Point to vector of OS environment variables
795 Process environment variables
797 for (char **p = envp; *p; p++)
798 start_environment_global.push_back (*p);
800 Handle old-style environment equivalent to
801 old-style -V or --verbose command arguments.
802 Set it to the equivalent for --loglevel-DEBUG
804 if (getenv ("LILYPOND_VERBOSE"))
805 set_loglevel (LOGLEVEL_DEBUG);
806 if (getenv ("LILYPOND_LOGLEVEL"))
807 set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
809 setup_localisation ();
810 parse_argv (argc, argv);
811 if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
814 setup_paths (argv[0]);
815 setup_guile_env (); // set up environment variables to pass into Guile API
817 * Start up Guile API using main_with_guile as a callback.
821 Set it on by default for Guile V2
822 while migration in progress.
826 scm_boot_guile (argc, argv, main_with_guile, 0);
830 error (_f ("exception caught: %s", e.what ()));
833 scm_boot_guile (argc, argv, main_with_guile, 0);
836 /* Only reachable if GUILE exits. That is an error. */