- use getopt

- use err
- add -p <filelevel> to chop levels like patch
- document all the options
This commit is contained in:
christos 2011-05-19 22:55:53 +00:00
parent aabb34a38b
commit ec9611ac0f
4 changed files with 125 additions and 86 deletions

View File

@ -1,4 +1,4 @@
.\" $NetBSD: error.1,v 1.14 2010/04/05 21:18:20 joerg Exp $
.\" $NetBSD: error.1,v 1.15 2011/05/19 22:55:53 christos Exp $
.\"
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
@ -29,7 +29,7 @@
.\"
.\" @(#)error.1 8.1 (Berkeley) 6/6/93
.\"
.Dd June 6, 1993
.Dd May 19, 2011
.Dt ERROR 1
.Os
.Sh NAME
@ -37,12 +37,15 @@
.Nd analyze and disperse compiler error messages
.Sh SYNOPSIS
.Nm
.Op Fl n
.Op Fl s
.Op Fl q
.Op Fl v
.Op Fl t Ar suffixlist
.Op Fl I Ar ignorefile
.Op Fl n
.Pp Fl p Ar filelevel
.Op Fl q
.Op Fl S
.Op Fl s
.Op Fl T
.Op Fl t Ar suffixlist
.Op Fl v
.Op name
.Sh DESCRIPTION
.Nm
@ -83,6 +86,8 @@ can't be found, try
or
.Xr \&ed 1
from standard places.
.It Fl T
Terse output.
.It Fl t
Take the following argument as a suffix list.
Files whose suffixes do not appear in the suffix list are not touched.
@ -94,6 +99,12 @@ Thus the suffix list:
allows
.Nm
to touch files ending with ``.c'', ``.y'', ``.foo*'' and ``.h''.
.It Fl p Ar filelevel
Interpret filenumber as a level of path component names to skip,
similar to
.Xr patch 1 .
.It Fl S
Show the errors in unsorted order (as they come from the error file).
.It Fl s
Print out
.Em statistics

View File

@ -1,4 +1,4 @@
/* $NetBSD: error.h,v 1.15 2009/08/13 06:59:37 dholland Exp $ */
/* $NetBSD: error.h,v 1.16 2011/05/19 22:55:53 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -88,6 +88,8 @@ typedef int Errorclass;
extern const char *class_table[];
extern int class_count[];
extern size_t filelevel;
#define nunknown class_count[C_UNKNOWN]
#define nignore class_count[C_IGNORE]
#define nsyncerrors class_count[C_SYNC]

View File

@ -1,4 +1,4 @@
/* $NetBSD: main.c,v 1.17 2009/08/13 06:59:37 dholland Exp $ */
/* $NetBSD: main.c,v 1.18 2011/05/19 22:55:53 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
#if 0
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: main.c,v 1.17 2009/08/13 06:59:37 dholland Exp $");
__RCSID("$NetBSD: main.c,v 1.18 2011/05/19 22:55:53 christos Exp $");
#endif /* not lint */
#include <signal.h>
@ -48,6 +48,7 @@ __RCSID("$NetBSD: main.c,v 1.17 2009/08/13 06:59:37 dholland Exp $");
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include "error.h"
#include "pathnames.h"
@ -57,6 +58,7 @@ FILE *queryfile; /* where the query responses from the user come from*/
int nignored;
char **names_ignored;
size_t filelevel = 0;
int nerrors = 0;
Eptr er_head;
static Eptr *errors;
@ -81,11 +83,10 @@ const char *suffixlist = ".*"; /* initially, can touch any file */
static int errorsort(const void *, const void *);
static void forkvi(int, char **);
static void try(const char *, int, char **);
static void usage(void) __attribute__((__noreturn__));
/*
* error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile]
*
* -T: terse output
* error [-nqSsTv] [-I <ignorename>] [-t <suffixlist>] [-p <level>] <infile>
*
* -I: the following name, `ignorename' contains a list of
* function names that are not to be treated as hard errors.
@ -93,42 +94,38 @@ static void try(const char *, int, char **);
*
* -n: don't touch ANY files!
*
* -p: take the next argument as the number of levels to skip
* from the filename, like perl.
*
* -q: The user is to be queried before touching each
* file; if not specified, all files with hard, non
* ignorable errors are touched (assuming they can be).
*
* -S: show the errors in unsorted order
* (as they come from the error file)
*
* -s: print a summary of the error's categories.
*
* -T: terse output
*
* -t: touch only files ending with the list of suffixes, each
* suffix preceded by a dot.
* eg, -t .c.y.l
* will touch only files ending with .c, .y or .l
*
* -s: print a summary of the error's categories.
*
* -v: after touching all files, overlay vi(1), ex(1) or ed(1)
* on top of error, entered in the first file with
* an error in it, with the appropriate editor
* set up to use the "next" command to get the other
* files containing errors.
*
* -p: (obsolete: for older versions of pi without bug
* fix regarding printing out the name of the main file
* with an error in it)
* Take the following argument and use it as the name of
* the pascal source file, suffix .p
*
* -E: show the errors in sorted order; intended for
* debugging.
*
* -S: show the errors in unsorted order
* (as they come from the error file)
*
* infile: The error messages come from this file.
* Default: stdin
*/
int
main(int argc, char **argv)
{
char *cp;
int c;
char *ignorename = 0;
int ed_argc;
char **ed_argv; /* return from touchfiles */
@ -137,60 +134,55 @@ main(int argc, char **argv)
boolean pr_summary = false;
boolean edit_files = false;
processname = argv[0];
setprogname(argv[0]);
errorfile = stdin;
if (argc > 1)
for (; argc > 1 && argv[1][0] == '-'; argc--, argv++) {
for (cp = argv[1] + 1; *cp; cp++)
switch (*cp) {
default:
fprintf(stderr, "%s: -%c: Unknown flag\n",
processname, *cp);
break;
case 'n': notouch = true; break;
case 'q': query = true; break;
case 'S': Show_Errors = true; break;
case 's': pr_summary = true; break;
case 'v': edit_files = true; break;
case 'T': terse = true; break;
case 't':
*cp-- = 0; argv++; argc--;
if (argc > 1) {
suffixlist = argv[1];
}
break;
case 'I': /*ignore file name*/
*cp-- = 0;
argv++;
argc--;
if (argc > 1)
ignorename = argv[1];
break;
}
while ((c = getopt(argc, argv, "I:np:qSsTt:v")) != -1)
switch (c) {
case 'I': /*ignore file name*/
ignorename = optarg;
break;
case 'n':
notouch = true;
break;
case 'p':
filelevel = (size_t)strtol(optarg, NULL, 0);
break;
case 'q':
query = true;
break;
case 'S':
Show_Errors = true;
break;
case 's':
pr_summary = true;
break;
case 'T':
terse = true;
break;
case 't':
suffixlist = optarg;
break;
case 'v':
edit_files = true;
break;
default:
usage();
}
argv += optind;
argc -= optind;
if (notouch)
suffixlist = 0;
if (argc > 1) {
if (argc > 3) {
fprintf(stderr, "%s: Only takes 0 or 1 arguments\n",
processname);
exit(3);
}
if ((errorfile = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "%s: %s: No such file or directory for reading errors.\n",
processname, argv[1]);
exit(4);
}
if (argc > 3)
usage();
if ((errorfile = fopen(argv[1], "r")) == NULL)
err(1, "Cannot open `%s' to read errors", argv[1]);
}
if ((queryfile = fopen(im_on, "r")) == NULL) {
if (query) {
fprintf(stderr,
"%s: Can't open \"%s\" to query the user.\n",
processname, im_on);
exit(9);
}
if (query)
err(1, "Cannot open `%s' to query the user", im_on);
}
if (signal(SIGINT, onintr) == SIG_IGN)
signal(SIGINT, SIG_IGN);
@ -301,3 +293,11 @@ errorsort(const void *x1, const void *x2)
}
return (order);
}
static void
usage(void)
{
fprintf(stderr, "Usage: %s [-nqSsTv] [-I <ignorename>] "
"[-t <suffixlist>] [-p <level>] <infile>\n", getprogname());
exit(1);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: touch.c,v 1.22 2009/08/13 06:59:37 dholland Exp $ */
/* $NetBSD: touch.c,v 1.23 2011/05/19 22:55:53 christos Exp $ */
/*
* Copyright (c) 1980, 1993
@ -34,7 +34,7 @@
#if 0
static char sccsid[] = "@(#)touch.c 8.1 (Berkeley) 6/6/93";
#endif
__RCSID("$NetBSD: touch.c,v 1.22 2009/08/13 06:59:37 dholland Exp $");
__RCSID("$NetBSD: touch.c,v 1.23 2011/05/19 22:55:53 christos Exp $");
#endif /* not lint */
#include <sys/param.h>
@ -87,12 +87,30 @@ static int mustwrite(const char *, unsigned, FILE *);
static void errorprint(FILE *, Eptr, boolean);
static int probethisfile(const char *);
static const char *
makename(const char *name, size_t level)
{
const char *p;
if (level-- == 0)
return name;
if (*name == '/') {
name++;
if (level-- == 0)
return name;
}
while (level-- != 0 && (p = strchr(name, '/')) != NULL)
name = p + 1;
return name;
}
void
findfiles(int my_nerrors, Eptr *my_errors, int *r_nfiles, Eptr ***r_files)
{
int my_nfiles;
Eptr **my_files;
const char *name;
int ei;
int fi;
@ -122,10 +140,11 @@ findfiles(int my_nerrors, Eptr *my_errors, int *r_nfiles, Eptr ***r_files)
name = "\1";
fi = 1;
ECITERATE(ei, errorp, ei, my_errors, my_nerrors) {
const char *fname = makename(errorp->error_text[0], filelevel);
if (errorp->error_e_class == C_NULLED
|| errorp->error_e_class == C_TRUE) {
if (strcmp(errorp->error_text[0], name) != 0) {
name = errorp->error_text[0];
if (strcmp(fname, name) != 0) {
name = fname;
touchedfiles[fi] = false;
my_files[fi] = &my_errors[ei];
fi++;
@ -149,9 +168,11 @@ countfiles(Eptr *errors)
name = "\1";
ECITERATE(ei, errorp, 0, errors, nerrors) {
if (SORTABLE(errorp->error_e_class)) {
if (strcmp(errorp->error_text[0],name) != 0) {
const char *fname = makename(errorp->error_text[0],
filelevel);
if (strcmp(fname, name) != 0) {
my_nfiles++;
name = errorp->error_text[0];
name = name;
}
}
}
@ -195,7 +216,9 @@ filenames(int my_nfiles, Eptr **my_files)
if (!terse) {
FILEITERATE(fi, 1, my_nfiles) {
fprintf(stdout, "%s\"%s\" (%d)",
sep, (*my_files[fi])->error_text[0],
sep, makename(
(*my_files[fi])->error_text[0],
filelevel),
(int)(my_files[fi+1] - my_files[fi]));
sep = ", ";
}
@ -241,6 +264,7 @@ nopertain(Eptr **my_files)
return (someerrors);
}
bool
touchfiles(int my_nfiles, Eptr **my_files, int *r_edargc, char ***r_edargv)
{
@ -254,8 +278,9 @@ touchfiles(int my_nfiles, Eptr **my_files, int *r_edargc, char ***r_edargv)
int spread;
FILEITERATE(fi, 1, my_nfiles) {
name = (*my_files[fi])->error_text[0];
name = makename((*my_files[fi])->error_text[0], filelevel);
spread = my_files[fi+1] - my_files[fi];
fprintf(stdout, terse
? "\"%s\" has %d error%s, "
: "\nFile \"%s\" has %d error%s.\n"
@ -501,7 +526,7 @@ static void
execvarg(int n_pissed_on, int *r_argc, char ***r_argv)
{
Eptr p;
const char *sep;
const char *sep, *name;
int fi;
sep = NULL;
@ -517,11 +542,12 @@ execvarg(int n_pissed_on, int *r_argc, char ***r_argv)
if (!touchedfiles[fi])
continue;
p = *(files[fi]);
name = makename(p->error_text[0], filelevel);
if (!terse) {
fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]);
fprintf(stdout,"%s\"%s\"", sep, name);
sep = ", ";
}
(*r_argv)[n_pissed_on++] = p->error_text[0];
(*r_argv)[n_pissed_on++] = __UNCONST(name);
}
if (!terse)
fprintf(stdout, "\n");