Fixes Issue 1504, allowing feather beam line breaking.
[lilypond/patrick.git] / lily / main.cc
blobd6ec34b1dcb9e4d325043f8630492d4c10d2b7ad
1 /*
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/>.
20 #include "main.hh"
22 #include <cassert>
23 #include <clocale>
24 #include <cstring>
25 #include <cerrno>
26 #include <cstdio>
27 using namespace std;
29 #include <unistd.h>
30 #include <sys/types.h>
31 #include "config.hh"
33 #if HAVE_GRP_H
34 #include <grp.h>
35 #endif
36 #if HAVE_PWD_H
37 #include <pwd.h>
38 #endif
39 #if HAVE_GETTEXT
40 #include <libintl.h>
41 #endif
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"
50 #include "misc.hh"
51 #include "output-def.hh"
52 #include "program-option.hh"
53 #include "relocate.hh"
54 #include "string-convert.hh"
55 #include "version.hh"
56 #include "warn.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;
69 /* Output formats to generate. */
70 string output_format_global = "";
72 /* Current output name. */
73 string output_name_global;
75 /* Run in safe mode? */
76 bool be_safe_global = false;
78 /* Provide URI links to the original file */
79 bool point_and_click_global = true;
81 /* Verbose progress indication? */
82 bool be_verbose_global = false;
84 /* Scheme code to execute before parsing, after .scm init.
85 This is where -e arguments are appended to. */
86 string init_scheme_code_global;
87 string init_scheme_variables_global;
89 bool relocate_binary = true;
93 * Miscellaneous global stuff.
95 File_path global_path;
98 * File globals.
101 static char const *AUTHORS
102 = " Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
103 " Jan Nieuwenhuizen <janneke@gnu.org>\n";
105 static char const *PROGRAM_NAME = "lilypond";
106 static char const *PROGRAM_URL = "http://lilypond.org";
108 static char const *NOTICE
109 = _i ("This program is free software. It is covered by the GNU General Public\n"
110 "License and you are welcome to change it and/or distribute copies of it\n"
111 "under certain conditions. Invoke as `%s --warranty' for more\n"
112 "information.\n");
114 static char const *WARRANTY
115 = _i (" This program is free software; you can redistribute it and/or\n"
116 "modify it under the terms of the GNU General Public License version 2\n"
117 "as published by the Free Software Foundation.\n"
118 "\n"
119 " This program is distributed in the hope that it will be useful,\n"
120 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
121 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n"
122 "General Public License for more details.\n"
123 "\n"
124 " You should have received a copy of the\n"
125 "GNU General Public License along with this program; if not, write to\n"
126 "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
127 "Boston, MA 02111-1307, USA.\n");
129 /* Where the init files live. Typically:
130 LILYPOND_DATADIR = /usr/share/lilypond
132 string lilypond_datadir;
134 /* The jail specification: USER, GROUP, JAIL, DIR. */
135 string jail_spec;
137 /* The option parser */
138 static Getopt_long *option_parser = 0;
140 /* Internationalisation kludge in two steps:
141 * use _i () to get entry in POT file
142 * call gettext () explicitly for actual "translation" */
144 static Long_option_init options_static[]
146 {_i ("SYM[=VAL]"), "define-default", 'd',
147 _i ("set Scheme option SYM to VAL (default: #t).\n"
148 "Use -dhelp for help.")},
150 {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
151 /* Bug in option parser: --output =foe is taken as an abbreviation
152 for --output-format. */
153 {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,... Also as separate options:")},
154 {0, "pdf", 0, _i ("generate PDF (default)")},
155 {0, "png", 0, _i ("generate PNG")},
156 {0, "ps", 0, _i ("generate PostScript")},
157 {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")},
160 {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
161 {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
162 #if HAVE_CHROOT
163 {_i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
164 "and cd into DIR")},
165 #endif
166 {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
167 {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
168 {0, "version", 'v', _i ("show version number and exit")},
169 {0, "verbose", 'V', _i ("be verbose")},
170 {0, "warranty", 'w', _i ("show warranty and copyright")},
171 {0, 0, 0, 0}
174 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
177 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
178 problems because the truncation from 80 bits to 64 bits can occur in
179 unpredictable places. To get around this, we tell the x87 FPU to use only
180 double precision. Note that this is not needed for x86_64 because that uses
181 the SSE unit by default instead of the x87 FPU. */
182 #if ((defined(__x86__) || defined(__i386__)) \
183 && defined(HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
185 #include <fpu_control.h>
186 static void
187 configure_fpu ()
189 fpu_control_t fpu_control = 0x027f;
190 _FPU_SETCW (fpu_control);
193 #else
195 static void
196 configure_fpu ()
200 #endif /* defined(__x86__) || defined(__i386__) */
203 static void
204 env_var_info (FILE *out, char const *key)
206 if (char const *value = getenv (key))
207 fprintf (out, "%s=\"%s\"\n", key, value);
210 static void
211 dir_info (FILE *out)
213 fputs ("\n", out);
214 fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
215 env_var_info (out, "LILYPONDPREFIX");
216 env_var_info (out, "LILYPOND_DATADIR");
217 fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
219 fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
221 if (relocate_binary)
223 env_var_info (out, "FONTCONFIG_FILE");
224 env_var_info (out, "FONTCONFIG_PATH");
225 env_var_info (out, "GS_FONTPATH");
226 env_var_info (out, "GS_LIB");
227 env_var_info (out, "GUILE_LOAD_PATH");
228 env_var_info (out, "PANGO_RC_FILE");
229 env_var_info (out, "PANGO_PREFIX");
230 env_var_info (out, "PATH");
234 static void
235 copyright ()
237 /* Do not update the copyright years here, run `make grand-replace' */
238 printf ("%s", (_f ("Copyright (c) %s by\n%s and others.", "1996--2011",
239 AUTHORS).c_str ()));
240 printf ("\n");
243 static void
244 identify (FILE *out)
246 fputs (gnu_lilypond_version_string ().c_str (), out);
247 fputs ("\n", out);
250 static void
251 notice ()
253 identify (stdout);
254 printf ("\n");
255 copyright ();
256 printf ("\n");
257 puts (_f (NOTICE, PROGRAM_NAME).c_str ());
260 LY_DEFINE (ly_usage, "ly:usage",
261 0, 0, 0, (),
262 "Print usage message.")
264 /* No version number or newline here. It confuses help2man. */
265 printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
266 printf ("\n\n");
267 printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
268 printf ("\n\n");
269 printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
270 printf ("\n");
271 printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
272 printf ("\n\n");
273 printf ("%s", (_ ("Options:").c_str ()));
274 printf ("\n");
275 printf ("%s", Long_option_init::table_string (options_static).c_str ());
276 printf ("\n");
277 /* Translators, please translate this string as
278 "Report bugs in English via %s",
279 or if there is a LilyPond users list or forum in your language
280 "Report bugs in English via %s or in YOUR_LANG via URI" */
281 printf ("%s", (_f ("Report bugs via %s",
282 "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
283 ).c_str ()));
284 printf ("\n");
285 printf ("\n");
286 return SCM_UNSPECIFIED;
289 static void
290 warranty ()
292 identify (stdout);
293 printf ("\n");
294 copyright ();
295 printf ("\n");
296 printf ("%s", (_ (WARRANTY).c_str ()));
299 static void
300 prepend_load_path (string dir)
302 string s = "(set! %load-path (cons \"" + dir + "\" %load-path))";
303 scm_c_eval_string (s.c_str ());
306 void init_global_tweak_registry ();
307 void init_fontconfig ();
309 #if HAVE_CHROOT
310 static void
311 do_chroot_jail ()
313 /* Now we chroot, setuid/setgrp and chdir. If something goes wrong,
314 we exit (this is a security-sensitive area). First we split
315 jail_spec into its components, then we retrieve the user/group id
316 (necessarily *before* chroot'ing) and finally we perform the
317 actual actions. */
319 enum Jail
321 USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
324 vector<string> components = string_split (jail_spec, ',');
325 if (components.size () != JAIL_MAX)
327 error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
328 (unsigned) components.size ()));
329 exit (2);
332 /* Hmm. */
333 errno = 0;
335 int uid;
336 if (passwd * passwd = getpwnam (components[USER_NAME].c_str ()))
337 uid = passwd->pw_uid;
338 else
340 if (errno == 0)
341 error (_f ("no such user: %s", components[USER_NAME]));
342 else
343 error (_f ("cannot get user id from user name: %s: %s",
344 components[USER_NAME],
345 strerror (errno)));
346 exit (3);
349 /* Hmm. */
350 errno = 0;
352 int gid;
353 if (group * group = getgrnam (components[GROUP_NAME].c_str ()))
354 gid = group->gr_gid;
355 else
357 if (errno == 0)
358 error (_f ("no such group: %s", components[GROUP_NAME]));
359 else
360 error (_f ("cannot get group id from group name: %s: %s",
361 components[GROUP_NAME],
362 strerror (errno)));
363 exit (3);
366 if (chroot (components[JAIL].c_str ()))
368 error (_f ("cannot chroot to: %s: %s", components[JAIL],
369 strerror (errno)));
370 exit (3);
373 if (setgid (gid))
375 error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
376 exit (3);
379 if (setuid (uid))
381 error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
382 exit (3);
385 if (chdir (components[DIR].c_str ()))
387 error (_f ("cannot change working directory to: %s: %s", components[DIR],
388 strerror (errno)));
389 exit (3);
392 #endif
394 static void
395 main_with_guile (void *, int, char **)
397 /* Engravers use lily.scm contents, need to make Guile find it.
398 Prepend onto GUILE %load-path, very ugh. */
400 prepend_load_path (lilypond_datadir);
401 prepend_load_path (lilypond_datadir + "/scm");
403 if (be_verbose_global)
404 dir_info (stderr);
406 init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
407 init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
409 ly_c_init_guile ();
410 call_constructors ();
411 init_fontconfig ();
413 init_freetype ();
414 ly_reset_all_fonts ();
416 /* We accept multiple independent music files on the command line to
417 reduce compile time when processing lots of small files.
418 Starting the GUILE engine is very time consuming. */
420 SCM files = SCM_EOL;
421 SCM *tail = &files;
422 while (char const *arg = option_parser->get_next_arg ())
424 *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
425 tail = SCM_CDRLOC (*tail);
428 delete option_parser;
429 option_parser = 0;
431 #if HAVE_CHROOT
432 if (!jail_spec.empty ())
433 do_chroot_jail ();
434 #endif
436 SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
437 (void) result;
439 /* Unreachable. */
440 exit (0);
443 static void
444 setup_localisation ()
446 #if HAVE_GETTEXT
447 /* Enable locales */
448 setlocale (LC_ALL, "");
450 /* FIXME: check if this is still true.
451 Disable localisation of float values. */
452 setlocale (LC_NUMERIC, "C");
454 string localedir = LOCALEDIR;
455 if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
456 localedir = env;
458 bindtextdomain ("lilypond", localedir.c_str ());
459 textdomain ("lilypond");
460 #endif
463 static void
464 add_output_format (string format)
466 if (output_format_global != "")
467 output_format_global += ",";
468 output_format_global += format;
471 static void
472 parse_argv (int argc, char **argv)
474 bool show_help = false;
475 option_parser = new Getopt_long (argc, argv, options_static);
476 while (Long_option_init const *opt = (*option_parser) ())
478 switch (opt->shortname_char_)
480 case 0:
481 if (string (opt->longname_str0_) == "pdf"
482 || string (opt->longname_str0_) == "png"
483 || string (opt->longname_str0_) == "ps")
484 add_output_format (opt->longname_str0_);
485 else if (string (opt->longname_str0_) == "relocate")
486 relocate_binary = true;
487 break;
489 case 'd':
491 string arg (option_parser->optional_argument_str0_);
492 ssize eq = arg.find ('=');
494 string key = arg;
495 string val = "#t";
497 if (eq != NPOS)
499 key = arg.substr (0, eq);
500 val = arg.substr (eq + 1, arg.length () - 1);
503 init_scheme_variables_global
504 += "(cons \'" + key + " '" + val + ")\n";
506 break;
508 case 'v':
509 notice ();
510 exit (0);
511 break;
512 case 'o':
514 string s = option_parser->optional_argument_str0_;
515 File_name file_name (s);
516 output_name_global = file_name.to_string ();
518 break;
519 case 'j':
520 jail_spec = option_parser->optional_argument_str0_;
521 break;
523 case 'e':
524 init_scheme_code_global
525 += option_parser->optional_argument_str0_ + string (" ");
526 break;
527 case 'w':
528 warranty ();
529 exit (0);
530 break;
532 case 'f':
534 vector<string> components
535 = string_split (option_parser->optional_argument_str0_, ',');
536 for (vsize i = 0; i < components.size (); i++)
537 add_output_format (components[i]);
539 break;
541 case 'H':
542 dump_header_fieldnames_global
543 .push_back (option_parser->optional_argument_str0_);
544 break;
545 case 'I':
546 global_path.append (option_parser->optional_argument_str0_);
547 break;
548 case 'i':
549 init_name_global = option_parser->optional_argument_str0_;
550 break;
551 case 'h':
552 show_help = true;
553 break;
554 case 'V':
555 be_verbose_global = true;
556 break;
557 default:
558 programming_error (to_string ("unhandled short option: %c",
559 opt->shortname_char_));
560 assert (false);
561 break;
565 if (output_format_global == "")
566 output_format_global = "pdf";
568 if (show_help)
570 ly_usage ();
571 if (be_verbose_global)
572 dir_info (stdout);
573 exit (0);
577 void
578 setup_guile_env ()
580 char const *yield = getenv ("LILYPOND_GC_YIELD");
581 bool overwrite = true;
582 if (!yield)
584 yield = "65";
585 overwrite = false;
588 sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
589 sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
590 sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
593 sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
594 "10485760", overwrite);
595 sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
596 "104857600", overwrite);
599 vector<string> start_environment_global;
602 main (int argc, char **argv, char **envp)
604 configure_fpu();
606 for (char **p = envp; *p; p++)
607 start_environment_global.push_back(*p);
609 if (getenv ("LILYPOND_VERBOSE"))
610 be_verbose_global = true;
612 setup_localisation ();
613 parse_argv (argc, argv);
614 if (isatty (STDIN_FILENO))
615 identify (stderr);
617 setup_paths (argv[0]);
618 setup_guile_env ();
620 #if 0
621 /* Debugging aid. */
624 scm_boot_guile (argc, argv, main_with_guile, 0);
626 catch (exception e)
628 error (_f ("exception caught: %s", e.what ()));
630 #else
631 scm_boot_guile (argc, argv, main_with_guile, 0);
632 #endif
634 /* Only reachable if GUILE exits. That is an error. */
635 return 1;