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:
parent
5792b7fe0b
commit
f1b5e7b750
@ -38,7 +38,6 @@ SUBDIR= apply \
|
||||
ee \
|
||||
enigma \
|
||||
env \
|
||||
error \
|
||||
expand \
|
||||
false \
|
||||
fetch \
|
||||
|
@ -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>
|
@ -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.
|
@ -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 *[]));
|
||||
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
@ -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"
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user