]> git.donarmstrong.com Git - lilypond.git/blob - lily/main.cc
Web-ja: update introduction
[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 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 static void
218 env_var_info (FILE *out, char const *key)
219 /*
220  * Retrieve value of an OS environment variable.
221  * Parameter:
222  *  key, the name of an environment variable.
223  */
224 {
225   if (char const *value = getenv (key))
226     fprintf (out, "%s=\"%s\"\n", key, value);
227 }
228
229 static void
230 dir_info (FILE *out)
231 /*
232  * Print out information re directories being used by LilyPond
233  * for this session.
234  */
235 {
236   fputs ("\n", out);
237   fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
238   env_var_info (out, "LILYPONDPREFIX");
239   env_var_info (out, "LILYPOND_DATADIR");
240   fprintf (out, "LOCALEDIR=\"%s\"\n", LOCALEDIR);
241
242   fprintf (out, "\nEffective prefix: \"%s\"\n", lilypond_datadir.c_str ());
243
244   if (relocate_binary)
245     {
246       env_var_info (out, "FONTCONFIG_FILE");
247       env_var_info (out, "FONTCONFIG_PATH");
248       env_var_info (out, "GS_FONTPATH");
249       env_var_info (out, "GS_LIB");
250       env_var_info (out, "GUILE_LOAD_PATH");
251       env_var_info (out, "PANGO_RC_FILE");
252       env_var_info (out, "PANGO_PREFIX");
253       env_var_info (out, "PATH");
254     }
255 }
256
257 static void
258 copyright ()
259 /*
260  * Print out LilyPond copyright info.
261  */
262 {
263   /* Do not update the copyright years here, run `make grand-replace'  */
264   printf ("%s", (_f ("Copyright (c) %s by\n%s  and others.", "1996--2015",
265                      AUTHORS).c_str ()));
266   printf ("\n");
267 }
268
269 static void
270 identify (FILE *out)
271 /*
272  * Print out LilyPond version string.
273  */
274 {
275   fputs (gnu_lilypond_version_string ().c_str (), out);
276   fputs ("\n", out);
277 }
278
279 static void
280 /*
281  * Print copyright and program name
282  */
283 notice ()
284 {
285   identify (stdout);
286   printf ("\n");
287   copyright ();
288   printf ("\n");
289   puts (_f (NOTICE, PROGRAM_NAME).c_str ());
290 }
291
292 LY_DEFINE (ly_usage, "ly:usage",
293            0, 0, 0, (),
294            "Print usage message.")
295 /*
296  * ly_usage: Routine to output standard information when LilyPond is run without a
297  * source file to compile.
298  * Also callable as ly:usage from Scheme.
299  */
300 {
301   /* No version number or newline here.  It confuses help2man.  */
302   printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
303   printf ("\n\n");
304   printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
305   printf ("\n\n");
306   printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
307   printf ("\n");
308   printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
309   printf ("\n\n");
310   printf ("%s", (_ ("Options:").c_str ()));
311   printf ("\n");
312   printf ("%s", Long_option_init::table_string (options_static).c_str ());
313   printf ("\n");
314   /* Translators, please translate this string as
315      "Report bugs in English via %s",
316      or if there is a LilyPond users list or forum in your language
317      "Report bugs in English via %s or in YOUR_LANG via URI"  */
318   printf ("%s", (_f ("Report bugs via %s",
319                      "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
320                     ).c_str ()));
321   printf ("\n");
322   printf ("\n");
323   return SCM_UNSPECIFIED;
324 }
325
326 static void
327 warranty ()
328 /*
329  * Prints out LilyPond warranty information
330  */
331 {
332   identify (stdout);
333   printf ("\n");
334   copyright ();
335   printf ("\n");
336   printf ("%s", (_ (WARRANTY).c_str ()));
337 }
338
339 static void
340 prepend_scheme_list (const string &dir, const string &scmlist)
341 /*
342  *  Inserts an item at the front of a Scheme list, e.g. %load-path
343  *  Parameters:
344  *    dir:     The directory to add to the front of the list
345  *    scmlist: The Scheme list onto which to prepend the directory
346  */
347 {
348   SCM var = scm_c_lookup (scmlist.c_str());
349   scm_variable_set_x (var, scm_cons (scm_from_locale_string (dir.c_str()),
350                                      scm_variable_ref (var)));
351   /*  string setcmd =
352              "(set! " + scmlist + " (cons \"" + dir + "\" " + scmlist +"))";
353              scm_c_eval_string (setcmd.c_str());*/
354 }
355
356 void init_global_tweak_registry ();
357 void init_fontconfig ();
358
359 #if HAVE_CHROOT
360 static void
361 do_chroot_jail ()
362 {
363   /* Now we chroot, setuid/setgrp and chdir.  If something goes wrong,
364      we exit (this is a security-sensitive area).  First we split
365      jail_spec into its components, then we retrieve the user/group id
366      (necessarily *before* chroot'ing) and finally we perform the
367      actual actions.  */
368
369   enum Jail
370   {
371     USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
372   };
373
374   vector<string> components = string_split (jail_spec, ',');
375   if (components.size () != JAIL_MAX)
376     {
377       error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
378                  (unsigned) components.size ()));
379       exit (2);
380     }
381
382   /* Hmm.  */
383   errno = 0;
384
385   int uid;
386   if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
387     uid = passwd->pw_uid;
388   else
389     {
390       if (errno == 0)
391         error (_f ("no such user: %s", components[USER_NAME]));
392       else
393         error (_f ("cannot get user id from user name: %s: %s",
394                    components[USER_NAME],
395                    strerror (errno)));
396       exit (3);
397     }
398
399   /* Hmm.  */
400   errno = 0;
401
402   int gid;
403   if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
404     gid = group->gr_gid;
405   else
406     {
407       if (errno == 0)
408         error (_f ("no such group: %s", components[GROUP_NAME]));
409       else
410         error (_f ("cannot get group id from group name: %s: %s",
411                    components[GROUP_NAME],
412                    strerror (errno)));
413       exit (3);
414     }
415
416   if (chroot (components[JAIL].c_str ()))
417     {
418       error (_f ("cannot chroot to: %s: %s", components[JAIL],
419                  strerror (errno)));
420       exit (3);
421     }
422
423   if (setgid (gid))
424     {
425       error (_f ("cannot change group id to: %d: %s", gid, strerror (errno)));
426       exit (3);
427     }
428
429   if (setuid (uid))
430     {
431       error (_f ("cannot change user id to: %d: %s", uid, strerror (errno)));
432       exit (3);
433     }
434
435   if (chdir (components[DIR].c_str ()))
436     {
437       error (_f ("cannot change working directory to: %s: %s", components[DIR],
438                  strerror (errno)));
439       exit (3);
440     }
441 }
442 #endif
443
444 static void
445 main_with_guile (void *, int, char **)
446 /*
447  * main-with-guile is invoked as a callback via scm_boot_guile from
448  * main.
449  * scm_boot_guile will have passed its data, argc and argv parameters
450  * to main_with_guile.
451  */
452 {
453   /* Engravers use lily.scm contents, so we need to make Guile find it.
454      Prepend onto GUILE %load-path.
455       %load-path is the symbol Guile searches for .scm files
456       %load-compiled-path is the symbol Guile V2 searches for .go files
457    */
458    string scm_pct_load_path = "%load-path";
459    string scm_pct_load_compiled_path = "%load-compiled-path";
460
461    prepend_scheme_list (lilypond_datadir, scm_pct_load_path );
462    prepend_scheme_list (lilypond_datadir + "/scm", scm_pct_load_path);
463
464 #if (GUILE2)
465    /*
466      Just as ughy - prepend "/scm/out" onto GUILE V2+ %load-compiled-path
467      and set %compile-fallback-path to our scm/out directory
468    */
469    /*
470      %load-compiled-path is the symbol Guile V2 searches for .go files
471    */
472    prepend_scheme_list (lilypond_datadir + "/scm/out",
473                           scm_pct_load_compiled_path);
474    /*
475      %compile-fallback-path is the guile cache root for auto-compiled files
476    */
477
478    string scm_pct_fallback_path = "%compile-fallback-path";
479    string ly_scm_go_dir = lilypond_datadir + "/scm/out";
480    //string scm_pct_set_fallback = "(set! " + scm_pct_fallback_path +
481    //  " \"" + lilypond_datadir + "/scm/out\")";
482    //scm_c_eval_string (scm_pct_set_fallback.c_str() );
483    scm_primitive_eval
484      (scm_list_3 (scm_from_latin1_symbol ("set!"),
485                   scm_from_latin1_symbol ("%compile-fallback-path"),
486                   scm_from_locale_string (ly_scm_go_dir.c_str())));
487 #endif
488
489   if (is_loglevel (LOG_DEBUG))
490     dir_info (stderr);
491
492   init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
493   init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
494
495   ly_c_init_guile ();
496   call_constructors ();
497   init_fontconfig ();
498
499   init_freetype ();
500   ly_reset_all_fonts ();
501
502   /*
503      We accept multiple independent music files on the command line to
504      reduce compile time when processing lots of small files.
505      This way we don't have to start the Guile/Scheme interpreter more than once, as
506      starting the GUILE engine is very time consuming.
507   */
508
509   SCM files = SCM_EOL;
510   SCM *tail = &files;
511   while (char const *arg = option_parser->get_next_arg ())
512     {
513       *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
514       tail = SCM_CDRLOC (*tail);
515     }
516
517   delete option_parser;
518   option_parser = 0;
519
520 #if HAVE_CHROOT
521   if (!jail_spec.empty ())
522     do_chroot_jail ();
523 #endif
524   /*
525     Now execute the Scheme entry-point declared in
526     lily.scm (lilypond-main)
527   */
528   // These commands moved to lily_guile_v2.scm
529   // SCM rep_mod = scm_c_resolve_module ("system repl repl");
530   // scm_c_use_module ("system repl repl");
531   // SCM err_handling_mod = scm_c_resolve_module ("system repl error-handling");
532   // SCM call_with_error_handling = scm_c_module_lookup (err_handling_mod, "call-with-error-handling");
533   // SCM result = scm_call_1 (
534   //                       scm_variable_ref (call_with_error_handling),
535   //                       scm_call_1 (ly_lily_module_constant ("lilypond-main"), files));
536
537   Lily::lilypond_main (files);
538
539   /* Unreachable.  */
540   exit (0);
541 }
542
543 static void
544 setup_localisation ()
545 /*
546  *  Set up local language text locale (if available from configure)
547  *  Implicit inputs:
548  *  HAVE_GETTEXT: Internationalization available for a local language.
549  */
550 {
551 #if HAVE_GETTEXT
552   /* Enable locales */
553   setlocale (LC_ALL, "");
554
555   /* FIXME: check if this is still true.
556      Disable localisation of float values. */
557   setlocale (LC_NUMERIC, "C");
558
559 #if GUILEV2
560   // In order not to have this porting aid backfire to GUILE1 usage,
561   // this is only compiled in the GUILEV2 version.  It should
562   // eventually be replaced with proper multibyte communication with
563   // GUILE2, but in the mean time it seems that this is the least
564   // invasive path to get comparable results between the
565   // not-really-multibyte-supporting GUILE1 and GUILE2
566
567   /* Disable character sets */
568   setlocale (LC_CTYPE, "C");
569   /* But our text domain is in UTF-8 */
570   bind_textdomain_codeset ("lilypond", "UTF-8");
571 #endif
572
573   string localedir = LOCALEDIR;
574   if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
575     localedir = env;
576
577   bindtextdomain ("lilypond", localedir.c_str ());
578   textdomain ("lilypond");
579 #endif
580 }
581
582 static void
583 add_output_format (const string &format)
584 /*
585  * Capture information internally from command-line options
586  * re output format.
587  *
588  */
589 {
590   if (output_format_global != "")
591     output_format_global += ",";
592   output_format_global += format;
593 }
594
595 static void
596 parse_argv (int argc, char **argv)
597 /*
598  *  Parse command-line options
599  *  also, if -h (help), -v (version) or  -w (warranty) is detected,
600  *  output the usage information and exit.
601  */
602 {
603   bool show_help = false;
604   option_parser = new Getopt_long (argc, argv, options_static);
605   while (Long_option_init const *opt = (*option_parser) ())
606     {
607       switch (opt->shortname_char_)
608         {
609         case 0:
610           if (string (opt->longname_str0_) == "pdf"
611               || string (opt->longname_str0_) == "png"
612               || string (opt->longname_str0_) == "ps")
613             add_output_format (opt->longname_str0_);
614           else if (string (opt->longname_str0_) == "relocate")
615             relocate_binary = true;
616           break;
617
618         case 'b':
619           bigpdfs = true;
620           break;
621
622         case 'd':
623           {
624             string arg (option_parser->optional_argument_str0_);
625             ssize eq = arg.find ('=');
626
627             string key = arg;
628             string val = "#t";
629
630             if (eq != NPOS)
631               {
632                 key = arg.substr (0, eq);
633                 val = arg.substr (eq + 1, arg.length () - 1);
634               }
635
636             init_scheme_variables_global
637             += "(cons \'" + key + " '" + val + ")\n";
638           }
639           break;
640
641         case 'v':
642           notice ();
643           exit (0);
644           break;
645         case 'o':
646           {
647             string s = option_parser->optional_argument_str0_;
648             File_name file_name (s);
649             output_name_global = file_name.to_string ();
650           }
651           break;
652         case 'j':
653           jail_spec = option_parser->optional_argument_str0_;
654           break;
655
656         case 'e':
657           init_scheme_code_global
658           += option_parser->optional_argument_str0_ + string (" ");
659           break;
660         case 'w':
661           warranty ();
662           exit (0);
663           break;
664
665         case 'f':
666           {
667             vector<string> components
668               = string_split (option_parser->optional_argument_str0_, ',');
669             for (vsize i = 0; i < components.size (); i++)
670               add_output_format (components[i]);
671           }
672           break;
673
674         case 'H':
675           dump_header_fieldnames_global
676           .push_back (option_parser->optional_argument_str0_);
677           break;
678         case 'I':
679           global_path.append (option_parser->optional_argument_str0_);
680           break;
681         case 'i':
682           init_name_global = option_parser->optional_argument_str0_;
683           break;
684         case 'h':
685           show_help = true;
686           break;
687         case 'V':
688           set_loglevel (LOGLEVEL_DEBUG);
689           break;
690         case 's':
691           set_loglevel (LOGLEVEL_ERROR);
692           break;
693         case 'l':
694           set_loglevel (option_parser->optional_argument_str0_);
695           break;
696         default:
697           programming_error (to_string ("unhandled short option: %c",
698                                         opt->shortname_char_));
699           assert (false);
700           break;
701         }
702     }
703
704   if (output_format_global == "")
705     output_format_global = "pdf";
706
707   if (show_help)
708     {
709       ly_usage ();
710       if (is_loglevel (LOG_DEBUG))
711         dir_info (stdout);
712       exit (0);
713     }
714 }
715
716 /*
717   T1686 Add two new routines called by setup_guile_env
718 */
719
720 void
721 setup_guile_gc_env ()
722 /*
723  * Set up environment variables relevant to the
724  * Garbage Collector
725  */
726 {
727   char const *yield = getenv ("LILYPOND_GC_YIELD");
728   bool overwrite = true;
729   if (!yield)
730     {
731       yield = "65";
732       overwrite = false;
733     }
734
735   sane_putenv ("GUILE_MIN_YIELD_1", yield, overwrite);
736   sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
737   sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
738
739   sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
740                "10485760", overwrite);
741   sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
742                "104857600", overwrite);
743 }
744
745
746 void
747 setup_guile_v2_env ()
748 /*
749  * Set up environment variables relevant to compiling
750  * Scheme files for Guile V2.
751  */
752 {
753      sane_putenv("GUILE_AUTO_COMPILE", "0", true);  // disable auto-compile
754      sane_putenv("GUILE_WARN_DEPRECATED",
755                   "detailed", "true");   // set Guile to info re deprecation
756      /*
757         Set root for Guile %compile-fallback to
758         Lilypond root for its data.
759       */
760      sane_putenv("XDG_CACHE_HOME",
761                   lilypond_datadir, true);
762 }
763
764 void
765 setup_guile_env ()
766 /*
767  * Set up environment variables relevant to Scheme
768  */
769 {
770
771   setup_guile_gc_env ();  // configure garbage collector
772 #if (GUILEV2)
773   setup_guile_v2_env ();  // configure Guile V2 behaviour
774 #endif
775 }
776
777 //vector<string> start_environment_global;
778
779 int
780 main (int argc, char **argv, char **envp)
781 /*
782  * Main entry-point for LilyPond executable image
783  * Parameters:
784  * argc:   Count of arguments on the command line
785  * argv:   Vector of string arguments on command line
786  * envp:   Point to vector of OS environment variables
787  */
788 {
789   configure_fpu ();
790   /*
791     Process environment variables
792   */
793   for (char **p = envp; *p; p++)
794     start_environment_global.push_back (*p);
795   /*
796     Handle old-style environment equivalent to
797     old-style -V or --verbose command arguments.
798     Set it to the equivalent for --loglevel-DEBUG
799    */
800   if (getenv ("LILYPOND_VERBOSE"))
801     set_loglevel (LOGLEVEL_DEBUG);
802   if (getenv ("LILYPOND_LOGLEVEL"))
803     set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
804
805   setup_localisation ();
806   parse_argv (argc, argv);
807   if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
808     identify (stderr);
809
810   setup_paths (argv[0]);
811   setup_guile_env ();  // set up environment variables to pass into Guile API
812   /*
813    * Start up Guile API using main_with_guile as a callback.
814    */
815 #if (GUILEV2)
816  /* Debugging aid.
817     Set it on by default for Guile V2
818     while migration in progress.
819  */
820   try
821     {
822       scm_boot_guile (argc, argv, main_with_guile, 0);
823     }
824   catch (exception e)
825     {
826       error (_f ("exception caught: %s", e.what ()));
827     };
828 #else
829   scm_boot_guile (argc, argv, main_with_guile, 0);
830 #endif
831
832   /* Only reachable if GUILE exits.  That is an error.  */
833   return 1;
834 }