]> git.donarmstrong.com Git - lilypond.git/blob - lily/main.cc
Revert "Issue 4550 (2/2) Avoid "using namespace std;" in included files"
[lilypond.git] / lily / main.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
5
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.
10
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.
15
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/>.
18 */
19
20 #include "main.hh"
21 #include "lily-guile.hh"
22
23 #include <cassert>
24 #include <clocale>
25 #include <cstring>
26 #include <cerrno>
27 #include <cstdio>
28 using namespace std;
29
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include "config.hh"
33
34 #if HAVE_GRP_H
35 #include <grp.h>
36 #endif
37 #if HAVE_PWD_H
38 #include <pwd.h>
39 #endif
40 #if HAVE_GETTEXT
41 #include <libintl.h>
42 #endif
43
44 #include "all-font-metrics.hh"
45 #include "file-name.hh"
46 #include "freetype.hh"
47 #include "getopt-long.hh"
48 #include "global-ctor.hh"
49 #include "international.hh"
50 #include "lily-version.hh"
51 #include "misc.hh"
52 #include "output-def.hh"
53 #include "program-option.hh"
54 #include "relocate.hh"
55 #include "string-convert.hh"
56 #include "version.hh"
57 #include "warn.hh"
58 #include "lily-imports.hh"
59
60 /*
61  * Global options that can be overridden through command line.
62  */
63
64 /* Names of header fields to be dumped to a separate file. */
65 //vector<string> dump_header_fieldnames_global; // moved to global-data.cc
66
67 /* Name of initialisation file. */
68 //string init_name_global; // moved to global-data.cc
69
70 /* Output formats to generate.  */
71 //string output_format_global = ""; // moved to global-data.cc
72
73 /* Current output name. */
74 //string output_name_global; // moved to global-data.cc
75
76 /* Run in safe mode? */
77 //bool be_safe_global = false; // moved to global-data.cc
78
79 /* Provide URI links to the original file */
80 bool point_and_click_global = true;
81
82 /* Scheme code to execute before parsing, after .scm init.
83    This is where -e arguments are appended to.  */
84 //string init_scheme_code_global; // moved to global-data.cc
85 //string init_scheme_variables_global; // moved to global-data.cc
86
87 //bool relocate_binary = true; // moved to global-data.cc
88
89 /*
90  * Miscellaneous global stuff.
91  */
92 //File_path global_path; // moved to global-data.cc
93
94 /*
95  * File globals.
96  */
97
98 static char const *AUTHORS
99   = "  Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
100     "  Jan Nieuwenhuizen <janneke@gnu.org>\n";
101
102 static char const *PROGRAM_NAME = "lilypond";
103 static char const *PROGRAM_URL = "http://lilypond.org";
104
105 static char const *NOTICE
106   = _i ("This program is free software.  It is covered by the GNU General Public\n"
107         "License and you are welcome to change it and/or distribute copies of it\n"
108         "under certain conditions.  Invoke as `%s --warranty' for more\n"
109         "information.\n");
110
111 static char const *WARRANTY
112   = _i ("    This program is free software; you can redistribute it and/or\n"
113         "modify it under the terms of the GNU General Public License as \n"
114         "published by the Free Software Foundation, either version 3 of\n"
115         "the License, or (at your option) any later version.\n"
116         "\n"
117         "    This program is distributed in the hope that it will be useful,\n"
118         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
119         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
120         "General Public License for more details.\n"
121         "\n"
122         "    You should have received a copy of the\n"
123         "GNU General Public License along with this program; if not, write to\n"
124         "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
125         "Boston, MA 02111-1307, USA.\n");
126
127 /* Where the init files live.  Typically:
128    LILYPOND_DATADIR = /usr/share/lilypond
129 */
130 //string lilypond_datadir; // moved to global-data.cc
131
132 /* The jail specification: USER, GROUP, JAIL, DIR. */
133 std::string jail_spec;
134
135 /*  The option parser */
136 static Getopt_long *option_parser = 0;
137
138 /* Internationalisation kludge in two steps:
139  * use _i () to get entry in POT file
140  * call gettext () explicitly for actual "translation"  */
141
142 /*
143   Data to be used to display when
144   -h command line option is detected.
145 */
146 static Long_option_init options_static[]
147 =
148 {
149   {
150     _i ("SYM[=VAL]"), "define-default", 'd',
151     _i ("set Scheme option SYM to VAL (default: #t).\n"
152     "Use -dhelp for help.")
153   },
154
155   {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
156   /* Bug in option parser: --output =foe is taken as an abbreviation
157      for --output-format.  */
158   {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,...  Also as separate options:")},
159   {0, "pdf", 0, _i ("generate PDF (default)")},
160   {0, "png", 0, _i ("generate PNG")},
161   {0, "ps", 0, _i ("generate PostScript")},
162   {0, "bigpdfs", 'b', _i("generate big PDF files")},
163   {0, "help", 'h', _i ("show this help and exit")},
164   {
165     _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
166     "named BASENAME.FIELD")
167   },
168   {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
169   {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
170 #if HAVE_CHROOT
171   {
172     _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
173     "and cd into DIR")
174   },
175 #endif
176   {
177     _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
178     " LOGLEVEL.  Possible values are:\n"
179     "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
180   },
181   {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
182   {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
183   {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
184   {0, "version", 'v', _i ("show version number and exit")},
185   {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
186   {0, "warranty", 'w', _i ("show warranty and copyright")},
187   {0, 0, 0, 0}
188 };
189
190 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
191
192 /* x86 defaults to using 80-bit extended precision arithmetic. This can cause
193    problems because the truncation from 80 bits to 64 bits can occur in
194    unpredictable places. To get around this, we tell the x87 FPU to use only
195    double precision. Note that this is not needed for x86_64 because that uses
196    the SSE unit by default instead of the x87 FPU. */
197 #if ((defined (__x86__) || defined (__i386__)) \
198   && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
199
200 #include <fpu_control.h>
201 static void
202 configure_fpu ()
203 {
204   fpu_control_t fpu_control = 0x027f;
205   _FPU_SETCW (fpu_control);
206 }
207
208 #else
209
210 static void
211 configure_fpu ()
212 {
213 }
214
215 #endif /* defined(__x86__) || defined(__i386__) */
216
217 using std::map;
218 using std::string;
219 using std::vector;
220
221 static void
222 env_var_info (FILE *out, char const *key)
223 /*
224  * Retrieve value of an OS environment variable.
225  * Parameter:
226  *  key, the name of an environment variable.
227  */
228 {
229   if (char const *value = getenv (key))
230     fprintf (out, "%s=\"%s\"\n", key, value);
231 }
232
233 static void
234 dir_info (FILE *out)
235 /*
236  * Print out information re directories being used by LilyPond
237  * for this session.
238  */
239 {
240   fputs ("\n", out);
241   fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
242   env_var_info (out, "LILYPONDPREFIX");
243   env_var_info (out, "LILYPOND_DATADIR");
244   fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
245
246   fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
247
248   if (relocate_binary)
249     {
250       env_var_info (out, "FONTCONFIG_FILE");
251       env_var_info (out, "FONTCONFIG_PATH");
252       env_var_info (out, "GS_FONTPATH");
253       env_var_info (out, "GS_LIB");
254       env_var_info (out, "GUILE_LOAD_PATH");
255       env_var_info (out, "PANGO_RC_FILE");
256       env_var_info (out, "PANGO_PREFIX");
257       env_var_info (out, "PATH");
258     }
259 }
260
261 static void
262 copyright ()
263 /*
264  * Print out LilyPond copyright info.
265  */
266 {
267   /* Do not update the copyright years here, run `make grand-replace'  */
268   printf ("%s", (_f ("Copyright (c) %s by\n%s  and others.", "1996--2015",
269                      AUTHORS).c_str ()));
270   printf ("\n");
271 }
272
273 static void
274 identify (FILE *out)
275 /*
276  * Print out LilyPond version string.
277  */
278 {
279   fputs (gnu_lilypond_version_string ().c_str (), out);
280   fputs ("\n", out);
281 }
282
283 static void
284 /*
285  * Print copyright and program name
286  */
287 notice ()
288 {
289   identify (stdout);
290   printf ("\n");
291   copyright ();
292   printf ("\n");
293   puts (_f (NOTICE, PROGRAM_NAME).c_str ());
294 }
295
296 LY_DEFINE (ly_usage, "ly:usage",
297            0, 0, 0, (),
298            "Print usage message.")
299 /*
300  * ly_usage: Routine to output standard information when LilyPond is run without a
301  * source file to compile.
302  * Also callable as ly:usage from Scheme.
303  */
304 {
305   /* No version number or newline here.  It confuses help2man.  */
306   printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
307   printf ("\n\n");
308   printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
309   printf ("\n\n");
310   printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
311   printf ("\n");
312   printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
313   printf ("\n\n");
314   printf ("%s", (_ ("Options:").c_str ()));
315   printf ("\n");
316   printf ("%s", Long_option_init::table_string (options_static).c_str ());
317   printf ("\n");
318   /* Translators, please translate this string as
319      "Report bugs in English via %s",
320      or if there is a LilyPond users list or forum in your language
321      "Report bugs in English via %s or in YOUR_LANG via URI"  */
322   printf ("%s", (_f ("Report bugs via %s",
323                      "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
324                     ).c_str ()));
325   printf ("\n");
326   printf ("\n");
327   return SCM_UNSPECIFIED;
328 }
329
330 static void
331 warranty ()
332 /*
333  * Prints out LilyPond warranty information
334  */
335 {
336   identify (stdout);
337   printf ("\n");
338   copyright ();
339   printf ("\n");
340   printf ("%s", (_ (WARRANTY).c_str ()));
341 }
342
343 static void
344 prepend_scheme_list (const string &dir, const string &scmlist)
345 /*
346  *  Inserts an item at the front of a Scheme list, e.g. %load-path
347  *  Parameters:
348  *    dir:     The directory to add to the front of the list
349  *    scmlist: The Scheme list onto which to prepend the directory
350  */
351 {
352   SCM var = scm_c_lookup (scmlist.c_str());
353   scm_variable_set_x (var, scm_cons (scm_from_locale_string (dir.c_str()),
354                                      scm_variable_ref (var)));
355   /*  string setcmd =
356              "(set! " + scmlist + " (cons \"" + dir + "\" " + scmlist +"))";
357              scm_c_eval_string (setcmd.c_str());*/
358 }
359
360 void init_global_tweak_registry ();
361 void init_fontconfig ();
362
363 #if HAVE_CHROOT
364 static void
365 do_chroot_jail ()
366 {
367   /* Now we chroot, setuid/setgrp and chdir.  If something goes wrong,
368      we exit (this is a security-sensitive area).  First we split
369      jail_spec into its components, then we retrieve the user/group id
370      (necessarily *before* chroot'ing) and finally we perform the
371      actual actions.  */
372
373   enum Jail
374   {
375     USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
376   };
377
378   vector<string> components = string_split (jail_spec, ',');
379   if (components.size () != JAIL_MAX)
380     {
381       error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
382                  (unsigned) components.size ()));
383       exit (2);
384     }
385
386   /* Hmm.  */
387   errno = 0;
388
389   int uid;
390   if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
391     uid = passwd->pw_uid;
392   else
393     {
394       if (errno == 0)
395         error (_f ("no such user: %s", components[USER_NAME]));
396       else
397         error (_f ("cannot get user id from user name: %s: %s",
398                    components[USER_NAME],
399                    strerror (errno)));
400       exit (3);
401     }
402
403   /* Hmm.  */
404   errno = 0;
405
406   int gid;
407   if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
408     gid = group->gr_gid;
409   else
410     {
411       if (errno == 0)
412         error (_f ("no such group: %s", components[GROUP_NAME]));
413       else
414         error (_f ("cannot get group id from group name: %s: %s",
415                    components[GROUP_NAME],
416                    strerror (errno)));
417       exit (3);
418     }
419
420   if (chroot (components[JAIL].c_str ()))
421     {
422       error (_f ("cannot chroot to: %s: %s", components[JAIL],
423                  strerror (errno)));
424       exit (3);
425     }
426
427   if (setgid (gid))
428     {
429       error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
430       exit (3);
431     }
432
433   if (setuid (uid))
434     {
435       error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
436       exit (3);
437     }
438
439   if (chdir (components[DIR].c_str ()))
440     {
441       error (_f ("cannot change working directory to: %s: %s", components[DIR],
442                  strerror (errno)));
443       exit (3);
444     }
445 }
446 #endif
447
448 static void
449 main_with_guile (void *, int, char **)
450 /*
451  * main-with-guile is invoked as a callback via scm_boot_guile from
452  * main.
453  * scm_boot_guile will have passed its data, argc and argv parameters
454  * to main_with_guile.
455  */
456 {
457   /* Engravers use lily.scm contents, so we need to make Guile find it.
458      Prepend onto GUILE %load-path.
459       %load-path is the symbol Guile searches for .scm files
460       %load-compiled-path is the symbol Guile V2 searches for .go files
461    */
462    string scm_pct_load_path = "%load-path";
463    string scm_pct_load_compiled_path = "%load-compiled-path";
464
465    prepend_scheme_list (lilypond_datadir, scm_pct_load_path );
466    prepend_scheme_list (lilypond_datadir + "/scm", scm_pct_load_path);
467
468 #if (GUILE2)
469    /*
470      Just as ughy - prepend "/scm/out" onto GUILE V2+ %load-compiled-path
471      and set %compile-fallback-path to our scm/out directory
472    */
473    /*
474      %load-compiled-path is the symbol Guile V2 searches for .go files
475    */
476    prepend_scheme_list (lilypond_datadir + "/scm/out",
477                           scm_pct_load_compiled_path);
478    /*
479      %compile-fallback-path is the guile cache root for auto-compiled files
480    */
481
482    string scm_pct_fallback_path = "%compile-fallback-path";
483    string ly_scm_go_dir = lilypond_datadir + "/scm/out";
484    //string scm_pct_set_fallback = "(set! " + scm_pct_fallback_path +
485    //  " \"" + lilypond_datadir + "/scm/out\")";
486    //scm_c_eval_string (scm_pct_set_fallback.c_str() );
487    scm_primitive_eval
488      (scm_list_3 (scm_from_latin1_symbol ("set!"),
489                   scm_from_latin1_symbol ("%compile-fallback-path"),
490                   scm_from_locale_string (ly_scm_go_dir.c_str())));
491 #endif
492
493   if (is_loglevel (LOG_DEBUG))
494     dir_info (stderr);
495
496   init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
497   init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
498
499   ly_c_init_guile ();
500   call_constructors ();
501   init_fontconfig ();
502
503   init_freetype ();
504   ly_reset_all_fonts ();
505
506   /*
507      We accept multiple independent music files on the command line to
508      reduce compile time when processing lots of small files.
509      This way we don't have to start the Guile/Scheme interpreter more than once, as
510      starting the GUILE engine is very time consuming.
511   */
512
513   SCM files = SCM_EOL;
514   SCM *tail = &files;
515   while (char const *arg = option_parser->get_next_arg ())
516     {
517       *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
518       tail = SCM_CDRLOC (*tail);
519     }
520
521   delete option_parser;
522   option_parser = 0;
523
524 #if HAVE_CHROOT
525   if (!jail_spec.empty ())
526     do_chroot_jail ();
527 #endif
528   /*
529     Now execute the Scheme entry-point declared in
530     lily.scm (lilypond-main)
531   */
532   // These commands moved to lily_guile_v2.scm
533   // SCM rep_mod = scm_c_resolve_module ("system repl repl");
534   // scm_c_use_module ("system repl repl");
535   // SCM err_handling_mod = scm_c_resolve_module ("system repl error-handling");
536   // SCM call_with_error_handling = scm_c_module_lookup (err_handling_mod, "call-with-error-handling");
537   // SCM result = scm_call_1 (
538   //                       scm_variable_ref (call_with_error_handling),
539   //                       scm_call_1 (ly_lily_module_constant ("lilypond-main"), files));
540
541   Lily::lilypond_main (files);
542
543   /* Unreachable.  */
544   exit (0);
545 }
546
547 static void
548 setup_localisation ()
549 /*
550  *  Set up local language text locale (if available from configure)
551  *  Implicit inputs:
552  *  HAVE_GETTEXT: Internationalization available for a local language.
553  */
554 {
555 #if HAVE_GETTEXT
556   /* Enable locales */
557   setlocale (LC_ALL, "");
558
559   /* FIXME: check if this is still true.
560      Disable localisation of float values. */
561   setlocale (LC_NUMERIC, "C");
562
563 #if GUILEV2
564   // In order not to have this porting aid backfire to GUILE1 usage,
565   // this is only compiled in the GUILEV2 version.  It should
566   // eventually be replaced with proper multibyte communication with
567   // GUILE2, but in the mean time it seems that this is the least
568   // invasive path to get comparable results between the
569   // not-really-multibyte-supporting GUILE1 and GUILE2
570
571   /* Disable character sets */
572   setlocale (LC_CTYPE, "C");
573   /* But our text domain is in UTF-8 */
574   bind_textdomain_codeset ("lilypond", "UTF-8");
575 #endif
576
577   string localedir = LOCALEDIR;
578   if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
579     localedir = env;
580
581   bindtextdomain ("lilypond", localedir.c_str ());
582   textdomain ("lilypond");
583 #endif
584 }
585
586 static void
587 add_output_format (const string &format)
588 /*
589  * Capture information internally from command-line options
590  * re output format.
591  *
592  */
593 {
594   if (output_format_global != "")
595     output_format_global += ",";
596   output_format_global += format;
597 }
598
599 static void
600 parse_argv (int argc, char **argv)
601 /*
602  *  Parse command-line options
603  *  also, if -h (help), -v (version) or  -w (warranty) is detected,
604  *  output the usage information and exit.
605  */
606 {
607   bool show_help = false;
608   option_parser = new Getopt_long (argc, argv, options_static);
609   while (Long_option_init const *opt = (*option_parser) ())
610     {
611       switch (opt->shortname_char_)
612         {
613         case 0:
614           if (string (opt->longname_str0_) == "pdf"
615               || string (opt->longname_str0_) == "png"
616               || string (opt->longname_str0_) == "ps")
617             add_output_format (opt->longname_str0_);
618           else if (string (opt->longname_str0_) == "relocate")
619             relocate_binary = true;
620           break;
621
622         case 'b':
623           bigpdfs = true;
624           break;
625
626         case 'd':
627           {
628             string arg (option_parser->optional_argument_str0_);
629             ssize eq = arg.find ('=');
630
631             string key = arg;
632             string val = "#t";
633
634             if (eq != NPOS)
635               {
636                 key = arg.substr (0, eq);
637                 val = arg.substr (eq + 1, arg.length () - 1);
638               }
639
640             init_scheme_variables_global
641             += "(cons \'" + key + " '" + val + ")\n";
642           }
643           break;
644
645         case 'v':
646           notice ();
647           exit (0);
648           break;
649         case 'o':
650           {
651             string s = option_parser->optional_argument_str0_;
652             File_name file_name (s);
653             output_name_global = file_name.to_string ();
654           }
655           break;
656         case 'j':
657           jail_spec = option_parser->optional_argument_str0_;
658           break;
659
660         case 'e':
661           init_scheme_code_global
662           += option_parser->optional_argument_str0_ + string (" ");
663           break;
664         case 'w':
665           warranty ();
666           exit (0);
667           break;
668
669         case 'f':
670           {
671             vector<string> components
672               = string_split (option_parser->optional_argument_str0_, ',');
673             for (vsize i = 0; i < components.size (); i++)
674               add_output_format (components[i]);
675           }
676           break;
677
678         case 'H':
679           dump_header_fieldnames_global
680           .push_back (option_parser->optional_argument_str0_);
681           break;
682         case 'I':
683           global_path.append (option_parser->optional_argument_str0_);
684           break;
685         case 'i':
686           init_name_global = option_parser->optional_argument_str0_;
687           break;
688         case 'h':
689           show_help = true;
690           break;
691         case 'V':
692           set_loglevel (LOGLEVEL_DEBUG);
693           break;
694         case 's':
695           set_loglevel (LOGLEVEL_ERROR);
696           break;
697         case 'l':
698           set_loglevel (option_parser->optional_argument_str0_);
699           break;
700         default:
701           programming_error (to_string ("unhandled short option: %c",
702                                         opt->shortname_char_));
703           assert (false);
704           break;
705         }
706     }
707
708   if (output_format_global == "")
709     output_format_global = "pdf";
710
711   if (show_help)
712     {
713       ly_usage ();
714       if (is_loglevel (LOG_DEBUG))
715         dir_info (stdout);
716       exit (0);
717     }
718 }
719
720 /*
721   T1686 Add two new routines called by setup_guile_env
722 */
723
724 void
725 setup_guile_gc_env ()
726 /*
727  * Set up environment variables relevant to the
728  * Garbage Collector
729  */
730 {
731   char const *yield = getenv ("LILYPOND_GC_YIELD");
732   bool overwrite = true;
733   if (!yield)
734     {
735       yield = "65";
736       overwrite = false;
737     }
738
739   sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
740   sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
741   sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
742
743   sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
744                "10485760", overwrite);
745   sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
746                "104857600", overwrite);
747 }
748
749
750 void
751 setup_guile_v2_env ()
752 /*
753  * Set up environment variables relevant to compiling
754  * Scheme files for Guile V2.
755  */
756 {
757      sane_putenv("GUILE_AUTO_COMPILE", "0", true);  // disable auto-compile
758      sane_putenv("GUILE_WARN_DEPRECATED",
759                   "detailed", "true");   // set Guile to info re deprecation
760      /*
761         Set root for Guile %compile-fallback to
762         Lilypond root for its data.
763       */
764      sane_putenv("XDG_CACHE_HOME",
765                   lilypond_datadir, true);
766 }
767
768 void
769 setup_guile_env ()
770 /*
771  * Set up environment variables relevant to Scheme
772  */
773 {
774
775   setup_guile_gc_env ();  // configure garbage collector
776 #if (GUILEV2)
777   setup_guile_v2_env ();  // configure Guile V2 behaviour
778 #endif
779 }
780
781 //vector<string> start_environment_global;
782
783 int
784 main (int argc, char **argv, char **envp)
785 /*
786  * Main entry-point for LilyPond executable image
787  * Parameters:
788  * argc:   Count of arguments on the command line
789  * argv:   Vector of string arguments on command line
790  * envp:   Point to vector of OS environment variables
791  */
792 {
793   configure_fpu ();
794   /*
795     Process environment variables
796   */
797   for (char **p = envp; *p; p++)
798     start_environment_global.push_back (*p);
799   /*
800     Handle old-style environment equivalent to
801     old-style -V or --verbose command arguments.
802     Set it to the equivalent for --loglevel-DEBUG
803    */
804   if (getenv ("LILYPOND_VERBOSE"))
805     set_loglevel (LOGLEVEL_DEBUG);
806   if (getenv ("LILYPOND_LOGLEVEL"))
807     set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
808
809   setup_localisation ();
810   parse_argv (argc, argv);
811   if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
812     identify (stderr);
813
814   setup_paths (argv[0]);
815   setup_guile_env ();  // set up environment variables to pass into Guile API
816   /*
817    * Start up Guile API using main_with_guile as a callback.
818    */
819 #if (GUILEV2)
820  /* Debugging aid.
821     Set it on by default for Guile V2
822     while migration in progress.
823  */
824   try
825     {
826       scm_boot_guile (argc, argv, main_with_guile, 0);
827     }
828   catch (exception e)
829     {
830       error (_f ("exception caught: %s", e.what ()));
831     };
832 #else
833   scm_boot_guile (argc, argv, main_with_guile, 0);
834 #endif
835
836   /* Only reachable if GUILE exits.  That is an error.  */
837   return 1;
838 }