|
|
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.