121636Sdist /*
2*61987Sbostic * Copyright (c) 1980, 1993
3*61987Sbostic * The Regents of the University of California. All rights reserved.
434664Sbostic *
542683Sbostic * %sccs.include.redist.c%
621636Sdist */
721636Sdist
821636Sdist #ifndef lint
9*61987Sbostic static char copyright[] =
10*61987Sbostic "@(#) Copyright (c) 1980, 1993\n\
11*61987Sbostic The Regents of the University of California. All rights reserved.\n";
1234664Sbostic #endif /* not lint */
1321636Sdist
1434664Sbostic #ifndef lint
15*61987Sbostic static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 06/06/93";
1634664Sbostic #endif /* not lint */
1734664Sbostic
1846694Sbostic #include <signal.h>
1946694Sbostic #include <unistd.h>
201457Sroot #include <stdio.h>
211457Sroot #include <ctype.h>
2246694Sbostic #include <stdlib.h>
2346694Sbostic #include <string.h>
241457Sroot #include "error.h"
2537791Sbostic #include "pathnames.h"
261457Sroot
271457Sroot int nerrors = 0;
285592Srrh Eptr er_head;
2937791Sbostic Eptr *errors;
301457Sroot
311457Sroot int nfiles = 0;
325592Srrh Eptr **files; /* array of pointers into errors*/
331457Sroot int language = INCC;
341457Sroot
351457Sroot char *currentfilename = "????";
361457Sroot char *processname;
3737791Sbostic char im_on[] = _PATH_TTY; /* my tty name */
381457Sroot
391457Sroot boolean query = FALSE; /* query the operator if touch files */
401457Sroot boolean notouch = FALSE; /* don't touch ANY files */
411457Sroot boolean piflag = FALSE; /* this is not pi */
425592Srrh boolean terse = FALSE; /* Terse output */
431457Sroot
441457Sroot char *suffixlist = ".*"; /* initially, can touch any file */
451457Sroot
461457Sroot int errorsort();
4746694Sbostic void onintr();
481457Sroot /*
491457Sroot * error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile]
501457Sroot *
515592Srrh * -T: terse output
525592Srrh *
531457Sroot * -I: the following name, `ignorename' contains a list of
541457Sroot * function names that are not to be treated as hard errors.
551457Sroot * Default: ~/.errorsrc
561457Sroot *
571457Sroot * -n: don't touch ANY files!
581457Sroot *
591457Sroot * -q: The user is to be queried before touching each
601457Sroot * file; if not specified, all files with hard, non
611457Sroot * ignorable errors are touched (assuming they can be).
621457Sroot *
631457Sroot * -t: touch only files ending with the list of suffices, each
641457Sroot * suffix preceded by a dot.
651457Sroot * eg, -t .c.y.l
661457Sroot * will touch only files ending with .c, .y or .l
671457Sroot *
681457Sroot * -s: print a summary of the error's categories.
691457Sroot *
701457Sroot * -v: after touching all files, overlay vi(1), ex(1) or ed(1)
711457Sroot * on top of error, entered in the first file with
721457Sroot * an error in it, with the appropriate editor
731457Sroot * set up to use the "next" command to get the other
741457Sroot * files containing errors.
751457Sroot *
761457Sroot * -p: (obsolete: for older versions of pi without bug
771457Sroot * fix regarding printing out the name of the main file
781457Sroot * with an error in it)
791457Sroot * Take the following argument and use it as the name of
801457Sroot * the pascal source file, suffix .p
811457Sroot *
821457Sroot * -E: show the errors in sorted order; intended for
831457Sroot * debugging.
841457Sroot *
851457Sroot * -S: show the errors in unsorted order
861457Sroot * (as they come from the error file)
871457Sroot *
881457Sroot * infile: The error messages come from this file.
891457Sroot * Default: stdin
901457Sroot */
main(argc,argv)911457Sroot main(argc, argv)
921457Sroot int argc;
931457Sroot char *argv[];
941457Sroot {
951457Sroot char *cp;
961457Sroot char *ignorename = 0;
971457Sroot int ed_argc;
981457Sroot char **ed_argv; /*return from touchfiles*/
991457Sroot boolean show_errors = FALSE;
1001457Sroot boolean Show_Errors = FALSE;
1011457Sroot boolean pr_summary = FALSE;
1021457Sroot boolean edit_files = FALSE;
1031457Sroot
1041457Sroot processname = argv[0];
1051457Sroot
1061457Sroot errorfile = stdin;
1075592Srrh if (argc > 1) for(; (argc > 1) && (argv[1][0] == '-'); argc--, argv++){
1085592Srrh for (cp = argv[1] + 1; *cp; cp++) switch(*cp){
1095592Srrh default:
1105592Srrh fprintf(stderr, "%s: -%c: Unknown flag\n",
1115592Srrh processname, *cp);
1125592Srrh break;
1135592Srrh
1145592Srrh case 'n': notouch = TRUE; break;
1155592Srrh case 'q': query = TRUE; break;
1165592Srrh case 'S': Show_Errors = TRUE; break;
1175592Srrh case 's': pr_summary = TRUE; break;
1185592Srrh case 'v': edit_files = TRUE; break;
1195592Srrh case 'T': terse = TRUE; break;
1205592Srrh case 't':
1215592Srrh *cp-- = 0; argv++; argc--;
1225592Srrh if (argc > 1){
1235592Srrh suffixlist = argv[1];
1245592Srrh }
1255592Srrh break;
1265592Srrh case 'I': /*ignore file name*/
1275592Srrh *cp-- = 0; argv++; argc--;
1285592Srrh if (argc > 1)
1295592Srrh ignorename = argv[1];
1305592Srrh break;
1315592Srrh }
1325592Srrh }
1331457Sroot if (notouch)
1341457Sroot suffixlist = 0;
1351457Sroot if (argc > 1){
1361457Sroot if (argc > 3){
1371457Sroot fprintf(stderr, "%s: Only takes 0 or 1 arguments\n",
1381457Sroot processname);
1391457Sroot exit(3);
1401457Sroot }
1411457Sroot if ( (errorfile = fopen(argv[1], "r")) == NULL){
1421457Sroot fprintf(stderr, "%s: %s: No such file or directory for reading errors.\n",
1431457Sroot processname, argv[1]);
1441457Sroot exit(4);
1451457Sroot }
1461457Sroot }
1471457Sroot if ( (queryfile = fopen(im_on, "r")) == NULL){
14816564Sralph if (query){
14916564Sralph fprintf(stderr,
15016564Sralph "%s: Can't open \"%s\" to query the user.\n",
15116564Sralph processname, im_on);
15216564Sralph exit(9);
15316564Sralph }
1541457Sroot }
1551457Sroot if (signal(SIGINT, onintr) == SIG_IGN)
1561457Sroot signal(SIGINT, SIG_IGN);
1571457Sroot if (signal(SIGTERM, onintr) == SIG_IGN)
1581457Sroot signal(SIGTERM, SIG_IGN);
1591457Sroot getignored(ignorename);
1601457Sroot eaterrors(&nerrors, &errors);
1611457Sroot if (Show_Errors)
1621457Sroot printerrors(TRUE, nerrors, errors);
1635592Srrh qsort(errors, nerrors, sizeof(Eptr), errorsort);
1641457Sroot if (show_errors)
1651457Sroot printerrors(FALSE, nerrors, errors);
1661457Sroot findfiles(nerrors, errors, &nfiles, &files);
1671457Sroot #define P(msg, arg) fprintf(stdout, msg, arg)
1681457Sroot if (pr_summary){
1691457Sroot if (nunknown)
1701457Sroot P("%d Errors are unclassifiable.\n", nunknown);
1711457Sroot if (nignore)
1721457Sroot P("%d Errors are classifiable, but totally discarded.\n",nignore);
1731457Sroot if (nsyncerrors)
1741457Sroot P("%d Errors are synchronization errors.\n", nsyncerrors);
1751457Sroot if (nignore)
1761457Sroot P("%d Errors are discarded because they refer to sacrosinct files.\n", ndiscard);
1771457Sroot if (nnulled)
1781457Sroot P("%d Errors are nulled because they refer to specific functions.\n", nnulled);
1791457Sroot if (nnonspec)
1801457Sroot P("%d Errors are not specific to any file.\n", nnonspec);
1811457Sroot if (nthisfile)
1821457Sroot P("%d Errors are specific to a given file, but not to a line.\n", nthisfile);
1831457Sroot if (ntrue)
1841457Sroot P("%d Errors are true errors, and can be inserted into the files.\n", ntrue);
1851457Sroot }
1861457Sroot filenames(nfiles, files);
1871457Sroot fflush(stdout);
1885592Srrh if (touchfiles(nfiles, files, &ed_argc, &ed_argv) && edit_files)
1895592Srrh forkvi(ed_argc, ed_argv);
1905592Srrh }
1915592Srrh
forkvi(argc,argv)1925592Srrh forkvi(argc, argv)
1935592Srrh int argc;
1945592Srrh char **argv;
1955592Srrh {
1965592Srrh if (query){
1975592Srrh switch(inquire(terse
1985592Srrh ? "Edit? "
1995592Srrh : "Do you still want to edit the files you touched? ")){
2005592Srrh case Q_NO:
2015592Srrh case Q_no:
2025592Srrh return;
2035592Srrh default:
2045592Srrh break;
2051457Sroot }
2061457Sroot }
2075592Srrh /*
2085592Srrh * ed_agument's first argument is
2095592Srrh * a vi/ex compatabile search argument
2105592Srrh * to find the first occurance of ###
2115592Srrh */
2125592Srrh try("vi", argc, argv);
2135592Srrh try("ex", argc, argv);
2145592Srrh try("ed", argc-1, argv+1);
2155592Srrh fprintf(stdout, "Can't find any editors.\n");
2161457Sroot }
2171457Sroot
try(name,argc,argv)2181457Sroot try(name, argc, argv)
2191457Sroot char *name;
2201457Sroot int argc;
2211457Sroot char **argv;
2221457Sroot {
2231457Sroot argv[0] = name;
2241457Sroot wordvprint(stdout, argc, argv);
2251457Sroot fprintf(stdout, "\n");
2261457Sroot fflush(stderr);
2271457Sroot fflush(stdout);
2281457Sroot sleep(2);
2291457Sroot if (freopen(im_on, "r", stdin) == NULL)
2301457Sroot return;
2311457Sroot if (freopen(im_on, "w", stdout) == NULL)
2321457Sroot return;
2331457Sroot execvp(name, argv);
2341457Sroot }
2351457Sroot
errorsort(epp1,epp2)2361457Sroot int errorsort(epp1, epp2)
2375592Srrh Eptr *epp1, *epp2;
2381457Sroot {
2395592Srrh reg Eptr ep1, ep2;
2405592Srrh int order;
2411457Sroot /*
2421457Sroot * Sort by:
2431457Sroot * 1) synchronization, non specific, discarded errors first;
2441457Sroot * 2) nulled and true errors last
2451457Sroot * a) grouped by similar file names
2461457Sroot * 1) grouped in ascending line number
2471457Sroot */
2481457Sroot ep1 = *epp1; ep2 = *epp2;
2491457Sroot if (ep1 == 0 || ep2 == 0)
2501457Sroot return(0);
2511457Sroot if ( (NOTSORTABLE(ep1->error_e_class)) ^ (NOTSORTABLE(ep2->error_e_class))){
2521457Sroot return(NOTSORTABLE(ep1->error_e_class) ? -1 : 1);
2531457Sroot }
2541457Sroot if (NOTSORTABLE(ep1->error_e_class)) /* then both are */
2551457Sroot return(ep1->error_no - ep2->error_no);
2561457Sroot order = strcmp(ep1->error_text[0], ep2->error_text[0]);
2571457Sroot if (order == 0){
2581457Sroot return(ep1->error_line - ep2->error_line);
2591457Sroot }
2601457Sroot return(order);
2611457Sroot }
262