2 main.cc -- implement main () entrypoint.
4 source file of the GNU LilyPond music typesetter
6 (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
18 #include <sys/types.h>
31 #include "all-font-metrics.hh"
32 #include "file-name.hh"
33 #include "freetype.hh"
34 #include "getopt-long.hh"
35 #include "global-ctor.hh"
36 #include "international.hh"
37 #include "lily-version.hh"
39 #include "output-def.hh"
40 #include "program-option.hh"
41 #include "relocate.hh"
42 #include "string-convert.hh"
47 * Global options that can be overridden through command line.
50 /* Names of header fields to be dumped to a separate file. */
51 vector<string> dump_header_fieldnames_global;
53 /* Name of initialisation file. */
54 string init_name_global;
57 /* Output formats to generate. */
58 string output_format_global = "";
60 bool is_pango_format_global;
61 bool is_TeX_format_global;
63 /* Current output name. */
64 string output_name_global;
66 /* Run in safe mode? */
67 bool be_safe_global = false;
69 /* Provide URI links to the original file */
70 bool point_and_click_global = true;
72 /* Verbose progress indication? */
73 bool be_verbose_global = false;
75 /* Scheme code to execute before parsing, after .scm init.
76 This is where -e arguments are appended to. */
77 string init_scheme_code_global;
78 string init_scheme_variables_global;
80 bool relocate_binary = true;
84 * Miscellaneous global stuff.
86 File_path global_path;
92 static char const *AUTHORS
93 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
94 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
96 static char const *PROGRAM_NAME = "lilypond";
97 static char const *PROGRAM_URL = "http://lilypond.org";
99 static char const *NOTICE
100 = _i ("This program is free software. It is covered by the GNU General Public\n"
101 "License and you are welcome to change it and/or distribute copies of it\n"
102 "under certain conditions. Invoke as `%s --warranty' for more\n"
105 static char const *WARRANTY
106 = _i (" This program is free software; you can redistribute it and/or\n"
107 "modify it under the terms of the GNU General Public License version 2\n"
108 "as published by the Free Software Foundation.\n"
110 " This program is distributed in the hope that it will be useful,\n"
111 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
112 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
113 "General Public License for more details.\n"
115 " You should have received a copy of the\n"
116 "GNU General Public License along with this program; if not, write to\n"
117 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
118 "Boston, MA 02111-1307, USA.\n");
120 /* Where the init files live. Typically:
121 LILYPOND_DATADIR = /usr/share/lilypond
123 string lilypond_datadir;
125 /* The jail specification: USER, GROUP, JAIL, DIR. */
128 /* The option parser */
129 static Getopt_long *option_parser = 0;
131 /* Internationalisation kludge in two steps:
132 * use _i () to get entry in POT file
133 * call gettext () explicitely for actual "translation" */
135 static Long_option_init options_static[]
137 {_i ("SYM[=VAL]"), "define-default", 'd',
138 _i ("set Scheme option SYM to VAL (default: #t).\n"
139 "Use -dhelp for help.")},
141 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
142 /* Bug in option parser: --output =foe is taken as an abbreviation
143 for --output-format. */
144 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
145 {0, "dvi", 0, _i ("generate DVI (tex backend only)")},
146 {0, "pdf", 0, _i ("generate PDF (default)")},
147 {0, "png", 0, _i ("generate PNG")},
148 {0, "ps", 0, _i ("generate PostScript")},
149 {0, "tex", 0, _i ("generate TeX (tex backend only)")},
150 {0, "help", 'h', _i ("show this help and exit")},
151 {_i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
152 "named BASENAME.FIELD")},
153 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
154 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
156 {_i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
159 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
160 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
161 {0, "version", 'v', _i ("show version number and exit")},
162 {0, "verbose", 'V', _i ("be verbose")},
163 {0, "warranty", 'w', _i ("show warranty and copyright")},
167 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
170 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
171 problems because the truncation from 80 bits to 64 bits can occur in
172 unpredictable places. To get around this, we tell the x87 FPU to use only
173 double precision. Note that this is not needed for x86_64 because that uses
174 the SSE unit by default instead of the x87 FPU. */
175 #if defined(__x86__) || defined(__i386__)
177 #include <fpu_control.h>
178 static void configure_fpu() {
179 fpu_control_t fpu_control = 0x027f;
180 _FPU_SETCW (fpu_control);
185 static void configure_fpu() {
188 #endif /* defined(__x86__) || defined(__i386__) */
192 env_var_info (FILE *out, char const *key)
194 if (char const *value = getenv (key))
195 fprintf (out, "%s=\"%s\"\n", key, value);
202 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
203 env_var_info (out, "LILYPONDPREFIX");
204 env_var_info (out, "LILYPOND_DATADIR");
205 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
207 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
211 env_var_info (out, "FONTCONFIG_FILE");
212 env_var_info (out, "FONTCONFIG_PATH");
213 env_var_info (out, "GS_FONTPATH");
214 env_var_info (out, "GS_LIB");
215 env_var_info (out, "GUILE_LOAD_PATH");
216 env_var_info (out, "PANGO_RC_FILE");
217 env_var_info (out, "PANGO_PREFIX");
218 env_var_info (out, "PATH");
225 printf (_f ("Copyright (c) %s by\n%s and others.",
234 fputs (gnu_lilypond_version_string ().c_str (), out);
242 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
247 LY_DEFINE (ly_usage, "ly:usage",
249 "Print usage message.")
251 /* No version number or newline here. It confuses help2man. */
252 printf (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ());
254 printf (_ ("Typeset music and/or produce MIDI from FILE.").c_str ());
256 printf (_ ("LilyPond produces beautiful music notation.").c_str ());
258 printf (_f ("For more information, see %s", PROGRAM_URL).c_str ());
260 printf (_ ("Options:").c_str ());
262 printf (Long_option_init::table_string (options_static).c_str ());
264 printf (_f ("Report bugs via %s",
265 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
269 return SCM_UNSPECIFIED;
279 printf (_ (WARRANTY).c_str ());
283 prepend_load_path (string dir)
285 string s = "(set! %load-path (cons \"" + dir + "\" %load-path))";
286 scm_c_eval_string (s.c_str ());
289 void init_global_tweak_registry ();
290 void init_fontconfig ();
296 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
297 we exit (this is a security-sensitive area). First we split
298 jail_spec into its components, then we retrieve the user/group id
299 (necessarily *before* chroot'ing) and finally we perform the
304 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
307 vector<string> components = string_split (jail_spec, ',');
308 if (components.size () != JAIL_MAX)
310 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
311 (unsigned) components.size ()));
319 if (passwd * passwd = getpwnam (components[USER_NAME].c_str ()))
320 uid = passwd->pw_uid;
324 error (_f ("no such user: %s", components[USER_NAME]));
326 error (_f ("cannot get user id from user name: %s: %s",
327 components[USER_NAME],
336 if (group * group = getgrnam (components[GROUP_NAME].c_str ()))
341 error (_f ("no such group: %s", components[GROUP_NAME]));
343 error (_f ("cannot get group id from group name: %s: %s",
344 components[GROUP_NAME],
349 if (chroot (components[JAIL].c_str ()))
351 error (_f ("cannot chroot to: %s: %s", components[JAIL],
358 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
364 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
368 if (chdir (components[DIR].c_str ()))
370 error (_f ("cannot change working directory to: %s: %s", components[DIR],
378 main_with_guile (void *, int, char **)
380 /* Engravers use lily.scm contents, need to make Guile find it.
381 Prepend onto GUILE %load-path, very ugh. */
383 prepend_load_path (lilypond_datadir);
384 prepend_load_path (lilypond_datadir + "/scm");
386 if (be_verbose_global)
389 is_pango_format_global = !is_TeX_format_global;
390 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
391 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
394 call_constructors ();
398 ly_reset_all_fonts ();
400 is_TeX_format_global = (get_output_backend_name () == "tex"
401 || get_output_backend_name () == "texstr");
404 /* We accept multiple independent music files on the command line to
405 reduce compile time when processing lots of small files.
406 Starting the GUILE engine is very time consuming. */
410 while (char const *arg = option_parser->get_next_arg ())
412 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
413 tail = SCM_CDRLOC (*tail);
416 delete option_parser;
420 if (!jail_spec.empty ())
424 SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
432 setup_localisation ()
436 setlocale (LC_ALL, "");
438 /* FIXME: check if this is still true.
439 Disable localisation of float values. This breaks TeX output. */
440 setlocale (LC_NUMERIC, "C");
442 string localedir = LOCALEDIR;
443 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
446 bindtextdomain ("lilypond", localedir.c_str ());
447 textdomain ("lilypond");
452 add_output_format (string format)
454 if (output_format_global != "")
455 output_format_global += ",";
456 output_format_global += format;
460 parse_argv (int argc, char **argv)
462 bool show_help = false;
463 option_parser = new Getopt_long (argc, argv, options_static);
464 while (Long_option_init const *opt = (*option_parser) ())
466 switch (opt->shortname_char_)
469 if (string (opt->longname_str0_) == "dvi"
470 || string (opt->longname_str0_) == "pdf"
471 || string (opt->longname_str0_) == "png"
472 || string (opt->longname_str0_) == "ps"
473 || string (opt->longname_str0_) == "tex")
474 add_output_format (opt->longname_str0_);
475 else if (string (opt->longname_str0_) == "relocate")
476 relocate_binary = true;
481 string arg (option_parser->optional_argument_str0_);
482 ssize eq = arg.find ('=');
489 key = arg.substr (0, eq);
490 val = arg.substr (eq + 1, arg.length () - 1);
493 init_scheme_variables_global
494 += "(cons \'" + key + " '" + val + ")\n";
504 string s = option_parser->optional_argument_str0_;
505 File_name file_name (s);
506 output_name_global = file_name.to_string ();
510 jail_spec = option_parser->optional_argument_str0_;
514 init_scheme_code_global += option_parser->optional_argument_str0_ + string (" ");
523 vector<string> components
524 = string_split (option_parser->optional_argument_str0_, ',');
525 for (vsize i = 0; i < components.size (); i++)
526 add_output_format (components[i]);
531 dump_header_fieldnames_global
532 .push_back (option_parser->optional_argument_str0_);
535 global_path.append (option_parser->optional_argument_str0_);
538 init_name_global = option_parser->optional_argument_str0_;
544 be_verbose_global = true;
547 programming_error (to_string ("unhandled short option: %c",
548 opt->shortname_char_));
554 if (output_format_global == "")
555 output_format_global = "pdf";
561 if (be_verbose_global)
570 const char *yield = getenv ("LILYPOND_GC_YIELD");
571 bool overwrite = true;
578 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
579 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
580 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
583 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
584 "10485760", overwrite);
585 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
586 "104857600", overwrite);
589 vector<string> start_environment_global;
592 main (int argc, char **argv, char **envp)
596 for (char **p = envp; *p; p++)
597 start_environment_global.push_back(*p);
599 if (getenv ("LILYPOND_VERBOSE"))
600 be_verbose_global = true;
602 setup_localisation ();
603 parse_argv (argc, argv);
604 if (isatty (STDIN_FILENO))
607 setup_paths (argv[0]);
614 scm_boot_guile (argc, argv, main_with_guile, 0);
618 error (_f ("exception caught: %s", e.what ()));
621 scm_boot_guile (argc, argv, main_with_guile, 0);
624 /* Only reachable if GUILE exits. That is an error. */