[net.sources] VMS make part 2 of 4

jon@boulder.UUCP (Jonathan Corbet) (05/15/85)

[fnord!]


This is part two of the VMS make distribution.
---------------------------- Tear here --------------------------------
$
$	babble :== write sys$output
$	babble "Creating EXECUTE.C"
$	create execute.c
# include <stdio.h>

execute (list, lib)
char **list;
int lib;
/*
 * Execute the list of commands.  Lib is true iff the target is in a
 * library.
 *
 * Jonathan Corbet
 * National Center for Atmospheric Research, Field Observing Facility.
 */
{
	char *lp, *st_getsym ();
/*
 * For compatibility, define the symbols $ and _.
 */
	st_defsym ("$", st_getsym ("MAKE$SOURCE"));
	st_defsym ("_", st_getsym ("MAKE$OUT_OF_DATE"));
/*
 * Mark the cache entry as having the current date.
 */
	if (! lib)
		fd_current (st_getsym ("MAKE$TARGET"));
	else
		fd_lib_current (st_getsym ("MAKE$TARGET"),
				st_getsym("MAKE$MODULE"));
/*
 * Close any open libraries.
 */
	fd_close_lib ();
/*
 * Now execute the list.
 */
	for (; *list; list++)
	{
	/*
	 * Put the line into the symbol table.
	 */
		st_defsym ("MAKE$EXECUTE", *list);
	/*
	 * Substitute symbols.
	 */
		refsym ("MAKE$EXECUTE");
		lp = st_getsym ("MAKE$EXECUTE");
	/*
	 * Execute the line.  If the first character is '#',
	 * then this is a sharp line, otherwise assume a DCL
	 * line.
	 */
		if (*lp == '#')
			sharp (l_blank (lp));
		else
		{
			st_symcat ("MAKE$EXECUTE", "\t! ");
			dcl (st_symcat ("MAKE$EXECUTE"),
				st_getsym ("MAKE$OUT_OF_DATE"));
		}
	}
}
$
$	babble "Creating FDATE.C"
$	create fdate.c
# include <stdio.h>
# include <ctype.h>
# include <fab.h>
# include <rab.h>
# include <xab.h>
# include <nam.h>
# include <rmsdef.h>
# include "fdate.h"
# include "make.h"
# include "lbrdef.h"
# include "debug.h"

/*
 * This module deals with file dates.  A cache is used to store these
 * dates, in an effort to minimize RMS calls.
 *
 * Jonathan Corbet
 * National Center for Atmospheric Research, Field Observing Facility.
 */
# define FD_FN_LEN	200	/* File name length */

/*
 * The file cache table.
 */
static struct fd_cache_entry
{
	char fdc_name[FD_FN_LEN];	/* File name		*/
	f_date_t fdc_date;		/* Modification date	*/
	struct fd_cache_entry *fdc_next;	/* Next entry	*/
} *fd_cache[36] = { 0 };

/*
 * The library cache table.
 */
static struct fd_lib_cache
{
	char fdl_l_name[FD_FN_LEN];	/* Library name		*/
	struct NAM fdl_nam;		/* NAM block.		*/
	struct fd_cache_entry *fdl_mod;	/* List of modules.	*/
	struct fd_lib_cache *fdl_next;	/* Next entry		*/
	int fdl_index;			/* Library index	*/
	char fdl_open;			/* Library is open	*/
} *fd_l_cache[36] = { 0 };

/*
 * RMS structures.
 */
static struct FAB fd_fab;
static struct RAB fd_rab;
static struct XABDAT fd_xab;
/*
 * Statistics.
 */
static int n_try = 0, n_hit = 0, n_l_try = 0, n_l_hit = 0;
static int n_lib_open = 0;	/* Number of library opens	*/
/*
 * Various bits of data.
 */
static char n_open_lib = 0;	/* Number of libraries open	*/
static int cache_files = TRUE;	/* Should we cache files?	*/
static int cache_lib = TRUE;	/* Should we cache libraries?	*/

fd_init ()
/*
 * Initialize the file date module.  This routine must be called
 * before any of the other fd_ routines.
 */
{
/*
 * Fill in the RMS structures.
 */
	fd_fab = cc$rms_fab;
	fd_fab.fab$b_shr = FAB$M_UPI;	/* out of ddate -- who knows?	*/
	fd_fab.fab$l_xab = &fd_xab;
	fd_fab.fab$b_fac = FAB$M_GET;

	fd_rab = cc$rms_rab;
	fd_rab.rab$l_fab = &fd_fab;

	fd_xab = cc$rms_xabdat;
}





int
fd_date (file, date, cache)
char *file;
f_date_t date;
int cache;
/*
 * Return the modification date of "file" in "date".  Returns TRUE iff
 * the file exists.  Only use the cache if "cache" is defined.
 */
{
	struct fd_cache_entry *fd_get_cache (), *cep;
	char uc_file[200];
	int index, status, sys$open ();

/*
 * If it is in the cache, Just return the date.
 */
	if (cache)
	{
		strcpyUC (uc_file, file);
		cep = fd_get_cache (uc_file);
		if (cep)
		{
			fd_cp_date (date, cep->fdc_date);
			return (TRUE);
		}
	}
/*
 * Fill in the FAB.
 */
	fd_fab.fab$l_fna = file;
	fd_fab.fab$b_fns = strlen (file);
	fd_clr_date (&fd_xab.xab$q_cdt);
	fd_clr_date (&fd_xab.xab$q_rdt);
/*
 * Attempt to open the file.
 */
	status = sys$open (&fd_fab);
	if (error (status))
	{
		if (status != RMS$_FNF)
			errmes (&status);
		return (FALSE);
	}
/*
 * Return the date and close the file.
 */
	fd_cp_date (date, &fd_xab.xab$q_rdt);
	if (! date[0] && ! date[1])
		fd_cp_date (date, &fd_xab.xab$q_cdt);
	sys$close (&fd_fab);
/*
 * Add an entry into the cache.
 */
	if (cache && cache_files)
	{
		if ((cep = (struct fd_cache_entry *)
			malloc (sizeof (struct fd_cache_entry))) == NULL)
			c_panic ("Out of memory");
		strcpy (cep->fdc_name, uc_file);
		fd_cp_date (cep->fdc_date, date);
		index = fd_i_index (file);
		cep->fdc_next = fd_cache[index];
		fd_cache[index] = cep;
	}

	return (TRUE);
}



int
fd_lib_date (lib, module, date)
char *lib, *module;
f_date_t date;
/*
 * Return the insertion date of "module" into library "lib" in "date".
 * Returns:
 *	-1 = Module not in library
 *	 1 = Module found
 *	 0 = Library not found.
 */
{
	struct fd_cache_entry *fd_get_lib (), *cep;
	struct fd_lib_cache *libp;
	char uc_module[200], uc_lib[200], header[600];
	int index, insert, status, h_len;
	long lib_index, rfa[2];
/*
 * Get the module name in upper case.
 */
	strcpyUC (uc_module, module);
	strcpyUC (uc_lib, lib);
	if (debug (D_FDATE))
		printf ("\nfd_lib_date (%s, %s)", uc_lib, uc_module);
/*
 * If the module is in the cache, just return the date.
 */
	cep = fd_get_lib (uc_lib, uc_module);
	if (cep)
	{
		if (debug (D_FDATE))
			printf ("  Found it in cache.");
		fd_cp_date (date, cep->fdc_date);
		return (1);
	}
/*
 * No such luck.  Lets look through the library list to see if we have
 * opened this library yet.
 */
	insert = FALSE;
	index = fd_i_index (uc_lib);
	for (libp = fd_l_cache[index]; libp; libp = libp->fdl_next)
	{
		if (debug (D_FDATE))
			printf ("\nComparing with %s", libp->fdl_l_name);
		if (! strcmp (uc_lib, libp->fdl_l_name))
			break;
	}
/*
 * If not, create a structure.  Do not insert it into the list
 * until the open works, however.
 */
	if (! libp)
	{
		if (debug (D_FDATE))
			printf ("\nDidn't find it.");
		libp = malloc (sizeof (struct fd_lib_cache));
		libp->fdl_nam = cc$rms_nam;
		strcpy (libp->fdl_l_name, uc_lib);
		libp->fdl_next = NULL;
		libp->fdl_mod  = NULL;
		libp->fdl_open = FALSE;
		libp->fdl_index = 0;
		insert = TRUE;
	}
/*
 * If the library index has not been created, do so now.
 */
	if (! libp->fdl_index)
	{
		status = lbr$ini_control (&libp->fdl_index, &LBR$C_READ,
			&LBR$C_TYP_UNK, &libp->fdl_nam);
		if (error (status))
		{
			errmes (&status);
			printf ("\nUnable to initialize library: %s",
				libp->fdl_l_name);
			return (0);
		}
	}
/*
 * If the library is not open, do so now.
 */
	if (! libp->fdl_open)
	{
		/*
		 * If this is the first open, provide the name, else use
		 * the NAM block.
		 */
		if (insert)
			status = lbr$open (&libp->fdl_index, descr (uc_lib));
		else
			status = lbr$open (&libp->fdl_index);
		if (error (status))
		{
			errmes (&status);
			printf ("\nUnable to open library %s",libp->fdl_l_name);
			return (0);
		}
		libp->fdl_open = TRUE;
		n_lib_open++;
		n_open_lib++;
	}
/*
 * Since the open worked, we can now insert the structure into the
 * list, if necessary.
 */
	if (insert)
	{
		if (debug (D_FDATE))
			printf ("\nInserting library now.");
		libp->fdl_next = fd_l_cache[index];
		fd_l_cache[index] = libp;
	}
/*
 * Look for the module in the library.
 */
	status = lbr$lookup_key (&libp->fdl_index, descr (uc_module), rfa);
	if (status == LBR$_KEYNOTFND)
		return (-1);
	else if (error (status))
	{
		errmes (&status);
		printf ("\nUnable to lookup %s in %s\n", uc_module, uc_lib);
		return (0);
	}
/*
 * Search out the module.
 */
	status = lbr$set_module (&libp->fdl_index, rfa, descr_n (header,600),
				 &h_len);
	if (error (status))
	{
		errmes (&status);
		printf("\nUnable to set to module %s in %s", uc_module, uc_lib);
		return (0);
	}
/*
 * We have got it!  Return the date and add the module to the list.
 */
	fd_cp_date (date, &header[8]);
	if (debug (D_FDATE))
		printf ("\nGot date, cache_lib is %d", cache_lib);
	if (cache_lib)
	{
		if (debug (D_FDATE))
			printf ("\nInserting module");
		cep = malloc (sizeof (struct fd_cache_entry));
		strcpy (cep->fdc_name, uc_module);
		fd_cp_date (cep->fdc_date, date);
		cep->fdc_next = libp->fdl_mod;
		libp->fdl_mod = cep;
	}
	return (1);
}



struct fd_cache_entry *
fd_get_lib (lib, module)
char *lib, *module;
/*
 * Return a pointer to the cache entry for "module" in library "lib",
 * if one exists.
 */
{
	int index;
	struct fd_lib_cache *libp;
	struct fd_cache_entry *cep;
/*
 * If the cache is disabled, just return.
 */
	if (debug (D_FDATE))
		printf ("\n\nfd_get_lib (%s %s)", lib, module);
	if (! cache_lib)
		return (NULL);
/*
 * Attempt to find the library in the cache.
 */
	index = fd_i_index (lib);
	n_l_try++;
	for (libp = fd_l_cache[index]; libp; libp = libp->fdl_next)
		if (! strcmp (lib, libp->fdl_l_name))
			break;
	if (! libp)
	{
		if (debug (D_FDATE))
			printf ("\nFailed to find library.");
		return (NULL);
	}
/*
 * We have the library.  Now search for the module.
 */
	for (cep = libp->fdl_mod; cep; cep = cep->fdc_next)
	{
		if (debug (D_FDATE))
			printf ("\nComparing %s.", cep->fdc_name);
		if (! strcmp (module, cep->fdc_name))
		{
			if (debug (D_FDATE))
				printf (" ... Found it!");
			n_l_hit++;
			return (cep);
		}
	}
	return (NULL);
}



int
fd_cmp_date (date1, date2)
f_date_t date1, date2;
/*
 * Returns:
 *	0	if date1 = date2
 *	< 0	if date1 < date2
 *	> 0	otherwise.
 */
{
	f_date_t temp;

	if (date1[0] == date2[0]  &&  date1[1] == date2[1])
		return (0);
	subquad (date1, date2, temp);
	return (temp[1]);
}




int
fd_dirty (file)
char *file;
/*
 * Invalidate the internal idea of what the date of "file" is,
 * requiring a check next time.  There is no problem if "file" is
 * not in the cache.
 */
{
	struct fd_cache_entry *cep, *last;
	char uc_file[200];
	int index;

	strcpyUC (uc_file, file);
	if (debug (D_FDATE))
		printf ("\nFd_dirty (%s)", uc_file);
	index = fd_i_index (uc_file);
	for (cep = fd_cache[index]; cep != NULL; cep = cep->fdc_next)
	{
		if (debug (D_FDATE))
			printf ("\nComparing with %s", cep->fdc_name);
		if (! strcmp (uc_file, cep->fdc_name))
		{
			if (debug (D_FDATE))
				printf (" Found it.");
			if (cep == fd_cache[index])
				fd_cache[index] = cep->fdc_next;
			else
				last->fdc_next = cep->fdc_next;
			free (cep);
			return;
		}
		last = cep;
	}
}



fd_lib_dirty (lib, module)
char *lib, *module;
/*
 * Invalidate the cache entry for the given library and module.  The
 * nonexistence of the entry causes a no-op.
 */
{
	int index;
	char uc_lib[200], uc_module[200];
	struct fd_cache_entry *cep, *last;
	struct fd_lib_cache *libp;

/*
 * Get everything in upper case.
 */
	strcpyUC (uc_lib, lib);
	strcpyUC (uc_module, module);
/*
 * See if we can find the library.
 */
	index = fd_i_index (uc_lib);
	for (libp = fd_l_cache[index]; libp; libp = libp->fdl_next)
		if (! strcmp (uc_lib, libp->fdl_l_name))
			break;
	if (! libp)
		return;
/*
 * Look for the module.
 *
 * Would you believe that when the loop was phrased as
 *
 *	for (cep = libp->fdl_mod; cep != 0; cep = cep->fdc_next)
 *
 * that it executed the first time with cep = 0?  Well, it happened.  I
 * am too tired to start looking at assembly code to figure it out,
 * so life will just have to go on with a while.
 */
	last = NULL;
	cep = libp->fdl_mod;
	while (cep != 0)
	{
		if (! strcmp (uc_module, cep->fdc_name))
		{
		/*
		 * Found it.  If this is the first entry in the list,
		 * we have to modify the library header structure.
		 */
			if (cep == libp->fdl_mod)
				libp->fdl_mod = cep->fdc_next;
		/*
		 * Else we just unlink it.
		 */
			else
				last->fdc_next = cep->fdc_next;
		/*
		 * Free up the module structure and go away.
		 */
			free (cep);
			return;
		}
		last = cep;
		cep = cep->fdc_next;
	}
	return;
}





int fd_i_index (file)
char *file;
/*
 * Return an index into the cache derived from the file name.
 */
{
	char *cp, *strchr ();
/*
 * If there is a directory or logical name in front of the file
 * name, skip over it.
 */
	if ((cp = strchr (file, ']')) == NULL)
		if ((cp = strchr (file, '>')) == NULL)
			cp = strchr (file, ':');
	if (cp)
		file = cp + 1;

	if (isdigit (*file))
		return (*file - '0');
	else if (isalpha (*file))
		return ((islower (*file) ? _toupper (*file) : *file) - 'A' +10);
	else
	{
		printf ("\nBad file name: %s", file);
		m_exit ();
	}
}



fd_cp_date (date1, date2)
f_date_t date1, date2;
/*
 * Copy date2 to date1
 */
{
	date1[0] = date2[0];
	date1[1] = date2[1];
}



struct fd_cache_entry
*fd_get_cache (file)
char *file;
/*
 * Return a pointer to the cache entry for the given file, or
 * NULL if no such entry exists.
 */
{
	int index = fd_i_index (file);
	struct fd_cache_entry *cep;
/*
 * If the cache is disabled, just return NULL.
 */
	if (! cache_files)
		return (NULL);
/*
 * Search out the file.
 */
	n_try++;
	for (cep = fd_cache[index]; cep; cep = cep->fdc_next)
		if (! strcmp (file, cep->fdc_name))
		{
			n_hit++;
			return (cep);
		}
	return (NULL);
}



fd_clr_date (date)
f_date_t date;
/*
 * Zero out the given date.
 */
{
	date[0] = date[1] = 0;
}



fd_dump_cache ()
/*
 * Dump out a listing of the file cache.
 */
{
	int slot;
	short len;
	struct fd_cache_entry *cp;
	char asctim[30];

	for (slot = 0; slot < 36; slot++)
		for (cp = fd_cache[slot]; cp; cp = cp->fdc_next)
		{
			sys$asctim (&len, descr_n (asctim, 100), cp->fdc_date, 0);
			asctim[len] = 0;
			printf ("\n%2d\t%-40s\t%s", slot, cp->fdc_name, asctim);
		}
}



fd_dump_lib ()
/*
 * Dump out the library cache.
 */
{
	int index, len;
	struct fd_lib_cache *libp;
	struct fd_cache_entry *cep;
	char date[40];

	for (index = 0; index < 36; index++)
		for (libp = fd_l_cache[index]; libp; libp = libp->fdl_next)
		{
			printf ("\nLibrary: %s", libp->fdl_l_name);
			for (cep = libp->fdl_mod; cep; cep = cep->fdc_next)
			{
				sys$asctim (&len, descr_n (date, 40), cep->fdc_date, 0);
				date[len] = 0;
				printf ("\n\t\t%-10s\t%s", cep->fdc_name, date);
			}
		}
}




fd_put_stats ()
/*
 * Put out file cache stats.
 */
{
	printf ("\nFile: %d tries %d hits.  Lib: %d tries %d hits",
		n_try, n_hit, n_l_try, n_l_hit);
	printf (" %d LBR$OPEN calls.", n_lib_open);
}


fd_dis_file ()
/*
 * Disable file cacheing.
 */
{
	cache_files = FALSE;
}


fd_en_file ()
/*
 * Enable file cacheing.
 */
{
	cache_files = TRUE;
}


fd_dis_lib ()
/*
 * Disable library cacheing.
 */
{
	cache_lib = FALSE;
}


fd_en_lib ()
/*
 * Enable library cacheing.
 */
{
	cache_lib = TRUE;
}


fd_cur_date (date)
f_date_t date;
/*
 * Return the current date in "date".
 */
{
	sys$gettim (date);
}



fd_current (file)
char *file;
/*
 * Set the date of the file to the current date in the file cache.  If
 * the file is not in the cache, it is not inserted.
 */
{
	struct fd_cache_entry *cep;
	char uc_file[200];

	strcpyUC (uc_file, file);
	if ((cep = fd_get_cache (uc_file)) != NULL)
		fd_cur_date (cep->fdc_date);
}



fd_lib_current (lib, module)
char *lib, *module;
/*
 * Mark the cache entry for lib and module as having the current date.
 */
{
	struct fd_cache_entry *cep;
	char uc_lib[200], uc_mod[200];

	strcpyUC (uc_lib, lib);
	strcpyUC (uc_mod, module);

	if (cep = fd_get_lib (uc_lib, uc_mod))
		fd_cur_date (cep->fdc_date);
}




fd_close_lib ()
/*
 * Close all the open libraries.
 */
{
	int i;
	struct fd_lib_cache *libp;

	if (debug (D_FDATE))
		printf ("\nClose_lib call");
/*
 * If there are no open libraries, blow it off.
 */
	if (! n_open_lib)
		return;
/*
 * No such luck.  Close them.
 */
	for (i = 0; i < 36; i++)
		for (libp = fd_l_cache[i]; libp; libp = libp->fdl_next)
			if (libp->fdl_open)
			{
				if (debug (D_FDATE))
					printf (" %s ", libp->fdl_l_name);
				lbr$close (&libp->fdl_index);
				libp->fdl_open = FALSE;
			/*
			 * Always force generation of a new index on
			 * the next open.
			 */
				libp->fdl_index = 0;
				if (! --n_open_lib)
					return;
			}
/*
 * We should never get here.
 */
	printf ("\nBUG: %d libs still open", n_open_lib);
}
$
$	babble "Creating FDATE.H"
$	create fdate.h
/*
 * Definitions for file dates.
 */
typedef int f_date_t[2];
$
$	babble "Creating FILE.C"
$	create file.c
/*
 * Handle input files.
 *
 * Jonathan Corbet
 * National Center for Atmospheric Research, Field Observing Facility.
 */
# include <stdio.h>
# include "make.h"

/*
 * File pointers are kept on a stack, to facilitate handling of #includes.
 * Here is a stack entry:
 */
static struct f_stack
{
	FILE *fs_fp;			/* File pointer */
	struct f_stack *fs_next;	/* Next entry.	*/
	int fs_if_level;		/* Saved if level */
} *file_stack = NULL;
static FILE *cur_fp = NULL;

int file_open (name)
char *name;
/*
 * Open the given file, pushing the old file onto the stack.
 */
{
	char f_sym[80];
	struct f_stack *fsp;
/*
 * Attempt to open the file first.
 */
	if ((cur_fp = fopen (name, "r")) == NULL)
	{
		perror (name);
		exit (1);
	}
/*
 * Push the file onto the stack.
 */
	sprintf (f_sym, "MAKE$FILE_%X", cur_fp);
	st_defsym (f_sym, name);
	if ((fsp = malloc (sizeof (struct f_stack))) == NULL)
		c_panic ("Out of memory");
	fsp->fs_fp = cur_fp;
	fsp->fs_next = file_stack;
	fsp->fs_if_level = if_level;
	file_stack = fsp;
}


int
file_getline (sym, doref)
char *sym;
int doref;
/*
 * Read a line from the file, and define it as the value of symbol "sym".
 * if doref, then symbols within the line are substituted in.  Returns
 * TRUE iff EOF was not hit.
 */
{
	char line[200], *lp;
	int c;
	char endline = FALSE, inquote = FALSE;
/*
 * Define the symbol as null.
 */
	st_defsym (sym, "");
/*
 * Read the line.
 */
	for (lp = line; ! endline;)
	{
	/*
	 * If EOF, we are certainly done reading the line.
	 */
		if ((c = fgetc (cur_fp)) == EOF)
		{
			if (lp == line)
			{
				if (file_close ())
					return (FALSE);
				continue;
			}
			endline = TRUE;
			*lp = NULL;
			st_symcat (sym, line);
		}
	/*
	 * \ means quote the next character.  If said next character is
	 * a newline, then continue onto the next line.  Flush the line
	 * buffer too.
	 */
		else if (c == '\\')
		{
			c = fgetc (cur_fp);
			if (c == '\n')
			{
				*lp++ = ' ';  *lp = NULL;
				st_symcat (sym, line);
				lp = line;
			}
			else
				*lp++ = c | C_QUOTE;
		}
	/*
	 * Delete leading blanks.
	 */
		else if ((line == lp) && ((c == ' ') || (c == '\t')))
			continue;
	/*
	 * An unquoted newline ends the line.  However, we want to
	 * delete blank lines.  We also need to search back for a
	 * quoted blank, which implies a continuation.
	 */
		else if (c == '\n')
		{
			if (lp == line)
				continue;
		/*
		 * Trim trailing blanks.
		 */
			while (*--lp == ' ')
				*lp = NULL;
			if (lp == line)
				continue;
		/*
		 * If the character is a quoted blank, continue the line.
		 */
			if (ebit (*lp) == (' ' | C_QUOTE))
			{
				*lp = ' ';  *++lp = NULL;
				lp = line;
			}
			else
			{
				endline = TRUE;
				*++lp = NULL;
			}
			st_symcat (sym, line);
		}
	/*
	 * ! Means comment the rest of the line.  This is slightly tricky,
	 *   since we want to put a comment past a line continuation.  Thus,
	 *   we must search back to the first nonblank character, and if it
	 *   is a continuation, continue the line.
	 */
		else if ((! inquote) && (c == '!'))
		{
			while (((c = fgetc (cur_fp)) != EOF) && (c != '\n')) ;
			if (line == lp)	/* ! was first char */
				continue;
			while ((*--lp == ' ') && lp > line) ;
			if ((ebit (*lp) == (' ' | C_QUOTE)) ||
				(ebit (*lp) == ('\t' | C_QUOTE)))
			{
				*lp = ' ';
				*++lp = NULL;
				lp = line;
			}
			else
			{
				*++lp = NULL;
				endline = TRUE;
			}
			st_symcat (sym, line);
		}

	/*
	 * Normal character.  Check for '"', and convert tabs to
	 * blanks.
	 */
		else
		{
			if (c == '\t')
				*lp++ = ' ';
			else
				*lp++ = c;
			if (c == '"')
				inquote = ! inquote;
		}
	}
		
/*
 * If requested, fill in the symbol.
 */
	if (doref)
		refsym (sym);
	return (TRUE);
}




int
file_close ()
/*
 * Close the current file.  Return .true. iff
 * this was the last file.
 */
{
	struct f_stack *fsp;
/*
 * Close the file.
 */
	fclose (cur_fp);
/*
 * Pop the file off the stack.
 */
	fsp = file_stack;
	file_stack = file_stack->fs_next;
	if (file_stack)
	{
		cur_fp = file_stack->fs_fp;
		if_level = file_stack->fs_if_level;
	}
	free ((char *) fsp);
	return (file_stack == NULL);
}
$
$ 	babble "---- End of MAKE part two ----"
$	exit
-- 
Jonathan Corbet
National Center for Atmospheric Research, Field Observing Facility
{seismo|hplabs}!hao!boulder!jon		(Thanks to CU CS department)