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