home *** CD-ROM | disk | FTP | other *** search
- #ifndef NO_IDENT
- static char *Id = "$Id: getraw.c,v 1.9 1995/10/21 18:55:13 tom Exp $";
- #endif
-
- /*
- * Title: getraw.c
- * Author: T.E.Dickey
- * Created: 03 May 1984
- * Last update:
- * 18 Feb 1995, removed syi-testing.
- * 24 Feb 1989, when reading from a command-file, suppress lines
- * which do not begin with '$' (with optional blanks)
- * 17 Aug 1988, use SYS$COMMAND instead of SYS$INPUT.
- * 10 Jun 1985, ensure type-ahead is killed if CTRL/X
- * 08 Jun 1985, added code for interactive type-ahead
- * 10 Apr 1985, made command-files nest, some better error checks.
- * 06 Apr 1985, added file-input, CTRL/X-ast
- * 29 Mar 1985, added 'status' to 'error'.
- * 24 Feb 1985, removed ^C^C.
- * 02 Dec 1984, added entry 'gotraw' to do QIO (no wait)
- * 09 Jul 1984, use virtual-block instead on TTY_READALL
- * 04 Jul 1984, make debug more readable
- * 27 Jun 1984, do debug-print to look for lockup
- * 22 Jun 1984, test status from 'iosb'
- * 20 Jun 1984, added timeout test
- * 18 Jun 1984, do 'fflush' to attempt fix for spurious lockups
- * 31 May 1984, double ^C causes walkback-exit
- * 10 May 1984, provide passall mode if no echo
- * 07 May 1984, to make echo optional, other arguments.
- *
- * Function: Obtain a single character from the terminal without echo.
- *
- * References: VAX/VMS I/O User's Guide
- * (1-16 to 1-19) - sys$qiow
- * (2-3) - Discussion of escapes vs read-terminator
- */
-
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
-
- #include <starlet.h>
- #include <lib$routines.h>
- #include <descrip.h>
- #include <iodef.h>
- #include <ssdef.h>
- #include <stsdef.h>
-
- #include "bool.h"
- #include "flist.h"
- #include "getraw.h"
- #include "rmsio.h"
- #include "rmscc.h"
-
- /*
- * Local definitions:
- */
- #define OK(f) $VMS_STATUS_SUCCESS(status=f)
- #define SYS(f) if (!OK(f)) lib$stop(status)
-
- /* patch: Should I use 'lib$get_ef' ? */
- #define ef2 2
-
- #define QA(efn,func,b,len,t)\
- efn, /* Event flag number */\
- tty_chan,\
- func,\
- &iosb,0,0,\
- b, /* buffer address */\
- len, /* buffer size */\
- t, /* timeout count */\
- 0, /* read terminator desc-blk addr */\
- 0, /* prompt-string buffer address */\
- 0 /* prompt-string buffer size */
-
- typedef struct { short sts, count; unsigned device; } IOSB;
-
- #undef CFP
- #define CFP struct _cmd_fp
-
- CFP {
- CFP *nest; /* linked-list to nest */
- RFILE *file; /* File-pointer */
- char *text; /* => I/O buffer */
- unsigned mark; /* = record-address */
- short size; /* I/O buffer size */
- short rlen; /* = length of current record */
- short used; /* number of chars used so far */
- short iscc; /* TRUE if format is carriage-control */
- };
-
- #define CFP_TEXT(n) cfp->text[cfp->n]
-
- /*
- * Local (static) data:
- */
- $DESCRIPTOR(tty_name,"SYS$COMMAND");
-
- static CFP *cfp = nullS(CFP); /* command-file-pointer */
- static unsigned
- short tty_chan = 0,
- ast_chan = 0,
- init = FALSE; /* Force auto-init */
- static unsigned ctlx_flag = FALSE;
- static char typeahead; /* input-buffer */
-
- static void getraw_free (void);
-
- /*
- * Provide a publicly-testable CTRL/X-flag, which is set only if the AST-routine
- * is called:
- */
- void
- ctlx_ast (void)
- {
- unsigned status;
-
- SYS(sys$cancel(tty_chan));
- ctlx_flag = TRUE;
- typeahead = EOS;
- }
-
- void
- ctlx_clr (void)
- {
- ctlx_flag = FALSE;
- }
-
- int
- ctlx_tst (void)
- {
- return(ctlx_flag);
- }
-
- /* <getraw_init>:
- * The initialization routine for this module may be either called explicitly
- * (to call in a new command file), or implicitly (when the module is first
- * invoked).
- *
- * Arguments:
- * cmd_ => command-file name
- * dft_ => file-specification default
- */
- void
- getraw_init (char *cmd_, char *dft_)
- {
- int bmask[2] = {0, 0x01000000};
- unsigned status;
-
- /*
- * If a command-file argument is provided, open the file for input.
- * We will read from this file until we get an end-of-file.
- */
- if (cmd_)
- {
- if (*cmd_)
- {
- CFP *old = cfp;
- cfp = calloc(1, sizeof(CFP));
- cfp->nest = old;
- if (cfp->file = ropen2 (cmd_, dft_, "r"))
- {
- cfp->size = 4 + rsize(cfp->file);
- cfp->text = calloc(1, cfp->size);
- cfp->iscc = rmscc(cfp->file) > 0;
- }
- else
- getraw_free ();
- }
- }
-
- if (! tty_chan)
- {
- SYS(sys$assign(&tty_name, &tty_chan, 0,0));
- }
-
- if (! ast_chan)
- {
- SYS(sys$assign(&tty_name,&ast_chan,0,0));
-
- /* Establish CTRL/X AST routine */
- SYS(sys$qiow(ef2,ast_chan,IO$_SETMODE | IO$M_OUTBAND,0,0,0,
- &ctlx_ast,&bmask,0,0,0,0));
- }
- init = TRUE;
- }
-
- /*
- * Wait for, read one or more characters for commands:
- */
- int
- getraw (void)
- {
- int gotc = FALSE,
- status;
- char newc;
- IOSB iosb;
-
- if (!init) getraw_init(0,0);
-
- if (cfp)
- {
- if (cfp->used >= cfp->rlen)
- {
- get_cmd:
- if ((cfp->rlen = rgetr(cfp->file, cfp->text,
- cfp->size, &cfp->mark)) >= 0)
- {
- strcpy (&CFP_TEXT(rlen++),
- cfp->iscc ? "\r" : "");
- cfp->used = 0;
- while (isspace(CFP_TEXT(used)))
- cfp->used++;
- if (CFP_TEXT(used++) != '$') goto get_cmd;
- while ( (CFP_TEXT(used) == ' ')
- || (CFP_TEXT(used) == '\t'))
- cfp->used++;
- }
- else
- getraw_free();
- }
- if (cfp) /* Still here if no end-of-file */
- {
- if (gotc = (cfp->used < cfp->rlen))
- newc = CFP_TEXT(used++);
- }
- }
-
- /*
- * Use data from call on 'gotraw':
- */
- if (! gotc && typeahead)
- {
- gotc = TRUE;
- newc = typeahead;
- }
-
- /*
- * If neither command-file, nor type-ahead, wait for input from the
- * terminal:
- */
- while (! gotc)
- {
- if (ctlx_tst())
- {
- newc = CTL('X');
- ctlx_clr(); /* Reset flag after use !! */
- break;
- }
- if (! OK(sys$qiow (QA(0,
- IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO,
- &typeahead,1,0))))
- error (status, 0);
-
- gotc = (iosb.sts == SS$_NORMAL);
- newc = typeahead;
- /* CTRL/X yields SS$_ABORT */
- }
-
- typeahead = EOS;
- return (newc);
- }
-
- /* <gotraw>:
- * Return TRUE iff we have already another character in the input buffer,
- * following the one which we have (just) read. This test lets us optimize
- * screen outputs by combining several refreshes together (e.g., postponing
- * updates of an input line until we have a carriage-return).
- */
- int
- gotraw (void)
- {
- int status;
- IOSB iosb;
-
- if (cfp)
- return (cfp->used < cfp->rlen);
- else if (! typeahead)
- {
- if (! OK(sys$qio (QA(ef2,
- IO$M_TIMED | IO$_READVBLK | IO$M_NOFILTR | IO$M_NOECHO,
- &typeahead,1,0))))
- error (status, 0);
-
- sys$waitfr (ef2);
- if (iosb.sts != SS$_NORMAL) typeahead = EOS;
- }
- return (isprint(typeahead));
- }
-
- /* <getraw_free>:
- * Close the current command-file, returning buffer space. If there is an
- * error, print the message.
- */
- static void
- getraw_free (void)
- {
- char msg[CRT_COLS];
-
- if (cfp)
- {
- CFP *old = cfp->nest;
- if (cfp->text) cfree (cfp->text);
- if (cfp->file)
- {
- if (erstat (cfp->file, msg, sizeof(msg)))
- warn (msg);
- rclose (cfp->file);
- }
- else
- rerror(); /* Show file-not-found message */
- cfree (cfp);
- cfp = old;
- }
- rclear(); /* Reset I/O-error latch */
- }
-
- /*
- * <getraw_flush>:
- * Discard the remainder of the current command-file line.
- */
- void
- getraw_flush(void)
- {
- if (cfp)
- cfp->used = cfp->rlen + 1;
- }
-