]> git.donarmstrong.com Git - lilypond.git/blob - flower/warn.cc
Merge branch 'master' into lilypond/translation
[lilypond.git] / flower / warn.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 1997--2011 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 "warn.hh"
21
22 #include <cstdlib>
23 #include <cstdio>
24
25 #include "international.hh"
26
27 using namespace std;
28
29 /** We have several different loglevels, each with its own message function(s):
30       ERROR: error, non_fatal_error, programming_error
31       WARN: warning
32       BASIC_PROGRESS: success/...
33       PROGRESS: progress_indication
34       INFO: message
35       DEBUG: debug
36   All these functions check whether the corresponding loglevel bit is set
37   and print the message only if that's the case
38 */
39
40 /* Define the loglevel (default is INFO) */
41 int loglevel = LOGLEVEL_INFO;
42
43 bool
44 is_loglevel (int level)
45 {
46   // Check the bitmask containing the loglevel
47   return (loglevel & level);
48 }
49
50 void
51 set_loglevel (int level)
52 {
53   loglevel = level;
54   debug_output (_f ("Log level set to %d\n", loglevel));
55 }
56
57 void
58 set_loglevel (string level)
59 {
60   /* Convert the loglevel string to lower-case, so we allow
61      both upper- and lower-case loglevels */
62   std::transform (level.begin (), level.end (), level.begin (), ::tolower);
63
64   /* Compare just the first few characters, so the loglevels
65      can be abbreviated */
66   if (level.compare (0, 5, "debug") == 0) // debug
67     set_loglevel (LOGLEVEL_DEBUG);
68   else if (level.compare (0, 4, "info") == 0) // info
69     set_loglevel (LOGLEVEL_INFO);
70   else if (level.compare (0, 4, "prog") == 0) // progress
71     set_loglevel (LOGLEVEL_PROGRESS);
72   else if (level.compare (0, 5, "basic") == 0) // basic progress
73     set_loglevel (LOGLEVEL_BASIC);
74   else if (level.compare (0, 4, "warn") == 0) // warning
75     set_loglevel (LOGLEVEL_WARN);
76   else if (level.compare (0, 3, "err") == 0) // error
77     set_loglevel (LOGLEVEL_ERROR);
78   else if (level.compare (0, 4, "none") == 0) // none
79     set_loglevel (LOGLEVEL_NONE);
80   else
81     {
82       int l;
83       if (sscanf (level.c_str (), "%d", &l))
84         set_loglevel (l);
85       else
86         {
87           non_fatal_error (_f ("unknown log level `%s', using default (INFO)", 
88                                level));
89           set_loglevel (LOGLEVEL_INFO);
90         }
91     }
92 }
93
94
95 /**
96  * Helper functions: print_message_part (no newline prepended)
97  *                   print_message (always starts on a new line)
98  */
99
100 /* Is output message at NEWLINE?  */
101 static bool message_newline = true;
102
103 /* Display user information as a full message.
104    if newline is true, start the message on a new line.
105 */
106 void
107 print_message (int level, string location, string s, bool newline)
108 {
109   /* Only print the message if the current loglevel allows it: */
110   if (!is_loglevel (level))
111     return;
112   if (newline && !message_newline)
113     fputc ('\n', stderr);
114
115   /* Test if all silly progress_indication ("\n") can be dropped now.  */
116   if (s == "\n")
117     return;
118
119   if (!location.empty ())
120     s = location + ": " + s;
121   fputs (s.c_str (), stderr);
122   fflush (stderr);
123   if (s.length ())
124     message_newline = s[s.length () - 1] == '\n';
125 }
126
127
128 /** The actual output functions to be called in lilypond code.
129  *  Sorted in descending order of importance (errors, warnings, progress, info,
130  *  debug). Each prints a message on a separate line.
131  */
132
133 /* Display a fatal error message.  Also exits lilypond.  */
134 void
135 error (string s, string location)
136 {
137   print_message (LOG_ERROR, location, _f ("fatal error: %s", s) + "\n");
138   exit (1);
139 }
140
141 /* Display a severe programming error message, but don't exit.  */
142 void
143 programming_error (string s, string location)
144 {
145   print_message (LOG_ERROR, location, _f ("programming error: %s", s) + "\n");
146   print_message (LOG_ERROR, location, _ ("continuing, cross fingers") + "\n");
147 }
148
149 /* Display a non-fatal error message, don't exit.  */
150 void
151 non_fatal_error (string s, string location)
152 {
153   print_message (LOG_ERROR, location, _f ("error: %s", s) + "\n");
154 }
155
156 /* Display a warning message. */
157 void
158 warning (string s, string location)
159 {
160   print_message (LOG_WARN, location, _f ("warning: %s", s) + "\n");
161 }
162
163 /* Display a success message.  */
164 void
165 successful (string s, string location)
166 {
167   print_message (LOG_BASIC, location, _f ("success: %s", s) + "\n", true);
168 }
169
170 /* Display information about the progress.  */
171 void
172 progress_indication (string s, bool newline, string location)
173 {
174   print_message (LOG_PROGRESS, location, s, newline);
175 }
176
177 /* Display a single info message.  */
178 void
179 message (string s, bool newline, string location)
180 {
181   // Use the progress loglevel for all normal messages (including progress msg)
182   print_message (LOG_INFO, location, s, newline);
183 }
184
185 /* Display a debug information, not necessarily on a new line.  */
186 void
187 debug_output (string s, bool newline, string location)
188 {
189   print_message (LOG_DEBUG, location, s, newline);
190 }