mirror of
https://github.com/PDP-10/its.git
synced 2026-01-26 12:12:12 +00:00
872 lines
20 KiB
C
872 lines
20 KiB
C
# include "c/c.defs"
|
|
# include "c/its.bits"
|
|
|
|
/*
|
|
*
|
|
* CIO - C I/O Routines (written in C)
|
|
*
|
|
* Routines:
|
|
*
|
|
* fd = copen (fname, mode, opt)
|
|
* c = getchar ()
|
|
* s = gets (s)
|
|
* putchar (c)
|
|
* puts (s)
|
|
* ch = mopen (f, mode)
|
|
* rc = mclose (ch)
|
|
* rc = fparse (s, f)
|
|
* s = prfile (f, s)
|
|
* ch = fopen (fname, mode)
|
|
* ch = open (&filespec, mode)
|
|
* argc = fxarg (argc, argv)
|
|
* n = prsarg (in, out, argv, job)
|
|
* valret (s)
|
|
* c6 = ccto6 (c)
|
|
* c = c6toc (c6)
|
|
* w = csto6 (s)
|
|
* s = c6tos (w, s)
|
|
*
|
|
* Internal routines:
|
|
*
|
|
* c0init () [called by startup routine]
|
|
* fd = c0open (fname, mode)
|
|
* w = cons (lh, rh)
|
|
* s = filscan (b, s)
|
|
* s = c6q2s (w, s)
|
|
*
|
|
* Variables:
|
|
*
|
|
* cin - standard input channel
|
|
* cout - standard output channel
|
|
* cerr - standard error output channel
|
|
*
|
|
* cinfn - standard input file name (if redirected)
|
|
* coutfn - standard output file name (if redirected)
|
|
* cerrfn - standard errout file name (if redirected)
|
|
*
|
|
*
|
|
*/
|
|
|
|
# rename c0fcbs "C0FCBS"
|
|
# rename gettab "GETTAB"
|
|
# rename puttab "PUTTAB"
|
|
# rename clotab "CLOTAB"
|
|
# rename gc_bad "GC$BAD"
|
|
# rename pc_bad "PC$BAD"
|
|
# rename cl_bad "CL$BAD"
|
|
# rename prsarg "PRSARG"
|
|
# rename pjflag "PJFLAG"
|
|
# rename riflag "RIFLAG"
|
|
# rename fcbtab "FCBTBL"
|
|
# rename tty_input_channel "TYICHN"
|
|
# rename tty_output_channel "TYOCHN"
|
|
# rename setappend "SETAPP"
|
|
|
|
# define _magic 37621 /* a magic number for validation */
|
|
# define buf_siz 0200
|
|
# define fcb_siz 7
|
|
# define NCHANNEL 10 /* number of CHANNELs */
|
|
|
|
# define phyeof_flag 001
|
|
# define open_flag 002
|
|
# define write_flag 004
|
|
# define tty_flag 010
|
|
# define unset_flag 020
|
|
|
|
# define QUOTE 021 /* control-Q, for file names */
|
|
|
|
# define _DSK 0446353000000 /* sixbit for DSK */
|
|
# define _GREATER 0360000000000 /* sixbit for > */
|
|
# define _TTY 0646471000000 /* sixbit for TTY */
|
|
# define _FILE 0164651544516 /* sixbit for .FILE. */
|
|
# define _DIR 0104451621100 /* sixbit for (DIR) */
|
|
|
|
channel cin, /* standard input unit */
|
|
cout, /* standard output unit */
|
|
cerr; /* standard error output unit */
|
|
|
|
char *cinfn, /* standard input file name, if redirected */
|
|
*coutfn, /* standard output file name, if redirected */
|
|
*cerrfn; /* standard errout file name, if redirected */
|
|
|
|
int cerrno; /* system OPEN error codes returned here */
|
|
|
|
extern int c0fcbs[], fcbtab[], puttab[], gettab[], clotab[],
|
|
gc_bad[], pc_bad[], cl_bad[];
|
|
|
|
/**********************************************************************
|
|
|
|
COPEN - CIO Open File
|
|
|
|
Open a file, given a file name, an optional mode, and an
|
|
optional options string. The possible modes are
|
|
|
|
'r' - read
|
|
'w' - write
|
|
'a' - append
|
|
|
|
The default mode is read. Normally, I/O is character oriented
|
|
and produces text files. In particular, the lines of a text
|
|
file are assumed (by the user) to be separated by newline
|
|
characters with any conversion to the system format performed
|
|
by the I/O routines.
|
|
|
|
If an options string is given and contains the character "b",
|
|
then I/O is integer (word) - oriented and produces image files.
|
|
|
|
I/O to and from character strings in core is accomplished by
|
|
including "s" in the options string and supplying a character
|
|
pointer to the string to be read or written into as the first
|
|
argument to COPEN. Closing a string open for write will
|
|
append a NULL character to the string and return a character
|
|
pointer to that character.
|
|
|
|
COPEN returns a CHANNEL, which is a pointer to a control block.
|
|
The external variables CIN, COUT, and CERR contain already-open
|
|
channels for standard input, standard output, and standard
|
|
error output, respectively.
|
|
|
|
COPEN returns OPENLOSS in case of error. The system error code is
|
|
stored in CERRNO.
|
|
|
|
**********************************************************************/
|
|
|
|
channel copen (fname, mode, opt)
|
|
char *fname;
|
|
|
|
{int *fcbp, i, fmode, bmode, its_mode, flags;
|
|
int chan, buffp, state, bcnt, device, c, sflag, *ip;
|
|
char *p, buf[5], *ep;
|
|
filespec f;
|
|
|
|
cerrno = 0;
|
|
if (mode<'A' || mode>'z') mode = 'r';
|
|
p = opt;
|
|
if (opt<0100 || opt>=01000000) p = "";
|
|
else if (p[0]<'A' || p[0]>'z') p = "";
|
|
|
|
flags = open_flag;
|
|
fmode = 0;
|
|
switch (lower (mode)) {
|
|
case 'r': fmode = 0; break;
|
|
case 'w': fmode = 1; break;
|
|
case 'a': fmode = 2; break;
|
|
default: cerrno = 012; /* mode not available */
|
|
return (OPENLOSS);
|
|
}
|
|
bmode = 0;
|
|
sflag = FALSE;
|
|
while (c = *p++) switch (lower (c)) {
|
|
case 'b': bmode = 4; break;
|
|
case 's': sflag = TRUE; break;
|
|
}
|
|
|
|
if (c0fcbs[0] != _magic) c0init(); /* initialize */
|
|
for (i=0; i<NCHANNEL; ++i)
|
|
{fcbp = fcbtab[i];
|
|
if (!(fcbp[0] & open_flag)) break;
|
|
}
|
|
if (i>=NCHANNEL)
|
|
{cerrno = 06; /* device full */
|
|
return (OPENLOSS);
|
|
}
|
|
chan = -1;
|
|
buffp = fcbp[0] >> 18;
|
|
if (sflag) /* string I/O */
|
|
{state = 3;
|
|
if (fmode==2) /* append */
|
|
while (*fname) ++fname;
|
|
}
|
|
else /* file I/O */
|
|
{state = 1;
|
|
fparse (fname, &f); /* parse file name */
|
|
if (f.dev == _TTY /* TTY special case */
|
|
&& (f.fn1 != _FILE || f.fn2 != _DIR))
|
|
{state = 0;
|
|
bmode = 0;
|
|
device = 0;
|
|
chan = -1;
|
|
flags =| tty_flag;
|
|
}
|
|
else /* normal case */
|
|
{if (f.dev == 0) f.dev = _DSK;
|
|
if (f.dir == 0) f.dir = rsname();
|
|
if (f.fn2 == 0) f.fn2 = _GREATER;
|
|
|
|
its_mode = (fmode==2 ? 0100001 : fmode);
|
|
its_mode =| 2; /* block mode */
|
|
its_mode =| bmode; /* image mode */
|
|
|
|
if (fmode==2 && !bmode) /* char append */
|
|
{chan = setappend (&f, its_mode, buf, &ep);
|
|
if (chan == -04) /* not found */
|
|
{chan = mopen (&f, its_mode & 077);
|
|
fmode = 1;
|
|
}
|
|
}
|
|
else chan = mopen (&f, its_mode);
|
|
if (chan<0) {cerrno = -chan; return (OPENLOSS);}
|
|
device = status (chan) & 077; /* device code */
|
|
if (bmode && device<=2) /* TTY in IMAGE mode ?? */
|
|
{close (chan);
|
|
bmode = 0;
|
|
its_mode =& ~4;
|
|
chan = mopen (&f, its_mode);
|
|
if (chan<0) {cerrno = -chan; return (OPENLOSS);}
|
|
device = status (chan) & 077;
|
|
}
|
|
if (state==1)
|
|
if (buffp==0)
|
|
{buffp = salloc (buf_siz);
|
|
if (buffp == -1)
|
|
{cerrno = 037; /* no core available */
|
|
return (OPENLOSS);
|
|
}
|
|
}
|
|
else
|
|
{i = buf_siz;
|
|
ip = buffp;
|
|
while (--i >= 0) *ip++ = 0;
|
|
}
|
|
}
|
|
}
|
|
bcnt = -1; /* special initialization hack */
|
|
if (fmode)
|
|
{bcnt = 5*buf_siz; /* char count */
|
|
if (bmode) bcnt = buf_siz; /* word count */
|
|
flags =| write_flag;
|
|
}
|
|
if (bmode && !sflag) state = 2;
|
|
if (chan < 0) {flags =| unset_flag; chan = 0;}
|
|
fcbp[0] = (buffp<<18) | ((chan&017)<<14) | ((device&077)<<8) | flags;
|
|
fcbp[2] = bcnt;
|
|
if (sflag) fcbp[1] = fname;
|
|
else fcbp[1] = cons (bmode ? 0 : 0440700, buffp);
|
|
if (fcbp[3]==0) fcbp[3] = salloc(20);
|
|
else fcbp[3] =& 0777777;
|
|
if (fmode) state =+ 4;
|
|
fcbp[4] = cons (clotab[state], fcbp[5]=gettab[state]);
|
|
fcbp[6] = puttab[state];
|
|
if (fmode==2 && !sflag) /* file append */
|
|
{i = fillen (chan);
|
|
if (bmode) access (chan, i); /* access to end of file */
|
|
else if (i>0)
|
|
{access (chan, i-1); /* write over last word */
|
|
p = buf;
|
|
while (p < ep) cputc (*p++ | 0400, fcbp);
|
|
}
|
|
}
|
|
return (fcbp);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
SETAPPEND - Set up for character append
|
|
|
|
**********************************************************************/
|
|
|
|
int setappend (fp, mode, buf, epp) filespec *fp; char buf[], **epp;
|
|
|
|
{int count, n, chan, wordlen, chanlen, c;
|
|
char *p;
|
|
|
|
count = 5; /* try 5 times */
|
|
while (--count>=0)
|
|
{p = buf;
|
|
chan = mopen (fp, UII);
|
|
if (chan < 0) return (chan);
|
|
wordlen = fillen (chan);
|
|
close (chan);
|
|
chan = mopen (fp, UAI);
|
|
if (chan < 0) return (chan);
|
|
chanlen = fillen (chan);
|
|
if (chanlen > 0)
|
|
{if (chanlen == wordlen) --chanlen;
|
|
else chanlen = ((chanlen-1)/5)*5;
|
|
access (chan, chanlen);
|
|
n = 5;
|
|
while (--n>=0 && (c = uiiot (chan)) >= 0 && c != 3)
|
|
*p++ = c;
|
|
}
|
|
close (chan);
|
|
*epp = p;
|
|
chan = mopen (fp, mode);
|
|
if (chan<0) return (chan);
|
|
if (wordlen == fillen(chan)) return (chan);
|
|
close (chan);
|
|
}
|
|
return (-012);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
GETCHAR - Read a character from the standard input unit
|
|
|
|
**********************************************************************/
|
|
|
|
getchar () {return (cgetc (cin));}
|
|
|
|
/**********************************************************************
|
|
|
|
GETS - Read a string from the standard input unit
|
|
|
|
**********************************************************************/
|
|
|
|
char *gets (p)
|
|
char *p;
|
|
|
|
{int c;
|
|
|
|
while ((c = cgetc (cin)) != '\n' && c>0) *p++ = c;
|
|
*p = 0;
|
|
return (p);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
PUTCHAR - Output a character to the standard output unit
|
|
|
|
**********************************************************************/
|
|
|
|
putchar (c)
|
|
int c;
|
|
|
|
{return (cputc (c, cout));}
|
|
|
|
/**********************************************************************
|
|
|
|
PUTS - Output a string to the standard output unit
|
|
|
|
**********************************************************************/
|
|
|
|
puts (s)
|
|
char *s;
|
|
|
|
{int c;
|
|
|
|
while (c = *s++) cputc (c, cout);
|
|
cputc ('\n', cout);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
MOPEN - OPEN FILE
|
|
|
|
Open file given filespec and mode.
|
|
Return ITS channel number or -FC if unsuccessful.
|
|
Same as OPEN, except handles TTY specially
|
|
and waits if file is locked.
|
|
|
|
**********************************************************************/
|
|
|
|
channel mopen (f, mode) filespec *f; int mode;
|
|
|
|
{int ch, n;
|
|
|
|
if (f->dev == _TTY && !(f->fn1 == _FILE && f->fn2 == _DIR))
|
|
return (mode & 1 ? tyoopn() : tyiopn());
|
|
|
|
ch = open (f, mode);
|
|
n = 8;
|
|
while (ch == -023 && --n>=0) /* file locked */
|
|
{sleep (30);
|
|
ch = open (f, mode);
|
|
}
|
|
return (ch);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
MCLOSE - Close ITS channel, unless its the TTY.
|
|
|
|
**********************************************************************/
|
|
|
|
mclose (ch) channel ch;
|
|
|
|
{extern int tty_input_channel, tty_output_channel;
|
|
if (ch == tty_input_channel) return (0);
|
|
if (ch == tty_output_channel)
|
|
{tyo_flush ();
|
|
return (0);
|
|
}
|
|
return (close (ch));
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
FPARSE - Convert an ASCIZ string representation of an ITS
|
|
file name or a path name to a FILESPEC.
|
|
|
|
Return 0 if OK, -1 if bad path name format.
|
|
|
|
**********************************************************************/
|
|
|
|
fparse (s, f) char s[]; filespec *f;
|
|
|
|
{int i, c, fnc, n_slash, no_its_chars, n_dot;
|
|
char buf[7], *p, *filscan();
|
|
|
|
f->dev = f->dir = f->fn1 = f->fn2 = 0;
|
|
|
|
/* check for path name */
|
|
|
|
p = s;
|
|
no_its_chars = TRUE;
|
|
n_slash = n_dot = 0;
|
|
|
|
while (c = *p++) switch (c) {
|
|
case QUOTE: if (*p) ++p; break;
|
|
case '.': ++n_dot; break;
|
|
case '/': ++n_slash; break;
|
|
case ' ':
|
|
case ':':
|
|
case ';': no_its_chars = FALSE; break;
|
|
}
|
|
|
|
if (no_its_chars && (n_dot>0 || n_slash>0))
|
|
|
|
/* here if path name */
|
|
|
|
{p = s;
|
|
if (*p=='/')
|
|
{--n_slash;
|
|
p = filscan (buf, ++p, &n_dot, &n_slash);
|
|
f->dev = csto6(buf);
|
|
c = *p++;
|
|
if (c!='/') return (-1);
|
|
}
|
|
p = filscan (buf, p, &n_dot, &n_slash);
|
|
c = *p++;
|
|
if (c=='/')
|
|
{f->dir = csto6(buf);
|
|
p = filscan (buf, p, &n_dot, &n_slash);
|
|
c = *p++;
|
|
}
|
|
if (c=='.')
|
|
{f->fn1 = csto6(buf);
|
|
p = filscan (buf, p, &n_dot, &n_slash);
|
|
c = *p++;
|
|
}
|
|
if (f->fn1) f->fn2 = csto6(buf);
|
|
else f->fn1 = csto6(buf);
|
|
return (0);
|
|
}
|
|
|
|
/* here if ITS file name */
|
|
|
|
p = s;
|
|
fnc = i = 0;
|
|
buf[0] = 0;
|
|
|
|
do {c = *p++;
|
|
switch (c) {
|
|
|
|
case ':': f->dev = csto6(buf);
|
|
i = 0;
|
|
break;
|
|
|
|
case ';': f->dir = csto6(buf);
|
|
i = 0;
|
|
break;
|
|
|
|
case ' ':
|
|
case 0: if (buf[0]) switch (fnc++) {
|
|
case 0: f->fn1 = csto6(buf); break;
|
|
case 1: f->fn2 = csto6(buf); break;
|
|
}
|
|
i = 0;
|
|
break;
|
|
|
|
default: if (c==QUOTE && *p) c = *p++;
|
|
if (i<6) buf[i++] = c;
|
|
}
|
|
|
|
buf[i] = 0;
|
|
}
|
|
while (c);
|
|
return (0);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
FILSCAN - scan for part of file name
|
|
|
|
**********************************************************************/
|
|
|
|
char *filscan (b, q, andot, anslash)
|
|
char *b, *q;
|
|
int *andot, *anslash;
|
|
|
|
{int c;
|
|
char *p;
|
|
|
|
p = q++;
|
|
while (c = *p++)
|
|
{if (c=='/') {--*anslash; break;}
|
|
else if (c=='.')
|
|
{if (--*andot == 0 && *anslash==0 && *p &&
|
|
p!=q) break;}
|
|
else if (c==QUOTE && *p) c = *p++;
|
|
*b++ = c;
|
|
}
|
|
*b = 0;
|
|
return (--p);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
PRFILE - convert FILESPEC to ITS file name
|
|
|
|
**********************************************************************/
|
|
|
|
char *prfile(f,p) filespec *f; char *p;
|
|
|
|
{char *c6q2s();
|
|
if (f->dev) {p = c6q2s (f->dev, p); *p++ = ':';}
|
|
if (f->dir) {p = c6q2s (f->dir, p); *p++ = ';';}
|
|
if (f->fn1) {p = c6q2s (f->fn1, p); *p++ = ' ';}
|
|
if (f->fn2) {p = c6q2s (f->fn2, p);}
|
|
*p = 0;
|
|
return (p);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
FOPEN - Open file given file name
|
|
|
|
**********************************************************************/
|
|
|
|
channel fopen (fname, mode) char *fname; int mode;
|
|
|
|
{filespec f;
|
|
|
|
fparse (fname, &f);
|
|
if (f.dev == 0) f.dev = _DSK;
|
|
if (f.dir == 0) f.dir = rsname();
|
|
return (open (&f, mode));
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
OPEN - Open file given filespec
|
|
|
|
**********************************************************************/
|
|
|
|
channel open (f, mode) filespec *f; int mode;
|
|
|
|
{channel c;
|
|
int rc;
|
|
|
|
c = chnloc();
|
|
if (c<0) return (-014); /* bad channel number */
|
|
rc = sysopen (c, f, mode);
|
|
if (rc) return (rc);
|
|
return (c);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
FXARG - Process Command Arguments to Set Up
|
|
Redirection of Standard Input and Output
|
|
|
|
This routine is called by the C start-up routine.
|
|
|
|
**********************************************************************/
|
|
|
|
int riflag {TRUE}; /* set to false in binary file to suppress action */
|
|
/* pjflag being false also suppresses it */
|
|
int pjflag {TRUE}; /* set to false in binary to suppress parsing */
|
|
/* in that case, get 2 args: job name and jcl */
|
|
|
|
int fxarg (argc, argv) int argc; char *argv[];
|
|
|
|
{char **p, **q, *s;
|
|
int i, append, errappend, f;
|
|
|
|
/* suppress action ? */
|
|
if ((!pjflag) || (!riflag)) return (argc);
|
|
|
|
i = argc; /* number of arguments given */
|
|
argc = 0; /* number of arguments returned */
|
|
p = argv; /* source pointer */
|
|
q = argv; /* destination pointer */
|
|
|
|
while (--i >= 0) /* for each argument given */
|
|
{s = *p++; /* the argument */
|
|
switch (s[0]) {
|
|
case '<': if (s[1]) cinfn = s+1; break;
|
|
case '>': if (s[1] == '>')
|
|
{if (s[2]) {coutfn = s+2; append = TRUE;}}
|
|
else {if (s[1]) {coutfn = s+1; append = FALSE;}}
|
|
break;
|
|
case '%': if (s[1] == '%')
|
|
{if (s[2]) {cerrfn = s+2; errappend=TRUE;}}
|
|
else {if (s[1]) {cerrfn = s+1; errappend = FALSE;}}
|
|
break;
|
|
default: /* normal argument */
|
|
++argc; *q++ = s;
|
|
}
|
|
}
|
|
|
|
/* now hack the standard file descriptors */
|
|
|
|
if (cinfn) /* input is redirected */
|
|
{f = c0open (cinfn, 'r');
|
|
if (f != OPENLOSS) {cclose (cin); cin = f;}
|
|
}
|
|
|
|
if (coutfn) /* output is redirected */
|
|
{f = c0open (coutfn, append ? 'a' : 'w');
|
|
if (f != OPENLOSS) {cout = f;}
|
|
}
|
|
|
|
if (cerrfn) /* errout is redirected */
|
|
{f = c0open (cerrfn, errappend ? 'a' : 'w');
|
|
if (f != OPENLOSS)
|
|
{if (cerr!=cout) cclose (cerr); cerr = f;}
|
|
}
|
|
return (argc);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
C0OPEN - Open with error message
|
|
|
|
**********************************************************************/
|
|
|
|
channel c0open (name, mode)
|
|
|
|
{channel f;
|
|
|
|
f = copen (name, mode, 0);
|
|
if (f == OPENLOSS) cprint (cerr, "Unable to open '%s'\n", name);
|
|
return (f);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
C0INIT - Initialization for C I/O Routines.
|
|
This routine is normally called first by the C start-up routine.
|
|
|
|
**********************************************************************/
|
|
|
|
c0init ()
|
|
|
|
{int *p, i;
|
|
|
|
c0fcbs[0] = _magic;
|
|
p = &c0fcbs[1];
|
|
i = NCHANNEL*fcb_siz;
|
|
while (--i >= 0) *p++ = 0;
|
|
i = NCHANNEL;
|
|
while (--i >= 0)
|
|
{p = &c0fcbs[fcb_siz*i+5];
|
|
p[0] = cons (cl_bad, gc_bad);
|
|
p[1] = gc_bad;
|
|
p[2] = pc_bad;
|
|
}
|
|
|
|
cin = copen ("/tty", 'r', 0); /* standard input */
|
|
cout = cerr = copen ("/tty", 'w', 0); /* standard output */
|
|
|
|
/* These calls do not actually open the TTY, the TTY is
|
|
automatically opened when I/O is done to it. This is helpful
|
|
for allowing C programs to run without the TTY. */
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
VALRET - Valret a String
|
|
|
|
**********************************************************************/
|
|
|
|
valret (s) char *s;
|
|
|
|
{int len, bp1, bp2, buf, c, flag;
|
|
|
|
flag = FALSE;
|
|
len = slen (s);
|
|
buf = salloc (len/5 + 1);
|
|
if (buf<=0)
|
|
{buf=s; /* gross hack */
|
|
flag = TRUE;
|
|
}
|
|
bp1 = bp2 = 0440700000000 | buf;
|
|
|
|
while (TRUE)
|
|
{c = *s++;
|
|
if (c=='\n') c='\r';
|
|
idpb (c, &bp1);
|
|
if (!c) break;
|
|
}
|
|
|
|
val7ret (bp2);
|
|
if (flag) cquit(1); else sfree (buf);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
PRSARG - Parse JCL Arguments (PDP-10 ITS)
|
|
|
|
given: in - an advance byte pointer to the JCL
|
|
out - a pointer to a character buffer where the
|
|
arguments should be placed
|
|
argv - a pointer to a character pointer array
|
|
where pointers to the args should be placed
|
|
job - the sixbit XJNAME
|
|
narg - the maximum number of arguments
|
|
returns: number of arguments
|
|
|
|
**********************************************************************/
|
|
|
|
int prsarg (in, out, argv, job, narg)
|
|
char *out, *argv[];
|
|
|
|
{int c, argc;
|
|
char *c6tos();
|
|
|
|
argc = 1;
|
|
argv[0] = out;
|
|
out = c6tos (job, out);
|
|
*out++ = 0;
|
|
argv[1] = out;
|
|
if (pjflag)
|
|
{while (c = ildb (&in))
|
|
{switch (c) {
|
|
case '\r': break;
|
|
case QUOTE: *out++ = ildb (&in); continue;
|
|
case ' ': continue;
|
|
case '"': while (c = ildb (&in))
|
|
{switch (c) {
|
|
case '\r': break;
|
|
case QUOTE: *out++ = ildb (&in); continue;
|
|
case '"': break;
|
|
default: *out++ = c; continue;
|
|
}
|
|
break;
|
|
}
|
|
*out++ = 0;
|
|
if (++argc < narg) argv[argc] = out;
|
|
if (c=='"') continue;
|
|
break;
|
|
default: *out++ = c;
|
|
while (c = ildb (&in))
|
|
{switch (c) {
|
|
case '\r': break;
|
|
case ' ': break;
|
|
case QUOTE: *out++ = ildb (&in); continue;
|
|
default: *out++ = c; continue;
|
|
}
|
|
break;
|
|
}
|
|
*out++ = 0;
|
|
if (++argc < narg) argv[argc] = out;
|
|
if (c==' ') continue;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else {while (c = ildb (&in))
|
|
{switch (c) {
|
|
case '\r': break;
|
|
case QUOTE: *out++ = ildb (&in); continue;
|
|
default: *out++ = c; continue;
|
|
}
|
|
break;
|
|
}
|
|
*out++ = 0;
|
|
++argc;
|
|
}
|
|
return (argc>narg ? narg : argc);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
CONS - construct word from left and right halves
|
|
|
|
**********************************************************************/
|
|
|
|
int cons (lh, rh) {return (((lh & 0777777) << 18) | (rh & 0777777));}
|
|
|
|
|
|
/**********************************************************************
|
|
|
|
CCTO6 - convert ascii character to sixbit character
|
|
|
|
**********************************************************************/
|
|
|
|
char ccto6 (c) char c;
|
|
|
|
{return (((c>=040 && c<0140) ? c+040 : c) & 077);}
|
|
|
|
/**********************************************************************
|
|
|
|
C6TOC - convert sixbit character to ascii character
|
|
|
|
**********************************************************************/
|
|
|
|
char c6toc (c) char c;
|
|
|
|
{return (c+040);}
|
|
|
|
/**********************************************************************
|
|
|
|
CSTO6 - convert ascii string to left-justified sixbit
|
|
|
|
**********************************************************************/
|
|
|
|
int csto6 (s) char *s;
|
|
|
|
{int c,i,j;
|
|
|
|
i=0;
|
|
j=30;
|
|
while (c = *s++) if (j>=0)
|
|
{i =| (ccto6(c)<<j);
|
|
j =- 6;
|
|
}
|
|
return (i);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
C6TOS - convert left-justified sixbit word to ascii string
|
|
|
|
**********************************************************************/
|
|
|
|
char *c6tos (i, p) int i; char *p;
|
|
|
|
{int c,j;
|
|
|
|
j = 30;
|
|
while (j>=0 && (c = (i>>j)&077))
|
|
{*p++ = c6toc(c); j =- 6;}
|
|
*p = 0;
|
|
return (p);
|
|
}
|
|
|
|
/**********************************************************************
|
|
|
|
C6Q2S - convert left-justified sixbit word to ascii string,
|
|
inserting QUOTE characters, where necessary
|
|
|
|
**********************************************************************/
|
|
|
|
char *c6q2s (i, p) int i; char *p;
|
|
|
|
{int c, j;
|
|
|
|
j = 30;
|
|
while (j>=0)
|
|
{c = c6toc ((i>>j) & 077);
|
|
if (c==' ' || c==':' || c==';') *p++ = QUOTE;
|
|
*p++ = c;
|
|
if (! (i & ((1<<j) - 1))) break;
|
|
j =- 6;
|
|
}
|
|
*p = 0;
|
|
return (p);
|
|
}
|
|
|