Ne.app NeANT
The Ne.app NeANT User module of the NeANT distribution.
opt_diags.cpp
Go to the documentation of this file.
1
29// expand _TEST_EXPORT macros
30#define _RWSTD_TEST_SRC
31
32#include "opt_diags.h"
33
34#include <assert.h> // for assert()
35#include <stdio.h> // for fprintf()
36#include <string.h> // for strlen(), strncmp(), ...
37
38
39#define ESC "\x1b"
40#define ESC_END ESC "[30;30;0m"
41#define ESC_CODE(fg, bg, attr) ESC "[" fg bg attr "m", ESC_END
42
43
44// ANSI VT100 terminal codes:
45#define AT_OFF "0;" // all attributes off
46#define AT_BLD "1;" // bright/bold
47#define AT_DIM "2;" // dim
48// #define AT_??? "3;" // ???
49#define AT_UND "4;" // underscore
50#define AT_BLI "5;" // blink
51// #define AT_??? "6;" // ???
52#define AT_RVS "7;" // reverse video
53#define AT_HID "8;" // hidden
54
55#define FG_BLK "30;" // foreground black
56#define FG_RED "31;" // foreground red
57#define FG_GRN "32;" // foreground green
58#define FG_YLW "33;" // foreground yellow
59#define FG_BLU "34;" // foreground blue
60#define FG_MAG "35;" // foreground magenta
61#define FG_CYN "36;" // foreground cyan
62#define FG_WHT "37;" // foreground white
63
64#define BG_BLK "40;" // background black
65#define BG_RED "41;" // background red
66#define BG_GRN "42;" // background green
67#define BG_YLW "43;" // background yellow
68#define BG_BLU "44;" // background blue
69#define BG_MAG "45;" // background magenta
70#define BG_CYN "46;" // background cyan
71#define BG_WHT "47;" // background white
72
73
75 /* severity 0 */ {
76 ESC_CODE (FG_CYN, "", AT_DIM),
77 "ITRACE",
78 "inactive diagnostic trace"
79 },
80 /* severity 1 */ {
81 ESC_CODE (FG_BLK, "", ""),
82 "INFO",
83 "information"
84 },
85 /* severity 2 */ {
86 ESC_CODE (FG_GRN, "", AT_BLI),
87 "NOTE",
88 "noteworthy event"
89 },
90 /* severity 3 */ {
92 "EXPECT",
93 "expected diagnostic inactive"
94 },
95 /* severity 4 */ {
96 ESC_CODE (FG_MAG, "", ""),
97 "XWARN",
98 "expected warning"
99 },
100 /* severity 5 */ {
102 "WARNING",
103 ""
104 },
105 /* severity 6 */ {
106 ESC_CODE (FG_RED, "", ""),
107 "XASSERT",
108 "expected assertion"
109 },
110 /* severity 7 */ {
112 "ASSERTION",
113 ""
114 },
115 /* severity 8 */ {
117 "ERROR",
118 "test error"
119 },
120 /* severity 9 */ {
122 "FATAL",
123 "fatal test error, abort imminent"
124 }
125};
126
127
128static const esc_text_t
129_rw_vt100_colors[] = {
130 // prefix suffix code description
131 { FG_BLK, ESC_END, "black", "" },
132 { FG_RED, ESC_END, "red", "" },
133 { FG_GRN, ESC_END, "green", "" },
134 { FG_YLW, ESC_END, "yellow", "" },
135 { FG_BLU, ESC_END, "blue", "" },
136 { FG_MAG, ESC_END, "magenta", "" },
137 { FG_CYN, ESC_END, "cyan", "" },
138 { FG_WHT, ESC_END, "white", "" }
139};
140
141
142static const esc_text_t
143_rw_vt100_attribs[] = {
144 // prefix suffix code description
145 { AT_OFF, ESC_END, "off", "" },
146 { AT_BLD, ESC_END, "bold", "" },
147 { AT_DIM, ESC_END, "dim", "" },
148 { AT_UND, ESC_END, "underscore", "" },
149 { AT_BLI, ESC_END, "blink", "" },
150 { AT_RVS, ESC_END, "reverse", "" },
151 { AT_HID, ESC_END, "hidden", "" }
152};
153
154
155static int
156_rw_match_name (const esc_text_t *text, size_t nelems,
157 const char *first, const char *last)
158{
159 assert (0 != text);
160 assert (0 != first);
161 assert (first <= last);
162
163 const size_t len = size_t (last - first);
164
165 if (0 == len)
166 return int (nelems);
167
168 for (size_t i = 0; i != nelems; ++i) {
169 if ( 0 == strncmp (text [i].code, first, len)
170 && '\0' == text [i].code [len])
171 return int (i);
172 }
173
174 return -1;
175}
176
177
178/* extern */ int
179_rw_setopt_diags (int argc, char *argv[])
180{
181 if (1 == argc && argv && 0 == argv [0]) {
182 static const char helpstr[] = {
183 "Sets the colors and names of the diagnostic messages issued by\n"
184 "the program.\n"
185 "There are 10 different types of diagnostic messages, each with\n"
186 "a unique severity level between 0 (the lowest) and 9. Each\n"
187 "diagnostic message can either be active or inactive. Each\n"
188 "message can have a name of up to 15 characters associated with\n"
189 "it, foreground color, background color, and a video attribute.\n"
190 "These parameters are controlled by the argument to this option.\n"
191 "\nThe syntax of <arg> is as follows:\n"
192 "<arg> ::= <color-list>\n"
193 "<color-list> ::= <color-txt> [ ,<color-list> ]\n"
194 "<color-txt> ::= <sev>:[<color>][:[<color>][:[<attr>][:[<text>]]]]"
195 "\n<sev> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9\n"
196 "<color> ::= black | red | green | yellow\n"
197 " | blue | magenta | cyan | white\n"
198 "<attr> ::= off | bold | dim | underscore\n"
199 " | blink | reverse | hidden\n"
200 "<text> ::= A-Z a-z 0-9 _\n\n"
201 "The first <color> component specifies the foreground color\n"
202 "while the second (optional) <color> component specifies\n"
203 "the background color for the diagnostic of the severity <sev>.\n"
204 "Empty arguments are permitted and denote the default system\n"
205 "color set for the terminal.\n"
206 };
207
208 argv [0] = _RWSTD_CONST_CAST (char*, helpstr);
209
210 return 0;
211 }
212
213 char *parg = strchr (argv [0], '=');
214
215 if (0 == parg || '\0' == parg [1]) {
216 fprintf (stderr, "%s:%d: missing argument in %s\n",
217 __FILE__, __LINE__, argv [0]);
218 return 1;
219 }
220
221 ++parg;
222
223 // argument syntax:
224 //
225 // <sev-color-list> := <sev-color-text> [ ,<sev-color-list> ]
226 // <sev-color-text> := <sev>:[<color>][:[<color>][:[<attr>][:[<text>]]]]
227 // <sev> := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
228 // <color> := black | red | green | yellow
229 // | blue | magenta | cyan | white
230 // <attr> := off | bold | dim | underscore
231 // | blink | reverse | hidden
232 // <text> := A-Z a-z 0-9 _
233
234
235 int ret = 0;
236
237 while (*parg) {
238
239 int sev = -1;
240 int fgcol = -1;
241 int bgcol = -1;
242 int attr = -1;
243
244 char diag_code [sizeof diag_msgs [0].code];
245 *diag_code = '\0';
246
247 if ('0' <= *parg && *parg <= '9') {
248 sev = *parg++ - '0';
249 }
250 else {
251 // digit expected
252 fprintf (stderr, "%s:%d: digit expected at position %d: %s\n",
253 __FILE__, __LINE__, int (parg - argv [0]), argv [0]);
254
255 ret = 1;
256 break;
257 }
258
259 if (':' == *parg) {
260 ++parg;
261 }
262 else {
263 // colon expected
264 fprintf (stderr, "%s:%d: colon expected at position %d: %s\n",
265 __FILE__, __LINE__, int (parg - argv [0]), argv [0]);
266
267 ret = 1;
268 break;
269 }
270
271 char *end = strpbrk (parg, ":,");
272 if (0 == end)
273 end = parg + strlen (parg);
274
275 fgcol = _rw_match_name (_rw_vt100_colors, 8, parg, end);
276 if (fgcol < 0 || 8 < fgcol) {
277 // invalid color
278 fprintf (stderr, "%s:%d: unknown color at position %d: %s\n",
279 __FILE__, __LINE__, int (parg - argv [0]), argv [0]);
280
281 ret = 1;
282 break;
283 }
284
285 RW_ASSERT (0 != end);
286
287 if (':' == *end || '\0' == *end) {
288 parg = end + (0 != *end);
289 end = strpbrk (parg, ":,");
290 if (0 == end)
291 end = parg + strlen (parg);
292
293 bgcol = _rw_match_name (_rw_vt100_colors, 8, parg, end);
294
295 if (bgcol < 0 || 8 < bgcol) {
296 // invalid color
297 fprintf (stderr, "%s:%d: unknown color at position %d: %s\n",
298 __FILE__, __LINE__, int (parg - argv [0]), argv [0]);
299
300 ret = 1;
301 break;
302 }
303
304 RW_ASSERT (0 != end);
305
306 if (':' == *end || '\0' == *end) {
307 parg = end + ('\0' != *end);
308 end = strpbrk (parg, ":,");
309 if (0 == end)
310 end = parg + strlen (parg);
311
312 attr = _rw_match_name (_rw_vt100_attribs, 8, parg, end);
313 if (attr < 0 || 8 < attr) {
314 // invalid attribute
315 fprintf (stderr,
316 "%s:%d: unknown attribute at position %d: %s\n",
317 __FILE__, __LINE__, int (parg - argv [0]),
318 argv [0]);
319
320 ret = 1;
321 break;
322 }
323
324 RW_ASSERT (0 != end);
325
326 if (':' == *end || '\0' == *end) {
327 parg = end + (0 != *end);
328 end = strpbrk (parg, ":,");
329 if (0 == end)
330 end = parg + strlen (parg);
331
332 size_t len = size_t (end - parg);
333
334 if (sizeof diag_msgs [sev].code < len) {
335
336 // name too long
337 fprintf (stderr,
338 "%s:%d: name too long at position %d: %s\n",
339 __FILE__, __LINE__, int (parg - argv [0]),
340 argv [0]);
341
342 len = strlen (diag_msgs [sev].code);
343 }
344
345 memcpy (diag_code, parg, len);
346 diag_code [len] = '\0';
347 }
348 }
349 }
350
351 strcpy (diag_msgs [sev].esc_pfx, ESC "[");
352
353 if (-1 < fgcol && fgcol < 8)
354 strcat (diag_msgs [sev].esc_pfx, _rw_vt100_colors [fgcol].esc_pfx);
355
356 if (-1 < bgcol && bgcol < 8) {
357 strcat (diag_msgs [sev].esc_pfx, _rw_vt100_colors [bgcol].esc_pfx);
358
359 const size_t bgdiginx = strlen (diag_msgs [sev].esc_pfx) - 3;
360
361 assert ('3' == diag_msgs [sev].esc_pfx [bgdiginx]);
362 diag_msgs [sev].esc_pfx [bgdiginx] = '4';
363 }
364
365 if (-1 < attr && attr < 8)
366 strcat (diag_msgs [sev].esc_pfx, _rw_vt100_attribs [attr].esc_pfx);
367
368 if (diag_msgs [sev].esc_pfx [2]) {
369 strcat (diag_msgs [sev].esc_pfx, "m");
370 strcpy (diag_msgs [sev].esc_sfx, ESC_END);
371 }
372 else {
373 diag_msgs [sev].esc_pfx [0] = '\0';
374 diag_msgs [sev].esc_sfx [0] = '\0';
375 }
376
377 if (*diag_code)
378 strcpy (diag_msgs [sev].code, diag_code);
379
380 parg = end + ('\0' != *end);
381 }
382
383 return ret;
384}
#define i
Definition 17.names.cpp:126
#define last
Definition 17.names.cpp:487
#define len
Definition 17.names.cpp:488
const int end
#define assert(expr)
Definition _cassert.h:40
#define stderr
#define _RWSTD_CONST_CAST(T, x)
Definition _defs.h:536
#define AT_DIM
Definition opt_diags.cpp:47
#define FG_RED
Definition opt_diags.cpp:56
#define FG_WHT
Definition opt_diags.cpp:62
#define FG_YLW
Definition opt_diags.cpp:58
int _rw_setopt_diags(int argc, char *argv[])
#define ESC
Definition opt_diags.cpp:39
#define FG_BLK
Definition opt_diags.cpp:55
#define FG_BLU
Definition opt_diags.cpp:59
#define AT_HID
Definition opt_diags.cpp:53
#define AT_UND
Definition opt_diags.cpp:49
#define AT_BLI
Definition opt_diags.cpp:50
#define ESC_END
Definition opt_diags.cpp:40
#define FG_GRN
Definition opt_diags.cpp:57
#define AT_OFF
Definition opt_diags.cpp:45
#define ESC_CODE(fg, bg, attr)
Definition opt_diags.cpp:41
#define FG_MAG
Definition opt_diags.cpp:60
#define FG_CYN
Definition opt_diags.cpp:61
#define BG_RED
Definition opt_diags.cpp:65
#define AT_BLD
Definition opt_diags.cpp:46
#define BG_GRN
Definition opt_diags.cpp:66
esc_text_t diag_msgs[]
Definition opt_diags.cpp:74
#define AT_RVS
Definition opt_diags.cpp:52
#define RW_ASSERT(expr)
char esc_pfx[40]
Definition opt_diags.h:54
char esc_sfx[40]
Definition opt_diags.h:55
char code[16]
Definition opt_diags.h:56