#include "defs.h"
#include "sym.h"
#include <errno.h>
#include <fcntl.h>
static int readb(struct fileblk *, int, int);
int
word(void)
{
unsigned int c, d, cc;
struct argnod *arg = (struct argnod *)locstak();
unsigned char *argp = arg->argval;
unsigned char *oldargp;
int alpha = 1;
unsigned char *pc;
wdnum = 0;
wdset = 0;
while (1)
{
while (c = nextwc(), space(c))
;
if (c == COMCHAR)
{
while ((c = readwc()) != NL && c != EOF);
peekc = c;
}
else
{
break;
}
}
if (!eofmeta(c))
{
do
{
if (c == LITERAL)
{
oldargp = argp;
while ((c = readwc()) && c != LITERAL){
pc = readw(c);
if (argp >= brkend)
growstak(argp);
*argp++='\\';
if (c == NL)
chkpr();
while (c = *pc++) {
if (argp >= brkend)
growstak(argp);
*argp++ = (unsigned char)c;
}
}
if (argp == oldargp) {
if (argp >= brkend)
growstak(argp);
*argp++ = '"';
if (argp >= brkend)
growstak(argp);
*argp++ = '"';
}
}
else
{
if (c == 0) {
if (argp >= brkend)
growstak(argp);
*argp++ = 0;
} else {
pc = readw(c);
while (*pc) {
if (argp >= brkend)
growstak(argp);
*argp++ = *pc++;
}
}
if (c == '\\') {
if ((cc = readwc()) == 0) {
if (argp >= brkend)
growstak(argp);
*argp++ = 0;
} else {
pc = readw(cc);
while (*pc) {
if (argp >= brkend)
growstak(argp);
*argp++ = *pc++;
}
}
}
if (c == '=')
wdset |= alpha;
if (!alphanum(c))
alpha = 0;
if (qotchar(c))
{
d = c;
for (;;)
{
if ((c = nextwc()) == 0) {
if (argp >= brkend)
growstak(argp);
*argp++ = 0;
} else {
pc = readw(c);
while (*pc) {
if (argp >= brkend)
growstak(argp);
*argp++ = *pc++;
}
}
if (c == 0 || c == d)
break;
if (c == NL)
chkpr();
if (c == '\\') {
if ((cc = readwc()) == 0) {
if (argp >= brkend)
growstak(argp);
*argp++ = 0;
} else {
pc = readw(cc);
while (*pc) {
if (argp >= brkend)
growstak(argp);
*argp++ = *pc++;
}
}
}
}
}
}
} while ((c = nextwc(), !eofmeta(c)));
argp = endstak(argp);
if (!letter(arg->argval[0]))
wdset = 0;
peekn = c | MARK;
if (arg->argval[1] == 0 &&
(d = arg->argval[0], digit(d)) &&
(c == '>' || c == '<'))
{
word();
wdnum = d - '0';
}else{
if (reserv == FALSE ||
(wdval = syslook(arg->argval,
reserved, no_reserved)) == 0) {
wdval = 0;
}
wdarg = arg;
}
}else if (dipchar(c)){
if ((d = nextwc()) == c)
{
wdval = c | SYMREP;
if (c == '<')
{
if ((d = nextwc()) == '-')
wdnum |= IOSTRIP;
else
peekn = d | MARK;
}
}
else
{
peekn = d | MARK;
wdval = c;
}
}
else
{
if ((wdval = c) == EOF)
wdval = EOFSYM;
if (iopend && eolchar(c))
{
struct ionod *tmp_iopend;
tmp_iopend = iopend;
iopend = 0;
copy(tmp_iopend);
}
}
reserv = FALSE;
return (wdval);
}
unsigned int skipwc()
{
unsigned int c;
while (c = nextwc(), space(c))
;
return (c);
}
unsigned int nextwc()
{
unsigned int c, d;
retry:
if ((d = readwc()) == ESCAPE) {
if ((c = readwc()) == NL) {
chkpr();
goto retry;
}
peekc = c | MARK;
}
return (d);
}
unsigned char *readw(d)
wchar_t d;
{
static unsigned char c[MULTI_BYTE_MAX + 1];
int length;
wchar_t l;
if (isascii(d)) {
c[0] = d;
c[1] = '\0';
return (c);
}
length = wctomb((char *)c, d);
if (length <= 0) {
c[0] = (unsigned char)d;
length = 1;
}
c[length] = '\0';
return (c);
}
unsigned int
readwc()
{
wchar_t c;
int len;
struct fileblk *f;
int mbmax = MB_CUR_MAX;
int i, mlen;
if (peekn) {
c = peekn & 0x7fffffff;
peekn = 0;
return (c);
}
if (peekc) {
c = peekc & 0x7fffffff;
peekc = 0;
return (c);
}
f = standin;
retry:
if (f->fend > f->fnxt) {
if (*f->fnxt == 0) {
f->fnxt++;
f->nxtoff++;
if (f->feval == 0)
goto retry;
if (estabf(*f->feval++))
c = EOF;
else
c = SPACE;
if (flags & readpr && standin->fstak == 0)
prc(c);
if (c == NL)
f->flin++;
return (c);
}
if (isascii(c = (unsigned char)*f->fnxt)) {
f->fnxt++;
f->nxtoff++;
if (flags & readpr && standin->fstak == 0)
prc(c);
if (c == NL)
f->flin++;
return (c);
}
for (i = 1; i <= mbmax; i++) {
int rest;
if ((rest = f->fend - f->fnxt) < i) {
len = readb(f,
(f->fsiz == 1) ? 1 : (f->fsiz - rest),
rest);
if (len == 0)
break;
}
mlen = mbtowc(&c, (char *)f->fnxt, i);
if (mlen > 0)
break;
}
if (i > mbmax) {
c = (unsigned char)*f->fnxt;
mlen = 1;
}
f->fnxt += mlen;
f->nxtoff += mlen;
if (flags & readpr && standin->fstak == 0)
prwc(c);
if (c == NL)
f->flin++;
return (c);
}
if (f->feof || f->fdes < 0){
c = EOF;
f->feof++;
return (c);
}
if (readb(f, f->fsiz, 0) <= 0){
if (f->fdes != input || !isatty(input)) {
close(f->fdes);
f->fdes = -1;
}
f->feof++;
c = EOF;
return (c);
}
goto retry;
}
static int
readb(struct fileblk *f, int toread, int rest)
{
int len;
int fflags;
if (rest) {
(void) memcpy(f->fbuf, f->fnxt, rest);
f->fnxt = f->fbuf;
f->fend = f->fnxt + rest;
f->nxtoff = 0;
f->endoff = rest;
if (f->fbuf[rest - 1] == '\n') {
return (rest);
}
}
retry:
do {
if (trapnote & SIGSET) {
newline();
sigchk();
} else if ((trapnote & TRAPSET) && (rwait > 0)) {
newline();
chktrap();
clearup();
}
} while ((len = read(f->fdes, f->fbuf + rest, toread)) < 0 && trapnote);
if (len == 0) {
if (((flags & intflg) ||
((flags & oneflg) == 0 && isatty(input) &&
(flags & stdflg))) &&
((fflags = fcntl(f->fdes, F_GETFL, 0)) & O_NDELAY)) {
fflags &= ~O_NDELAY;
fcntl(f->fdes, F_SETFL, fflags);
goto retry;
}
} else if (len < 0) {
if (errno == EAGAIN) {
fflags = fcntl(f->fdes, F_GETFL, 0);
fflags &= ~O_NONBLOCK;
fcntl(f->fdes, F_SETFL, fflags);
goto retry;
}
len = 0;
}
f->fnxt = f->fbuf;
f->fend = f->fnxt + (len + rest);
f->nxtoff = 0;
f->endoff = len + rest;
return (len + rest);
}