Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_FS_1_19910112 - c/ccmd/ccmdmd.dos
There is 1 other file named ccmdmd.dos in the archive. Click here to see a list.
/*
 Author: Andrew Lowry

 Columbia University Center for Computing Activities, July 1986.
 Copyright (C) 1986, 1987, Trustees of Columbia University in the City
 of New York.  Permission is granted to any individual or institution
 to use, copy, or redistribute this software so long as it is not sold
 for profit, provided this copyright notice is retained.
*/

/* Machine dependent code for systems running under MS-DOS.
** Assumes ANSI.SYS has been installed as an installable device
** driver.  For any version or compiler peculiarities, use 
** preprocessor conditionals, but PLEASE -- do not nest
** conditionals!
*/

#include "ccmd.h"		/* get ccmd symbols */
#include "cmfncs.h"		/* and internal symbols */

/* cmrpjmp
**
** Purpose:
**   Automatic reparse handler, installed via the cmsetrp macro from
**   ccmd.h.  If this handler is installed in a CSB for which a reparse
**   is needed, it will perform a longjmp to restart execution at the
**   point following the installing cmsetrp invocation.  This point
**   should be following the call to cmini that set up parsing for
**   the current command line, and before the comnd call for the first
**   field in the command.
**
** Input arguments: None
** Output arguments: None
** Returns: Nothing
**/


jmp_buf cmrpjb;			/* global jump buffer for autoreparse */

cmrpjmp()
{
#ifdef LATTICE
  longjmp(&cmrpjb,1);		/* do the jump */
#else
  longjmp(cmrpjb,1);
#endif
  return(CMxNOAR);		/* if it returns, it failed */
}

/* cmerjmp
**
** Purpose:
**   Automatic parse error handler, much like the automatic reparse
**   handler described above.  This macro should be invoked just prior
**   to issuing a prompt.  When a parsing error subsequently occurs
**   (that is, the parse function is about to return anything but
**   CMxOK), cmperr will be called to print the error, and then
**   execution will jump back to the site of this macro.  When the
**   automatic error handler is installed, the user program can
**   ignore the codes returned by parse, since they will always be
**   CMxOK.
**
**   Note: Reparse situations will be handled by the error handler if
**   no reparse handler has been installed.
**
** Input arguments: None.
** Output arguments: None.
** Returns: Nothing.
**/

jmp_buf cmerjb;				/* global jump buffer */

cmerjmp(ret)
int ret;				/* code that triggered the handler */
{
  cmperr(ret);				/* issue error message */
#ifdef LATTICE
  longjmp(&cmerjb,1);			/* take the jump */
#else
  longjmp(cmerjb,1);
#endif
  return(CMxNOAE);			/* failed */
}

cmerjnp(ret)
int ret;				/* code that triggered the handler */
{
#ifdef LATTICE
  longjmp(&cmerjb,1);			/* take the jump */
#else
  longjmp(cmerjb,1);
#endif
  return(CMxNOAE);			/* failed */
}
/*
 * if handling nonblocking I/O, and a BLOCKING error comes up
 * Then jump to the point set with a cmsetbl() call.
 * The user then could wait for input.
 */

jmp_buf cmbljb;				/* global jump buffer */

cmbljmp(ret)
int ret;				/* code that triggered the handler */
{
  /*
   * how to check for a blocking error here?
   */
  return(ret);				/* for now, ignore */
#ifdef LATTICE
  longjmp(&cmbljb,1);			/* take the jump */
#else
  longjmp(cmbljb,1);			/* take the jump */
#endif
  return(CMxNOAE);			/* failed */
}

/*
** Machine-dependent IO routines... In each case, if the file descriptor
** argument is the special value CONSOLE, the IO is done to the console
** using Lattice C's direct console I/O routines.  If the file descriptor
** is not CONSOLE but nevertheless refers to the console, the direct
** console I/O operations will also be used.  Any other file descriptor
** is assumed NOT to refer to a terminal, so no echoing will be performed.
** In this case, the user program may want to set CM_TTY and/or CM_CRT 
** in order to cause normal terminal handling.  If CRT is set in this
** case, a dumb crt will be assumed, which does automatic wraparound
** at the right border and which has no screen functions other than
** character output, carriage return, linefeed, backspace, and
** destructive space.
**/

static int console;			/* TRUE if source is console */

/* cmgetc - get a character from the input source.  Return std return code */

int
cmgetc(c,fd)
char *c;			/* pointer where input char is placed */
FILE *fd;			/* input filedesc */
{
  int cc;			/* int returned by system routines */

  if (console) {
    *c = getch();
    return(CMxOK);
  }
  if (cmcsb._cmoj != NULL)
    fflush(cmcsb._cmoj);
  if (fd == NULL)
    return(CMxEOF);
  *c = getc(fd);
  if (*c == EOF)
    return(CMxEOF);
  return(CMxOK);
}

/* cmputc - Output a single character to the terminal */

cmputc(c,fd)
char c;				/* character to output */
FILE *fd;			/* input filedesc */
{
  if (console) {
    if (c == '\n')
      putch('\r');
    putch(c);
  }
  else {
    if (fd != NULL) {
      putc(c,fd);
      if (c == '\n')
	fflush(fd);
    }
  }
}

/* cmputs - Output null-terminated string to the terminal */

cmputs(s,fd)
char *s;			/* string to output */
FILE *fd;			/* output filedesc */
{
  while(*s != NULL) {
    cmputc(*s,fd);
    *s++;
  }
}

/* cmcr - Move to the beginning of the current line */

cmcr(fd)
FILE *fd;			/* input filedesc */
{
  cmputc(RETURN,fd);		/* output a carriage return */
}

/* cmnl - Output a newline sequence to the command stream */

cmnl(fd)
FILE *fd;			/* input filedesc */
{
  cmputc(NEWLINE,fd);		/* just a newline character */
}

/* cmflsh - flush output on fd */
cmflsh(fd)
FILE *fd;
{
  if (fd != NULL)
    fflush(fd);
}

/* cmwrap - Make sure the cursor wraps when it is required */

cmwrap(fd)
FILE *fd;
{
				/* This happens for console automatically */
				/* and we assume the same for other devices */
}

/* cmcls - Clear the screen.  Only invoked if source is a CRT.  Return
** TRUE iff we think the operation succeeded.
**/

cmcls()
{
  if (console)
    cputs("\033[2J");		/* home and clear screen: ESC [ 2 J */
  else
    cmputc(FORMFEED);		/* for other terminal try a formfeed */
  return(TRUE);			/* assume it worked */
}

/* cmceol - Clear to end of line.  Only invoked on a CRT.  Return
** TRUE iff we think we succeeded.
**/

cmceol()
{
  if (console) {
    cputs("\033[K");		/* erase to end-of-line: ESC [ k */
    return(TRUE);
  }
  else
    return(FALSE);		/* say we can't do it on other terminals */
}


/* cmupl - Moves up one line in the display without changing column
** position.  Should not wrap to bottom of screen or cause destructive
** downward scrolling.  Only invoked on a CRT.  Returns TRUE iff we
** think the operation succeeded.
**/

cmupl()
{
  if (console) {
    cputs("\033[A");		/* up one line: ESC [ A */
    return(TRUE);
  }
  else
    return(FALSE);		/* assume other terminals are incapable */
}

/* cmcpos - Returns current column position on display.  If the
** command source is not the console, the column position currently
** stored in the CSB is returned.
**/

int
cmcpos()
{
  int nscan;			/* # of items successfully scanned in */
				/* cursor position report */
  int row,col;			/* reported cursor position */

  if (console) {
    cputs("\033[6n");		/* device status report: ESC [ 6 n */
    nscan = cscanf("\033[%d;%dR",&row,&col); /* scan response */
#ifndef RAINBOW
    getch();			/* pick up the carriage return */
#endif
    if (nscan != 2)
      return(cmcsb._cmcol);	/* undecipherable response */
    else
      return(col-1);		/* give back response adjusted for 0-origin */
  }
  else
    return(cmcsb._cmcol);	/* unknown for other than console */
}

/* cmflush - Flush all pending input on the input source */

cmflush(fd)
FILE *fd;
{
  char junk;

  if (console)
    while(kbhit())
      getch();
  else
    if (fd != NULL) {
      while (read(fileno(fd),&junk,1) == 1); /* flush other terminal */
	fd->_cnt = 0;
    }
}

/* cmtset - Initialize the source terminal.  Check if the source is
** the console, and if so set the console flag as well as the CM_TTY
** and CM_CRT flags in the CSB.  Otherwise, clear all three flags.
** In all cases, the column limit in the CSB is set to 79.
**/

#include	"dos.h"			/* for interrupt calls */
#define	CARRY	0x01			/* carry in processor flag register */
#define ISCOT	0x02			/* device status flags */
#define	ISCIN	0x01			
#define	ISDEV	0x80			

cmtset()
{
  int ifd;
  int ofd;
  union REGS inregs,outregs;		/* registers for DOS call */
  int flags;				/* processor flags after DOS call */

  if (cmcsb._cmij != NULL)
    ifd = fileno(cmcsb._cmij);	/* get desired input source */
  if (cmcsb._cmoj != NULL)
    ofd = fileno(cmcsb._cmoj);

  if (cmcsb._cmij != NULL) {
    inregs.h.ah = 0x44;			/* IOCTL call */
    inregs.h.al = 0x00;			/* get device info */
    inregs.x.bx = ifd;			/* file handle */
    flags = intdos(&inregs,&outregs);	/* do the call */
#ifdef LATTICE
    if (((flags & CARRY) != 0) || (outregs.x.ax == 0xff)) /* error? */
#else
    if ((outregs.x.cflag != 0) || (outregs.x.ax == 0xff)) /* error? */
#endif
      console = FALSE;			/* then assume nothing */
    else if ((outregs.x.dx & ISDEV) == 0) /* disk file? */
      console = FALSE;			/* then it's not the console */
    else if (outregs.x.dx & (ISCOT | ISCIN)) /* console input or output? */
      console = TRUE;			/* then set flag */
    else
      console = FALSE;			/* otherwise clear it */
  }
  else {
    console = FALSE;
  }
  if (console)
    cmcsb._cmflg |= (CM_TTY | CM_CRT); /* console is a CRT */
  else
    cmcsb._cmflg &= ~(CM_TTY | CM_CRT); /* anything else is not a tty */
  cmcsb._cmcmx = 79;			/* everything has 80 columns */
}

/* cmtend - Restore prior terminal state. Nothing needed for PC */

cmtend()
{
}