Doxygen
message.cpp
浏览该文件的文档.
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2020 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15 
16 #include <stdio.h>
17 #include "config.h"
18 #include "debug.h"
19 #include "portable.h"
20 #include "message.h"
21 #include "doxygen.h"
22 
23 #include <mutex>
24 
25 // globals
27 static const char * g_warningStr = "warning: ";
28 static const char * g_errorStr = "error: ";
29 static FILE * g_warnFile = stderr;
30 static WARN_AS_ERROR_t g_warnBehavior = WARN_AS_ERROR_t::NO;
31 static bool g_warnStat = false;
32 static std::mutex g_mutex;
33 
35 {
36  g_warnFormat = Config_getString(WARN_FORMAT);
37  if (!Config_getString(WARN_LOGFILE).isEmpty())
38  {
39  g_warnFile = Portable::fopen(Config_getString(WARN_LOGFILE).data(),"w");
40  }
41  if (!g_warnFile) // point it to something valid, because warn() relies on it
42  {
43  g_warnFile = stderr;
44  }
45  g_warnBehavior = Config_getEnum(WARN_AS_ERROR);
46  if (g_warnBehavior != WARN_AS_ERROR_t::NO)
47  {
49  }
50 }
51 
52 
53 void msg(const char *fmt, ...)
54 {
55  if (!Config_getBool(QUIET))
56  {
57  std::unique_lock<std::mutex> lock(g_mutex);
59  {
60  printf("%.3f sec: ",((double)Debug::elapsedTime()));
61  }
62  va_list args;
63  va_start(args, fmt);
64  vfprintf(stdout, fmt, args);
65  va_end(args);
66  }
67 }
68 
69 static void format_warn(const QCString &file,int line,const QCString &text)
70 {
71  QCString fileSubst = file.isEmpty() ? "<unknown>" : file;
72  QCString lineSubst; lineSubst.setNum(line);
73  QCString textSubst = text;
74  QCString versionSubst;
75  // substitute markers by actual values
76  QCString msgText =
77  substitute(
78  substitute(
79  substitute(
80  substitute(
82  "$file",fileSubst
83  ),
84  "$line",lineSubst
85  ),
86  "$version",versionSubst
87  ),
88  "$text",textSubst
89  );
90  if (g_warnBehavior == WARN_AS_ERROR_t::YES)
91  {
92  msgText += " (warning treated as error, aborting now)";
93  }
94  msgText += '\n';
95 
96  {
97  std::unique_lock<std::mutex> lock(g_mutex);
98  // print resulting message
99  fwrite(msgText.data(),1,msgText.length(),g_warnFile);
100  }
101  if (g_warnBehavior == WARN_AS_ERROR_t::YES)
102  {
103  exit(1);
104  }
105  g_warnStat = true;
106 }
107 
108 static void handle_warn_as_error()
109 {
110  if (g_warnBehavior == WARN_AS_ERROR_t::YES)
111  {
112  {
113  std::unique_lock<std::mutex> lock(g_mutex);
114  QCString msgText = " (warning treated as error, aborting now)\n";
115  fwrite(msgText.data(),1,msgText.length(),g_warnFile);
116  }
117  exit(1);
118  }
119  g_warnStat = true;
120 }
121 
122 static void do_warn(bool enabled, const QCString &file, int line, const char *prefix, const char *fmt, va_list args)
123 {
124  if (!enabled) return; // warning type disabled
125 
126  va_list argsCopy;
127  va_copy(argsCopy, args);
128 
129  int l=0;
130  if (prefix)
131  {
132  l=(int)strlen(prefix);
133  }
134  // determine needed buffersize based on:
135  // format + arguments
136  // prefix
137  // 1 position for `\0`
138  int bufSize = vsnprintf(NULL, 0, fmt, args) + l + 1;
139  QCString text(bufSize);
140  if (prefix)
141  {
142  qstrncpy(text.rawData(),prefix,bufSize);
143  }
144  vsnprintf(text.rawData()+l, bufSize-l, fmt, argsCopy);
145  text[bufSize-1]='\0';
146  format_warn(file,line,text);
147 
148  va_end(argsCopy);
149 }
150 
151 void warn(const QCString &file,int line,const char *fmt, ...)
152 {
153  va_list args;
154  va_start(args, fmt);
155  do_warn(Config_getBool(WARNINGS), file, line, g_warningStr, fmt, args);
156  va_end(args);
157 }
158 
159 void va_warn(const QCString &file,int line,const char *fmt,va_list args)
160 {
161  do_warn(Config_getBool(WARNINGS), file, line, g_warningStr, fmt, args);
162 }
163 
164 void warn_simple(const QCString &file,int line,const char *text)
165 {
166  if (!Config_getBool(WARNINGS)) return; // warning type disabled
167  format_warn(file,line,QCString(g_warningStr) + text);
168 }
169 
170 void warn_undoc(const QCString &file,int line,const char *fmt, ...)
171 {
172  va_list args;
173  va_start(args, fmt);
174  do_warn(Config_getBool(WARN_IF_UNDOCUMENTED), file, line, g_warningStr, fmt, args);
175  va_end(args);
176 }
177 
178 void warn_incomplete_doc(const QCString &file,int line,const char *fmt, ...)
179 {
180  va_list args;
181  va_start(args, fmt);
182  do_warn(Config_getBool(WARN_IF_INCOMPLETE_DOC), file, line, g_warningStr, fmt, args);
183  va_end(args);
184 }
185 
186 void warn_doc_error(const QCString &file,int line,const char *fmt, ...)
187 {
188  va_list args;
189  va_start(args, fmt);
190  do_warn(Config_getBool(WARN_IF_DOC_ERROR), file, line, g_warningStr, fmt, args);
191  va_end(args);
192 }
193 
194 void warn_uncond(const char *fmt, ...)
195 {
196  va_list args;
197  va_start(args, fmt);
198  vfprintf(g_warnFile, (QCString(g_warningStr) + fmt).data(), args);
199  va_end(args);
201 }
202 
203 void err(const char *fmt, ...)
204 {
205  va_list args;
206  va_start(args, fmt);
207  vfprintf(g_warnFile, (QCString(g_errorStr) + fmt).data(), args);
208  va_end(args);
210 }
211 
212 extern void err_full(const QCString &file,int line,const char *fmt, ...)
213 {
214  va_list args;
215  va_start(args, fmt);
216  do_warn(TRUE, file, line, g_errorStr, fmt, args);
217  va_end(args);
218 }
219 
220 void term(const char *fmt, ...)
221 {
222  {
223  std::unique_lock<std::mutex> lock(g_mutex);
224  va_list args;
225  va_start(args, fmt);
226  vfprintf(g_warnFile, (QCString(g_errorStr) + fmt).data(), args);
227  va_end(args);
228  if (g_warnFile != stderr)
229  {
230  for (int i = 0; i < (int)strlen(g_errorStr); i++) fprintf(g_warnFile, " ");
231  fprintf(g_warnFile, "%s\n", "Exiting...");
232  }
233  }
234  exit(1);
235 }
236 
238 {
239  fflush(g_warnFile);
240 }
241 
242 
243 void printlex(int dbg, bool enter, const char *lexName, const char *fileName)
244 {
245  const char *enter_txt = "entering";
246  const char *enter_txt_uc = "Entering";
247 
248  if (!enter)
249  {
250  enter_txt = "finished";
251  enter_txt_uc = "Finished";
252  }
253 
254  std::unique_lock<std::mutex> lock(g_mutex);
255  if (dbg)
256  {
257  if (fileName)
258  fprintf(stderr,"--%s lexical analyzer: %s (for: %s)\n",enter_txt, qPrint(lexName), qPrint(fileName));
259  else
260  fprintf(stderr,"--%s lexical analyzer: %s\n",enter_txt, qPrint(lexName));
261  }
262  else
263  {
264  if (fileName)
265  Debug::print(Debug::Lex,0,"%s lexical analyzer: %s (for: %s)\n",enter_txt_uc, qPrint(lexName), qPrint(fileName));
266  else
267  Debug::print(Debug::Lex,0,"%s lexical analyzer: %s\n",enter_txt_uc, qPrint(lexName));
268  }
269 }
270 
271 extern void finishWarnExit()
272 {
273  if (g_warnStat && g_warnBehavior == WARN_AS_ERROR_t::FAIL_ON_WARNINGS)
274  {
275  exit(1);
276  }
277 }
g_warnFile
static FILE * g_warnFile
Definition: message.cpp:29
g_warningStr
static const char * g_warningStr
Definition: message.cpp:27
warn_incomplete_doc
void warn_incomplete_doc(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:178
g_warnBehavior
static WARN_AS_ERROR_t g_warnBehavior
Definition: message.cpp:30
QCString::rawData
char * rawData()
Returns a writable pointer to the data.
Definition: qcstring.h:157
Config_getEnum
#define Config_getEnum(name)
Definition: config.h:35
finishWarnExit
void finishWarnExit()
Definition: message.cpp:271
Portable::fopen
FILE * fopen(const QCString &fileName, const QCString &mode)
Definition: portable.cpp:322
g_mutex
static std::mutex g_mutex
Definition: message.cpp:32
QCString::length
uint length() const
Returns the length of the string, not counting the 0-terminator.
Definition: qcstring.h:147
QCString::isEmpty
bool isEmpty() const
Returns TRUE iff the string is empty
Definition: qcstring.h:144
qstrncpy
char * qstrncpy(char *dst, const char *src, size_t len)
Definition: qcstring.cpp:423
warn_flush
void warn_flush()
Definition: message.cpp:237
g_warnFormat
static QCString g_warnFormat
Definition: message.cpp:26
Debug::Lex
@ Lex
Definition: debug.h:39
warn_doc_error
void warn_doc_error(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:186
err
void err(const char *fmt,...)
Definition: message.cpp:203
warn_simple
void warn_simple(const QCString &file, int line, const char *text)
Definition: message.cpp:164
do_warn
static void do_warn(bool enabled, const QCString &file, int line, const char *prefix, const char *fmt, va_list args)
Definition: message.cpp:122
warn
void warn(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:151
Debug::isFlagSet
static bool isFlagSet(DebugMask mask)
Definition: debug.cpp:99
format_warn
static void format_warn(const QCString &file, int line, const QCString &text)
Definition: message.cpp:69
warn_uncond
void warn_uncond(const char *fmt,...)
Definition: message.cpp:194
message.h
Debug::print
static void print(DebugMask mask, int prio, const char *fmt,...)
Definition: debug.cpp:57
initWarningFormat
void initWarningFormat()
Definition: message.cpp:34
g_warnStat
static bool g_warnStat
Definition: message.cpp:31
doxygen.h
warn_undoc
void warn_undoc(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:170
TRUE
#define TRUE
Definition: qcstring.h:36
va_warn
void va_warn(const QCString &file, int line, const char *fmt, va_list args)
Definition: message.cpp:159
printlex
void printlex(int dbg, bool enter, const char *lexName, const char *fileName)
Definition: message.cpp:243
QCString::setNum
QCString & setNum(short n)
Definition: qcstring.h:372
Debug::elapsedTime
static double elapsedTime()
Definition: debug.cpp:138
substitute
QCString substitute(const QCString &s, const QCString &src, const QCString &dst)
substitute all occurrences of src in s by dst
Definition: qcstring.cpp:465
Config_getBool
#define Config_getBool(name)
Definition: config.h:33
handle_warn_as_error
static void handle_warn_as_error()
Definition: message.cpp:108
msg
void msg(const char *fmt,...)
Definition: message.cpp:53
term
void term(const char *fmt,...)
Definition: message.cpp:220
g_errorStr
static const char * g_errorStr
Definition: message.cpp:28
qPrint
const char * qPrint(const char *s)
Definition: qcstring.h:589
Debug::Time
@ Time
Definition: debug.h:35
Config_getString
#define Config_getString(name)
Definition: config.h:32
config.h
err_full
void err_full(const QCString &file, int line, const char *fmt,...)
Definition: message.cpp:212
QCString::data
const char * data() const
Returns a pointer to the contents of the string in the form of a 0-terminated C string
Definition: qcstring.h:153
portable.h
Portable versions of functions that are platform dependent.
debug.h
QCString
This is an alternative implementation of QCString.
Definition: qcstring.h:108