|
|
1.1 ! root 1: static char *sccsid = "@(#)errortouch.c 1.2 (Berkeley) 10/16/80"; ! 2: #include <stdio.h> ! 3: #include <ctype.h> ! 4: #include <sys/types.h> ! 5: #include <sys/stat.h> ! 6: #include <signal.h> ! 7: #include "error.h" ! 8: ! 9: findfiles(nerrors, errors, r_nfiles, r_files) ! 10: int nerrors; ! 11: struct error_desc **errors; ! 12: int *r_nfiles; ! 13: struct error_desc ****r_files; ! 14: { ! 15: int nfiles; ! 16: struct error_desc ***files; ! 17: ! 18: char *currentfilename; ! 19: register int errorindex; ! 20: int fileindex; ! 21: register struct error_desc *errorp; ! 22: /* ! 23: * First, go through and count all of the filenames ! 24: */ ! 25: for (errorp = errors[errorindex = 0],nfiles = 0, currentfilename = "\1"; ! 26: errorindex < nerrors; ! 27: errorp = errors[++errorindex]){ ! 28: if (SORTABLE(errorp->error_e_class)){ ! 29: if (strcmp(errorp->error_text[0],currentfilename) != 0){ ! 30: nfiles++; ! 31: currentfilename = errorp->error_text[0]; ! 32: } ! 33: } ! 34: } ! 35: files = (struct error_desc ***)Calloc(nfiles + 3, ! 36: sizeof (struct error_desc**)); ! 37: touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean)); ! 38: /* ! 39: * Now, go through and partition off the error messages ! 40: * into those that are synchronization, discarded or ! 41: * not specific to any file, and those that were ! 42: * nulled or true errors. ! 43: */ ! 44: files[0] = &errors[0]; ! 45: for (errorp = errors[errorindex = 0], fileindex = 0; ! 46: (errorindex < nerrors) && ! 47: (NOTSORTABLE(errorp->error_e_class)); ! 48: errorp = errors[++errorindex]){ ! 49: continue; ! 50: } ! 51: /* ! 52: * Now, go through and partition off all error messages ! 53: * for a given file. ! 54: */ ! 55: files[1] = &errors[errorindex]; ! 56: touchedfiles[0] = touchedfiles[1] = FALSE; ! 57: for (errorp = errors[errorindex], currentfilename = "\1", fileindex = 1; ! 58: errorindex < nerrors; errorp = errors[++errorindex]){ ! 59: if ( (errorp->error_e_class == C_NULLED) || (errorp->error_e_class == C_TRUE) ){ ! 60: if (strcmp(errorp->error_text[0],currentfilename) != 0){ ! 61: currentfilename = errorp->error_text[0]; ! 62: touchedfiles[fileindex] = FALSE; ! 63: files[fileindex++] = &errors[errorindex]; ! 64: } ! 65: } ! 66: } ! 67: files[fileindex] = &errors[nerrors]; ! 68: *r_nfiles = nfiles; ! 69: *r_files = files; ! 70: } ! 71: ! 72: char *class_table[] = { ! 73: /*C_UNKNOWN 0 */ "Unknown", ! 74: /*C_IGNORE 1 */ "ignore", ! 75: /*C_SYNC 2 */ "synchronization", ! 76: /*C_DISCARD 3 */ "discarded", ! 77: /*C_NONSPEC 4 */ "non specific", ! 78: /*C_THISFILE 5 */ "specific to this file", ! 79: /*C_NULLED 6 */ "nulled", ! 80: /*C_TRUE 7 */ "true", ! 81: /*C_DUPL 8 */ "duplicated" ! 82: }; ! 83: ! 84: int class_count[C_LAST - C_FIRST] = {0}; ! 85: ! 86: filenames(nfiles, files) ! 87: int nfiles; ! 88: struct error_desc ***files; ! 89: { ! 90: register int fileindex; ! 91: register struct error_desc *errorp; ! 92: register struct error_desc **erpp; ! 93: char *sep = " "; ! 94: register int errortype; ! 95: extern char *class_table[]; ! 96: int someerrors = 0; ! 97: ! 98: /* ! 99: * first, go through and simply dump out errors that ! 100: * don't pertain to any file ! 101: */ ! 102: if (files[1] - files[0] > 0){ ! 103: for(errortype = C_UNKNOWN; NOTSORTABLE(errortype); errortype++){ ! 104: if (class_count[errortype] > 0){ ! 105: if (errortype > C_SYNC) ! 106: someerrors++; ! 107: fprintf(stdout, "\n\t%d %s errors follow:\n", ! 108: class_count[errortype], class_table[errortype]); ! 109: for (errorp = *(erpp = files[0]); ! 110: erpp < files[1]; ! 111: errorp = (*++erpp)){ ! 112: if (errorp->error_e_class == errortype) ! 113: errorprint(stdout, errorp, TRUE); ! 114: } ! 115: } ! 116: } ! 117: } ! 118: if (nfiles){ ! 119: someerrors++; ! 120: fprintf(stdout, "%d files contain errors:", nfiles); ! 121: for (fileindex = 1; fileindex <= nfiles; fileindex++){ ! 122: fprintf(stdout, "%s\"%s\" (%d)", ! 123: sep, (*files[fileindex])->error_text[0], ! 124: files[fileindex+1] - files[fileindex]); ! 125: sep = ", "; ! 126: } ! 127: fprintf(stdout, "\n"); ! 128: } ! 129: if (!someerrors) ! 130: fprintf(stdout, "No errors.\n"); ! 131: } ! 132: ! 133: extern boolean notouch; ! 134: ! 135: boolean touchfiles(nfiles, files, r_edargc, r_edargv) ! 136: int nfiles; ! 137: struct error_desc ***files; ! 138: int *r_edargc; ! 139: char ***r_edargv; ! 140: { ! 141: char *currentfilename; ! 142: register struct error_desc *errorp; ! 143: register int fileindex; ! 144: register struct error_desc **erpp; ! 145: int ntrueerrors; ! 146: int errordest; /* where errors go*/ ! 147: char *sep; ! 148: boolean scribbled; ! 149: int n_pissed_on; /* # of file touched*/ ! 150: int previewed; ! 151: ! 152: for (fileindex = 1; fileindex <= nfiles; fileindex++){ ! 153: fprintf(stdout, "\nFile \"%s\" has %d total error messages.\n", ! 154: currentfilename = (*files[fileindex])->error_text[0], ! 155: files[fileindex+1] - files[fileindex]); ! 156: /* ! 157: * First, iterate through all error messages in this file ! 158: * to see how many of the error messages really will ! 159: * get inserted into the file. ! 160: */ ! 161: for (erpp = files[fileindex], ntrueerrors = 0; ! 162: erpp < files[fileindex+1]; ! 163: erpp++){ ! 164: errorp = *erpp; ! 165: if (errorp->error_e_class == C_TRUE) ! 166: ntrueerrors++; ! 167: } ! 168: fprintf(stdout,"\t%d of these errors can be inserted into the file.\n", ! 169: ntrueerrors); ! 170: ! 171: /* ! 172: * What does the operator want? ! 173: */ ! 174: previewed = 0; ! 175: errordest = TOSTDOUT; ! 176: if (oktotouch(currentfilename) && (ntrueerrors > 0) ){ ! 177: if (query && inquire("Do you want to preview the errors first?")){ ! 178: previewed = 1; ! 179: for (erpp = files[fileindex]; ! 180: erpp < files[fileindex + 1]; ! 181: erpp++){ ! 182: errorprint(stdout, *erpp, TRUE); ! 183: } ! 184: fprintf(stdout, "\n"); ! 185: } ! 186: if ( !query ! 187: || inquire("Do you want to touch file \"%s\"? ", ! 188: currentfilename) ! 189: ){ ! 190: errordest = TOTHEFILE; ! 191: if (!probethisfile(currentfilename)){ ! 192: errordest = TOSTDOUT; ! 193: fprintf(stdout, ! 194: "Can't find file \"%s\" to insert error messages into.\n", ! 195: currentfilename); ! 196: } else { ! 197: if (edit(currentfilename)) ! 198: errordest = TOSTDOUT; ! 199: else ! 200: touchedfiles[fileindex] = TRUE; ! 201: } ! 202: } ! 203: } ! 204: if (previewed && (errordest == TOSTDOUT)) ! 205: continue; /* with the next file */ ! 206: /* ! 207: * go through and print each error message, ! 208: * diverting to the right place ! 209: */ ! 210: if ( (files[fileindex+1] - files[fileindex]) != ntrueerrors) ! 211: if (!previewed) fprintf(stdout, ! 212: ">>Uninserted error messages for file \"%s\" follow.\n", ! 213: currentfilename); ! 214: for (erpp = files[fileindex];erpp < files[fileindex+1];erpp++){ ! 215: errorp = *erpp; ! 216: if (errorp->error_e_class == C_TRUE){ ! 217: switch (errordest){ ! 218: case TOSTDOUT: ! 219: if (!previewed) ! 220: errorprint(stdout,errorp, TRUE); ! 221: break; ! 222: case TOTHEFILE: ! 223: insert(errorp->error_line); ! 224: text(errorp, FALSE); ! 225: break; ! 226: } /* switch */ ! 227: } else { ! 228: if (!previewed) ! 229: errorprint(stdout, errorp, TRUE); ! 230: } ! 231: } /* end of walking through all errors*/ ! 232: if (errordest == TOTHEFILE){ ! 233: writetouched(); ! 234: } ! 235: } /* end of walking through all files*/ ! 236: scribbled = FALSE; ! 237: for (n_pissed_on = 0, fileindex = 1; fileindex <= nfiles; fileindex++){ ! 238: scribbled |= touchedfiles[fileindex]; ! 239: n_pissed_on++; ! 240: } ! 241: if (scribbled){ ! 242: /* ! 243: * Construct an execv argument ! 244: * We need 1 argument for the editor's name ! 245: * We need 1 argument for the initial search string ! 246: * We need n_pissed_on arguments for the file names ! 247: * We need 1 argument that is a null for execv. ! 248: * The caller fills in the editor's name. ! 249: * We fill in the initial search string. ! 250: * We fill in the arguments, and the null. ! 251: */ ! 252: (*r_edargv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *)); ! 253: (*r_edargc) = n_pissed_on + 2; ! 254: (*r_edargv)[1] = "+/###/"; ! 255: n_pissed_on = 2; ! 256: fprintf(stdout, "You touched file(s):"); ! 257: sep = " "; ! 258: for (fileindex = 1; fileindex <= nfiles; fileindex++){ ! 259: if (!touchedfiles[fileindex]) ! 260: continue; ! 261: errorp = *(files[fileindex]); ! 262: fprintf(stdout,"%s\"%s\"", sep, errorp->error_text[0]); ! 263: sep = ", "; ! 264: (*r_edargv)[n_pissed_on++] = errorp->error_text[0]; ! 265: } ! 266: fprintf(stdout, "\n"); ! 267: (*r_edargv)[n_pissed_on] = 0; ! 268: return(TRUE); ! 269: } else { ! 270: fprintf(stdout, "You didn't touch any files.\n"); ! 271: return(FALSE); ! 272: } ! 273: ! 274: } /* end of touchfiles*/ ! 275: int oktotouch(filename) ! 276: char *filename; ! 277: { ! 278: extern char *suffixlist; ! 279: register char *src; ! 280: register char *pat; ! 281: char *osrc; ! 282: ! 283: pat = suffixlist; ! 284: if (pat == 0) ! 285: return(0); ! 286: if (*pat == '*') ! 287: return(1); ! 288: while (*pat++ != '.') ! 289: continue; ! 290: --pat; /* point to the period */ ! 291: ! 292: for (src = &filename[strlen(filename)], --src; ! 293: (src > filename) && (*src != '.'); --src) ! 294: continue; ! 295: if (*src != '.') ! 296: return(0); ! 297: ! 298: for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){ ! 299: for (; *src /* not at end of the source */ ! 300: && *pat /* not off end of pattern */ ! 301: && *pat != '.' /* not off end of sub pattern */ ! 302: && *pat != '*' /* not wild card */ ! 303: && *src == *pat; /* and equal... */ ! 304: src++, pat++) ! 305: continue; ! 306: if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*')) ! 307: return(1); ! 308: if (*src != 0 && *pat == '*') ! 309: return(1); ! 310: while (*pat && *pat != '.') ! 311: pat++; ! 312: if (! *pat) ! 313: return(0); ! 314: } ! 315: return(0); ! 316: } ! 317: ! 318: FILE *o_touchedfile; /* the old file */ ! 319: FILE *n_touchedfile; /* the new file */ ! 320: char *o_name; ! 321: char n_name[32]; ! 322: char *canon_name = "ErrorXXXXXX"; ! 323: int o_lineno; ! 324: int n_lineno; ! 325: boolean tempfileopen = FALSE; ! 326: /* ! 327: * open the file; guaranteed to be both readable and writable ! 328: * Well, if it isn't, then return TRUE if something failed ! 329: */ ! 330: boolean edit(name) ! 331: char *name; ! 332: { ! 333: o_name = name; ! 334: if ( (o_touchedfile = fopen(name, "r")) == NULL){ ! 335: fprintf(stderr, "%s: Can't open file \"%s\" to touch (read).\n", ! 336: processname, name); ! 337: return(TRUE); ! 338: } ! 339: strcpy(n_name, canon_name); ! 340: mktemp(n_name); ! 341: if ( (n_touchedfile = fopen(n_name, "w")) == NULL){ ! 342: fprintf(stderr,"%s: Can't open file \"%s\" to touch (write).\n", ! 343: processname, name); ! 344: return(TRUE); ! 345: } ! 346: tempfileopen = TRUE; ! 347: n_lineno = 0; ! 348: o_lineno = 0; ! 349: return(FALSE); ! 350: } ! 351: /* ! 352: * Position to the line (before, after) the line given by place ! 353: */ ! 354: char edbuffer[BUFSIZ]; ! 355: insert(place) ! 356: int place; ! 357: { ! 358: --place; /* always insert messages before the offending line*/ ! 359: for(; o_lineno < place; o_lineno++, n_lineno++){ ! 360: if(fgets(edbuffer, BUFSIZ, o_touchedfile) == NULL) ! 361: return; ! 362: fputs(edbuffer, n_touchedfile); ! 363: } ! 364: } ! 365: ! 366: text(errorp, use_all) ! 367: register struct error_desc *errorp; ! 368: boolean use_all; ! 369: { ! 370: int offset = use_all ? 0 : 2; ! 371: fputs(lang_table[errorp->error_language].lang_incomment, n_touchedfile); ! 372: fprintf(n_touchedfile, "%d [%s] ", ! 373: errorp->error_line, ! 374: lang_table[errorp->error_language].lang_name); ! 375: wordvprint(n_touchedfile, ! 376: errorp->error_lgtext-offset, errorp->error_text+offset); ! 377: fputs(lang_table[errorp->error_language].lang_outcomment,n_touchedfile); ! 378: n_lineno++; ! 379: } ! 380: ! 381: writetouched() ! 382: { ! 383: int bytes_read; ! 384: for(; (bytes_read = fread(edbuffer, 1, sizeof(edbuffer), o_touchedfile))!= NULL; ){ ! 385: fwrite(edbuffer, 1, bytes_read, n_touchedfile); ! 386: } ! 387: fclose(n_touchedfile); ! 388: fclose(o_touchedfile); ! 389: unlink(o_name); ! 390: link(n_name, o_name); ! 391: unlink(n_name); ! 392: tempfileopen = FALSE; ! 393: } ! 394: onintr() ! 395: { ! 396: if (inquire("\nInterrupt: Do you want to continue?")){ ! 397: signal(SIGINT, onintr); ! 398: return; ! 399: } ! 400: if (tempfileopen) ! 401: writetouched(); ! 402: exit(1); ! 403: } ! 404: errorprint(place, errorp, print_all) ! 405: FILE *place; ! 406: struct error_desc *errorp; ! 407: boolean print_all; ! 408: { ! 409: int offset = print_all ? 0 : 2; ! 410: ! 411: if (errorp->error_e_class == C_IGNORE) ! 412: return; ! 413: fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name); ! 414: wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset); ! 415: putc('\n', place); ! 416: } ! 417: ! 418: boolean inquire(fmt, a1, a2) ! 419: char *fmt; ! 420: /*VARARGS1*/ ! 421: { ! 422: char buffer[128]; ! 423: char ch; ! 424: for(;;){ ! 425: do{ ! 426: fflush(stdout); ! 427: fprintf(stderr, fmt, a1, a2); ! 428: fflush(stderr); ! 429: } while (fgets(buffer, 127, queryfile) == NULL); ! 430: ch = buffer[0]; ! 431: if (ch == 'Y' || ch == 'y') ! 432: return(TRUE); ! 433: if (ch == 'N' || ch == 'n') ! 434: return(FALSE); ! 435: fprintf(stderr, "Yes or No only!\n"); ! 436: } ! 437: } ! 438: ! 439: boolean probethisfile(currentfilename) ! 440: char *currentfilename; ! 441: { ! 442: struct stat statbuf; ! 443: if (stat(currentfilename, &statbuf) != 0) ! 444: return(FALSE); ! 445: if ( (statbuf.st_mode&S_IREAD) && (statbuf.st_mode&S_IWRITE)) ! 446: return(TRUE); ! 447: return(FALSE); ! 448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.