]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/main.cc
Run grand replace for 2015.
[lilypond.git] / lily / main.cc
index 3c0f7ae88eb7a4f28a065d1555ff4ffcf9c07aa9..93b784f0ffcc296015357e2101989b49c9fe63ee 100644 (file)
@@ -1,17 +1,30 @@
 /*
-  main.cc -- implement main () entrypoint.
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
 
-  (c) 1997--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
+  LilyPond is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  LilyPond is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "main.hh"
+#include "lily-guile.hh"
 
 #include <cassert>
 #include <clocale>
 #include <cstring>
 #include <cerrno>
+#include <cstdio>
 using namespace std;
 
 #include <unistd.h>
@@ -48,79 +61,72 @@ using namespace std;
  */
 
 /* Names of header fields to be dumped to a separate file. */
-vector<string> dump_header_fieldnames_global;
+//vector<string> dump_header_fieldnames_global; // moved to global-data.cc
 
 /* Name of initialisation file. */
-string init_name_global;
-
+//string init_name_global; // moved to global-data.cc
 
 /* Output formats to generate.  */
-string output_format_global = "";
-
-bool is_pango_format_global;
-bool is_TeX_format_global;
+//string output_format_global = ""; // moved to global-data.cc
 
 /* Current output name. */
-string output_name_global;
+//string output_name_global; // moved to global-data.cc
 
 /* Run in safe mode? */
-bool be_safe_global = false;
+//bool be_safe_global = false; // moved to global-data.cc
 
 /* Provide URI links to the original file */
 bool point_and_click_global = true;
 
-/* Verbose progress indication? */
-bool be_verbose_global = false;
-
 /* Scheme code to execute before parsing, after .scm init.
    This is where -e arguments are appended to.  */
-string init_scheme_code_global;
-string init_scheme_variables_global;
-
-bool relocate_binary = true;
+//string init_scheme_code_global; // moved to global-data.cc
+//string init_scheme_variables_global; // moved to global-data.cc
 
+//bool relocate_binary = true; // moved to global-data.cc
 
 /*
  * Miscellaneous global stuff.
  */
-File_path global_path;
+//File_path global_path; // moved to global-data.cc
 
 /*
  * File globals.
  */
 
 static char const *AUTHORS
-= "  Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
-  "  Jan Nieuwenhuizen <janneke@gnu.org>\n";
+  = "  Han-Wen Nienhuys <hanwen@xs4all.nl>\n"
+    "  Jan Nieuwenhuizen <janneke@gnu.org>\n";
 
 static char const *PROGRAM_NAME = "lilypond";
 static char const *PROGRAM_URL = "http://lilypond.org";
 
 static char const *NOTICE
-= _i ("This program is free software.  It is covered by the GNU General Public\n"
-      "License and you are welcome to change it and/or distribute copies of it\n"
-      "under certain conditions.  Invoke as `%s --warranty' for more\n"
-      "information.\n");
+  = _i ("This program is free software.  It is covered by the GNU General Public\n"
+        "License and you are welcome to change it and/or distribute copies of it\n"
+        "under certain conditions.  Invoke as `%s --warranty' for more\n"
+        "information.\n");
 
 static char const *WARRANTY
-= _i ("    This program is free software; you can redistribute it and/or\n"
-      "modify it under the terms of the GNU General Public License version 2\n"
-      "as published by the Free Software Foundation.\n"
-      "\n"
-      "    This program is distributed in the hope that it will be useful,\n"
-      "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
-      "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
-      "General Public License for more details.\n"
-      "\n"
-      "    You should have received a copy of the\n"
-      "GNU General Public License along with this program; if not, write to\n"
-      "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
-      "Boston, MA 02111-1307, USA.\n");
+  = _i ("    This program is free software; you can redistribute it and/or\n"
+        "modify it under the terms of the GNU General Public License as \n"
+        "published by the Free Software Foundation, either version 3 of\n"
+        "the License, or (at your option) any later version.\n"
+        "\n"
+        "    This program is distributed in the hope that it will be useful,\n"
+        "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+        "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
+        "General Public License for more details.\n"
+        "\n"
+        "    You should have received a copy of the\n"
+        "GNU General Public License along with this program; if not, write to\n"
+        "the Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n"
+        "Boston, MA 02111-1307, USA.\n");
 
 /* Where the init files live.  Typically:
    LILYPOND_DATADIR = /usr/share/lilypond
 */
-string lilypond_datadir;
+//string lilypond_datadir; // moved to global-data.cc
 
 /* The jail specification: USER, GROUP, JAIL, DIR. */
 string jail_spec;
@@ -130,44 +136,89 @@ static Getopt_long *option_parser = 0;
 
 /* Internationalisation kludge in two steps:
  * use _i () to get entry in POT file
- * call gettext () explicitely for actual "translation"  */
+ * call gettext () explicitly for actual "translation"  */
 
+/*
+  Data to be used to display when
+  -h command line option is detected.
+*/
 static Long_option_init options_static[]
-= {
-  {_i ("SYM[=VAL]"), "define-default", 'd',
-   _i ("set Scheme option SYM to VAL (default: #t).\n"
-       "Use -dhelp for help.")},
+=
+{
+  {
+    _i ("SYM[=VAL]"), "define-default", 'd',
+    _i ("set Scheme option SYM to VAL (default: #t).\n"
+    "Use -dhelp for help.")
+  },
 
   {_i ("EXPR"), "evaluate", 'e', _i ("evaluate scheme code")},
   /* Bug in option parser: --output =foe is taken as an abbreviation
      for --output-format.  */
   {_i ("FORMATs"), "formats", 'f', _i ("dump FORMAT,...  Also as separate options:")},
-  {0, "dvi", 0, _i ("generate DVI (tex backend only)")},
   {0, "pdf", 0, _i ("generate PDF (default)")},
   {0, "png", 0, _i ("generate PNG")},
   {0, "ps", 0, _i ("generate PostScript")},
-  {0, "tex", 0, _i ("generate TeX (tex backend only)")},
-  {0, "help", 'h',  _i ("show this help and exit")},
-  {_i ("FIELD"), "header", 'H',  _i ("dump header field FIELD to file\n"
-                                    "named BASENAME.FIELD")},
-  {_i ("DIR"), "include", 'I',  _i ("add DIR to search path")},
-  {_i ("FILE"), "init", 'i',  _i ("use FILE as init file")},
+  {0, "help", 'h', _i ("show this help and exit")},
+  {
+    _i ("FIELD"), "header", 'H', _i ("dump header field FIELD to file\n"
+    "named BASENAME.FIELD")
+  },
+  {_i ("DIR"), "include", 'I', _i ("add DIR to search path")},
+  {_i ("FILE"), "init", 'i', _i ("use FILE as init file")},
 #if HAVE_CHROOT
-  {_i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
-                                               "and cd into DIR")},
+  {
+    _i ("USER, GROUP, JAIL, DIR"), "jail", 'j', _i ("chroot to JAIL, become USER:GROUP\n"
+    "and cd into DIR")
+  },
 #endif
-  {_i ("FILE"), "output", 'o',  _i ("write output to FILE (suffix will be added)")},
+  {
+    _i ("LOGLEVEL"), "loglevel", 'l', _i ("print log messages according to"
+    " LOGLEVEL.  Possible values are:\n"
+    "NONE, ERROR, WARNING, BASIC, PROGRESS, INFO (default) and DEBUG.")
+  },
+  {_i ("FILE"), "output", 'o', _i ("write output to FILE (suffix will be added)")},
   {0, "relocate", 0, _i ("relocate using directory of lilypond program")},
-  {0, "version", 'v',  _i ("show version number and exit")},
-  {0, "verbose", 'V', _i ("be verbose")},
-  {0, "warranty", 'w',  _i ("show warranty and copyright")},
+  {0, "silent", 's', _i ("no progress, only error messages (equivalent to loglevel=ERROR)")},
+  {0, "version", 'v', _i ("show version number and exit")},
+  {0, "verbose", 'V', _i ("be verbose (equivalent to loglevel=DEBUG)")},
+  {0, "warranty", 'w', _i ("show warranty and copyright")},
   {0, 0, 0, 0}
 };
 
 char const *LILYPOND_DATADIR = PACKAGE_DATADIR "/" TOPLEVEL_VERSION;
 
+/* x86 defaults to using 80-bit extended precision arithmetic. This can cause
+   problems because the truncation from 80 bits to 64 bits can occur in
+   unpredictable places. To get around this, we tell the x87 FPU to use only
+   double precision. Note that this is not needed for x86_64 because that uses
+   the SSE unit by default instead of the x87 FPU. */
+#if ((defined (__x86__) || defined (__i386__)) \
+  && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
+
+#include <fpu_control.h>
+static void
+configure_fpu ()
+{
+  fpu_control_t fpu_control = 0x027f;
+  _FPU_SETCW (fpu_control);
+}
+
+#else
+
+static void
+configure_fpu ()
+{
+}
+
+#endif /* defined(__x86__) || defined(__i386__) */
+
 static void
 env_var_info (FILE *out, char const *key)
+/*
+ * Retrieve value of an OS environment variable.
+ * Parameter:
+ *  key, the name of an environment variable.
+ */
 {
   if (char const *value = getenv (key))
     fprintf (out, "%s=\"%s\"\n", key, value);
@@ -175,6 +226,10 @@ env_var_info (FILE *out, char const *key)
 
 static void
 dir_info (FILE *out)
+/*
+ * Print out information re directories being used by LilyPond
+ * for this session.
+ */
 {
   fputs ("\n", out);
   fprintf (out, "LILYPOND_DATADIR=\"%s\"\n", LILYPOND_DATADIR);
@@ -199,49 +254,68 @@ dir_info (FILE *out)
 
 static void
 copyright ()
+/*
+ * Print out LilyPond copyright info.
+ */
 {
-  printf (_f ("Copyright (c) %s by\n%s  and others.",
-             "1996--2007",
-             AUTHORS).c_str ());
+  /* Do not update the copyright years here, run `make grand-replace'  */
+  printf ("%s", (_f ("Copyright (c) %s by\n%s  and others.", "1996--2015",
+                     AUTHORS).c_str ()));
   printf ("\n");
 }
 
 static void
 identify (FILE *out)
+/*
+ * Print out LilyPond version string.
+ */
 {
   fputs (gnu_lilypond_version_string ().c_str (), out);
   fputs ("\n", out);
 }
 
 static void
+/*
+ * Print copyright and program name
+ */
 notice ()
 {
   identify (stdout);
-  puts (_f (NOTICE, PROGRAM_NAME).c_str ());
   printf ("\n");
   copyright ();
+  printf ("\n");
+  puts (_f (NOTICE, PROGRAM_NAME).c_str ());
 }
 
 LY_DEFINE (ly_usage, "ly:usage",
-          0, 0, 0, (),
-          "Print usage message.")
+           0, 0, 0, (),
+           "Print usage message.")
+/*
+ * ly_usage: Routine to output standard information when LilyPond is run without a
+ * source file to compile.
+ * Also callable as ly:usage from Scheme.
+ */
 {
   /* No version number or newline here.  It confuses help2man.  */
-  printf (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ());
+  printf ("%s", (_f ("Usage: %s [OPTION]... FILE...", PROGRAM_NAME).c_str ()));
   printf ("\n\n");
-  printf (_ ("Typeset music and/or produce MIDI from FILE.").c_str ());
+  printf ("%s", (_ ("Typeset music and/or produce MIDI from FILE.").c_str ()));
   printf ("\n\n");
-  printf (_ ("LilyPond produces beautiful music notation.").c_str ());
+  printf ("%s", (_ ("LilyPond produces beautiful music notation.").c_str ()));
   printf ("\n");
-  printf (_f ("For more information, see %s", PROGRAM_URL).c_str ());
+  printf ("%s", (_f ("For more information, see %s", PROGRAM_URL).c_str ()));
   printf ("\n\n");
-  printf (_ ("Options:").c_str ());
+  printf ("%s", (_ ("Options:").c_str ()));
   printf ("\n");
-  printf (Long_option_init::table_string (options_static).c_str ());
+  printf ("%s", Long_option_init::table_string (options_static).c_str ());
   printf ("\n");
-  printf (_f ("Report bugs via %s",
-             "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
-             ).c_str ());
+  /* Translators, please translate this string as
+     "Report bugs in English via %s",
+     or if there is a LilyPond users list or forum in your language
+     "Report bugs in English via %s or in YOUR_LANG via URI"  */
+  printf ("%s", (_f ("Report bugs via %s",
+                     "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
+                    ).c_str ()));
   printf ("\n");
   printf ("\n");
   return SCM_UNSPECIFIED;
@@ -249,19 +323,32 @@ LY_DEFINE (ly_usage, "ly:usage",
 
 static void
 warranty ()
+/*
+ * Prints out LilyPond warranty information
+ */
 {
   identify (stdout);
   printf ("\n");
   copyright ();
   printf ("\n");
-  printf (_ (WARRANTY).c_str ());
+  printf ("%s", (_ (WARRANTY).c_str ()));
 }
 
 static void
-prepend_load_path (string dir)
+prepend_scheme_list (const string &dir, const string &scmlist)
+/*
+ *  Inserts an item at the front of a Scheme list, e.g. %load-path
+ *  Parameters:
+ *    dir:     The directory to add to the front of the list
+ *    scmlist: The Scheme list onto which to prepend the directory
+ */
 {
-  string s = "(set! %load-path (cons \"" + dir + "\" %load-path))";
-  scm_c_eval_string (s.c_str ());
+  SCM var = scm_c_lookup (scmlist.c_str());
+  scm_variable_set_x (var, scm_cons (scm_from_locale_string (dir.c_str()),
+                                    scm_variable_ref (var)));
+  /*  string setcmd =
+             "(set! " + scmlist + " (cons \"" + dir + "\" " + scmlist +"))";
+            scm_c_eval_string (setcmd.c_str());*/
 }
 
 void init_global_tweak_registry ();
@@ -278,15 +365,15 @@ do_chroot_jail ()
      actual actions.  */
 
   enum Jail
-    {
-      USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
-    };
+  {
+    USER_NAME, GROUP_NAME, JAIL, DIR, JAIL_MAX
+  };
 
   vector<string> components = string_split (jail_spec, ',');
   if (components.size () != JAIL_MAX)
     {
       error (_f ("expected %d arguments with jail, found: %u", JAIL_MAX,
-                (unsigned) components.size ()));
+                 (unsigned) components.size ()));
       exit (2);
     }
 
@@ -294,16 +381,16 @@ do_chroot_jail ()
   errno = 0;
 
   int uid;
-  if (passwd * passwd = getpwnam (components[USER_NAME].c_str ()))
+  if (passwd *passwd = getpwnam (components[USER_NAME].c_str ()))
     uid = passwd->pw_uid;
   else
     {
       if (errno == 0)
-       error (_f ("no such user: %s", components[USER_NAME]));
+        error (_f ("no such user: %s", components[USER_NAME]));
       else
-       error (_f ("cannot get user id from user name: %s: %s",
-                  components[USER_NAME],
-                  strerror (errno)));
+        error (_f ("cannot get user id from user name: %s: %s",
+                   components[USER_NAME],
+                   strerror (errno)));
       exit (3);
     }
 
@@ -311,23 +398,23 @@ do_chroot_jail ()
   errno = 0;
 
   int gid;
-  if (group * group = getgrnam (components[GROUP_NAME].c_str ()))
+  if (group *group = getgrnam (components[GROUP_NAME].c_str ()))
     gid = group->gr_gid;
   else
     {
       if (errno == 0)
-       error (_f ("no such group: %s", components[GROUP_NAME]));
+        error (_f ("no such group: %s", components[GROUP_NAME]));
       else
-       error (_f ("cannot get group id from group name: %s: %s",
-                  components[GROUP_NAME],
-                  strerror (errno)));
+        error (_f ("cannot get group id from group name: %s: %s",
+                   components[GROUP_NAME],
+                   strerror (errno)));
       exit (3);
     }
 
   if (chroot (components[JAIL].c_str ()))
     {
       error (_f ("cannot chroot to: %s: %s", components[JAIL],
-                strerror (errno)));
+                 strerror (errno)));
       exit (3);
     }
 
@@ -346,7 +433,7 @@ do_chroot_jail ()
   if (chdir (components[DIR].c_str ()))
     {
       error (_f ("cannot change working directory to: %s: %s", components[DIR],
-                strerror (errno)));
+                 strerror (errno)));
       exit (3);
     }
 }
@@ -354,17 +441,52 @@ do_chroot_jail ()
 
 static void
 main_with_guile (void *, int, char **)
+/*
+ * main-with-guile is invoked as a callback via scm_boot_guile from
+ * main.
+ * scm_boot_guile will have passed its data, argc and argv parameters
+ * to main_with_guile.
+ */
 {
-  /* Engravers use lily.scm contents, need to make Guile find it.
-     Prepend onto GUILE %load-path, very ugh. */
-
-  prepend_load_path (lilypond_datadir);
-  prepend_load_path (lilypond_datadir + "/scm");
+  /* Engravers use lily.scm contents, so we need to make Guile find it.
+     Prepend onto GUILE %load-path.
+      %load-path is the symbol Guile searches for .scm files
+      %load-compiled-path is the symbol Guile V2 searches for .go files
+   */
+   string scm_pct_load_path = "%load-path";
+   string scm_pct_load_compiled_path = "%load-compiled-path";
+
+   prepend_scheme_list (lilypond_datadir, scm_pct_load_path );
+   prepend_scheme_list (lilypond_datadir + "/scm", scm_pct_load_path);
+
+#if (GUILE2)
+   /*
+     Just as ughy - prepend "/scm/out" onto GUILE V2+ %load-compiled-path
+     and set %compile-fallback-path to our scm/out directory
+   */
+   /*
+     %load-compiled-path is the symbol Guile V2 searches for .go files
+   */
+   prepend_scheme_list (lilypond_datadir + "/scm/out",
+                         scm_pct_load_compiled_path);
+   /*
+     %compile-fallback-path is the guile cache root for auto-compiled files
+   */
+
+   string scm_pct_fallback_path = "%compile-fallback-path";
+   string ly_scm_go_dir = lilypond_datadir + "/scm/out";
+   //string scm_pct_set_fallback = "(set! " + scm_pct_fallback_path +
+   //  " \"" + lilypond_datadir + "/scm/out\")";
+   //scm_c_eval_string (scm_pct_set_fallback.c_str() );
+   scm_primitive_eval
+     (scm_list_3 (scm_from_locale_symbol ("set!"),
+                  scm_from_locale_symbol ("%compile-fallback-path"),
+                  scm_from_locale_string (ly_scm_go_dir.c_str())));
+#endif
 
-  if (be_verbose_global)
+  if (is_loglevel (LOG_DEBUG))
     dir_info (stderr);
 
-  is_pango_format_global = !is_TeX_format_global;
   init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
   init_scheme_code_global = "(begin " + init_scheme_code_global + ")";
 
@@ -375,13 +497,12 @@ main_with_guile (void *, int, char **)
   init_freetype ();
   ly_reset_all_fonts ();
 
-  is_TeX_format_global = (get_output_backend_name () == "tex"
-                         || get_output_backend_name () == "texstr");
-  
-
-  /* We accept multiple independent music files on the command line to
+  /*
+     We accept multiple independent music files on the command line to
      reduce compile time when processing lots of small files.
-     Starting the GUILE engine is very time consuming.  */
+     This way we don't have to start the Guile/Scheme interpreter more than once, as
+     starting the GUILE engine is very time consuming.
+  */
 
   SCM files = SCM_EOL;
   SCM *tail = &files;
@@ -390,7 +511,7 @@ main_with_guile (void *, int, char **)
       *tail = scm_cons (scm_from_locale_string (arg), SCM_EOL);
       tail = SCM_CDRLOC (*tail);
     }
-  
+
   delete option_parser;
   option_parser = 0;
 
@@ -398,7 +519,18 @@ main_with_guile (void *, int, char **)
   if (!jail_spec.empty ())
     do_chroot_jail ();
 #endif
-
+  /*
+    Now execute the Scheme entry-point declared in
+    lily.scm (lilypond-main)
+  */
+  // These commands moved to lily_guile_v2.scm
+  // SCM rep_mod = scm_c_resolve_module ("system repl repl");
+  // scm_c_use_module ("system repl repl");
+  // SCM err_handling_mod = scm_c_resolve_module ("system repl error-handling");
+  // SCM call_with_error_handling = scm_c_module_lookup (err_handling_mod, "call-with-error-handling");
+  // SCM result = scm_call_1 (
+  //                      scm_variable_ref (call_with_error_handling),
+  //                      scm_call_1 (ly_lily_module_constant ("lilypond-main"), files));
   SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
   (void) result;
 
@@ -408,15 +540,34 @@ main_with_guile (void *, int, char **)
 
 static void
 setup_localisation ()
+/*
+ *  Set up local language text locale (if available from configure)
+ *  Implicit inputs:
+ *  HAVE_GETTEXT: Internationalization available for a local language.
+ */
 {
 #if HAVE_GETTEXT
   /* Enable locales */
   setlocale (LC_ALL, "");
 
   /* FIXME: check if this is still true.
-     Disable localisation of float values.  This breaks TeX output.  */
+     Disable localisation of float values. */
   setlocale (LC_NUMERIC, "C");
 
+#if GUILEV2
+  // In order not to have this porting aid backfire to GUILE1 usage,
+  // this is only compiled in the GUILEV2 version.  It should
+  // eventually be replaced with proper multibyte communication with
+  // GUILE2, but in the mean time it seems that this is the least
+  // invasive path to get comparable results between the
+  // not-really-multibyte-supporting GUILE1 and GUILE2
+
+  /* Disable character sets */
+  setlocale (LC_CTYPE, "C");
+  /* But our text domain is in UTF-8 */
+  bind_textdomain_codeset ("lilypond", "UTF-8");
+#endif
+
   string localedir = LOCALEDIR;
   if (char const *env = getenv ("LILYPOND_LOCALEDIR"))
     localedir = env;
@@ -427,7 +578,12 @@ setup_localisation ()
 }
 
 static void
-add_output_format (string format)
+add_output_format (const string &format)
+/*
+ * Capture information internally from command-line options
+ * re output format.
+ *
+ */
 {
   if (output_format_global != "")
     output_format_global += ",";
@@ -436,97 +592,107 @@ add_output_format (string format)
 
 static void
 parse_argv (int argc, char **argv)
+/*
+ *  Parse command-line options
+ *  also, if -h (help), -v (version) or  -w (warranty) is detected,
+ *  output the usage information and exit.
+ */
 {
   bool show_help = false;
   option_parser = new Getopt_long (argc, argv, options_static);
   while (Long_option_init const *opt = (*option_parser) ())
     {
       switch (opt->shortname_char_)
-       {
-       case 0:
-         if (string (opt->longname_str0_) == "dvi"
-             || string (opt->longname_str0_) == "pdf"
-             || string (opt->longname_str0_) == "png"
-             || string (opt->longname_str0_) == "ps"
-             || string (opt->longname_str0_) == "tex")
-           add_output_format (opt->longname_str0_);
-         else if (string (opt->longname_str0_) == "relocate")
-           relocate_binary = true;
-         break;
-
-       case 'd':
-         {
-           string arg (option_parser->optional_argument_str0_);
-           ssize eq = arg.find ('=');
-
-           string key = arg;
-           string val = "#t";
-
-           if (eq != NPOS)
-             {
-               key = arg.substr (0, eq);
-               val = arg.substr (eq + 1, arg.length () - 1);
-             }
-
-           init_scheme_variables_global
-             += "(cons \'" + key + " '" + val + ")\n";
-         }
-         break;
-
-       case 'v':
-         notice ();
-         exit (0);
-         break;
-       case 'o':
-         {
-           string s = option_parser->optional_argument_str0_;
-           File_name file_name (s);
-           output_name_global = file_name.to_string ();
-         }
-         break;
-       case 'j':
-         jail_spec = option_parser->optional_argument_str0_;
-         break;
-         
-       case 'e':
-         init_scheme_code_global += option_parser->optional_argument_str0_ + string (" ");
-         break;
-       case 'w':
-         warranty ();
-         exit (0);
-         break;
-
-       case 'f':
-         {
-           vector<string> components
-             = string_split (option_parser->optional_argument_str0_, ',');
-           for (vsize i = 0; i < components.size (); i++)
-             add_output_format (components[i]);
-         }
-         break;
-
-       case 'H':
-         dump_header_fieldnames_global
-           .push_back (option_parser->optional_argument_str0_);
-         break;
-       case 'I':
-         global_path.append (option_parser->optional_argument_str0_);
-         break;
-       case 'i':
-         init_name_global = option_parser->optional_argument_str0_;
-         break;
-       case 'h':
-         show_help = true;
-         break;
-       case 'V':
-         be_verbose_global = true;
-         break;
-       default:
-         programming_error (to_string ("unhandled short option: %c",
-                                       opt->shortname_char_));
-         assert (false);
-         break;
-       }
+        {
+        case 0:
+          if (string (opt->longname_str0_) == "pdf"
+              || string (opt->longname_str0_) == "png"
+              || string (opt->longname_str0_) == "ps")
+            add_output_format (opt->longname_str0_);
+          else if (string (opt->longname_str0_) == "relocate")
+            relocate_binary = true;
+          break;
+
+        case 'd':
+          {
+            string arg (option_parser->optional_argument_str0_);
+            ssize eq = arg.find ('=');
+
+            string key = arg;
+            string val = "#t";
+
+            if (eq != NPOS)
+              {
+                key = arg.substr (0, eq);
+                val = arg.substr (eq + 1, arg.length () - 1);
+              }
+
+            init_scheme_variables_global
+            += "(cons \'" + key + " '" + val + ")\n";
+          }
+          break;
+
+        case 'v':
+          notice ();
+          exit (0);
+          break;
+        case 'o':
+          {
+            string s = option_parser->optional_argument_str0_;
+            File_name file_name (s);
+            output_name_global = file_name.to_string ();
+          }
+          break;
+        case 'j':
+          jail_spec = option_parser->optional_argument_str0_;
+          break;
+
+        case 'e':
+          init_scheme_code_global
+          += option_parser->optional_argument_str0_ + string (" ");
+          break;
+        case 'w':
+          warranty ();
+          exit (0);
+          break;
+
+        case 'f':
+          {
+            vector<string> components
+              = string_split (option_parser->optional_argument_str0_, ',');
+            for (vsize i = 0; i < components.size (); i++)
+              add_output_format (components[i]);
+          }
+          break;
+
+        case 'H':
+          dump_header_fieldnames_global
+          .push_back (option_parser->optional_argument_str0_);
+          break;
+        case 'I':
+          global_path.append (option_parser->optional_argument_str0_);
+          break;
+        case 'i':
+          init_name_global = option_parser->optional_argument_str0_;
+          break;
+        case 'h':
+          show_help = true;
+          break;
+        case 'V':
+          set_loglevel (LOGLEVEL_DEBUG);
+          break;
+        case 's':
+          set_loglevel (LOGLEVEL_ERROR);
+          break;
+        case 'l':
+          set_loglevel (option_parser->optional_argument_str0_);
+          break;
+        default:
+          programming_error (to_string ("unhandled short option: %c",
+                                        opt->shortname_char_));
+          assert (false);
+          break;
+        }
     }
 
   if (output_format_global == "")
@@ -534,18 +700,25 @@ parse_argv (int argc, char **argv)
 
   if (show_help)
     {
-      identify (stdout);
       ly_usage ();
-      if (be_verbose_global)
-       dir_info (stdout);
+      if (is_loglevel (LOG_DEBUG))
+        dir_info (stdout);
       exit (0);
     }
 }
 
+/*
+  T1686 Add two new routines called by setup_guile_env
+*/
+
 void
-setup_guile_env ()
+setup_guile_gc_env ()
+/*
+ * Set up environment variables relevant to the
+ * Garbage Collector
+ */
 {
-  const char *yield = getenv ("LILYPOND_GC_YIELD");
+  char const *yield = getenv ("LILYPOND_GC_YIELD");
   bool overwrite = true;
   if (!yield)
     {
@@ -557,34 +730,87 @@ setup_guile_env ()
   sane_putenv ("GUILE_MIN_YIELD_2", yield, overwrite);
   sane_putenv ("GUILE_MIN_YIELD_MALLOC", yield, overwrite);
 
-
   sane_putenv ("GUILE_INIT_SEGMENT_SIZE_1",
-              "10485760", overwrite);
+               "10485760", overwrite);
   sane_putenv ("GUILE_MAX_SEGMENT_SIZE",
-              "104857600", overwrite);
+               "104857600", overwrite);
 }
 
-vector<string> start_environment_global;
+
+void
+setup_guile_v2_env ()
+/*
+ * Set up environment variables relevant to compiling
+ * Scheme files for Guile V2.
+ */
+{
+     sane_putenv("GUILE_AUTO_COMPILE", "0", true);  // disable auto-compile
+     sane_putenv("GUILE_WARN_DEPRECATED",
+                  "detailed", "true");   // set Guile to info re deprecation
+     /*
+        Set root for Guile %compile-fallback to
+        Lilypond root for its data.
+      */
+     sane_putenv("XDG_CACHE_HOME",
+                  lilypond_datadir, true);
+}
+
+void
+setup_guile_env ()
+/*
+ * Set up environment variables relevant to Scheme
+ */
+{
+
+  setup_guile_gc_env ();  // configure garbage collector
+#if (GUILEV2)
+  setup_guile_v2_env ();  // configure Guile V2 behaviour
+#endif
+}
+
+//vector<string> start_environment_global;
+
 int
 main (int argc, char **argv, char **envp)
+/*
+ * Main entry-point for LilyPond executable image
+ * Parameters:
+ * argc:   Count of arguments on the command line
+ * argv:   Vector of string arguments on command line
+ * envp:   Point to vector of OS environment variables
+ */
 {
+  configure_fpu ();
+  /*
+    Process environment variables
+  */
   for (char **p = envp; *p; p++)
-    start_environment_global.push_back(*p);
-  
+    start_environment_global.push_back (*p);
+  /*
+    Handle old-style environment equivalent to
+    old-style -V or --verbose command arguments.
+    Set it to the equivalent for --loglevel-DEBUG
+   */
   if (getenv ("LILYPOND_VERBOSE"))
-    be_verbose_global = true;
+    set_loglevel (LOGLEVEL_DEBUG);
+  if (getenv ("LILYPOND_LOGLEVEL"))
+    set_loglevel (getenv ("LILYPOND_LOGLEVEL"));
 
   setup_localisation ();
   parse_argv (argc, argv);
-  if (isatty (STDIN_FILENO))
+  if (isatty (STDIN_FILENO) && (is_loglevel (LOG_BASIC)))
     identify (stderr);
 
   setup_paths (argv[0]);
-  setup_guile_env ();
-
-#if 0
-  /* Debugging aid.  */
+  setup_guile_env ();  // set up environment variables to pass into Guile API
+  /*
+   * Start up Guile API using main_with_guile as a callback.
+   */
+#if (GUILEV2)
+ /* Debugging aid.
+    Set it on by default for Guile V2
+    while migration in progress.
+ */
   try
     {
       scm_boot_guile (argc, argv, main_with_guile, 0);
@@ -596,7 +822,7 @@ main (int argc, char **argv, char **envp)
 #else
   scm_boot_guile (argc, argv, main_with_guile, 0);
 #endif
-       
+
   /* Only reachable if GUILE exits.  That is an error.  */
   return 1;
 }