Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/user/comnd.c
There are no other files named comnd.c in the archive.
/* -*- C -*- */
/*
* COMND interface for TOPS-20
*/
#include <c-env.h>
#if SYS_T20 /* Everything in file depends on this! */
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/file.h>
#include <nic/comnd.h>
#include <nic/strung.h>
#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif
cm_def_fdb(cmini, _CMINI, 0, 0, 0, 0, 0, 0) /* initialize for parse */
cm_def_fdb(cmcfm, _CMCFM, 0, 0, 0, 0, 0, 0) /* parse confirmation */
cm_def_fdb(cmcma, _CMCMA, 0, 0, 0, 0, 0, 0) /* parse a comma */
cm_def_fdb(cmnoi, _CMNOI, 0, 0, 0, 0, 0, 0) /* parse for noise string */
struct cm_state cm_state_block; /* pointer to users state block */
#define CSB cm_state_block
/************* Forward-Referenced Procedure Declarations ************/
static int cm_open_file(); /* open given file, read or write */
/************* Externally-Referenced Procedure Declarations *************/
extern int open(); /* open or create a file */
extern char *strerror(); /* get string for last error */
extern char *strncpy(); /* copy chars between strings */
/*
* initialize for parsing. this declares the users state block,
* initializes it, and then initializes the FDBs and keyword tables
* pointed to by the fdbs arg.
*/
void cm_init(fdbs, prompt)
cm_fdb *fdbs[]; /* array of all user FDBs */
cm_char *prompt;
{
cm_fdb *fdb;
cm_table *tp; /* pointer to table structure */
int i; /* pointer to internalized keytab */
/* this is the input buffer */
CSB.cmbfp = CSB.cmptr = CSB.cmB_input - 1;
CSB.cmcnt = CM_IBUF_SIZE; /* it holds n 7-bit bytes */
CSB.cmabp = CSB.cmB_atom - 1; /* this is the atom buf */
CSB.cmabc = CM_ABUF_SIZE; /* size of atom buffer */
CSB.ijfn = _PRIIN; /* input from primary in */
CSB.ojfn = _PRIOU; /* output to primary out */
CSB.reparse = (int) cm_do_reparse; /* set reparse address */
CSB.cmrty = prompt; /* pointer to ^R prompt */
for (i = 0; fdb = fdbs[i]; i++) {
switch (fdb->cmF_function) {
case _CMKEY: case _CMSWI:
tp = (cm_table *) fdb->cmF_data;/* data is ptr to key table */
if (!tp->cmT_internalized) /* if it hasnt been interned */
cm_intern_keytab(tp); /* then do it now. */
fdb->cmF_data = (cm_char *) tp->cmT_intab;
break; /* point FDB to it */
}
if (fdb->cmF_next_fdb) /* need to chain that fdb? */
fdb->cmF_next = (int) fdb->cmF_next_fdb; /* yes, so do it */
}
}
/*
* set up the noise fdb for your string then parse for noise
*/
int cm_noise(s)
cm_char *s;
{
cmnoi.cmF_data = s; /* point to your string */
return cm_parse(&cmnoi); /* and do the parse! */
}
/*
* do an actual parse. returns 0 if the jsys failed, or CM%NOP was
* set (another failure indication). else the return values are
* stored in the users cm_ret structure and 1 is returned.
*/
static int cm_dbgflg = 0;
static void cm_show();
int cm_parse(fdb)
cm_fdb *fdb;
{
int *key_p, ablock[5];
cm_tbluk_table_entry *tp;
ablock[1] = (int) &CSB;
ablock[2] = (int) fdb;
if ((jsys(COMND, ablock) < 1) || (ablock[1] & CM_NOP)) {
cm_terpri(); /* get to new line */
printf("?%s\n", strerror(_ERRNO_LASTSYSERR)); /* output sys error */
longjmp(cm_error_jmpbuf,0); /* jump to user error */
} /* restart point. */
CSB.r_flags = ablock[1]; /* save returned flags, */
CSB.r_used = (cm_fdb *) cm_global_ptr(ablock[3]);
switch (CSB.r_used->cmF_function) {
case _CMKEY: case _CMSWI:
tp = (cm_tbluk_table_entry *) cm_global_ptr(ablock[2] & RH);
key_p = (int *) cm_global_ptr(tp->cmT_key);
if ((*key_p & CM_FW) && !(*key_p & 0770000000000))
key_p++;
CSB.r_data.cmR_table_key = (cm_char *) key_p;
CSB.r_data.cmR_table_data = tp->cmT_value;
break;
case _CMNUM:
CSB.r_data.cmR_number = ablock[2];
break;
case _CMOFI:
CSB.r_data.cmR_fd = cm_open_file(ablock[2], FALSE);
break;
case _CMIFI:
CSB.r_data.cmR_fd = cm_open_file(ablock[2], TRUE);
break;
case _CMFIL:
CSB.r_data.cmR_fd = cm_open_file(ablock[2],
(CSB.cmgjb->flags&GJ_OLD));
break;
case _CMDIR:
CSB.r_data.cmR_directory = ablock[2];
break;
case _CMUSR:
CSB.r_data.cmR_user = ablock[2];
break;
case _CMFLT:
CSB.r_data.cmR_float = (float) ablock[2];
break;
}
if (cm_dbgflg) cm_show(); /* Show results if debugging. */
return TRUE;
}
/*
* given a JFN and a direction (TRUE for input, FALSE for output),
* open the given file, returning an FD to it, or fatal error-reset.
*/
static int cm_open_file(jfn, direction)
int jfn, direction;
{
int fd;
fd = open((char*) jfn, O_SYSFD | ((direction) ? O_RDONLY : O_WRONLY), jfn);
if ((CSB.r_data.cmR_fd = fd) < 0) {
cm_terpri();
printf("?Can't open file -- %s\n", strerror(_ERRNO_LASTSYSERR));
longjmp(CSB.err_buf,0);
}
return fd;
}
/*
* turn an 18-bit FDB pointer into the real thing
*/
int *cm_global_ptr(a)
int a;
{
asm("hrrz 1,-1(17)\n xmovei 1,(1)\n");
}
/*
* internalize a keyword table. given a pointer to the raw table,
* gets the address of the destination internal-format array from
* the key field of the first element. the first word of the internal
* keytab has already been filled in, so the keys and data just need
* to be copied over. too bad this can't be done at compile-time!
*/
int cm_intern_keytab(table)
cm_table *table;
{
int i, *rt, *key_p; /* raw table pointer */
cm_tent *p;
if (table->cmT_count > 0 && !table->cmT_intab) {
rt = (int *) calloc(1, (table->cmT_count + 1) * sizeof(int));
if (!rt) return FALSE;
table->cmT_intab = rt; /* this is internal table */
} else
rt = table->cmT_intab; /* point to internal-format */
*rt = (table->cmT_count << 18) | (table->cmT_size & 0777777);
for (p = table->cmT_entries, i = 0; i < table->cmT_count; p++, i++) {
key_p = (p->cmT_flags) ? (int *) &p->cmT_flags : (int *) p->cmT_key;
*++rt = ((int) key_p << 18) | ((int) p->cmT_data & 0777777);
}
return table->cmT_internalized = TRUE; /* it's been internalized */
}
/* CM_SHOW - for debugging, show result of a successful call to cm_parse.
*/
static void
cm_show()
{
int fun = CSB.r_used->cmF_function;
char *name = NULL;
static struct fnam { int val; char *str; } *fp, fnam[] = {
_CMKEY, "KEY",
_CMNOI, "NOI",
_CMNUM, "NUM",
_CMSWI, "SWI",
_CMIFI, "IFI",
_CMOFI, "OFI",
_CMFIL, "FIL",
_CMFLD, "FLD",
_CMCFM, "CFM",
_CMDIR, "DIR",
_CMUSR, "USR",
_CMCMA, "CMA",
_CMINI, "INI",
_CMFLT, "FLT",
_CMDEV, "DEV",
_CMTXT, "TXT",
_CMTAD, "TAD",
_CMQST, "QST",
_CMUQS, "UQS",
_CMTOK, "TOK",
_CMNUX, "NUX",
_CMACT, "ACT",
_CMNOD, "NOD",
0, NULL
};
for (fp = fnam; fp->str; ++fp) /* Look up name for function */
if (fun == fp->val) {
name = fp->str;
break;
}
if (!name) {
fprintf(stderr, "[?%d?: \"%s\" %#o]", fun, CSB.cmabp+1, CSB.r_used);
return;
}
fprintf(stderr, "[%s: \"%s\" %#o => ", name, CSB.cmabp+1, CSB.r_used);
switch (fun) {
case _CMKEY:
case _CMSWI:
fprintf(stderr,"\"%s\" val %d",
CSB.r_data.cmR_table_key,
CSB.r_data.cmR_table_data);
break;
case _CMNUM:
fprintf(stderr,"%d. %#o",
CSB.r_data.cmR_number, CSB.r_data.cmR_number);
break;
case _CMNOI:
fprintf(stderr, "(%s)", CSB.r_used->cmF_data + 1);
break;
case _CMOFI:
case _CMIFI:
case _CMFIL:
fprintf(stderr,"fd %d", CSB.r_data.cmR_fd);
break;
case _CMDIR:
fprintf(stderr,"dir %#o", CSB.r_data.cmR_directory);
break;
case _CMUSR:
fprintf(stderr,"user %#o", CSB.r_data.cmR_user);
break;
case _CMFLT:
fprintf(stderr,"%f", CSB.r_data.cmR_float);
break;
}
fprintf(stderr, "]");
}
/*
* dynamic table building routines
*/
int cm_put_table(table, key, flags, data)
cm_table *table;
cm_char *key;
int flags;
int *data;
{
cm_tent *tp;
if (table->cmT_count >= table->cmT_size)
return FALSE; /* table full */
tp = &table->cmT_entries[table->cmT_count++];
strncpy(tp->cmT_key, key, CM_MAX_KEYWORD);
tp->cmT_flags = flags;
tp->cmT_data = data;
return TRUE; /* success!!! */
}
int cm_finalize_table(table)
cm_table *table;
{
if (table->cmT_count)
qsort((char *) table->cmT_entries, table->cmT_count,
sizeof(cm_tent), cm_table_compare);
return cm_intern_keytab(table);
}
int cm_table_compare(s1, s2)
cm_char *s1, *s2;
{
return strCMP(((cm_tent *) s1)->cmT_key, ((cm_tent *) s2)->cmT_key);
}
/*
* set the prompt
*/
void cm_prompt_set(s)
cm_char *s;
{
CSB.cmrty = s; /* set it in state block */
}
/*
* setup a gtjfn block
*/
void cm_setup_gtjfn(gjb, flags, dev, dir, name, ext)
gtjfn_block *gjb;
int flags;
cm_char *dev, *dir, *name, *ext;
{
CSB.cmgjb = gjb; /* use this gtjfn_block */
gjb->flags = flags;
gjb->ijfn = gjb->ojfn = 0;
gjb->device = dev; /* default device */
gjb->directory = dir; /* default directory */
gjb->name = name; /* default filename */
gjb->extension = ext; /* default extension */
gjb->protection = gjb->account = NULL; /* none of that junk */
gjb->jfn = gjb->xflags = gjb->count = 0; /* no xtra gubbish */
}
/*
* when reparse hits, we come here. the user should have set their
* reparse address with a cm_set_reparse() command before doing this,
* which would have setjmp'd the state at that point into a jmp_buf
* in the users cm_state structure. on reparse, we longjmp back to
* that saved state (and location).
*/
void cm_do_reparse()
{
longjmp(CSB.rep_buf, 0);
}
/*
* do a terpri, which means gets to the beginning of a fresh line.
* if we're already at the beginning of a line, do nothing
*/
void cm_terpri()
{
int ablock[5];
ablock[1] = _PRIOU; /* JFN */
if (jsys(RFPOS, ablock) && (ablock[2] & RH)) /* in middle of line?*/
putchar('\n'); /* yes, get to new */
}
#endif /* SYS_T20 */