]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/main.cc
Doc-es: various updates.
[lilypond.git] / lily / main.cc
index 8fc3c3ceb616d8f12d06be2ce89b4f0c568bc726..d84f90ebd8ab55c85395adbdd6b750bb0d334f19 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--2008 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>
@@ -42,82 +55,79 @@ using namespace std;
 #include "string-convert.hh"
 #include "version.hh"
 #include "warn.hh"
+#include "lily-imports.hh"
 
 /*
  * Global options that can be overridden through command line.
  */
 
 /* 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 = "";
+//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;
@@ -127,13 +137,20 @@ 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
@@ -142,50 +159,68 @@ static Long_option_init options_static[]
   {0, "pdf", 0, _i ("generate PDF (default)")},
   {0, "png", 0, _i ("generate PNG")},
   {0, "ps", 0, _i ("generate PostScript")},
-  {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, "bigpdfs", 'b', _i("generate big PDF files")},
+  {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))
+#if ((defined (__x86__) || defined (__i386__)) \
+  && defined (HAVE_FPU_CONTROL_H) && (HAVE_FPU_CONTROL_H == 1))
 
 #include <fpu_control.h>
-static void configure_fpu() {
+static void
+configure_fpu ()
+{
   fpu_control_t fpu_control = 0x027f;
   _FPU_SETCW (fpu_control);
 }
 
 #else
 
-static void configure_fpu() {
+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);
@@ -193,6 +228,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);
@@ -217,21 +256,30 @@ dir_info (FILE *out)
 
 static void
 copyright ()
+/*
+ * Print out LilyPond copyright info.
+ */
 {
-  printf (_f ("Copyright (c) %s by\n%s  and others.",
-             "1996--2008",
-             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);
@@ -242,29 +290,34 @@ notice ()
 }
 
 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");
   /* Translators, please translate this string as
-         "Report bugs in English via %s",
+     "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 (_f ("Report bugs via %s",
-             "http://post.gmane.org/post.php?group=gmane.comp.gnu.lilypond.bugs"
-             ).c_str ());
+     "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;
@@ -272,19 +325,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 ();
@@ -301,15 +367,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);
     }
 
@@ -317,16 +383,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);
     }
 
@@ -334,23 +400,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);
     }
 
@@ -369,7 +435,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);
     }
 }
@@ -377,14 +443,50 @@ 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_latin1_symbol ("set!"),
+                  scm_from_latin1_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);
 
   init_scheme_variables_global = "(list " + init_scheme_variables_global + ")";
@@ -397,9 +499,12 @@ main_with_guile (void *, int, char **)
   init_freetype ();
   ly_reset_all_fonts ();
 
-  /* 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;
@@ -408,7 +513,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;
 
@@ -416,9 +521,20 @@ main_with_guile (void *, int, char **)
   if (!jail_spec.empty ())
     do_chroot_jail ();
 #endif
-
-  SCM result = scm_call_1 (ly_lily_module_constant ("lilypond-main"), files);
-  (void) result;
+  /*
+    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));
+
+  Lily::lilypond_main (files);
 
   /* Unreachable.  */
   exit (0);
@@ -426,6 +542,11 @@ 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 */
@@ -435,6 +556,20 @@ setup_localisation ()
      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;
@@ -445,7 +580,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 += ",";
@@ -454,95 +594,111 @@ 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_) == "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':
-         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 'b':
+          bigpdfs = 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 == "")
@@ -551,16 +707,24 @@ parse_argv (int argc, char **argv)
   if (show_help)
     {
       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)
     {
@@ -572,36 +736,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);
+}
+
+
+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);
 }
 
-vector<string> start_environment_global;
+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();
-
+  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);
@@ -613,7 +828,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;
 }