Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
diagnostic.cpp
Go to the documentation of this file.
1
29#include "diagnostic.h"
30#include "scanner.h" // for Scanner::token_t
31#include "loc_exception.h"
32
33#include <cstdarg> // for va_list, ...
34#include <cstdio> // for puts(), fprintf(), ...
35#include <set> // for set
36
37
38// set of disabled warnings
39static std::set<int> disabled;
40
41static bool warn = true; // warnings (on by default)
42static bool info = false; // info messages (off by default)
43
44
45// write a warning or error message to standard output. If it is a warning
46// that is issued and that warning has not been disabled then return true.
47bool issue_diag (int type, bool, const Scanner::token_t *token,
48 const char *fmt, ...)
49{
50 bool enabled = false;
51
52 if (0 == fmt) {
53
54 // special treatment when format string is 0: a request
55 // to enable or disable this type of diagnostic, e.g.,
56 // in response to a command line option
57
58 if (W_DISABLE == type) {
59 // disable all warnings
60 enabled = warn;
61 warn = false;
62 }
63 else if (I_ENABLE == type) {
64 // enable all informational messages
65 enabled = info;
66 info = true;
67 }
68 else {
69 // disable a specific warning and return its previous
70 // setting (i.e., enabled or disabled)
71 enabled = disabled.find (type) == disabled.end ();
72 disabled.insert (type);
73 }
74
75 return enabled;
76 }
77
78 const bool is_info = I_FIRST <= type && type <= I_LAST;
79 const bool is_warn = !is_info && W_FIRST <= type && type <= W_LAST;
80 const bool is_error = !is_info && !is_warn;
81
82 if (is_warn && (!warn || disabled.end () != disabled.find (type))) {
83 // warning disabled
84 return enabled;
85 }
86
87 if (is_info && !info) {
88 // info disabled
89 return enabled;
90 }
91
92 // all errors and those warnings that are not disabled
93 // must be issued
94 enabled = true;
95
96 if (token && token->file)
97 std::fprintf (stderr, "%s:%d: ", token->file, token->line);
98
99 if (is_error)
100 std::fprintf (stderr, "Error %-3d: ", type);
101 else if (is_warn)
102 std::fprintf (stderr, "Warning %-3d: ", type);
103 else
104 std::fprintf (stderr, "Note %-3d: ", type);
105
106 // get the variable sized argument and pass it to vfprintf
107 // to be printed
108 std::va_list va;
109 va_start (va, fmt);
110 std::vfprintf (stderr, fmt, va);
111 va_end (va);
112
113 // if the token pointer is non-zero, find the file and line
114 // the token appears on and print it out, followed by a line
115 // underscoring the token that caused the diagnostic with
116 // a string of carets ('^')
117
118 std::FILE* const ftok = token ? std::fopen (token->file, "r") : 0;
119
120 if (ftok) {
121 int i;
122 char line [1024]; // FIXME: handle longer lines
123
124 // advance to the specified line in the file
125 for (i = 0; i < token->line; ++i) {
126 if (0 == std::fgets (line, 1024, ftok)) {
127 *line = '\0';
128 break;
129 }
130 }
131
132 if (i == token->line && '\0' != *line) {
133 std::fputs ("\t\t", stderr);
134 std::fputs (line, stderr);
135 std::fputs ("\t\t", stderr);
136
137 // tok->col is the column number where the first character
138 // in the token begins. Go through the line saving tabs
139 // so that the '^' will line up with the token
140
141 for (i = 0; i < token->column; ++i)
142 std::fputc (line [i] == '\t' ? '\t' : ' ', stderr);
143
144 for (unsigned j = 0; j < token->name.size (); ++j)
145 std::fputc ('^', stderr);
146
147 std::fputc ('\n', stderr);
148 }
149
150 std::fclose (ftok);
151 }
152
153 if (is_error) {
154 // throw an exception if the diagnostic is a hard error
155 throw loc_exception ();
156 }
157
158 // return otherwise (i.e., the diagnostic is not an error)
159 return enabled;
160}
#define i
Definition 17.names.cpp:126
#define line
Definition 17.names.cpp:490
#define j
Definition 17.names.cpp:127
#define va_end(ignore)
#define va_start(va, name)
#define stderr
bool issue_diag(int type, bool, const Scanner::token_t *token, const char *fmt,...)
@ I_FIRST
Definition diagnostic.h:79
@ I_ENABLE
Definition diagnostic.h:80
@ W_DISABLE
Definition diagnostic.h:62
@ W_FIRST
Definition diagnostic.h:61
@ W_LAST
Definition diagnostic.h:77
@ I_LAST
Definition diagnostic.h:87
#define is_error()
Definition parser.inl:822
std::string name
Definition scanner.h:178
const char * file
Definition scanner.h:186