coan  6.0.1
A C/C++ Configuration Analyzer
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
diagnostic.h
Go to the documentation of this file.
1 #ifndef DIAGNOSTIC_H
2 #define DIAGNOSTIC_H
3 #pragma once
4 /***************************************************************************
5  * Copyright (C) 2007-2013 Mike Kinghan, imk@burroingroingjoing.com *
6  * All rights reserved. *
7  * *
8  * Contributed originally by Mike Kinghan, imk@burroingroingjoing.com *
9  * *
10  * Redistribution and use in source and binary forms, with or without *
11  * modification, are permitted provided that the following conditions *
12  * are met: *
13  * *
14  * Redistributions of source code must retain the above copyright *
15  * notice, this list of conditions and the following disclaimer. *
16  * *
17  * Redistributions in binary form must reproduce the above copyright *
18  * notice, this list of conditions and the following disclaimer in the *
19  * documentation and/or other materials provided with the distribution. *
20  * *
21  * Neither the name of Mike Kinghan nor the names of its contributors *
22  * may be used to endorse or promote products derived from this software *
23  * without specific prior written permission. *
24  * *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT *
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS *
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE *
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, *
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, *
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS *
32  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED *
33  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,*
34  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF *
35  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
36  * DAMAGE. *
37  * *
38  **************************************************************************/
39 
40 #include "prohibit.h"
41 #include "cloner.h"
42 #include <sstream>
43 #include <list>
44 #include <memory>
45 
50 enum struct severity {
53  none = 0,
55  progress = 1,
57  info = 2,
59  warning = 4,
61  error = 8,
63  abend = 16,
65  summary = 32,
72 };
73 
77 struct emit {};
78 
82 struct defer {};
83 
85 struct diagnostic_base : private no_assign {
86 
88  using ptr = std::shared_ptr<diagnostic_base>;
89 
99  diagnostic_base(std::string const & severity_name,
100  severity level, unsigned id,
101  bool in_code_only = false);
102 
105  : _gagged(src._gagged),_text(src._text.str()) {}
106 
107 
108  virtual ~diagnostic_base() = default;
109 
111  void queue() const {
112  _queue_.push_back(ptr(clone()));
113  }
114 
116  virtual severity level() const {
117  return severity::none;
118  }
119 
127  virtual unsigned id() const {
128  return 0;
129  }
130 
138  unsigned encode() const {
139  return code(level(),id());
140  }
141 
143  explicit operator unsigned () const {
144  return encode();
145  }
146 
148  bool gagged() const {
149  return _gagged;
150  }
151 
153  std::string text() const {
154  return _text.str();
155  }
156 
158  explicit operator std::string () const {
159  return text();
160  }
161 
170  template<typename T>
171  diagnostic_base & operator<<(T const & obj) {
172  if (!_gagged) {
173  _text << obj;
174  }
175  return *this;
176  }
177 
186  if (!_gagged) {
187  queue();
188  }
189  return *this;
190  }
191 
200  if (!_gagged) {
201  despatch();
202  }
203  return *this;
204  }
205 
207  static size_t deferred() {
208  return _queue_.size();
209  }
210 
217  static size_t discard(unsigned reason) {
218  return volley(reason,&diagnostic_base::encode);
219  }
220 
227  static size_t discard(severity level) {
228  return volley(level,&diagnostic_base::level);
229  }
230 
232  static void discard_all() {
233  _queue_.resize(0);
234  }
235 
237  static size_t flush(unsigned reason) {
238  return volley(
239  reason,
242  }
243 
245  static size_t flush(severity level) {
246  return volley(
247  level,
250  }
251 
253  static void flush_all();
254 
255 
261  static void epilogue();
262 
285  static int exitcode();
286 
287 protected:
288 
290  virtual void count() const {}
291 
293  virtual diagnostic_base * clone() const {
294  return new diagnostic_base(*this);
295  }
296 
298  void despatch() const throw (unsigned);
299 
301  bool _gagged;
302 
304  std::stringstream _text;
305 
314  static unsigned code(severity level, unsigned id) {
315  return (int(level) << 8) | id;
316  }
317 
323  static std::list<ptr> _queue_;
324 
326  static unsigned _infos_;
328  static unsigned _warnings_;
330  static unsigned _errors_;
332  static unsigned _abends_;
337 
338 private:
339 
351  template<class T>
352  static size_t
354  T match,
355  T (diagnostic_base::*selector)() const,
356  void (diagnostic_base::*action)() const = nullptr)
357  {
358  if (match == T(0)) {
359  return 0;
360  }
361  size_t shots = 0;
362  std::list<ptr>::iterator qit(_queue_.begin());
363  while ( qit != _queue_.end()) {
364  if ((qit->get()->*selector)() == match) {
365  if (action) {
366  (qit->get()->*action)();
367  }
368  qit = _queue_.erase(qit);
369  ++shots;
370  } else {
371  ++qit;
372  }
373  }
374  return shots;
375  }
376 
377 };
378 
385 template<severity Level, unsigned Id>
386 struct diagnostic : cloner<diagnostic_base,diagnostic<Level,Id>>
387 {
388 
391 
393  static const severity _severity_ = Level;
395  static const unsigned _id_ = Id;
396 
401  explicit diagnostic(std::string const & severity_name)
402  : base(severity_name,Level,Id) {}
403 
405  severity level() const {
406  return Level;
407  }
408 
410  unsigned id() const {
411  return Id;
412  }
413 
415  static unsigned code() {
416  return diagnostic_base::code(Level,Id);
417  }
418 
420  static size_t discard() {
421  return diagnostic_base::discard(code());
422  }
423 
425  static size_t flush() {
426  return diagnostic_base::flush(code());
427  }
428 };
429 
434 template<unsigned Id>
435 struct progress_msg : cloner<diagnostic<severity::progress,Id>,progress_msg<Id>>
436 {
439 
442  : base("progress") {}
443 };
444 
449 template<unsigned Id>
450 struct info_msg : cloner<diagnostic<severity::info,Id>,info_msg<Id>>
451 {
454 
457  : base("info") {}
458 
459 private:
460 
462  void count() const override {
463  ++base::_infos_;
464  };
465 
466 };
467 
472 template<unsigned Id>
473 struct warning_msg : cloner<diagnostic<severity::warning,Id>,warning_msg<Id>>
474 {
477 
480  : base("warning") {}
481 
482 private:
484  virtual void count() const override {
485  ++base::_warnings_;
486  };
487 
488 };
489 
494 template<unsigned Id>
495 struct error_msg : cloner<diagnostic<severity::error,Id>,error_msg<Id>>
496 {
499 
502  : base("error") {}
503 
504 private:
506  void count() const override {
507  ++base::_errors_;
508  };
509 
510 };
511 
517 template<unsigned Id>
518 struct abend_msg : cloner<diagnostic<severity::abend,Id>,abend_msg<Id>>
519 {
522 
525  : base("abend") {}
526 
527 private:
529  void count() const override {
530  ++base::_abends_;
531  };
532 
533 };
534 
540 template<unsigned Id>
542  diagnostic<severity::summary_progress,Id> {
545  : diagnostic<severity::summary_progress,Id>("progress") {}
546 };
547 
553 template<unsigned Id>
554 struct info_summary_msg : diagnostic<severity::summary_info,Id> {
557  : diagnostic<severity::summary_info,Id>("info") {}
558 };
559 
565 template<unsigned Id>
567  diagnostic<severity::summary_warning,Id> {
570  : diagnostic<severity::summary_warning,Id>("warning") {}
571 };
572 
591 
596 
624 
629 
635 private:
637  void count() const override {
638  ++_warnings_;
640  }
641 };
647 private:
649  void count() const override {
650  ++_warnings_;
652  }
653 };
659 private:
661  void count() const override {
662  ++_warnings_;
664  }
665 };
722 
781 
782 
819 
820 
835 
836 #endif // EOF
static size_t volley(T match, T(diagnostic_base::*selector)() const, void(diagnostic_base::*action)() const =nullptr)
Call a member function on all queued diagnostics for which a given member function returns a given re...
Definition: diagnostic.h:353
diagnostic_base(diagnostic_base const &src)
Copy constructor.
Definition: diagnostic.h:104
void count() const override
Increment the global count of informational diagnostics.
Definition: diagnostic.h:462
bool gagged() const
Say whether this diagnostic is suppressed.
Definition: diagnostic.h:148
template struct warning_msg<Id> generically encapsulates a warning diagnostic.
Definition: diagnostic.h:473
A fatal error disgnostic.
static unsigned _abends_
Global count of fatal error diagnostics.
Definition: diagnostic.h:332
std::shared_ptr< diagnostic_base > ptr
Type of pointer to diagnostic_base
Definition: diagnostic.h:88
static size_t deferred()
Count the diagnostics enqueued for deferred action.
Definition: diagnostic.h:207
template struct error_msg<Id> generically encapsulates an error diagnostic.
Definition: diagnostic.h:495
An informational diagnostic.
static unsigned code(severity level, unsigned id)
Get the reason-code that encodes a causal identifier and severity.
Definition: diagnostic.h:314
static void discard_all()
Discard all queued diagnostics.
Definition: diagnostic.h:232
template struct warning_summary_msg<Id> generically encapsulates a warning summary diagnostic...
Definition: diagnostic.h:566
diagnostic_base(std::string const &severity_name, severity level, unsigned id, bool in_code_only=false)
Constructor.
Definition: diagnostic.cpp:61
progress_summary_msg()
Default constructor.
Definition: diagnostic.h:544
void queue() const
Globally enqueue a copy of this diagnostic_base for deferred action.
Definition: diagnostic.h:111
virtual unsigned id() const
Get the unique identifier of the runtime type.
Definition: diagnostic.h:127
A warning diagnostic.
virtual diagnostic_base * clone() const
Clone the runtime object on the heap.
Definition: diagnostic.h:293
static unsigned code()
Get the reason-code of this diagnostic's type.
Definition: diagnostic.h:415
static size_t flush()
Emit all deferred diagnostics of this type.
Definition: diagnostic.h:425
A progress summary.
A utility class to prevent assignment of containing class.
Definition: prohibit.h:56
A warning summary.
static void flush_all()
Emit any queued diagnostics.
Definition: diagnostic.cpp:191
A base class for diagnostic classes.
Definition: diagnostic.h:85
`template struct diagnostic<Level,Id> generically encapsulates a type of diagnostic.
Definition: diagnostic.h:386
`struct warning_unconditional_error_input' encapsulates a diagnostic for an error directive input unc...
Definition: diagnostic.h:634
template struct abend_msg generically encapsulates a fatal error diagnostic.
Definition: diagnostic.h:518
void count() const override
Increment global counts appropriately.
Definition: diagnostic.h:637
static int exitcode()
Convert the internal exit status to an exit code for exit().
Definition: diagnostic.cpp:156
template struct info_summary_msg<Id> generically encapsulates an informational summary diagnostic...
Definition: diagnostic.h:554
static std::list< ptr > _queue_
Queue of deferred diagnostics.
Definition: diagnostic.h:323
void count() const override
Increment the global count of abend diagnostics.
Definition: diagnostic.h:529
A progress diagnostic.
struct warning_unconditional_error_output encapsulates a diagnostic for an error directive output unc...
Definition: diagnostic.h:658
warning_msg()
Constructor.
Definition: diagnostic.h:479
void count() const override
Increment global counts appropriately.
Definition: diagnostic.h:661
static const severity _severity_
The severity level of this diagnostic type.
Definition: diagnostic.h:393
static unsigned _errors_
Global count of error diagnostics.
Definition: diagnostic.h:330
severity
Enumerated constants representing the severities of diagnostics.
Definition: diagnostic.h:51
unsigned id() const
Get the causal identifier of this diagnostic.
Definition: diagnostic.h:410
info_msg()
Constructor.
Definition: diagnostic.h:456
template struct progress_msg<Id>` generically encapsulates a progress diagnostic. ...
Definition: diagnostic.h:435
diagnostic_base & operator<<(T const &obj)
Insert an arbitrary object into the diagnostic.
Definition: diagnostic.h:171
static const unsigned _id_
The causal identifier of this diagnostic type.
Definition: diagnostic.h:395
virtual void count() const
Increment global counts appropriately for the runtime type.
Definition: diagnostic.h:290
An informational summary.
bool _gagged
Is the diagnostic suppressed?
Definition: diagnostic.h:301
static size_t flush(unsigned reason)
Emit all queued diagnostics that match a reason-code.
Definition: diagnostic.h:237
template struct info_msg generically encapsulates an informational diagnostic.
Definition: diagnostic.h:450
static void epilogue()
Write summary diagnostics on cerr at exit.
Definition: diagnostic.cpp:101
warning_summary_msg()
Default constructor.
Definition: diagnostic.h:569
static size_t discard()
Forget all queued diagnostics of this type.
Definition: diagnostic.h:420
The tag class is inserted in a diagnostic_base to tell it to emit itself.
Definition: diagnostic.h:77
static unsigned _error_directives_generated_
Global count of error directives output.
Definition: diagnostic.h:334
error_msg()
Constructor.
Definition: diagnostic.h:501
The tag class is inserted in a diagnostic_base to tell it to defer itself.
Definition: diagnostic.h:82
static size_t flush(severity level)
Emit all queued diagnostics that match a severity.
Definition: diagnostic.h:245
diagnostic_base & operator<<(defer)
Queue the diagnostic for deferred action.
Definition: diagnostic.h:185
An error diagnostic.
static unsigned _error_directives_operative_
Global count of operative error directives output.
Definition: diagnostic.h:336
std::string text() const
Get the text of the diagnostic.
Definition: diagnostic.h:153
A summary diagnostic.
template struct cloner<B,D> is a base template from which derived instantiations can inherit cloneabi...
Definition: cloner.h:48
progress_msg()
Constructor.
Definition: diagnostic.h:441
template struct progress_summary_msg<Id> generically encapsulates a progress summary diagnostic...
Definition: diagnostic.h:541
diagnostic_base & operator<<(emit)
Emit the diagnostic.
Definition: diagnostic.h:199
virtual severity level() const
Get the severity level of the runtime type.
Definition: diagnostic.h:116
static size_t discard(unsigned reason)
Discard any queued diagnostics that match a reason-code, returning the number discarded.
Definition: diagnostic.h:217
virtual void count() const override
Increment the global count of warning diagnostics.
Definition: diagnostic.h:484
`template struct warning_error_generated_input' encapsulates a diagnostic for error directive output ...
Definition: diagnostic.h:646
abend_msg()
Constructor.
Definition: diagnostic.h:524
static unsigned _warnings_
Global count of warning diagnostics.
Definition: diagnostic.h:328
static size_t discard(severity level)
Discard any queued diagnostics that match a severity, returning the number discarded.
Definition: diagnostic.h:227
void count() const override
Increment the global count of error diagnostics.
Definition: diagnostic.h:506
severity level() const
Get the severity level of this diagnostic.
Definition: diagnostic.h:405
unsigned encode() const
Get the reason-code of the diagnostic.
Definition: diagnostic.h:138
void count() const override
Increment global counts appropriately.
Definition: diagnostic.h:649
std::stringstream _text
The text of the diagnostic.
Definition: diagnostic.h:304
static unsigned _infos_
Global count of informational diagnostics.
Definition: diagnostic.h:326
diagnostic(std::string const &severity_name)
Explicitly construct given a severity name.
Definition: diagnostic.h:401
No severity.
void despatch() const
Emit the diagnostic.
Definition: diagnostic.cpp:87
info_summary_msg()
Default constructor.
Definition: diagnostic.h:556