2 This file is part of LilyPond, the GNU music typesetter.
4 Copyright (C) 1997--2015 Han-Wen Nienhuys <hanwen@xs4all.nl>
6 LilyPond is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
11 LilyPond is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
25 #include "std-vector.hh"
26 #include "international.hh"
32 /** We have several different loglevels, each with its own message function(s):
33 ERROR: error, non_fatal_error, programming_error
35 BASIC_PROGRESS: success/...
36 PROGRESS: progress_indication
39 All these functions check whether the corresponding loglevel bit is set
40 and print the message only if that's the case
43 /* Define the loglevel (default is INFO) */
44 int loglevel = LOGLEVEL_INFO;
45 bool warning_as_error = false;
48 is_loglevel (int level)
50 // Check the bitmask containing the loglevel
51 return (loglevel & level);
55 set_loglevel (int level)
58 debug_output (_f ("Log level set to %d\n", loglevel));
62 set_loglevel (string level)
64 /* Convert the loglevel string to lower-case, so we allow
65 both upper- and lower-case loglevels */
66 std::transform (level.begin (), level.end (), level.begin (), ::tolower);
68 /* Compare just the first few characters, so the loglevels
70 if (level.compare (0, 5, "debug") == 0) // debug
71 set_loglevel (LOGLEVEL_DEBUG);
72 else if (level.compare (0, 4, "info") == 0) // info
73 set_loglevel (LOGLEVEL_INFO);
74 else if (level.compare (0, 4, "prog") == 0) // progress
75 set_loglevel (LOGLEVEL_PROGRESS);
76 else if (level.compare (0, 5, "basic") == 0) // basic progress
77 set_loglevel (LOGLEVEL_BASIC);
78 else if (level.compare (0, 4, "warn") == 0) // warning
79 set_loglevel (LOGLEVEL_WARN);
80 else if (level.compare (0, 3, "err") == 0) // error
81 set_loglevel (LOGLEVEL_ERROR);
82 else if (level.compare (0, 4, "none") == 0) // none
83 set_loglevel (LOGLEVEL_NONE);
87 if (sscanf (level.c_str (), "%d", &l))
91 non_fatal_error (_f ("unknown log level `%s', using default (INFO)",
93 set_loglevel (LOGLEVEL_INFO);
99 * Register a warning string to be expected and the output suppressed.
100 * If the warning is encountered, it will be removed from the list of
101 * expected warnings again.
103 vector<string> expected_warnings;
104 void expect_warning (const string &msg)
106 expected_warnings.push_back (msg);
109 void check_expected_warnings ()
111 if (expected_warnings.size () > 0)
113 /* Some expected warning was not triggered, so print out a warning. */
114 string msg = _f ("%d expected warning(s) not encountered: ",
115 expected_warnings.size ());
116 for (vsize i = 0; i < expected_warnings.size (); i++)
117 msg += "\n " + expected_warnings[i];
121 expected_warnings.clear ();
124 bool is_expected (const string &s)
126 bool expected = false;
127 for (vsize i = 0; i < expected_warnings.size (); i++)
129 // Compare the msg with the suppressed string; If the beginning matches,
130 // i.e. the msg can have additional content AFTER the full (exact)
131 // suppressed message, suppress the warning.
132 // This is needed for the Input class, where the message contains
133 // the input file contents after the real message.
134 if (s.compare (0, expected_warnings[i].size (), expected_warnings[i]) == 0)
137 expected_warnings.erase (expected_warnings.begin () + i);
145 * Helper functions: print_message_part (no newline prepended)
146 * print_message (always starts on a new line)
149 /* Is output message at NEWLINE? */
150 static bool message_newline = true;
152 /* Display user information as a full message.
153 if newline is true, start the message on a new line.
156 print_message (int level, const string &location, string s, bool newline)
158 /* Only print the message if the current loglevel allows it: */
159 if (!is_loglevel (level))
161 if (newline && !message_newline)
162 fputc ('\n', stderr);
164 /* Test if all silly progress_indication ("\n") can be dropped now. */
168 if (!location.empty ())
169 s = location + ": " + s;
170 fputs (s.c_str (), stderr);
173 message_newline = s[s.length () - 1] == '\n';
176 /** The actual output functions to be called in lilypond code.
177 * Sorted in descending order of importance (errors, warnings, progress, info,
178 * debug). Each prints a message on a separate line.
181 /* Display a fatal error message. Also exits lilypond. */
183 error (string s, const string &location)
185 print_message (LOG_ERROR, location, _f ("fatal error: %s", s) + "\n");
189 /* Display a severe programming error message, but don't exit. */
191 programming_error (const string &s, const string &location)
194 print_message (LOG_DEBUG, location, _f ("suppressed programming error: %s", s) + "\n");
195 else if (warning_as_error)
199 print_message (LOG_ERROR, location, _f ("programming error: %s", s) + "\n");
200 print_message (LOG_ERROR, location, _ ("continuing, cross fingers") + "\n");
204 /* Display a non-fatal error message, don't exit. */
206 non_fatal_error (const string &s, const string &location)
209 print_message (LOG_DEBUG, location, _f ("suppressed error: %s", s) + "\n");
210 else if (warning_as_error)
213 print_message (LOG_ERROR, location, _f ("error: %s", s) + "\n");
216 /* Display a warning message. */
218 warning (const string &s, const string &location)
221 print_message (LOG_DEBUG, location, _f ("suppressed warning: %s", s) + "\n");
222 else if (warning_as_error)
225 print_message (LOG_WARN, location, _f ("warning: %s", s) + "\n");
228 /* Display a success message. */
230 basic_progress (const string &s, const string &location)
232 print_message (LOG_BASIC, location, s + "\n", true);
235 /* Display information about the progress. */
237 progress_indication (const string &s, bool newline, const string &location)
239 print_message (LOG_PROGRESS, location, s, newline);
242 /* Display a single info message. */
244 message (const string &s, bool newline, const string &location)
246 // Use the progress loglevel for all normal messages (including progress msg)
247 print_message (LOG_INFO, location, s, newline);
250 /* Display a debug information, not necessarily on a new line. */
252 debug_output (const string &s, bool newline, const string &location)
254 print_message (LOG_DEBUG, location, s, newline);