used a random block size if not given an argv[1].
[unix-history] / usr / src / usr.bin / error / main.c
CommitLineData
442fe3bf
DF
1/*
2 * Copyright (c) 1980 Regents of the University of California.
c9bf2796
KB
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that this notice is preserved and that due credit is given
7 * to the University of California at Berkeley. The name of the University
8 * may not be used to endorse or promote products derived from this
9 * software without specific prior written permission. This software
10 * is provided ``as is'' without express or implied warranty.
442fe3bf
DF
11 */
12
13#ifndef lint
14char copyright[] =
15"@(#) Copyright (c) 1980 Regents of the University of California.\n\
16 All rights reserved.\n";
c9bf2796
KB
17#endif /* not lint */
18
19#ifndef lint
20static char sccsid[] = "@(#)main.c 5.2 (Berkeley) %G%";
21#endif /* not lint */
442fe3bf 22
ad33082a
BJ
23#include <stdio.h>
24#include <ctype.h>
25#include <signal.h>
26#include "error.h"
27
28int nerrors = 0;
58195f21
RH
29Eptr er_head;
30Eptr *errors;
ad33082a
BJ
31
32int nfiles = 0;
58195f21 33Eptr **files; /* array of pointers into errors*/
ad33082a
BJ
34int language = INCC;
35
36char *currentfilename = "????";
37char *processname;
7799334e 38char im_on[] = "/dev/tty"; /* my tty name */
ad33082a
BJ
39
40boolean query = FALSE; /* query the operator if touch files */
41boolean notouch = FALSE; /* don't touch ANY files */
42boolean piflag = FALSE; /* this is not pi */
58195f21 43boolean terse = FALSE; /* Terse output */
ad33082a
BJ
44
45char *suffixlist = ".*"; /* initially, can touch any file */
46
47int errorsort();
48int onintr();
49/*
50 * error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile]
51 *
58195f21
RH
52 * -T: terse output
53 *
ad33082a
BJ
54 * -I: the following name, `ignorename' contains a list of
55 * function names that are not to be treated as hard errors.
56 * Default: ~/.errorsrc
57 *
58 * -n: don't touch ANY files!
59 *
60 * -q: The user is to be queried before touching each
61 * file; if not specified, all files with hard, non
62 * ignorable errors are touched (assuming they can be).
63 *
64 * -t: touch only files ending with the list of suffices, each
65 * suffix preceded by a dot.
66 * eg, -t .c.y.l
67 * will touch only files ending with .c, .y or .l
68 *
69 * -s: print a summary of the error's categories.
70 *
71 * -v: after touching all files, overlay vi(1), ex(1) or ed(1)
72 * on top of error, entered in the first file with
73 * an error in it, with the appropriate editor
74 * set up to use the "next" command to get the other
75 * files containing errors.
76 *
77 * -p: (obsolete: for older versions of pi without bug
78 * fix regarding printing out the name of the main file
79 * with an error in it)
80 * Take the following argument and use it as the name of
81 * the pascal source file, suffix .p
82 *
83 * -E: show the errors in sorted order; intended for
84 * debugging.
85 *
86 * -S: show the errors in unsorted order
87 * (as they come from the error file)
88 *
89 * infile: The error messages come from this file.
90 * Default: stdin
91 */
92main(argc, argv)
93 int argc;
94 char *argv[];
95{
96 char *cp;
97 char *ignorename = 0;
98 int ed_argc;
99 char **ed_argv; /*return from touchfiles*/
100 boolean show_errors = FALSE;
101 boolean Show_Errors = FALSE;
102 boolean pr_summary = FALSE;
103 boolean edit_files = FALSE;
104
105 processname = argv[0];
106
107 errorfile = stdin;
58195f21
RH
108 if (argc > 1) for(; (argc > 1) && (argv[1][0] == '-'); argc--, argv++){
109 for (cp = argv[1] + 1; *cp; cp++) switch(*cp){
110 default:
111 fprintf(stderr, "%s: -%c: Unknown flag\n",
112 processname, *cp);
113 break;
114
115 case 'n': notouch = TRUE; break;
116 case 'q': query = TRUE; break;
117 case 'S': Show_Errors = TRUE; break;
118 case 's': pr_summary = TRUE; break;
119 case 'v': edit_files = TRUE; break;
120 case 'T': terse = TRUE; break;
58195f21
RH
121 case 't':
122 *cp-- = 0; argv++; argc--;
123 if (argc > 1){
124 suffixlist = argv[1];
125 }
126 break;
127 case 'I': /*ignore file name*/
128 *cp-- = 0; argv++; argc--;
129 if (argc > 1)
130 ignorename = argv[1];
131 break;
132 }
133 }
ad33082a
BJ
134 if (notouch)
135 suffixlist = 0;
136 if (argc > 1){
137 if (argc > 3){
138 fprintf(stderr, "%s: Only takes 0 or 1 arguments\n",
139 processname);
140 exit(3);
141 }
142 if ( (errorfile = fopen(argv[1], "r")) == NULL){
143 fprintf(stderr, "%s: %s: No such file or directory for reading errors.\n",
144 processname, argv[1]);
145 exit(4);
146 }
147 }
ad33082a 148 if ( (queryfile = fopen(im_on, "r")) == NULL){
7799334e
RC
149 if (query){
150 fprintf(stderr,
151 "%s: Can't open \"%s\" to query the user.\n",
152 processname, im_on);
153 exit(9);
154 }
ad33082a
BJ
155 }
156 if (signal(SIGINT, onintr) == SIG_IGN)
157 signal(SIGINT, SIG_IGN);
158 if (signal(SIGTERM, onintr) == SIG_IGN)
159 signal(SIGTERM, SIG_IGN);
160 getignored(ignorename);
161 eaterrors(&nerrors, &errors);
162 if (Show_Errors)
163 printerrors(TRUE, nerrors, errors);
58195f21 164 qsort(errors, nerrors, sizeof(Eptr), errorsort);
ad33082a
BJ
165 if (show_errors)
166 printerrors(FALSE, nerrors, errors);
167 findfiles(nerrors, errors, &nfiles, &files);
168#define P(msg, arg) fprintf(stdout, msg, arg)
169 if (pr_summary){
170 if (nunknown)
171 P("%d Errors are unclassifiable.\n", nunknown);
172 if (nignore)
173 P("%d Errors are classifiable, but totally discarded.\n",nignore);
174 if (nsyncerrors)
175 P("%d Errors are synchronization errors.\n", nsyncerrors);
176 if (nignore)
177 P("%d Errors are discarded because they refer to sacrosinct files.\n", ndiscard);
178 if (nnulled)
179 P("%d Errors are nulled because they refer to specific functions.\n", nnulled);
180 if (nnonspec)
181 P("%d Errors are not specific to any file.\n", nnonspec);
182 if (nthisfile)
183 P("%d Errors are specific to a given file, but not to a line.\n", nthisfile);
184 if (ntrue)
185 P("%d Errors are true errors, and can be inserted into the files.\n", ntrue);
186 }
187 filenames(nfiles, files);
188 fflush(stdout);
58195f21
RH
189 if (touchfiles(nfiles, files, &ed_argc, &ed_argv) && edit_files)
190 forkvi(ed_argc, ed_argv);
191}
192
193forkvi(argc, argv)
194 int argc;
195 char **argv;
196{
197 if (query){
198 switch(inquire(terse
199 ? "Edit? "
200 : "Do you still want to edit the files you touched? ")){
201 case Q_NO:
202 case Q_no:
203 return;
204 default:
205 break;
ad33082a
BJ
206 }
207 }
58195f21
RH
208 /*
209 * ed_agument's first argument is
210 * a vi/ex compatabile search argument
211 * to find the first occurance of ###
212 */
213 try("vi", argc, argv);
214 try("ex", argc, argv);
215 try("ed", argc-1, argv+1);
216 fprintf(stdout, "Can't find any editors.\n");
ad33082a
BJ
217}
218
219try(name, argc, argv)
220 char *name;
221 int argc;
222 char **argv;
223{
224 argv[0] = name;
225 wordvprint(stdout, argc, argv);
226 fprintf(stdout, "\n");
227 fflush(stderr);
228 fflush(stdout);
229 sleep(2);
230 if (freopen(im_on, "r", stdin) == NULL)
231 return;
232 if (freopen(im_on, "w", stdout) == NULL)
233 return;
234 execvp(name, argv);
235}
236
237int errorsort(epp1, epp2)
58195f21 238 Eptr *epp1, *epp2;
ad33082a 239{
58195f21
RH
240 reg Eptr ep1, ep2;
241 int order;
ad33082a
BJ
242 /*
243 * Sort by:
244 * 1) synchronization, non specific, discarded errors first;
245 * 2) nulled and true errors last
246 * a) grouped by similar file names
247 * 1) grouped in ascending line number
248 */
249 ep1 = *epp1; ep2 = *epp2;
250 if (ep1 == 0 || ep2 == 0)
251 return(0);
252 if ( (NOTSORTABLE(ep1->error_e_class)) ^ (NOTSORTABLE(ep2->error_e_class))){
253 return(NOTSORTABLE(ep1->error_e_class) ? -1 : 1);
254 }
255 if (NOTSORTABLE(ep1->error_e_class)) /* then both are */
256 return(ep1->error_no - ep2->error_no);
257 order = strcmp(ep1->error_text[0], ep2->error_text[0]);
258 if (order == 0){
259 return(ep1->error_line - ep2->error_line);
260 }
261 return(order);
262}