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"
30 #include <sys/types.h>
43 #include "all-font-metrics.hh"
44 #include "file-name.hh"
45 #include "freetype.hh"
46 #include "getopt-long.hh"
47 #include "global-ctor.hh"
48 #include "international.hh"
49 #include "lily-version.hh"
51 #include "output-def.hh"
52 #include "program-option.hh"
53 #include "relocate.hh"
54 #include "string-convert.hh"
57 #include "lily-imports.hh"
60 * Global options that can be overridden through command line.
63 /* Names of header fields to be dumped to a separate file. */
64 //vector<string> dump_header_fieldnames_global; // moved to global-data.cc
66 /* Name of initialisation file. */
67 //string init_name_global; // moved to global-data.cc
69 /* Output formats to generate. */
70 //string output_format_global = ""; // moved to global-data.cc
72 /* Current output name. */
73 //string output_name_global; // moved to global-data.cc
75 /* Run in safe mode? */
76 //bool be_safe_global = false; // moved to global-data.cc
78 /* Provide URI links to the original file */
79 bool point_and_click_global = true;
81 /* Scheme code to execute before parsing, after .scm init.
82 This is where -e arguments are appended to. */
83 //string init_scheme_code_global; // moved to global-data.cc
84 //string init_scheme_variables_global; // moved to global-data.cc
86 //bool relocate_binary = true; // moved to global-data.cc
89 * Miscellaneous global stuff.
91 //File_path global_path; // moved to global-data.cc
97 static char const *AUTHORS
98 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
99 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
101 static char const *PROGRAM_NAME = "lilypond";
102 static char const *PROGRAM_URL = "http://lilypond.org";
104 static char const *NOTICE
105 = _i ("This program is free software. It is covered by the GNU General Public\n"
106 "License and you are welcome to change it and/or distribute copies of it\n"
107 "under certain conditions. Invoke as `%s --warranty' for more\n"
110 static char const *WARRANTY
111 = _i (" This program is free software; you can redistribute it and/or\n"
112 "modify it under the terms of the GNU General Public License as \n"
113 "published by the Free Software Foundation, either version 3 of\n"
114 "the License, or (at your option) any later version.\n"
116 " This program is distributed in the hope that it will be useful,\n"
117 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
118 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
119 "General Public License for more details.\n"
121 " You should have received a copy of the\n"
122 "GNU General Public License along with this program; if not, write to\n"
123 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
124 "Boston, MA 02111-1307, USA.\n");
126 /* Where the init files live. Typically:
127 LILYPOND_DATADIR = /usr/share/lilypond
129 //string lilypond_datadir; // moved to global-data.cc
131 /* The jail specification: USER, GROUP, JAIL, DIR. */
132 std::string jail_spec;
134 /* The option parser */
135 static Getopt_long *option_parser = 0;
137 /* Internationalisation kludge in two steps:
138 * use _i () to get entry in POT file
139 * call gettext () explicitly for actual "translation" */
142 Data to be used to display when
143 -h command line option is detected.
145 static Long_option_init options_static[]
149 _i ("SYM[=VAL]"), "define-default", 'd',
150 _i ("set Scheme option SYM to VAL (default: #t).\n"
151 "Use -dhelp for help.")
154 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
155 /* Bug in option parser: --output =foe is taken as an abbreviation
156 for --output-format. */
157 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
158 {0, "pdf", 0, _i ("generate PDF (default)")},
159 {0, "png", 0, _i ("generate PNG")},
160 {0, "ps", 0, _i ("generate PostScript")},
161 {0, "bigpdfs", 'b', _i("generate big PDF files")},
162 {0, "help", 'h', _i ("show this help and exit")},
164 _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
165 "named BASENAME.FIELD")
167 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
168 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
171 _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
176 _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
177 " LOGLEVEL. Possible values are:\n"
178 "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
180 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
181 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
182 {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
183 {0, "version", 'v', _i ("show version number and exit")},
184 {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
185 {0, "warranty", 'w', _i ("show warranty and copyright")},
189 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
191 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
192 problems because the truncation from 80 bits to 64 bits can occur in
193 unpredictable places. To get around this, we tell the x87 FPU to use only
194 double precision. Note that this is not needed for x86_64 because that uses
195 the SSE unit by default instead of the x87 FPU. */
196 #if ((defined (__x86__) || defined (__i386__)) \
197 && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
199 #include <fpu_control.h>
203 fpu_control_t fpu_control = 0x027f;
204 _FPU_SETCW (fpu_control);
214 #endif /* defined(__x86__) || defined(__i386__) */
221 env_var_info (FILE *out, char const *key)
223 * Retrieve value of an OS environment variable.
225 * key, the name of an environment variable.
228 if (char const *value = getenv (key))
229 fprintf (out, "%s=\"%s\"\n", key, value);
235 * Print out information re directories being used by LilyPond
240 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
241 env_var_info (out, "LILYPONDPREFIX");
242 env_var_info (out, "LILYPOND_DATADIR");
243 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
245 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
249 env_var_info (out, "FONTCONFIG_FILE");
250 env_var_info (out, "FONTCONFIG_PATH");
251 env_var_info (out, "GS_FONTPATH");
252 env_var_info (out, "GS_LIB");
253 env_var_info (out, "GUILE_LOAD_PATH");
254 env_var_info (out, "PANGO_RC_FILE");
255 env_var_info (out, "PANGO_PREFIX");
256 env_var_info (out, "PATH");
263 * Print out LilyPond copyright info.
266 /* Do not update the copyright years here, run `make grand-replace' */
267 printf ("%s", (_f ("Copyright (c) %s by\n%s and others.", "1996--2015",
275 * Print out LilyPond version string.
278 fputs (gnu_lilypond_version_string ().c_str (), out);
284 * Print copyright and program name
292 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
295 LY_DEFINE (ly_usage, "ly:usage",
297 "Print usage message.")
299 * ly_usage: Routine to output standard information when LilyPond is run without a
300 * source file to compile.
301 * Also callable as ly:usage from Scheme.
304 /* No version number or newline here. It confuses help2man. */
305 printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
307 printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
309 printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
311 printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
313 printf ("%s", (_ ("Options:").c_str ()));
315 printf ("%s", Long_option_init::table_string (options_static).c_str ());
317 /* Translators, please translate this string as
318 "Report bugs in English via %s",
319 or if there is a LilyPond users list or forum in your language
320 "Report bugs in English via %s or in YOUR_LANG via URI" */
321 printf ("%s", (_f ("Report bugs via %s",
322 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
326 return SCM_UNSPECIFIED;
332 * Prints out LilyPond warranty information
339 printf ("%s", (_ (WARRANTY).c_str ()));
343 prepend_scheme_list (const string &dir, const string &scmlist)
345 * Inserts an item at the front of a Scheme list, e.g. %load-path
347 * dir: The directory to add to the front of the list
348 * scmlist: The Scheme list onto which to prepend the directory
351 SCM var = scm_c_lookup (scmlist.c_str());
352 scm_variable_set_x (var, scm_cons (scm_from_locale_string (dir.c_str()),
353 scm_variable_ref (var)));
355 "(set! " + scmlist + " (cons \"" + dir + "\" " + scmlist +"))";
356 scm_c_eval_string (setcmd.c_str());*/
359 void init_global_tweak_registry ();
360 void init_fontconfig ();
366 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
367 we exit (this is a security-sensitive area). First we split
368 jail_spec into its components, then we retrieve the user/group id
369 (necessarily *before* chroot'ing) and finally we perform the
374 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
377 vector<string> components = string_split (jail_spec, ',');
378 if (components.size () != JAIL_MAX)
380 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
381 (unsigned) components.size ()));
389 if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
390 uid = passwd->pw_uid;
394 error (_f ("no such user: %s", components[USER_NAME]));
396 error (_f ("cannot get user id from user name: %s: %s",
397 components[USER_NAME],
406 if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
411 error (_f ("no such group: %s", components[GROUP_NAME]));
413 error (_f ("cannot get group id from group name: %s: %s",
414 components[GROUP_NAME],
419 if (chroot (components[JAIL].c_str ()))
421 error (_f ("cannot chroot to: %s: %s", components[JAIL],
428 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
434 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
438 if (chdir (components[DIR].c_str ()))
440 error (_f ("cannot change working directory to: %s: %s", components[DIR],
448 main_with_guile (void *, int, char **)
450 * main-with-guile is invoked as a callback via scm_boot_guile from
452 * scm_boot_guile will have passed its data, argc and argv parameters
453 * to main_with_guile.
456 /* Engravers use lily.scm contents, so we need to make Guile find it.
457 Prepend onto GUILE %load-path.
458 %load-path is the symbol Guile searches for .scm files
459 %load-compiled-path is the symbol Guile V2 searches for .go files
461 string scm_pct_load_path = "%load-path";
462 string scm_pct_load_compiled_path = "%load-compiled-path";
464 prepend_scheme_list (lilypond_datadir, scm_pct_load_path );
465 prepend_scheme_list (lilypond_datadir + "/scm", scm_pct_load_path);
469 Just as ughy - prepend "/scm/out" onto GUILE V2+Â %load-compiled-path
470 and set %compile-fallback-path to our scm/out directory
473 %load-compiled-path is the symbol Guile V2 searches for .go files
475 prepend_scheme_list (lilypond_datadir + "/scm/out",
476 scm_pct_load_compiled_path);
478 %compile-fallback-path is the guile cache root for auto-compiled files
481 string scm_pct_fallback_path = "%compile-fallback-path";
482 string ly_scm_go_dir = lilypond_datadir + "/scm/out";
483 //string scm_pct_set_fallback = "(set! " + scm_pct_fallback_path +
484 // " \"" + lilypond_datadir + "/scm/out\")";
485 //scm_c_eval_string (scm_pct_set_fallback.c_str() );
487 (scm_list_3 (scm_from_latin1_symbol ("set!"),
488 scm_from_latin1_symbol ("%compile-fallback-path"),
489 scm_from_locale_string (ly_scm_go_dir.c_str())));
492 if (is_loglevel (LOG_DEBUG))
495 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
496 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
499 call_constructors ();
503 ly_reset_all_fonts ();
506 We accept multiple independent music files on the command line to
507 reduce compile time when processing lots of small files.
508 This way we don't have to start the Guile/Scheme interpreter more than once, as
509 starting the GUILE engine is very time consuming.
514 while (char const *arg = option_parser->get_next_arg ())
516 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
517 tail = SCM_CDRLOC (*tail);
520 delete option_parser;
524 if (!jail_spec.empty ())
528 Now execute the Scheme entry-point declared in
529 lily.scm (lilypond-main)
531 // These commands moved to lily_guile_v2.scm
532 // SCM rep_mod = scm_c_resolve_module ("system repl repl");
533 // scm_c_use_module ("system repl repl");
534 // SCM err_handling_mod = scm_c_resolve_module ("system repl error-handling");
535 // SCM call_with_error_handling = scm_c_module_lookup (err_handling_mod, "call-with-error-handling");
536 // SCM result = scm_call_1 (
537 // scm_variable_ref (call_with_error_handling),
538 // scm_call_1 (ly_lily_module_constant ("lilypond-main"), files));
540 Lily::lilypond_main (files);
547 setup_localisation ()
549 * Set up local language text locale (if available from configure)
551 * HAVE_GETTEXT: Internationalization available for a local language.
556 setlocale (LC_ALL, "");
558 /* FIXME: check if this is still true.
559 Disable localisation of float values. */
560 setlocale (LC_NUMERIC, "C");
563 // In order not to have this porting aid backfire to GUILE1 usage,
564 // this is only compiled in the GUILEV2 version. It should
565 // eventually be replaced with proper multibyte communication with
566 // GUILE2, but in the mean time it seems that this is the least
567 // invasive path to get comparable results between the
568 // not-really-multibyte-supporting GUILE1 and GUILE2
570 /* Disable character sets */
571 setlocale (LC_CTYPE, "C");
572 /* But our text domain is in UTF-8 */
573 bind_textdomain_codeset ("lilypond", "UTF-8");
576 string localedir = LOCALEDIR;
577 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
580 bindtextdomain ("lilypond", localedir.c_str ());
581 textdomain ("lilypond");
586 add_output_format (const string &format)
588 * Capture information internally from command-line options
593 if (output_format_global != "")
594 output_format_global += ",";
595 output_format_global += format;
599 parse_argv (int argc, char **argv)
601 * Parse command-line options
602 * also, if -h (help), -v (version) or -w (warranty) is detected,
603 * output the usage information and exit.
606 bool show_help = false;
607 option_parser = new Getopt_long (argc, argv, options_static);
608 while (Long_option_init const *opt = (*option_parser) ())
610 switch (opt->shortname_char_)
613 if (string (opt->longname_str0_) == "pdf"
614 || string (opt->longname_str0_) == "png"
615 || string (opt->longname_str0_) == "ps")
616 add_output_format (opt->longname_str0_);
617 else if (string (opt->longname_str0_) == "relocate")
618 relocate_binary = true;
627 string arg (option_parser->optional_argument_str0_);
628 ssize eq = arg.find ('=');
635 key = arg.substr (0, eq);
636 val = arg.substr (eq + 1, arg.length () - 1);
639 init_scheme_variables_global
640 += "(cons \'" + key + " '" + val + ")\n";
650 string s = option_parser->optional_argument_str0_;
651 File_name file_name (s);
652 output_name_global = file_name.to_string ();
656 jail_spec = option_parser->optional_argument_str0_;
660 init_scheme_code_global
661 += option_parser->optional_argument_str0_ + string (" ");
670 vector<string> components
671 = string_split (option_parser->optional_argument_str0_, ',');
672 for (vsize i = 0; i < components.size (); i++)
673 add_output_format (components[i]);
678 dump_header_fieldnames_global
679 .push_back (option_parser->optional_argument_str0_);
682 global_path.append (option_parser->optional_argument_str0_);
685 init_name_global = option_parser->optional_argument_str0_;
691 set_loglevel (LOGLEVEL_DEBUG);
694 set_loglevel (LOGLEVEL_ERROR);
697 set_loglevel (option_parser->optional_argument_str0_);
700 programming_error (to_string ("unhandled short option: %c",
701 opt->shortname_char_));
707 if (output_format_global == "")
708 output_format_global = "pdf";
713 if (is_loglevel (LOG_DEBUG))
720 T1686 Add two new routines called by setup_guile_env
724 setup_guile_gc_env ()
726 * Set up environment variables relevant to the
730 char const *yield = getenv ("LILYPOND_GC_YIELD");
731 bool overwrite = true;
738 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
739 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
740 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
742 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
743 "10485760", overwrite);
744 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
745 "104857600", overwrite);
750 setup_guile_v2_env ()
752 * Set up environment variables relevant to compiling
753 * Scheme files for Guile V2.
756 sane_putenv("GUILE_AUTO_COMPILE", "0", true); // disable auto-compile
757 sane_putenv("GUILE_WARN_DEPRECATED",
758 "detailed", "true"); // set Guile to info re deprecation
760 Set root for Guile %compile-fallback to
761 Lilypond root for its data.
763 sane_putenv("XDG_CACHE_HOME",
764 lilypond_datadir, true);
770 * Set up environment variables relevant to Scheme
774 setup_guile_gc_env (); // configure garbage collector
776 setup_guile_v2_env (); // configure Guile V2 behaviour
780 //vector<string> start_environment_global;
783 main (int argc, char **argv, char **envp)
785 * Main entry-point for LilyPond executable image
787 * argc: Count of arguments on the command line
788 * argv: Vector of string arguments on command line
789 * envp: Point to vector of OS environment variables
794 Process environment variables
796 for (char **p = envp; *p; p++)
797 start_environment_global.push_back (*p);
799 Handle old-style environment equivalent to
800 old-style -V or --verbose command arguments.
801 Set it to the equivalent for --loglevel-DEBUG
803 if (getenv ("LILYPOND_VERBOSE"))
804 set_loglevel (LOGLEVEL_DEBUG);
805 if (getenv ("LILYPOND_LOGLEVEL"))
806 set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
808 setup_localisation ();
809 parse_argv (argc, argv);
810 if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
813 setup_paths (argv[0]);
814 setup_guile_env (); // set up environment variables to pass into Guile API
816 * Start up Guile API using main_with_guile as a callback.
820 Set it on by default for Guile V2
821 while migration in progress.
825 scm_boot_guile (argc, argv, main_with_guile, 0);
829 error (_f ("exception caught: %s", e.what ()));
832 scm_boot_guile (argc, argv, main_with_guile, 0);
835 /* Only reachable if GUILE exits. That is an error. */