1 /* $NetBSD: main.c,v 1.16 2009/08/13 05:53:58 dholland Exp $ */
4 * Copyright (c) 1980, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1980, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
42 __RCSID("$NetBSD: main.c,v 1.16 2009/08/13 05:53:58 dholland Exp $");
52 #include "pathnames.h"
54 FILE *errorfile
; /* where error file comes from */
55 FILE *queryfile
; /* where the query responses from the user come from*/
65 Eptr
**files
; /* array of pointers into errors*/
66 boolean
*touchedfiles
; /* which files we touched */
69 static char default_currentfilename
[] = "????";
70 char *currentfilename
= default_currentfilename
;
73 boolean query
= false; /* query the operator if touch files */
74 boolean terse
= false; /* Terse output */
76 static char im_on
[] = _PATH_TTY
; /* my tty name */
77 static boolean notouch
= false; /* don't touch ANY files */
79 const char *suffixlist
= ".*"; /* initially, can touch any file */
81 static int errorsort(const void *, const void *);
82 static void forkvi(int, char **);
83 static void try(const char *, int, char **);
86 * error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile]
90 * -I: the following name, `ignorename' contains a list of
91 * function names that are not to be treated as hard errors.
92 * Default: ~/.errorsrc
94 * -n: don't touch ANY files!
96 * -q: The user is to be queried before touching each
97 * file; if not specified, all files with hard, non
98 * ignorable errors are touched (assuming they can be).
100 * -t: touch only files ending with the list of suffixes, each
101 * suffix preceded by a dot.
103 * will touch only files ending with .c, .y or .l
105 * -s: print a summary of the error's categories.
107 * -v: after touching all files, overlay vi(1), ex(1) or ed(1)
108 * on top of error, entered in the first file with
109 * an error in it, with the appropriate editor
110 * set up to use the "next" command to get the other
111 * files containing errors.
113 * -p: (obsolete: for older versions of pi without bug
114 * fix regarding printing out the name of the main file
115 * with an error in it)
116 * Take the following argument and use it as the name of
117 * the pascal source file, suffix .p
119 * -E: show the errors in sorted order; intended for
122 * -S: show the errors in unsorted order
123 * (as they come from the error file)
125 * infile: The error messages come from this file.
129 main(int argc
, char **argv
)
132 char *ignorename
= 0;
134 char **ed_argv
; /* return from touchfiles */
135 boolean show_errors
= false;
136 boolean Show_Errors
= false;
137 boolean pr_summary
= false;
138 boolean edit_files
= false;
140 processname
= argv
[0];
144 for (; argc
> 1 && argv
[1][0] == '-'; argc
--, argv
++) {
145 for (cp
= argv
[1] + 1; *cp
; cp
++)
148 fprintf(stderr
, "%s: -%c: Unknown flag\n",
152 case 'n': notouch
= true; break;
153 case 'q': query
= true; break;
154 case 'S': Show_Errors
= true; break;
155 case 's': pr_summary
= true; break;
156 case 'v': edit_files
= true; break;
157 case 'T': terse
= true; break;
159 *cp
-- = 0; argv
++; argc
--;
161 suffixlist
= argv
[1];
164 case 'I': /*ignore file name*/
169 ignorename
= argv
[1];
177 fprintf(stderr
, "%s: Only takes 0 or 1 arguments\n",
181 if ((errorfile
= fopen(argv
[1], "r")) == NULL
) {
182 fprintf(stderr
, "%s: %s: No such file or directory for reading errors.\n",
183 processname
, argv
[1]);
187 if ((queryfile
= fopen(im_on
, "r")) == NULL
) {
190 "%s: Can't open \"%s\" to query the user.\n",
195 if (signal(SIGINT
, onintr
) == SIG_IGN
)
196 signal(SIGINT
, SIG_IGN
);
197 if (signal(SIGTERM
, onintr
) == SIG_IGN
)
198 signal(SIGTERM
, SIG_IGN
);
199 getignored(ignorename
);
200 eaterrors(&nerrors
, &errors
);
202 printerrors(true, nerrors
, errors
);
203 qsort(errors
, nerrors
, sizeof(Eptr
), errorsort
);
205 printerrors(false, nerrors
, errors
);
206 findfiles(nerrors
, errors
, &nfiles
, &files
);
207 #define P(msg, arg) fprintf(stdout, msg, arg)
210 P("%d Errors are unclassifiable.\n", nunknown
);
212 P("%d Errors are classifiable, but totally discarded.\n",nignore
);
214 P("%d Errors are synchronization errors.\n", nsyncerrors
);
216 P("%d Errors are discarded because they refer to sacrosinct files.\n", ndiscard
);
218 P("%d Errors are nulled because they refer to specific functions.\n", nnulled
);
220 P("%d Errors are not specific to any file.\n", nnonspec
);
222 P("%d Errors are specific to a given file, but not to a line.\n", nthisfile
);
224 P("%d Errors are true errors, and can be inserted into the files.\n", ntrue
);
226 filenames(nfiles
, files
);
228 if (touchfiles(nfiles
, files
, &ed_argc
, &ed_argv
) && edit_files
)
229 forkvi(ed_argc
, ed_argv
);
234 forkvi(int argc
, char **argv
)
237 switch (inquire(terse
239 : "Do you still want to edit the files you touched? ")) {
249 * ed_agument's first argument is
250 * a vi/ex compatible search argument
251 * to find the first occurrence of ###
253 try("vi", argc
, argv
);
254 try("ex", argc
, argv
);
255 try("ed", argc
-1, argv
+1);
256 fprintf(stdout
, "Can't find any editors.\n");
260 try(const char *name
, int argc
, char **argv
)
262 argv
[0] = __UNCONST(name
);
263 wordvprint(stdout
, argc
, argv
);
264 fprintf(stdout
, "\n");
268 if (freopen(im_on
, "r", stdin
) == NULL
)
270 if (freopen(im_on
, "w", stdout
) == NULL
)
276 errorsort(const void *x1
, const void *x2
)
278 const Eptr
*epp1
= x1
;
279 const Eptr
*epp2
= x2
;
285 * 1) synchronization, non specific, discarded errors first;
286 * 2) nulled and true errors last
287 * a) grouped by similar file names
288 * 1) grouped in ascending line number
290 ep1
= *epp1
; ep2
= *epp2
;
291 if (ep1
== 0 || ep2
== 0)
293 if ((NOTSORTABLE(ep1
->error_e_class
)) ^ (NOTSORTABLE(ep2
->error_e_class
))) {
294 return (NOTSORTABLE(ep1
->error_e_class
) ? -1 : 1);
296 if (NOTSORTABLE(ep1
->error_e_class
)) /* then both are */
297 return (ep1
->error_no
- ep2
->error_no
);
298 order
= strcmp(ep1
->error_text
[0], ep2
->error_text
[0]);
300 return (ep1
->error_line
- ep2
->error_line
);