/* xlio - xlisp i/o routines */
/*	Copyright (c) 1985, by David Michael Betz
	All Rights Reserved
	Permission is granted for unrestricted non-commercial use	*/

#include "xlisp.h"

/* xlgetc - get a character from a file or stream */
int xlgetc (NODE *fptr)
{
    NODE *lptr,*cptr;
    FILE *fp;
    int ch;

    /* check for input from nil */
    if (fptr == NIL)
	ch = EOF;

    /* otherwise, check for input from a stream */
    else if (consp(fptr)) {
	if ((lptr = car(fptr)) == NIL)
	    ch = EOF;
	else {
	    if (!consp(lptr) ||
		(cptr = car(lptr)) == NIL || !fixp(cptr))
		xlfail("bad stream");
	    if (rplaca(fptr,cdr(lptr)) == NIL)
		rplacd(fptr,NIL);
	    ch = getint(cptr, 0, UCHAR_MAX);
	}
    }

    /* otherwise, check for a buffered file character */
    else if ((ch = getsavech(fptr)))
	setsavech(fptr,0);

    /* otherwise, get a new character */
    else {

	/* get the file pointer */
	fp = getfile(fptr);

	/* prompt if necessary */
	if (prompt && fp == stdin) {

	    /* print the debug level */
	    if (xldebug)
		{ sprintf(buf,"%d:",xldebug); stdputstr(buf); }

	    /* print the nesting level */
	    if (xlplevel > 0)
		{ sprintf(buf,"%d",xlplevel); stdputstr(buf); }

	    /* print the prompt */
	    stdputstr("> ");
	    prompt = FALSE;
	}

	/* get the character */
	if (((ch = osgetc(fp)) == '\n' || ch == EOF) && fp == stdin)
	    prompt = TRUE;
    }

    /* return the character */
    return (ch);
}

/* docommand - create a nested MS-DOS shell */
#ifdef SYSTEM
docommand()
{
    stdputstr("\n[ creating a nested command processor ]\n");
    system("COMMAND");
    stdputstr("[ returning to XLISP ]\n");
}
#endif

/* xlpeek - peek at a character from a file or stream */
int xlpeek (NODE *fptr)
{
    NODE *lptr,*cptr;
    int ch;

    /* check for input from nil */
    if (fptr == NIL)
	ch = EOF;

    /* otherwise, check for input from a stream */
    else if (consp(fptr)) {
	if ((lptr = car(fptr)) == NIL)
	    ch = EOF;
	else {
	    if (!consp(lptr) ||
		(cptr = car(lptr)) == NIL || !fixp(cptr))
		xlfail("bad stream");
	    ch = getint(cptr, 0, UCHAR_MAX);
	}
    }

    /* otherwise, get the next file character and save it */
    else
	setsavech(fptr,ch = xlgetc(fptr));

    /* return the character */
    return (ch);
}

/* xlputc - put a character to a file or stream */
void xlputc (NODE *fptr, int ch)
{
    NODE ***oldstk,*lptr;

    /* count the character */
    xlfsize++;

    /* check for output to nil */
    if (fptr == NIL)
	;

    /* otherwise, check for output to a stream */
    else if (consp(fptr)) {
	oldstk = xlsave(&lptr,(NODE **)NULL);
	lptr = consa(NIL);
	rplaca(lptr,cvfixnum((FIXNUM)ch));
	if (cdr(fptr))
	    rplacd(cdr(fptr),lptr);
	else
	    rplaca(fptr,lptr);
	rplacd(fptr,lptr);
	xlstack = oldstk;
    }

    /* otherwise, output the character to a file */
    else
	osputc(ch,getfile(fptr));
}

/* xlflush - flush the input buffer */
void xlflush (void)
{
    if (!prompt)
	while (xlgetc(getvalue(s_stdin)) != '\n')
	    ;
}

