static char *SccsId = "@(#)debug.c 4.4 (TU-Delft) 01/28/93";
/**********************************************************

Name/Version      : aux/4.4

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Authors           : A.J. van Genderen
                  : N.P. van der Meijs
Creation date     : 15-Mar-1988
Modified by       :
Modification date :


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1988. All rights reserved.
**********************************************************/

#ifdef DRIVER
#define DEBUG
#endif /* DRIVER */

#include <stdio.h>
#include "debug.h"
#define   TRUE 	1
#define   FALSE 0

/* 
 * The initial value of _IfDebug should be 1 so that
 * cIfDebug is called at least once
 */
int _IfDebug = 1;

static   char *namelist[BUFSIZ];

/*
 * DESCRIPTION
 * 
 * cIfDebug - debugging.
 * 
 * The file .debug in the current working directory (or the 
 * file named in the environment variable DEBUG) can contain
 * the names of the .c source files
 * on a separate line.
 * For each file named in the .debug file, the debugging mode
 * is turned on.
 * 
 * Suppose the "foo.c" is in the .debug file. Then, the call
 * 
 *   cIfDebug ("foo.c", 100)
 * 
 * will print (without a newline, but with a tab)
 * 
 *   ---foo.c, 100:\t
 * 
 * and returns TRUE.
 * 
 * Typically, the call to cIfDebug is in an if-statement,
 * and by means of the macro DEBUG to fill in the name
 * of the current source file and the current line number
 * automatically.
 * Example:
 * 
 * #define DEBUG _IfDebug && cIfDebug (__FILE__, __LINE__)
 * ...
 * #ifdef DEBUG
 *     if (DEBUG) {
 *         print (some diagnostics);
 *     }
 * #endif
 * 
 * The .debug file is read only once, and if it can't be
 * opened the overhead is very low.
 *
 * Only the first BUFSIZ files mentioned in the :debug file
 * are honored.
 */
int cIfDebug (file, line)
char   *file;
int     line;
{
    static  int init = TRUE;
    FILE  * dfp = NULL;
    int    check  ();
    FILE  * fopen  ();
    char  * getenv ();
    void    setup  ();

    if (init == TRUE) {
	init = FALSE;
	if (getenv ("DEBUG"))
	    dfp = fopen (getenv ("DEBUG"), "r");
	else 
	    dfp = fopen (":debug", "r");
	if (dfp) {
	    setup (dfp);
	    fclose (dfp);
	}
    }

    if (_IfDebug)
	return (check (file, line));
    else 
	return (FALSE);
}

static  void setup (dfp)
FILE * dfp;
{
    register int    i = 0;
    char   *strsave ();
    char    buf[BUFSIZ];

    while (fgets (buf, BUFSIZ, dfp)) {
	buf[strlen (buf) - 1] = '\0';
	if (i < (sizeof (namelist) / sizeof (*namelist) - 2)) {
	    namelist[i++] = strsave (buf);
	}
	else {
	    say ("Ignoring debugging of file %s", buf);
	}
    }
    namelist[i] = NULL;

    if (i == 0)		/* no debugging, set global var */
	_IfDebug = 0;

    return;
}

static int check (file, line)
char   *file;
int     line;
{
    register int    i;

    for (i = 0; namelist[i] != NULL; i++) {
	if (strcmp (namelist[i], file) == 0) {
	    fprintf (stderr, "# %s%4d:\t", file, line);
	    return (TRUE);
	}
    }
    return (FALSE);
}

/*
 * cSetDebug can be called from an interactive debugger
 * or from a program to toggle debugging.
 */
void cSetDebug (file)
char   *file;
{
    register int    i, j;

    _IfDebug = 1;

    for (i = 0; namelist[i] != NULL; i++) {
	if (!strcmp (namelist[i], file)) {
	    /* turn of debugging:
	     * move last name in namelist in this position
	     */
	    for (j = i + 1; namelist[j] != NULL; j++);
	    if (j != i + 1)
		j--;
	    namelist[i] = namelist[j];
	    namelist[j] = NULL;
	    return;
	}
    }
    namelist[i] = strsave (file);
    namelist[++i] = NULL;
}

# ifdef DRIVER
/ * test driver */
main ()
{
    if (DEBUG) fprintf (stderr, "blah. \n");
}
# endif /* DRIVER */
