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