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 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. 11 */ 12 13 #ifndef lint 14 char copyright[] = 15 "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 16 All rights reserved.\n"; 17 #endif /* not lint */ 18 19 #ifndef lint 20 static char sccsid[] = "@(#)main.c 5.2 (Berkeley) 06/06/88"; 21 #endif /* not lint */ 22 23 #include <stdio.h> 24 #include <ctype.h> 25 #include <signal.h> 26 #include "error.h" 27 28 int nerrors = 0; 29 Eptr er_head; 30 Eptr *errors; 31 32 int nfiles = 0; 33 Eptr **files; /* array of pointers into errors*/ 34 int language = INCC; 35 36 char *currentfilename = "????"; 37 char *processname; 38 char im_on[] = "/dev/tty"; /* my tty name */ 39 40 boolean query = FALSE; /* query the operator if touch files */ 41 boolean notouch = FALSE; /* don't touch ANY files */ 42 boolean piflag = FALSE; /* this is not pi */ 43 boolean terse = FALSE; /* Terse output */ 44 45 char *suffixlist = ".*"; /* initially, can touch any file */ 46 47 int errorsort(); 48 int onintr(); 49 /* 50 * error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile] 51 * 52 * -T: terse output 53 * 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 */ 92 main(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; 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; 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 } 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 } 148 if ( (queryfile = fopen(im_on, "r")) == NULL){ 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 } 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); 164 qsort(errors, nerrors, sizeof(Eptr), errorsort); 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); 189 if (touchfiles(nfiles, files, &ed_argc, &ed_argv) && edit_files) 190 forkvi(ed_argc, ed_argv); 191 } 192 193 forkvi(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; 206 } 207 } 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"); 217 } 218 219 try(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 237 int errorsort(epp1, epp2) 238 Eptr *epp1, *epp2; 239 { 240 reg Eptr ep1, ep2; 241 int order; 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 } 263