2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2012 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/>.
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"
59 * Global options that can be overridden through command line.
62 /* Names of header fields to be dumped to a separate file. */
63 vector<string> dump_header_fieldnames_global;
65 /* Name of initialisation file. */
66 string init_name_global;
68 /* Output formats to generate. */
69 string output_format_global = "";
71 /* Current output name. */
72 string output_name_global;
74 /* Run in safe mode? */
75 bool be_safe_global = false;
77 /* Scheme code to execute before parsing, after .scm init.
78 This is where -e arguments are appended to. */
79 string init_scheme_code_global;
80 string init_scheme_variables_global;
82 bool relocate_binary = true;
85 * Miscellaneous global stuff.
87 File_path global_path;
93 static char const *AUTHORS
94 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
95 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
97 static char const *PROGRAM_NAME = "lilypond";
98 static char const *PROGRAM_URL = "http://lilypond.org";
100 static char const *NOTICE
101 = _i ("This program is free software. It is covered by the GNU General Public\n"
102 "License and you are welcome to change it and/or distribute copies of it\n"
103 "under certain conditions. Invoke as `%s --warranty' for more\n"
106 static char const *WARRANTY
107 = _i (" This program is free software; you can redistribute it and/or\n"
108 "modify it under the terms of the GNU General Public License as \n"
109 "published by the Free Software Foundation, either version 3 of\n"
110 "the License, or (at your option) any later version.\n"
112 " This program is distributed in the hope that it will be useful,\n"
113 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
114 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
115 "General Public License for more details.\n"
117 " You should have received a copy of the\n"
118 "GNU General Public License along with this program; if not, write to\n"
119 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
120 "Boston, MA 02111-1307, USA.\n");
122 /* Where the init files live. Typically:
123 LILYPOND_DATADIR = /usr/share/lilypond
125 string lilypond_datadir;
127 /* The jail specification: USER, GROUP, JAIL, DIR. */
130 /* The option parser */
131 static Getopt_long *option_parser = 0;
133 /* Internationalisation kludge in two steps:
134 * use _i () to get entry in POT file
135 * call gettext () explicitly for actual "translation" */
137 static Long_option_init options_static[]
141 _i ("SYM[=VAL]"), "define-default", 'd',
142 _i ("set Scheme option SYM to VAL (default: #t).\n"
143 "Use -dhelp for help.")
146 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
147 /* Bug in option parser: --output =foe is taken as an abbreviation
148 for --output-format. */
149 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
150 {0, "pdf", 0, _i ("generate PDF (default)")},
151 {0, "png", 0, _i ("generate PNG")},
152 {0, "ps", 0, _i ("generate PostScript")},
153 {0, "help", 'h', _i ("show this help and exit")},
155 _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
156 "named BASENAME.FIELD")
158 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
159 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
162 _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
167 _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
168 " LOGLEVEL. Possible values are:\n"
169 "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
171 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
172 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
173 {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
174 {0, "version", 'v', _i ("show version number and exit")},
175 {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
176 {0, "warranty", 'w', _i ("show warranty and copyright")},
180 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
182 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
183 problems because the truncation from 80 bits to 64 bits can occur in
184 unpredictable places. To get around this, we tell the x87 FPU to use only
185 double precision. Note that this is not needed for x86_64 because that uses
186 the SSE unit by default instead of the x87 FPU. */
187 #if ((defined (__x86__) || defined (__i386__)) \
188 && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
190 #include <fpu_control.h>
194 fpu_control_t fpu_control = 0x027f;
195 _FPU_SETCW (fpu_control);
205 #endif /* defined(__x86__) || defined(__i386__) */
208 env_var_info (FILE *out, char const *key)
210 if (char const *value = getenv (key))
211 fprintf (out, "%s=\"%s\"\n", key, value);
218 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
219 env_var_info (out, "LILYPONDPREFIX");
220 env_var_info (out, "LILYPOND_DATADIR");
221 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
223 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
227 env_var_info (out, "FONTCONFIG_FILE");
228 env_var_info (out, "FONTCONFIG_PATH");
229 env_var_info (out, "GS_FONTPATH");
230 env_var_info (out, "GS_LIB");
231 env_var_info (out, "GUILE_LOAD_PATH");
232 env_var_info (out, "PANGO_RC_FILE");
233 env_var_info (out, "PANGO_PREFIX");
234 env_var_info (out, "PATH");
241 /* Do not update the copyright years here, run `make grand-replace' */
242 printf ("%s", (_f ("Copyright (c) %s by\n%s and others.", "1996--2012",
250 fputs (gnu_lilypond_version_string ().c_str (), out);
261 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
264 LY_DEFINE (ly_usage, "ly:usage",
266 "Print usage message.")
268 /* No version number or newline here. It confuses help2man. */
269 printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
271 printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
273 printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
275 printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
277 printf ("%s", (_ ("Options:").c_str ()));
279 printf ("%s", Long_option_init::table_string (options_static).c_str ());
281 /* Translators, please translate this string as
282 "Report bugs in English via %s",
283 or if there is a LilyPond users list or forum in your language
284 "Report bugs in English via %s or in YOUR_LANG via URI" */
285 printf ("%s", (_f ("Report bugs via %s",
286 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
290 return SCM_UNSPECIFIED;
300 printf ("%s", (_ (WARRANTY).c_str ()));
304 prepend_load_path (string dir)
306 string s = "(set! %load-path (cons \"" + dir + "\" %load-path))";
307 scm_c_eval_string (s.c_str ());
310 void init_global_tweak_registry ();
311 void init_fontconfig ();
317 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
318 we exit (this is a security-sensitive area). First we split
319 jail_spec into its components, then we retrieve the user/group id
320 (necessarily *before* chroot'ing) and finally we perform the
325 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
328 vector<string> components = string_split (jail_spec, ',');
329 if (components.size () != JAIL_MAX)
331 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
332 (unsigned) components.size ()));
340 if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
341 uid = passwd->pw_uid;
345 error (_f ("no such user: %s", components[USER_NAME]));
347 error (_f ("cannot get user id from user name: %s: %s",
348 components[USER_NAME],
357 if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
362 error (_f ("no such group: %s", components[GROUP_NAME]));
364 error (_f ("cannot get group id from group name: %s: %s",
365 components[GROUP_NAME],
370 if (chroot (components[JAIL].c_str ()))
372 error (_f ("cannot chroot to: %s: %s", components[JAIL],
379 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
385 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
389 if (chdir (components[DIR].c_str ()))
391 error (_f ("cannot change working directory to: %s: %s", components[DIR],
399 main_with_guile (void *, int, char **)
401 /* Engravers use lily.scm contents, need to make Guile find it.
402 Prepend onto GUILE %load-path, very ugh. */
404 prepend_load_path (lilypond_datadir);
405 prepend_load_path (lilypond_datadir + "/scm");
407 if (is_loglevel (LOG_DEBUG))
410 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
411 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
414 call_constructors ();
418 ly_reset_all_fonts ();
420 /* We accept multiple independent music files on the command line to
421 reduce compile time when processing lots of small files.
422 Starting the GUILE engine is very time consuming. */
426 while (char const *arg = option_parser->get_next_arg ())
428 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
429 tail = SCM_CDRLOC (*tail);
432 delete option_parser;
436 if (!jail_spec.empty ())
440 SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
448 setup_localisation ()
452 setlocale (LC_ALL, "");
454 /* FIXME: check if this is still true.
455 Disable localisation of float values. */
456 setlocale (LC_NUMERIC, "C");
458 string localedir = LOCALEDIR;
459 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
462 bindtextdomain ("lilypond", localedir.c_str ());
463 textdomain ("lilypond");
468 add_output_format (string format)
470 if (output_format_global != "")
471 output_format_global += ",";
472 output_format_global += format;
476 parse_argv (int argc, char **argv)
478 bool show_help = false;
479 option_parser = new Getopt_long (argc, argv, options_static);
480 while (Long_option_init const *opt = (*option_parser) ())
482 switch (opt->shortname_char_)
485 if (string (opt->longname_str0_) == "pdf"
486 || string (opt->longname_str0_) == "png"
487 || string (opt->longname_str0_) == "ps")
488 add_output_format (opt->longname_str0_);
489 else if (string (opt->longname_str0_) == "relocate")
490 relocate_binary = true;
495 string arg (option_parser->optional_argument_str0_);
496 ssize eq = arg.find ('=');
503 key = arg.substr (0, eq);
504 val = arg.substr (eq + 1, arg.length () - 1);
507 init_scheme_variables_global
508 += "(cons \'" + key + " '" + val + ")\n";
518 string s = option_parser->optional_argument_str0_;
519 File_name file_name (s);
520 output_name_global = file_name.to_string ();
524 jail_spec = option_parser->optional_argument_str0_;
528 init_scheme_code_global
529 += option_parser->optional_argument_str0_ + string (" ");
538 vector<string> components
539 = string_split (option_parser->optional_argument_str0_, ',');
540 for (vsize i = 0; i < components.size (); i++)
541 add_output_format (components[i]);
546 dump_header_fieldnames_global
547 .push_back (option_parser->optional_argument_str0_);
550 global_path.append (option_parser->optional_argument_str0_);
553 init_name_global = option_parser->optional_argument_str0_;
559 set_loglevel (LOGLEVEL_DEBUG);
562 set_loglevel (LOGLEVEL_ERROR);
565 set_loglevel (option_parser->optional_argument_str0_);
568 programming_error (to_string ("unhandled short option: %c",
569 opt->shortname_char_));
575 if (output_format_global == "")
576 output_format_global = "pdf";
581 if (is_loglevel (LOG_DEBUG))
590 char const *yield = getenv ("LILYPOND_GC_YIELD");
591 bool overwrite = true;
598 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
599 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
600 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
602 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
603 "10485760", overwrite);
604 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
605 "104857600", overwrite);
608 vector<string> start_environment_global;
611 main (int argc, char **argv, char **envp)
615 for (char **p = envp; *p; p++)
616 start_environment_global.push_back (*p);
618 if (getenv ("LILYPOND_VERBOSE"))
619 set_loglevel (LOGLEVEL_DEBUG);
620 if (getenv ("LILYPOND_LOGLEVEL"))
621 set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
623 setup_localisation ();
624 parse_argv (argc, argv);
625 if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
628 setup_paths (argv[0]);
635 scm_boot_guile (argc, argv, main_with_guile, 0);
639 error (_f ("exception caught: %s", e.what ()));
642 scm_boot_guile (argc, argv, main_with_guile, 0);
645 /* Only reachable if GUILE exits. That is an error. */