#include "c.h" 
#include "strings.h"
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/param.h>
#include "tcl.h"
#include "tclInt.h"
#include "tclUnix.h"

/* Postgres/libpq includes */

#include "tmp/libpq-fe.h"
#include "tmp/libpq-fs.h"


/* PQ_SourceCmd --
 *
 *	This procedure is invoked to process the "PQsource" Tcl command.
 *
 * Results:
 *	A standard Tcl result.
 *
 *----------------------------------------------------------------------
 */

	/* ARGSUSED */
int
PGTK_SourceCmd(dummy, interp, argc, argv)
    ClientData dummy;			/* Not used. */
    Tcl_Interp *interp;			/* Current interpreter. */
    int argc;				/* Number of arguments. */
    char **argv;			/* Argument strings. */
{
    if (argc != 2) {
	Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
		" fileName\"", (char *) NULL);
	return TCL_ERROR;
    }
    return PQ_EvalFile(interp, argv[1]);
}

/* PQ_EvalFile --
 *
 *	Read in an inversion large object and process the entire thing as one gigantic
 *	Tcl command.
 *
 * Results:
 *	A standard Tcl result, which is either the result of executing
 *	the file or an error indicating why the file couldn't be read.
 *
 * Side effects:
 *	Depends on the commands in the file.
 *
 *----------------------------------------------------------------------
 */

int
PQ_EvalFile(interp, LargeObName)
    Tcl_Interp *interp;		/* Interpreter in which to process file. */
    char *LargeObName;		/* Name of file to process.  Tilde-substitution
				 * will be performed on this name. */
{
    int fileId, result;
    struct pgstat statBuf;
    char *cmdBuffer, *end, *oldScriptFile;
    char workbuffer[1024];
    Interp *iPtr = (Interp *) interp;

    workbuffer[0] = '\0';
    oldScriptFile = iPtr->scriptFile;
    iPtr->scriptFile = LargeObName;
    if (LargeObName[0] != '/') {
       /* This probably can cause problems, but... */
       strcat(workbuffer, "/PGTcl/src/");
       strcat(workbuffer, LargeObName);
       LargeObName = workbuffer;
    }
    if (LargeObName == NULL) {
	Tcl_AppendResult(interp, "couldn't read postgres large obj \"", LargeObName,
		(char *) NULL);
	goto error;
    }

    PQexec ("begin"); 

    fileId = p_open(LargeObName, O_RDONLY);

    if (fileId < 0) {
	Tcl_AppendResult(interp, "couldn't open postgres large obj \"", LargeObName,
		(char *) NULL);
	goto error;
    }

    if (p_stat(LargeObName, &statBuf) == -1) {
	Tcl_AppendResult(interp, "couldn't stat large obj \"", LargeObName,
		(char *) NULL);
	p_close(fileId);
	goto error;
    }

    cmdBuffer = (char *) ckalloc((unsigned) statBuf.st_size+1);

    if (p_read(fileId, cmdBuffer, (int) statBuf.st_size) != statBuf.st_size) {
	Tcl_AppendResult(interp, "error in reading file \"", LargeObName,
		(char *) NULL);
	p_close(fileId);
	goto error;
    }


    if (p_close(fileId) != 0) {
	Tcl_AppendResult(interp, "error closing large obj \"", LargeObName,
		(char *) NULL);
	goto error;
    }
    PQexec("end"); 
    cmdBuffer[statBuf.st_size] = 0;
    result = Tcl_Eval(interp, cmdBuffer, 0, &end);
    if (result == TCL_RETURN) {
	result = TCL_OK;
    }
    if (result == TCL_ERROR) {
	char msg[200];

	/*
	 * Record information telling where the error occurred.
	 */

	sprintf(msg, "\n    (file \"%.150s\" line %d)", LargeObName,
		interp->errorLine);
	Tcl_AddErrorInfo(interp, msg);
    }
    ckfree(cmdBuffer);
    iPtr->scriptFile = oldScriptFile;
    return result;

    error:
    iPtr->scriptFile = oldScriptFile;
    return TCL_ERROR;
}
