ve - An interactive viewer of programming errors
Joseph Kam
joseph at cadvaxoz.eecs.unsw.oz
Thu Aug 7 13:34:00 AEST 1986
This is a very versatile little program which allows the rapid
positioning to the error lines specified in the error file one after
the other, and if possible, prints the corresponding error
message on the terminal's status line. The error file may contain
errors output from cc(1), ld(1), lint(1), cyntax(1) and make(1).
It should be able to run on both System V and BSD4.2 systems.
The program uses terminfo(4) to print out error messages to the status
line of a terminal. If you do not have terminfo, then just do not
define TERMINFO in the Makefile. In this case, the error message will
not be displayed on the status line of your terminal. As the program
only do a heuristic parsing of the form of error messages given out
from cc, ld, lint, cyntax, and make from our UNSW Unix System (which
is a mixture or a mess of Version 7, System 5, and BSD4.2 with
significant local hacks), it may not able to recognise error messages
in a different format. But you can look into the individual parser
and do necessary changes or rewrite to make it work on your system.
You are free to change the program, but if you have extended its
capabilities like able to recognise error messages from yacc, lex,
awk, grep, etc., please send a copy back to me. For sending flame,
please direct to /dev/null and hopefully I may get it (you never know)
or just do a '/bin/rm *' if that will make you feel happier. Anyway,
enjoy it.
Ming Chi Kam ISD: +61 2 697-4056
University of NSW, STD: (02) 697-4056
P.O. Box 1, Kensington, ARPA: joseph%cadvax.oz at seismo.arpa
Sydney, NSW, 2033, UUCP: seismo!munnari!cadvax.oz!joseph
AUSTRALIA. ACSnet: joseph at cadvax.oz
------- CUT HERE ----------- CUT HERE ----------- CUT HERE ----
# Shell Archive created by cadvax! at Thu Aug 7 12:00:29 1986
# To unpack the enclosed files, please use this file as input to the
# Bourne (sh) shell. This can be most easily done by the command;
# sh < thisfilename
# This archive contains;
# ve.1 Makefile cctag.c cyntag.c etag.c ldtag.c lintag.c
# ---------- file ve.1 ----------
filename="ve.1"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file ve.1...
fi
cat << 'END-OF-FILE' > $filename
.TH VE 1
.SH NAME
ve \- an interactive viewer of programming errors
.SH SYNOPSIS
.B ve file
.SH DESCRIPTION
.I Ve
accepts only one argument which is the name of the file containing
errors output from cc, ld, lint, cyntax and make. With the automatic
invocation of the
screen editor - vi,
.I ve
allows the rapid positioning to the error lines specified
in the error file one after the other, and if possible,
prints the corresponding error message on the terminal's status line.
Three commands may be typed when in the vi editor to browse through the
error lines.
.P
.in +10
^A \(em go to next error line,
.br
^Z \(em go back to the last error line, and
.br
^C \(em go to the current error line.
.in -10
.SH ARTHOR
Ming Chi, Kam (joseph at cadvax.unsw.oz)
.SH BUGS
As users may change the contents of the file, so
.I ve
does not rely on the line number specified in the error file to
position the cursor to the line which may cause the error. Instead,
.I ve
uses a pattern matching method to try to match the original line pattern
before invoking vi, with the same file, after being possibly changed.
As a result, there may be a chance, possibly very slight, that the file
contains more than one line with the same pattern and incidently,
.I ve
positions to the wrong one. So users are advised to compare the line number
in the error message with the line number of error line positioned by
.I ve
in cases where the users have some doubts as a result of their big
difference or no error can be spotted. In both cases, the command n or N
may be typed to see if any other match can be found.
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 1600 ]
then
echo $filename changed - should be 1600 bytes, not $size bytes
fi
chmod 600 $filename
fi
# ---------- file Makefile ----------
filename="Makefile"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file Makefile...
fi
cat << 'END-OF-FILE' > $filename
# Define GETLOGIN if you do not have getlogin(3C) call
# Define TMPFILE if you do not have tmpfile(3C) call
# Define BSD if you use index(3C) call instead of strchr(3C)
# Define TERMINFO only if your system supports terminfo(4).
CFLAGS= -O
LINKFLAGS= -n
CC= cc
CFILES= cctag.c cyntag.c etag.c ldtag.c lintag.c
OBJECTS= cctag.o cyntag.o etag.o ldtag.o lintag.o
# Use -lterminfo if you do not have -lcurses
LIBS= -lcurses
ve: $(OBJECTS)
$(CC) $(LINKFLAGS) -o ve $(OBJECTS) $(LIBS)
.c.o:
$(CC) $(CFLAGS) -c $*.c
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 462 ]
then
echo $filename changed - should be 462 bytes, not $size bytes
fi
chmod 600 $filename
fi
# ---------- file cctag.c ----------
filename="cctag.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file cctag.c...
fi
cat << 'END-OF-FILE' > $filename
#include <stdio.h>
int makecctag(infp, outfp)
FILE *infp ;
FILE *outfp ;
{
int find = 0 ;
char lbuf[512] ;
while (fgets(lbuf, 512, infp) != NULL)
{
if (*lbuf == '"' )
{
fputs(lbuf, outfp) ;
find = 1 ;
}
}
return(find) ;
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 253 ]
then
echo $filename changed - should be 253 bytes, not $size bytes
fi
chmod 600 $filename
fi
# ---------- file cyntag.c ----------
filename="cyntag.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file cyntag.c...
fi
cat << 'END-OF-FILE' > $filename
#include <stdio.h>
static int line ;
static FILE *outfp ;
static FILE *infp ;
static char mesg[254] ;
static char filename[100] ;
int makecyntag(infilep, outfilep)
FILE *infilep ;
FILE *outfilep ;
{
int find = 0 ;
char lbuf[512] ;
infp = infilep ;
outfp = outfilep ;
while (fgets(lbuf, 512, infp) != NULL)
{
switch ( CynMatch1(lbuf) )
{
case 1 :
find = 1 ;
break ;
case -1 :
return(0) ;
case 0 :
switch (CynMatch2(lbuf) )
{
case 1 :
find = 1 ;
break ;
case -1 :
return(0) ;
case 0 :
switch (CynMatch3(lbuf) )
{
case 1 :
find = 1 ;
break ;
case -1 :
return(0) ;
case 0 :
switch (CynMatch4(lbuf) )
{
case 1 :
find = 1 ;
break ;
case -1 :
return(0) ;
}
}
}
}
}
return(find) ;
}
int CynMatch1(lbuf)
/*
* Match ordinary error line with the format
* file: line: error
*/
char *lbuf ;
{
if ( sscanf(lbuf, "%[^: \t]: %d: %[^\n]", filename, &line, mesg) > 2)
{
fprintf(outfp, "\"%s\", line %d: %s\n", filename, line, mesg ) ;
return(1) ;
}
return(0) ;
}
int CynMatch2(lbuf)
/*
* match line with the format
* variable "multiply declared":
*/
char *lbuf ;
{
char c ;
char varname[100] ;
char linebuf[512] ;
if (
sscanf(lbuf, "%s multiply declared%c", varname, &c) > 1
&&
c == ':'
)
{
if (
(getc(infp) == '\t')
&&
fgets(linebuf, 512, infp) != NULL
)
{
if (
sscanf(linebuf, "%[^:]: %d %[^\n]", filename, &line, mesg) > 2
&&
strncmp(mesg, "implicitly as", 13) == 0
)
{
if (
getc(infp) != '\t'
||
fgets(linebuf, 512, infp) == NULL)
return(-1) ;
}
else
{
if (fscanf(infp, " %[^:]: %d %[^\n]\n", filename, &line, mesg) < 3)
return(-1) ;
}
fprintf(
outfp,
"\"%s\", line %d: %s %s : %s",
filename,
line,
varname,
mesg,
linebuf
) ;
return(1) ;
}
else return(-1) ;
}
else return(0) ;
}
int CynMatch3(lbuf)
/*
* match line with the format
* variable "multiply defined":
*/
char *lbuf ;
{
char word[512] ;
char linebuf[512] ;
char c ;
if (
sscanf(lbuf, "%*s multiply defined%c", &c) > 0
&&
c == ':'
)
{
while ((c = getc(infp)) == '\t')
{
if (
fgets(linebuf, 512, infp) != NULL
&&
sscanf(linebuf, "%[^:]: %d", filename, &line) > 1
)
{
fprintf(
outfp,
"\"%s\", line %d: %s",
filename,
line,
lbuf
) ;
}
else return(-1) ;
}
ungetc(c, infp) ;
return(1) ;
}
else return(0) ;
}
int CynMatch4(lbuf)
/*
* match line with the format
* "function" function: library
* or
* "function" function: file: line
*/
char *lbuf ;
{
char word[512] ;
char linebuf[512] ;
char c ;
if (
sscanf(lbuf, "function %*[^:]: %[^\n]", word) > 0
)
{
lbuf[strlen(lbuf) - 1] = '\0' ;
while ((c = getc(infp)) == '\t')
{
if (
fgets(linebuf, 512, infp) != NULL
&&
sscanf(linebuf, "%[^:]: %d, %[^\n]", filename, &line, mesg) > 2
)
{
fprintf(
outfp,
"\"%s\", line %d: %s %s\n",
filename,
line,
lbuf,
mesg
) ;
}
else return(-1) ;
}
ungetc(c, infp) ;
return(1) ;
}
else return(0) ;
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 3424 ]
then
echo $filename changed - should be 3424 bytes, not $size bytes
fi
chmod 600 $filename
fi
# ---------- file etag.c ----------
filename="etag.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file etag.c...
fi
cat << 'END-OF-FILE' > $filename
/*
* This is a program to make the debugging of C programs much
* easier and faster. It makes use of the capability of vi
* and terminfo.
* Currently it can work with errors output from cc, lint,
* ld, yacc, cyntax and make.
*
* Written by M.C. KAM
*/
#define SINGLE
#define MAXEXSIZE 62
#define BELL "\007\007\007\007\007\007\007\007\007"
#include <stdio.h>
#ifdef BSD
#define strchr index
#define strrchr rindex
#endif
extern char *strrchr() ;
extern int strcmp() ;
extern char *getcmdpath() ;
extern char *getenv() ;
extern FILE *tmpfile() ;
extern int makelintag() ;
extern int makeldtag() ;
extern int makecctag() ;
extern int makecyntag() ;
static void creattag() ;
typedef struct
{
int (*translator)() ;
int checktype ;
} ERRDRIVER ;
ERRDRIVER driverlist[] =
{
makecyntag, 1,
makecctag, 0,
makeldtag, 0,
makelintag, 0,
NULL
} ;
static FILE *srcefp ;
static FILE *errfp;
static FILE *tmpfp ;
static FILE *terrfp ;
static char tempfile[64] ;
static char cursrcefile[128] ;
static char curlinebuf[512] ;
static char lbuf[512];
static int curlineno ;
static int patmatch ;
static FILE *fp;
static int tabsize = 0 ;
static int line = 0 ;
static char tagfile[50] ;
main(argc, argv, envp)
int argc;
char **argv;
char **envp;
{
int i ;
char **newenvp ;
int eline;
int initflag = 0 ;
char filename[100];
char errmsg[132] ;
char tagmsg[512] ;
char envstr[300] ;
char srhpat[50] ;
char *homep ;
extern char *getlogin() ;
extern char *ttyname() ;
extern char *strrchr() ;
long addr ;
if (isatty(0) == 0)
{
fputs(BELL, stderr) ;
sleep(1) ;
fputs(BELL, stderr) ;
sleep(1) ;
fputs(BELL, stderr) ;
exit(1) ;
}
else homep = strrchr(ttyname(0), '/') + 1 ;
line = 0 ;
strcpy(tagfile, "/tmp/tags.") ;
strcat(tagfile, homep) ;
strcat(tagfile, getlogin());
switch (*argv[1])
{
case '+' :
(void) getheader(&line, &patmatch, &tabsize) ;
if ((++line ) > tabsize)
{
fputs(BELL, stdout) ;
fseek(fp, 3 * sizeof(int) + tabsize * sizeof(long), 0) ;
fread((char *) &addr, sizeof (long), 1, fp) ;
fseek(fp, addr + 55 * sizeof(char), 0) ;
fprintf(fp, "/$/%62.s\n", "") ;
fclose(fp) ;
tprintf("ve : no more error line found");
exit(0) ;
}
break;
case '=' :
(void) getheader(&line, &patmatch, &tabsize) ;
break;
case '-' : initflag = -1 ;
(void) getheader(&line, &patmatch, &tabsize) ;
if (line > 1)
line-- ;
else
{
fputs(BELL, stdout) ;
tprintf("ve : no more previous error line");
exit(0) ;
}
break;
default:
if (argc < 2)
{
fprintf(stderr, "usage : %s file\n", argv[0]) ;
exit(1) ;
}
else
{
if ((errfp = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "%s : can not open error file : %s\n", argv[0], argv[1]) ;
exit(2) ;
}
}
if (getc(errfp) != EOF)
rewind(errfp) ;
else
{
fputs(BELL, stdout) ;
tprintf("ve : no recognisable syntax error ");
exit(1) ;
}
patmatch = (argc <= 2) ;
openfile() ;
CallTranslator() ;
initflag = 1 ;
line++ ;
fputs(BELL, stderr) ;
break;
}
fseek(fp, (line - 1) * sizeof( long), 1) ;
fread((char *) &addr, sizeof (long), 1, fp) ;
fseek(fp, addr, 0) ;
fgets(lbuf, 512, fp) ;
rewind(fp) ;
fwrite((char *) &line, sizeof (int), 1, fp) ;
fseek(fp, 3 * sizeof(int) + tabsize * sizeof(long), 0) ;
fread((char *) &addr, sizeof (long), 1, fp) ;
fseek(fp, addr, 0) ;
if (*lbuf == '"')
{
if (sscanf(lbuf, "\"%[^\"]\", line %d: %[^\^\n]%[^\n]",
filename, &eline, errmsg, tagmsg) > 3
&&
(
patmatch == 1
&&
initflag != 1
)
)
{
char *ch ;
tprintf("%s, %d: %s", filename, eline, errmsg) ;
ch = (initflag == -1 ? "?" : "/") ;
fprintf(fp, "err\t%50.50s\t%s%s%-*.1s\n", filename, ch, tagmsg, MAXEXSIZE + 2 - strlen(tagmsg), ch);
}
else
{
tprintf("%s, %d: %s", filename, eline, errmsg) ;
fprintf(fp, "err\t%50.50s\t%5d%60.s\n", filename, eline, "");
}
}
else if (*lbuf == '\'')
{
char *ch ;
ch = (initflag == -1 ? "?" : "/") ;
sscanf(lbuf, "'%[^']', %s : %[^\n]", filename, srhpat, tagmsg) ;
tprintf("%s, %s", filename, tagmsg ) ;
fprintf(fp, "err\t%50.50s\t%s%.*s%-*.1s\n",
filename, ch, MAXEXSIZE + 1, srhpat,
MAXEXSIZE + 2 - strlen(srhpat), ch);
}
fclose(fp) ;
if (initflag == 1 )
{
for (i = 0 ; envp[i] != NULL && strncmp(envp[i], "EXINIT", 6) ; i++) ;
if (envp[i] != NULL)
{
sprintf(
envstr,
"EXINIT=%s | set tags=%s\\ tags | set nu | map ? :!%s +\r:ta err\r | map ? :!%s +\r | map ? :ta err\r | map ? :!%s =\r:ta err\r | map ? :!%s -\r:ta err\r | set nomagic",
envp[i]+7,
tagfile,
argv[0],
argv[0],
argv[0],
argv[0]
);
envp[i] = envstr ;
fflush(stdout) ;
execle(getcmdpath("vi"), "vi", "-t", "err", 0, envp) ;
perror("ve") ;
exit(2) ;
}
else
{
int j ;
newenvp = (char **) malloc ((i + 2) * sizeof (char **)) ;
for (j = 0 ; j < i ; j++)
newenvp[j] = envp[j] ;
sprintf(
envstr,
"EXINIT=set tags=%s\\ tags | set nomagic | map ? :!%s +\r:ta err\r | map ? :!%s =\r:ta err\r | map ? :!%s -\r:ta err\r | set nu",
tagfile,
argv[0],
argv[0],
argv[0]
);
newenvp[i+1] = NULL ;
newenvp[i] = envstr ;
fflush(stdout) ;
execle(getcmdpath("vi"), "vi", "-t", "err", 0, newenvp) ;
perror("ve") ;
exit(2) ;
}
}
}
CallTranslator()
{
register ERRDRIVER *errdp ;
for (
errdp = driverlist ;
errdp->translator != NULL ;
errdp++
)
{
if ((* errdp->translator)( errfp, terrfp) == 1 && errdp->checktype == 0)
break ;
else
rewind(errfp) ;
}
fclose(errfp) ;
rewind(terrfp) ;
preprocess() ;
}
preprocess()
{
*cursrcefile = '\0' ;
tabsize = 0 ;
while (fgets(lbuf, 512, terrfp) != NULL)
{
switch (*lbuf )
{
case '\'' :
fputs(lbuf, tmpfp) ;
tabsize++ ;
break ;
case '"' : lbuf[strlen(lbuf) - 1] = '\0' ;
extract(lbuf) ;
tabsize++ ;
break ;
}
}
if (tabsize != 0)
creattag(tmpfp) ;
else
{
fputs(BELL, stdout) ;
tprintf("ve : no recognisable syntax error ");
exit(1) ;
}
}
extract(linebuf)
char *linebuf ;
{
char filename[64] ;
int eline ;
if (sscanf(linebuf, "\"%[^\"]\", line %d:", filename, &eline) <= 1)
return ;
if (! strcmp(cursrcefile, filename))
{
if (curlineno > eline)
{
rewind(srcefp) ;
curlineno = 0 ;
}
processsrce(linebuf, eline) ;
}
else
{
if (srcefp != NULL)
fclose(srcefp) ;
if ((srcefp = fopen(filename, "r")) == NULL)
fprintf(tmpfp, "%s\n", linebuf) ;
else
{
curlineno = 0 ;
strcpy(cursrcefile, filename) ;
processsrce(linebuf, eline) ;
}
}
}
processsrce(linebuf, eline)
int eline ;
char linebuf[];
{
if (curlineno < eline)
{
do
{
if (fgets(curlinebuf, 512, srcefp) == NULL)
break ;
else curlineno ++ ;
}
while (curlineno < eline) ;
if (curlineno < eline)
{
fprintf(tmpfp, "%s\n", linebuf) ;
return ;
}
else
{
int LineLen ;
register char *cp ;
cp = curlinebuf ;
/*
* put extra '\' to quote the magic char
*/
while (*cp != '\0')
{
if (*cp == '\\' || *cp == '/')
{
mvstr(cp) ;
*cp++ = '\\' ;
}
cp++ ;
}
if ((LineLen = strlen(curlinebuf)) <= MAXEXSIZE)
curlinebuf[LineLen - 1] = '$' ;
else
curlinebuf[MAXEXSIZE] = '\0' ;
}
}
fprintf(tmpfp, "%s^%s\n", linebuf, curlinebuf) ;
}
mvstr(tcp)
char tcp[] ;
{
register int slen ;
for (slen = strlen(tcp) + 1 ; slen > 0 ; slen--)
{
tcp[slen ] = tcp[slen - 1] ;
}
}
#ifdef TERMINFO
#include <curses.h>
#include <term.h>
#endif
tprintf(format, p1, p2, p3, p4)
char *format ;
{
char buf[512] ;
#ifdef TERMINFO
setupterm(0, 1, 0) ;
if (has_status_line == 0)
{
/*
* put it out to the status line
*/
putp(to_status_line) ;
fprintf(stdout, format, p1, p2, p3, p4) ;
putp(from_status_line) ;
}
else
#endif
{
fprintf(stdout, format, p1, p2, p3, p4) ;
fputc('\n', stdout) ;
}
#ifdef TERMINFO
resetterm() ;
#endif
}
openfile()
{
if ((tmpfp = tmpfile()) == NULL || (terrfp = tmpfile()) == NULL)
{
fprintf(stderr, "ve : can not open temporary file for writing\n") ;
exit(2) ;
}
}
static void
creattag(tempfp)
FILE *tempfp ;
{
long address ;
long startadd ;
register int c ;
extern long ftell() ;
rewind(tempfp) ;
if ((fp = fopen(tagfile, "w+")) == NULL)
{
perror("ve") ;
exit(1) ;
}
/*
setbuf(fp, NULL) ;
/**/
startadd = 3 * sizeof (int) + (tabsize + 1) * sizeof( long) ;
fwrite((char *) &line, sizeof(int), 1, fp) ;
fwrite((char *) &patmatch, sizeof(int), 1, fp) ;
fwrite((char *) &tabsize, sizeof(int), 1, fp) ;
fwrite((char *) &startadd, sizeof(long), 1, fp) ;
while ((c = getc(tempfp)) != EOF)
{
if (c == '\n')
{
address = ftell(tempfp) + startadd ;
fwrite((char *) &address, sizeof(long), 1, fp) ;
}
}
rewind(tempfp) ;
while (( c = getc(tempfp)) != EOF)
putc(c, fp) ;
fseek(fp, 3 * sizeof(int), 0) ;
}
getheader(errno, type, size)
int *errno ;
int *type ;
int *size ;
{
if ((fp = fopen(tagfile, "r+")) == NULL)
{
perror("ve") ;
exit(1) ;
}
else
{
/*
setbuf(fp, NULL) ;
/**/
fread((char *)errno, sizeof(int), 1, fp) ;
fread((char *)type, sizeof(int), 1, fp) ;
fread((char *)size, sizeof(int), 1, fp) ;
}
}
#ifdef GETLOGIN
#include <pwd.h>
char *
getlogin()
{
extern struct passwd *getpwuid();
struct passwd *pwd;
if ((pwd = getpwuid(getuid())) == (struct passwd *) NULL)
return NULL;
else
return(pwd->pw_name);
}
#endif GETLOGIN
#ifdef TMPFILE
FILE *
tmpfile()
{
char filename[15] ;
FILE *fp;
strcpy(filename, "/tmp/tagXXXXXX") ;
if ((fp = fopen(mktemp(filename), "w+")) != NULL)
{
unlink(filename);
return(fp);
}
return(NULL);
}
#endif TMPFILE
/*
*
* getcmdpath.c returns the full path name of the argument cmd
* by looking through the environment variable PATH.
*
*
*/
char *
getcmdpath(cmd)
char *cmd;
{
extern char *getenv();
extern char *strchr();
char *path, *cp;
static char buf[200];
char patbuf[512];
if (cmd == NULL || *cmd == '/')
return(cmd) ;
strcpy(patbuf, getenv("PATH"));
path = patbuf;
cp = path;
while(1) {
if (path == NULL || *path == '\0')
return(NULL) ;
if (*path == ':')
strcpy(buf, cmd);
else
{
cp = strchr(path, ':');
if (cp != NULL)
*cp = '\0';
sprintf(buf, "%s/%s", path, cmd);
}
path = ++cp;
if (access(buf, 1) == 0) {
return(buf) ;
}
}
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 10732 ]
then
echo $filename changed - should be 10732 bytes, not $size bytes
fi
chmod 600 $filename
fi
# ---------- file ldtag.c ----------
filename="ldtag.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file ldtag.c...
fi
cat << 'END-OF-FILE' > $filename
#include <stdio.h>
int makeldtag(infp, outfp)
FILE *infp ;
FILE *outfp ;
{
int find = 0 ;
char lbuf[512] ;
char varname[100] ;
char filename[100] ;
char filename2[100] ;
while (fgets(lbuf, 512, infp) != NULL)
{
if (
*lbuf == '_'
&&
sscanf(lbuf+1, "%s %s", varname, filename) > 1
)
{
filename[strlen(filename) - 1 ] = 'c' ;
fprintf(outfp, "'%s', %s : undefined symbol %s\n", filename, varname, varname ) ;
find = 1 ;
}
else if ( sscanf(
lbuf,
"ld : Symbol _%s in %s is multiply defined. First defined in %s",
varname,
filename,
filename2
) > 2
)
{
filename[strlen(filename) - 1 ] = 'c' ;
filename2[strlen(filename2) - 1 ] = 'c' ;
fprintf(
outfp,
"'%s', %s : multiply defined symbol %s. First defined in %s\n",
filename,
varname,
varname,
filename2
) ;
find = 1 ;
}
}
return(find) ;
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 944 ]
then
echo $filename changed - should be 944 bytes, not $size bytes
fi
chmod 600 $filename
fi
# ---------- file lintag.c ----------
filename="lintag.c"
if [ -f $filename ]
then
echo File \"$filename\" already exists\! Skipping...
filename=/dev/null # throw it away
else
echo extracting file lintag.c...
fi
cat << 'END-OF-FILE' > $filename
#include <stdio.h>
char lbuf[512] ;
char rbuf[512] ;
char mbuf[512] ;
char *varname[100] ;
char filename[100] ;
int linenum1 ;
int linenum2 ;
int linenum3 ;
int lineref = 0 ;
int j ;
FILE *infp ;
extern char *strchr() ;
extern char *strrchr() ;
char *getline(linebuf)
char *linebuf ;
{
if (fgets(linebuf, 512, infp) != NULL)
{
lineref++ ;
/*
fprintf(stderr, "line %d : %s\n", lineref, linebuf) ;
*/
linebuf[strlen(linebuf) - 1] = '\0' ;
return(linebuf) ;
}
else return(NULL) ;
}
int makelintag(infilep, outfp)
FILE *infilep ;
FILE *outfp ;
{
int lintfilepresent = 0 ;
while (fgets(lbuf, 512, infilep) != NULL)
{
if (*lbuf == '=' )
{
if ( ! strncmp(lbuf + 1, "=============", 13))
{
lintfilepresent = 1 ;
rewind(infilep) ;
break ;
}
}
}
if (lintfilepresent == 0)
{
/*
fprintf(stderr, "Lint file not present\n") ;
/**/
return(0) ;
}
else infp = infilep ;
/*
fprintf(stderr, "Lint file present\n") ;
/**/
while (getline(lbuf) != NULL)
{
if (*lbuf == '\0')
continue ;
if (*lbuf == '=')
{
if (getline(lbuf) == NULL)
goto end ;
while (*lbuf != ' ')
{
strcpy(rbuf, lbuf) ;
if (getline(lbuf) == NULL)
goto end ;
if (match3(lbuf, mbuf, varname, filename, &linenum1))
{
do
{
strcat(mbuf, " - ");
strcat(mbuf, varname) ;
fprintf(outfp, "\"%s\", line %d: %s: %s\n", filename, linenum1, rbuf, mbuf) ;
if (getline(lbuf) == NULL)
goto end ;
}
while (match3(lbuf, mbuf, varname, filename, &linenum1) ) ;
}
else if (match4( lbuf, mbuf, filename, &linenum1))
{
do
{
fprintf(outfp, "\"%s\", line %d: %s: %s\n", filename, linenum1, rbuf, mbuf) ;
if (getline(lbuf) == NULL)
goto end ;
}
while (match4( lbuf, mbuf, filename, &linenum1)) ;
}
}
goto end ;
}
loop1: strcpy(rbuf, lbuf) ;
if (getline(lbuf) == NULL)
goto end ;
switch (*lbuf)
{
case '=' : sscanf(rbuf, "%s", filename) ;
/*
fprintf(stderr, "File %s found\n", filename) ;
/**/
break ;
case '\0' : continue ;
default :
goto loop1 ;
}
if (getline(lbuf) == NULL)
goto end ;
if (! match1(lbuf,& linenum1, mbuf))
{
loop2 : strcpy(rbuf, lbuf) ;
if (getline(lbuf) == NULL)
goto end ;
if (*lbuf == '\0')
continue ;
if ((j = match5(lbuf, &linenum1, &linenum2, &linenum3)) > 1)
{
do
{
fprintf(outfp, "\"%s\", line %d: %s %s\n", filename, linenum1, rbuf, mbuf) ;
fprintf(outfp, "\"%s\", line %d: %s %s\n", filename, linenum2, rbuf, mbuf) ;
if (j > 2)
fprintf(outfp, "\"%s\", line %d: %s %s\n", filename, linenum3, rbuf, mbuf) ;
if (getline(lbuf) == NULL)
goto end ;
}
while ((j = match5(lbuf, &linenum1, &linenum2, &linenum3)) > 1 ) ;
}
else if (match2(lbuf, &linenum1, mbuf) )
{
do
{
fprintf(outfp, "\"%s\", line %d: %s %s\n", filename, linenum1, rbuf, mbuf) ;
if (getline(lbuf) == NULL)
goto end ;
}
while (match2(lbuf, &linenum1, mbuf) ) ;
}
goto loop2 ;
}
else
do
{
fprintf(outfp, "\"%s\", line %d: %s\n", filename, linenum1, mbuf) ;
if (getline(lbuf) == NULL)
goto end ;
}
while (match1( lbuf, &linenum1, mbuf) ) ;
goto loop2 ;
}
end : return(1) ;
}
int match1(linebuf, linenum, msg)
/*
* match line with the format
* (line) message
*/
char *linebuf ;
int *linenum ;
char *msg ;
{
return(sscanf(linebuf, "(%d) %[^$]", linenum, msg) > 1) ;
}
int match2(linebuf, linenum, msg)
/*
* match line with the format
* 4 spaces (line) message
*/
char *linebuf ;
int *linenum ;
char *msg ;
{
int i ;
for (i = 0 ; linebuf[i] != '\0' && linebuf[i] == ' ' ; i++);
if (i != 4)
return(0) ;
else
{
*msg = '\0' ;
return(sscanf(linebuf, " (%d) %[^$]", linenum, msg) > 0) ;
}
}
int match3(linebuf, msg, vname, fname, linenum)
/*
* match line with the format
* message file1(line1) :: file2(line2)
*/
char *linebuf ;
char *msg ;
char *fname ;
char *vname ;
int *linenum ;
{
int i ;
for (i = 0 ; linebuf[i] != '\0' && linebuf[i] == ' ' ; i++);
if (i != 4)
return(0) ;
if (sscanf(linebuf, " %[^\t]\t%s :: %[^\(](%d)", msg, vname, fname, linenum) > 3)
{
if (fname[strlen(fname) - 2] != '.')
{
char filenamebuf[100] ;
int line ;
sscanf(vname, "%[^\(](%d)", filenamebuf, &line) ;
sprintf(vname, "%s(%d)", fname, *linenum) ;
strcpy(fname, filenamebuf) ;
*linenum = line ;
}
return(1) ;
}
else
return(0) ;
}
int match4(linebuf, msg, fname, linenum)
/*
* match line with the format:
* message file(line)
*/
char *linebuf ;
char *msg ;
char *fname ;
int *linenum ;
{
int i ;
for (i = 0 ; linebuf[i] != '\0' && linebuf[i] == ' ' ; i++);
if (i != 4)
return(0) ;
if (sscanf(linebuf, " %s %[^\(](%d)", msg, fname, linenum) > 2)
{
i = strlen(fname) - 1 ;
if (fname[i] == '?')
fname[i] = '\0' ;
return(1) ;
}
else return(0) ;
}
int match5(linebuf, lnum1, lnum2, lnum3)
/*
* match line which contains only numbers
*/
char *linebuf ;
int *lnum1 ;
int *lnum2 ;
int *lnum3 ;
{
int i ;
for (i = 0 ; linebuf[i] != '\0' && linebuf[i] == ' ' ; i++);
if (i != 4)
return(0) ;
return( sscanf(linebuf, " (%d)\t(%d)\t(%d)", lnum1, lnum2, lnum3)) ;
}
END-OF-FILE
if [ "$filename" != "/dev/null" ]
then
size=`wc -c < $filename`
if [ $size != 5575 ]
then
echo $filename changed - should be 5575 bytes, not $size bytes
fi
chmod 600 $filename
fi
echo done
exit 0
More information about the Comp.sources.unix
mailing list