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