[comp.lang.lisp.x] vmsstuff.c

ardai@bass.bu.edu (Michael Ardai) (04/14/90)

Here is an os-specific module that I hacked together for VMS.  It runs 
under both 4.7 and 5.
/mike


/* vmsstuff.c - VMS specific routines */

#include "xlisp.h"
#include <descrip.h>
#include <iodef.h>
#include <ttdef.h>
#include <tt2def.h>

#define LBSIZE 200

static int tty_channel;

/* external variables */
extern LVAL s_unbound,true;
extern FILE *tfp;
extern int errno;

/* make sure we get a large stack */
int _stklen = 32766;

/* local variables */
static char lbuf[LBSIZE];
static int lpos[LBSIZE];
static int lindex;
static int lcount;
static int lposition;
static long rseed = 1L;
static char terminal_mode[12];

/* osinit - initialize */
osinit(banner)
char *banner;
{
  char newmode[12];
  short status_blk[4];
  struct dsc$descriptor_s ttydesc = { 3, DSC$K_DTYPE_T, DSC$K_CLASS_S, "TT:" };
  int *tmp;

  printf("%s\n",banner);
  printf("VMS version\n");
  lposition = 0;
  lindex = 0;
  lcount = 0;
  /* Read TTY mode and set to passthru so VMS won't trap control characters */
  SYS$ASSIGN(&ttydesc, &tty_channel, 0, 0);
  SYS$QIOW(0, tty_channel, IO$_SENSEMODE, 
    &status_blk[0], 0, 0, terminal_mode, 12, 0, 0, 0, 0);
  memcpy(newmode, terminal_mode, 12);
  tmp = &(newmode[8]);
  *tmp |= TT2$M_PASTHRU;
  tmp = &(newmode[4]);
  *tmp |= TT$M_TTSYNC; /* So ^s/^q will work */
  SYS$QIOW(0, tty_channel, IO$_SETMODE, 
    &status_blk[0], 0, 0, newmode, 12, 0, 0, 0, 0);
}

/* osfinish - clean up before returning to the operating system */
osfinish()
{
  short status_blk[4];
  /* Set terminal to how we found it */
  SYS$QIOW(0, tty_channel, IO$_SETMODE, 
    &status_blk[0], 0, 0, terminal_mode, 12, 0, 0, 0, 0);
  SYS$DASSGN(tty_channel);
}

/* oserror - print an error message */
oserror(msg)
char *msg;
{
  printf("error: %s\n",msg);
}

/* osrand - return a random number between 0 and n-1 */
int osrand(n)
int n;
{
  long k1;

  /* make sure we don't get stuck at zero */
  if (rseed == 0L) rseed = 1L;

  /* algorithm taken from Dr. Dobbs Journal, November 1985, page 91 */
  k1 = rseed / 127773L;
  if ((rseed = 16807L * (rseed - k1 * 127773L) - k1 * 2836L) < 0L)
    rseed += 2147483647L;

  /* return a random number between 0 and n-1 */
  return ((int)(rseed % (long)n));
}

/* osaopen - open an ascii file */
FILE *osaopen(name,mode)
char *name,*mode;
{
  return (fopen(name,mode));
}

/* osbopen - open a binary file */
FILE *osbopen(name,mode)
char *name,*mode;
{
  return (fopen(name,mode));
}

/* osclose - close a file */
int osclose(fp)
FILE *fp;
{
  return (fclose(fp));
}

/* osagetc - get a character from an ascii file */
int osagetc(fp)
FILE *fp;
{
  return (getc(fp));
}

/* osaputc - put a character to an ascii file */
int osaputc(ch,fp)
int ch; 
FILE *fp;
{
  return (putc(ch,fp));
}

/* osbgetc - get a character from a binary file */
int osbgetc(fp)
FILE *fp;
{
  return (getc(fp));
}

/* osbputc - put a character to a binary file */
int osbputc(ch,fp)
int ch; 
FILE *fp;
{
  return (putc(ch,fp));
}

/* ostgetc - get a character from the terminal */
int ostgetc()
{
  int ch;

  /* check for a buffered character */
  if (lcount--)
    return (lbuf[lindex++]);

  /* get an input line */
  for (lcount = 0; ; )
    switch (ch = xgetc()) {
    case '\r':
      lbuf[lcount++] = '\n';
      xputc('\r'); 
      xputc('\n'); 
      lposition = 0;
      if (tfp)
        for (lindex = 0; lindex < lcount; ++lindex)
          osaputc(lbuf[lindex],tfp);
      lindex = 0; 
      lcount--;
      return (lbuf[lindex++]);
    case '\010':
    case '\177':
      if (lcount) {
        lcount--;
        while (lposition > lpos[lcount]) {
          xputc('\010'); 
          xputc(' '); 
          xputc('\010');
          lposition--;
        }
      }
      break;
    case '\032':
      xflush();
      return (EOF);
    case '\024':	/* control-t */
      xinfo();
      printf("\n ");
      break;
    default:
      if (ch == '\t' || (ch >= 0x20 && ch < 0x7F)) {
        lbuf[lcount] = ch;
        lpos[lcount] = lposition;
        if (ch == '\t')
        do {
          xputc(' ');
        } 
        while (++lposition & 7);
        else {
          xputc(ch); 
          lposition++;
        }
        lcount++;
      }
      else {
        xflush();
        switch (ch) {
        case '\003':	
          xltoplevel();	/* control-c */
        case '\007':	
          xlcleanup();	/* control-g */
        case '\020':	
          xlcontinue();	/* control-p */
        case '\032':	
          return (EOF);	/* control-z */
        default:		
          return (ch);
        }
      }
    }
}

/* ostputc - put a character to the terminal */
ostputc(ch)
int ch;
{
  /* check for control characters */
  oscheck();

  /* output the character */
  if (ch == '\n') {
    xputc('\r'); 
    xputc('\n');
    lposition = 0;
  }
  else {
    xputc(ch);
    lposition++;
  }

  /* output the character to the transcript file */
  if (tfp)
    osaputc(ch,tfp);
}

/* osflush - flush the terminal input buffer */
osflush()
{
  lindex = lcount = lposition = 0;
}

/* oscheck - check for control characters during execution */
oscheck()
{
  int ch;
  if (ch = xcheck())
    switch (ch) {
    case '\002':	/* control-b */
      xflush();
      xlbreak("BREAK",s_unbound);
      break;
    case '\003':	/* control-c */
      xflush();
      xltoplevel();
      break;
    case '\024':	/* control-t */
      xinfo();
      break;
    }
}

/* xinfo - show information on control-t */
static xinfo()
{
  extern int nfree,gccalls;
  extern long total;
  char buf[80], tymebuf[20];
  int tyme;

  tyme = time(0);
  strcpy(tymebuf, ctime(&tyme));
  tymebuf[19] = '\0';
  sprintf(buf,"\n[ %s Free: %d, GC calls: %d, Total: %ld ]",
    tymebuf, nfree,gccalls,total);
  errputstr(buf);
}

/* xflush - flush the input line buffer and start a new line */
static xflush()
{
  osflush();
  ostputc('\n');
}

/* xgetc - get a character from the terminal without echo */
static int xgetc()
{
  short status_blk[4];
  char ch;

  SYS$QIOW(0, tty_channel, IO$M_NOECHO|IO$_READVBLK|IO$_READLBLK|IO$M_NOFILTR,
  &status_blk[0], 0, 0, &ch, 1, 0, 0, 0, 0);
  return(ch);
}

/* xputc - put a character to the terminal */
static xputc(ch)
int ch;
{
  putchar(ch);
}

/* xcheck - check for a character */
static int xcheck()
{
  short status_blk[4];
  char blk[8], ch;

  SYS$QIOW(0, tty_channel, IO$_SENSEMODE | IO$M_TYPEAHDCNT,
  &status_blk[0], 0, 0, blk, 8, 0, 0, 0, 0);
  if (blk[0] == 0) return(0);
  return(xgetc());
}

/* xsystem - execute a system command */
LVAL xsystem()
{
  char *cmd="";
  if (moreargs())
    cmd = (char *)getstring(xlgastring());
  else
    errputstr("\nSpawning.  Type 'logout' to return to XLISP\n");
  xllastarg();
  return (system(cmd) == 0 ? true : cvfixnum((FIXTYPE)errno));
}

/* xgetkey - get a key from the keyboard */
LVAL xgetkey()
{
  xllastarg();
  return (cvfixnum((FIXTYPE)xgetc()));
}

/* ossymbols - enter os specific symbols */
ossymbols()
{
}

\|/ Michael L. Ardai     ardai@bu-pub.bu.edu   
--- ---------------------------------------------------------------
/|\ ...!sun!teda!maven.dnet!ardai (preferred)