/*	Q_file

Use:

    #include	<qioret.h>		RSX IO error codes
    #include	<filequeue.h>

    FILE_QUEUE *
    enQ_file (queue, file, filename)

    FILE_QUEUE	*queue;		The relevant file queue (null if new queue)
    FILE	*file;		Current file pointer
    char	*filename;	Name of new file to become the current file


    FILE_QUEUE *
    deQ_file (queue, file)

Description:

A file is enqueued/dequeued to/from the specified file queue.
The FILE_QUEUE is defined in the filequeue.h header file.

These routines manage a queue, or stack, of files typically used in
indirect command file processing.  They allow for an indefinate number
of files to be processed in a nested fashion where a currently open file
from which commands are being read may encounter a command to open
another file from which to continue reading commands, recursively. Upon
completion (for any reason) of processing a nested file, the file
previously being read (if any) when the currenty active file reference
was encountered, can be restored to its previous condition as the
current file. 

enQ_file -

The enQ_file function will place the name of the currently open file,
and the location in the file, on a singly linked (reverse) queue, or
push down stack; close it; and open the new file using the same file
pointer. Memory is allocated for the FILE_QUEUE data structure. 

The new FILE_QUEUE pointer is returned; check IO_ERROR to see if an
error occured.  On error it is set appropriately.  IE_NBF - no buffer
space available - is set if memory cannot be allocated for the
FILE_QUEUE data structure. 


deQ_file -

The deQ_file function will close the current file; open the previously
enqueued file using the same file pointer; and position the file to the
same location it was in when it was enqueued. 

The next previous FILE_QUEUE pointer is returned.  This will be null if
the queue is now empty.  Check if IO_ERROR is set to see if an error
occured. 

>>> CAUTION <<< The use user MUST refer to the returned FILE_QUEUE
pointer when dequeueing the file, otherwise the files stacked subsequent
to the establishment of the queue pointer value will be lost (the file
pointed to in the file queue by the current value of queue will be
accessed by a deQ_file operation).  Typical usage is: 

    file = fopen (old_file, "r");
    {
    ... old_file is processed; probably until new_file is encountered.
    }
    queue = enQ_file (queue, file, new_file);
    {
    ... new_file is processed; probably to EOF.
    }
    queue = deQ_file (queue, file);
    {
    ... processing of old_file continues; positioned where it was when 
    	it was queued (ready to read the next line from the file).
    }

******************************************************************************/

#include	<std.h>
#include	<stdio.h>
#include	<qioret.h>
#include	<filequeue.h>

#define	MAX_FILENAME	32


FILE_QUEUE *
enQ_file (queue, file, filename)

FILE_QUEUE	*queue;
FILE		*file;
char		*filename;
{
FILE_QUEUE	*entry;
char		name[MAX_FILENAME];
FILE		*temp;

extern long	ftell ();


IO_ERROR = NULL;
/*
Build a new file queue entry.
*/

fgetname (file, name);

if (entry = malloc (sizeof (FILE_QUEUE) + strlen (name) + 1))
    {
    entry->position = ftell (file);
    if (temp = fopen (filename, "r"))
	{
	fclose (temp);
	file = freopen (filename, "r", file);
	entry->previous = queue;
	queue = entry;
	entry->filename = (STRING)entry + sizeof (FILE_QUEUE);
	strcpy (entry->filename, name);
	}
    else
	free (entry);
    }
else
    IO_ERROR = IE_NBF;

return (queue);
}


FILE_QUEUE *
deQ_file (queue, file)
FILE_QUEUE	*queue;
FILE		*file;
{
FILE_QUEUE	*entry;
FILE		*temp;


IO_ERROR = NULL;

if (queue)
    {
    if (temp = fopen (queue->filename, "r"))
	{
	fclose (temp);
	file = freopen (queue->filename, "r", file);
	fseek (file, queue->position, 0);
	if (! IO_ERROR)
	    {
	    entry = queue;
	    queue = queue->previous;
	    free (entry);
	    }
	}
    }
return (queue);
}
