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"
62 static char const *AUTHORS
63 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
64 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
66 static char const *PROGRAM_NAME = "lilypond";
67 static char const *PROGRAM_URL = "http://lilypond.org";
69 static char const *NOTICE
70 = _i ("This program is free software. It is covered by the GNU General Public\n"
71 "License and you are welcome to change it and/or distribute copies of it\n"
72 "under certain conditions. Invoke as `%s --warranty' for more\n"
75 static char const *WARRANTY
76 = _i (" This program is free software; you can redistribute it and/or\n"
77 "modify it under the terms of the GNU General Public License as \n"
78 "published by the Free Software Foundation, either version 3 of\n"
79 "the License, or (at your option) any later version.\n"
81 " This program is distributed in the hope that it will be useful,\n"
82 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
83 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
84 "General Public License for more details.\n"
86 " You should have received a copy of the\n"
87 "GNU General Public License along with this program; if not, write to\n"
88 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
89 "Boston, MA 02111-1307, USA.\n");
91 /* The jail specification: USER, GROUP, JAIL, DIR. */
92 static string jail_spec;
94 /* The option parser */
95 static Getopt_long *option_parser = 0;
97 /* Internationalisation kludge in two steps:
98 * use _i () to get entry in POT file
99 * call gettext () explicitly for actual "translation" */
101 static Long_option_init options_static[]
105 _i ("SYM[=VAL]"), "define-default", 'd',
106 _i ("set Scheme option SYM to VAL (default: #t).\n"
107 "Use -dhelp for help.")
110 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
111 /* Bug in option parser: --output =foe is taken as an abbreviation
112 for --output-format. */
113 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
114 {0, "pdf", 0, _i ("generate PDF (default)")},
115 {0, "png", 0, _i ("generate PNG")},
116 {0, "ps", 0, _i ("generate PostScript")},
117 {0, "help", 'h', _i ("show this help and exit")},
119 _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
120 "named BASENAME.FIELD")
122 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
123 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
126 _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
131 _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
132 " LOGLEVEL. Possible values are:\n"
133 "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
135 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
136 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
137 {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
138 {0, "version", 'v', _i ("show version number and exit")},
139 {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
140 {0, "warranty", 'w', _i ("show warranty and copyright")},
144 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
146 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
147 problems because the truncation from 80 bits to 64 bits can occur in
148 unpredictable places. To get around this, we tell the x87 FPU to use only
149 double precision. Note that this is not needed for x86_64 because that uses
150 the SSE unit by default instead of the x87 FPU. */
151 #if ((defined (__x86__) || defined (__i386__)) \
152 && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
154 #include <fpu_control.h>
158 fpu_control_t fpu_control = 0x027f;
159 _FPU_SETCW (fpu_control);
169 #endif /* defined(__x86__) || defined(__i386__) */
172 env_var_info (FILE *out, char const *key)
174 if (char const *value = getenv (key))
175 fprintf (out, "%s=\"%s\"\n", key, value);
182 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
183 env_var_info (out, "LILYPONDPREFIX");
184 env_var_info (out, "LILYPOND_DATADIR");
185 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
187 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
191 env_var_info (out, "FONTCONFIG_FILE");
192 env_var_info (out, "FONTCONFIG_PATH");
193 env_var_info (out, "GS_FONTPATH");
194 env_var_info (out, "GS_LIB");
195 env_var_info (out, "GUILE_LOAD_PATH");
196 env_var_info (out, "PANGO_RC_FILE");
197 env_var_info (out, "PANGO_PREFIX");
198 env_var_info (out, "PATH");
205 /* Do not update the copyright years here, run `make grand-replace' */
206 printf ("%s", (_f ("Copyright (c) %s by\n%s and others.", "1996--2012",
214 fputs (gnu_lilypond_version_string ().c_str (), out);
225 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
228 LY_DEFINE (ly_usage, "ly:usage",
230 "Print usage message.")
232 /* No version number or newline here. It confuses help2man. */
233 printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
235 printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
237 printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
239 printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
241 printf ("%s", (_ ("Options:").c_str ()));
243 printf ("%s", Long_option_init::table_string (options_static).c_str ());
245 /* Translators, please translate this string as
246 "Report bugs in English via %s",
247 or if there is a LilyPond users list or forum in your language
248 "Report bugs in English via %s or in YOUR_LANG via URI" */
249 printf ("%s", (_f ("Report bugs via %s",
250 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
254 return SCM_UNSPECIFIED;
264 printf ("%s", (_ (WARRANTY).c_str ()));
268 prepend_load_path (string dir)
270 string s = "(set! %load-path (cons \"" + dir + "\" %load-path))";
271 scm_c_eval_string (s.c_str ());
274 void init_global_tweak_registry ();
275 void init_fontconfig ();
281 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
282 we exit (this is a security-sensitive area). First we split
283 jail_spec into its components, then we retrieve the user/group id
284 (necessarily *before* chroot'ing) and finally we perform the
289 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
292 vector<string> components = string_split (jail_spec, ',');
293 if (components.size () != JAIL_MAX)
295 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
296 (unsigned) components.size ()));
304 if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
305 uid = passwd->pw_uid;
309 error (_f ("no such user: %s", components[USER_NAME]));
311 error (_f ("cannot get user id from user name: %s: %s",
312 components[USER_NAME],
321 if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
326 error (_f ("no such group: %s", components[GROUP_NAME]));
328 error (_f ("cannot get group id from group name: %s: %s",
329 components[GROUP_NAME],
334 if (chroot (components[JAIL].c_str ()))
336 error (_f ("cannot chroot to: %s: %s", components[JAIL],
343 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
349 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
353 if (chdir (components[DIR].c_str ()))
355 error (_f ("cannot change working directory to: %s: %s", components[DIR],
363 main_with_guile (void *, int, char **)
365 /* Engravers use lily.scm contents, need to make Guile find it.
366 Prepend onto GUILE %load-path, very ugh. */
368 prepend_load_path (lilypond_datadir);
369 prepend_load_path (lilypond_datadir + "/scm");
371 if (is_loglevel (LOG_DEBUG))
374 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
375 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
378 call_constructors ();
382 ly_reset_all_fonts ();
384 /* We accept multiple independent music files on the command line to
385 reduce compile time when processing lots of small files.
386 Starting the GUILE engine is very time consuming. */
390 while (char const *arg = option_parser->get_next_arg ())
392 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
393 tail = SCM_CDRLOC (*tail);
396 delete option_parser;
400 if (!jail_spec.empty ())
404 SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
412 setup_localisation ()
416 setlocale (LC_ALL, "");
418 /* FIXME: check if this is still true.
419 Disable localisation of float values. */
420 setlocale (LC_NUMERIC, "C");
422 string localedir = LOCALEDIR;
423 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
426 bindtextdomain ("lilypond", localedir.c_str ());
427 textdomain ("lilypond");
432 add_output_format (string format)
434 if (output_format_global != "")
435 output_format_global += ",";
436 output_format_global += format;
440 parse_argv (int argc, char **argv)
442 bool show_help = false;
443 option_parser = new Getopt_long (argc, argv, options_static);
444 while (Long_option_init const *opt = (*option_parser) ())
446 switch (opt->shortname_char_)
449 if (string (opt->longname_str0_) == "pdf"
450 || string (opt->longname_str0_) == "png"
451 || string (opt->longname_str0_) == "ps")
452 add_output_format (opt->longname_str0_);
453 else if (string (opt->longname_str0_) == "relocate")
454 relocate_binary = true;
459 string arg (option_parser->optional_argument_str0_);
460 ssize eq = arg.find ('=');
467 key = arg.substr (0, eq);
468 val = arg.substr (eq + 1, arg.length () - 1);
471 init_scheme_variables_global
472 += "(cons \'" + key + " '" + val + ")\n";
482 string s = option_parser->optional_argument_str0_;
483 File_name file_name (s);
484 output_name_global = file_name.to_string ();
488 jail_spec = option_parser->optional_argument_str0_;
492 init_scheme_code_global
493 += option_parser->optional_argument_str0_ + string (" ");
502 vector<string> components
503 = string_split (option_parser->optional_argument_str0_, ',');
504 for (vsize i = 0; i < components.size (); i++)
505 add_output_format (components[i]);
510 dump_header_fieldnames_global
511 .push_back (option_parser->optional_argument_str0_);
514 global_path.append (option_parser->optional_argument_str0_);
517 init_name_global = option_parser->optional_argument_str0_;
523 set_loglevel (LOGLEVEL_DEBUG);
526 set_loglevel (LOGLEVEL_ERROR);
529 set_loglevel (option_parser->optional_argument_str0_);
532 programming_error (to_string ("unhandled short option: %c",
533 opt->shortname_char_));
539 if (output_format_global == "")
540 output_format_global = "pdf";
545 if (is_loglevel (LOG_DEBUG))
554 char const *yield = getenv ("LILYPOND_GC_YIELD");
555 bool overwrite = true;
562 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
563 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
564 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
566 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
567 "10485760", overwrite);
568 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
569 "104857600", overwrite);
573 main (int argc, char **argv, char **envp)
577 for (char **p = envp; *p; p++)
578 start_environment_global.push_back (*p);
580 if (getenv ("LILYPOND_VERBOSE"))
581 set_loglevel (LOGLEVEL_DEBUG);
582 if (getenv ("LILYPOND_LOGLEVEL"))
583 set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
585 setup_localisation ();
586 parse_argv (argc, argv);
587 if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
590 setup_paths (argv[0]);
597 scm_boot_guile (argc, argv, main_with_guile, 0);
601 error (_f ("exception caught: %s", e.what ()));
604 scm_boot_guile (argc, argv, main_with_guile, 0);
607 /* Only reachable if GUILE exits. That is an error. */