Retire error(1). This is no longer useful as it applies only to the 4.xBSD

toolchain.

Reviewed by:	current@freebsd.org
Axe kindly supplied by:	Institute of Danish Surgeons
This commit is contained in:
Kris Kennaway 1999-12-11 03:33:33 +00:00
parent 5792b7fe0b
commit f1b5e7b750
11 changed files with 0 additions and 3267 deletions

View File

@ -38,7 +38,6 @@ SUBDIR= apply \
ee \
enigma \
env \
error \
expand \
false \
fetch \

View File

@ -1,7 +0,0 @@
# @(#)Makefile 8.1 (Berkeley) 6/6/93
PROG= error
CFLAGS+=-Wall
SRCS= main.c input.c pi.c subr.c filter.c touch.c
.include <bsd.prog.mk>

View File

@ -1,305 +0,0 @@
.\" Copyright (c) 1980, 1990, 1993
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by the University of
.\" California, Berkeley and its contributors.
.\" 4. Neither the name of the University nor the names of its contributors
.\" may be used to endorse or promote products derived from this software
.\" without specific prior written permission.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" @(#)error.1 8.1 (Berkeley) 6/6/93
.\" $FreeBSD$
.\"
.Dd June 6, 1993
.Dt ERROR 1
.Os BSD 4
.Sh NAME
.Nm error
.Nd analyze and disperse compiler error messages
.Sh SYNOPSIS
.Nm error
.Op Fl n
.Op Fl s
.Op Fl q
.Op Fl v
.Op Fl t Ar suffixlist
.Op Fl I Ar ignorefile
.Op name
.Sh DESCRIPTION
.Nm Error
analyzes and optionally disperses the diagnostic error messages
produced by a number of compilers and language processors to the source
file and line where the errors occurred. It can replace the painful,
traditional methods of scribbling abbreviations of errors on paper, and
permits error messages and source code to be viewed simultaneously
without machinations of multiple windows in a screen editor.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl n
Do
.Em not
touch any files; all error messages are sent to the
standard output.
.It Fl q
The user is
.Ar queried
whether s/he wants to touch the file.
A ``y'' or ``n'' to the question is necessary to continue.
Absence of the
.Fl q
option implies that all referenced files
(except those referring to discarded error messages)
are to be touched.
.It Fl v
After all files have been touched,
overlay the visual editor
.Xr \&vi 1
with it set up to edit all files touched,
and positioned in the first touched file at the first error.
If
.Xr \&vi 1
can't be found, try
.Xr \&ex 1
or
.Xr \&ed 1
from standard places.
.It Fl t
Take the following argument as a suffix list.
Files whose suffixes do not appear in the suffix list are not touched.
The suffix list is dot separated, and ``*'' wildcards work.
Thus the suffix list:
.Pp
.Dl ".c.y.foo*.h"
.Pp
allows
.Nm
to touch files ending with ``.c'', ``.y'', ``.foo*'' and ``.h''.
.It Fl s
Print out
.Em statistics
regarding the error categorization.
Not too useful.
.El
.Pp
.Nm Error
looks at the error messages,
either from the specified file
.Ar name
or from the standard input,
and attempts to determine which
language processor produced each error message,
determines the source file and line number to which the error message refers,
determines if the error message is to be ignored or not,
and inserts the (possibly slightly modified) error message into
the source file as a comment on the line preceding to which the
line the error message refers.
Error messages which can't be categorized by language processor
or content are not inserted into any file,
but are sent to the standard output.
.Nm Error
touches source files only after all input has been read.
.Pp
.Nm Error
is intended to be run
with its standard input
connected via a pipe to the error message source.
Some language processors put error messages on their standard error file;
others put their messages on the standard output.
Hence, both error sources should be piped together into
.Nm Ns .
For example, when using the
.Xr csh 1
syntax,
.Pp
.Dl make \-s lint \&| error \-q \-v
.Pp
will analyze all the error messages produced
by whatever programs
.Xr make 1
runs when making lint.
.Pp
.Nm Error
knows about the error messages produced by:
.Xr make 1 ,
.Xr \&cc 1 ,
.Xr cpp 1 ,
.Xr ccom 1 ,
.Xr \&as 1 ,
.Xr \&ld 1 ,
.Xr lint 1 ,
.Xr \&pi 1 ,
.Xr \&pc 1 ,
.Xr f77 1 ,
and
.Em DEC Western Research Modula\-2 .
.Nm Error
knows a standard format for error messages produced by
the language processors,
so is sensitive to changes in these formats.
For all languages except
.Em Pascal ,
error messages are restricted to be on one line.
Some error messages refer to more than one line in more than
one files;
.Nm
will duplicate the error message and insert it at
all of the places referenced.
.Pp
.Nm Error
will do one of six things with error messages.
.Bl -tag -width Em synchronize
.It Em synchronize
Some language processors produce short errors describing
which file it is processing.
.Nm Error
uses these to determine the file name for languages that
don't include the file name in each error message.
These synchronization messages are consumed entirely by
.Nm Ns .
.It Em discard
Error messages from
.Xr lint 1
that refer to one of the two
.Xr lint 1
libraries,
.Pa /usr/libdata/lint/llib-lc
and
.Pa /usr/libdata/lint/llib-port
are discarded,
to prevent accidently touching these libraries.
Again, these error messages are consumed entirely by
.Nm Ns .
.It Em nullify
Error messages from
.Xr lint 1
can be nullified if they refer to a specific function,
which is known to generate diagnostics which are not interesting.
Nullified error messages are not inserted into the source file,
but are written to the standard output.
The names of functions to ignore are taken from
either the file named
.Pa .errorrc
in the users's home directory,
or from the file named by the
.Fl I
option.
If the file does not exist,
no error messages are nullified.
If the file does exist, there must be one function
name per line.
.It Em not file specific
Error messages that can't be intuited are grouped together,
and written to the standard output before any files are touched.
They will not be inserted into any source file.
.It Em file specific
Error message that refer to a specific file,
but to no specific line,
are written to the standard output when
that file is touched.
.It Em true errors
Error messages that can be intuited are candidates for
insertion into the file to which they refer.
.El
.Pp
Only true error messages are candidates for inserting into
the file they refer to.
Other error messages are consumed entirely by
.Nm
or are written to the standard output.
.Nm Error
inserts the error messages into the source file on the line
preceding the line the language processor found in error.
Each error message is turned into a one line comment for the
language,
and is internally flagged
with the string ``###'' at
the beginning of the error,
and ``%%%'' at the end of the error.
This makes pattern searching for errors easier with an editor,
and allows the messages to be easily removed.
In addition, each error message contains the source line number
for the line the message refers to.
A reasonably formatted source program can be recompiled
with the error messages still in it,
without having the error messages themselves cause future errors.
For poorly formatted source programs in free format languages,
such as C or Pascal,
it is possible to insert a comment into another comment,
which can wreak havoc with a future compilation.
To avoid this, programs with comments and source
on the same line should be formatted
so that language statements appear before comments.
.Pp
.Nm Error
catches interrupt and terminate signals,
and if in the insertion phase,
will orderly terminate what it is doing.
.Sh FILES
.Bl -tag -width ~/.errorrc -compact
.It Pa ~/.errorrc
function names to ignore for
.Xr lint 1
error messages
.It Pa /dev/tty
user's teletype
.El
.Sh HISTORY
The
.Nm
command
appeared in
.Bx 4.0 .
.Sh AUTHORS
.An Robert Henry
.Sh BUGS
.Pp
Opens the teletype directly to do user querying.
.Pp
Source files with links make a new copy of the file with
only one link to it.
.Pp
Changing a language processor's format of error messages
may cause
.Nm
to not understand the error message.
.Pp
.Nm Error ,
since it is purely mechanical,
will not filter out subsequent errors caused by `floodgating'
initiated by one syntactically trivial error.
Humans are still much better at discarding these related errors.
.Pp
Pascal error messages belong after the lines affected
(error puts them before). The alignment of the `\\' marking
the point of error is also disturbed by
.Nm Ns .
.Pp
.Nm Error
was designed for work on
.Tn CRT Ns 's
at reasonably high speed.
It is less pleasant on slow speed terminals, and has never been
used on hardcopy terminals.

View File

@ -1,241 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)error.h 8.1 (Berkeley) 6/6/93
*/
typedef int boolean;
#define reg register
#define TRUE 1
#define FALSE 0
#define true 1
#define false 0
/*
* Descriptors for the various languages we know about.
* If you touch these, also touch lang_table
*/
#define INUNKNOWN 0
#define INCPP 1
#define INCC 2
#define INAS 3
#define INLD 4
#define INLINT 5
#define INF77 6
#define INPI 7
#define INPC 8
#define INFRANZ 9
#define INLISP 10
#define INVAXIMA 11
#define INRATFOR 12
#define INLEX 13
#define INYACC 14
#define INAPL 15
#define INMAKE 16
#define INRI 17
#define INTROFF 18
#define INMOD2 19
extern int language;
/*
* We analyze each line in the error message file, and
* attempt to categorize it by type, as well as language.
* Here are the type descriptors.
*/
typedef int Errorclass;
#define C_FIRST 0 /* first error category */
#define C_UNKNOWN 0 /* must be zero */
#define C_IGNORE 1 /* ignore the message; used for pi */
#define C_SYNC 2 /* synchronization errors */
#define C_DISCARD 3 /* touches dangerous files, so discard */
#define C_NONSPEC 4 /* not specific to any file */
#define C_THISFILE 5 /* specific to this file, but at no line */
#define C_NULLED 6 /* refers to special func; so null */
#define C_TRUE 7 /* fits into true error format */
#define C_DUPL 8 /* sub class only; duplicated error message */
#define C_LAST 9 /* last error category */
#define SORTABLE(x) (!(NOTSORTABLE(x)))
#define NOTSORTABLE(x) (x <= C_NONSPEC)
/*
* Resources to count and print out the error categories
*/
extern char *class_table[];
extern int class_count[];
#define nunknown class_count[C_UNKNOWN]
#define nignore class_count[C_IGNORE]
#define nsyncerrors class_count[C_SYNC]
#define ndiscard class_count[C_DISCARD]
#define nnonspec class_count[C_NONSPEC]
#define nthisfile class_count[C_THISFILE]
#define nnulled class_count[C_NULLED]
#define ntrue class_count[C_TRUE]
#define ndupl class_count[C_DUPL]
/* places to put the error complaints */
#define TOTHEFILE 1 /* touch the file */
#define TOSTDOUT 2 /* just print them out (ho-hum) */
FILE *errorfile; /* where error file comes from */
FILE *queryfile; /* where the query responses from the user come from*/
extern char *currentfilename;
extern char *scriptname;
extern boolean query;
extern boolean terse;
int inquire(); /* inquire for yes/no */
/*
* codes for inquire() to return
*/
#define Q_NO 1 /* 'N' */
#define Q_no 2 /* 'n' */
#define Q_YES 3 /* 'Y' */
#define Q_yes 4 /* 'y' */
int probethisfile();
/*
* codes for probethisfile to return
*/
#define F_NOTEXIST 1
#define F_NOTREAD 2
#define F_NOTWRITE 3
#define F_TOUCHIT 4
/*
* Describes attributes about a language
*/
struct lang_desc{
char *lang_name;
char *lang_incomment; /* one of the following defines */
char *lang_outcomment; /* one of the following defines */
};
extern struct lang_desc lang_table[];
#define CINCOMMENT "/*###"
#define COUTCOMMENT "%%%*/\n"
#define FINCOMMENT "C###"
#define FOUTCOMMENT "%%%\n"
#define NEWLINE "%%%\n"
#define PIINCOMMENT "(*###"
#define PIOUTCOMMENT "%%%*)\n"
#define LISPINCOMMENT ";###"
#define ASINCOMMENT "####"
#define RIINCOMMENT CINCOMMENT
#define RIOUTCOMMENT COUTCOMMENT
#define TROFFINCOMMENT ".\\\"###"
#define TROFFOUTCOMMENT NEWLINE
#define MOD2INCOMMENT "(*###"
#define MOD2OUTCOMMENT "%%%*)\n"
/*
* Defines and resources for determing if a given line
* is to be discarded because it refers to a file not to
* be touched, or if the function reference is to a
* function the user doesn't want recorded.
*/
#define ERRORNAME "/.errorrc"
int nignored;
char **names_ignored;
/*
* Structure definition for a full error
*/
typedef struct edesc Edesc;
typedef Edesc *Eptr;
struct edesc{
Eptr error_next; /*linked together*/
int error_lgtext; /* how many on the right hand side*/
char **error_text; /* the right hand side proper*/
Errorclass error_e_class; /* error category of this error*/
Errorclass error_s_class; /* sub descriptor of error_e_class*/
int error_language; /* the language for this error*/
int error_position; /* oridinal position */
int error_line; /* discovered line number*/
int error_no; /* sequence number on input */
};
/*
* Resources for the true errors
*/
extern int nerrors;
extern Eptr er_head;
extern Eptr *errors;
/*
* Resources for each of the files mentioned
*/
extern int nfiles;
extern Eptr **files; /* array of pointers into errors*/
boolean *touchedfiles; /* which files we touched */
/*
* The langauge the compilation is in, as intuited from
* the flavor of error messages analyzed.
*/
extern int langauge;
extern char *currentfilename;
/*
* Functional forwards
*/
char *Calloc();
char *strsave();
char *clobberfirst();
char lastchar();
char firstchar();
char next_lastchar();
char **wordvsplice();
int wordvcmp();
boolean persperdexplode();
/*
* Printing hacks
*/
char *plural(), *verbform();
void arrayify __P((int *, Eptr **, Eptr));
void clob_last __P((char *, char));
Errorclass discardit __P((Eptr));
void eaterrors __P((int *, Eptr **));
void erroradd __P((int, char **, Errorclass, Errorclass));
void filenames __P((int, Eptr **));
void findfiles __P((int, Eptr *, int *, Eptr ***));
void getignored __P((char *));
void onintr __P((int));
int position __P((char *, char));
void printerrors __P((boolean, int, Eptr []));
char *substitute __P((char *, char, char));
boolean touchfiles __P((int, Eptr **, int *, char ***));
void wordvbuild __P((char *, int *, char ***));
void wordvprint __P((FILE *, int, char *[]));

View File

@ -1,199 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)filter.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/types.h>
#include <ctype.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "error.h"
#include "pathnames.h"
char *lint_libs[] = {
IG_FILE1,
IG_FILE2,
IG_FILE3,
IG_FILE4,
0
};
int lexsort __P((const void *, const void *));
/*
* Read the file ERRORNAME of the names of functions in lint
* to ignore complaints about.
*/
void
getignored(auxname)
char *auxname;
{
reg int i;
FILE *fyle;
char inbuffer[256];
int uid;
char filename[128];
char *username;
struct passwd *passwdentry;
nignored = 0;
if (auxname == 0){ /* use the default */
if ( (username = (char *)getlogin()) == NULL){
username = "Unknown";
uid = getuid();
if ( (passwdentry = (struct passwd *)getpwuid(uid)) == NULL){
return;
}
} else {
if ( (passwdentry = (struct passwd *)getpwnam(username)) == NULL)
return;
}
strcpy(filename, passwdentry->pw_dir);
(void)strcat(filename, ERRORNAME);
} else
(void)strcpy(filename, auxname);
#ifdef FULLDEBUG
printf("Opening file \"%s\" to read names to ignore.\n",
filename);
#endif
if ( (fyle = fopen(filename, "r")) == NULL){
#ifdef FULLDEBUG
warnx("can't open file \"%s\"", filename);
#endif
return;
}
/*
* Make the first pass through the file, counting lines
*/
for (nignored = 0; fgets(inbuffer, 255, fyle) != NULL; nignored++)
continue;
names_ignored = (char **)Calloc(nignored+1, sizeof (char *));
fclose(fyle);
if (freopen(filename, "r", fyle) == NULL){
#ifdef FULLDEBUG
warnx("failure to open \"%s\" for second read", filename);
#endif
nignored = 0;
return;
}
for (i=0; i < nignored && (fgets (inbuffer, 255, fyle) != NULL); i++){
names_ignored[i] = strsave(inbuffer);
(void)substitute(names_ignored[i], '\n', '\0');
}
qsort(names_ignored, nignored, sizeof *names_ignored, lexsort);
#ifdef FULLDEBUG
printf("Names to ignore follow.\n");
for (i=0; i < nignored; i++){
printf("\tIgnore: %s\n", names_ignored[i]);
}
#endif
}
int lexsort(vcpp1, vcpp2)
const void *vcpp1, *vcpp2;
{
char * const *cpp1 = vcpp1, * const *cpp2 = vcpp2;
return(strcmp(*cpp1, *cpp2));
}
int search_ignore(key)
char *key;
{
reg int ub, lb;
reg int halfway;
int order;
if (nignored == 0)
return(-1);
for(lb = 0, ub = nignored - 1; ub >= lb; ){
halfway = (ub + lb)/2;
if ( (order = strcmp(key, names_ignored[halfway])) == 0)
return(halfway);
if (order < 0) /*key is less than probe, throw away above*/
ub = halfway - 1;
else
lb = halfway + 1;
}
return(-1);
}
/*
* Tell if the error text is to be ignored.
* The error must have been canonicalized, with
* the file name the zeroth entry in the errorv,
* and the linenumber the second.
* Return the new categorization of the error class.
*/
Errorclass discardit(errorp)
reg Eptr errorp;
{
int language;
reg int i;
Errorclass errorclass = errorp->error_e_class;
switch(errorclass){
case C_SYNC:
case C_NONSPEC:
case C_UNKNOWN: return(errorclass);
default: ;
}
if(errorp->error_lgtext < 2){
return(C_NONSPEC);
}
language = errorp->error_language;
if(language == INLINT){
if (errorclass != C_NONSPEC){ /* no file */
for(i=0; lint_libs[i] != 0; i++){
if (strcmp(errorp->error_text[0], lint_libs[i]) == 0){
return(C_DISCARD);
}
}
}
/* check if the argument to the error message is to be ignored*/
if (ispunct(lastchar(errorp->error_text[2])))
clob_last(errorp->error_text[2], '\0');
if (search_ignore(errorp->error_text[errorclass == C_NONSPEC ? 0 : 2]) >= 0){
return(C_NULLED);
}
}
return(errorclass);
}

View File

@ -1,556 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)input.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
int wordc; /* how long the current error message is */
char **wordv; /* the actual error message */
int nerrors;
int language;
Errorclass onelong();
Errorclass cpp();
Errorclass pccccom(); /* Portable C Compiler C Compiler */
Errorclass richieccom(); /* Richie Compiler for 11 */
Errorclass lint0();
Errorclass lint1();
Errorclass lint2();
Errorclass lint3();
Errorclass make();
Errorclass f77();
Errorclass pi();
Errorclass ri();
Errorclass troff();
Errorclass mod2();
Errorclass catchall __P((void));
/*
* Eat all of the lines in the input file, attempting to categorize
* them by their various flavors
*/
static char inbuffer[BUFSIZ];
void
eaterrors(r_errorc, r_errorv)
int *r_errorc;
Eptr **r_errorv;
{
Errorclass errorclass = C_SYNC;
for (;;){
if (fgets(inbuffer, BUFSIZ, errorfile) == NULL)
break;
wordvbuild(inbuffer, &wordc, &wordv);
/*
* for convience, convert wordv to be 1 based, instead
* of 0 based.
*/
wordv -= 1;
if ( wordc > 0 &&
((( errorclass = onelong() ) != C_UNKNOWN)
|| (( errorclass = cpp() ) != C_UNKNOWN)
|| (( errorclass = pccccom() ) != C_UNKNOWN)
|| (( errorclass = richieccom() ) != C_UNKNOWN)
|| (( errorclass = lint0() ) != C_UNKNOWN)
|| (( errorclass = lint1() ) != C_UNKNOWN)
|| (( errorclass = lint2() ) != C_UNKNOWN)
|| (( errorclass = lint3() ) != C_UNKNOWN)
|| (( errorclass = make() ) != C_UNKNOWN)
|| (( errorclass = f77() ) != C_UNKNOWN)
|| ((errorclass = pi() ) != C_UNKNOWN)
|| (( errorclass = ri() )!= C_UNKNOWN)
|| (( errorclass = mod2() )!= C_UNKNOWN)
|| (( errorclass = troff() )!= C_UNKNOWN))
) ;
else
errorclass = catchall();
if (wordc)
erroradd(wordc, wordv+1, errorclass, C_UNKNOWN);
}
#ifdef FULLDEBUG
printf("%d errorentrys\n", nerrors);
#endif
arrayify(r_errorc, r_errorv, er_head);
}
/*
* create a new error entry, given a zero based array and count
*/
void
erroradd(errorlength, errorv, errorclass, errorsubclass)
int errorlength;
char **errorv;
Errorclass errorclass;
Errorclass errorsubclass;
{
reg Eptr newerror;
reg char *cp;
if (errorclass == C_TRUE){
/* check canonicalization of the second argument*/
for(cp = errorv[1]; *cp && isdigit(*cp); cp++)
continue;
errorclass = (*cp == '\0') ? C_TRUE : C_NONSPEC;
#ifdef FULLDEBUG
if (errorclass != C_TRUE)
printf("The 2nd word, \"%s\" is not a number.\n",
errorv[1]);
#endif
}
if (errorlength > 0){
newerror = (Eptr)Calloc(1, sizeof(Edesc));
newerror->error_language = language; /* language is global */
newerror->error_text = errorv;
newerror->error_lgtext = errorlength;
if (errorclass == C_TRUE)
newerror->error_line = atoi(errorv[1]);
newerror->error_e_class = errorclass;
newerror->error_s_class = errorsubclass;
switch(newerror->error_e_class = discardit(newerror)){
case C_SYNC: nsyncerrors++; break;
case C_DISCARD: ndiscard++; break;
case C_NULLED: nnulled++; break;
case C_NONSPEC: nnonspec++; break;
case C_THISFILE: nthisfile++; break;
case C_TRUE: ntrue++; break;
case C_UNKNOWN: nunknown++; break;
case C_IGNORE: nignore++; break;
}
newerror->error_next = er_head;
er_head = newerror;
newerror->error_no = nerrors++;
} /* length > 0 */
}
Errorclass onelong()
{
char **nwordv;
if ( (wordc == 1) && (language != INLD) ){
/*
* We have either:
* a) file name from cc
* b) Assembler telling world that it is complaining
* c) Noise from make ("Stop.")
* c) Random noise
*/
wordc = 0;
if (strcmp(wordv[1], "Stop.") == 0){
language = INMAKE; return(C_SYNC);
}
if (strcmp(wordv[1], "Assembler:") == 0){
/* assembler always alerts us to what happened*/
language = INAS; return(C_SYNC);
} else
if (strcmp(wordv[1], "Undefined:") == 0){
/* loader complains about unknown symbols*/
language = INLD; return(C_SYNC);
}
if (lastchar(wordv[1]) == ':'){
/* cc tells us what file we are in */
currentfilename = wordv[1];
(void)substitute(currentfilename, ':', '\0');
language = INCC; return(C_SYNC);
}
} else
if ( (wordc == 1) && (language == INLD) ){
nwordv = (char **)Calloc(4, sizeof(char *));
nwordv[0] = "ld:";
nwordv[1] = wordv[1];
nwordv[2] = "is";
nwordv[3] = "undefined.";
wordc = 4;
wordv = nwordv - 1;
return(C_NONSPEC);
} else
if (wordc == 1){
return(C_SYNC);
}
return(C_UNKNOWN);
} /* end of one long */
Errorclass cpp()
{
/*
* Now attempt a cpp error message match
* Examples:
* ./morse.h: 23: undefined control
* morsesend.c: 229: MAGNIBBL: argument mismatch
* morsesend.c: 237: MAGNIBBL: argument mismatch
* test1.c: 6: undefined control
*/
if ( (language != INLD) /* loader errors have almost same fmt*/
&& (lastchar(wordv[1]) == ':')
&& (isdigit(firstchar(wordv[2])))
&& (lastchar(wordv[2]) == ':') ){
language = INCPP;
clob_last(wordv[1], '\0');
clob_last(wordv[2], '\0');
return(C_TRUE);
}
return(C_UNKNOWN);
} /*end of cpp*/
Errorclass pccccom()
{
/*
* Now attempt a ccom error message match:
* Examples:
* "morsesend.c", line 237: operands of & have incompatible types
* "test.c", line 7: warning: old-fashioned initialization: use =
* "subdir.d/foo2.h", line 1: illegal initialization
*/
if ( (firstchar(wordv[1]) == '"')
&& (lastchar(wordv[1]) == ',')
&& (next_lastchar(wordv[1]) == '"')
&& (strcmp(wordv[2],"line") == 0)
&& (isdigit(firstchar(wordv[3])))
&& (lastchar(wordv[3]) == ':') ){
clob_last(wordv[1], '\0'); /* drop last , */
clob_last(wordv[1], '\0'); /* drop last " */
wordv[1]++; /* drop first " */
clob_last(wordv[3], '\0'); /* drop : on line number */
wordv[2] = wordv[1]; /* overwrite "line" */
wordv++; /*compensate*/
wordc--;
currentfilename = wordv[1];
language = INCC;
return(C_TRUE);
}
return(C_UNKNOWN);
} /* end of ccom */
/*
* Do the error message from the Richie C Compiler for the PDP11,
* which has this source:
*
* if (filename[0])
* fprintf(stderr, "%s:", filename);
* fprintf(stderr, "%d: ", line);
*
*/
Errorclass richieccom()
{
reg char *cp;
reg char **nwordv;
char *file;
if (lastchar(wordv[1]) == ':'){
cp = wordv[1] + strlen(wordv[1]) - 1;
while (isdigit(*--cp))
continue;
if (*cp == ':'){
clob_last(wordv[1], '\0'); /* last : */
*cp = '\0'; /* first : */
file = wordv[1];
nwordv = wordvsplice(1, wordc, wordv+1);
nwordv[0] = file;
nwordv[1] = cp + 1;
wordc += 1;
wordv = nwordv - 1;
language = INCC;
currentfilename = wordv[1];
return(C_TRUE);
}
}
return(C_UNKNOWN);
}
Errorclass lint0()
{
reg char **nwordv;
char *line, *file;
/*
* Attempt a match for the new lint style normal compiler
* error messages, of the form
*
* printf("%s(%d): %s\n", filename, linenumber, message);
*/
if (wordc >= 2){
if ( (lastchar(wordv[1]) == ':')
&& (next_lastchar(wordv[1]) == ')')
) {
clob_last(wordv[1], '\0'); /* colon */
if (persperdexplode(wordv[1], &line, &file)){
nwordv = wordvsplice(1, wordc, wordv+1);
nwordv[0] = file; /* file name */
nwordv[1] = line; /* line number */
wordc += 1;
wordv = nwordv - 1;
language = INLINT;
return(C_TRUE);
}
wordv[1][strlen(wordv[1])] = ':';
}
}
return (C_UNKNOWN);
}
Errorclass lint1()
{
char *line1, *line2;
char *file1, *file2;
char **nwordv1, **nwordv2;
/*
* Now, attempt a match for the various errors that lint
* can complain about.
*
* Look first for type 1 lint errors
*/
if (wordc > 1 && strcmp(wordv[wordc-1], "::") == 0){
/*
* %.7s, arg. %d used inconsistently %s(%d) :: %s(%d)
* %.7s value used inconsistently %s(%d) :: %s(%d)
* %.7s multiply declared %s(%d) :: %s(%d)
* %.7s value declared inconsistently %s(%d) :: %s(%d)
* %.7s function value type must be declared before use %s(%d) :: %s(%d)
*/
language = INLINT;
if (wordc > 2
&& (persperdexplode(wordv[wordc], &line2, &file2))
&& (persperdexplode(wordv[wordc-2], &line1, &file1)) ){
nwordv1 = wordvsplice(2, wordc, wordv+1);
nwordv2 = wordvsplice(2, wordc, wordv+1);
nwordv1[0] = file1; nwordv1[1] = line1;
erroradd(wordc+2, nwordv1, C_TRUE, C_DUPL); /* takes 0 based*/
nwordv2[0] = file2; nwordv2[1] = line2;
wordc = wordc + 2;
wordv = nwordv2 - 1; /* 1 based */
return(C_TRUE);
}
}
return(C_UNKNOWN);
} /* end of lint 1*/
Errorclass lint2()
{
char *file;
char *line;
char **nwordv;
/*
* Look for type 2 lint errors
*
* %.7s used( %s(%d) ), but not defined
* %.7s defined( %s(%d) ), but never used
* %.7s declared( %s(%d) ), but never used or defined
*
* bufp defined( "./metric.h"(10) ), but never used
*/
if ( (lastchar(wordv[2]) == '(' /* ')' */ )
&& (strcmp(wordv[4], "),") == 0) ){
language = INLINT;
if (persperdexplode(wordv[3], &line, &file)){
nwordv = wordvsplice(2, wordc, wordv+1);
nwordv[0] = file; nwordv[1] = line;
wordc = wordc + 2;
wordv = nwordv - 1; /* 1 based */
return(C_TRUE);
}
}
return(C_UNKNOWN);
} /* end of lint 2*/
char *Lint31[4] = {"returns", "value", "which", "is"};
char *Lint32[6] = {"value", "is", "used,", "but", "none", "returned"};
Errorclass lint3()
{
if ( (wordvcmp(wordv+2, 4, Lint31) == 0)
|| (wordvcmp(wordv+2, 6, Lint32) == 0) ){
language = INLINT;
return(C_NONSPEC);
}
return(C_UNKNOWN);
}
/*
* Special word vectors for use by F77 recognition
*/
char *F77_fatal[3] = {"Compiler", "error", "line"};
char *F77_error[3] = {"Error", "on", "line"};
char *F77_warning[3] = {"Warning", "on", "line"};
char *F77_no_ass[3] = {"Error.","No","assembly."};
Errorclass
f77()
{
char **nwordv;
/*
* look for f77 errors:
* Error messages from /usr/src/cmd/f77/error.c, with
* these printf formats:
*
* Compiler error line %d of %s: %s
* Error on line %d of %s: %s
* Warning on line %d of %s: %s
* Error. No assembly.
*/
if (wordc == 3 && wordvcmp(wordv+1, 3, F77_no_ass) == 0) {
wordc = 0;
return(C_SYNC);
}
if (wordc < 6)
return(C_UNKNOWN);
if ( (lastchar(wordv[6]) == ':')
&&(
(wordvcmp(wordv+1, 3, F77_fatal) == 0)
|| (wordvcmp(wordv+1, 3, F77_error) == 0)
|| (wordvcmp(wordv+1, 3, F77_warning) == 0) )
){
language = INF77;
nwordv = wordvsplice(2, wordc, wordv+1);
nwordv[0] = wordv[6];
clob_last(nwordv[0],'\0');
nwordv[1] = wordv[4];
wordc += 2;
wordv = nwordv - 1; /* 1 based */
return(C_TRUE);
}
return(C_UNKNOWN);
} /* end of f77 */
char *Make_Croak[3] = {"***", "Error", "code"};
char *Make_NotRemade[5] = {"not", "remade", "because", "of", "errors"};
Errorclass make()
{
if (wordvcmp(wordv+1, 3, Make_Croak) == 0){
language = INMAKE;
return(C_SYNC);
}
if (wordvcmp(wordv+2, 5, Make_NotRemade) == 0){
language = INMAKE;
return(C_SYNC);
}
return(C_UNKNOWN);
}
Errorclass ri()
{
/*
* Match an error message produced by ri; here is the
* procedure yanked from the distributed version of ri
* April 24, 1980.
*
* serror(str, x1, x2, x3)
* char str[];
* char *x1, *x2, *x3;
* {
* extern int yylineno;
*
* putc('"', stdout);
* fputs(srcfile, stdout);
* putc('"', stdout);
* fprintf(stdout, " %d: ", yylineno);
* fprintf(stdout, str, x1, x2, x3);
* fprintf(stdout, "\n");
* synerrs++;
* }
*/
if ( (firstchar(wordv[1]) == '"')
&&(lastchar(wordv[1]) == '"')
&&(lastchar(wordv[2]) == ':')
&&(isdigit(firstchar(wordv[2]))) ){
clob_last(wordv[1], '\0'); /* drop the last " */
wordv[1]++; /* skip over the first " */
clob_last(wordv[2], '\0');
language = INRI;
return(C_TRUE);
}
return(C_UNKNOWN);
}
Errorclass catchall()
{
/*
* Catches random things.
*/
language = INUNKNOWN;
return(C_NONSPEC);
} /* end of catch all*/
Errorclass troff()
{
/*
* troff source error message, from eqn, bib, tbl...
* Just like pcc ccom, except uses `'
*/
if ( (firstchar(wordv[1]) == '`')
&& (lastchar(wordv[1]) == ',')
&& (next_lastchar(wordv[1]) == '\'')
&& (strcmp(wordv[2],"line") == 0)
&& (isdigit(firstchar(wordv[3])))
&& (lastchar(wordv[3]) == ':') ){
clob_last(wordv[1], '\0'); /* drop last , */
clob_last(wordv[1], '\0'); /* drop last " */
wordv[1]++; /* drop first " */
clob_last(wordv[3], '\0'); /* drop : on line number */
wordv[2] = wordv[1]; /* overwrite "line" */
wordv++; /*compensate*/
currentfilename = wordv[1];
language = INTROFF;
return(C_TRUE);
}
return(C_UNKNOWN);
}
Errorclass mod2()
{
/*
* for decwrl modula2 compiler (powell)
*/
if ( ( (strcmp(wordv[1], "!!!") == 0) /* early version */
||(strcmp(wordv[1], "File") == 0)) /* later version */
&& (lastchar(wordv[2]) == ',') /* file name */
&& (strcmp(wordv[3], "line") == 0)
&& (isdigit(firstchar(wordv[4]))) /* line number */
&& (lastchar(wordv[4]) == ':') /* line number */
){
clob_last(wordv[2], '\0'); /* drop last , on file name */
clob_last(wordv[4], '\0'); /* drop last : on line number */
wordv[3] = wordv[2]; /* file name on top of "line" */
wordv += 2;
wordc -= 2;
currentfilename = wordv[1];
language = INMOD2;
return(C_TRUE);
}
return(C_UNKNOWN);
}

View File

@ -1,287 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static const char copyright[] =
"@(#) Copyright (c) 1980, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <ctype.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "error.h"
#include "pathnames.h"
int nerrors = 0;
Eptr er_head;
Eptr *errors;
int nfiles = 0;
Eptr **files; /* array of pointers into errors*/
int language = INCC;
char *currentfilename = "????";
char im_on[] = _PATH_TTY; /* my tty name */
boolean query = FALSE; /* query the operator if touch files */
boolean notouch = FALSE; /* don't touch ANY files */
boolean piflag = FALSE; /* this is not pi */
boolean terse = FALSE; /* Terse output */
char *suffixlist = ".*"; /* initially, can touch any file */
int errorsort __P((const void *, const void *));
void forkvi __P((int, char **));
void try __P((char *, int, char **));
/*
* error [-I ignorename] [-n] [-q] [-t suffixlist] [-s] [-v] [infile]
*
* -T: terse output
*
* -I: the following name, `ignorename' contains a list of
* function names that are not to be treated as hard errors.
* Default: ~/.errorsrc
*
* -n: don't touch ANY files!
*
* -q: The user is to be queried before touching each
* file; if not specified, all files with hard, non
* ignorable errors are touched (assuming they can be).
*
* -t: touch only files ending with the list of suffices, each
* suffix preceded by a dot.
* eg, -t .c.y.l
* will touch only files ending with .c, .y or .l
*
* -s: print a summary of the error's categories.
*
* -v: after touching all files, overlay vi(1), ex(1) or ed(1)
* on top of error, entered in the first file with
* an error in it, with the appropriate editor
* set up to use the "next" command to get the other
* files containing errors.
*
* -p: (obsolete: for older versions of pi without bug
* fix regarding printing out the name of the main file
* with an error in it)
* Take the following argument and use it as the name of
* the pascal source file, suffix .p
*
* -E: show the errors in sorted order; intended for
* debugging.
*
* -S: show the errors in unsorted order
* (as they come from the error file)
*
* infile: The error messages come from this file.
* Default: stdin
*/
int
main(argc, argv)
int argc;
char *argv[];
{
char *cp;
char *ignorename = 0;
int ed_argc;
char **ed_argv; /*return from touchfiles*/
boolean show_errors = FALSE;
boolean Show_Errors = FALSE;
boolean pr_summary = FALSE;
boolean edit_files = FALSE;
errorfile = stdin;
if (argc > 1) for(; (argc > 1) && (argv[1][0] == '-'); argc--, argv++){
for (cp = argv[1] + 1; *cp; cp++) switch(*cp){
default:
warnx("-%c: unknown flag", *cp);
break;
case 'n': notouch = TRUE; break;
case 'q': query = TRUE; break;
case 'S': Show_Errors = TRUE; break;
case 's': pr_summary = TRUE; break;
case 'v': edit_files = TRUE; break;
case 'T': terse = TRUE; break;
case 't':
*cp-- = 0; argv++; argc--;
if (argc > 1){
suffixlist = argv[1];
}
break;
case 'I': /*ignore file name*/
*cp-- = 0; argv++; argc--;
if (argc > 1)
ignorename = argv[1];
break;
}
}
if (notouch)
suffixlist = 0;
if (argc > 1){
if (argc > 3)
errx(3, "only takes 0 or 1 argument");
if ( (errorfile = fopen(argv[1], "r")) == NULL)
errx(4,
"%s: no such file or directory for reading errors",
argv[1]);
}
if ( (queryfile = fopen(im_on, "r")) == NULL){
if (query)
errx(9, "can't open \"%s\" to query the user", im_on);
}
if (signal(SIGINT, onintr) == SIG_IGN)
signal(SIGINT, SIG_IGN);
if (signal(SIGTERM, onintr) == SIG_IGN)
signal(SIGTERM, SIG_IGN);
getignored(ignorename);
eaterrors(&nerrors, &errors);
if (Show_Errors)
printerrors(TRUE, nerrors, errors);
qsort(errors, nerrors, sizeof(Eptr), errorsort);
if (show_errors)
printerrors(FALSE, nerrors, errors);
findfiles(nerrors, errors, &nfiles, &files);
#define P(msg, arg) fprintf(stdout, msg, arg)
if (pr_summary){
if (nunknown)
P("%d Errors are unclassifiable.\n", nunknown);
if (nignore)
P("%d Errors are classifiable, but totally discarded.\n",nignore);
if (nsyncerrors)
P("%d Errors are synchronization errors.\n", nsyncerrors);
if (nignore)
P("%d Errors are discarded because they refer to sacrosinct files.\n", ndiscard);
if (nnulled)
P("%d Errors are nulled because they refer to specific functions.\n", nnulled);
if (nnonspec)
P("%d Errors are not specific to any file.\n", nnonspec);
if (nthisfile)
P("%d Errors are specific to a given file, but not to a line.\n", nthisfile);
if (ntrue)
P("%d Errors are true errors, and can be inserted into the files.\n", ntrue);
}
filenames(nfiles, files);
fflush(stdout);
if (touchfiles(nfiles, files, &ed_argc, &ed_argv) && edit_files)
forkvi(ed_argc, ed_argv);
return(0);
}
void
forkvi(argc, argv)
int argc;
char **argv;
{
if (query){
switch(inquire(terse
? "Edit? "
: "Do you still want to edit the files you touched? ")){
case Q_NO:
case Q_no:
return;
default:
break;
}
}
/*
* ed_agument's first argument is
* a vi/ex compatabile search argument
* to find the first occurance of ###
*/
try("vi", argc, argv);
try("ex", argc, argv);
try("ed", argc-1, argv+1);
fprintf(stdout, "Can't find any editors.\n");
}
void
try(name, argc, argv)
char *name;
int argc;
char **argv;
{
argv[0] = name;
wordvprint(stdout, argc, argv);
fprintf(stdout, "\n");
fflush(stderr);
fflush(stdout);
sleep(2);
if (freopen(im_on, "r", stdin) == NULL)
return;
if (freopen(im_on, "w", stdout) == NULL)
return;
execvp(name, argv);
}
int errorsort(vepp1, vepp2)
const void *vepp1, *vepp2;
{
const Eptr *epp1 = vepp1, *epp2 = vepp2;
reg Eptr ep1, ep2;
int order;
/*
* Sort by:
* 1) synchronization, non specific, discarded errors first;
* 2) nulled and true errors last
* a) grouped by similar file names
* 1) grouped in ascending line number
*/
ep1 = *epp1; ep2 = *epp2;
if (ep1 == 0 || ep2 == 0)
return(0);
if ( (NOTSORTABLE(ep1->error_e_class)) ^ (NOTSORTABLE(ep2->error_e_class))){
return(NOTSORTABLE(ep1->error_e_class) ? -1 : 1);
}
if (NOTSORTABLE(ep1->error_e_class)) /* then both are */
return(ep1->error_no - ep2->error_no);
order = strcmp(ep1->error_text[0], ep2->error_text[0]);
if (order == 0){
return(ep1->error_line - ep2->error_line);
}
return(order);
}

View File

@ -1,43 +0,0 @@
/*
* Copyright (c) 1989, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)pathnames.h 8.1 (Berkeley) 6/6/93
*/
#include <paths.h>
#define IG_FILE1 "llib-lc"
#define IG_FILE2 "llib-port"
#define IG_FILE3 "/usr/lib/llib-lc"
#define IG_FILE4 "/usr/lib/llib-port"
#undef _PATH_TMP
#define _PATH_TMP "/tmp/ErrorXXXXXX"

View File

@ -1,408 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)pi.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "error.h"
extern char *currentfilename;
static char *c_linenumber;
static char *unk_hdr[] = {"In", "program", "???"};
static char **c_header = &unk_hdr[0];
/*
* Attempt to handle error messages produced by pi (and by pc)
*
* problem #1: There is no file name available when a file does not
* use a #include; this will have to be given to error
* in the command line.
* problem #2: pi doesn't always tell you what line number
* a error refers to; for example during the tree
* walk phase of code generation and error detection,
* an error can refer to "variable foo in procedure bletch"
* without giving a line number
* problem #3: line numbers, when available, are attached to
* the source line, along with the source line itself
* These line numbers must be extracted, and
* the source line thrown away.
* problem #4: Some error messages produce more than one line number
* on the same message.
* There are only two (I think):
* %s undefined on line%s
* %s improperly used on line%s
* here, the %s makes line plural or singular.
*
* Here are the error strings used in pi version 1.2 that can refer
* to a file name or line number:
*
* Multiply defined label in case, lines %d and %d
* Goto %s from line %d is into a structured statement
* End matched %s on line %d
* Inserted keyword end matching %s on line %d
*
* Here are the general pi patterns recognized:
* define piptr == -.*^-.*
* define msg = .*
* define digit = [0-9]
* definename = .*
* define date_format letter*3 letter*3 (digit | (digit digit))
* (digit | (digit digit)):digit*2 digit*4
*
* {e,E} (piptr) (msg) Encounter an error during textual scan
* E {digit}* - (msg) Have an error message that refers to a new line
* E - msg Have an error message that refers to current
* function, program or procedure
* (date_format) (name): When switch compilation files
* ... (msg) When refer to the previous line
* 'In' ('procedure'|'function'|'program') (name):
* pi is now complaining about 2nd pass errors.
*
* Here is the output from a compilation
*
*
* 2 var i:integer;
* e --------------^--- Inserted ';'
* E 2 - All variables must be declared in one var part
* E 5 - Include filename must end in .i
* Mon Apr 21 15:56 1980 test.h:
* 2 begin
* e ------^--- Inserted ';'
* Mon Apr 21 16:06 1980 test.p:
* E 2 - Function type must be specified
* 6 procedure foo(var x:real);
* e ------^--- Inserted ';'
* In function bletch:
* E - No assignment to the function variable
* w - variable x is never used
* E 6 - foo is already defined in this block
* In procedure foo:
* w - variable x is neither used nor set
* 9 z : = 23;
* E --------------^--- Undefined variable
* 10 y = [1];
* e ----------------^--- Inserted ':'
* 13 z := 345.;
* e -----------------------^--- Digits required after decimal point
* E 10 - Constant set involved in non set context
* E 11 - Type clash: real is incompatible with integer
* ... Type of expression clashed with type of variable in assignment
* E 12 - Parameter type not identical to type of var parameter x of foo
* In program mung:
* w - variable y is never used
* w - type foo is never used
* w - function bletch is never used
* E - z undefined on lines 9 13
*/
char *Months[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct","Nov", "Dec",
0
};
char *Days[] = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", 0
};
char *Piroutines[] = {
"program", "function", "procedure", 0
};
static boolean structured, multiple;
char *pi_Endmatched[] = {"End", "matched"};
char *pi_Inserted[] = {"Inserted", "keyword", "end", "matching"};
char *pi_multiple[] = {"Mutiply", "defined", "label", "in", "case,", "line"};
char *pi_structured[] = {"is", "into", "a", "structured", "statement"};
char *pi_und1[] = {"undefined", "on", "line"};
char *pi_und2[] = {"undefined", "on", "lines"};
char *pi_imp1[] = {"improperly", "used", "on", "line"};
char *pi_imp2[] = {"improperly", "used", "on", "lines"};
boolean alldigits(string)
reg char *string;
{
for (; *string && isdigit(*string); string++)
continue;
return(*string == '\0');
}
boolean instringset(member, set)
char *member;
reg char **set;
{
for(; *set; set++){
if (strcmp(*set, member) == 0)
return(TRUE);
}
return(FALSE);
}
boolean isdateformat(wordc, wordv)
int wordc;
char **wordv;
{
return(
(wordc == 5)
&& (instringset(wordv[0], Days))
&& (instringset(wordv[1], Months))
&& (alldigits(wordv[2]))
&& (alldigits(wordv[4])) );
}
boolean piptr(string)
reg char *string;
{
if (*string != '-')
return(FALSE);
while (*string && *string == '-')
string++;
if (*string != '^')
return(FALSE);
string++;
while (*string && *string == '-')
string++;
return(*string == '\0');
}
extern int wordc;
extern char **wordv;
Errorclass pi()
{
char **nwordv = NULL;
if (wordc < 2)
return (C_UNKNOWN);
if ( ( strlen(wordv[1]) == 1)
&& ( (wordv[1][0] == 'e') || (wordv[1][0] == 'E') )
&& ( piptr(wordv[2]) )
) {
boolean longpiptr = 0;
/*
* We have recognized a first pass error of the form:
* letter ------^---- message
*
* turn into an error message of the form:
*
* file line 'pascal errortype' letter \n |---- message
* or of the form:
* file line letter |---- message
* when there are strlen("(*[pi]") or more
* preceding '-' on the error pointer.
*
* Where the | is intended to be a down arrow, so that
* the pi error messages can be inserted above the
* line in error, instead of below. (All of the other
* langauges put thier messages before the source line,
* instead of after it as does pi.)
*
* where the pointer to the error has been truncated
* by 6 characters to account for the fact that
* the pointer points into a tab preceded input line.
*/
language = INPI;
(void)substitute(wordv[2], '^', '|');
longpiptr = position(wordv[2],'|') > (6+8);
nwordv = wordvsplice(longpiptr ? 2 : 4, wordc, wordv+1);
nwordv[0] = strsave(currentfilename);
nwordv[1] = strsave(c_linenumber);
if (!longpiptr){
nwordv[2] = "pascal errortype";
nwordv[3] = wordv[1];
nwordv[4] = strsave("%%%\n");
if (strlen(nwordv[5]) > (8-2)) /* this is the pointer */
nwordv[5] += (8-2); /* bump over 6 characters */
}
wordv = nwordv - 1; /* convert to 1 based */
wordc += longpiptr ? 2 : 4;
return(C_TRUE);
}
if ( (wordc >= 4)
&& (strlen(wordv[1]) == 1)
&& ( (*wordv[1] == 'E') || (*wordv[1] == 'w') || (*wordv[1] == 'e') )
&& (alldigits(wordv[2]))
&& (strlen(wordv[3]) == 1)
&& (wordv[3][0] == '-')
){
/*
* Message of the form: letter linenumber - message
* Turn into form: filename linenumber letter - message
*/
language = INPI;
nwordv = wordvsplice(1, wordc, wordv + 1);
nwordv[0] = strsave(currentfilename);
nwordv[1] = wordv[2];
nwordv[2] = wordv[1];
c_linenumber = wordv[2];
wordc += 1;
wordv = nwordv - 1;
return(C_TRUE);
}
if ( (wordc >= 3)
&& (strlen(wordv[1]) == 1)
&& ( (*(wordv[1]) == 'E') || (*(wordv[1]) == 'w') || (*(wordv[1]) == 'e') )
&& (strlen(wordv[2]) == 1)
&& (wordv[2][0] == '-')
) {
/*
* Message of the form: letter - message
* This happens only when we are traversing the tree
* during the second pass of pi, and discover semantic
* errors.
*
* We have already (presumably) saved the header message
* and can now construct a nulled error message for the
* current file.
*
* Turns into a message of the form:
* filename (header) letter - message
*
* First, see if it is a message referring to more than
* one line number. Only of the form:
* %s undefined on line%s
* %s improperly used on line%s
*/
boolean undefined = 0;
int wordindex;
language = INPI;
if ( (undefined = (wordvcmp(wordv+2, 3, pi_und1) == 0) )
|| (undefined = (wordvcmp(wordv+2, 3, pi_und2) == 0) )
|| (wordvcmp(wordv+2, 4, pi_imp1) == 0)
|| (wordvcmp(wordv+2, 4, pi_imp2) == 0)
){
for (wordindex = undefined ? 5 : 6; wordindex <= wordc;
wordindex++){
nwordv = wordvsplice(2, undefined ? 2 : 3, wordv+1);
nwordv[0] = strsave(currentfilename);
nwordv[1] = wordv[wordindex];
if (wordindex != wordc)
erroradd(undefined ? 4 : 5, nwordv,
C_TRUE, C_UNKNOWN);
}
wordc = undefined ? 4 : 5;
wordv = nwordv - 1;
return(C_TRUE);
}
nwordv = wordvsplice(1+3, wordc, wordv+1);
nwordv[0] = strsave(currentfilename);
nwordv[1] = strsave(c_header[0]);
nwordv[2] = strsave(c_header[1]);
nwordv[3] = strsave(c_header[2]);
wordv = nwordv - 1;
wordc += 1 + 3;
return(C_THISFILE);
}
if (strcmp(wordv[1], "...") == 0){
/*
* have a continuation error message
* of the form: ... message
* Turn into form : filename linenumber message
*/
language = INPI;
nwordv = wordvsplice(1, wordc, wordv+1);
nwordv[0] = strsave(currentfilename);
nwordv[1] = strsave(c_linenumber);
wordv = nwordv - 1;
wordc += 1;
return(C_TRUE);
}
if( (wordc == 6)
&& (lastchar(wordv[6]) == ':')
&& (isdateformat(5, wordv + 1))
){
/*
* Have message that tells us we have changed files
*/
language = INPI;
currentfilename = strsave(wordv[6]);
clob_last(currentfilename, '\0');
return(C_SYNC);
}
if( (wordc == 3)
&& (strcmp(wordv[1], "In") == 0)
&& (lastchar(wordv[3]) == ':')
&& (instringset(wordv[2], Piroutines))
) {
language = INPI;
c_header = wordvsplice(0, wordc, wordv+1);
return(C_SYNC);
}
/*
* now, check for just the line number followed by the text
*/
if (alldigits(wordv[1])){
language = INPI;
c_linenumber = wordv[1];
return(C_IGNORE);
}
/*
* Attempt to match messages refering to a line number
*
* Multiply defined label in case, lines %d and %d
* Goto %s from line %d is into a structured statement
* End matched %s on line %d
* Inserted keyword end matching %s on line %d
*/
multiple = structured = 0;
if (
( (wordc == 6) && (wordvcmp(wordv+1, 2, pi_Endmatched) == 0))
|| ( (wordc == 8) && (wordvcmp(wordv+1, 4, pi_Inserted) == 0))
|| ( multiple = ((wordc == 9) && (wordvcmp(wordv+1,6, pi_multiple) == 0) ) )
|| ( structured = ((wordc == 10) && (wordvcmp(wordv+6,5, pi_structured) == 0 ) ))
){
language = INPI;
nwordv = wordvsplice(2, wordc, wordv+1);
nwordv[0] = strsave(currentfilename);
nwordv[1] = structured ? wordv [5] : wordv[wordc];
wordc += 2;
wordv = nwordv - 1;
if (!multiple)
return(C_TRUE);
erroradd(wordc, nwordv, C_TRUE, C_UNKNOWN);
nwordv = wordvsplice(0, wordc, nwordv);
nwordv[1] = wordv[wordc - 2];
return(C_TRUE);
}
return(C_UNKNOWN);
}

View File

@ -1,420 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)subr.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
/*
* Arrayify a list of rules
*/
void
arrayify(e_length, e_array, header)
int *e_length;
Eptr **e_array;
Eptr header;
{
reg Eptr errorp;
reg Eptr *array;
reg int listlength;
reg int listindex;
for (errorp = header, listlength = 0;
errorp; errorp = errorp->error_next, listlength++)
continue;
array = (Eptr*)Calloc(listlength+1, sizeof (Eptr));
for(listindex = 0, errorp = header;
listindex < listlength;
listindex++, errorp = errorp->error_next){
array[listindex] = errorp;
errorp->error_position = listindex;
}
array[listindex] = (Eptr)0;
*e_length = listlength;
*e_array = array;
}
/*ARGSUSED*/
char *Calloc(nelements, size)
int nelements;
int size;
{
char *back;
if ( (back = (char *)calloc(nelements, size)) == (char *)NULL)
errx(6, "ran out of memory");
return(back);
}
char *strsave(instring)
char *instring;
{
char *outstring;
(void)strcpy(outstring = (char *)Calloc(1, strlen(instring) + 1),
instring);
return(outstring);
}
/*
* find the position of a given character in a string
* (one based)
*/
int position(string, ch)
reg char *string;
reg char ch;
{
reg int i;
if (string)
for (i=1; *string; string++, i++){
if (*string == ch)
return(i);
}
return(-1);
}
/*
* clobber the first occurance of ch in string by the new character
*/
char *substitute(string, chold, chnew)
char *string;
char chold, chnew;
{
reg char *cp = string;
if (cp)
while (*cp){
if (*cp == chold){
*cp = chnew;
break;
}
cp++;
}
return(string);
}
char lastchar(string)
char *string;
{
int length;
if (string == 0) return('\0');
length = strlen(string);
if (length >= 1)
return(string[length-1]);
else
return('\0');
}
char firstchar(string)
char *string;
{
if (string)
return(string[0]);
else
return('\0');
}
char next_lastchar(string)
char *string;
{
int length;
if (string == 0) return('\0');
length = strlen(string);
if (length >= 2)
return(string[length - 2]);
else
return('\0');
}
void
clob_last(string, newstuff)
char *string, newstuff;
{
int length = 0;
if (string)
length = strlen(string);
if (length >= 1)
string[length - 1] = newstuff;
}
/*
* parse a string that is the result of a format %s(%d)
* return TRUE if this is of the proper format
*/
boolean persperdexplode(string, r_perd, r_pers)
char *string;
char **r_perd, **r_pers;
{
reg char *cp;
int length = 0;
if (string)
length = strlen(string);
if ( (length >= 4)
&& (string[length - 1] == ')' ) ){
for (cp = &string[length - 2];
(isdigit(*cp)) && (*cp != '(');
--cp)
continue;
if (*cp == '('){
string[length - 1] = '\0'; /* clobber the ) */
*r_perd = strsave(cp+1);
string[length - 1] = ')';
*cp = '\0'; /* clobber the ( */
*r_pers = strsave(string);
*cp = '(';
return(TRUE);
}
}
return(FALSE);
}
/*
* parse a quoted string that is the result of a format \"%s\"(%d)
* return TRUE if this is of the proper format
*/
boolean qpersperdexplode(string, r_perd, r_pers)
char *string;
char **r_perd, **r_pers;
{
reg char *cp;
int length = 0;
if (string)
length = strlen(string);
if ( (length >= 4)
&& (string[length - 1] == ')' ) ){
for (cp = &string[length - 2];
(isdigit(*cp)) && (*cp != '(');
--cp)
continue;
if (*cp == '(' && *(cp - 1) == '"'){
string[length - 1] = '\0';
*r_perd = strsave(cp+1);
string[length - 1] = ')';
*(cp - 1) = '\0'; /* clobber the " */
*r_pers = strsave(string + 1);
*(cp - 1) = '"';
return(TRUE);
}
}
return(FALSE);
}
static char cincomment[] = CINCOMMENT;
static char coutcomment[] = COUTCOMMENT;
static char fincomment[] = FINCOMMENT;
static char foutcomment[] = FOUTCOMMENT;
static char newline[] = NEWLINE;
static char piincomment[] = PIINCOMMENT;
static char pioutcomment[] = PIOUTCOMMENT;
static char lispincomment[] = LISPINCOMMENT;
static char riincomment[] = RIINCOMMENT;
static char rioutcomment[] = RIOUTCOMMENT;
static char troffincomment[] = TROFFINCOMMENT;
static char troffoutcomment[] = TROFFOUTCOMMENT;
static char mod2incomment[] = MOD2INCOMMENT;
static char mod2outcomment[] = MOD2OUTCOMMENT;
struct lang_desc lang_table[] = {
/*INUNKNOWN 0*/ {"unknown", cincomment, coutcomment},
/*INCPP 1*/ {"cpp", cincomment, coutcomment},
/*INCC 2*/ {"cc", cincomment, coutcomment},
/*INAS 3*/ {"as", ASINCOMMENT, newline},
/*INLD 4*/ {"ld", cincomment, coutcomment},
/*INLINT 5*/ {"lint", cincomment, coutcomment},
/*INF77 6*/ {"f77", fincomment, foutcomment},
/*INPI 7*/ {"pi", piincomment, pioutcomment},
/*INPC 8*/ {"pc", piincomment, pioutcomment},
/*INFRANZ 9*/ {"franz",lispincomment, newline},
/*INLISP 10*/ {"lisp", lispincomment, newline},
/*INVAXIMA 11*/ {"vaxima",lispincomment,newline},
/*INRATFOR 12*/ {"ratfor",fincomment, foutcomment},
/*INLEX 13*/ {"lex", cincomment, coutcomment},
/*INYACC 14*/ {"yacc", cincomment, coutcomment},
/*INAPL 15*/ {"apl", ".lm", newline},
/*INMAKE 16*/ {"make", ASINCOMMENT, newline},
/*INRI 17*/ {"ri", riincomment, rioutcomment},
/*INTROFF 18*/ {"troff",troffincomment,troffoutcomment},
/*INMOD2 19*/ {"mod2", mod2incomment, mod2outcomment},
{0, 0, 0}
};
void
printerrors(look_at_subclass, errorc, errorv)
boolean look_at_subclass;
int errorc;
Eptr errorv[];
{
reg int i;
reg Eptr errorp;
for (errorp = errorv[i = 0]; i < errorc; errorp = errorv[++i]){
if (errorp->error_e_class == C_IGNORE)
continue;
if (look_at_subclass && errorp->error_s_class == C_DUPL)
continue;
printf("Error %d, (%s error) [%s], text = \"",
i,
class_table[errorp->error_e_class],
lang_table[errorp->error_language].lang_name);
wordvprint(stdout,errorp->error_lgtext,errorp->error_text);
printf("\"\n");
}
}
void
wordvprint(fyle, wordc, wordv)
FILE *fyle;
int wordc;
char *wordv[];
{
int i;
char *sep = "";
for(i = 0; i < wordc; i++)
if (wordv[i]) {
fprintf(fyle, "%s%s",sep,wordv[i]);
sep = " ";
}
}
/*
* Given a string, parse it into a number of words, and build
* a wordc wordv combination pointing into it.
*/
void
wordvbuild(string, r_wordc, r_wordv)
char *string;
int *r_wordc;
char ***r_wordv;
{
reg char *cp;
char *saltedbuffer;
char **wordv;
int wordcount;
int wordindex;
saltedbuffer = strsave(string);
for (wordcount = 0, cp = saltedbuffer; *cp; wordcount++){
while (*cp && isspace(*cp))
cp++;
if (*cp == 0)
break;
while (!isspace(*cp))
cp++;
}
wordv = (char **)Calloc(wordcount + 1, sizeof (char *));
for (cp=saltedbuffer,wordindex=0; wordcount; wordindex++,--wordcount){
while (*cp && isspace(*cp))
cp++;
if (*cp == 0)
break;
wordv[wordindex] = cp;
while(!isspace(*cp))
cp++;
*cp++ = '\0';
}
if (wordcount != 0)
errx(6, "initial miscount of the number of words in a line");
wordv[wordindex] = (char *)0;
#ifdef FULLDEBUG
for (wordcount = 0; wordcount < wordindex; wordcount++)
printf("Word %d = \"%s\"\n", wordcount, wordv[wordcount]);
printf("\n");
#endif
*r_wordc = wordindex;
*r_wordv = wordv;
}
/*
* Compare two 0 based wordvectors
*/
int wordvcmp(wordv1, wordc, wordv2)
char **wordv1;
int wordc;
char **wordv2;
{
reg int i;
int back;
for (i = 0; i < wordc; i++){
if (wordv1[i] == 0 || wordv2[i] == 0)
return(-1);
if ((back = strcmp(wordv1[i], wordv2[i]))){
return(back);
}
}
return(0); /* they are equal */
}
/*
* splice a 0 basedword vector onto the tail of a
* new wordv, allowing the first emptyhead slots to be empty
*/
char **wordvsplice(emptyhead, wordc, wordv)
int emptyhead;
int wordc;
char **wordv;
{
reg char **nwordv;
int nwordc = emptyhead + wordc;
reg int i;
nwordv = (char **)Calloc(nwordc, sizeof (char *));
for (i = 0; i < emptyhead; i++)
nwordv[i] = 0;
for(i = emptyhead; i < nwordc; i++){
nwordv[i] = wordv[i-emptyhead];
}
return(nwordv);
}
/*
* plural'ize and verb forms
*/
static char *S = "s";
static char *N = "";
char *plural(n)
int n;
{
return( n > 1 ? S : N);
}
char *verbform(n)
int n;
{
return( n > 1 ? N : S);
}

View File

@ -1,800 +0,0 @@
/*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
#if 0
static char sccsid[] = "@(#)touch.c 8.1 (Berkeley) 6/6/93";
#endif
static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <ctype.h>
#include <err.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "error.h"
#include "pathnames.h"
/*
* Iterate through errors
*/
#define EITERATE(p, fv, i) for (p = fv[i]; p < fv[i+1]; p++)
#define ECITERATE(ei, p, lb) for (ei = lb; p = errors[ei],ei < nerrors; ei++)
#define FILEITERATE(fi, lb) for (fi = lb; fi <= nfiles; fi++)
int touchstatus = Q_YES;
int countfiles __P((Eptr *));
boolean edit __P((char *));
void errorprint __P((FILE *, Eptr, boolean));
void execvarg __P((int, int *, char ***));
void diverterrors __P((char *, int, Eptr **, int, boolean, int));
void hackfile __P((char *, Eptr **, int, int));
void insert __P((int));
int mustoverwrite __P((FILE *, FILE *));
int mustwrite __P((char *, int, FILE *));
int nopertain __P((Eptr **));
int oktotouch __P((char *));
boolean preview __P((char *, int, Eptr **, int));
int settotouch __P((char *));
void text __P((Eptr, boolean));
boolean writetouched __P((int));
void
findfiles(nerrors, errors, r_nfiles, r_files)
int nerrors;
Eptr *errors;
int *r_nfiles;
Eptr ***r_files;
{
int nfiles;
Eptr **files;
char *name;
reg int ei;
int fi;
reg Eptr errorp;
nfiles = countfiles(errors);
files = (Eptr**)Calloc(nfiles + 3, sizeof (Eptr*));
touchedfiles = (boolean *)Calloc(nfiles+3, sizeof(boolean));
/*
* Now, partition off the error messages
* into those that are synchronization, discarded or
* not specific to any file, and those that were
* nulled or true errors.
*/
files[0] = &errors[0];
ECITERATE(ei, errorp, 0){
if ( ! (NOTSORTABLE(errorp->error_e_class)))
break;
}
/*
* Now, and partition off all error messages
* for a given file.
*/
files[1] = &errors[ei];
touchedfiles[0] = touchedfiles[1] = FALSE;
name = "\1";
fi = 1;
ECITERATE(ei, errorp, ei){
if ( (errorp->error_e_class == C_NULLED)
|| (errorp->error_e_class == C_TRUE) ){
if (strcmp(errorp->error_text[0], name) != 0){
name = errorp->error_text[0];
touchedfiles[fi] = FALSE;
files[fi] = &errors[ei];
fi++;
}
}
}
files[fi] = &errors[nerrors];
*r_nfiles = nfiles;
*r_files = files;
}
int countfiles(errors)
Eptr *errors;
{
char *name;
int ei;
reg Eptr errorp;
int nfiles;
nfiles = 0;
name = "\1";
ECITERATE(ei, errorp, 0){
if (SORTABLE(errorp->error_e_class)){
if (strcmp(errorp->error_text[0],name) != 0){
nfiles++;
name = errorp->error_text[0];
}
}
}
return(nfiles);
}
char *class_table[] = {
/*C_UNKNOWN 0 */ "Unknown",
/*C_IGNORE 1 */ "ignore",
/*C_SYNC 2 */ "synchronization",
/*C_DISCARD 3 */ "discarded",
/*C_NONSPEC 4 */ "non specific",
/*C_THISFILE 5 */ "specific to this file",
/*C_NULLED 6 */ "nulled",
/*C_TRUE 7 */ "true",
/*C_DUPL 8 */ "duplicated"
};
int class_count[C_LAST - C_FIRST] = {0};
void
filenames(nfiles, files)
int nfiles;
Eptr **files;
{
reg int fi;
char *sep = " ";
extern char *class_table[];
int someerrors;
/*
* first, simply dump out errors that
* don't pertain to any file
*/
someerrors = nopertain(files);
if (nfiles){
someerrors++;
fprintf(stdout, terse
? "%d file%s"
: "%d file%s contain%s errors",
nfiles, plural(nfiles), verbform(nfiles));
if (!terse){
FILEITERATE(fi, 1){
fprintf(stdout, "%s\"%s\" (%d)",
sep, (*files[fi])->error_text[0],
files[fi+1] - files[fi]);
sep = ", ";
}
}
fprintf(stdout, "\n");
}
if (!someerrors)
fprintf(stdout, "No errors.\n");
}
/*
* Dump out errors that don't pertain to any file
*/
int nopertain(files)
Eptr **files;
{
int type;
int someerrors = 0;
reg Eptr *erpp;
reg Eptr errorp;
if (files[1] - files[0] <= 0)
return(0);
for(type = C_UNKNOWN; NOTSORTABLE(type); type++){
if (class_count[type] <= 0)
continue;
if (type > C_SYNC)
someerrors++;
if (terse){
fprintf(stdout, "\t%d %s errors NOT PRINTED\n",
class_count[type], class_table[type]);
} else {
fprintf(stdout, "\n\t%d %s errors follow\n",
class_count[type], class_table[type]);
EITERATE(erpp, files, 0){
errorp = *erpp;
if (errorp->error_e_class == type){
errorprint(stdout, errorp, TRUE);
}
}
}
}
return(someerrors);
}
extern boolean notouch;
boolean touchfiles(nfiles, files, r_edargc, r_edargv)
int nfiles;
Eptr **files;
int *r_edargc;
char ***r_edargv;
{
char *name;
reg Eptr errorp;
reg int fi;
reg Eptr *erpp;
int ntrueerrors;
boolean scribbled;
int n_pissed_on; /* # of file touched*/
int spread;
FILEITERATE(fi, 1){
name = (*files[fi])->error_text[0];
spread = files[fi+1] - files[fi];
fprintf(stdout, terse
? "\"%s\" has %d error%s, "
: "\nFile \"%s\" has %d error%s.\n"
, name ,spread ,plural(spread));
/*
* First, iterate through all error messages in this file
* to see how many of the error messages really will
* get inserted into the file.
*/
ntrueerrors = 0;
EITERATE(erpp, files, fi){
errorp = *erpp;
if (errorp->error_e_class == C_TRUE)
ntrueerrors++;
}
fprintf(stdout, terse
? "insert %d\n"
: "\t%d of these errors can be inserted into the file.\n",
ntrueerrors);
hackfile(name, files, fi, ntrueerrors);
}
scribbled = FALSE;
n_pissed_on = 0;
FILEITERATE(fi, 1){
scribbled |= touchedfiles[fi];
n_pissed_on++;
}
if (scribbled){
/*
* Construct an execv argument
*/
execvarg(n_pissed_on, r_edargc, r_edargv);
return(TRUE);
} else {
if (!terse)
fprintf(stdout, "You didn't touch any files.\n");
return(FALSE);
}
}
void
hackfile(name, files, ix, nerrors)
char *name;
Eptr **files;
int ix;
{
boolean previewed;
int errordest; /* where errors go */
if (!oktotouch(name)) {
previewed = FALSE;
errordest = TOSTDOUT;
} else {
previewed = preview(name, nerrors, files, ix);
errordest = settotouch(name);
}
if (errordest != TOSTDOUT)
touchedfiles[ix] = TRUE;
if (previewed && (errordest == TOSTDOUT))
return;
diverterrors(name, errordest, files, ix, previewed, nerrors);
if (errordest == TOTHEFILE){
/*
* overwrite the original file
*/
writetouched(1);
}
}
boolean preview(name, nerrors, files, ix)
char *name;
int nerrors;
Eptr **files;
int ix;
{
int back;
reg Eptr *erpp;
if (nerrors <= 0)
return(FALSE);
back = FALSE;
if(query){
switch(inquire(terse
? "Preview? "
: "Do you want to preview the errors first? ")){
case Q_YES:
case Q_yes:
back = TRUE;
EITERATE(erpp, files, ix){
errorprint(stdout, *erpp, TRUE);
}
if (!terse)
fprintf(stdout, "\n");
default:
break;
}
}
return(back);
}
int settotouch(name)
char *name;
{
int dest = TOSTDOUT;
if (query){
switch(touchstatus = inquire(terse
? "Touch? "
: "Do you want to touch file \"%s\"? ",
name)){
case Q_NO:
case Q_no:
return(dest);
default:
break;
}
}
switch(probethisfile(name)){
case F_NOTREAD:
dest = TOSTDOUT;
fprintf(stdout, terse
? "\"%s\" unreadable\n"
: "File \"%s\" is unreadable\n",
name);
break;
case F_NOTWRITE:
dest = TOSTDOUT;
fprintf(stdout, terse
? "\"%s\" unwritable\n"
: "File \"%s\" is unwritable\n",
name);
break;
case F_NOTEXIST:
dest = TOSTDOUT;
fprintf(stdout, terse
? "\"%s\" not found\n"
: "Can't find file \"%s\" to insert error messages into.\n",
name);
break;
default:
dest = edit(name) ? TOSTDOUT : TOTHEFILE;
break;
}
return(dest);
}
void
diverterrors(name, dest, files, ix, previewed, nterrors)
char *name;
int dest;
Eptr **files;
int ix;
boolean previewed;
int nterrors;
{
int nerrors;
reg Eptr *erpp;
reg Eptr errorp;
nerrors = files[ix+1] - files[ix];
if ( (nerrors != nterrors)
&& (!previewed) ){
fprintf(stdout, terse
? "Uninserted errors\n"
: ">>Uninserted errors for file \"%s\" follow.\n",
name);
}
EITERATE(erpp, files, ix){
errorp = *erpp;
if (errorp->error_e_class != C_TRUE){
if (previewed || touchstatus == Q_NO)
continue;
errorprint(stdout, errorp, TRUE);
continue;
}
switch (dest){
case TOSTDOUT:
if (previewed || touchstatus == Q_NO)
continue;
errorprint(stdout,errorp, TRUE);
break;
case TOTHEFILE:
insert(errorp->error_line);
text(errorp, FALSE);
break;
}
}
}
int oktotouch(filename)
char *filename;
{
extern char *suffixlist;
reg char *src;
reg char *pat;
char *osrc;
pat = suffixlist;
if (pat == 0)
return(0);
if (*pat == '*')
return(1);
while (*pat++ != '.')
continue;
--pat; /* point to the period */
for (src = &filename[strlen(filename)], --src;
(src > filename) && (*src != '.'); --src)
continue;
if (*src != '.')
return(0);
for (src++, pat++, osrc = src; *src && *pat; src = osrc, pat++){
for (; *src /* not at end of the source */
&& *pat /* not off end of pattern */
&& *pat != '.' /* not off end of sub pattern */
&& *pat != '*' /* not wild card */
&& *src == *pat; /* and equal... */
src++, pat++)
continue;
if (*src == 0 && (*pat == 0 || *pat == '.' || *pat == '*'))
return(1);
if (*src != 0 && *pat == '*')
return(1);
while (*pat && *pat != '.')
pat++;
if (! *pat)
return(0);
}
return(0);
}
/*
* Construct an execv argument
* We need 1 argument for the editor's name
* We need 1 argument for the initial search string
* We need n_pissed_on arguments for the file names
* We need 1 argument that is a null for execv.
* The caller fills in the editor's name.
* We fill in the initial search string.
* We fill in the arguments, and the null.
*/
void
execvarg(n_pissed_on, r_argc, r_argv)
int n_pissed_on;
int *r_argc;
char ***r_argv;
{
Eptr p;
char *sep = NULL;
int fi;
(*r_argv) = (char **)Calloc(n_pissed_on + 3, sizeof(char *));
(*r_argc) = n_pissed_on + 2;
(*r_argv)[1] = "+1;/###/";
n_pissed_on = 2;
if (!terse){
fprintf(stdout, "You touched file(s):");
sep = " ";
}
FILEITERATE(fi, 1){
if (!touchedfiles[fi])
continue;
p = *(files[fi]);
if (!terse){
fprintf(stdout,"%s\"%s\"", sep, p->error_text[0]);
sep = ", ";
}
(*r_argv)[n_pissed_on++] = p->error_text[0];
}
if (!terse)
fprintf(stdout, "\n");
(*r_argv)[n_pissed_on] = 0;
}
FILE *o_touchedfile; /* the old file */
FILE *n_touchedfile; /* the new file */
char *o_name;
char n_name[MAXPATHLEN];
char *canon_name = _PATH_TMP;
int o_lineno;
int n_lineno;
boolean tempfileopen = FALSE;
/*
* open the file; guaranteed to be both readable and writable
* Well, if it isn't, then return TRUE if something failed
*/
boolean edit(name)
char *name;
{
int fd;
o_name = name;
if ( (o_touchedfile = fopen(name, "r")) == NULL){
warnx("can't open file \"%s\" to touch (read)", name);
return(TRUE);
}
(void)strcpy(n_name, canon_name);
(void)strcat(n_name,"error.XXXXXX");
fd = mkstemp(n_name);
if ( fd < 0 || (n_touchedfile = fdopen(fd, "w")) == NULL) {
if (fd >= 0)
close(fd);
warnx("can't open file \"%s\" to touch (write)", name);
return(TRUE);
}
tempfileopen = TRUE;
n_lineno = 0;
o_lineno = 0;
return(FALSE);
}
/*
* Position to the line (before, after) the line given by place
*/
char edbuf[BUFSIZ];
void
insert(place)
int place;
{
--place; /* always insert messages before the offending line*/
for(; o_lineno < place; o_lineno++, n_lineno++){
if(fgets(edbuf, BUFSIZ, o_touchedfile) == NULL)
return;
fputs(edbuf, n_touchedfile);
}
}
void
text(p, use_all)
reg Eptr p;
boolean use_all;
{
int offset = use_all ? 0 : 2;
fputs(lang_table[p->error_language].lang_incomment, n_touchedfile);
fprintf(n_touchedfile, "%d [%s] ",
p->error_line,
lang_table[p->error_language].lang_name);
wordvprint(n_touchedfile, p->error_lgtext-offset, p->error_text+offset);
fputs(lang_table[p->error_language].lang_outcomment,n_touchedfile);
n_lineno++;
}
/*
* write the touched file to its temporary copy,
* then bring the temporary in over the local file
*/
boolean
writetouched(overwrite)
int overwrite;
{
reg int nread;
reg FILE *localfile;
reg FILE *tmpfile;
int botch;
int oktorm;
botch = 0;
oktorm = 1;
while((nread = fread(edbuf, 1, sizeof(edbuf), o_touchedfile)) != 0) {
if (nread != fwrite(edbuf, 1, nread, n_touchedfile)){
/*
* Catastrophe in temporary area: file system full?
*/
botch = 1;
warnx("write failure: no errors inserted in \"%s\"",
o_name);
}
}
fclose(n_touchedfile);
fclose(o_touchedfile);
/*
* Now, copy the temp file back over the original
* file, thus preserving links, etc
*/
if (botch == 0 && overwrite){
botch = 0;
localfile = NULL;
tmpfile = NULL;
if ((localfile = fopen(o_name, "w")) == NULL){
warnx("can't open file \"%s\" to overwrite", o_name);
botch++;
}
if ((tmpfile = fopen(n_name, "r")) == NULL){
warnx("can't open file \"%s\" to read", n_name);
botch++;
}
if (!botch)
oktorm = mustoverwrite(localfile, tmpfile);
if (localfile != NULL)
fclose(localfile);
if (tmpfile != NULL)
fclose(tmpfile);
}
if (oktorm == 0)
errx(1, "catastrophe: a copy of \"%s\" was saved in \"%s\"",
o_name, n_name);
/*
* Kiss the temp file good bye
*/
unlink(n_name);
tempfileopen = FALSE;
return(TRUE);
}
/*
* return 1 if the tmpfile can be removed after writing it out
*/
int
mustoverwrite(preciousfile, tmpfile)
FILE *preciousfile;
FILE *tmpfile;
{
int nread;
while((nread = fread(edbuf, 1, sizeof(edbuf), tmpfile)) != 0) {
if (mustwrite(edbuf, nread, preciousfile) == 0)
return(0);
}
return(1);
}
/*
* return 0 on catastrophe
*/
int
mustwrite(base, n, preciousfile)
char *base;
int n;
FILE *preciousfile;
{
int nwrote;
if (n <= 0)
return(1);
nwrote = fwrite(base, 1, n, preciousfile);
if (nwrote == n)
return(1);
warn("fwrite");
switch(inquire(terse
? "Botch overwriting: retry? "
: "Botch overwriting the source file: retry? ")){
case Q_YES:
case Q_yes:
mustwrite(base + nwrote, n - nwrote, preciousfile);
return(1);
case Q_NO:
case Q_no:
switch(inquire("Are you sure? ")){
case Q_YES:
case Q_yes:
return(0);
case Q_NO:
case Q_no:
mustwrite(base + nwrote, n - nwrote, preciousfile);
return(1);
}
default:
return(0);
}
}
void
onintr(sig)
int sig;
{
switch(inquire(terse
? "\nContinue? "
: "\nInterrupt: Do you want to continue? ")){
case Q_YES:
case Q_yes:
signal(SIGINT, onintr);
return;
default:
if (tempfileopen){
/*
* Don't overwrite the original file!
*/
writetouched(0);
}
exit(1);
}
/*NOTREACHED*/
}
void
errorprint(place, errorp, print_all)
FILE *place;
Eptr errorp;
boolean print_all;
{
int offset = print_all ? 0 : 2;
if (errorp->error_e_class == C_IGNORE)
return;
fprintf(place, "[%s] ", lang_table[errorp->error_language].lang_name);
wordvprint(place,errorp->error_lgtext-offset,errorp->error_text+offset);
putc('\n', place);
}
int inquire(fmt, a1, a2)
char *fmt;
/*VARARGS1*/
{
char buffer[128];
if (queryfile == NULL)
return(0);
for(;;){
do{
fflush(stdout);
fprintf(stderr, fmt, a1, a2);
fflush(stderr);
} while (fgets(buffer, 127, queryfile) == NULL);
switch(buffer[0]){
case 'Y': return(Q_YES);
case 'y': return(Q_yes);
case 'N': return(Q_NO);
case 'n': return(Q_no);
default: fprintf(stderr, "Yes or No only!\n");
}
}
}
int probethisfile(name)
char *name;
{
struct stat statbuf;
if (stat(name, &statbuf) < 0)
return(F_NOTEXIST);
if((statbuf.st_mode & S_IREAD) == 0)
return(F_NOTREAD);
if((statbuf.st_mode & S_IWRITE) == 0)
return(F_NOTWRITE);
return(F_TOUCHIT);
}