/*  input.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */

#include <stream.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdlib.h>
#include "slist.h"
#include "stdyac.h"
#include "stdyacp.h"
#include "input.h"
#include "cgidbg.h"

static FILE * CurrentFile = stdin ;
extern FILE * yyin ;
int EmbSt = 0 ;

int EmitCCLinePragma = 0 ;

void DoEmitCCLinePragma(const char * Name, int Line)
{
	if (!EmitCCLinePragma) return ;
	cout << "#line " << Line << " " << '"' << Name << '"' << "\n" ;
}


struct FileState {
	int LineNumber ;
	FILE * File ;
	const char * FileName ;
	FileState(int line, FILE * file, const char * name)
		{LineNumber = line ; File = file ; FileName = name; }
	~FileState() {}
	void EmitCCLinePragma() const {DoEmitCCLinePragma(FileName,LineNumber);}
};

class FileList: public SingleList {
public:
	ErrCode Insert(FileState *nt) {return SingleList::Insert(nt);}
	ErrCode Append(FileState *nt) {return SingleList::Append(nt);}
	FileState * Get()   {return (FileState *) SingleList::Get();}
	FileState * Pop() {return (FileState *) SingleList::Pop();}
	void Push(FileState * File) {Append(File);}
	FileState * GetNFromTop(int N) ;
	FileState * GetNthEntry(int N) ;
	FileList(){CurrentFile=stdin;}
	int Size(){return SingleList::Size();}
} ;

class FileListIterator: public SingleListIterator {
public:
	FileListIterator(FileList& df):
		SingleListIterator((SingleList&) df){}
	FileState * operator()()
		{return (FileState *) Next();}
};

static FileList TheFileStack ;

int PopFile()
{
	FileState * TheOldState = TheFileStack.Pop();
	if (!TheOldState) {
		// LogOut << "PopFile empty file stack\n" ;
		return 0;
	}
	fclose(CurrentFile);
	yyin = CurrentFile = TheOldState->File ;
	LineNumber = TheOldState->LineNumber ;
	CurrentFileName = TheOldState->FileName ;
	TheOldState->EmitCCLinePragma();
	delete TheOldState ;
	// LogOut << "PopFile file is now `" << CurrentFileName << "'\n" ;
	return 1;
}


int mygetc(FILE *)
{
	int Char = fgetc(CurrentFile) ;
	if (Char > 0 ) return Char ;
	else if (!PopFile()) return Char ;
	int ret = mygetc(0) ;
	cerr << "mygetc returning at EOF: " << ret << "\n" ;
	return ret ;
}

void PushFile(const char * FileName)
{
	// LogOut << "PushFile `" << FileName << "'\n" ;
	TheFileStack.Push(new FileState(LineNumber,CurrentFile,
		CurrentFileName)) ;
	CurrentFileName = MakeName(FileName) ;
	yyin = CurrentFile = fopen(FileName,"r");
	LineNumber = 1 ;
	if (!CurrentFile) {
		cerr << "Can't open file `" << CurrentFileName << "'" ;
		OutWhereEnd();
		exit(4);
	}
	DoEmitCCLinePragma(FileName,LineNumber);
}

