* more error handling cleanup
@ 2010-08-18 16:12 Ingo Schwarze
2010-08-18 17:43 ` Kristaps Dzonsons
2010-08-19 9:38 ` Sascha Wildner
0 siblings, 2 replies; 13+ messages in thread
From: Ingo Schwarze @ 2010-08-18 16:12 UTC (permalink / raw)
To: discuss
Hi,
here is more error handling cleanup:
* Retire -Werror.
It is not useful.
When running automatically, that is, in a build,
you never want to abort due to end-of-line whitespace.
When running interactively, you can get what you want
in much simpler ways, without a dedicated option:
- In case -Wall is generating lots of output, redirect
it to a file, then process all of it.
That is much simpler and more efficient than using -Werror
and re-running mandoc again and again.
- In case the run takes a long time, use
mandoc -Tlint * 2>&1 | tee mandoc.log
and start processing the output in parallel.
- In case that wastes too much CPU resources and you need them
for something else, just send SIGINT to the mandoc process
when you are content with the amount of information you got.
In no case do you need -Werror.
Regarding useless knobs, less is more.
* Improve the message complaining about bad -W arguments.
* More cleanup in mmsg():
- Print "WARNING:" just like "ERROR:". We want the output
to be easy to understand even for casual users.
- For uniformity, use a single else-if-cascade,
instead of nested conditionals.
* In the manual,
- Simplify -W documentation accordingly.
I don't think we ever want to complicate this.
We have made a clear plan in Rostock what FATAL, ERROR
and WARNING are supposed to mean. We should stick with
that. There is no point in making this configurable.
We want one easy set of rules for everybody.
Remember mandoc is intended to be used by people who like
to write code and who need not become mdoc(7) specialists.
This is just a tool, it is supposed to work out of the
box, and when we start implementing complicated warning
options, we are certainly on the wrong track.
- Fully document the EXIT STATUS.
- Use the DIAGNOSTICS section to explain FATAL, ERROR
and WARNING.
OK?
Yours,
Ingo
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/main.c,v
retrieving revision 1.44
diff -u -p -r1.44 main.c
--- main.c 18 Aug 2010 01:03:22 -0000 1.44
+++ main.c 18 Aug 2010 16:07:53 -0000
@@ -65,9 +65,7 @@ struct curparse {
const char *file; /* Current parse. */
int fd; /* Current parse. */
int wflags;
- /* FIXME: set by max error */
#define WARN_WALL (1 << 0) /* All-warnings mask. */
-#define WARN_WERR (1 << 2) /* Warnings->errors. */
int fflags;
#define FL_IGN_SCOPE (1 << 0) /* Ignore scope errors. */
#define FL_NIGN_ESCAPE (1 << 1) /* Don't ignore bad escapes. */
@@ -844,8 +842,7 @@ woptions(int *wflags, char *arg)
const char *toks[3];
toks[0] = "all";
- toks[1] = "error";
- toks[2] = NULL;
+ toks[1] = NULL;
while (*arg) {
o = arg;
@@ -853,11 +850,8 @@ woptions(int *wflags, char *arg)
case (0):
*wflags |= WARN_WALL;
break;
- case (1):
- *wflags |= WARN_WERR;
- break;
default:
- fprintf(stderr, "%s: Bad argument\n", o);
+ fprintf(stderr, "-W%s: Bad argument\n", o);
return(0);
}
}
@@ -881,23 +875,17 @@ mmsg(enum mandocerr t, void *arg, int ln
with_fatal = 1;
level = "FATAL";
rc = 0;
+ } else if ( ! (WARN_WALL & cp->wflags)) {
+ return(1);
+ } else if (t >= MANDOCERR_ERROR) {
+ with_error = 1;
+ level = "ERROR";
} else {
- if ( ! (WARN_WALL & cp->wflags))
- return(1);
- if (t >= MANDOCERR_ERROR) {
- with_error = 1;
- level = "ERROR";
- }
- if (WARN_WERR & cp->wflags) {
- with_fatal = 1;
- rc = 0;
- }
+ level = "WARNING";
}
- fprintf(stderr, "%s:%d:%d:", cp->file, ln, col + 1);
- if (level)
- fprintf(stderr, " %s:", level);
- fprintf(stderr, " %s", mandocerrs[t]);
+ fprintf(stderr, "%s:%d:%d: %s: %s",
+ cp->file, ln, col + 1, level, mandocerrs[t]);
if (msg)
fprintf(stderr, ": %s", msg);
fputc('\n', stderr);
Index: mandoc.1
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mandoc.1,v
retrieving revision 1.37
diff -u -p -r1.37 mandoc.1
--- mandoc.1 18 Aug 2010 01:35:01 -0000 1.37
+++ mandoc.1 18 Aug 2010 16:07:54 -0000
@@ -27,7 +27,7 @@
.Op Fl m Ns Ar format
.Op Fl O Ns Ar option
.Op Fl T Ns Ar output
-.Op Fl W Ns Ar err
+.Op Fl W Ns Cm all
.Op Ar file...
.Sh DESCRIPTION
The
@@ -60,18 +60,14 @@ Defaults to
.Fl T Ns Cm ascii .
.It Fl V
Print version and exit.
-.It Fl W Ns Ar err
-Comma-separated warning options.
-Use
-.Fl W Ns Cm all
-to print warnings,
-.Fl W Ns Cm error
-for warnings to be considered errors and cause utility
-termination.
-Multiple
-.Fl W
-arguments may be comma-separated, such as
-.Fl W Ns Cm error , Ns Cm all .
+.It Fl W Ns Cm all
+Report non-fatal errors and warnings on the standard error output,
+and exit with a non-zero exit status in case non-fatal errors occur.
+See
+.Sx EXIT STATUS
+and
+.Sx DIAGNOSTICS
+for details.
.It Ar file
Read input from zero or more files.
If unspecified, reads from stdin.
@@ -91,8 +87,6 @@ text from stdin, implying
and produces
.Fl T Ns Cm ascii
output.
-.Pp
-.Ex -std mandoc
.Ss Input Formats
The
.Nm
@@ -352,10 +346,23 @@ See
.Sx HTML Output
for details; beyond generating XHTML tags instead of HTML tags, these
output modes are identical.
+.Sh EXIT STATUS
+.Ex -std mandoc
+.Pp
+By default, only fatal errors are considered for this purpose.
+When
+.Fl W Ns Cm all
+is specified, non-fatal errors cause a non-zero exit status, too.
+Warnings never cause a non-zero exit status.
+.Pp
+Note that selecting
+.Fl T Ns Cm lint
+output mode implies
+.Fl W Ns Cm all .
.Sh EXAMPLES
To page manuals to the terminal:
.Pp
-.D1 $ mandoc \-Wall,error \-fstrict mandoc.1 2\*(Gt&1 | less
+.D1 $ mandoc \-Wall \-fstrict mandoc.1 2\*(Gt&1 | less
.D1 $ mandoc mandoc.1 mdoc.3 mdoc.7 | less
.Pp
To produce HTML manuals with
@@ -371,6 +378,40 @@ To check over a large set of manuals:
To produce a series of PostScript manuals for A4 paper:
.Pp
.D1 $ mandoc \-Tps \-Opaper=a4 mdoc.7 man.7 \*(Gt manuals.ps
+.Sh DIAGNOSTICS
+Fatal errors occur when the parser is unable to parse a given input
+file at all.
+In this case, no formatted output is produced from that input file,
+and a message containing the string
+.Dq FATAL:
+is printed on the standard error output.
+.Pp
+When
+.Fl W Ns Cm all
+is specified, non-fatal errors and warnings are reported to the
+standard error output as well.
+The former include the string
+.Dq ERROR: ,
+the latter the string
+.Dq WARNING:
+in their message.
+.Pp
+In general, non-fatal errors indicate problems in an input file
+that might cause information loss, broken document structure
+or unintended formatting; yet, the parser is able to continue
+processing, usually by discarding part of the input, or sometimes
+by adding missing tokens.
+Quite often, the parser's guess which information to discard
+or to add will not match the author's intent.
+Thus, it is recommended to correct input documents causing
+non-fatal errors.
+.Pp
+Warnings are issued when the meaning of the input is unambiguous
+and a correct rendering can be produced, but the syntax used is
+obsolete, discouraged, or causes portability issues.
+Documents causing warnings may render poorly when using other
+formatting tools instead of
+.Nm .
.Sh COMPATIBILITY
This section summarises
.Nm
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-18 16:12 more error handling cleanup Ingo Schwarze
@ 2010-08-18 17:43 ` Kristaps Dzonsons
2010-08-18 18:42 ` Ingo Schwarze
2010-08-18 19:00 ` Joerg Sonnenberger
2010-08-19 9:38 ` Sascha Wildner
1 sibling, 2 replies; 13+ messages in thread
From: Kristaps Dzonsons @ 2010-08-18 17:43 UTC (permalink / raw)
To: discuss
> here is more error handling cleanup:
>
> * Retire -Werror.
> It is not useful.
> When running automatically, that is, in a build,
> you never want to abort due to end-of-line whitespace.
> When running interactively, you can get what you want
> in much simpler ways, without a dedicated option:
> - In case -Wall is generating lots of output, redirect
> it to a file, then process all of it.
> That is much simpler and more efficient than using -Werror
> and re-running mandoc again and again.
> - In case the run takes a long time, use
> mandoc -Tlint * 2>&1 | tee mandoc.log
> and start processing the output in parallel.
> - In case that wastes too much CPU resources and you need them
> for something else, just send SIGINT to the mandoc process
> when you are content with the amount of information you got.
> In no case do you need -Werror.
> Regarding useless knobs, less is more.
I agree that -Werror, as it is, isn't helpful. But I don't think this
is the right way to fix things.
I think "-W" should accept the minimum message level, such as "-Wwarn"
or "-Wfatal". A "-Whalt" should stipulate that any messages at the
given level should result in error (so the existing "-Werror" would need
to be disambiguated to "-Whalt"). However, it should do so /after/
processing the rest of the manual. This way we get the whole message
list; the system would halt prior to formatting output.
Thoughts?
> * Improve the message complaining about bad -W arguments.
>
> * More cleanup in mmsg():
> - Print "WARNING:" just like "ERROR:". We want the output
> to be easy to understand even for casual users.
> - For uniformity, use a single else-if-cascade,
> instead of nested conditionals.
I agree with this.
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-18 17:43 ` Kristaps Dzonsons
@ 2010-08-18 18:42 ` Ingo Schwarze
2010-08-18 18:52 ` Kristaps Dzonsons
2010-08-18 19:00 ` Joerg Sonnenberger
1 sibling, 1 reply; 13+ messages in thread
From: Ingo Schwarze @ 2010-08-18 18:42 UTC (permalink / raw)
To: discuss
Hi Kristaps,
Kristaps Dzonsons wrote on Wed, Aug 18, 2010 at 07:43:52PM +0200:
> Ingo Schwarze wrote:
>> * Retire -Werror.
>> It is not useful.
>> When running automatically, that is, in a build,
>> you never want to abort due to end-of-line whitespace.
>> When running interactively, you can get what you want
>> in much simpler ways, without a dedicated option:
>> - In case -Wall is generating lots of output, redirect
>> it to a file, then process all of it.
>> That is much simpler and more efficient than using -Werror
>> and re-running mandoc again and again.
>> - In case the run takes a long time, use
>> mandoc -Tlint * 2>&1 | tee mandoc.log
>> and start processing the output in parallel.
>> - In case that wastes too much CPU resources and you need them
>> for something else, just send SIGINT to the mandoc process
>> when you are content with the amount of information you got.
>> In no case do you need -Werror.
>> Regarding useless knobs, less is more.
> I agree that -Werror, as it is, isn't helpful. But I don't think this
> is the right way to fix things.
>
> I think "-W" should accept the minimum message level, such as "-Wwarn"
> or "-Wfatal". A "-Whalt" should stipulate that any messages at the
> given level should result in error (so the existing "-Werror" would need
> to be disambiguated to "-Whalt"). However, it should do so /after/
> processing the rest of the manual. This way we get the whole message
> list; the system would halt prior to formatting output.
Hm, i see, what you propose is not more complicated than what
i proposed, but a bit more flexible.
My proposal needs to document:
1. -Wall
2. fatal is always printed
3. fatal always causes a non-zero exit status
4. warning and error are printed with -Wall
5. error causes a non-zero exit status with -Wall
6. warning never causes a non-zero exit status
Your proposal just needs:
1. -Wlevel, level can be warning (with alias all), error, fatal
2. everything >= level is printed
3. everything >= level causes a non-zero exit status
4. -Wfatal is the default
5. -Whalt (or i think i would prefer -Wstop)
So, that is even simpler.
Of course, changing -Werror badly breaks backward compatibility.
But i think mandoc is still young enough to do that, i can't
imagine anybody already relying on -Werror as it is.
Building the base system would then use -Wfatal (the default),
ports would use -Werror to catch incompatibilities,
and fall back to a groff build dependency,
and when hunting for issues, you would use -Wall as before.
Fine.
It costs us nothing to steer the exit status by the same mechanism:
#define EXIT_SUCCESS 0
#define EXIT_WARNING 2
#define EXIT_ERROR 3
#define EXIT_FATAL 4
#define EXIT_BADARG 5
#define EXIT_SYSERR 6
I have a fuzzy feeling that it might come in handy to reserve
the exit status 1 for future use; probably, i'm wrong, but
again, it costs us nothing.
So, i'm going back to the drawing board.
Expect a new diff.
Yours,
Ingo
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-18 18:42 ` Ingo Schwarze
@ 2010-08-18 18:52 ` Kristaps Dzonsons
2010-08-19 17:57 ` Ingo Schwarze
0 siblings, 1 reply; 13+ messages in thread
From: Kristaps Dzonsons @ 2010-08-18 18:52 UTC (permalink / raw)
To: discuss
>>> * Retire -Werror.
>>> It is not useful.
>>> When running automatically, that is, in a build,
>>> you never want to abort due to end-of-line whitespace.
>>> When running interactively, you can get what you want
>>> in much simpler ways, without a dedicated option:
>>> - In case -Wall is generating lots of output, redirect
>>> it to a file, then process all of it.
>>> That is much simpler and more efficient than using -Werror
>>> and re-running mandoc again and again.
>>> - In case the run takes a long time, use
>>> mandoc -Tlint * 2>&1 | tee mandoc.log
>>> and start processing the output in parallel.
>>> - In case that wastes too much CPU resources and you need them
>>> for something else, just send SIGINT to the mandoc process
>>> when you are content with the amount of information you got.
>>> In no case do you need -Werror.
>>> Regarding useless knobs, less is more.
>
>> I agree that -Werror, as it is, isn't helpful. But I don't think this
>> is the right way to fix things.
>>
>> I think "-W" should accept the minimum message level, such as "-Wwarn"
>> or "-Wfatal". A "-Whalt" should stipulate that any messages at the
>> given level should result in error (so the existing "-Werror" would need
>> to be disambiguated to "-Whalt"). However, it should do so /after/
>> processing the rest of the manual. This way we get the whole message
>> list; the system would halt prior to formatting output.
>
> Hm, i see, what you propose is not more complicated than what
> i proposed, but a bit more flexible.
>
> My proposal needs to document:
>
> 1. -Wall
> 2. fatal is always printed
> 3. fatal always causes a non-zero exit status
> 4. warning and error are printed with -Wall
> 5. error causes a non-zero exit status with -Wall
> 6. warning never causes a non-zero exit status
>
> Your proposal just needs:
>
> 1. -Wlevel, level can be warning (with alias all), error, fatal
> 2. everything >= level is printed
> 3. everything >= level causes a non-zero exit status
> 4. -Wfatal is the default
> 5. -Whalt (or i think i would prefer -Wstop)
>
> So, that is even simpler.
> Of course, changing -Werror badly breaks backward compatibility.
> But i think mandoc is still young enough to do that, i can't
> imagine anybody already relying on -Werror as it is.
>
> Building the base system would then use -Wfatal (the default),
> ports would use -Werror to catch incompatibilities,
> and fall back to a groff build dependency,
> and when hunting for issues, you would use -Wall as before.
> Fine.
>
> It costs us nothing to steer the exit status by the same mechanism:
>
> #define EXIT_SUCCESS 0
> #define EXIT_WARNING 2
> #define EXIT_ERROR 3
> #define EXIT_FATAL 4
> #define EXIT_BADARG 5
> #define EXIT_SYSERR 6
>
> I have a fuzzy feeling that it might come in handy to reserve
> the exit status 1 for future use; probably, i'm wrong, but
> again, it costs us nothing.
>
> So, i'm going back to the drawing board.
> Expect a new diff.
Ingo, I look forward to it!
My suggestion is only because my own makefiles always use [what would
be] "-Twarn,stop", as I like to have everything linted and fully-warned
just in case. I can see "-Terror,stop" being useful for "important"
manuals, like those in the base system, and "-Tfatal,stop" for any old
manual.
I vaguely remember talking about this at supper during m210k...
I'm not concerned with the "-Werror" backward compatibility in this
regard. All downstream people are on this list.
Thanks,
Kristaps
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-18 17:43 ` Kristaps Dzonsons
2010-08-18 18:42 ` Ingo Schwarze
@ 2010-08-18 19:00 ` Joerg Sonnenberger
1 sibling, 0 replies; 13+ messages in thread
From: Joerg Sonnenberger @ 2010-08-18 19:00 UTC (permalink / raw)
To: discuss
On Wed, Aug 18, 2010 at 07:43:52PM +0200, Kristaps Dzonsons wrote:
> I think "-W" should accept the minimum message level, such as "-Wwarn"
> or "-Wfatal". A "-Whalt" should stipulate that any messages at the
> given level should result in error (so the existing "-Werror" would need
> to be disambiguated to "-Whalt"). However, it should do so /after/
> processing the rest of the manual. This way we get the whole message
> list; the system would halt prior to formatting output.
I think that's the conclusion we reached originally. Always do the
return value computation at the end, have an option for what is
considered an error.
Joerg
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-18 16:12 more error handling cleanup Ingo Schwarze
2010-08-18 17:43 ` Kristaps Dzonsons
@ 2010-08-19 9:38 ` Sascha Wildner
2010-08-19 13:19 ` Kristaps Dzonsons
2010-08-19 21:55 ` Ingo Schwarze
1 sibling, 2 replies; 13+ messages in thread
From: Sascha Wildner @ 2010-08-19 9:38 UTC (permalink / raw)
To: discuss
On 8/18/2010 18:12, Ingo Schwarze wrote:
> Hi,
>
> here is more error handling cleanup:
>
> * Retire -Werror.
My general thought on this is that I definitely have the future plan to
integrate running mandoc on manpages during _buildworld_ and have the
build break if mandoc encounters issues.
My reasoning is that only if the build breaks, you'll get the
developer's attention in case they introduced issues in manual pages. :)
If that is still possible with the later proposals from this discussion
(just scanned it quickly since I'm at work), I'm fine.
Sascha
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-19 9:38 ` Sascha Wildner
@ 2010-08-19 13:19 ` Kristaps Dzonsons
2010-08-20 12:18 ` Sascha Wildner
2010-08-19 21:55 ` Ingo Schwarze
1 sibling, 1 reply; 13+ messages in thread
From: Kristaps Dzonsons @ 2010-08-19 13:19 UTC (permalink / raw)
To: discuss
> My general thought on this is that I definitely have the future plan to
> integrate running mandoc on manpages during _buildworld_ and have the
> build break if mandoc encounters issues.
>
> My reasoning is that only if the build breaks, you'll get the
> developer's attention in case they introduced issues in manual pages. :)
>
> If that is still possible with the later proposals from this discussion
> (just scanned it quickly since I'm at work), I'm fine.
Sascha,
(To answer your question: it is.)
Out of curiosity, what's your time-frame on this endeavour (if you have
one at all)?
Note, by the way, that FreeBSD's GSoC regarding mandoc appears to have
failed:
http://lists.freebsd.org/pipermail/soc-status/2010-August/000282.html
Kristaps
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-18 18:52 ` Kristaps Dzonsons
@ 2010-08-19 17:57 ` Ingo Schwarze
2010-08-19 22:47 ` Kristaps Dzonsons
0 siblings, 1 reply; 13+ messages in thread
From: Ingo Schwarze @ 2010-08-19 17:57 UTC (permalink / raw)
To: discuss
Hi,
i'm sending this to discuss@ again because it has implications for how
mandoc can be used, even though this posting now contains a large diff.
Feel free to ignore the diff and just look at the interface changes.
This implements what was already discussed:
- provide -Wlevel (warning, error or fatal) to select what you care about
- provide -Wstop to stop after parsing a file with warnings you care about
- provide consistent exit status codes for those warnings you care about
- remove the old -Werror because calling warnings "fatal" is silly
- always finish parsing each file, unless fatal errors prevent that
In addition to that, it turned out this needs one other interface change:
The -fno-ign-escape and -fno-ign-macro options caused fatal error exit
without throwing a fatal message. This was ugly with the old code;
it breaks with the new code. As they do not really look useful in
the first place - in case you are searching for these errors, just
run -Tlint -Werror and look at the output - i removed them instead
of fixing them.
As -fign-scope had no effect anyway, no more -f options were left,
so i removed the whole -f infrastructure. As i said, i strongly
believe we should not introduce new warning options, we want one
standard, easy way to handle all issues. I hope the user interface
resulting from this cleanup will last for a long time, maybe for good.
This entails various technical changes behind the scenes:
- We can now also zap the pflags from struct mdoc and struct man
and the pflags argument from the *_alloc() functions, and thus
even drop the now empty *_init() functions.
While here, i adjusted the order of arguments in roff_alloc()
to match mdoc_alloc() and man_alloc().
- I have replaced the WARN_W* #defines by a nice enum mandoclevel
in mandoc.h, in analogy to the existing enum mandocerr.
In main.c, in parallel to static mandocerrs[], we now have
static mandoclevels[] for printing and static mandoclimits[]
to link both enums together.
- Now that we have meaningful exit status codes, scattering
exit(3) across lots of files becomes a problem. Instead,
use the mandoc_*alloc() functions we already have everywhere.
- While doing this, i noticed that MANDOCERR_MEM had a
misleading text: It is not "memory exhausted" but
"static buffer exhausted" (and should eventually go away).
- Another consequence of using mandoc_*alloc everywhere is that
no function needs to report errors on malloc failures any more,
everybody just exits. So, from the point of view of the callers,
some cannot fail at all any more and can become void:
pset(), resize_buf() in main.c; roffnode_push() in roff.c.
- Yet another consequence is that *_alloc do not return any more
when they fail, so assert()ing their result is sufficient, no
error handling is needed any more in the caller.
- While i kept the return value of mmsg(), telling whether the error
is fatal, i regard it as mostly useless. The caller always knows
whether the error is fatal or non-fatal, so testing the return
value is almost always useless and just making the code harder to
read and more error-prone. I did not scour the code to remove such
tests, but left them out at those places i needed to touch anyway.
- The couple of
assert(MANDOCLEVEL_FATAL <= exit_status);
in fdesc() maybe need an explanation.
The parsers might contain programming errors of the following type:
Throw a non-fatal error or a warning, then return failure.
In that case, the main program would not produce output for the
file, but not show a fatal message either. These asserts are
intended to catch such programming errors.
- The mmsg() function has once again been rewritten and is once
again simpler and more powerful than before.
- The patch is shortening (+186 -347) and simplifying the code
while adding functionality and documentation (+145 -75).
Comments, OKs?
Yours,
Ingo
Index: chars.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/chars.c,v
retrieving revision 1.11
diff -u -p -r1.11 chars.c
--- chars.c 18 Aug 2010 02:46:37 -0000 1.11
+++ chars.c 19 Aug 2010 17:09:15 -0000
@@ -21,6 +21,7 @@
#include "mandoc.h"
#include "chars.h"
+#include "libmandoc.h"
#define PRINT_HI 126
#define PRINT_LO 32
@@ -87,17 +88,8 @@ chars_init(enum chars type)
* (they're in-line re-ordered during lookup).
*/
- tab = malloc(sizeof(struct tbl));
- if (NULL == tab) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
-
- htab = calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
- if (NULL == htab) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
+ tab = mandoc_malloc(sizeof(struct tbl));
+ htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
for (i = 0; i < LINES_MAX; i++) {
hash = (int)lines[i].code[0] - PRINT_LO;
Index: html.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/html.c,v
retrieving revision 1.14
diff -u -p -r1.14 html.c
--- html.c 31 Jul 2010 21:43:07 -0000 1.14
+++ html.c 19 Aug 2010 17:09:15 -0000
@@ -30,6 +30,7 @@
#include "chars.h"
#include "html.h"
#include "main.h"
+#include "libmandoc.h"
struct htmldata {
const char *name;
@@ -109,12 +110,7 @@ ml_alloc(char *outopts, enum htmltype ty
toks[2] = "includes";
toks[3] = NULL;
- h = calloc(1, sizeof(struct html));
- if (NULL == h) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
-
+ h = mandoc_calloc(1, sizeof(struct html));
h->type = type;
h->tags.head = NULL;
h->ords.head = NULL;
@@ -391,11 +387,7 @@ print_otag(struct html *h, enum htmltag
/* Push this tags onto the stack of open scopes. */
if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
- t = malloc(sizeof(struct tag));
- if (NULL == t) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
+ t = mandoc_malloc(sizeof(struct tag));
t->tag = tag;
t->next = h->tags.head;
h->tags.head = t;
Index: libman.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/libman.h,v
retrieving revision 1.24
diff -u -p -r1.24 libman.h
--- libman.h 13 Jul 2010 01:09:12 -0000 1.24
+++ libman.h 19 Aug 2010 17:09:15 -0000
@@ -27,7 +27,6 @@ enum man_next {
struct man {
void *data; /* private application data */
mandocmsg msg; /* output message handler */
- int pflags; /* parse flags (see man.h) */
int flags; /* parse flags */
#define MAN_HALT (1 << 0) /* badness happened: die */
#define MAN_ELINE (1 << 1) /* Next-line element scope. */
Index: libmdoc.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/libmdoc.h,v
retrieving revision 1.41
diff -u -p -r1.41 libmdoc.h
--- libmdoc.h 13 Jul 2010 01:09:12 -0000 1.41
+++ libmdoc.h 19 Aug 2010 17:09:15 -0000
@@ -36,7 +36,6 @@ struct mdoc {
#define MDOC_PPHRASE (1 << 5) /* within a partial phrase */
#define MDOC_FREECOL (1 << 6) /* `It' invocation should close */
#define MDOC_SYNOPSIS (1 << 7) /* SYNOPSIS-style formatting */
- int pflags;
enum mdoc_next next; /* where to put the next node */
struct mdoc_node *last; /* the last node parsed */
struct mdoc_node *first; /* the first node parsed */
Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/main.c,v
retrieving revision 1.44
diff -u -p -r1.44 main.c
--- main.c 18 Aug 2010 01:03:22 -0000 1.44
+++ main.c 19 Aug 2010 17:09:15 -0000
@@ -33,6 +33,7 @@
#include "mdoc.h"
#include "man.h"
#include "roff.h"
+#include "libmandoc.h"
#define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
@@ -64,17 +65,8 @@ enum outt {
struct curparse {
const char *file; /* Current parse. */
int fd; /* Current parse. */
- int wflags;
- /* FIXME: set by max error */
-#define WARN_WALL (1 << 0) /* All-warnings mask. */
-#define WARN_WERR (1 << 2) /* Warnings->errors. */
- int fflags;
-#define FL_IGN_SCOPE (1 << 0) /* Ignore scope errors. */
-#define FL_NIGN_ESCAPE (1 << 1) /* Don't ignore bad escapes. */
-#define FL_NIGN_MACRO (1 << 2) /* Don't ignore bad macros. */
-#define FL_IGN_ERRORS (1 << 4) /* Ignore failed parse. */
-#define FL_STRICT FL_NIGN_ESCAPE | \
- FL_NIGN_MACRO /* ignore nothing */
+ enum mandoclevel wlevel; /* Ignore messages below this. */
+ int wstop; /* Stop after a file with a warning. */
enum intt inttype; /* which parser to use */
struct man *man; /* man parser */
struct mdoc *mdoc; /* mdoc parser */
@@ -88,6 +80,26 @@ struct curparse {
char outopts[BUFSIZ]; /* buf of output opts */
};
+static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
+ "SUCCESS",
+ "RESERVED",
+ "WARNING",
+ "ERROR",
+ "FATAL",
+ "BADARG",
+ "SYSERR"
+};
+
+static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
+ MANDOCERR_OK,
+ MANDOCERR_WARNING,
+ MANDOCERR_WARNING,
+ MANDOCERR_ERROR,
+ MANDOCERR_FATAL,
+ MANDOCERR_MAX,
+ MANDOCERR_MAX
+};
+
static const char * const mandocerrs[MANDOCERR_MAX] = {
"ok",
@@ -164,28 +176,23 @@ static const char * const mandocerrs[MAN
"no document body",
"no document prologue",
"utsname system call failed",
- "memory exhausted",
+ "static buffer exhausted",
};
static void fdesc(struct curparse *);
static void ffile(const char *, struct curparse *);
-static int foptions(int *, char *);
-static struct man *man_init(struct curparse *);
-static struct mdoc *mdoc_init(struct curparse *);
-static struct roff *roff_init(struct curparse *);
static int moptions(enum intt *, char *);
static int mmsg(enum mandocerr, void *,
int, int, const char *);
-static int pset(const char *, int, struct curparse *,
+static void pset(const char *, int, struct curparse *,
struct man **, struct mdoc **);
static int toptions(struct curparse *, char *);
static void usage(void) __attribute__((noreturn));
static void version(void) __attribute__((noreturn));
-static int woptions(int *, char *);
+static int woptions(struct curparse *, char *);
static const char *progname;
-static int with_fatal;
-static int with_error;
+static enum mandoclevel exit_status = MANDOCLEVEL_OK;
int
main(int argc, char *argv[])
@@ -203,17 +210,14 @@ main(int argc, char *argv[])
curp.inttype = INTT_AUTO;
curp.outtype = OUTT_ASCII;
+ curp.wlevel = MANDOCLEVEL_FATAL;
/* LINTED */
- while (-1 != (c = getopt(argc, argv, "f:m:O:T:VW:")))
+ while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
switch (c) {
- case ('f'):
- if ( ! foptions(&curp.fflags, optarg))
- return(EXIT_FAILURE);
- break;
case ('m'):
if ( ! moptions(&curp.inttype, optarg))
- return(EXIT_FAILURE);
+ return(MANDOCLEVEL_BADARG);
break;
case ('O'):
(void)strlcat(curp.outopts, optarg, BUFSIZ);
@@ -221,11 +225,11 @@ main(int argc, char *argv[])
break;
case ('T'):
if ( ! toptions(&curp, optarg))
- return(EXIT_FAILURE);
+ return(MANDOCLEVEL_BADARG);
break;
case ('W'):
- if ( ! woptions(&curp.wflags, optarg))
- return(EXIT_FAILURE);
+ if ( ! woptions(&curp, optarg))
+ return(MANDOCLEVEL_BADARG);
break;
case ('V'):
version();
@@ -247,8 +251,7 @@ main(int argc, char *argv[])
while (*argv) {
ffile(*argv, &curp);
-
- if (with_fatal && !(curp.fflags & FL_IGN_ERRORS))
+ if (MANDOCLEVEL_OK != exit_status && curp.wstop)
break;
++argv;
}
@@ -262,8 +265,7 @@ main(int argc, char *argv[])
if (curp.roff)
roff_free(curp.roff);
- return((with_fatal || with_error) ?
- EXIT_FAILURE : EXIT_SUCCESS);
+ return(exit_status);
}
@@ -272,7 +274,7 @@ version(void)
{
(void)printf("%s %s\n", progname, VERSION);
- exit(EXIT_SUCCESS);
+ exit(MANDOCLEVEL_OK);
}
@@ -283,53 +285,7 @@ usage(void)
(void)fprintf(stderr, "usage: %s [-V] [-foption] "
"[-mformat] [-Ooption] [-Toutput] "
"[-Werr] [file...]\n", progname);
- exit(EXIT_FAILURE);
-}
-
-
-static struct man *
-man_init(struct curparse *curp)
-{
- int pflags;
-
- /* Defaults from mandoc.1. */
-
- pflags = MAN_IGN_MACRO | MAN_IGN_ESCAPE;
-
- if (curp->fflags & FL_NIGN_MACRO)
- pflags &= ~MAN_IGN_MACRO;
- if (curp->fflags & FL_NIGN_ESCAPE)
- pflags &= ~MAN_IGN_ESCAPE;
-
- return(man_alloc(&curp->regs, curp, pflags, mmsg));
-}
-
-
-static struct roff *
-roff_init(struct curparse *curp)
-{
-
- return(roff_alloc(&curp->regs, mmsg, curp));
-}
-
-
-static struct mdoc *
-mdoc_init(struct curparse *curp)
-{
- int pflags;
-
- /* Defaults from mandoc.1. */
-
- pflags = MDOC_IGN_MACRO | MDOC_IGN_ESCAPE;
-
- if (curp->fflags & FL_IGN_SCOPE)
- pflags |= MDOC_IGN_SCOPE;
- if (curp->fflags & FL_NIGN_ESCAPE)
- pflags &= ~MDOC_IGN_ESCAPE;
- if (curp->fflags & FL_NIGN_MACRO)
- pflags &= ~MDOC_IGN_MACRO;
-
- return(mdoc_alloc(&curp->regs, curp, pflags, mmsg));
+ exit(MANDOCLEVEL_BADARG);
}
@@ -340,7 +296,7 @@ ffile(const char *file, struct curparse
curp->file = file;
if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
perror(curp->file);
- with_fatal = 1;
+ exit_status = MANDOCLEVEL_SYSERR;
return;
}
@@ -351,24 +307,12 @@ ffile(const char *file, struct curparse
}
-static int
+static void
resize_buf(struct buf *buf, size_t initial)
{
- void *tmp;
- size_t sz;
- if (buf->sz == 0)
- sz = initial;
- else
- sz = 2 * buf->sz;
- tmp = realloc(buf->buf, sz);
- if (NULL == tmp) {
- perror(NULL);
- return(0);
- }
- buf->buf = tmp;
- buf->sz = sz;
- return(1);
+ buf->sz = buf->sz ? 2 * buf->sz : initial;
+ buf->buf = mandoc_realloc(buf->buf, buf->sz);
}
@@ -381,7 +325,6 @@ read_whole_file(struct curparse *curp, s
if (-1 == fstat(curp->fd, &st)) {
perror(curp->file);
- with_fatal = 1;
return(0);
}
@@ -396,7 +339,6 @@ read_whole_file(struct curparse *curp, s
if (st.st_size >= (1U << 31)) {
fprintf(stderr, "%s: input too large\n",
curp->file);
- with_fatal = 1;
return(0);
}
*with_mmap = 1;
@@ -423,8 +365,7 @@ read_whole_file(struct curparse *curp, s
curp->file);
break;
}
- if (! resize_buf(fb, 65536))
- break;
+ resize_buf(fb, 65536);
}
ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off);
if (ssz == 0) {
@@ -440,7 +381,6 @@ read_whole_file(struct curparse *curp, s
free(fb->buf);
fb->buf = NULL;
- with_fatal = 1;
return(0);
}
@@ -467,13 +407,15 @@ fdesc(struct curparse *curp)
* memory mapped. ln is a line buffer and grows on-demand.
*/
- if ( ! read_whole_file(curp, &blk, &with_mmap))
+ if ( ! read_whole_file(curp, &blk, &with_mmap)) {
+ exit_status = MANDOCLEVEL_SYSERR;
return;
+ }
if (NULL == curp->roff)
- curp->roff = roff_init(curp);
- if (NULL == (roff = curp->roff))
- goto bailout;
+ curp->roff = roff_alloc(&curp->regs, curp, mmsg);
+ assert(curp->roff);
+ roff = curp->roff;
for (i = 0, lnn = 1; i < (int)blk.sz;) {
pos = 0;
@@ -496,10 +438,8 @@ fdesc(struct curparse *curp)
c = (unsigned char) blk.buf[i];
if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) {
- if ( ! mmsg(MANDOCERR_BADCHAR, curp,
- lnn_start, pos,
- "ignoring byte"))
- goto bailout;
+ mmsg(MANDOCERR_BADCHAR, curp,
+ lnn_start, pos, "ignoring byte");
i++;
continue;
}
@@ -507,8 +447,7 @@ fdesc(struct curparse *curp)
/* Trailing backslash is like a plain character. */
if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
if (pos >= (int)ln.sz)
- if (! resize_buf(&ln, 256))
- goto bailout;
+ resize_buf(&ln, 256);
ln.buf[pos++] = blk.buf[i++];
continue;
}
@@ -540,16 +479,14 @@ fdesc(struct curparse *curp)
}
/* Some other escape sequence, copy and continue. */
if (pos + 1 >= (int)ln.sz)
- if (! resize_buf(&ln, 256))
- goto bailout;
+ resize_buf(&ln, 256);
ln.buf[pos++] = blk.buf[i++];
ln.buf[pos++] = blk.buf[i++];
}
if (pos >= (int)ln.sz)
- if (! resize_buf(&ln, 256))
- goto bailout;
+ resize_buf(&ln, 256);
ln.buf[pos] = '\0';
/*
@@ -567,10 +504,12 @@ fdesc(struct curparse *curp)
&ln.buf, &ln.sz, of, &of);
} while (ROFF_RERUN == re);
- if (ROFF_IGN == re)
+ if (ROFF_IGN == re) {
continue;
- else if (ROFF_ERR == re)
- goto bailout;
+ } else if (ROFF_ERR == re) {
+ assert(MANDOCLEVEL_FATAL <= exit_status);
+ goto cleanup;
+ }
/*
* If input parsers have not been allocated, do so now.
@@ -580,32 +519,50 @@ fdesc(struct curparse *curp)
*/
if ( ! (man || mdoc))
- if ( ! pset(ln.buf + of, pos - of, curp, &man, &mdoc))
- goto bailout;
+ pset(ln.buf + of, pos - of, curp, &man, &mdoc);
/* Lastly, push down into the parsers themselves. */
- if (man && ! man_parseln(man, lnn_start, ln.buf, of))
- goto bailout;
- if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of))
- goto bailout;
+ if (man && ! man_parseln(man, lnn_start, ln.buf, of)) {
+ assert(MANDOCLEVEL_FATAL <= exit_status);
+ goto cleanup;
+ }
+ if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of)) {
+ assert(MANDOCLEVEL_FATAL <= exit_status);
+ goto cleanup;
+ }
}
+ /*
+ * With -Wstop and warnings or errors of at least
+ * the requested level, do not produce output.
+ */
+
+ if (MANDOCLEVEL_OK != exit_status && curp->wstop)
+ goto cleanup;
+
/* NOTE a parser may not have been assigned, yet. */
if ( ! (man || mdoc)) {
fprintf(stderr, "%s: Not a manual\n", curp->file);
- goto bailout;
+ exit_status = MANDOCLEVEL_FATAL;
+ goto cleanup;
}
/* Clean up the parse routine ASTs. */
- if (mdoc && ! mdoc_endparse(mdoc))
- goto bailout;
- if (man && ! man_endparse(man))
- goto bailout;
- if (roff && ! roff_endparse(roff))
- goto bailout;
+ if (mdoc && ! mdoc_endparse(mdoc)) {
+ assert(MANDOCLEVEL_FATAL <= exit_status);
+ goto cleanup;
+ }
+ if (man && ! man_endparse(man)) {
+ assert(MANDOCLEVEL_FATAL <= exit_status);
+ goto cleanup;
+ }
+ if (roff && ! roff_endparse(roff)) {
+ assert(MANDOCLEVEL_FATAL <= exit_status);
+ goto cleanup;
+ }
/* If unset, allocate output dev now (if applicable). */
@@ -681,14 +638,10 @@ fdesc(struct curparse *curp)
free(blk.buf);
return;
-
- bailout:
- with_fatal = 1;
- goto cleanup;
}
-static int
+static void
pset(const char *buf, int pos, struct curparse *curp,
struct man **man, struct mdoc **mdoc)
{
@@ -707,39 +660,38 @@ pset(const char *buf, int pos, struct cu
if (' ' != buf[i] && '\t' != buf[i])
break;
if (0 == buf[i])
- return(1);
+ return;
}
switch (curp->inttype) {
case (INTT_MDOC):
if (NULL == curp->mdoc)
- curp->mdoc = mdoc_init(curp);
- if (NULL == (*mdoc = curp->mdoc))
- return(0);
- return(1);
+ curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg);
+ assert(curp->mdoc);
+ *mdoc = curp->mdoc;
+ return;
case (INTT_MAN):
if (NULL == curp->man)
- curp->man = man_init(curp);
- if (NULL == (*man = curp->man))
- return(0);
- return(1);
+ curp->man = man_alloc(&curp->regs, curp, mmsg);
+ assert(curp->man);
+ *man = curp->man;
+ return;
default:
break;
}
if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
if (NULL == curp->mdoc)
- curp->mdoc = mdoc_init(curp);
- if (NULL == (*mdoc = curp->mdoc))
- return(0);
- return(1);
+ curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg);
+ assert(curp->mdoc);
+ *mdoc = curp->mdoc;
+ return;
}
if (NULL == curp->man)
- curp->man = man_init(curp);
- if (NULL == (*man = curp->man))
- return(0);
- return(1);
+ curp->man = man_alloc(&curp->regs, curp, mmsg);
+ assert(curp->man);
+ *man = curp->man;
}
@@ -770,8 +722,7 @@ toptions(struct curparse *curp, char *ar
curp->outtype = OUTT_ASCII;
else if (0 == strcmp(arg, "lint")) {
curp->outtype = OUTT_LINT;
- curp->wflags |= WARN_WALL;
- curp->fflags |= FL_STRICT;
+ curp->wlevel = MANDOCLEVEL_WARNING;
}
else if (0 == strcmp(arg, "tree"))
curp->outtype = OUTT_TREE;
@@ -793,71 +744,37 @@ toptions(struct curparse *curp, char *ar
static int
-foptions(int *fflags, char *arg)
+woptions(struct curparse *curp, char *arg)
{
char *v, *o;
- const char *toks[8];
+ const char *toks[6];
- toks[0] = "ign-scope";
- toks[1] = "no-ign-escape";
- toks[2] = "no-ign-macro";
- toks[3] = "ign-errors";
- toks[4] = "strict";
- toks[5] = "ign-escape";
- toks[6] = NULL;
+ toks[0] = "stop";
+ toks[1] = "all";
+ toks[2] = "warning";
+ toks[3] = "error";
+ toks[4] = "fatal";
+ toks[5] = NULL;
while (*arg) {
o = arg;
switch (getsubopt(&arg, UNCONST(toks), &v)) {
case (0):
- *fflags |= FL_IGN_SCOPE;
+ curp->wstop = 1;
break;
case (1):
- *fflags |= FL_NIGN_ESCAPE;
- break;
+ /* FALLTHROUGH */
case (2):
- *fflags |= FL_NIGN_MACRO;
+ curp->wlevel = MANDOCLEVEL_WARNING;
break;
case (3):
- *fflags |= FL_IGN_ERRORS;
+ curp->wlevel = MANDOCLEVEL_ERROR;
break;
case (4):
- *fflags |= FL_STRICT;
- break;
- case (5):
- *fflags &= ~FL_NIGN_ESCAPE;
- break;
- default:
- fprintf(stderr, "%s: Bad argument\n", o);
- return(0);
- }
- }
-
- return(1);
-}
-
-
-static int
-woptions(int *wflags, char *arg)
-{
- char *v, *o;
- const char *toks[3];
-
- toks[0] = "all";
- toks[1] = "error";
- toks[2] = NULL;
-
- while (*arg) {
- o = arg;
- switch (getsubopt(&arg, UNCONST(toks), &v)) {
- case (0):
- *wflags |= WARN_WALL;
- break;
- case (1):
- *wflags |= WARN_WERR;
+ curp->wlevel = MANDOCLEVEL_FATAL;
break;
default:
- fprintf(stderr, "%s: Bad argument\n", o);
+ fprintf(stderr, "-W%s: Bad argument\n", o);
return(0);
}
}
@@ -870,37 +787,24 @@ static int
mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
{
struct curparse *cp;
- const char *level;
- int rc;
+ enum mandoclevel level;
- cp = (struct curparse *)arg;
- level = NULL;
- rc = 1;
+ level = MANDOCLEVEL_FATAL;
+ while (t < mandoclimits[level])
+ level--;
- if (t >= MANDOCERR_FATAL) {
- with_fatal = 1;
- level = "FATAL";
- rc = 0;
- } else {
- if ( ! (WARN_WALL & cp->wflags))
- return(1);
- if (t >= MANDOCERR_ERROR) {
- with_error = 1;
- level = "ERROR";
- }
- if (WARN_WERR & cp->wflags) {
- with_fatal = 1;
- rc = 0;
- }
- }
+ cp = (struct curparse *)arg;
+ if (level < cp->wlevel)
+ return(1);
- fprintf(stderr, "%s:%d:%d:", cp->file, ln, col + 1);
- if (level)
- fprintf(stderr, " %s:", level);
- fprintf(stderr, " %s", mandocerrs[t]);
+ fprintf(stderr, "%s:%d:%d: %s: %s",
+ cp->file, ln, col + 1, mandoclevels[level], mandocerrs[t]);
if (msg)
fprintf(stderr, ": %s", msg);
fputc('\n', stderr);
- return(rc);
+ if (exit_status < level)
+ exit_status = level;
+
+ return(level < MANDOCLEVEL_FATAL);
}
Index: man.3
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man.3,v
retrieving revision 1.14
diff -u -p -r1.14 man.3
--- man.3 18 Aug 2010 02:46:37 -0000 1.14
+++ man.3 19 Aug 2010 17:09:16 -0000
@@ -35,7 +35,6 @@
.Fo man_alloc
.Fa "struct regset *regs"
.Fa "void *data"
-.Fa "int pflags"
.Fa "mandocmsg msgs"
.Fc
.Ft int
@@ -172,10 +171,6 @@ The
.Fa data
pointer is passed to
.Fa msgs .
-The
-.Fa pflags
-arguments are defined in
-.Pa man.h .
Returns NULL on failure.
If non-NULL, the pointer must be freed with
.Fn man_free .
@@ -298,7 +293,7 @@ int line;
bzero(®s, sizeof(struct regset));
line = 1;
-man = man_alloc(®s, NULL, 0, NULL);
+man = man_alloc(®s, NULL, NULL);
buf = NULL;
alloc_len = 0;
Index: man.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man.c,v
retrieving revision 1.39
diff -u -p -r1.39 man.c
--- man.c 18 Aug 2010 01:17:44 -0000 1.39
+++ man.c 19 Aug 2010 17:09:16 -0000
@@ -52,7 +52,6 @@ static int man_ptext(struct man *, int
static int man_pmacro(struct man *, int, char *, int);
static void man_free1(struct man *);
static void man_alloc1(struct man *);
-static int macrowarn(struct man *, int, const char *, int);
const struct man_node *
@@ -90,8 +89,7 @@ man_free(struct man *man)
struct man *
-man_alloc(struct regset *regs, void *data,
- int pflags, mandocmsg msg)
+man_alloc(struct regset *regs, void *data, mandocmsg msg)
{
struct man *p;
@@ -99,7 +97,6 @@ man_alloc(struct regset *regs, void *dat
man_hash_init();
p->data = data;
- p->pflags = pflags;
p->msg = msg;
p->regs = regs;
@@ -431,19 +428,6 @@ descope:
}
-static int
-macrowarn(struct man *m, int ln, const char *buf, int offs)
-{
- int rc;
-
- rc = man_vmsg(m, MANDOCERR_MACRO, ln, offs,
- "unknown macro: %s%s",
- buf, strlen(buf) > 3 ? "..." : "");
-
- return(MAN_IGN_MACRO & m->pflags ? rc : 0);
-}
-
-
int
man_pmacro(struct man *m, int ln, char *buf, int offs)
{
@@ -486,15 +470,11 @@ man_pmacro(struct man *m, int ln, char *
mac[j++] = buf[i++];
mac[j] = '\0';
- if (j == 4 || j < 1) {
- if ( ! macrowarn(m, ln, mac, ppos))
- goto err;
- return(1);
- }
-
- if (MAN_MAX == (tok = man_hash_find(mac))) {
- if ( ! macrowarn(m, ln, mac, ppos))
- goto err;
+ tok = (j > 0 && j < 4) ? man_hash_find(mac) : MAN_MAX;
+ if (MAN_MAX == tok) {
+ man_vmsg(m, MANDOCERR_MACRO, ln, ppos,
+ "unknown macro: %s%s",
+ buf, strlen(buf) > 3 ? "..." : "");
return(1);
}
Index: man.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man.h,v
retrieving revision 1.25
diff -u -p -r1.25 man.h
--- man.h 25 Jul 2010 18:05:54 -0000 1.25
+++ man.h 19 Aug 2010 17:09:16 -0000
@@ -97,9 +97,6 @@ struct man_node {
struct man_node *body;
};
-#define MAN_IGN_MACRO (1 << 0)
-#define MAN_IGN_ESCAPE (1 << 2)
-
extern const char *const *man_macronames;
__BEGIN_DECLS
@@ -107,7 +104,7 @@ __BEGIN_DECLS
struct man;
void man_free(struct man *);
-struct man *man_alloc(struct regset *, void *, int, mandocmsg);
+struct man *man_alloc(struct regset *, void *, mandocmsg);
void man_reset(struct man *);
int man_parseln(struct man *, int, char *, int);
int man_endparse(struct man *);
Index: man_validate.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/man_validate.c,v
retrieving revision 1.28
diff -u -p -r1.28 man_validate.c
--- man_validate.c 25 Jul 2010 18:05:54 -0000 1.28
+++ man_validate.c 19 Aug 2010 17:09:16 -0000
@@ -229,12 +229,8 @@ check_text(CHKARGS)
if (c) {
p += c - 1;
pos += c - 1;
- continue;
- }
-
- c = man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
- if ( ! (MAN_IGN_ESCAPE & m->pflags) && ! c)
- return(c);
+ } else
+ man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
}
return(1);
Index: mandoc.1
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mandoc.1,v
retrieving revision 1.37
diff -u -p -r1.37 mandoc.1
--- mandoc.1 18 Aug 2010 01:35:01 -0000 1.37
+++ mandoc.1 19 Aug 2010 17:09:16 -0000
@@ -23,11 +23,10 @@
.Sh SYNOPSIS
.Nm mandoc
.Op Fl V
-.Op Fl f Ns Ar option
.Op Fl m Ns Ar format
.Op Fl O Ns Ar option
.Op Fl T Ns Ar output
-.Op Fl W Ns Ar err
+.Op Fl W Ns Ar level
.Op Ar file...
.Sh DESCRIPTION
The
@@ -37,11 +36,6 @@ utility formats
manual pages for display.
The arguments are as follows:
.Bl -tag -width Ds
-.It Fl f Ns Ar option
-Comma-separated compiler options.
-See
-.Sx Compiler Options
-for details.
.It Fl m Ns Ar format
Input format.
See
@@ -60,18 +54,41 @@ Defaults to
.Fl T Ns Cm ascii .
.It Fl V
Print version and exit.
-.It Fl W Ns Ar err
-Comma-separated warning options.
-Use
+.It Fl W Ns Ar level
+Specify the minimum message
+.Ar level
+to be reported on the standard error output and to affect the exit status.
+The
+.Ar level
+can be
+.Cm warning ,
+.Cm error ,
+or
+.Cm fatal .
+The default is
+.Fl W Ns Cm fatal ;
.Fl W Ns Cm all
-to print warnings,
-.Fl W Ns Cm error
-for warnings to be considered errors and cause utility
-termination.
-Multiple
-.Fl W
-arguments may be comma-separated, such as
-.Fl W Ns Cm error , Ns Cm all .
+is an alias for
+.Fl W Ns Cm warning .
+See
+.Sx EXIT STATUS
+and
+.Sx DIAGNOSTICS
+for details.
+.Pp
+The special option
+.Fl W Ns Cm stop
+tells
+.Nm
+to exit after parsing a file that causes warnings or errors of at least
+the requested level.
+No formatted output will be produced from that file.
+If both a
+.Ar level
+and
+.Cm stop
+are requested, they can be joined with a comma, for example
+.Fl W Ns Cm error , Ns Cm stop .
.It Ar file
Read input from zero or more files.
If unspecified, reads from stdin.
@@ -91,8 +108,6 @@ text from stdin, implying
and produces
.Fl T Ns Cm ascii
output.
-.Pp
-.Ex -std mandoc
.Ss Input Formats
The
.Nm
@@ -136,39 +151,6 @@ specified and
or
.Fl m Ns Cm an
is specified, then this format is used exclusively.
-.Ss Compiler Options
-Default
-.Xr mdoc 7
-and
-.Xr man 7
-compilation behaviour may be overridden with the
-.Fl f
-flag.
-.Bl -tag -width Ds
-.It Fl f Ns Cm ign-errors
-When parsing multiple files, don't halt when one errors out.
-Useful with
-.Fl T Ns Cm lint
-over a large set of manuals passed on the command line.
-.It Fl f Ns Cm ign-escape
-Ignore invalid escape sequences.
-This is the default, but the option can be used to override an earlier
-.Fl f Ns Cm strict .
-.It Fl f Ns Cm ign-scope
-When rewinding the scope of a block macro, forces the compiler to ignore
-scope violations.
-This can seriously mangle the resulting tree.
-.Pq mdoc only
-.It Fl f Ns Cm no-ign-escape
-Do not ignore invalid escape sequences.
-.It Fl f Ns Cm no-ign-macro
-Do not ignore unknown macros at the start of input lines.
-.It Fl f Ns Cm strict
-Implies
-.Fl f Ns Cm no-ign-escape
-and
-.Fl f Ns Cm no-ign-macro .
-.El
.Ss Output Formats
The
.Nm
@@ -189,9 +171,7 @@ See
.It Fl T Ns Cm lint
Parse only: produce no output.
Implies
-.Fl W Ns Cm all
-and
-.Fl f Ns Cm strict .
+.Fl W Ns Cm warning .
.It Fl T Ns Cm pdf
Produce PDF output.
See
@@ -352,10 +332,51 @@ See
.Sx HTML Output
for details; beyond generating XHTML tags instead of HTML tags, these
output modes are identical.
+.Sh EXIT STATUS
+The
+.Nm
+utility exits with one of the following values, controlled by the message
+.Ar level
+associated with the
+.Fl W
+option:
+.Pp
+.Bl -tag -width Ds -compact
+.It 0
+No warnings or errors occurred, or those that did were ignored because
+they were lower than the requested
+.Ar level .
+.It 2
+At least one warning occurred, but no error, and
+.Fl W Ns Cm warning
+was specified.
+.It 3
+At least one parsing error occurred, but no fatal error, and
+.Fl W Ns Cm error
+or
+.Fl W Ns Cm warning
+was specified.
+.It 4
+A fatal parsing error occurred.
+.It 5
+Invalid command line arguments were specified.
+No input files have been read.
+.It 6
+An operating system error occurred, for example memory exhaustion or an
+error accessing input files.
+Such errors cause
+.Nm
+to exit at once, possibly in the middle of parsing or formatting a file.
+.El
+.Pp
+Note that selecting
+.Fl T Ns Cm lint
+output mode implies
+.Fl W Ns Cm warning .
.Sh EXAMPLES
To page manuals to the terminal:
.Pp
-.D1 $ mandoc \-Wall,error \-fstrict mandoc.1 2\*(Gt&1 | less
+.D1 $ mandoc \-Wall,stop mandoc.1 2\*(Gt&1 | less
.D1 $ mandoc mandoc.1 mdoc.3 mdoc.7 | less
.Pp
To produce HTML manuals with
@@ -366,11 +387,74 @@ as the style-sheet:
.Pp
To check over a large set of manuals:
.Pp
-.Dl $ mandoc \-Tlint \-fign-errors `find /usr/src -name \e*\e.[1-9]`
+.Dl $ mandoc \-Tlint `find /usr/src -name \e*\e.[1-9]`
.Pp
To produce a series of PostScript manuals for A4 paper:
.Pp
.D1 $ mandoc \-Tps \-Opaper=a4 mdoc.7 man.7 \*(Gt manuals.ps
+.Sh DIAGNOSTICS
+Standard error messages reporting parsing errors are prefixed by
+.Pp
+.Sm off
+.D1 Ar file : line : column : \ level :
+.Sm on
+.Pp
+where the fields have the following meanings:
+.Bl -tag -width "column"
+.It Ar file
+The name of the input file causing the message.
+.It Ar line
+The line number in that input file.
+Line numbering starts at 1.
+.It Ar column
+The column number in that input file.
+Column numbering starts at 1.
+If the issue is caused by a word, the column number usually
+points to the first character of the word.
+.It Ar level
+The message level, printed in capital letters.
+.El
+.Pp
+Message levels have the following meanings:
+.Bl -tag -width "warning"
+.It Cm fatal
+The parser is unable to parse a given input file at all.
+No formatted output is produced from that input file.
+.It Cm error
+An input file contains syntax that cannot be safely interpreted,
+either because it is invalid or because
+.Nm
+does not implement it yet.
+By discarding part of the input or inserting missing tokens,
+the parser is able to continue, and the error does not prevent
+generation of formatted output, but typically, preparing that
+output involves information loss, broken document structure
+or unintended formatting.
+.It Cm warning
+An input file uses obsolete, discouraged or non-portable syntax.
+All the same, the meaning of the input is unambiguous and a correct
+rendering can be produced.
+Documents causing warnings may render poorly when using other
+formatting tools instead of
+.Nm .
+.El
+.Pp
+Messages of the
+.Cm warning
+and
+.Cm error
+levels are hidden unless their level, or a lower level, is requested using a
+.Fl W
+option or
+.Fl T Ns Cm lint
+output mode.
+.Pp
+The
+.Nm
+utility may also print messages related to invalid command line arguments
+or operating system errors, for example when memory is exhausted or
+input files cannot be read. Such messages do not carry the prefix
+described above.
.Sh COMPATIBILITY
This section summarises
.Nm
Index: mandoc.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mandoc.c,v
retrieving revision 1.17
diff -u -p -r1.17 mandoc.c
--- mandoc.c 18 Aug 2010 02:38:40 -0000 1.17
+++ mandoc.c 19 Aug 2010 17:09:16 -0000
@@ -195,7 +195,7 @@ mandoc_calloc(size_t num, size_t size)
ptr = calloc(num, size);
if (NULL == ptr) {
perror(NULL);
- exit(EXIT_FAILURE);
+ exit(MANDOCLEVEL_SYSERR);
}
return(ptr);
@@ -210,7 +210,7 @@ mandoc_malloc(size_t size)
ptr = malloc(size);
if (NULL == ptr) {
perror(NULL);
- exit(EXIT_FAILURE);
+ exit(MANDOCLEVEL_SYSERR);
}
return(ptr);
@@ -224,7 +224,7 @@ mandoc_realloc(void *ptr, size_t size)
ptr = realloc(ptr, size);
if (NULL == ptr) {
perror(NULL);
- exit(EXIT_FAILURE);
+ exit(MANDOCLEVEL_SYSERR);
}
return(ptr);
@@ -239,7 +239,7 @@ mandoc_strdup(const char *ptr)
p = strdup(ptr);
if (NULL == p) {
perror(NULL);
- exit(EXIT_FAILURE);
+ exit(MANDOCLEVEL_SYSERR);
}
return(p);
Index: mandoc.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mandoc.h,v
retrieving revision 1.11
diff -u -p -r1.11 mandoc.h
--- mandoc.h 25 Jul 2010 18:05:54 -0000 1.11
+++ mandoc.h 19 Aug 2010 17:09:16 -0000
@@ -26,6 +26,17 @@
__BEGIN_DECLS
+enum mandoclevel {
+ MANDOCLEVEL_OK = 0,
+ MANDOCLEVEL_RESERVED,
+ MANDOCLEVEL_WARNING,
+ MANDOCLEVEL_ERROR,
+ MANDOCLEVEL_FATAL,
+ MANDOCLEVEL_BADARG,
+ MANDOCLEVEL_SYSERR,
+ MANDOCLEVEL_MAX
+};
+
enum mandocerr {
MANDOCERR_OK,
@@ -105,7 +116,7 @@ enum mandocerr {
MANDOCERR_NODOCBODY, /* no document body */
MANDOCERR_NODOCPROLOG, /* no document prologue */
MANDOCERR_UTSNAME, /* utsname system call failed */
- MANDOCERR_MEM, /* memory exhausted */
+ MANDOCERR_MEM, /* static buffer exhausted */
MANDOCERR_MAX
};
Index: mdoc.3
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mdoc.3,v
retrieving revision 1.11
diff -u -p -r1.11 mdoc.3
--- mdoc.3 13 Jul 2010 01:09:13 -0000 1.11
+++ mdoc.3 19 Aug 2010 17:09:16 -0000
@@ -37,7 +37,6 @@
.Fo mdoc_alloc
.Fa "struct regset *regs"
.Fa "void *data"
-.Fa "int pflags"
.Fa "mandocmsg msgs"
.Fc
.Ft int
@@ -124,10 +123,6 @@ The
.Fa data
pointer is passed to
.Fa msgs .
-The
-.Fa pflags
-arguments are defined in
-.Pa mdoc.h .
Returns NULL on failure.
If non-NULL, the pointer must be freed with
.Fn mdoc_free .
@@ -338,7 +333,7 @@ int line;
bzero(®s, sizeof(struct regset));
line = 1;
-mdoc = mdoc_alloc(®s, NULL, 0, NULL);
+mdoc = mdoc_alloc(®s, NULL, NULL);
buf = NULL;
alloc_len = 0;
Index: mdoc.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mdoc.c,v
retrieving revision 1.64
diff -u -p -r1.64 mdoc.c
--- mdoc.c 18 Aug 2010 01:17:44 -0000 1.64
+++ mdoc.c 19 Aug 2010 17:09:16 -0000
@@ -94,8 +94,6 @@ static int node_append(struct mdoc *,
struct mdoc_node *);
static int mdoc_ptext(struct mdoc *, int, char *, int);
static int mdoc_pmacro(struct mdoc *, int, char *, int);
-static int macrowarn(struct mdoc *, int,
- const char *, int);
const struct mdoc_node *
@@ -187,8 +185,7 @@ mdoc_free(struct mdoc *mdoc)
* Allocate volatile and non-volatile parse resources.
*/
struct mdoc *
-mdoc_alloc(struct regset *regs, void *data,
- int pflags, mandocmsg msg)
+mdoc_alloc(struct regset *regs, void *data, mandocmsg msg)
{
struct mdoc *p;
@@ -196,7 +193,6 @@ mdoc_alloc(struct regset *regs, void *da
p->msg = msg;
p->data = data;
- p->pflags = pflags;
p->regs = regs;
mdoc_hash_init();
@@ -723,21 +719,6 @@ mdoc_ptext(struct mdoc *m, int line, cha
}
-static int
-macrowarn(struct mdoc *m, int ln, const char *buf, int offs)
-{
- int rc;
-
- rc = mdoc_vmsg(m, MANDOCERR_MACRO, ln, offs,
- "unknown macro: %s%s",
- buf, strlen(buf) > 3 ? "..." : "");
-
- /* FIXME: logic should be in driver. */
- /* FIXME: broken, will error out and not omit a message. */
- return(MDOC_IGN_MACRO & m->pflags ? rc : 0);
-}
-
-
/*
* Parse a macro line, that is, a line beginning with the control
* character.
@@ -781,15 +762,11 @@ mdoc_pmacro(struct mdoc *m, int ln, char
mac[j++] = buf[i++];
mac[j] = '\0';
- if (j == 4 || j < 2) {
- if ( ! macrowarn(m, ln, mac, sv))
- goto err;
- return(1);
- }
-
- if (MDOC_MAX == (tok = mdoc_hash_find(mac))) {
- if ( ! macrowarn(m, ln, mac, sv))
- goto err;
+ tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
+ if (MDOC_MAX == tok) {
+ mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv,
+ "unknown macro: %s%s",
+ buf, strlen(buf) > 3 ? "..." : "");
return(1);
}
Index: mdoc.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mdoc.h,v
retrieving revision 1.32
diff -u -p -r1.32 mdoc.h
--- mdoc.h 25 Jul 2010 18:05:54 -0000 1.32
+++ mdoc.h 19 Aug 2010 17:09:16 -0000
@@ -352,10 +352,6 @@ struct mdoc_node {
} data;
};
-#define MDOC_IGN_SCOPE (1 << 0) /* Ignore scope violations. */
-#define MDOC_IGN_ESCAPE (1 << 1) /* Ignore bad escape sequences. */
-#define MDOC_IGN_MACRO (1 << 2) /* Ignore unknown macros. */
-
/* See mdoc.3 for documentation. */
extern const char *const *mdoc_macronames;
@@ -368,7 +364,7 @@ struct mdoc;
/* See mdoc.3 for documentation. */
void mdoc_free(struct mdoc *);
-struct mdoc *mdoc_alloc(struct regset *, void *, int, mandocmsg);
+struct mdoc *mdoc_alloc(struct regset *, void *, mandocmsg);
void mdoc_reset(struct mdoc *);
int mdoc_parseln(struct mdoc *, int, char *, int);
const struct mdoc_node *mdoc_node(const struct mdoc *);
Index: mdoc_html.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mdoc_html.c,v
retrieving revision 1.28
diff -u -p -r1.28 mdoc_html.c
--- mdoc_html.c 7 Aug 2010 17:26:11 -0000 1.28
+++ mdoc_html.c 19 Aug 2010 17:09:17 -0000
@@ -28,6 +28,7 @@
#include "html.h"
#include "mdoc.h"
#include "main.h"
+#include "libmandoc.h"
#define INDENT 5
#define HALFINDENT 3
@@ -1176,11 +1177,7 @@ mdoc_bl_pre(MDOC_ARGS)
if (LIST_enum != n->data.Bl->type)
return(1);
- ord = malloc(sizeof(struct ord));
- if (NULL == ord) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
+ ord = mandoc_malloc(sizeof(struct ord));
ord->cookie = n;
ord->pos = 1;
ord->next = h->ords.head;
Index: mdoc_validate.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/mdoc_validate.c,v
retrieving revision 1.67
diff -u -p -r1.67 mdoc_validate.c
--- mdoc_validate.c 31 Jul 2010 21:43:07 -0000 1.67
+++ mdoc_validate.c 19 Aug 2010 17:09:17 -0000
@@ -477,12 +477,8 @@ check_text(struct mdoc *m, int ln, int p
if (c) {
p += c - 1;
pos += c - 1;
- continue;
- }
-
- c = mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE);
- if ( ! (MDOC_IGN_ESCAPE & m->pflags) && ! c)
- return(c);
+ } else
+ mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE);
}
return(1);
Index: roff.3
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/roff.3,v
retrieving revision 1.4
diff -u -p -r1.4 roff.3
--- roff.3 13 Jul 2010 01:09:13 -0000 1.4
+++ roff.3 19 Aug 2010 17:09:18 -0000
@@ -31,8 +31,8 @@
.Ft "struct roff *"
.Fo roff_alloc
.Fa "struct regset *regs"
-.Fa "mandocmsg msgs"
.Fa "void *data"
+.Fa "mandocmsg msgs"
.Fc
.Ft int
.Fn roff_endparse "struct roff *roff"
@@ -111,10 +111,6 @@ The
.Fa data
pointer is passed to
.Fa msgs .
-The
-.Fa pflags
-arguments are defined in
-.Pa roff.h .
Returns NULL on failure.
If non-NULL, the pointer must be freed with
.Fn roff_free .
Index: roff.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/roff.c,v
retrieving revision 1.10
diff -u -p -r1.10 roff.c
--- roff.c 31 Jul 2010 21:43:07 -0000 1.10
+++ roff.c 19 Aug 2010 17:09:18 -0000
@@ -160,7 +160,7 @@ static void roff_free1(struct roff *);
static enum rofft roff_hash_find(const char *);
static void roff_hash_init(void);
static void roffnode_cleanscope(struct roff *);
-static int roffnode_push(struct roff *,
+static void roffnode_push(struct roff *,
enum rofft, int, int);
static void roffnode_pop(struct roff *);
static enum rofft roff_parse(const char *, int *);
@@ -250,16 +250,12 @@ roffnode_pop(struct roff *r)
* Push a roff node onto the instruction stack. This must later be
* removed with roffnode_pop().
*/
-static int
+static void
roffnode_push(struct roff *r, enum rofft tok, int line, int col)
{
struct roffnode *p;
- if (NULL == (p = calloc(1, sizeof(struct roffnode)))) {
- (*r->msg)(MANDOCERR_MEM, r->data, line, col, NULL);
- return(0);
- }
-
+ p = mandoc_calloc(1, sizeof(struct roffnode));
p->tok = tok;
p->parent = r->last;
p->line = line;
@@ -267,7 +263,6 @@ roffnode_push(struct roff *r, enum rofft
p->rule = p->parent ? p->parent->rule : ROFFRULE_DENY;
r->last = p;
- return(1);
}
@@ -299,15 +294,11 @@ roff_free(struct roff *r)
struct roff *
-roff_alloc(struct regset *regs, const mandocmsg msg, void *data)
+roff_alloc(struct regset *regs, void *data, const mandocmsg msg)
{
struct roff *r;
- if (NULL == (r = calloc(1, sizeof(struct roff)))) {
- (*msg)(MANDOCERR_MEM, data, 0, 0, NULL);
- return(0);
- }
-
+ r = mandoc_calloc(1, sizeof(struct roff));
r->regs = regs;
r->msg = msg;
r->data = data;
@@ -634,8 +625,7 @@ roff_block(ROFF_ARGS)
pos++;
}
- if ( ! roffnode_push(r, tok, ln, ppos))
- return(ROFF_ERR);
+ roffnode_push(r, tok, ln, ppos);
if ('\0' == (*bufp)[pos])
return(ROFF_IGN);
@@ -657,12 +647,7 @@ roff_block(ROFF_ARGS)
if (1 == sz && '.' == (*bufp)[sv])
return(ROFF_IGN);
- r->last->end = malloc(sz + 1);
-
- if (NULL == r->last->end) {
- (*r->msg)(MANDOCERR_MEM, r->data, ln, pos, NULL);
- return(ROFF_ERR);
- }
+ r->last->end = mandoc_malloc(sz + 1);
memcpy(r->last->end, *bufp + sv, sz);
r->last->end[(int)sz] = '\0';
@@ -889,8 +874,7 @@ roff_cond(ROFF_ARGS)
return(ROFF_ERR);
}
- if ( ! roffnode_push(r, tok, ln, ppos))
- return(ROFF_ERR);
+ roffnode_push(r, tok, ln, ppos);
r->last->rule = rule;
Index: roff.h
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/roff.h,v
retrieving revision 1.3
diff -u -p -r1.3 roff.h
--- roff.h 27 Jun 2010 21:54:42 -0000 1.3
+++ roff.h 19 Aug 2010 17:09:18 -0000
@@ -29,7 +29,7 @@ __BEGIN_DECLS
struct roff;
void roff_free(struct roff *);
-struct roff *roff_alloc(struct regset *, mandocmsg, void *);
+struct roff *roff_alloc(struct regset *, void *, mandocmsg);
void roff_reset(struct roff *);
enum rofferr roff_parseln(struct roff *, int,
char **, size_t *, int, int *);
Index: term.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/term.c,v
retrieving revision 1.46
diff -u -p -r1.46 term.c
--- term.c 31 Jul 2010 21:43:07 -0000 1.46
+++ term.c 19 Aug 2010 17:09:18 -0000
@@ -29,6 +29,7 @@
#include "out.h"
#include "term.h"
#include "main.h"
+#include "libmandoc.h"
static void spec(struct termp *, enum roffdeco,
const char *, size_t);
@@ -76,12 +77,7 @@ term_alloc(enum termenc enc)
{
struct termp *p;
- p = calloc(1, sizeof(struct termp));
- if (NULL == p) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
-
+ p = mandoc_calloc(1, sizeof(struct termp));
p->enc = enc;
return(p);
}
@@ -570,11 +566,7 @@ adjbuf(struct termp *p, size_t sz)
while (sz >= p->maxcols)
p->maxcols <<= 2;
- p->buf = realloc(p->buf, p->maxcols);
- if (NULL == p->buf) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
+ p->buf = mandoc_realloc(p->buf, p->maxcols);
}
Index: term_ps.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/term_ps.c,v
retrieving revision 1.9
diff -u -p -r1.9 term_ps.c
--- term_ps.c 18 Aug 2010 01:30:16 -0000 1.9
+++ term_ps.c 19 Aug 2010 17:09:18 -0000
@@ -32,6 +32,7 @@
#include "out.h"
#include "main.h"
#include "term.h"
+#include "libmandoc.h"
/* Convert PostScript point "x" to an AFM unit. */
#define PNT2AFM(p, x) /* LINTED */ \
@@ -365,14 +366,9 @@ ps_growbuf(struct termp *p, size_t sz)
p->engine.ps.psmargsz += sz;
- p->engine.ps.psmarg = realloc
+ p->engine.ps.psmarg = mandoc_realloc
(p->engine.ps.psmarg,
p->engine.ps.psmargsz);
-
- if (NULL == p->engine.ps.psmarg) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
}
static double ps_hspan(const struct termp *,
@@ -603,13 +599,9 @@ pdf_obj(struct termp *p, size_t obj)
if ((obj - 1) >= p->engine.ps.pdfobjsz) {
p->engine.ps.pdfobjsz = obj + 128;
- p->engine.ps.pdfobjs = realloc
+ p->engine.ps.pdfobjs = mandoc_realloc
(p->engine.ps.pdfobjs,
p->engine.ps.pdfobjsz * sizeof(size_t));
- if (NULL == p->engine.ps.pdfobjs) {
- perror(NULL);
- exit(EXIT_FAILURE);
- }
}
p->engine.ps.pdfobjs[(int)obj - 1] = p->engine.ps.pdfbytes;
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-19 9:38 ` Sascha Wildner
2010-08-19 13:19 ` Kristaps Dzonsons
@ 2010-08-19 21:55 ` Ingo Schwarze
2010-08-20 12:31 ` Sascha Wildner
1 sibling, 1 reply; 13+ messages in thread
From: Ingo Schwarze @ 2010-08-19 21:55 UTC (permalink / raw)
To: discuss
Hi Sascha,
Sascha Wildner wrote on Thu, Aug 19, 2010 at 11:38:52AM +0200:
> On 8/18/2010 18:12, Ingo Schwarze wrote:
>> here is more error handling cleanup:
>> * Retire -Werror.
In my newest patch, -Werror has been replaced by -Wstop,
which finishes parsing the file, possibly reporting more
issues, then exits mandoc before starting the formatting
frontend.
> My general thought on this is that I definitely have the future
> plan to integrate running mandoc on manpages during _buildworld_
Sounds nice; be confident that it will work, we have done it in
OpenBSD. The 4.8 release ISOs have just been built like that and
will soon go to the CD factory.
> and have the build break if mandoc encounters issues.
You probably don't even need -Wstop for that:
I guess you are calling mandoc once for each individual manual,
are you? Otherwise, how do you get separate output files for
the manuals?
We are using the following make(1) rule in bsd.man.mk:
MANDOC?= mandoc
.9.cat9 .8.cat8 .7.cat7 .6.cat6 .5.cat5 .4.cat4 .3p.cat3p .3.cat3 \
.2.cat2 .1.cat1:
@echo "${MANDOC} ${.IMPSRC} > ${.TARGET}"
@${MANDOC} ${.IMPSRC} > ${.TARGET} || (rm -f ${.TARGET}; false)
To break the build in case of errors, you might put
MANDOC?= mandoc -Werror
or to even break it in case of warnings,
MANDOC?= mandoc -Wwarning
Right now, this won't work that well, because mandoc is still
reporting some bogus errors. But that we be worked on.
> My reasoning is that only if the build breaks, you'll get the
> developer's attention in case they introduced issues in manual
> pages. :)
Really? Oops.
Of course, you are welcome to use that tool if it works for you. :-)
In OpenBSD, we are taking great care to *not* break the tree, ever.
The problem is that several people are often running builds on
slow architectures. If you break the build, these people typically
lose days of their time, sometimes weeks. They won't be amused.
On the other hand, Jason is scrutinizing each manual commit,
and i'm also running most manual commits through mandoc -Tlint.
So, bad style or content in manuals will rarely go undetected,
and when contacted, developers *will* listen to us.
So, were are using -Wfatal without -Wstop for building the tree,
and that won't change. I guess ports will use -Werror to decide
whether mandoc can be used for their manuals, and fall back to
groff in case t can't. That is not yet implemented, i plan to
work on it this autumn, in particular during the p2k10 ports
hackathon in Budapest in November.
> If that is still possible with the later proposals from this
> discussion (just scanned it quickly since I'm at work), I'm fine.
As Kristaps already said, yes, you are.
Yours,
Ingo
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-19 17:57 ` Ingo Schwarze
@ 2010-08-19 22:47 ` Kristaps Dzonsons
2010-08-19 22:49 ` Kristaps Dzonsons
0 siblings, 1 reply; 13+ messages in thread
From: Kristaps Dzonsons @ 2010-08-19 22:47 UTC (permalink / raw)
To: discuss
Ingo,
I like this patch and I like what it brings us. I like getting rid of
-f and I like having -W levelised. This is nice work and the code will
be leaner and more readable when it's checked in: thank you!
I in-line-commented the nits I picked.
The only thing that bothered me was the inclusion of libmandoc.h's
allocation functions. I mention this in-line so I won't so it again
here (it's the first comment). For now, leave this part out. We'll fix
it in later commits.
Thanks again,
Kristaps
> Index: chars.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/chars.c,v
> retrieving revision 1.11
> diff -u -p -r1.11 chars.c
> --- chars.c 18 Aug 2010 02:46:37 -0000 1.11
> +++ chars.c 19 Aug 2010 17:09:15 -0000
> @@ -21,6 +21,7 @@
>
> #include "mandoc.h"
> #include "chars.h"
> +#include "libmandoc.h"
>
> #define PRINT_HI 126
> #define PRINT_LO 32
> @@ -87,17 +88,8 @@ chars_init(enum chars type)
> * (they're in-line re-ordered during lookup).
> */
>
> - tab = malloc(sizeof(struct tbl));
> - if (NULL == tab) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> -
> - htab = calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
> - if (NULL == htab) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> + tab = mandoc_malloc(sizeof(struct tbl));
> + htab = mandoc_calloc(PRINT_HI - PRINT_LO + 1, sizeof(struct ln **));
>
> for (i = 0; i < LINES_MAX; i++) {
> hash = (int)lines[i].code[0] - PRINT_LO;
This is not correct. libmandoc is only for use by libroff, libmdoc, and
libman. chars.o is linked directly into the mandoc binary.
In order to do this, the libmandoc mandoc_*alloc() functions would need
to be put into mandoc.h, and another file to implement this. For now,
let's leave it as is.
> Index: html.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/html.c,v
> retrieving revision 1.14
> diff -u -p -r1.14 html.c
> --- html.c 31 Jul 2010 21:43:07 -0000 1.14
> +++ html.c 19 Aug 2010 17:09:15 -0000
> @@ -30,6 +30,7 @@
> #include "chars.h"
> #include "html.h"
> #include "main.h"
> +#include "libmandoc.h"
>
> struct htmldata {
> const char *name;
> @@ -109,12 +110,7 @@ ml_alloc(char *outopts, enum htmltype ty
> toks[2] = "includes";
> toks[3] = NULL;
>
> - h = calloc(1, sizeof(struct html));
> - if (NULL == h) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> -
> + h = mandoc_calloc(1, sizeof(struct html));
> h->type = type;
> h->tags.head = NULL;
> h->ords.head = NULL;
> @@ -391,11 +387,7 @@ print_otag(struct html *h, enum htmltag
> /* Push this tags onto the stack of open scopes. */
>
> if ( ! (HTML_NOSTACK & htmltags[tag].flags)) {
> - t = malloc(sizeof(struct tag));
> - if (NULL == t) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> + t = mandoc_malloc(sizeof(struct tag));
> t->tag = tag;
> t->next = h->tags.head;
> h->tags.head = t;
Same here as above.
> Index: libman.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/libman.h,v
> retrieving revision 1.24
> diff -u -p -r1.24 libman.h
> --- libman.h 13 Jul 2010 01:09:12 -0000 1.24
> +++ libman.h 19 Aug 2010 17:09:15 -0000
> @@ -27,7 +27,6 @@ enum man_next {
> struct man {
> void *data; /* private application data */
> mandocmsg msg; /* output message handler */
> - int pflags; /* parse flags (see man.h) */
> int flags; /* parse flags */
> #define MAN_HALT (1 << 0) /* badness happened: die */
> #define MAN_ELINE (1 << 1) /* Next-line element scope. */
> Index: libmdoc.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/libmdoc.h,v
> retrieving revision 1.41
> diff -u -p -r1.41 libmdoc.h
> --- libmdoc.h 13 Jul 2010 01:09:12 -0000 1.41
> +++ libmdoc.h 19 Aug 2010 17:09:15 -0000
> @@ -36,7 +36,6 @@ struct mdoc {
> #define MDOC_PPHRASE (1 << 5) /* within a partial phrase */
> #define MDOC_FREECOL (1 << 6) /* `It' invocation should close */
> #define MDOC_SYNOPSIS (1 << 7) /* SYNOPSIS-style formatting */
> - int pflags;
> enum mdoc_next next; /* where to put the next node */
> struct mdoc_node *last; /* the last node parsed */
> struct mdoc_node *first; /* the first node parsed */
> Index: main.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/main.c,v
> retrieving revision 1.44
> diff -u -p -r1.44 main.c
> --- main.c 18 Aug 2010 01:03:22 -0000 1.44
> +++ main.c 19 Aug 2010 17:09:15 -0000
> @@ -33,6 +33,7 @@
> #include "mdoc.h"
> #include "man.h"
> #include "roff.h"
> +#include "libmandoc.h"
...and same here again...
>
> #define UNCONST(a) ((void *)(uintptr_t)(const void *)(a))
>
> @@ -64,17 +65,8 @@ enum outt {
> struct curparse {
> const char *file; /* Current parse. */
> int fd; /* Current parse. */
> - int wflags;
> - /* FIXME: set by max error */
> -#define WARN_WALL (1 << 0) /* All-warnings mask. */
> -#define WARN_WERR (1 << 2) /* Warnings->errors. */
> - int fflags;
> -#define FL_IGN_SCOPE (1 << 0) /* Ignore scope errors. */
> -#define FL_NIGN_ESCAPE (1 << 1) /* Don't ignore bad escapes. */
> -#define FL_NIGN_MACRO (1 << 2) /* Don't ignore bad macros. */
> -#define FL_IGN_ERRORS (1 << 4) /* Ignore failed parse. */
> -#define FL_STRICT FL_NIGN_ESCAPE | \
> - FL_NIGN_MACRO /* ignore nothing */
> + enum mandoclevel wlevel; /* Ignore messages below this. */
> + int wstop; /* Stop after a file with a warning. */
> enum intt inttype; /* which parser to use */
> struct man *man; /* man parser */
> struct mdoc *mdoc; /* mdoc parser */
> @@ -88,6 +80,26 @@ struct curparse {
> char outopts[BUFSIZ]; /* buf of output opts */
> };
>
> +static const char * const mandoclevels[MANDOCLEVEL_MAX] = {
> + "SUCCESS",
> + "RESERVED",
> + "WARNING",
> + "ERROR",
> + "FATAL",
> + "BADARG",
> + "SYSERR"
> +};
> +
> +static const enum mandocerr mandoclimits[MANDOCLEVEL_MAX] = {
> + MANDOCERR_OK,
> + MANDOCERR_WARNING,
> + MANDOCERR_WARNING,
> + MANDOCERR_ERROR,
> + MANDOCERR_FATAL,
> + MANDOCERR_MAX,
> + MANDOCERR_MAX
> +};
> +
> static const char * const mandocerrs[MANDOCERR_MAX] = {
> "ok",
>
> @@ -164,28 +176,23 @@ static const char * const mandocerrs[MAN
> "no document body",
> "no document prologue",
> "utsname system call failed",
> - "memory exhausted",
> + "static buffer exhausted",
> };
>
> static void fdesc(struct curparse *);
> static void ffile(const char *, struct curparse *);
> -static int foptions(int *, char *);
> -static struct man *man_init(struct curparse *);
> -static struct mdoc *mdoc_init(struct curparse *);
> -static struct roff *roff_init(struct curparse *);
> static int moptions(enum intt *, char *);
> static int mmsg(enum mandocerr, void *,
> int, int, const char *);
> -static int pset(const char *, int, struct curparse *,
> +static void pset(const char *, int, struct curparse *,
> struct man **, struct mdoc **);
> static int toptions(struct curparse *, char *);
> static void usage(void) __attribute__((noreturn));
> static void version(void) __attribute__((noreturn));
> -static int woptions(int *, char *);
> +static int woptions(struct curparse *, char *);
>
> static const char *progname;
> -static int with_fatal;
> -static int with_error;
> +static enum mandoclevel exit_status = MANDOCLEVEL_OK;
>
> int
> main(int argc, char *argv[])
> @@ -203,17 +210,14 @@ main(int argc, char *argv[])
>
> curp.inttype = INTT_AUTO;
> curp.outtype = OUTT_ASCII;
> + curp.wlevel = MANDOCLEVEL_FATAL;
>
> /* LINTED */
> - while (-1 != (c = getopt(argc, argv, "f:m:O:T:VW:")))
> + while (-1 != (c = getopt(argc, argv, "m:O:T:VW:")))
> switch (c) {
> - case ('f'):
> - if ( ! foptions(&curp.fflags, optarg))
> - return(EXIT_FAILURE);
> - break;
> case ('m'):
> if ( ! moptions(&curp.inttype, optarg))
> - return(EXIT_FAILURE);
> + return(MANDOCLEVEL_BADARG);
> break;
> case ('O'):
> (void)strlcat(curp.outopts, optarg, BUFSIZ);
> @@ -221,11 +225,11 @@ main(int argc, char *argv[])
> break;
> case ('T'):
> if ( ! toptions(&curp, optarg))
> - return(EXIT_FAILURE);
> + return(MANDOCLEVEL_BADARG);
> break;
> case ('W'):
> - if ( ! woptions(&curp.wflags, optarg))
> - return(EXIT_FAILURE);
> + if ( ! woptions(&curp, optarg))
> + return(MANDOCLEVEL_BADARG);
> break;
> case ('V'):
> version();
> @@ -247,8 +251,7 @@ main(int argc, char *argv[])
>
> while (*argv) {
> ffile(*argv, &curp);
> -
> - if (with_fatal && !(curp.fflags & FL_IGN_ERRORS))
> + if (MANDOCLEVEL_OK != exit_status && curp.wstop)
> break;
> ++argv;
> }
> @@ -262,8 +265,7 @@ main(int argc, char *argv[])
> if (curp.roff)
> roff_free(curp.roff);
>
> - return((with_fatal || with_error) ?
> - EXIT_FAILURE : EXIT_SUCCESS);
> + return(exit_status);
> }
>
>
> @@ -272,7 +274,7 @@ version(void)
> {
>
> (void)printf("%s %s\n", progname, VERSION);
> - exit(EXIT_SUCCESS);
> + exit(MANDOCLEVEL_OK);
> }
>
>
> @@ -283,53 +285,7 @@ usage(void)
> (void)fprintf(stderr, "usage: %s [-V] [-foption] "
> "[-mformat] [-Ooption] [-Toutput] "
> "[-Werr] [file...]\n", progname);
> - exit(EXIT_FAILURE);
> -}
> -
> -
> -static struct man *
> -man_init(struct curparse *curp)
> -{
> - int pflags;
> -
> - /* Defaults from mandoc.1. */
> -
> - pflags = MAN_IGN_MACRO | MAN_IGN_ESCAPE;
> -
> - if (curp->fflags & FL_NIGN_MACRO)
> - pflags &= ~MAN_IGN_MACRO;
> - if (curp->fflags & FL_NIGN_ESCAPE)
> - pflags &= ~MAN_IGN_ESCAPE;
> -
> - return(man_alloc(&curp->regs, curp, pflags, mmsg));
> -}
> -
> -
> -static struct roff *
> -roff_init(struct curparse *curp)
> -{
> -
> - return(roff_alloc(&curp->regs, mmsg, curp));
> -}
> -
> -
> -static struct mdoc *
> -mdoc_init(struct curparse *curp)
> -{
> - int pflags;
> -
> - /* Defaults from mandoc.1. */
> -
> - pflags = MDOC_IGN_MACRO | MDOC_IGN_ESCAPE;
> -
> - if (curp->fflags & FL_IGN_SCOPE)
> - pflags |= MDOC_IGN_SCOPE;
> - if (curp->fflags & FL_NIGN_ESCAPE)
> - pflags &= ~MDOC_IGN_ESCAPE;
> - if (curp->fflags & FL_NIGN_MACRO)
> - pflags &= ~MDOC_IGN_MACRO;
> -
> - return(mdoc_alloc(&curp->regs, curp, pflags, mmsg));
> + exit(MANDOCLEVEL_BADARG);
> }
>
>
> @@ -340,7 +296,7 @@ ffile(const char *file, struct curparse
> curp->file = file;
> if (-1 == (curp->fd = open(curp->file, O_RDONLY, 0))) {
> perror(curp->file);
> - with_fatal = 1;
> + exit_status = MANDOCLEVEL_SYSERR;
> return;
> }
>
> @@ -351,24 +307,12 @@ ffile(const char *file, struct curparse
> }
>
>
> -static int
> +static void
> resize_buf(struct buf *buf, size_t initial)
> {
> - void *tmp;
> - size_t sz;
>
> - if (buf->sz == 0)
> - sz = initial;
> - else
> - sz = 2 * buf->sz;
> - tmp = realloc(buf->buf, sz);
> - if (NULL == tmp) {
> - perror(NULL);
> - return(0);
> - }
> - buf->buf = tmp;
> - buf->sz = sz;
> - return(1);
> + buf->sz = buf->sz ? 2 * buf->sz : initial;
> + buf->buf = mandoc_realloc(buf->buf, buf->sz);
> }
Note that I'm ok with this function returning void, although the same
again goes with mandoc_realloc...
>
>
> @@ -381,7 +325,6 @@ read_whole_file(struct curparse *curp, s
>
> if (-1 == fstat(curp->fd, &st)) {
> perror(curp->file);
> - with_fatal = 1;
> return(0);
> }
>
> @@ -396,7 +339,6 @@ read_whole_file(struct curparse *curp, s
> if (st.st_size >= (1U << 31)) {
> fprintf(stderr, "%s: input too large\n",
> curp->file);
> - with_fatal = 1;
> return(0);
> }
> *with_mmap = 1;
> @@ -423,8 +365,7 @@ read_whole_file(struct curparse *curp, s
> curp->file);
> break;
> }
> - if (! resize_buf(fb, 65536))
> - break;
> + resize_buf(fb, 65536);
> }
> ssz = read(curp->fd, fb->buf + (int)off, fb->sz - off);
> if (ssz == 0) {
> @@ -440,7 +381,6 @@ read_whole_file(struct curparse *curp, s
>
> free(fb->buf);
> fb->buf = NULL;
> - with_fatal = 1;
> return(0);
> }
>
> @@ -467,13 +407,15 @@ fdesc(struct curparse *curp)
> * memory mapped. ln is a line buffer and grows on-demand.
> */
>
> - if ( ! read_whole_file(curp, &blk, &with_mmap))
> + if ( ! read_whole_file(curp, &blk, &with_mmap)) {
> + exit_status = MANDOCLEVEL_SYSERR;
> return;
> + }
>
> if (NULL == curp->roff)
> - curp->roff = roff_init(curp);
> - if (NULL == (roff = curp->roff))
> - goto bailout;
> + curp->roff = roff_alloc(&curp->regs, curp, mmsg);
> + assert(curp->roff);
> + roff = curp->roff;
>
> for (i = 0, lnn = 1; i < (int)blk.sz;) {
> pos = 0;
> @@ -496,10 +438,8 @@ fdesc(struct curparse *curp)
>
> c = (unsigned char) blk.buf[i];
> if ( ! (isascii(c) && (isgraph(c) || isblank(c)))) {
> - if ( ! mmsg(MANDOCERR_BADCHAR, curp,
> - lnn_start, pos,
> - "ignoring byte"))
> - goto bailout;
> + mmsg(MANDOCERR_BADCHAR, curp,
> + lnn_start, pos, "ignoring byte");
> i++;
> continue;
> }
> @@ -507,8 +447,7 @@ fdesc(struct curparse *curp)
> /* Trailing backslash is like a plain character. */
> if ('\\' != blk.buf[i] || i + 1 == (int)blk.sz) {
> if (pos >= (int)ln.sz)
> - if (! resize_buf(&ln, 256))
> - goto bailout;
> + resize_buf(&ln, 256);
> ln.buf[pos++] = blk.buf[i++];
> continue;
> }
> @@ -540,16 +479,14 @@ fdesc(struct curparse *curp)
> }
> /* Some other escape sequence, copy and continue. */
> if (pos + 1 >= (int)ln.sz)
> - if (! resize_buf(&ln, 256))
> - goto bailout;
> + resize_buf(&ln, 256);
>
> ln.buf[pos++] = blk.buf[i++];
> ln.buf[pos++] = blk.buf[i++];
> }
>
> if (pos >= (int)ln.sz)
> - if (! resize_buf(&ln, 256))
> - goto bailout;
> + resize_buf(&ln, 256);
> ln.buf[pos] = '\0';
>
> /*
> @@ -567,10 +504,12 @@ fdesc(struct curparse *curp)
> &ln.buf, &ln.sz, of, &of);
> } while (ROFF_RERUN == re);
>
> - if (ROFF_IGN == re)
> + if (ROFF_IGN == re) {
> continue;
> - else if (ROFF_ERR == re)
> - goto bailout;
> + } else if (ROFF_ERR == re) {
> + assert(MANDOCLEVEL_FATAL <= exit_status);
> + goto cleanup;
> + }
>
> /*
> * If input parsers have not been allocated, do so now.
> @@ -580,32 +519,50 @@ fdesc(struct curparse *curp)
> */
>
> if ( ! (man || mdoc))
> - if ( ! pset(ln.buf + of, pos - of, curp, &man, &mdoc))
> - goto bailout;
> + pset(ln.buf + of, pos - of, curp, &man, &mdoc);
>
> /* Lastly, push down into the parsers themselves. */
>
> - if (man && ! man_parseln(man, lnn_start, ln.buf, of))
> - goto bailout;
> - if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of))
> - goto bailout;
> + if (man && ! man_parseln(man, lnn_start, ln.buf, of)) {
> + assert(MANDOCLEVEL_FATAL <= exit_status);
> + goto cleanup;
> + }
> + if (mdoc && ! mdoc_parseln(mdoc, lnn_start, ln.buf, of)) {
> + assert(MANDOCLEVEL_FATAL <= exit_status);
> + goto cleanup;
> + }
> }
>
> + /*
> + * With -Wstop and warnings or errors of at least
> + * the requested level, do not produce output.
> + */
> +
> + if (MANDOCLEVEL_OK != exit_status && curp->wstop)
> + goto cleanup;
> +
> /* NOTE a parser may not have been assigned, yet. */
>
> if ( ! (man || mdoc)) {
> fprintf(stderr, "%s: Not a manual\n", curp->file);
> - goto bailout;
> + exit_status = MANDOCLEVEL_FATAL;
> + goto cleanup;
> }
>
> /* Clean up the parse routine ASTs. */
>
> - if (mdoc && ! mdoc_endparse(mdoc))
> - goto bailout;
> - if (man && ! man_endparse(man))
> - goto bailout;
> - if (roff && ! roff_endparse(roff))
> - goto bailout;
> + if (mdoc && ! mdoc_endparse(mdoc)) {
> + assert(MANDOCLEVEL_FATAL <= exit_status);
> + goto cleanup;
> + }
> + if (man && ! man_endparse(man)) {
> + assert(MANDOCLEVEL_FATAL <= exit_status);
> + goto cleanup;
> + }
> + if (roff && ! roff_endparse(roff)) {
> + assert(MANDOCLEVEL_FATAL <= exit_status);
> + goto cleanup;
> + }
>
> /* If unset, allocate output dev now (if applicable). */
>
> @@ -681,14 +638,10 @@ fdesc(struct curparse *curp)
> free(blk.buf);
>
> return;
> -
> - bailout:
> - with_fatal = 1;
> - goto cleanup;
> }
>
>
> -static int
> +static void
> pset(const char *buf, int pos, struct curparse *curp,
> struct man **man, struct mdoc **mdoc)
> {
> @@ -707,39 +660,38 @@ pset(const char *buf, int pos, struct cu
> if (' ' != buf[i] && '\t' != buf[i])
> break;
> if (0 == buf[i])
Addendum: this should be '\0' == buf[i]...
> - return(1);
> + return;
> }
>
> switch (curp->inttype) {
> case (INTT_MDOC):
> if (NULL == curp->mdoc)
> - curp->mdoc = mdoc_init(curp);
> - if (NULL == (*mdoc = curp->mdoc))
> - return(0);
> - return(1);
> + curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg);
> + assert(curp->mdoc);
> + *mdoc = curp->mdoc;
> + return;
> case (INTT_MAN):
> if (NULL == curp->man)
> - curp->man = man_init(curp);
> - if (NULL == (*man = curp->man))
> - return(0);
> - return(1);
> + curp->man = man_alloc(&curp->regs, curp, mmsg);
> + assert(curp->man);
> + *man = curp->man;
> + return;
> default:
> break;
> }
>
> if (pos >= 3 && 0 == memcmp(buf, ".Dd", 3)) {
> if (NULL == curp->mdoc)
> - curp->mdoc = mdoc_init(curp);
> - if (NULL == (*mdoc = curp->mdoc))
> - return(0);
> - return(1);
> + curp->mdoc = mdoc_alloc(&curp->regs, curp, mmsg);
> + assert(curp->mdoc);
> + *mdoc = curp->mdoc;
> + return;
> }
>
> if (NULL == curp->man)
> - curp->man = man_init(curp);
> - if (NULL == (*man = curp->man))
> - return(0);
> - return(1);
> + curp->man = man_alloc(&curp->regs, curp, mmsg);
> + assert(curp->man);
> + *man = curp->man;
> }
>
>
> @@ -770,8 +722,7 @@ toptions(struct curparse *curp, char *ar
> curp->outtype = OUTT_ASCII;
> else if (0 == strcmp(arg, "lint")) {
> curp->outtype = OUTT_LINT;
> - curp->wflags |= WARN_WALL;
> - curp->fflags |= FL_STRICT;
> + curp->wlevel = MANDOCLEVEL_WARNING;
> }
> else if (0 == strcmp(arg, "tree"))
> curp->outtype = OUTT_TREE;
> @@ -793,71 +744,37 @@ toptions(struct curparse *curp, char *ar
>
>
> static int
> -foptions(int *fflags, char *arg)
> +woptions(struct curparse *curp, char *arg)
> {
> char *v, *o;
> - const char *toks[8];
> + const char *toks[6];
>
> - toks[0] = "ign-scope";
> - toks[1] = "no-ign-escape";
> - toks[2] = "no-ign-macro";
> - toks[3] = "ign-errors";
> - toks[4] = "strict";
> - toks[5] = "ign-escape";
> - toks[6] = NULL;
> + toks[0] = "stop";
> + toks[1] = "all";
> + toks[2] = "warning";
> + toks[3] = "error";
> + toks[4] = "fatal";
> + toks[5] = NULL;
>
> while (*arg) {
> o = arg;
> switch (getsubopt(&arg, UNCONST(toks), &v)) {
> case (0):
> - *fflags |= FL_IGN_SCOPE;
> + curp->wstop = 1;
> break;
> case (1):
> - *fflags |= FL_NIGN_ESCAPE;
> - break;
> + /* FALLTHROUGH */
> case (2):
> - *fflags |= FL_NIGN_MACRO;
> + curp->wlevel = MANDOCLEVEL_WARNING;
> break;
> case (3):
> - *fflags |= FL_IGN_ERRORS;
> + curp->wlevel = MANDOCLEVEL_ERROR;
> break;
> case (4):
> - *fflags |= FL_STRICT;
> - break;
> - case (5):
> - *fflags &= ~FL_NIGN_ESCAPE;
> - break;
> - default:
> - fprintf(stderr, "%s: Bad argument\n", o);
> - return(0);
> - }
> - }
> -
> - return(1);
> -}
> -
> -
> -static int
> -woptions(int *wflags, char *arg)
> -{
> - char *v, *o;
> - const char *toks[3];
> -
> - toks[0] = "all";
> - toks[1] = "error";
> - toks[2] = NULL;
> -
> - while (*arg) {
> - o = arg;
> - switch (getsubopt(&arg, UNCONST(toks), &v)) {
> - case (0):
> - *wflags |= WARN_WALL;
> - break;
> - case (1):
> - *wflags |= WARN_WERR;
> + curp->wlevel = MANDOCLEVEL_FATAL;
> break;
> default:
> - fprintf(stderr, "%s: Bad argument\n", o);
> + fprintf(stderr, "-W%s: Bad argument\n", o);
> return(0);
> }
> }
> @@ -870,37 +787,24 @@ static int
> mmsg(enum mandocerr t, void *arg, int ln, int col, const char *msg)
> {
> struct curparse *cp;
> - const char *level;
> - int rc;
> + enum mandoclevel level;
>
> - cp = (struct curparse *)arg;
> - level = NULL;
> - rc = 1;
> + level = MANDOCLEVEL_FATAL;
> + while (t < mandoclimits[level])
> + level--;
>
> - if (t >= MANDOCERR_FATAL) {
> - with_fatal = 1;
> - level = "FATAL";
> - rc = 0;
> - } else {
> - if ( ! (WARN_WALL & cp->wflags))
> - return(1);
> - if (t >= MANDOCERR_ERROR) {
> - with_error = 1;
> - level = "ERROR";
> - }
> - if (WARN_WERR & cp->wflags) {
> - with_fatal = 1;
> - rc = 0;
> - }
> - }
> + cp = (struct curparse *)arg;
> + if (level < cp->wlevel)
> + return(1);
>
> - fprintf(stderr, "%s:%d:%d:", cp->file, ln, col + 1);
> - if (level)
> - fprintf(stderr, " %s:", level);
> - fprintf(stderr, " %s", mandocerrs[t]);
> + fprintf(stderr, "%s:%d:%d: %s: %s",
> + cp->file, ln, col + 1, mandoclevels[level], mandocerrs[t]);
> if (msg)
> fprintf(stderr, ": %s", msg);
> fputc('\n', stderr);
>
> - return(rc);
> + if (exit_status < level)
> + exit_status = level;
> +
> + return(level < MANDOCLEVEL_FATAL);
> }
> Index: man.3
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/man.3,v
> retrieving revision 1.14
> diff -u -p -r1.14 man.3
> --- man.3 18 Aug 2010 02:46:37 -0000 1.14
> +++ man.3 19 Aug 2010 17:09:16 -0000
> @@ -35,7 +35,6 @@
> .Fo man_alloc
> .Fa "struct regset *regs"
> .Fa "void *data"
> -.Fa "int pflags"
> .Fa "mandocmsg msgs"
> .Fc
> .Ft int
> @@ -172,10 +171,6 @@ The
> .Fa data
> pointer is passed to
> .Fa msgs .
> -The
> -.Fa pflags
> -arguments are defined in
> -.Pa man.h .
> Returns NULL on failure.
> If non-NULL, the pointer must be freed with
> .Fn man_free .
> @@ -298,7 +293,7 @@ int line;
>
> bzero(®s, sizeof(struct regset));
> line = 1;
> -man = man_alloc(®s, NULL, 0, NULL);
> +man = man_alloc(®s, NULL, NULL);
> buf = NULL;
> alloc_len = 0;
>
> Index: man.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/man.c,v
> retrieving revision 1.39
> diff -u -p -r1.39 man.c
> --- man.c 18 Aug 2010 01:17:44 -0000 1.39
> +++ man.c 19 Aug 2010 17:09:16 -0000
> @@ -52,7 +52,6 @@ static int man_ptext(struct man *, int
> static int man_pmacro(struct man *, int, char *, int);
> static void man_free1(struct man *);
> static void man_alloc1(struct man *);
> -static int macrowarn(struct man *, int, const char *, int);
>
>
> const struct man_node *
> @@ -90,8 +89,7 @@ man_free(struct man *man)
>
>
> struct man *
> -man_alloc(struct regset *regs, void *data,
> - int pflags, mandocmsg msg)
> +man_alloc(struct regset *regs, void *data, mandocmsg msg)
> {
> struct man *p;
>
> @@ -99,7 +97,6 @@ man_alloc(struct regset *regs, void *dat
>
> man_hash_init();
> p->data = data;
> - p->pflags = pflags;
> p->msg = msg;
> p->regs = regs;
>
> @@ -431,19 +428,6 @@ descope:
> }
>
>
> -static int
> -macrowarn(struct man *m, int ln, const char *buf, int offs)
> -{
> - int rc;
> -
> - rc = man_vmsg(m, MANDOCERR_MACRO, ln, offs,
> - "unknown macro: %s%s",
> - buf, strlen(buf) > 3 ? "..." : "");
> -
> - return(MAN_IGN_MACRO & m->pflags ? rc : 0);
> -}
> -
> -
> int
> man_pmacro(struct man *m, int ln, char *buf, int offs)
> {
> @@ -486,15 +470,11 @@ man_pmacro(struct man *m, int ln, char *
> mac[j++] = buf[i++];
> mac[j] = '\0';
>
> - if (j == 4 || j < 1) {
> - if ( ! macrowarn(m, ln, mac, ppos))
> - goto err;
> - return(1);
> - }
> -
> - if (MAN_MAX == (tok = man_hash_find(mac))) {
> - if ( ! macrowarn(m, ln, mac, ppos))
> - goto err;
> + tok = (j > 0 && j < 4) ? man_hash_find(mac) : MAN_MAX;
> + if (MAN_MAX == tok) {
> + man_vmsg(m, MANDOCERR_MACRO, ln, ppos,
> + "unknown macro: %s%s",
> + buf, strlen(buf) > 3 ? "..." : "");
Ooh, I like this.
> return(1);
> }
>
> Index: man.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/man.h,v
> retrieving revision 1.25
> diff -u -p -r1.25 man.h
> --- man.h 25 Jul 2010 18:05:54 -0000 1.25
> +++ man.h 19 Aug 2010 17:09:16 -0000
> @@ -97,9 +97,6 @@ struct man_node {
> struct man_node *body;
> };
>
> -#define MAN_IGN_MACRO (1 << 0)
> -#define MAN_IGN_ESCAPE (1 << 2)
> -
> extern const char *const *man_macronames;
>
> __BEGIN_DECLS
> @@ -107,7 +104,7 @@ __BEGIN_DECLS
> struct man;
>
> void man_free(struct man *);
> -struct man *man_alloc(struct regset *, void *, int, mandocmsg);
> +struct man *man_alloc(struct regset *, void *, mandocmsg);
> void man_reset(struct man *);
> int man_parseln(struct man *, int, char *, int);
> int man_endparse(struct man *);
> Index: man_validate.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/man_validate.c,v
> retrieving revision 1.28
> diff -u -p -r1.28 man_validate.c
> --- man_validate.c 25 Jul 2010 18:05:54 -0000 1.28
> +++ man_validate.c 19 Aug 2010 17:09:16 -0000
> @@ -229,12 +229,8 @@ check_text(CHKARGS)
> if (c) {
> p += c - 1;
> pos += c - 1;
> - continue;
> - }
> -
> - c = man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
> - if ( ! (MAN_IGN_ESCAPE & m->pflags) && ! c)
> - return(c);
> + } else
> + man_pmsg(m, n->line, pos, MANDOCERR_BADESCAPE);
> }
>
> return(1);
> Index: mandoc.1
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mandoc.1,v
> retrieving revision 1.37
> diff -u -p -r1.37 mandoc.1
> --- mandoc.1 18 Aug 2010 01:35:01 -0000 1.37
> +++ mandoc.1 19 Aug 2010 17:09:16 -0000
> @@ -23,11 +23,10 @@
> .Sh SYNOPSIS
> .Nm mandoc
> .Op Fl V
> -.Op Fl f Ns Ar option
> .Op Fl m Ns Ar format
> .Op Fl O Ns Ar option
> .Op Fl T Ns Ar output
> -.Op Fl W Ns Ar err
> +.Op Fl W Ns Ar level
> .Op Ar file...
> .Sh DESCRIPTION
> The
> @@ -37,11 +36,6 @@ utility formats
> manual pages for display.
> The arguments are as follows:
> .Bl -tag -width Ds
> -.It Fl f Ns Ar option
> -Comma-separated compiler options.
> -See
> -.Sx Compiler Options
> -for details.
> .It Fl m Ns Ar format
> Input format.
> See
> @@ -60,18 +54,41 @@ Defaults to
> .Fl T Ns Cm ascii .
> .It Fl V
> Print version and exit.
> -.It Fl W Ns Ar err
> -Comma-separated warning options.
> -Use
> +.It Fl W Ns Ar level
> +Specify the minimum message
> +.Ar level
> +to be reported on the standard error output and to affect the exit status.
> +The
> +.Ar level
> +can be
> +.Cm warning ,
> +.Cm error ,
> +or
> +.Cm fatal .
> +The default is
> +.Fl W Ns Cm fatal ;
> .Fl W Ns Cm all
> -to print warnings,
> -.Fl W Ns Cm error
> -for warnings to be considered errors and cause utility
> -termination.
> -Multiple
> -.Fl W
> -arguments may be comma-separated, such as
> -.Fl W Ns Cm error , Ns Cm all .
> +is an alias for
> +.Fl W Ns Cm warning .
> +See
> +.Sx EXIT STATUS
> +and
> +.Sx DIAGNOSTICS
> +for details.
> +.Pp
> +The special option
> +.Fl W Ns Cm stop
> +tells
> +.Nm
> +to exit after parsing a file that causes warnings or errors of at least
> +the requested level.
> +No formatted output will be produced from that file.
> +If both a
> +.Ar level
> +and
> +.Cm stop
> +are requested, they can be joined with a comma, for example
> +.Fl W Ns Cm error , Ns Cm stop .
> .It Ar file
> Read input from zero or more files.
> If unspecified, reads from stdin.
> @@ -91,8 +108,6 @@ text from stdin, implying
> and produces
> .Fl T Ns Cm ascii
> output.
> -.Pp
> -.Ex -std mandoc
> .Ss Input Formats
> The
> .Nm
> @@ -136,39 +151,6 @@ specified and
> or
> .Fl m Ns Cm an
> is specified, then this format is used exclusively.
> -.Ss Compiler Options
> -Default
> -.Xr mdoc 7
> -and
> -.Xr man 7
> -compilation behaviour may be overridden with the
> -.Fl f
> -flag.
> -.Bl -tag -width Ds
> -.It Fl f Ns Cm ign-errors
> -When parsing multiple files, don't halt when one errors out.
> -Useful with
> -.Fl T Ns Cm lint
> -over a large set of manuals passed on the command line.
> -.It Fl f Ns Cm ign-escape
> -Ignore invalid escape sequences.
> -This is the default, but the option can be used to override an earlier
> -.Fl f Ns Cm strict .
> -.It Fl f Ns Cm ign-scope
> -When rewinding the scope of a block macro, forces the compiler to ignore
> -scope violations.
> -This can seriously mangle the resulting tree.
> -.Pq mdoc only
> -.It Fl f Ns Cm no-ign-escape
> -Do not ignore invalid escape sequences.
> -.It Fl f Ns Cm no-ign-macro
> -Do not ignore unknown macros at the start of input lines.
> -.It Fl f Ns Cm strict
> -Implies
> -.Fl f Ns Cm no-ign-escape
> -and
> -.Fl f Ns Cm no-ign-macro .
> -.El
> .Ss Output Formats
> The
> .Nm
> @@ -189,9 +171,7 @@ See
> .It Fl T Ns Cm lint
> Parse only: produce no output.
> Implies
> -.Fl W Ns Cm all
> -and
> -.Fl f Ns Cm strict .
> +.Fl W Ns Cm warning .
> .It Fl T Ns Cm pdf
> Produce PDF output.
> See
> @@ -352,10 +332,51 @@ See
> .Sx HTML Output
> for details; beyond generating XHTML tags instead of HTML tags, these
> output modes are identical.
> +.Sh EXIT STATUS
> +The
> +.Nm
> +utility exits with one of the following values, controlled by the message
> +.Ar level
> +associated with the
> +.Fl W
> +option:
> +.Pp
> +.Bl -tag -width Ds -compact
> +.It 0
> +No warnings or errors occurred, or those that did were ignored because
> +they were lower than the requested
> +.Ar level .
> +.It 2
> +At least one warning occurred, but no error, and
> +.Fl W Ns Cm warning
> +was specified.
> +.It 3
> +At least one parsing error occurred, but no fatal error, and
> +.Fl W Ns Cm error
> +or
> +.Fl W Ns Cm warning
> +was specified.
> +.It 4
> +A fatal parsing error occurred.
> +.It 5
> +Invalid command line arguments were specified.
> +No input files have been read.
> +.It 6
> +An operating system error occurred, for example memory exhaustion or an
> +error accessing input files.
> +Such errors cause
> +.Nm
> +to exit at once, possibly in the middle of parsing or formatting a file.
> +.El
> +.Pp
> +Note that selecting
> +.Fl T Ns Cm lint
> +output mode implies
> +.Fl W Ns Cm warning .
> .Sh EXAMPLES
> To page manuals to the terminal:
> .Pp
> -.D1 $ mandoc \-Wall,error \-fstrict mandoc.1 2\*(Gt&1 | less
> +.D1 $ mandoc \-Wall,stop mandoc.1 2\*(Gt&1 | less
> .D1 $ mandoc mandoc.1 mdoc.3 mdoc.7 | less
> .Pp
> To produce HTML manuals with
> @@ -366,11 +387,74 @@ as the style-sheet:
> .Pp
> To check over a large set of manuals:
> .Pp
> -.Dl $ mandoc \-Tlint \-fign-errors `find /usr/src -name \e*\e.[1-9]`
> +.Dl $ mandoc \-Tlint `find /usr/src -name \e*\e.[1-9]`
> .Pp
> To produce a series of PostScript manuals for A4 paper:
> .Pp
> .D1 $ mandoc \-Tps \-Opaper=a4 mdoc.7 man.7 \*(Gt manuals.ps
> +.Sh DIAGNOSTICS
> +Standard error messages reporting parsing errors are prefixed by
> +.Pp
> +.Sm off
> +.D1 Ar file : line : column : \ level :
> +.Sm on
> +.Pp
> +where the fields have the following meanings:
> +.Bl -tag -width "column"
> +.It Ar file
> +The name of the input file causing the message.
> +.It Ar line
> +The line number in that input file.
> +Line numbering starts at 1.
> +.It Ar column
> +The column number in that input file.
> +Column numbering starts at 1.
> +If the issue is caused by a word, the column number usually
> +points to the first character of the word.
> +.It Ar level
> +The message level, printed in capital letters.
> +.El
> +.Pp
> +Message levels have the following meanings:
> +.Bl -tag -width "warning"
> +.It Cm fatal
> +The parser is unable to parse a given input file at all.
> +No formatted output is produced from that input file.
> +.It Cm error
> +An input file contains syntax that cannot be safely interpreted,
> +either because it is invalid or because
> +.Nm
> +does not implement it yet.
> +By discarding part of the input or inserting missing tokens,
> +the parser is able to continue, and the error does not prevent
> +generation of formatted output, but typically, preparing that
> +output involves information loss, broken document structure
> +or unintended formatting.
> +.It Cm warning
> +An input file uses obsolete, discouraged or non-portable syntax.
> +All the same, the meaning of the input is unambiguous and a correct
> +rendering can be produced.
> +Documents causing warnings may render poorly when using other
> +formatting tools instead of
> +.Nm .
> +.El
> +.Pp
> +Messages of the
> +.Cm warning
> +and
> +.Cm error
> +levels are hidden unless their level, or a lower level, is requested using a
> +.Fl W
> +option or
> +.Fl T Ns Cm lint
> +output mode.
> +.Pp
> +The
> +.Nm
> +utility may also print messages related to invalid command line arguments
> +or operating system errors, for example when memory is exhausted or
> +input files cannot be read. Such messages do not carry the prefix
> +described above.
> .Sh COMPATIBILITY
> This section summarises
> .Nm
> Index: mandoc.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mandoc.c,v
> retrieving revision 1.17
> diff -u -p -r1.17 mandoc.c
> --- mandoc.c 18 Aug 2010 02:38:40 -0000 1.17
> +++ mandoc.c 19 Aug 2010 17:09:16 -0000
> @@ -195,7 +195,7 @@ mandoc_calloc(size_t num, size_t size)
> ptr = calloc(num, size);
> if (NULL == ptr) {
> perror(NULL);
> - exit(EXIT_FAILURE);
> + exit(MANDOCLEVEL_SYSERR);
> }
>
> return(ptr);
> @@ -210,7 +210,7 @@ mandoc_malloc(size_t size)
> ptr = malloc(size);
> if (NULL == ptr) {
> perror(NULL);
> - exit(EXIT_FAILURE);
> + exit(MANDOCLEVEL_SYSERR);
> }
>
> return(ptr);
> @@ -224,7 +224,7 @@ mandoc_realloc(void *ptr, size_t size)
> ptr = realloc(ptr, size);
> if (NULL == ptr) {
> perror(NULL);
> - exit(EXIT_FAILURE);
> + exit(MANDOCLEVEL_SYSERR);
> }
>
> return(ptr);
> @@ -239,7 +239,7 @@ mandoc_strdup(const char *ptr)
> p = strdup(ptr);
> if (NULL == p) {
> perror(NULL);
> - exit(EXIT_FAILURE);
> + exit(MANDOCLEVEL_SYSERR);
> }
>
> return(p);
> Index: mandoc.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mandoc.h,v
> retrieving revision 1.11
> diff -u -p -r1.11 mandoc.h
> --- mandoc.h 25 Jul 2010 18:05:54 -0000 1.11
> +++ mandoc.h 19 Aug 2010 17:09:16 -0000
> @@ -26,6 +26,17 @@
>
> __BEGIN_DECLS
>
> +enum mandoclevel {
> + MANDOCLEVEL_OK = 0,
> + MANDOCLEVEL_RESERVED,
> + MANDOCLEVEL_WARNING,
> + MANDOCLEVEL_ERROR,
> + MANDOCLEVEL_FATAL,
> + MANDOCLEVEL_BADARG,
> + MANDOCLEVEL_SYSERR,
> + MANDOCLEVEL_MAX
> +};
> +
> enum mandocerr {
> MANDOCERR_OK,
>
> @@ -105,7 +116,7 @@ enum mandocerr {
> MANDOCERR_NODOCBODY, /* no document body */
> MANDOCERR_NODOCPROLOG, /* no document prologue */
> MANDOCERR_UTSNAME, /* utsname system call failed */
> - MANDOCERR_MEM, /* memory exhausted */
> + MANDOCERR_MEM, /* static buffer exhausted */
>
> MANDOCERR_MAX
> };
> Index: mdoc.3
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mdoc.3,v
> retrieving revision 1.11
> diff -u -p -r1.11 mdoc.3
> --- mdoc.3 13 Jul 2010 01:09:13 -0000 1.11
> +++ mdoc.3 19 Aug 2010 17:09:16 -0000
> @@ -37,7 +37,6 @@
> .Fo mdoc_alloc
> .Fa "struct regset *regs"
> .Fa "void *data"
> -.Fa "int pflags"
> .Fa "mandocmsg msgs"
> .Fc
> .Ft int
> @@ -124,10 +123,6 @@ The
> .Fa data
> pointer is passed to
> .Fa msgs .
> -The
> -.Fa pflags
> -arguments are defined in
> -.Pa mdoc.h .
> Returns NULL on failure.
> If non-NULL, the pointer must be freed with
> .Fn mdoc_free .
> @@ -338,7 +333,7 @@ int line;
>
> bzero(®s, sizeof(struct regset));
> line = 1;
> -mdoc = mdoc_alloc(®s, NULL, 0, NULL);
> +mdoc = mdoc_alloc(®s, NULL, NULL);
> buf = NULL;
> alloc_len = 0;
>
> Index: mdoc.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mdoc.c,v
> retrieving revision 1.64
> diff -u -p -r1.64 mdoc.c
> --- mdoc.c 18 Aug 2010 01:17:44 -0000 1.64
> +++ mdoc.c 19 Aug 2010 17:09:16 -0000
> @@ -94,8 +94,6 @@ static int node_append(struct mdoc *,
> struct mdoc_node *);
> static int mdoc_ptext(struct mdoc *, int, char *, int);
> static int mdoc_pmacro(struct mdoc *, int, char *, int);
> -static int macrowarn(struct mdoc *, int,
> - const char *, int);
>
>
> const struct mdoc_node *
> @@ -187,8 +185,7 @@ mdoc_free(struct mdoc *mdoc)
> * Allocate volatile and non-volatile parse resources.
> */
> struct mdoc *
> -mdoc_alloc(struct regset *regs, void *data,
> - int pflags, mandocmsg msg)
> +mdoc_alloc(struct regset *regs, void *data, mandocmsg msg)
> {
> struct mdoc *p;
>
> @@ -196,7 +193,6 @@ mdoc_alloc(struct regset *regs, void *da
>
> p->msg = msg;
> p->data = data;
> - p->pflags = pflags;
> p->regs = regs;
>
> mdoc_hash_init();
> @@ -723,21 +719,6 @@ mdoc_ptext(struct mdoc *m, int line, cha
> }
>
>
> -static int
> -macrowarn(struct mdoc *m, int ln, const char *buf, int offs)
> -{
> - int rc;
> -
> - rc = mdoc_vmsg(m, MANDOCERR_MACRO, ln, offs,
> - "unknown macro: %s%s",
> - buf, strlen(buf) > 3 ? "..." : "");
> -
> - /* FIXME: logic should be in driver. */
> - /* FIXME: broken, will error out and not omit a message. */
> - return(MDOC_IGN_MACRO & m->pflags ? rc : 0);
> -}
> -
> -
> /*
> * Parse a macro line, that is, a line beginning with the control
> * character.
> @@ -781,15 +762,11 @@ mdoc_pmacro(struct mdoc *m, int ln, char
> mac[j++] = buf[i++];
> mac[j] = '\0';
>
> - if (j == 4 || j < 2) {
> - if ( ! macrowarn(m, ln, mac, sv))
> - goto err;
> - return(1);
> - }
> -
> - if (MDOC_MAX == (tok = mdoc_hash_find(mac))) {
> - if ( ! macrowarn(m, ln, mac, sv))
> - goto err;
> + tok = (j > 1 || j < 4) ? mdoc_hash_find(mac) : MDOC_MAX;
> + if (MDOC_MAX == tok) {
> + mdoc_vmsg(m, MANDOCERR_MACRO, ln, sv,
> + "unknown macro: %s%s",
> + buf, strlen(buf) > 3 ? "..." : "");
I'll say it again: I like this.
> return(1);
> }
>
> Index: mdoc.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mdoc.h,v
> retrieving revision 1.32
> diff -u -p -r1.32 mdoc.h
> --- mdoc.h 25 Jul 2010 18:05:54 -0000 1.32
> +++ mdoc.h 19 Aug 2010 17:09:16 -0000
> @@ -352,10 +352,6 @@ struct mdoc_node {
> } data;
> };
>
> -#define MDOC_IGN_SCOPE (1 << 0) /* Ignore scope violations. */
> -#define MDOC_IGN_ESCAPE (1 << 1) /* Ignore bad escape sequences. */
> -#define MDOC_IGN_MACRO (1 << 2) /* Ignore unknown macros. */
> -
> /* See mdoc.3 for documentation. */
>
> extern const char *const *mdoc_macronames;
> @@ -368,7 +364,7 @@ struct mdoc;
> /* See mdoc.3 for documentation. */
>
> void mdoc_free(struct mdoc *);
> -struct mdoc *mdoc_alloc(struct regset *, void *, int, mandocmsg);
> +struct mdoc *mdoc_alloc(struct regset *, void *, mandocmsg);
> void mdoc_reset(struct mdoc *);
> int mdoc_parseln(struct mdoc *, int, char *, int);
> const struct mdoc_node *mdoc_node(const struct mdoc *);
> Index: mdoc_html.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mdoc_html.c,v
> retrieving revision 1.28
> diff -u -p -r1.28 mdoc_html.c
> --- mdoc_html.c 7 Aug 2010 17:26:11 -0000 1.28
> +++ mdoc_html.c 19 Aug 2010 17:09:17 -0000
> @@ -28,6 +28,7 @@
> #include "html.h"
> #include "mdoc.h"
> #include "main.h"
> +#include "libmandoc.h"
>
> #define INDENT 5
> #define HALFINDENT 3
> @@ -1176,11 +1177,7 @@ mdoc_bl_pre(MDOC_ARGS)
> if (LIST_enum != n->data.Bl->type)
> return(1);
>
> - ord = malloc(sizeof(struct ord));
> - if (NULL == ord) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> + ord = mandoc_malloc(sizeof(struct ord));
Same again... mandoc_malloc is in libmandoc.h, not mandoc.h, and thus
only in the parsers (as it's implemented now).
> ord->cookie = n;
> ord->pos = 1;
> ord->next = h->ords.head;
> Index: mdoc_validate.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/mdoc_validate.c,v
> retrieving revision 1.67
> diff -u -p -r1.67 mdoc_validate.c
> --- mdoc_validate.c 31 Jul 2010 21:43:07 -0000 1.67
> +++ mdoc_validate.c 19 Aug 2010 17:09:17 -0000
> @@ -477,12 +477,8 @@ check_text(struct mdoc *m, int ln, int p
> if (c) {
> p += c - 1;
> pos += c - 1;
> - continue;
> - }
> -
> - c = mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE);
> - if ( ! (MDOC_IGN_ESCAPE & m->pflags) && ! c)
> - return(c);
> + } else
> + mdoc_pmsg(m, ln, pos, MANDOCERR_BADESCAPE);
> }
>
> return(1);
> Index: roff.3
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/roff.3,v
> retrieving revision 1.4
> diff -u -p -r1.4 roff.3
> --- roff.3 13 Jul 2010 01:09:13 -0000 1.4
> +++ roff.3 19 Aug 2010 17:09:18 -0000
> @@ -31,8 +31,8 @@
> .Ft "struct roff *"
> .Fo roff_alloc
> .Fa "struct regset *regs"
> -.Fa "mandocmsg msgs"
> .Fa "void *data"
> +.Fa "mandocmsg msgs"
> .Fc
> .Ft int
> .Fn roff_endparse "struct roff *roff"
> @@ -111,10 +111,6 @@ The
> .Fa data
> pointer is passed to
> .Fa msgs .
> -The
> -.Fa pflags
> -arguments are defined in
> -.Pa roff.h .
> Returns NULL on failure.
> If non-NULL, the pointer must be freed with
> .Fn roff_free .
> Index: roff.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/roff.c,v
> retrieving revision 1.10
> diff -u -p -r1.10 roff.c
> --- roff.c 31 Jul 2010 21:43:07 -0000 1.10
> +++ roff.c 19 Aug 2010 17:09:18 -0000
> @@ -160,7 +160,7 @@ static void roff_free1(struct roff *);
> static enum rofft roff_hash_find(const char *);
> static void roff_hash_init(void);
> static void roffnode_cleanscope(struct roff *);
> -static int roffnode_push(struct roff *,
> +static void roffnode_push(struct roff *,
> enum rofft, int, int);
> static void roffnode_pop(struct roff *);
> static enum rofft roff_parse(const char *, int *);
> @@ -250,16 +250,12 @@ roffnode_pop(struct roff *r)
> * Push a roff node onto the instruction stack. This must later be
> * removed with roffnode_pop().
> */
> -static int
> +static void
> roffnode_push(struct roff *r, enum rofft tok, int line, int col)
> {
> struct roffnode *p;
>
> - if (NULL == (p = calloc(1, sizeof(struct roffnode)))) {
> - (*r->msg)(MANDOCERR_MEM, r->data, line, col, NULL);
> - return(0);
> - }
> -
> + p = mandoc_calloc(1, sizeof(struct roffnode));
Counterexample: this is fine cause it's in libroff.
> p->tok = tok;
> p->parent = r->last;
> p->line = line;
> @@ -267,7 +263,6 @@ roffnode_push(struct roff *r, enum rofft
> p->rule = p->parent ? p->parent->rule : ROFFRULE_DENY;
>
> r->last = p;
> - return(1);
> }
>
>
> @@ -299,15 +294,11 @@ roff_free(struct roff *r)
>
>
> struct roff *
> -roff_alloc(struct regset *regs, const mandocmsg msg, void *data)
> +roff_alloc(struct regset *regs, void *data, const mandocmsg msg)
> {
> struct roff *r;
>
> - if (NULL == (r = calloc(1, sizeof(struct roff)))) {
> - (*msg)(MANDOCERR_MEM, data, 0, 0, NULL);
> - return(0);
> - }
> -
> + r = mandoc_calloc(1, sizeof(struct roff));
> r->regs = regs;
> r->msg = msg;
> r->data = data;
> @@ -634,8 +625,7 @@ roff_block(ROFF_ARGS)
> pos++;
> }
>
> - if ( ! roffnode_push(r, tok, ln, ppos))
> - return(ROFF_ERR);
> + roffnode_push(r, tok, ln, ppos);
>
> if ('\0' == (*bufp)[pos])
> return(ROFF_IGN);
> @@ -657,12 +647,7 @@ roff_block(ROFF_ARGS)
> if (1 == sz && '.' == (*bufp)[sv])
> return(ROFF_IGN);
>
> - r->last->end = malloc(sz + 1);
> -
> - if (NULL == r->last->end) {
> - (*r->msg)(MANDOCERR_MEM, r->data, ln, pos, NULL);
> - return(ROFF_ERR);
> - }
> + r->last->end = mandoc_malloc(sz + 1);
>
> memcpy(r->last->end, *bufp + sv, sz);
> r->last->end[(int)sz] = '\0';
> @@ -889,8 +874,7 @@ roff_cond(ROFF_ARGS)
> return(ROFF_ERR);
> }
>
> - if ( ! roffnode_push(r, tok, ln, ppos))
> - return(ROFF_ERR);
> + roffnode_push(r, tok, ln, ppos);
>
> r->last->rule = rule;
>
> Index: roff.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/roff.h,v
> retrieving revision 1.3
> diff -u -p -r1.3 roff.h
> --- roff.h 27 Jun 2010 21:54:42 -0000 1.3
> +++ roff.h 19 Aug 2010 17:09:18 -0000
> @@ -29,7 +29,7 @@ __BEGIN_DECLS
> struct roff;
>
> void roff_free(struct roff *);
> -struct roff *roff_alloc(struct regset *, mandocmsg, void *);
> +struct roff *roff_alloc(struct regset *, void *, mandocmsg);
> void roff_reset(struct roff *);
> enum rofferr roff_parseln(struct roff *, int,
> char **, size_t *, int, int *);
> Index: term.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/term.c,v
> retrieving revision 1.46
> diff -u -p -r1.46 term.c
> --- term.c 31 Jul 2010 21:43:07 -0000 1.46
> +++ term.c 19 Aug 2010 17:09:18 -0000
> @@ -29,6 +29,7 @@
> #include "out.h"
> #include "term.h"
> #include "main.h"
> +#include "libmandoc.h"
Nope: libmandoc/mandoc.h.
>
> static void spec(struct termp *, enum roffdeco,
> const char *, size_t);
> @@ -76,12 +77,7 @@ term_alloc(enum termenc enc)
> {
> struct termp *p;
>
> - p = calloc(1, sizeof(struct termp));
> - if (NULL == p) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> -
> + p = mandoc_calloc(1, sizeof(struct termp));
> p->enc = enc;
> return(p);
> }
> @@ -570,11 +566,7 @@ adjbuf(struct termp *p, size_t sz)
> while (sz >= p->maxcols)
> p->maxcols <<= 2;
>
> - p->buf = realloc(p->buf, p->maxcols);
> - if (NULL == p->buf) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> + p->buf = mandoc_realloc(p->buf, p->maxcols);
> }
>
>
> Index: term_ps.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/mandoc/term_ps.c,v
> retrieving revision 1.9
> diff -u -p -r1.9 term_ps.c
> --- term_ps.c 18 Aug 2010 01:30:16 -0000 1.9
> +++ term_ps.c 19 Aug 2010 17:09:18 -0000
> @@ -32,6 +32,7 @@
> #include "out.h"
> #include "main.h"
> #include "term.h"
> +#include "libmandoc.h"
>
> /* Convert PostScript point "x" to an AFM unit. */
> #define PNT2AFM(p, x) /* LINTED */ \
> @@ -365,14 +366,9 @@ ps_growbuf(struct termp *p, size_t sz)
>
> p->engine.ps.psmargsz += sz;
>
> - p->engine.ps.psmarg = realloc
> + p->engine.ps.psmarg = mandoc_realloc
> (p->engine.ps.psmarg,
> p->engine.ps.psmargsz);
Nope...
> -
> - if (NULL == p->engine.ps.psmarg) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> }
>
> static double ps_hspan(const struct termp *,
> @@ -603,13 +599,9 @@ pdf_obj(struct termp *p, size_t obj)
>
> if ((obj - 1) >= p->engine.ps.pdfobjsz) {
> p->engine.ps.pdfobjsz = obj + 128;
> - p->engine.ps.pdfobjs = realloc
> + p->engine.ps.pdfobjs = mandoc_realloc
> (p->engine.ps.pdfobjs,
> p->engine.ps.pdfobjsz * sizeof(size_t));
> - if (NULL == p->engine.ps.pdfobjs) {
> - perror(NULL);
> - exit(EXIT_FAILURE);
> - }
> }
>
> p->engine.ps.pdfobjs[(int)obj - 1] = p->engine.ps.pdfbytes;
> --
> To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-19 22:47 ` Kristaps Dzonsons
@ 2010-08-19 22:49 ` Kristaps Dzonsons
0 siblings, 0 replies; 13+ messages in thread
From: Kristaps Dzonsons @ 2010-08-19 22:49 UTC (permalink / raw)
To: discuss
...Note that I didn't look over the *.[1-9] changes, just the code...
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-19 13:19 ` Kristaps Dzonsons
@ 2010-08-20 12:18 ` Sascha Wildner
0 siblings, 0 replies; 13+ messages in thread
From: Sascha Wildner @ 2010-08-20 12:18 UTC (permalink / raw)
To: discuss; +Cc: Kristaps Dzonsons
On 8/19/2010 15:19, Kristaps Dzonsons wrote:
> Out of curiosity, what's your time-frame on this endeavour (if you have
> one at all)?
I really don't know. Time is usually tight and our team is very small.
Sascha
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: more error handling cleanup
2010-08-19 21:55 ` Ingo Schwarze
@ 2010-08-20 12:31 ` Sascha Wildner
0 siblings, 0 replies; 13+ messages in thread
From: Sascha Wildner @ 2010-08-20 12:31 UTC (permalink / raw)
To: discuss; +Cc: Ingo Schwarze
On 8/19/2010 23:55, Ingo Schwarze wrote:
> You probably don't even need -Wstop for that:
> I guess you are calling mandoc once for each individual manual,
> are you? Otherwise, how do you get separate output files for
> the manuals?
Yeah but my idea was not necessarily to format all pages to files that
would get installed. Only unformatted pages get installed and they get
formatted when man is run and the formatted page is older than the
unformatted one or if a formatted version doesn't exist.
My idea was more about running mandoc during build-/quickworld for
checking the pages only and whining if a regression was introduced.
>> My reasoning is that only if the build breaks, you'll get the
>> developer's attention in case they introduced issues in manual
>> pages. :)
>
> Really? Oops.
> Of course, you are welcome to use that tool if it works for you. :-)
>
> In OpenBSD, we are taking great care to *not* break the tree, ever.
> The problem is that several people are often running builds on
> slow architectures. If you break the build, these people typically
> lose days of their time, sometimes weeks. They won't be amused.
Well if the build breaks on some manpage that previously formatted
without problems, obviously someone didn't check their changes to it
with a build- or quickworld before committing. I'd like to have it work
the same way as the compiler does for the source. Someone commits a
manpage error -> build breaks.
> On the other hand, Jason is scrutinizing each manual commit,
> and i'm also running most manual commits through mandoc -Tlint.
> So, bad style or content in manuals will rarely go undetected,
> and when contacted, developers *will* listen to us.
Sure, I do the same in DragonFly at the moment and by having buildworld
break if some mandoc problem was introduced in a commit that wasn't
properly tested, I'd like to offload that work to those who committed
the problem. It just eats too much of my time to review manual page work
and also I'd like to counter a certain "Sascha will fix it anyways"
attitude. :-)
Sascha
--
To unsubscribe send an email to discuss+unsubscribe@mdocml.bsd.lv
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2010-08-20 12:31 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-18 16:12 more error handling cleanup Ingo Schwarze
2010-08-18 17:43 ` Kristaps Dzonsons
2010-08-18 18:42 ` Ingo Schwarze
2010-08-18 18:52 ` Kristaps Dzonsons
2010-08-19 17:57 ` Ingo Schwarze
2010-08-19 22:47 ` Kristaps Dzonsons
2010-08-19 22:49 ` Kristaps Dzonsons
2010-08-18 19:00 ` Joerg Sonnenberger
2010-08-19 9:38 ` Sascha Wildner
2010-08-19 13:19 ` Kristaps Dzonsons
2010-08-20 12:18 ` Sascha Wildner
2010-08-19 21:55 ` Ingo Schwarze
2010-08-20 12:31 ` Sascha Wildner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).