Annotation of src/usr.bin/mandoc/mandoc_msg.c, Revision 1.17
1.17 ! schwarze 1: /* $OpenBSD: mandoc_msg.c,v 1.16 2022/04/28 16:16:46 schwarze Exp $ */
1.1 schwarze 2: /*
1.15 schwarze 3: * Copyright (c) 2014-2022 Ingo Schwarze <schwarze@openbsd.org>
1.1 schwarze 4: * Copyright (c) 2010, 2011 Kristaps Dzonsons <kristaps@bsd.lv>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.9 schwarze 17: *
18: * Implementation of warning and error messages for mandoc(1).
1.1 schwarze 19: */
20: #include <stdarg.h>
21: #include <stdio.h>
22: #include <stdlib.h>
23:
24: #include "mandoc.h"
25:
26: static const enum mandocerr lowest_type[MANDOCLEVEL_MAX] = {
27: MANDOCERR_OK,
28: MANDOCERR_OK,
29: MANDOCERR_WARNING,
30: MANDOCERR_ERROR,
31: MANDOCERR_UNSUPP,
1.5 schwarze 32: MANDOCERR_BADARG,
33: MANDOCERR_SYSERR
1.1 schwarze 34: };
35:
36: static const char *const level_name[MANDOCLEVEL_MAX] = {
37: "SUCCESS",
38: "STYLE",
39: "WARNING",
40: "ERROR",
41: "UNSUPP",
42: "BADARG",
43: "SYSERR"
44: };
45:
46: static const char *const type_message[MANDOCERR_MAX] = {
47: "ok",
48:
49: "base system convention",
50:
51: "Mdocdate found",
52: "Mdocdate missing",
53: "unknown architecture",
54: "operating system explicitly specified",
55: "RCS id missing",
56:
57: "generic style suggestion",
58:
59: "legacy man(7) date format",
60: "normalizing date format to",
61: "lower case character in document title",
62: "duplicate RCS id",
63: "possible typo in section name",
64: "unterminated quoted argument",
65: "useless macro",
66: "consider using OS macro",
67: "errnos out of order",
68: "duplicate errno",
1.11 schwarze 69: "referenced manual not found",
1.1 schwarze 70: "trailing delimiter",
71: "no blank before trailing delimiter",
72: "fill mode already enabled, skipping",
73: "fill mode already disabled, skipping",
1.12 schwarze 74: "input text line longer than 80 bytes",
1.1 schwarze 75: "verbatim \"--\", maybe consider using \\(em",
76: "function name without markup",
77: "whitespace at end of input line",
78: "bad comment style",
79:
80: "generic warning",
81:
82: /* related to the prologue */
83: "missing manual title, using UNTITLED",
84: "missing manual title, using \"\"",
85: "missing manual section, using \"\"",
86: "unknown manual section",
1.9 schwarze 87: "filename/section mismatch",
1.7 schwarze 88: "missing date, using \"\"",
1.1 schwarze 89: "cannot parse date, using it verbatim",
90: "date in the future, using it anyway",
91: "missing Os macro, using \"\"",
92: "late prologue macro",
93: "prologue macros out of order",
94:
95: /* related to document structure */
96: ".so is fragile, better use ln(1)",
97: "no document body",
98: "content before first section header",
99: "first section is not \"NAME\"",
100: "NAME section without Nm before Nd",
101: "NAME section without description",
102: "description not at the end of NAME",
103: "bad NAME section content",
104: "missing comma before name",
105: "missing description line, using \"\"",
106: "description line outside NAME section",
107: "sections out of conventional order",
108: "duplicate section title",
109: "unexpected section",
110: "cross reference to self",
111: "unusual Xr order",
112: "unusual Xr punctuation",
113: "AUTHORS section without An macro",
114:
115: /* related to macros and nesting */
116: "obsolete macro",
117: "macro neither callable nor escaped",
118: "skipping paragraph macro",
119: "moving paragraph macro out of list",
120: "skipping no-space macro",
121: "blocks badly nested",
122: "nested displays are not portable",
123: "moving content out of list",
124: "first macro on line",
125: "line scope broken",
126: "skipping blank line in line scope",
127:
128: /* related to missing macro arguments */
129: "skipping empty request",
130: "conditional request controls empty scope",
131: "skipping empty macro",
132: "empty block",
133: "empty argument, using 0n",
134: "missing display type, using -ragged",
135: "list type is not the first argument",
136: "missing -width in -tag list, using 6n",
137: "missing utility name, using \"\"",
138: "missing function name, using \"\"",
139: "empty head in list item",
140: "empty list item",
141: "missing argument, using next line",
142: "missing font type, using \\fR",
143: "unknown font type, using \\fR",
144: "nothing follows prefix",
145: "empty reference block",
146: "missing section argument",
147: "missing -std argument, adding it",
148: "missing option string, using \"\"",
149: "missing resource identifier, using \"\"",
150: "missing eqn box, using \"\"",
151:
152: /* related to bad macro arguments */
153: "duplicate argument",
154: "skipping duplicate argument",
155: "skipping duplicate display type",
156: "skipping duplicate list type",
157: "skipping -width argument",
158: "wrong number of cells",
159: "unknown AT&T UNIX version",
160: "comma in function argument",
161: "parenthesis in function name",
162: "unknown library name",
163: "invalid content in Rs block",
164: "invalid Boolean argument",
165: "argument contains two font escapes",
166: "unknown font, skipping request",
1.16 schwarze 167: "ignoring distance argument",
1.1 schwarze 168: "odd number of characters in request",
169:
170: /* related to plain text */
171: "blank line in fill mode, using .sp",
172: "tab in filled text",
173: "new sentence, new line",
174: "invalid escape sequence",
1.3 schwarze 175: "undefined escape, printing literally",
1.1 schwarze 176: "undefined string, using \"\"",
177:
178: /* related to tables */
179: "tbl line starts with span",
180: "tbl column starts with span",
181: "skipping vertical bar in tbl layout",
182:
183: "generic error",
184:
185: /* related to tables */
186: "non-alphabetic character in tbl options",
187: "skipping unknown tbl option",
188: "missing tbl option argument",
189: "wrong tbl option argument size",
190: "empty tbl layout",
191: "invalid character in tbl layout",
192: "unmatched parenthesis in tbl layout",
1.10 schwarze 193: "ignoring excessive spacing in tbl layout",
1.1 schwarze 194: "tbl without any data cells",
195: "ignoring data in spanned tbl cell",
196: "ignoring extra tbl data cells",
197: "data block open at end of tbl",
198:
199: /* related to document structure and macros */
200: "duplicate prologue macro",
201: "skipping late title macro",
202: "input stack limit exceeded, infinite loop?",
203: "skipping bad character",
204: "skipping unknown macro",
205: "ignoring request outside macro",
206: "skipping insecure request",
207: "skipping item outside list",
208: "skipping column outside column list",
209: "skipping end of block that is not open",
210: "fewer RS blocks open, skipping",
211: "inserting missing end of block",
212: "appending missing end of block",
213:
214: /* related to request and macro arguments */
215: "escaped character not allowed in a name",
216: "using macro argument outside macro",
217: "argument number is not numeric",
1.15 schwarze 218: "negative argument, using 0",
1.1 schwarze 219: "NOT IMPLEMENTED: Bd -file",
220: "skipping display without arguments",
221: "missing list type, using -item",
222: "argument is not numeric, using 1",
223: "argument is not a character",
1.16 schwarze 224: "skipping unusable escape sequence",
1.1 schwarze 225: "missing manual name, using \"\"",
226: "uname(3) system call failed, using UNKNOWN",
227: "unknown standard specifier",
228: "skipping request without numeric argument",
229: "excessive shift",
230: "NOT IMPLEMENTED: .so with absolute path or \"..\"",
231: ".so request failed",
1.8 schwarze 232: "skipping tag containing whitespace",
1.1 schwarze 233: "skipping all arguments",
234: "skipping excess arguments",
235: "divide by zero",
1.17 ! schwarze 236:
! 237: /* related to escape sequences */
! 238: "incomplete escape sequence",
! 239: "invalid special character",
! 240: "unknown special character",
1.1 schwarze 241:
242: "unsupported feature",
243: "input too large",
244: "unsupported control character",
1.3 schwarze 245: "unsupported escape sequence",
1.1 schwarze 246: "unsupported roff request",
247: "nested .while loops",
248: "end of scope with open .while loop",
249: "end of .while loop in inner scope",
250: "cannot continue this .while loop",
251: "eqn delim option in tbl",
252: "unsupported tbl layout modifier",
253: "ignoring macro in table",
1.13 schwarze 254: "skipping tbl in -Tman mode",
255: "skipping eqn in -Tman mode",
1.5 schwarze 256:
257: /* bad command line arguments */
258: NULL,
259: "bad command line argument",
260: "duplicate command line argument",
261: "option has a superfluous value",
262: "missing option value",
263: "bad option value",
264: "duplicate option value",
265: "no such tag",
1.14 schwarze 266: "-Tmarkdown unsupported for man(7) input",
1.5 schwarze 267:
268: /* system errors */
269: NULL,
270: "dup",
271: "exec",
272: "fdopen",
273: "fflush",
274: "fork",
275: "fstat",
276: "getline",
277: "glob",
278: "gzclose",
279: "gzdopen",
280: "mkstemp",
281: "open",
282: "pledge",
283: "read",
284: "wait",
285: "write",
1.1 schwarze 286: };
287:
1.4 schwarze 288: static FILE *fileptr = NULL;
1.1 schwarze 289: static const char *filename = NULL;
1.5 schwarze 290: static enum mandocerr min_type = MANDOCERR_BADARG;
1.1 schwarze 291: static enum mandoclevel rc = MANDOCLEVEL_OK;
292:
293:
294: void
295: mandoc_msg_setoutfile(FILE *fp)
296: {
297: fileptr = fp;
298: }
299:
300: const char *
301: mandoc_msg_getinfilename(void)
302: {
303: return filename;
304: }
305:
306: void
307: mandoc_msg_setinfilename(const char *fn)
308: {
309: filename = fn;
310: }
311:
312: enum mandocerr
313: mandoc_msg_getmin(void)
314: {
315: return min_type;
316: }
317:
318: void
319: mandoc_msg_setmin(enum mandocerr t)
320: {
321: min_type = t;
322: }
323:
324: enum mandoclevel
325: mandoc_msg_getrc(void)
326: {
327: return rc;
328: }
329:
330: void
331: mandoc_msg_setrc(enum mandoclevel level)
332: {
333: if (rc < level)
334: rc = level;
335: }
336:
337: void
1.2 schwarze 338: mandoc_msg(enum mandocerr t, int line, int col, const char *fmt, ...)
1.1 schwarze 339: {
340: va_list ap;
341: enum mandoclevel level;
342:
1.5 schwarze 343: if (t < min_type)
1.1 schwarze 344: return;
345:
1.5 schwarze 346: level = MANDOCLEVEL_SYSERR;
1.1 schwarze 347: while (t < lowest_type[level])
348: level--;
349: mandoc_msg_setrc(level);
350:
351: if (fileptr == NULL)
352: return;
353:
354: fprintf(fileptr, "%s:", getprogname());
355: if (filename != NULL)
356: fprintf(fileptr, " %s:", filename);
357:
358: if (line > 0)
359: fprintf(fileptr, "%d:%d:", line, col + 1);
360:
361: fprintf(fileptr, " %s", level_name[level]);
362: if (type_message[t] != NULL)
363: fprintf(fileptr, ": %s", type_message[t]);
364:
365: if (fmt != NULL) {
366: fprintf(fileptr, ": ");
367: va_start(ap, fmt);
368: vfprintf(fileptr, fmt, ap);
369: va_end(ap);
370: }
371: fputc('\n', fileptr);
1.6 schwarze 372: }
373:
374: void
375: mandoc_msg_summary(void)
376: {
377: if (fileptr != NULL && rc != MANDOCLEVEL_OK)
378: fprintf(fileptr,
379: "%s: see above the output for %s messages\n",
380: getprogname(), level_name[rc]);
1.1 schwarze 381: }