2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2011 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 /* Provide URI links to the original file */
78 bool point_and_click_global = true;
80 /* Scheme code to execute before parsing, after .scm init.
81 This is where -e arguments are appended to. */
82 string init_scheme_code_global;
83 string init_scheme_variables_global;
85 bool relocate_binary = true;
88 * Miscellaneous global stuff.
90 File_path global_path;
96 static char const *AUTHORS
97 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
98 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
100 static char const *PROGRAM_NAME = "lilypond";
101 static char const *PROGRAM_URL = "http://lilypond.org";
103 static char const *NOTICE
104 = _i ("This program is free software. It is covered by the GNU General Public\n"
105 "License and you are welcome to change it and/or distribute copies of it\n"
106 "under certain conditions. Invoke as `%s --warranty' for more\n"
109 static char const *WARRANTY
110 = _i (" This program is free software; you can redistribute it and/or\n"
111 "modify it under the terms of the GNU General Public License as \n"
112 "published by the Free Software Foundation, either version 3 of\n"
113 "the License, or (at your option) any later version.\n"
115 " This program is distributed in the hope that it will be useful,\n"
116 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
117 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
118 "General Public License for more details.\n"
120 " You should have received a copy of the\n"
121 "GNU General Public License along with this program; if not, write to\n"
122 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
123 "Boston, MA 02111-1307, USA.\n");
125 /* Where the init files live. Typically:
126 LILYPOND_DATADIR = /usr/share/lilypond
128 string lilypond_datadir;
130 /* The jail specification: USER, GROUP, JAIL, DIR. */
133 /* The option parser */
134 static Getopt_long *option_parser = 0;
136 /* Internationalisation kludge in two steps:
137 * use _i () to get entry in POT file
138 * call gettext () explicitly for actual "translation" */
140 static Long_option_init options_static[]
144 _i ("SYM[=VAL]"), "define-default", 'd',
145 _i ("set Scheme option SYM to VAL (default: #t).\n"
146 "Use -dhelp for help.")
149 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
150 /* Bug in option parser: --output =foe is taken as an abbreviation
151 for --output-format. */
152 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
153 {0, "pdf", 0, _i ("generate PDF (default)")},
154 {0, "png", 0, _i ("generate PNG")},
155 {0, "ps", 0, _i ("generate PostScript")},
156 {0, "help", 'h', _i ("show this help and exit")},
158 _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
159 "named BASENAME.FIELD")
161 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
162 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
165 _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
170 _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
171 " LOGLEVEL. Possible values are:\n"
172 "NONE, ERROR, WARNING, BASIC, PROGRESS (default) and DEBUG.")
174 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
175 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
176 {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
177 {0, "version", 'v', _i ("show version number and exit")},
178 {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
179 {0, "warranty", 'w', _i ("show warranty and copyright")},
183 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
185 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
186 problems because the truncation from 80 bits to 64 bits can occur in
187 unpredictable places. To get around this, we tell the x87 FPU to use only
188 double precision. Note that this is not needed for x86_64 because that uses
189 the SSE unit by default instead of the x87 FPU. */
190 #if ((defined (__x86__) || defined (__i386__)) \
191 && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
193 #include <fpu_control.h>
197 fpu_control_t fpu_control = 0x027f;
198 _FPU_SETCW (fpu_control);
208 #endif /* defined(__x86__) || defined(__i386__) */
211 env_var_info (FILE *out, char const *key)
213 if (char const *value = getenv (key))
214 fprintf (out, "%s=\"%s\"\n", key, value);
221 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
222 env_var_info (out, "LILYPONDPREFIX");
223 env_var_info (out, "LILYPOND_DATADIR");
224 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
226 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
230 env_var_info (out, "FONTCONFIG_FILE");
231 env_var_info (out, "FONTCONFIG_PATH");
232 env_var_info (out, "GS_FONTPATH");
233 env_var_info (out, "GS_LIB");
234 env_var_info (out, "GUILE_LOAD_PATH");
235 env_var_info (out, "PANGO_RC_FILE");
236 env_var_info (out, "PANGO_PREFIX");
237 env_var_info (out, "PATH");
244 /* Do not update the copyright years here, run `make grand-replace' */
245 printf ("%s", (_f ("Copyright (c) %s by\n%s and others.", "1996--2011",
253 fputs (gnu_lilypond_version_string ().c_str (), out);
264 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
267 LY_DEFINE (ly_usage, "ly:usage",
269 "Print usage message.")
271 /* No version number or newline here. It confuses help2man. */
272 printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
274 printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
276 printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
278 printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
280 printf ("%s", (_ ("Options:").c_str ()));
282 printf ("%s", Long_option_init::table_string (options_static).c_str ());
284 /* Translators, please translate this string as
285 "Report bugs in English via %s",
286 or if there is a LilyPond users list or forum in your language
287 "Report bugs in English via %s or in YOUR_LANG via URI" */
288 printf ("%s", (_f ("Report bugs via %s",
289 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
293 return SCM_UNSPECIFIED;
303 printf ("%s", (_ (WARRANTY).c_str ()));
307 prepend_load_path (string dir)
309 string s = "(set! %load-path (cons \"" + dir + "\" %load-path))";
310 scm_c_eval_string (s.c_str ());
313 void init_global_tweak_registry ();
314 void init_fontconfig ();
320 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
321 we exit (this is a security-sensitive area). First we split
322 jail_spec into its components, then we retrieve the user/group id
323 (necessarily *before* chroot'ing) and finally we perform the
328 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
331 vector<string> components = string_split (jail_spec, ',');
332 if (components.size () != JAIL_MAX)
334 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
335 (unsigned) components.size ()));
343 if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
344 uid = passwd->pw_uid;
348 error (_f ("no such user: %s", components[USER_NAME]));
350 error (_f ("cannot get user id from user name: %s: %s",
351 components[USER_NAME],
360 if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
365 error (_f ("no such group: %s", components[GROUP_NAME]));
367 error (_f ("cannot get group id from group name: %s: %s",
368 components[GROUP_NAME],
373 if (chroot (components[JAIL].c_str ()))
375 error (_f ("cannot chroot to: %s: %s", components[JAIL],
382 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
388 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
392 if (chdir (components[DIR].c_str ()))
394 error (_f ("cannot change working directory to: %s: %s", components[DIR],
402 main_with_guile (void *, int, char **)
404 /* Engravers use lily.scm contents, need to make Guile find it.
405 Prepend onto GUILE %load-path, very ugh. */
407 prepend_load_path (lilypond_datadir);
408 prepend_load_path (lilypond_datadir + "/scm");
410 if (is_loglevel (LOG_DEBUG))
413 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
414 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
417 call_constructors ();
421 ly_reset_all_fonts ();
423 /* We accept multiple independent music files on the command line to
424 reduce compile time when processing lots of small files.
425 Starting the GUILE engine is very time consuming. */
429 while (char const *arg = option_parser->get_next_arg ())
431 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
432 tail = SCM_CDRLOC (*tail);
435 delete option_parser;
439 if (!jail_spec.empty ())
443 SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
451 setup_localisation ()
455 setlocale (LC_ALL, "");
457 /* FIXME: check if this is still true.
458 Disable localisation of float values. */
459 setlocale (LC_NUMERIC, "C");
461 string localedir = LOCALEDIR;
462 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
465 bindtextdomain ("lilypond", localedir.c_str ());
466 textdomain ("lilypond");
471 add_output_format (string format)
473 if (output_format_global != "")
474 output_format_global += ",";
475 output_format_global += format;
479 parse_argv (int argc, char **argv)
481 bool show_help = false;
482 option_parser = new Getopt_long (argc, argv, options_static);
483 while (Long_option_init const *opt = (*option_parser) ())
485 switch (opt->shortname_char_)
488 if (string (opt->longname_str0_) == "pdf"
489 || string (opt->longname_str0_) == "png"
490 || string (opt->longname_str0_) == "ps")
491 add_output_format (opt->longname_str0_);
492 else if (string (opt->longname_str0_) == "relocate")
493 relocate_binary = true;
498 string arg (option_parser->optional_argument_str0_);
499 ssize eq = arg.find ('=');
506 key = arg.substr (0, eq);
507 val = arg.substr (eq + 1, arg.length () - 1);
510 init_scheme_variables_global
511 += "(cons \'" + key + " '" + val + ")\n";
521 string s = option_parser->optional_argument_str0_;
522 File_name file_name (s);
523 output_name_global = file_name.to_string ();
527 jail_spec = option_parser->optional_argument_str0_;
531 init_scheme_code_global
532 += option_parser->optional_argument_str0_ + string (" ");
541 vector<string> components
542 = string_split (option_parser->optional_argument_str0_, ',');
543 for (vsize i = 0; i < components.size (); i++)
544 add_output_format (components[i]);
549 dump_header_fieldnames_global
550 .push_back (option_parser->optional_argument_str0_);
553 global_path.append (option_parser->optional_argument_str0_);
556 init_name_global = option_parser->optional_argument_str0_;
562 set_loglevel (LOGLEVEL_DEBUG);
565 set_loglevel (LOGLEVEL_ERROR);
568 set_loglevel (option_parser->optional_argument_str0_);
571 programming_error (to_string ("unhandled short option: %c",
572 opt->shortname_char_));
578 if (output_format_global == "")
579 output_format_global = "pdf";
584 if (is_loglevel (LOG_DEBUG))
593 char const *yield = getenv ("LILYPOND_GC_YIELD");
594 bool overwrite = true;
601 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
602 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
603 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
605 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
606 "10485760", overwrite);
607 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
608 "104857600", overwrite);
611 vector<string> start_environment_global;
614 main (int argc, char **argv, char **envp)
618 for (char **p = envp; *p; p++)
619 start_environment_global.push_back (*p);
621 if (getenv ("LILYPOND_VERBOSE"))
622 set_loglevel (LOGLEVEL_DEBUG);
623 if (getenv ("LILYPOND_LOGLEVEL"))
624 set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
626 setup_localisation ();
627 parse_argv (argc, argv);
628 if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
631 setup_paths (argv[0]);
638 scm_boot_guile (argc, argv, main_with_guile, 0);
642 error (_f ("exception caught: %s", e.what ()));
645 scm_boot_guile (argc, argv, main_with_guile, 0);
648 /* Only reachable if GUILE exits. That is an error. */