1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 char copyright[] = 36 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 /*static char sccsid[] = "from: @(#)main.c 5.6 (Berkeley) 2/26/91";*/ 42 static char rcsid[] = "$Id: main.c,v 1.2 1993/08/01 18:16:43 mycroft Exp $"; 43 #endif /* not lint */ 44 45 #include <signal.h> 46 #include <unistd.h> 47 #include <stdio.h> 48 #include <ctype.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include "error.h" 52 #include "pathnames.h" 53 54 int nerrors = 0; 55 Eptr er_head; 56 Eptr *errors; 57 58 int nfiles = 0; 59 Eptr **files; /* array of pointers into errors*/ 60 int language = INCC; 61 62 char *currentfilename = "????"; 63 char *processname; 64 char im_on[] = _PATH_TTY; /* my tty name */ 65 66 boolean query = FALSE; /* query the operator if touch files */ 67 boolean notouch = FALSE; /* don't touch ANY files */ 68 boolean piflag = FALSE; /* this is not pi */ 69 boolean terse = FALSE; /* Terse output */ 70 71 char *suffixlist = ".*"; /* initially, can touch any file */ 72 73 int errorsort(); 74 void onintr(); 75 /* 76 * error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile] 77 * 78 * -T: terse output 79 * 80 * -I: the following name, `ignorename' contains a list of 81 * function names that are not to be treated as hard errors. 82 * Default: ~/.errorsrc 83 * 84 * -n: don't touch ANY files! 85 * 86 * -q: The user is to be queried before touching each 87 * file; if not specified, all files with hard, non 88 * ignorable errors are touched (assuming they can be). 89 * 90 * -t: touch only files ending with the list of suffices, each 91 * suffix preceded by a dot. 92 * eg, -t .c.y.l 93 * will touch only files ending with .c, .y or .l 94 * 95 * -s: print a summary of the error's categories. 96 * 97 * -v: after touching all files, overlay vi(1), ex(1) or ed(1) 98 * on top of error, entered in the first file with 99 * an error in it, with the appropriate editor 100 * set up to use the "next" command to get the other 101 * files containing errors. 102 * 103 * -p: (obsolete: for older versions of pi without bug 104 * fix regarding printing out the name of the main file 105 * with an error in it) 106 * Take the following argument and use it as the name of 107 * the pascal source file, suffix .p 108 * 109 * -E: show the errors in sorted order; intended for 110 * debugging. 111 * 112 * -S: show the errors in unsorted order 113 * (as they come from the error file) 114 * 115 * infile: The error messages come from this file. 116 * Default: stdin 117 */ 118 main(argc, argv) 119 int argc; 120 char *argv[]; 121 { 122 char *cp; 123 char *ignorename = 0; 124 int ed_argc; 125 char **ed_argv; /*return from touchfiles*/ 126 boolean show_errors = FALSE; 127 boolean Show_Errors = FALSE; 128 boolean pr_summary = FALSE; 129 boolean edit_files = FALSE; 130 131 processname = argv[0]; 132 133 errorfile = stdin; 134 if (argc > 1) for(; (argc > 1) && (argv[1][0] == '-'); argc--, argv++){ 135 for (cp = argv[1] + 1; *cp; cp++) switch(*cp){ 136 default: 137 fprintf(stderr, "%s: -%c: Unknown flag\n", 138 processname, *cp); 139 break; 140 141 case 'n': notouch = TRUE; break; 142 case 'q': query = TRUE; break; 143 case 'S': Show_Errors = TRUE; break; 144 case 's': pr_summary = TRUE; break; 145 case 'v': edit_files = TRUE; break; 146 case 'T': terse = TRUE; break; 147 case 't': 148 *cp-- = 0; argv++; argc--; 149 if (argc > 1){ 150 suffixlist = argv[1]; 151 } 152 break; 153 case 'I': /*ignore file name*/ 154 *cp-- = 0; argv++; argc--; 155 if (argc > 1) 156 ignorename = argv[1]; 157 break; 158 } 159 } 160 if (notouch) 161 suffixlist = 0; 162 if (argc > 1){ 163 if (argc > 3){ 164 fprintf(stderr, "%s: Only takes 0 or 1 arguments\n", 165 processname); 166 exit(3); 167 } 168 if ( (errorfile = fopen(argv[1], "r")) == NULL){ 169 fprintf(stderr, "%s: %s: No such file or directory for reading errors.\n", 170 processname, argv[1]); 171 exit(4); 172 } 173 } 174 if ( (queryfile = fopen(im_on, "r")) == NULL){ 175 if (query){ 176 fprintf(stderr, 177 "%s: Can't open \"%s\" to query the user.\n", 178 processname, im_on); 179 exit(9); 180 } 181 } 182 if (signal(SIGINT, onintr) == SIG_IGN) 183 signal(SIGINT, SIG_IGN); 184 if (signal(SIGTERM, onintr) == SIG_IGN) 185 signal(SIGTERM, SIG_IGN); 186 getignored(ignorename); 187 eaterrors(&nerrors, &errors); 188 if (Show_Errors) 189 printerrors(TRUE, nerrors, errors); 190 qsort(errors, nerrors, sizeof(Eptr), errorsort); 191 if (show_errors) 192 printerrors(FALSE, nerrors, errors); 193 findfiles(nerrors, errors, &nfiles, &files); 194 #define P(msg, arg) fprintf(stdout, msg, arg) 195 if (pr_summary){ 196 if (nunknown) 197 P("%d Errors are unclassifiable.\n", nunknown); 198 if (nignore) 199 P("%d Errors are classifiable, but totally discarded.\n",nignore); 200 if (nsyncerrors) 201 P("%d Errors are synchronization errors.\n", nsyncerrors); 202 if (nignore) 203 P("%d Errors are discarded because they refer to sacrosinct files.\n", ndiscard); 204 if (nnulled) 205 P("%d Errors are nulled because they refer to specific functions.\n", nnulled); 206 if (nnonspec) 207 P("%d Errors are not specific to any file.\n", nnonspec); 208 if (nthisfile) 209 P("%d Errors are specific to a given file, but not to a line.\n", nthisfile); 210 if (ntrue) 211 P("%d Errors are true errors, and can be inserted into the files.\n", ntrue); 212 } 213 filenames(nfiles, files); 214 fflush(stdout); 215 if (touchfiles(nfiles, files, &ed_argc, &ed_argv) && edit_files) 216 forkvi(ed_argc, ed_argv); 217 } 218 219 forkvi(argc, argv) 220 int argc; 221 char **argv; 222 { 223 if (query){ 224 switch(inquire(terse 225 ? "Edit? " 226 : "Do you still want to edit the files you touched? ")){ 227 case Q_NO: 228 case Q_no: 229 return; 230 default: 231 break; 232 } 233 } 234 /* 235 * ed_agument's first argument is 236 * a vi/ex compatabile search argument 237 * to find the first occurance of ### 238 */ 239 try("vi", argc, argv); 240 try("ex", argc, argv); 241 try("ed", argc-1, argv+1); 242 fprintf(stdout, "Can't find any editors.\n"); 243 } 244 245 try(name, argc, argv) 246 char *name; 247 int argc; 248 char **argv; 249 { 250 argv[0] = name; 251 wordvprint(stdout, argc, argv); 252 fprintf(stdout, "\n"); 253 fflush(stderr); 254 fflush(stdout); 255 sleep(2); 256 if (freopen(im_on, "r", stdin) == NULL) 257 return; 258 if (freopen(im_on, "w", stdout) == NULL) 259 return; 260 execvp(name, argv); 261 } 262 263 int errorsort(epp1, epp2) 264 Eptr *epp1, *epp2; 265 { 266 reg Eptr ep1, ep2; 267 int order; 268 /* 269 * Sort by: 270 * 1) synchronization, non specific, discarded errors first; 271 * 2) nulled and true errors last 272 * a) grouped by similar file names 273 * 1) grouped in ascending line number 274 */ 275 ep1 = *epp1; ep2 = *epp2; 276 if (ep1 == 0 || ep2 == 0) 277 return(0); 278 if ( (NOTSORTABLE(ep1->error_e_class)) ^ (NOTSORTABLE(ep2->error_e_class))){ 279 return(NOTSORTABLE(ep1->error_e_class) ? -1 : 1); 280 } 281 if (NOTSORTABLE(ep1->error_e_class)) /* then both are */ 282 return(ep1->error_no - ep2->error_no); 283 order = strcmp(ep1->error_text[0], ep2->error_text[0]); 284 if (order == 0){ 285 return(ep1->error_line - ep2->error_line); 286 } 287 return(order); 288 } 289