Add argument -k to allow continuing after non-fatal errors

This commit is contained in:
Tim Bray 2021-03-16 20:40:26 -07:00
parent 86e0984f2b
commit 56c18c63ed
3 changed files with 71 additions and 10 deletions

View file

@ -60,6 +60,7 @@
<arg><option>-t</option></arg>
<arg><option>-N</option></arg>
<arg><option>-k</option></arg>
<arg><option>-v</option></arg>
<arg>file ...</arg>
@ -293,6 +294,20 @@ supports both.
</listitem>
</varlistentry>
<varlistentry>
<term><option>-k</option></term>
<listitem>
<para>
When processing multiple files, Expat by default halts after the
the first file with an error. This tells Expat to report the error
but to keep processing.
This can be useful, for example, when testing a filter that converts
many files to XML and you want to quickly find out which conversions
failed.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option></term>
<listitem>
@ -379,11 +394,17 @@ supports both.
<refsect1>
<title>OUTPUT</title>
<para>
If an input file is not well-formed,
<command>&dhpackage;</command> prints a single line describing
the problem to standard output. If a file is well formed,
<command>&dhpackage;</command> outputs nothing.
</para>
<command>&dhpackage;</command> outputs nothing for files which are problem-free.
If any input file is not well-formed, or if the output for any
input file cannot be opened, <command>&dhpackage;</command> prints a single
line describing the problem to standard output.
</para>
<para>
If the <option>-k</option> option is not provided, <command>&dhpackage;</command>
halts upon encountering a well-formedness or output-file error.
If <option>-k</option> is provided, <command>&dhpackage;</command> continues
processing the remaining input files, describing problems found with any of them.
</para>
</refsect1>
<refsect1>
@ -392,7 +413,7 @@ supports both.
<variablelist>
<varlistentry>
<term><option>0</option></term>
<listitem><para>The input files are well-formed.</para>
<listitem><para>The input files are well-formed and the output (if requested) was written successfully.</para>
</listitem>
</varlistentry>
<varlistentry>

View file

@ -322,6 +322,13 @@ freeNotations(XmlwfUserData *data) {
data->notationListHead = NULL;
}
static void
cleanupUserData(XmlwfUserData *userData) {
free((void *)userData->currentDoctypeName);
userData->currentDoctypeName = NULL;
freeNotations(userData);
}
static int
xcscmp(const XML_Char *xs, const XML_Char *xt) {
while (*xs != 0 && *xt != 0) {
@ -848,9 +855,11 @@ usage(const XML_Char *prog, int rc) {
stderr,
/* Generated with:
* $ xmlwf/xmlwf_helpgen.sh
* To update, change xmlwf/xmlwf_helpgen.py, then paste the output of
* xmlwf/xmlwf_helpgen.sh in here.
*/
/* clang-format off */
T("usage: %s [-s] [-n] [-p] [-x] [-e ENCODING] [-w] [-r] [-d DIRECTORY]\n")
T("usage: %s [-s] [-n] [-p] [-x] [-e ENCODING] [-w] [-r] [-k] [-d DIRECTORY]\n")
T(" [-c | -m | -t] [-N]\n")
T(" [FILE [FILE ...]]\n")
T("\n")
@ -867,6 +876,7 @@ usage(const XML_Char *prog, int rc) {
T(" -e ENCODING override any in-document [e]ncoding declaration\n")
T(" -w enable support for [W]indows code pages\n")
T(" -r disable memory-mapping and use normal file [r]ead IO calls instead\n")
T(" -k when processing multiple files, [k]eep processing after first file with error\n")
T("\n")
T("output control arguments:\n")
T(" -d DIRECTORY output [d]estination directory\n")
@ -879,6 +889,12 @@ usage(const XML_Char *prog, int rc) {
T(" -h show this [h]elp message and exit\n")
T(" -v show program's [v]ersion number and exit\n")
T("\n")
T("exit status:\n")
T(" 0 the input files are well-formed and the output (if requested) was written successfully\n")
T(" 1 could not allocate data structures, signals a serious problem with execution environment\n")
T(" 2 command-line argument error, or one or more input files were not well-formed\n")
T(" 3 could not create an output file\n")
T("\n")
T("xmlwf of libexpat is software libre, licensed under the MIT license.\n")
T("Please report bugs at https://github.com/libexpat/libexpat/issues. Thank you!\n")
, /* clang-format on */
@ -902,6 +918,8 @@ tmain(int argc, XML_Char **argv) {
int useNamespaces = 0;
int requireStandalone = 0;
int requiresNotations = 0;
int continueOnError = 0;
int exitCode = 0;
enum XML_ParamEntityParsing paramEntityParsing
= XML_PARAM_ENTITY_PARSING_NEVER;
int useStdin = 0;
@ -990,6 +1008,10 @@ tmain(int argc, XML_Char **argv) {
case T('v'):
showVersion(argv[0]);
return 0;
case T('k'):
continueOnError = 1;
j++;
break;
case T('\0'):
if (j > 1) {
i++;
@ -1061,7 +1083,14 @@ tmain(int argc, XML_Char **argv) {
userData.fp = tfopen(outName, T("wb"));
if (! userData.fp) {
tperror(outName);
exit(3);
exitCode = 3;
if (continueOnError) {
free(outName);
cleanupUserData(&userData);
continue;
} else {
break;
}
}
setvbuf(userData.fp, NULL, _IOFBF, 16384);
#ifdef XML_UNICODE
@ -1123,8 +1152,12 @@ tmain(int argc, XML_Char **argv) {
}
XML_ParserFree(parser);
if (! result) {
exit(2);
exitCode = 2;
cleanupUserData(&userData);
if (! continueOnError) {
break;
}
}
}
return 0;
return exitCode;
}

View file

@ -31,6 +31,12 @@
import argparse
epilog = """
exit status:
0 the input files are well-formed and the output (if requested) was written successfully
1 could not allocate data structures, signals a serious problem with execution environment
2 command-line argument error, or one or more input files were not well-formed
3 could not create an output file
xmlwf of libexpat is software libre, licensed under the MIT license.
Please report bugs at https://github.com/libexpat/libexpat/issues. Thank you!
"""
@ -48,6 +54,7 @@ input_related.add_argument('-x', action='store_true', help='enable processing of
input_related.add_argument('-e', action='store', metavar='ENCODING', help='override any in-document [e]ncoding declaration')
input_related.add_argument('-w', action='store_true', help='enable support for [W]indows code pages')
input_related.add_argument('-r', action='store_true', help='disable memory-mapping and use normal file [r]ead IO calls instead')
input_related.add_argument('-k', action='store_true', help='when processing multiple files, [k]eep processing after first file with error')
output_related = parser.add_argument_group('output control arguments')
output_related.add_argument('-d', action='store', metavar='DIRECTORY', help='output [d]estination directory')