[unix-pc.sources] FAKE: A nice tool for compiling programs/w MAKE and fixing errors

lenny@icus.ICUS.COM (Lenny Tropiano) (03/02/90)

This shar file was sent to me, the author doesn't have a reliable way of
posting this himself, so I'm posting it for him as per his request.  I
looked at this program briefly and it reminds me of a BSD utility "error"
but much more simplistic, making it easy to use.  The manual page
explains the program and how to use it.

Essentially the program ("fake") [I would have called it emake for error/make,
but that's *my* opinion] searches out errors from a spawned of /bin/make 
(changable with environment variables) and using a Regular Expression
searching pattern it inserts the compile time errors in a temporary file
intermixed at the line of error.  You fix the error, and re-run fake.

[A suggestion from me is to set this in your .profile ... If you use "vi"]

	FAKEMASK='^"\(.*\)", line \([0-9]*\):'
	EDITOPTS='+/,,/'

|From: attmail!auxnj!icepit!mark
|
|   "fake" provides C "error-editing" capabilities similar to those found
|in other environments, such as MS-DOS Quick C or Turbo C.  "fake" works
|exactly like make, except that if any errors occur you are immediately
|thrown into your favorite editor, with the error message intermixed at
|the appropriate place, just below the offending line.  You can easily
|move from one error to another, always seeing the error message and the
|associated source line.

Mark Schulman
Cincinnati Bell Information Systems
attmail!auxnj!icepit!mark

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by typing sh file.  To overwrite existing files, type "sh file -c".
# If this archive is complete, you will see the following message at the end:
#		"End of shell archive."
# Contents:  Makefile README fake.1 fake.c
# Wrapped by icepit!mark on Fri Feb 16 15:30:46 EST 1990
echo "extracting files ..."
if test -f 'Makefile' -a "${1}" != -c ; then 
echo "shar:  Will not clobber existing file \"Makefile\""
else
echo "x - Makefile (38 characters)"
sed 's/^X//' >'Makefile' <<'EOF'
Xfake:	fake.o
X	$(CC) fake.o -s -o fake
EOF
if test 38 -ne `wc -c <'Makefile'`; then
    echo shar:  Makefile unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != -c ; then 
echo "shar:  Will not clobber existing file \"README\""
else
echo "x - README (754 characters)"
sed 's/^X//' >'README' <<'EOF'
X   If you've done any development work in MS-DOS, you may be aware of
Xthe nifty development environments available in Quick C or Turbo C.
XWhen running a compile, if any errors occur you are immediately thrown
Xinto the editor, with the error message displayed and the cursor on
Xthe offending line.  Very nice.  You can easily move from one error
Xto another, always seeing the error message and the associated source
Xline.
X   "fake" provides similar capabilities.
X   Now when you run make and get a ton of errors, you don't have to print
Xthem out or write them down in order to get into vi and fix them.  "fake"
Xwill throw you into vi (or EMACS) with source code and error messages
Xintermixed.  Simply locate each error, fix it, and get out of the editor.
EOF
if test 754 -ne `wc -c <'README'`; then
    echo shar:  README unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'fake.1' -a "${1}" != -c ; then 
echo "shar:  Will not clobber existing file \"fake.1\""
else
echo "x - fake.1 (3287 characters)"
sed 's/^X//' >'fake.1' <<'EOF'
X.TH FAKE 2.0 1
X.SH "NAME"
Xfake - "fix make" - execute a make and edit errors
X.SH "SYNOPSIS"
X.B fake
X[make options]
X.SH "RIGHTS & LIMITATIONS"
X.B fake
Xis distributed "as is".  You assume the risk of any and
Xall damage or loss from use, or inability to use the software.
XThe author does not warrant that the functions of the software will
Xmeet your needs or that the software will be error-free or uninterrupted.
X.B fake
Xhas never been observed to destroy a source file, but I take no
Xresponsibility if it does.
X.SH "DESCRIPTION"
XHow many times does this happen:  You run
X.BR make ,
Xget a ton of errors, and either have to print them out or write them down
Xso that you can get into vi and fix them.  If you've had this problem,
X.B fake is your salvation.
X.PP
X.B fake
Xruns
X.B make
Xand accepts all make options.  If errors occur,
X.B fake
Xcaptures the errors and creates a temporary file which contains
Xthe errors interspersed amongst the source code.  The user is thrown into
Xan editor (default is vi).  Each error message
Xwill appear just after the line that caused the error.  The message is
Xprefixed with a comma-comma (",,"), a phrase which is easy to search for
Xand yet does not normally occur within a C program.
X.PP
XA snippet of what you might see in the editor if compilation errors are
Xfound:
X.PP
X.in +.25i
X.nf
X     execvp (argv[0],argv);
X     perror (p);
X,, -> "test.c", line 82: p undefined
X     exit (1);
X.fi
X.in -.25i
X.PP
XBy repeatedly searching for
Xcomma-comma, you can visit each error message one by one, and repair
Xeach error.  (Don't forget to delete the error messages themselves.)
XWhen you leave the editor, the temporary file is copied onto the original
Xsource file.
X.PP
XIf no changes are made to the temporary file, it is not copied back
Xonto the source file.
X.PP
XAn easy way (in vi) to get rid of all the error messages once the problems
Xhave been corrected is:
X.sp
X.ti +.5i
X:g/,,/d
X.PP
XFive environment variables (1 mandatory, 4 optional) are used by
X.BR fake :
X.PP
X.IP FAKEMASK 1i
X(required).  This variable contains a regular expression that tells
X.B fake
Xhow to identify an error message and how to extract the file name and line
Xnumber.  The regular expression must contain two pairs of parentheses --
X\e( and \e) -- the first surrounding the file name, the second the error
Xline number.  For example, if a typical error message looks like this:
X.br
X.in +.5i
X"test.c", line 60: syntax error
X.in -.5i
X.br
Xthen FAKEMASK might be set like this:
X.br
X.in +.5i
X.nf
XFAKEMASK='^"\(.*\)", line \([0-9]*\):'
Xexport FAKEMASK
X.fi
X.in -.5i
X.IP FAKEMARKER 1i
X(optional).  Specifies the characters to prepend to the beginning of error
Xmessages, to facilitate searching through the source for the errors.
XIf undefined, comma-comma is used.
X.IP MAKE 1i
XThis is the program run underneath
X.B fake
X-- default is /bin/make.
X.IP EDITOR 1i
X(optional) is the editor to load if errors are detected.  Default is vi.
X.IP EDITOPTS 1i
X(optional) specifies an option to be fed to the editor when loaded.
XIf vi is used, specifying  EDITOPTS=+/,,  will cause the cursor to be
Xpositioned automatically on the first error.
X.SH "AUTHOR"
X.nf
XE-mail:		{auxnj,cbis2}!icepit!mark
XSnail Mail:	Mark Schulman
X		Cincinnati Bell Information Systems
X		851 Trafalgar Ct. Suite 300W
X		Maitland, FL  32751
X.fi
EOF
if test 3287 -ne `wc -c <'fake.1'`; then
    echo shar:  fake.1 unpacked with wrong size!
fi
# end of 'fake.1'
fi
if test -f 'fake.c' -a "${1}" != -c ; then 
echo "shar:  Will not clobber existing file \"fake.c\""
else
echo "x - fake.c (4216 characters)"
sed 's/^X//' >'fake.c' <<'EOF'
X/*
X *  FAKE -- a C source development tool by Mark Schulman, Cincinnati
X *  Bell Information Systems, Maitland, Florida.
X */
X
X#include <stdio.h>
X#include <ctype.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X#define	MAXLINE		32767
X
XFILE *mf;		/*  pipe from make				*/
XFILE *sf;		/*  source file (NULL if not yet open)		*/
XFILE *tf;		/*  temp file (NULL if not yet open)		*/
Xint lineno;		/*  line number of source file			*/
Xint err_line;		/*  line number of last error message		*/
Xchar err_file[51];	/*  file name for last error message		*/
Xchar last_file[51];	/*  name of file already open			*/
Xchar err_text[129];	/*  text of last error message			*/
Xchar temp_file[51];	/*  temporary file				*/
Xchar *marker;		/*  marker for error messages			*/
Xchar *errmask;		/*  regular expression for error		*/
X
Xextern char *getenv ();
X
X#define	INIT		register char *sp = errmask;
X#define	GETC()		(*sp++)
X#define	PEEKC()		(*sp)
X#define	UNGETC(c)	(--sp)
X#define	RETURN(c)	return;
X#define	ERROR(c)	regerr ()
X#include <regexp.h>
X
Xregerr (n)
Xint n;
X{
X	fprintf (stderr,"regular expression error %d\n",n);
X	exit (1);
X}
X
Xmain (argc,argv)
Xint argc;
Xchar *argv[];
X{
X	/*  get the error mask  */
X	if ((errmask = getenv ("FAKEMASK")) == NULL) {
X		fputs ("fake:  FAKEMASK must be defined.\n",stderr);
X		exit (1);
X		}
X
X	/*  set things up  */
X	init_pipe (argv);
X	if ((marker = getenv ("FAKEMARKER"))==NULL) marker = ",,";
X
X	/*  read the error messages  */
X	while (get_error ())
X		if (err_line != -1) do_error ();
X
X	/*  finish up  */
X	fclose (mf);
X	finish ();
X	wait ((int*) 0);
X}
X
Xinit_pipe (argv)
Xchar *argv[];
X{
Xint fd[2];
X
X	if (pipe (fd)) {
X		perror ("fake: can't open pipe");
X		exit (1);
X		}
X	if (!fork ()) {
X		/*  child process (make)  */
X		close (fd[0]);
X		close (1);
X		dup (fd[1]);
X		close (fd[1]);
X		close (2);
X		dup (1);
X		if ((argv[0] = getenv ("MAKE"))==NULL)
X			argv[0] = "/bin/make";
X		execvp (argv[0],argv);
X		perror (argv[0]);
X		exit (1);
X		}
X	signal (SIGINT,SIG_IGN);
X	close (fd[1]);
X	if ((mf = fdopen (fd[0],"r"))==NULL) {
X		perror ("fake: fdopen failed");
X		exit (1);
X		}
X}
X
Xget_error ()
X{
Xchar *p,expr[512];
X
X	if (!fgets (err_text,sizeof (err_text),mf)) return (0);
X	fputs (err_text,stdout);
X
X	p = compile (errmask, expr, expr+sizeof (expr), 0);
X	if (step (err_text, expr) == 0) {
X		err_line = -1;
X		return (1);
X		}
X	if (nbra != 2) {
X		fputs ("fake:  mask must have 2 pairs of \\( \\) in it.\n",
X			stderr);
X		exit (1);
X		}
X
X	memcpy (err_file, braslist[0], braelist[0] - braslist[0]);
X	err_file[braelist[0] - braslist[0]] = 0;
X	err_line = atoi (braslist[1]);
X	return (1);
X}
X
Xdo_error ()
X{
X	if (strcmp (err_file,last_file)) {
X		finish ();
X		sprintf (temp_file,"/tmp/fake.%d",getpid ());
X		if ((tf = fopen (temp_file,"w"))==NULL) {
X			fputs ("can't open tempfile ",stderr);
X			perror (temp_file);
X			exit (1);
X			}
X		strcpy (last_file,err_file);
X		if ((sf = fopen (err_file,"r"))==NULL) {
X			fputs ("can't open source file ",stderr);
X			perror (err_file);
X			exit (1);
X			}
X		}
X	while (lineno < err_line) copy_line ();
X	fprintf (tf,"%s -> %s",marker,err_text);
X}
X
Xcopy_line ()
X{
Xint c;
X
X	lineno++;
X	do {
X		c = fgetc (sf);
X		if (c == EOF) {
X			lineno = MAXLINE;
X			return (0);
X			}
X		fputc (c,tf);
X		} while (c != '\n');
X	return (1);
X}
X
Xfinish ()
X{
Xchar *editor,*opts;
Xint pid;
Xstruct stat st;
Xlong time_stamp;
X
X	if (!*last_file) return;
X	while (copy_line ())
X		;
X	fclose (sf);
X	fclose (tf);
X	if (stat (temp_file,&st)) {
X		fputs ("can't stat temp file ",stderr);
X		perror (temp_file);
X		exit (1);
X		}
X	time_stamp = st.st_mtime;
X	if (!(pid = fork ())) {
X		/*  child process (vi)  */
X		signal (SIGINT,SIG_DFL);
X		if ((editor = getenv ("EDITOR"))==NULL)
X			editor = "/usr/bin/vi";
X		if ((opts = getenv ("EDITOPTS"))==NULL)
X			execlp (editor,editor,temp_file,NULL);
X		else execlp (editor,editor,opts,temp_file,NULL);
X		perror (editor);
X		exit (1);
X		}
X	while (wait (NULL) != pid);
X	if (stat (temp_file,&st)) return;
X	if (time_stamp == st.st_mtime) {
X		if (unlink (temp_file)) {
X			fputs ("can't unlink ",stderr);
X			perror (temp_file);
X			}
X		return;
X		}
X
X	if (!fork ()) {
X		/*  child process (mv)  */
X		execlp ("/bin/mv","/bin/mv",temp_file,err_file,NULL);
X		perror ("can't move temp file");
X		exit (1);
X		}
X}
EOF
if test 4216 -ne `wc -c <'fake.c'`; then
    echo shar:  fake.c unpacked with wrong size!
fi
# end of 'fake.c'
fi
echo End of shell archive.
exit 0

[Special side-note ... I am phasing out the US Domain syntax in favor
of my new domain ICUS.COM, please update your mail aliases and use the
lenny@icus.ICUS.COM or lenny@icus.com from now on, sometime in the not
so distant future the icus.islp.ny.us MX record on the Internet will
be removed -- if you have trouble getting mail to me using this new syntax,
please let me know ASAP]

-- 
| Lenny Tropiano           ICUS Software Systems        lenny@icus.ICUS.COM |
| {ames,pacbell,decuac,sbcs,hombre,rayssd}!icus!lenny   attmail!icus!lenny  |
+------ ICUS Software Systems --  PO Box 1;  Islip Terrace, NY  11752 ------+