/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include "dc.h"
#include <locale.h>
#include <stdlib.h>
#define LASTFUN 026
long longest = 0, maxsize = 0, active = 0;
int lall = 0, lrel = 0, lcopy = 0, lmore = 0, lbytes = 0;
/*
* Routine to handle sign extension of characters on systems that do not
* do automatic sign extension. This should be portable to all 2's and 1's
* complement systems that do or do not provide automatic sign
* extension. If the system provides automatic sign extension or the
* value of 'c' is positive, ctoint() will always return quickly,
* otherwise ctoint() will search for the negative value by attempting
* to wrap 'c' to 0. The number of increments needed to get to 0 is the
* negative value.
*
* Note: This assummes that the representation of values stored in chars
* is sequential and allowed to wrap, and that values < 128 are
* positive. While this is true on 1's and 2's complement machines, it
* may vary on less common architectures.
*/
#if __STDC__
int
ctoint(char c)
#else
int
ctoint(unsigned char c)
#endif
{
int i;
if ((unsigned char)c <= SCHAR_MAX)
return ((int)c); /* Normal promotion will work */
for (i = 0; c++; i--); /* Scan for negative value */
return (i);
}
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't. */
#endif
void commnds(void) __NORETURN;
int
main(int argc, char **argv)
{
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
init(argc, argv);
commnds();
/* NOTREACHED */
}
void
commnds(void)
{
int c;
struct blk *p, *q;
long l;
int sign;
struct blk **ptr, *s, *t;
struct sym *sp;
int sk, sk1, sk2;
int n, d;
int scalev; /* scaling value for converting blks to integers */
for (; ; ) {
if (((c = readc()) >= '0' && c <= '9') ||
(c >= 'A' && c <= 'F') || c == '.') {
unreadc(c);
p = readin();
pushp(p);
continue;
}
switch (c) {
case ' ':
case '\n':
case 0377:
case EOF:
continue;
case 'Y':
sdump("stk", *stkptr);
printf(gettext
("all %ld rel %ld headmor %ld\n"), all, rel,
headmor);
printf(gettext("nbytes %ld\n"), nbytes);
printf(gettext
("longest %ld active %ld maxsize %ld\n"), longest,
active, maxsize);
printf(gettext
("new all %d rel %d copy %d more %d lbytes %d\n"),
lall, lrel, lcopy, lmore, lbytes);
lall = lrel = lcopy = lmore = lbytes = 0;
continue;
case '_':
p = readin();
savk = sunputc(p);
chsign(p);
sputc(p, savk);
pushp(p);
continue;
case '-':
subt();
continue;
case '+':
if (eqk() != 0)
continue;
binop('+');
continue;
case '*':
arg1 = pop();
EMPTY;
arg2 = pop();
EMPTYR(arg1);
sk1 = sunputc(arg1);
sk2 = sunputc(arg2);
binop('*');
p = pop();
sunputc(p);
savk = n = sk1 + sk2;
if (n > k && n > sk1 && n > sk2) {
sk = sk1;
if (sk < sk2)
sk = sk2;
if (sk < k)
sk = k;
p = removc(p, n - sk);
savk = sk;
}
sputc(p, savk);
pushp(p);
continue;
case '/':
casediv:
if (dscale() != 0)
continue;
binop('/');
if (irem != 0)
release(irem);
release(rem);
continue;
case '%':
if (dscale() != 0)
continue;
binop('/');
p = pop();
release(p);
if (irem == 0) {
sputc(rem, skr + k);
pushp(rem);
continue;
}
p = add0(rem, skd - (skr + k));
q = add(p, irem);
release(p);
release(irem);
sputc(q, skd);
pushp(q);
continue;
case 'v':
p = pop();
EMPTY;
savk = sunputc(p);
if (length(p) == 0) {
sputc(p, savk);
pushp(p);
continue;
}
if ((c = sbackc(p)) < 0) {
error(gettext("sqrt of neg number\n"));
}
if (k < savk)
n = savk;
else {
n = k * 2 - savk;
savk = k;
}
arg1 = add0(p, n);
arg2 = sqrt(arg1);
sputc(arg2, savk);
pushp(arg2);
continue;
case '^':
neg = 0;
arg1 = pop();
EMPTY;
if (sunputc(arg1) != 0)
error(gettext("exp not an integer\n"));
arg2 = pop();
EMPTYR(arg1);
if (sfbeg(arg1) == 0 && sbackc(arg1) < 0) {
neg++;
chsign(arg1);
}
if (length(arg1) >= 3)
error(gettext("exp too big\n"));
savk = sunputc(arg2);
p = exp(arg2, arg1);
release(arg2);
rewind(arg1);
c = sgetc(arg1);
if (c == EOF)
c = 0;
else if (sfeof(arg1) == 0)
c = sgetc(arg1) * 100 + c;
d = c * savk;
release(arg1);
if (k >= savk)
n = k;
else
n = savk;
if (n < d) {
q = removc(p, d - n);
sputc(q, n);
pushp(q);
} else {
sputc(p, d);
pushp(p);
}
if (neg == 0)
continue;
p = pop();
q = salloc(2);
sputc(q, 1);
sputc(q, 0);
pushp(q);
pushp(p);
goto casediv;
case 'z':
p = salloc(2);
n = stkptr - stkbeg;
if (n >= 100) {
sputc(p, n / 100);
n %= 100;
}
sputc(p, n);
sputc(p, 0);
pushp(p);
continue;
case 'Z':
p = pop();
EMPTY;
n = (length(p) - 1) << 1;
fsfile(p);
sbackc(p);
if (sfbeg(p) == 0) {
if ((c = sbackc(p)) < 0) {
n -= 2;
if (sfbeg(p) == 1)
n += 1;
else {
if ((c = sbackc(p)) == 0)
n += 1;
else if (c > 90)
n -= 1;
}
} else
if (c < 10)
n -= 1;
}
release(p);
q = salloc(1);
if (n >= 100) {
sputc(q, n%100);
n /= 100;
}
sputc(q, n);
sputc(q, 0);
pushp(q);
continue;
case 'i':
p = pop();
EMPTY;
p = scalint(p);
/*
* POSIX.2
* input base must be between 2 and 16
*/
n = length(p);
q = copy(p, n);
fsfile(q);
c = sbackc(q);
if (sfbeg(q) == 0)
error(gettext("input base is too large\n"));
if (c < 2)
error(gettext("input base is too small\n"));
if (c > 16)
error(gettext("input base is too large\n"));
release(q);
release(inbas);
inbas = p;
continue;
case 'I':
p = copy(inbas, length(inbas) + 1);
sputc(p, 0);
pushp(p);
continue;
case 'o':
p = pop();
EMPTY;
p = scalint(p);
sign = 0;
n = length(p);
q = copy(p, n);
fsfile(q);
l = c = sbackc(q);
if (n != 1) {
if (c < 0) {
sign = 1;
chsign(q);
n = length(q);
fsfile(q);
l = c = sbackc(q);
}
if (n != 1) {
while (sfbeg(q) == 0)
l = l * 100 + sbackc(q);
}
}
/*
* POSIX.2
* Check that output base is less than or equal
* BC_BASE_MAX.
*/
if (l > BC_BASE_MAX)
error(gettext("output base is too large\n"));
logo = log2(l);
obase = l;
release(basptr);
if (sign == 1)
obase = -l;
basptr = p;
outdit = bigot;
if (n == 1 && sign == 0) {
if (c <= 16) {
outdit = hexot;
fw = 1;
fw1 = 0;
/*
* POSIX.2
* Line length is 70 characters,
* including newline.
*/
ll = 70;
release(q);
continue;
}
}
n = 0;
if (sign == 1)
n++;
p = salloc(1);
sputc(p, -1);
t = add(p, q);
n += length(t) * 2;
fsfile(t);
if ((c = sbackc(t)) > 9)
n++;
release(t);
release(q);
release(p);
fw = n;
fw1 = n-1;
/*
* POSIX.2
* Line length is 70 characters including newline
*/
ll = 70;
if (fw >= ll)
continue;
ll = (70 / fw) * fw;
continue;
case 'O':
p = copy(basptr, length(basptr) + 1);
sputc(p, 0);
pushp(p);
continue;
case '[':
n = 0;
p = salloc(0);
for (; ; ) {
if ((c = readc()) == ']') {
if (n == 0)
break;
n--;
}
sputc(p, c);
if (c == '[')
n++;
}
pushp(p);
continue;
case 'k':
p = pop();
EMPTY;
p = scalint(p);
/*
* POSIX.2
* Make sure scaling factor is between 0 and
* BC_SCALE_MAX. Copy p to q and figure the
* scaling factor.
*/
n = length(p);
q = copy(p, n);
fsfile(q);
c = 0;
if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0))
error(gettext("invalid scale factor\n"));
scalev = 1;
while (c < BC_SCALE_MAX && sfbeg(q) == 0)
c = (c * (scalev *= 100)) + sbackc(q);
if (c > BC_SCALE_MAX)
error(gettext("scale factor is too large\n"));
release(q);
rewind(p);
k = sfeof(p) ? 0 : sgetc(p);
release(scalptr);
scalptr = p;
continue;
case 'K':
p = copy(scalptr, length(scalptr) + 1);
sputc(p, 0);
pushp(p);
continue;
case 'X':
p = pop();
EMPTY;
fsfile(p);
n = sbackc(p);
release(p);
p = salloc(2);
sputc(p, n);
sputc(p, 0);
pushp(p);
continue;
case 'Q':
p = pop();
EMPTY;
if (length(p) > 2) {
error("Q?\n");
}
rewind(p);
if ((c = sgetc(p)) < 0) {
error(gettext("neg Q\n"));
}
release(p);
while (c-- > 0) {
if (readptr == &readstk[0]) {
error("readstk?\n");
}
if (*readptr != 0)
release(*readptr);
readptr--;
}
continue;
case 'q':
if (readptr <= &readstk[1])
exit(0);
if (*readptr != 0)
release(*readptr);
readptr--;
if (*readptr != 0)
release(*readptr);
readptr--;
continue;
case 'f':
if (stkptr == &stack[0])
printf(gettext("empty stack\n"));
else {
for (ptr = stkptr; ptr > &stack[0]; ) {
print(*ptr--);
}
}
continue;
case 'p':
if (stkptr == &stack[0])
printf(gettext("empty stack\n"));
else {
print(*stkptr);
}
continue;
case 'P':
p = pop();
EMPTY;
sputc(p, 0);
printf("%s", p->beg);
release(p);
continue;
case 'd':
if (stkptr == &stack[0]) {
printf(gettext("empty stack\n"));
continue;
}
q = *stkptr;
n = length(q);
p = copy(*stkptr, n);
pushp(p);
continue;
case 'c':
while (stkerr == 0) {
p = pop();
if (stkerr == 0)
release(p);
}
continue;
case 'S':
if (stkptr == &stack[0]) {
error(gettext("save: args\n"));
}
c = readc() & 0377;
sptr = stable[c];
sp = stable[c] = sfree;
sfree = sfree->next;
if (sfree == 0)
goto sempty;
sp->next = sptr;
p = pop();
EMPTY;
if (c >= ARRAYST) {
q = copy(p, length(p) + PTRSZ);
for (n = 0; n < PTRSZ; n++) {
sputc(q, 0);
}
release(p);
p = q;
}
sp->val = p;
continue;
sempty:
error(gettext("symbol table overflow\n"));
case 's':
if (stkptr == &stack[0]) {
error(gettext("save:args\n"));
}
c = readc() & 0377;
sptr = stable[c];
if (sptr != 0) {
p = sptr->val;
if (c >= ARRAYST) {
rewind(p);
while (sfeof(p) == 0)
release(getwd(p));
}
release(p);
} else {
sptr = stable[c] = sfree;
sfree = sfree->next;
if (sfree == 0)
goto sempty;
sptr->next = 0;
}
p = pop();
sptr->val = p;
continue;
case 'l':
load();
continue;
case 'L':
c = readc() & 0377;
sptr = stable[c];
if (sptr == 0) {
error("L?\n");
}
stable[c] = sptr->next;
sptr->next = sfree;
sfree = sptr;
p = sptr->val;
if (c >= ARRAYST) {
rewind(p);
while (sfeof(p) == 0) {
q = getwd(p);
if (q != 0)
release(q);
}
}
pushp(p);
continue;
case ':':
p = pop();
EMPTY;
q = scalint(p);
fsfile(q);
/*
* POSIX.2
* Make sure index is between 0 and BC_DIM_MAX-1
*/
c = 0;
if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0))
error(gettext("invalid index\n"));
scalev = 1;
while (c < BC_DIM_MAX && sfbeg(q) == 0)
c = (c * (scalev *= 100)) + sbackc(q);
if (c >= BC_DIM_MAX)
error(gettext("index is too large\n"));
release(q);
n = readc() & 0377;
sptr = stable[n];
if (sptr == 0) {
sptr = stable[n] = sfree;
sfree = sfree->next;
if (sfree == 0)
goto sempty;
sptr->next = 0;
p = salloc((c + PTRSZ) * PTRSZ);
zero(p);
} else {
p = sptr->val;
if (length(p) - PTRSZ < c * PTRSZ) {
q = copy(p, (c + PTRSZ) * PTRSZ);
release(p);
p = q;
}
}
seekc(p, c * PTRSZ);
q = lookwd(p);
if (q != NULL)
release(q);
s = pop();
EMPTY;
salterwd((struct wblk *)p, s);
sptr->val = p;
continue;
case ';':
p = pop();
EMPTY;
q = scalint(p);
fsfile(q);
/*
* POSIX.2
* Make sure index is between 0 and BC_DIM_MAX-1
*/
c = 0;
if ((sfbeg(q) == 0) && ((c = sbackc(q)) < 0))
error(gettext("invalid index\n"));
scalev = 1;
while (c < BC_DIM_MAX && sfbeg(q) == 0)
c = (c * (scalev *= 100)) + sbackc(q);
if (c >= BC_DIM_MAX)
error(gettext("index is too large\n"));
release(q);
n = readc() & 0377;
sptr = stable[n];
if (sptr != 0) {
p = sptr->val;
if (length(p) - PTRSZ >= c * PTRSZ) {
seekc(p, c * PTRSZ);
s = getwd(p);
if (s != 0) {
q = copy(s, length(s));
pushp(q);
continue;
}
}
}
q = salloc(1); /* uninitializd array elt prints as 0 */
sputc(q, 0);
pushp(q);
continue;
case 'x':
execute:
p = pop();
EMPTY;
if ((readptr != &readstk[0]) && (*readptr != 0)) {
if ((*readptr)->rd == (*readptr)->wt)
release(*readptr);
else {
if (readptr++ == &readstk[RDSKSZ]) {
error(gettext
("nesting depth\n"));
}
}
} else
readptr++;
*readptr = p;
if (p != 0)
rewind(p);
else {
if ((c = readc()) != '\n')
unreadc(c);
}
continue;
case '?':
if (++readptr == &readstk[RDSKSZ]) {
error(gettext("nesting depth\n"));
}
*readptr = 0;
fsave = curfile;
curfile = stdin;
while ((c = readc()) == '!')
command();
p = salloc(0);
sputc(p, c);
while ((c = readc()) != '\n') {
sputc(p, c);
if (c == '\\')
sputc(p, readc());
}
curfile = fsave;
*readptr = p;
continue;
case '!':
if (command() == 1)
goto execute;
continue;
case '<':
case '>':
case '=':
if (cond(c) == 1)
goto execute;
continue;
default:
printf(gettext("%o is unimplemented\n"), c);
}
}
}
struct blk *
dcdiv(struct blk *ddivd, struct blk *ddivr)
{
int divsign, remsign, offset, divcarry;
int carry, dig, magic, d, dd, under;
long c, td, cc;
struct blk *ps, *px;
struct blk *p, *divd, *divr;
rem = 0;
p = salloc(0);
if (length(ddivr) == 0) {
pushp(ddivr);
printf(gettext("divide by 0\n"));
return (p);
}
divsign = remsign = 0;
divr = ddivr;
fsfile(divr);
if (sbackc(divr) == -1) {
divr = copy(ddivr, length(ddivr));
chsign(divr);
divsign = ~divsign;
}
divd = copy(ddivd, length(ddivd));
fsfile(divd);
if (sfbeg(divd) == 0 && sbackc(divd) == -1) {
chsign(divd);
divsign = ~divsign;
remsign = ~remsign;
}
offset = length(divd) - length(divr);
if (offset < 0)
goto ddone;
seekc(p, offset + 1);
sputc(divd, 0);
magic = 0;
fsfile(divr);
c = sbackc(divr);
if (c < 10)
magic++;
c = c * 100 + (sfbeg(divr)?0:sbackc(divr));
if (magic > 0) {
c = (c * 100 +(sfbeg(divr)?0:sbackc(divr)))*2;
c /= 25;
}
while (offset >= 0) {
fsfile(divd);
td = sbackc(divd) * 100;
dd = sfbeg(divd)?0:sbackc(divd);
td = (td + dd) * 100;
dd = sfbeg(divd)?0:sbackc(divd);
td = td + dd;
cc = c;
if (offset == 0)
td++;
else
cc++;
if (magic != 0)
td = td<<3;
dig = td/cc;
under = 0;
if (td%cc < 8 && dig > 0 && magic) {
dig--;
under = 1;
}
rewind(divr);
rewind(divxyz);
carry = 0;
while (sfeof(divr) == 0) {
d = sgetc(divr) * dig + carry;
carry = d / 100;
salterc(divxyz, d % 100);
}
salterc(divxyz, carry);
rewind(divxyz);
seekc(divd, offset);
carry = 0;
while (sfeof(divd) == 0) {
d = slookc(divd);
d = d - (sfeof(divxyz) ? 0 : sgetc(divxyz)) - carry;
carry = 0;
if (d < 0) {
d += 100;
carry = 1;
}
salterc(divd, d);
}
divcarry = carry;
sbackc(p);
salterc(p, dig);
sbackc(p);
fsfile(divd);
d = sbackc(divd);
if ((d != 0) && /* !divcarry */ (offset != 0)) {
d = sbackc(divd) + 100;
salterc(divd, d);
}
if (--offset >= 0) {
divd->wt--;
}
}
if (under) { /* undershot last - adjust */
px = copy(divr, length(divr)); /* 11/88 don't corrupt ddivr */
chsign(px);
ps = add(px, divd);
fsfile(ps);
if (length(ps) > 0 && sbackc(ps) < 0) {
release(ps); /* only adjust in really undershot */
} else {
release(divd);
salterc(p, dig + 1);
divd = ps;
}
}
if (divcarry != 0) {
salterc(p, dig - 1);
salterc(divd, -1);
ps = add(divr, divd);
release(divd);
divd = ps;
}
rewind(p);
divcarry = 0;
while (sfeof(p) == 0) {
d = slookc(p) + divcarry;
divcarry = 0;
if (d >= 100) {
d -= 100;
divcarry = 1;
}
salterc(p, d);
}
if (divcarry != 0)
salterc(p, divcarry);
fsfile(p);
while (sfbeg(p) == 0) {
if (sbackc(p) == 0)
truncate(p);
else break;
}
if (divsign < 0)
chsign(p);
fsfile(divd);
while (sfbeg(divd) == 0) {
if (sbackc(divd) == 0)
truncate(divd);
else break;
}
ddone:
if (remsign < 0)
chsign(divd);
if (divr != ddivr)
release(divr);
rem = divd;
return (p);
}
int
dscale(void)
{
struct blk *dd, *dr, *r;
int c;
dr = pop();
EMPTYS;
dd = pop();
EMPTYSR(dr);
fsfile(dd);
skd = sunputc(dd);
fsfile(dr);
skr = sunputc(dr);
if (sfbeg(dr) == 1 || (sfbeg(dr) == 0 && sbackc(dr) == 0)) {
sputc(dr, skr);
pushp(dr);
printf(gettext("divide by 0\n"));
return (1);
}
if (sfbeg(dd) == 1 || (sfbeg(dd) == 0 && sbackc(dd) == 0)) {
#ifdef XPG6
sputc(dd, k);
#else
sputc(dd, skd);
#endif
pushp(dd);
return (1);
}
c = k-skd+skr;
if (c < 0)
r = removr(dd, -c);
else {
r = add0(dd, c);
irem = 0;
}
arg1 = r;
arg2 = dr;
savk = k;
return (0);
}
struct blk *
removr(struct blk *p, int n)
{
int nn, neg;
struct blk *q, *s, *r;
fsfile(p);
neg = sbackc(p);
if (neg < 0)
chsign(p);
rewind(p);
nn = (n + 1) / 2;
q = salloc(nn);
while (n > 1) {
sputc(q, sgetc(p));
n -= 2;
}
r = salloc(2);
while (sfeof(p) == 0)
sputc(r, sgetc(p));
release(p);
if (n == 1) {
s = dcdiv(r, tenptr);
release(r);
rewind(rem);
if (sfeof(rem) == 0)
sputc(q, sgetc(rem));
release(rem);
if (neg < 0) {
chsign(s);
chsign(q);
irem = q;
return (s);
}
irem = q;
return (s);
}
if (neg < 0) {
chsign(r);
chsign(q);
irem = q;
return (r);
}
irem = q;
return (r);
}
struct blk *
sqrt(struct blk *p)
{
struct blk *r, *q, *s, *t;
int c, n, nn;
n = length(p);
fsfile(p);
c = sbackc(p);
if ((n & 1) != 1)
c = c * 100 + (sfbeg(p) ? 0 : sbackc(p));
n = (n + 1) >> 1;
r = salloc(n);
zero(r);
seekc(r, n);
nn = 1;
while ((c -= nn) >= 0)
nn += 2;
c = (nn + 1) >> 1;
fsfile(r);
sbackc(r);
if (c >= 100) {
c -= 100;
salterc(r, c);
sputc(r, 1);
} else
salterc(r, c);
for (; ; ) {
q = dcdiv(p, r);
s = add(q, r);
release(q);
release(rem);
q = dcdiv(s, sqtemp);
release(s);
release(rem);
s = copy(r, length(r));
chsign(s);
t = add(s, q);
release(s);
fsfile(t);
nn = sfbeg(t) ? 0 : sbackc(t);
if (nn >= 0)
break;
release(r);
release(t);
r = q;
}
release(t);
release(q);
release(p);
return (r);
}
struct blk *
exp(struct blk *base, struct blk *ex)
{
struct blk *r, *e, *p, *e1, *t, *cp;
int temp, c, n;
r = salloc(1);
sputc(r, 1);
p = copy(base, length(base));
e = copy(ex, length(ex));
fsfile(e);
if (sfbeg(e) != 0)
goto edone;
temp = 0;
c = sbackc(e);
if (c < 0) {
temp++;
chsign(e);
}
while (length(e) != 0) {
e1 = dcdiv(e, sqtemp);
release(e);
e = e1;
n = length(rem);
release(rem);
if (n != 0) {
e1 = mult(p, r);
release(r);
r = e1;
}
t = copy(p, length(p));
cp = mult(p, t);
release(p);
release(t);
p = cp;
}
if (temp != 0) {
if ((c = length(base)) == 0) {
goto edone;
}
if (c > 1)
create(r);
else {
rewind(base);
if ((c = sgetc(base)) <= 1) {
create(r);
sputc(r, c);
} else
create(r);
}
}
edone:
release(p);
release(e);
return (r);
}
void
init(int argc, char **argv)
{
struct sym *sp;
char *dcmalloc();
struct stat tsb;
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, onintr);
setbuf(stdout, (char *)NULL);
svargc = --argc;
svargv = argv;
while (svargc > 0 && svargv[1][0] == '-') {
switch (svargv[1][1]) {
default:
dbg = 1;
}
svargc--;
svargv++;
}
ifile = 1;
if (svargc <= 0)
curfile = stdin;
else {
if (stat(svargv[1], &tsb) < 0) {
printf(gettext("Cannot stat %s: "), svargv[1]);
perror("");
exit(1);
}
if (S_ISREG(tsb.st_mode)) {
if ((curfile = fopen(svargv[1], "r")) == NULL) {
printf(gettext("can't open file %s\n"), \
svargv[1]);
exit(1);
}
} else {
printf(gettext("invalid file type: %s\n"), \
svargv[1]);
exit(1);
}
}
dummy = dcmalloc(0);
scalptr = salloc(1);
sputc(scalptr, 0);
basptr = salloc(1);
sputc(basptr, 10);
obase = 10;
log10 = log2(10L);
/*
* POSIX.2
* default line length is 70 characters including newline
*/
ll = 70;
fw = 1;
fw1 = 0;
tenptr = salloc(1);
sputc(tenptr, 10);
obase = 10;
inbas = salloc(1);
sputc(inbas, 10);
sqtemp = salloc(1);
sputc(sqtemp, 2);
chptr = salloc(0);
strptr = salloc(0);
divxyz = salloc(0);
stkbeg = stkptr = &stack[0];
stkend = &stack[STKSZ];
stkerr = 0;
readptr = &readstk[0];
k = 0;
sp = sptr = &symlst[0];
while (sptr < &symlst[TBLSZ]) {
sptr->next = ++sp;
sptr++;
}
sptr->next = 0;
sfree = &symlst[0];
}
void
onintr(int sig)
{
signal(sig, onintr);
while (readptr != &readstk[0]) {
if (*readptr != 0)
release(*readptr);
readptr--;
}
curfile = stdin;
commnds();
}
void
pushp(struct blk *p)
{
if (stkptr == stkend)
printf(gettext("out of stack space\n"));
else {
stkerr = 0;
*++stkptr = p;
}
}
struct blk *
pop(void)
{
if (stkptr == stack) {
stkerr = 1;
return (0);
}
return (*stkptr--);
}
struct blk *
readin(void)
{
struct blk *p, *q;
int dp, dpct;
int c;
dp = dpct = 0;
p = salloc(0);
for (; ; ) {
c = readc();
switch (c) {
case '.':
if (dp != 0)
goto gotnum;
dp++;
continue;
case '\\':
readc();
continue;
default:
if (c >= 'A' && c <= 'F')
c = c - 'A' + 10;
else
if (c >= '0' && c <= '9')
c -= '0';
else
goto gotnum;
if (dp != 0) {
if (dpct >= 99)
continue;
dpct++;
}
create(chptr);
if (c != 0)
sputc(chptr, c);
q = mult(p, inbas);
release(p);
p = add(chptr, q);
release(q);
}
}
gotnum:
unreadc(c);
if (dp == 0) {
sputc(p, 0);
return (p);
} else {
/* if not base 10, then scale fractional input to precision */
if (((int)*(inbas->beg)) != 10) {
while (dpct < k) {
create(chptr);
q = mult(p, inbas);
release(p);
p = add(chptr, q);
release(q);
dpct++;
}
}
q = scale(p, dpct);
return (q);
}
}
/*
* returns pointer to struct with ct 0's & p
*/
struct blk *
add0(struct blk *p, int ct)
{
struct blk *q, *t;
q = salloc(length(p) + (ct + 1) / 2);
while (ct > 1) {
sputc(q, 0);
ct -= 2;
}
rewind(p);
while (sfeof(p) == 0) {
sputc(q, sgetc(p));
}
release(p);
if (ct == 1) {
t = mult(tenptr, q);
release(q);
return (t);
}
return (q);
}
struct blk *
mult(struct blk *p, struct blk *q)
{
struct blk *mp, *mq, *mr;
int sign, offset, carry;
int cq, cp, mt, mcr;
offset = sign = 0;
fsfile(p);
mp = p;
if (sfbeg(p) == 0) {
if (sbackc(p) < 0) {
mp = copy(p, length(p));
chsign(mp);
sign = ~sign;
}
}
fsfile(q);
mq = q;
if (sfbeg(q) == 0) {
if (sbackc(q) < 0) {
mq = copy(q, length(q));
chsign(mq);
sign = ~sign;
}
}
mr = salloc(length(mp) + length(mq));
zero(mr);
rewind(mq);
while (sfeof(mq) == 0) {
cq = sgetc(mq);
rewind(mp);
rewind(mr);
mr->rd += offset;
carry = 0;
while (sfeof(mp) == 0) {
cp = sgetc(mp);
mcr = sfeof(mr) ? 0 : slookc(mr);
mt = cp*cq + carry + mcr;
carry = mt / 100;
salterc(mr, mt % 100);
}
offset++;
if (carry != 0) {
mcr = sfeof(mr) ? 0 : slookc(mr);
salterc(mr, mcr + carry);
}
}
if (sign < 0) {
chsign(mr);
}
if (mp != p)
release(mp);
if (mq != q)
release(mq);
return (mr);
}
void
chsign(struct blk *p)
{
int carry;
char ct;
carry = 0;
rewind(p);
while (sfeof(p) == 0) {
ct = 100 - slookc(p) - carry;
carry = 1;
if (ct >= 100) {
ct -= 100;
carry = 0;
}
salterc(p, ct);
}
if (carry != 0) {
sputc(p, -1);
fsfile(p);
sbackc(p);
ct = sbackc(p);
if (ct == 99) {
truncate(p);
sputc(p, -1);
}
} else {
fsfile(p);
ct = sbackc(p);
if (ct == 0)
truncate(p);
}
}
char
readc(void)
{
loop:
if ((readptr != &readstk[0]) && (*readptr != 0)) {
if (sfeof(*readptr) == 0)
return (lastchar = sgetc(*readptr));
release(*readptr);
readptr--;
goto loop;
}
lastchar = getc(curfile);
if (lastchar != EOF)
return (lastchar);
if (readptr != &readptr[0]) {
readptr--;
if (*readptr == 0)
curfile = stdin;
goto loop;
}
if (curfile != stdin) {
fclose(curfile);
curfile = stdin;
goto loop;
}
exit(0);
}
void
unreadc(char c)
{
if ((readptr != &readstk[0]) && (*readptr != 0)) {
sungetc(*readptr, c);
} else
ungetc(c, curfile);
}
void
binop(char c)
{
struct blk *r;
switch (c) {
case '+':
r = add(arg1, arg2);
break;
case '*':
r = mult(arg1, arg2);
break;
case '/':
r = dcdiv(arg1, arg2);
break;
}
release(arg1);
release(arg2);
sputc(r, savk);
pushp(r);
}
void
print(struct blk *hptr)
{
struct blk *p, *q, *dec;
int sc; /* scale */
int dig, dout, ct;
rewind(hptr);
while (sfeof(hptr) == 0) {
if (sgetc(hptr) > 99) {
rewind(hptr);
while (sfeof(hptr) == 0) {
printf("%c", sgetc(hptr));
}
printf("\n");
return;
}
}
fsfile(hptr);
sc = sbackc(hptr); /* read scale off end of blk */
if (sfbeg(hptr) != 0) {
printf("0\n");
return;
}
count = ll;
p = copy(hptr, length(hptr));
sunputc(p);
fsfile(p);
if (sbackc(p) < 0) {
chsign(p);
OUTC('-');
}
if ((obase == 0) || (obase == -1)) {
oneot(p, sc, 'd');
return;
}
if (obase == 1) {
oneot(p, sc, '1');
return;
}
if (obase == 10) {
tenot(p, sc);
return;
}
create(strptr);
dig = log10 * sc;
dout = ((dig / 10) + dig) / logo;
dec = getdec(p, sc);
p = removc(p, sc);
while (length(p) != 0) {
q = dcdiv(p, basptr);
release(p);
p = q;
(*outdit)(rem, 0);
if (obase > 16)
sputc(strptr, ' ');
}
release(p);
fsfile(strptr);
while (sfbeg(strptr) == 0)
OUTC(sbackc(strptr));
if (sc == 0) {
release(dec);
printf("\n");
return;
}
create(strptr);
OUTC('.');
ct = 0;
do {
if (ct != 0 && obase > 16)
sputc(strptr, ' ');
q = mult(basptr, dec);
release(dec);
dec = getdec(q, sc);
p = removc(q, sc);
(*outdit)(p, 1);
} while (++ct < dout);
release(dec);
rewind(strptr);
while (sfeof(strptr) == 0)
OUTC(sgetc(strptr));
printf("\n");
}
struct blk *
getdec(struct blk *p, int sc)
{
int cc;
struct blk *q, *t, *s;
rewind(p);
if (length(p) * 2 < sc) {
q = copy(p, length(p));
return (q);
}
q = salloc(length(p));
while (sc >= 1) {
sputc(q, sgetc(p));
sc -= 2;
}
if (sc != 0) {
t = mult(q, tenptr);
s = salloc(cc = length(q));
release(q);
rewind(t);
while (cc-- > 0)
sputc(s, sgetc(t));
sputc(s, 0);
release(t);
t = dcdiv(s, tenptr);
release(s);
release(rem);
return (t);
}
return (q);
}
void
tenot(struct blk *p, int sc)
{
int c, f;
fsfile(p);
f = 0;
/*
* at this point, the number is stored as base 100 (two decimal
* digits per char) stuck in a buf (character array) backwards.
* sc indicates the scaling factor.
*/
while ((sfbeg(p) == 0) && ((p->rd-p->beg-1)*2 >= sc)) {
/*
* get numbers from the buf until we are the beginning of
* the buf (i.e., there are no more numbers) or the numbers
* remaining fall within the scaled (to the right of the
* decimal point) portion.
*/
c = sbackc(p);
/*
* POSIX.2
* as we output digits, we have to watch the line length (ll)
* which should include a '\' and a newline.
*/
if (c < 10) {
/*
* if the number is less than 10, we need to output
* a space-holding '0' (unless this is the first time
* through).
*/
if (f == 1) {
CHECKEND;
printf("0");
count--;
}
CHECKEND;
printf("%d", c);
count--;
} else {
CHECKEND;
printf("%d", c / 10);
count--;
CHECKEND;
printf("%d", c % 10);
count--;
}
f = 1;
}
if (sc == 0) {
/*
* no scaling factor, so we must have exited loop because we
* ran out of numbers.
*/
printf("\n");
release(p);
return;
}
if ((p->rd - p->beg) * 2 > sc) {
c = sbackc(p);
CHECKEND;
printf("%d", c / 10);
count--;
CHECKEND;
printf(".");
count--;
CHECKEND;
printf("%d", c % 10);
count--;
sc--;
} else {
CHECKEND;
printf(".");
count--;
}
if (sc > (p->rd - p->beg) * 2) {
while (sc > (p->rd - p->beg) * 2) {
CHECKEND;
printf("0");
count--;
sc--;
}
}
/* now go through the scaled portion of the number */
while (sc > 1) {
c = sbackc(p);
if (c < 10) {
CHECKEND;
printf("0");
count--;
CHECKEND;
printf("%d", c);
count--;
} else {
CHECKEND;
printf("%d", c / 10);
count--;
CHECKEND;
printf("%d", c % 10);
count--;
}
sc -= 2;
}
if (sc == 1) { /* just in case the scaling factor was odd */
CHECKEND;
printf("%d", sbackc(p) / 10);
}
printf("\n");
release(p);
}
void
oneot(struct blk *p, int sc, char ch)
{
struct blk *q;
q = removc(p, sc);
create(strptr);
sputc(strptr, -1);
while (length(q) > 0) {
p = add(strptr, q);
release(q);
q = p;
OUTC(ch);
}
release(q);
printf("\n");
}
void
hexot(struct blk *p, int flg)
{
int c;
rewind(p);
if (sfeof(p) != 0) {
sputc(strptr, '0');
release(p);
return;
}
c = sgetc(p);
release(p);
if (c >= 16) {
printf(gettext("hex digit > 16"));
return;
}
sputc(strptr, c < 10 ? c + '0' : c - 10 + 'A');
}
void
bigot(struct blk *p, int flg)
{
struct blk *t, *q;
int l;
int neg;
if (flg == 1)
t = salloc(0);
else {
t = strptr;
l = length(strptr) + fw - 1;
}
neg = 0;
if (length(p) != 0) {
fsfile(p);
if (sbackc(p) < 0) {
neg = 1;
chsign(p);
}
while (length(p) != 0) {
q = dcdiv(p, tenptr);
release(p);
p = q;
rewind(rem);
sputc(t, sfeof(rem) ? '0' : sgetc(rem) + '0');
release(rem);
}
}
release(p);
if (flg == 1) {
l = fw1 - length(t);
if (neg != 0) {
l--;
sputc(strptr, '-');
}
fsfile(t);
while (l-- > 0)
sputc(strptr, '0');
while (sfbeg(t) == 0)
sputc(strptr, sbackc(t));
release(t);
} else {
l -= length(strptr);
while (l-- > 0)
sputc(strptr, '0');
if (neg != 0) {
sunputc(strptr);
sputc(strptr, '-');
}
}
}
struct blk *
add(struct blk *a1, struct blk *a2)
{
struct blk *p;
int carry, n;
int size;
int c, n1, n2;
size = length(a1) > length(a2) ? length(a1) : length(a2);
p = salloc(size);
rewind(a1);
rewind(a2);
carry = 0;
while (--size >= 0) {
n1 = sfeof(a1) ? 0 : sgetc(a1);
n2 = sfeof(a2) ? 0 : sgetc(a2);
n = n1 + n2 + carry;
if (n >= 100) {
carry = 1;
n -= 100;
} else
if (n < 0) {
carry = -1;
n += 100;
} else
carry = 0;
sputc(p, n);
}
if (carry != 0)
sputc(p, carry);
fsfile(p);
if (sfbeg(p) == 0) {
while (sfbeg(p) == 0 && (c = sbackc(p)) == 0);
if (c != 0)
salterc(p, c);
truncate(p);
}
fsfile(p);
if (sfbeg(p) == 0 && sbackc(p) == -1) {
while ((c = sbackc(p)) == 99) {
if (c == EOF)
break;
}
sgetc(p);
salterc(p, -1);
truncate(p);
}
return (p);
}
int
eqk(void) {
struct blk *p, *q;
int skp, skq;
p = pop();
EMPTYS;
q = pop();
EMPTYSR(p);
skp = sunputc(p);
skq = sunputc(q);
if (skp == skq) {
arg1 = p;
arg2 = q;
savk = skp;
return (0);
} else
if (skp < skq) {
savk = skq;
p = add0(p, skq - skp);
} else {
savk = skp;
q = add0(q, skp - skq);
}
arg1 = p;
arg2 = q;
return (0);
}
struct blk *
removc(struct blk *p, int n)
{
struct blk *q, *r;
rewind(p);
while (n > 1) {
sgetc(p);
n -= 2;
}
q = salloc(2);
while (sfeof(p) == 0)
sputc(q, sgetc(p));
if (n == 1) {
r = dcdiv(q, tenptr);
release(q);
release(rem);
q = r;
}
release(p);
return (q);
}
struct blk *
scalint(struct blk *p)
{
int n;
n = sunputc(p);
p = removc(p, n);
return (p);
}
struct blk *
scale(struct blk *p, int n)
{
struct blk *q, *s, *t;
t = add0(p, n);
q = salloc(1);
sputc(q, n);
s = exp(inbas, q);
release(q);
q = dcdiv(t, s);
release(t);
release(s);
release(rem);
sputc(q, n);
return (q);
}
int
subt(void)
{
arg1 = pop();
EMPTYS;
savk = sunputc(arg1);
chsign(arg1);
sputc(arg1, savk);
pushp(arg1);
if (eqk() != 0)
return (1);
binop('+');
return (0);
}
int
command(void)
{
int c;
char line[100], *sl;
void (*savint)();
pid_t pid, rpid;
int retcode;
switch (c = readc()) {
case '<':
return (cond(NL));
case '>':
return (cond(NG));
case '=':
return (cond(NE));
default:
sl = line;
*sl++ = c;
while ((c = readc()) != '\n')
*sl++ = c;
*sl = 0;
if ((pid = fork()) == (pid_t)0) {
execl("/usr/bin/sh", "sh", "-c", line, 0);
exit(0100);
}
savint = signal(SIGINT, SIG_IGN);
while ((rpid = wait(&retcode)) != pid && rpid != (pid_t)-1);
signal(SIGINT, savint);
printf(gettext("!\n"));
return (0);
}
}
int
cond(char c)
{
struct blk *p;
int cc;
if (subt() != 0)
return (1);
p = pop();
sunputc(p);
if (length(p) == 0) {
release(p);
if (c == '<' || c == '>' || c == NE) {
readc();
return (0);
}
load();
return (1);
} else {
if (c == '=') {
release(p);
readc();
return (0);
}
}
if (c == NE) {
release(p);
load();
return (1);
}
fsfile(p);
cc = sbackc(p);
release(p);
if ((cc < 0 && (c == '<' || c == NG)) ||
(cc > 0) && (c == '>' || c == NL)) {
readc();
return (0);
}
load();
return (1);
}
void
load(void)
{
int c;
struct blk *p, *q, *t, *s;
c = readc() & 0377;
sptr = stable[c];
if (sptr != 0) {
p = sptr->val;
if (c >= ARRAYST) {
q = salloc(length(p));
rewind(p);
while (sfeof(p) == 0) {
s = getwd(p);
if (s == 0)
putwd(q, (struct blk *)NULL);
else {
t = copy(s, length(s));
putwd(q, t);
}
}
pushp(q);
} else {
q = copy(p, length(p));
pushp(q);
}
} else {
q = salloc(1);
if (c <= LASTFUN) {
printf(gettext
("function %c undefined\n"), c + 'a' - 1);
sputc(q, 'c');
sputc(q, '0');
sputc(q, ' ');
sputc(q, '1');
sputc(q, 'Q');
} else
sputc(q, 0);
pushp(q);
}
}
int
log2(long n)
{
int i;
if (n == 0)
return (0);
i = 31;
if (n < 0)
return (i);
while ((n = n << 1) > 0)
i--;
return (--i);
}
struct blk *
salloc(int size)
{
struct blk *hdr;
char *ptr;
char *dcmalloc();
all++;
lall++;
if (all - rel > active)
active = all - rel;
nbytes += size;
lbytes += size;
if (nbytes > maxsize)
maxsize = nbytes;
if (size > longest)
longest = size;
ptr = dcmalloc((unsigned)size);
if (ptr == 0) {
garbage("salloc");
if ((ptr = dcmalloc((unsigned)size)) == 0)
ospace("salloc");
}
if ((hdr = hfree) == 0)
hdr = morehd();
hfree = (struct blk *)hdr->rd;
hdr->rd = hdr->wt = hdr->beg = ptr;
hdr->last = ptr + size;
return (hdr);
}
struct blk *
morehd(void)
{
struct blk *h, *kk;
char *dcmalloc();
headmor++;
nbytes += HEADSZ;
hfree = h = (struct blk *)dcmalloc(HEADSZ);
if (hfree == 0) {
garbage("morehd");
if ((hfree = h = (struct blk *)dcmalloc(HEADSZ)) == 0)
ospace("headers");
}
kk = h;
while (h < hfree + (HEADSZ/BLK))
(h++)->rd = (char *)++kk;
(--h)->rd = 0;
return (hfree);
}
struct blk *
copy(struct blk *hptr, int size)
{
struct blk *hdr;
unsigned sz;
char *ptr;
all++;
lall++;
lcopy++;
nbytes += size;
lbytes += size;
if (size > longest)
longest = size;
if (size > maxsize)
maxsize = size;
sz = length(hptr);
ptr = nalloc(hptr->beg, (unsigned)size);
if (ptr == 0) {
garbage("copy");
if ((ptr = nalloc(hptr->beg, (unsigned)size)) == NULL) {
printf(gettext("copy size %d\n"), size);
ospace("copy");
}
}
if ((hdr = hfree) == 0)
hdr = morehd();
hfree = (struct blk *)hdr->rd;
hdr->rd = hdr->beg = ptr;
hdr->last = ptr + size;
hdr->wt = ptr + sz;
ptr = hdr->wt;
while (ptr < hdr->last)
*ptr++ = '\0';
return (hdr);
}
void
sdump(char *s1, struct blk *hptr)
{
char *p;
if (hptr) {
printf("%s %o rd %o wt %o beg %o last %o\n", s1, hptr,
hptr->rd, hptr->wt, hptr->beg, hptr->last);
p = hptr->beg;
while (p < hptr->wt)
printf("%d ", *p++);
printf("\n");
} else
printf("%s %o\n", s1, hptr);
}
void
seekc(struct blk *hptr, int n)
{
char *nn, *p;
nn = hptr->beg + n;
if (nn > hptr->last) {
nbytes += nn - hptr->last;
if (nbytes > maxsize)
maxsize = nbytes;
lbytes += nn - hptr->last;
if (n > longest)
longest = n;
p = realloc(hptr->beg, (unsigned)n);
if (p == 0) {
hptr->beg = realloc(hptr->beg,
(unsigned)(hptr->last - hptr->beg));
garbage("seekc");
if ((p = realloc(hptr->beg, (unsigned)n)) == 0)
ospace("seekc");
}
hptr->beg = p;
hptr->wt = hptr->last = hptr->rd = p + n;
return;
}
hptr->rd = nn;
if (nn > hptr->wt)
hptr->wt = nn;
}
void
salterwd(struct wblk *hptr, struct blk *n)
{
if (hptr->rdw == hptr->lastw)
more((struct blk *)hptr);
*hptr->rdw++ = n;
if (hptr->rdw > hptr->wtw)
hptr->wtw = hptr->rdw;
}
void
more(struct blk *hptr)
{
unsigned size;
char *p;
if ((size = (hptr->last - hptr->beg) * 2) == 0)
size = 1;
nbytes += size / 2;
if (nbytes > maxsize)
maxsize = nbytes;
if (size > longest)
longest = size;
lbytes += size / 2;
lmore++;
p = realloc(hptr->beg, (unsigned)size);
if (p == 0) {
hptr->beg = realloc(hptr->beg,
(unsigned)(hptr->last - hptr->beg));
garbage("more");
if ((p = realloc(hptr->beg, size)) == 0)
ospace("more");
}
hptr->rd = hptr->rd - hptr->beg + p;
hptr->wt = hptr->wt - hptr->beg + p;
hptr->beg = p;
hptr->last = p + size;
}
void
ospace(char *s)
{
printf(gettext("out of space: %s\n"), s);
printf(gettext("all %ld rel %ld headmor %ld\n"), all, rel, headmor);
printf(gettext("nbytes %ld\n"), nbytes);
sdump("stk", *stkptr);
abort();
}
#define G1 gettext("array %o elt %d odd\n")
#define G2 gettext("tmps %o p %o\n")
void
garbage(char *s)
{
int i;
struct blk *p, *q;
struct sym *tmps;
int ct;
printf(gettext("got to garbage %s\n"), s);
for (i = 0; i < TBLSZ; i++) {
tmps = stable[i];
if (tmps != 0) {
if (i < ARRAYST) {
do {
p = tmps->val;
if (((int)p->beg & 01) != 0) {
printf(gettext(
"string %o\n"), i);
sdump("odd beg", p);
}
redef(p);
tmps = tmps->next;
} while (tmps != 0);
continue;
} else {
do {
p = tmps->val;
rewind(p);
ct = 0;
while ((q = getwd(p)) != NULL) {
ct++;
if (q != 0) {
if (((int)q->beg & 01)
!= 0) {
printf(G1,
i - ARRAYST,
ct);
printf(G2,
tmps, p);
sdump("elt", q);
}
redef(q);
}
}
tmps = tmps->next;
} while (tmps != 0);
}
}
}
}
void
redef(struct blk *p)
{
int offset;
char *newp;
char *dcmalloc();
if ((int)p->beg & 01) {
printf(gettext("odd ptr %o hdr %o\n"), p->beg, p);
ospace("redef-bad");
}
free(dummy);
dummy = dcmalloc(0);
if (dummy == NULL)
ospace("dummy");
newp = realloc(p->beg, (unsigned)(p->last - p->beg));
if (newp == NULL)
ospace("redef");
offset = newp - p->beg;
p->beg = newp;
p->rd += offset;
p->wt += offset;
p->last += offset;
}
void
release(struct blk *p)
{
rel++;
lrel++;
nbytes -= p->last - p->beg;
p->rd = (char *)hfree;
hfree = p;
free(p->beg);
p->beg = NULL;
}
struct blk *
getwd(struct blk *p)
{
struct wblk *wp;
wp = (struct wblk *)p;
if (wp->rdw == wp->wtw)
return (NULL);
return (*wp->rdw++);
}
void
putwd(struct blk *p, struct blk *c)
{
struct wblk *wp;
wp = (struct wblk *)p;
if (wp->wtw == wp->lastw)
more(p);
*wp->wtw++ = c;
}
struct blk *
lookwd(struct blk *p)
{
struct wblk *wp;
wp = (struct wblk *)p;
if (wp->rdw == wp->wtw)
return (NULL);
return (*wp->rdw);
}
char *
nalloc(char *p, unsigned int nbytes)
{
char *dcmalloc();
char *q, *r;
q = r = dcmalloc(nbytes);
if (q == 0)
return (0);
while (nbytes--)
*q++ = *p++;
return (r);
}
char *
dcmalloc(int size)
{
return (malloc(size ? size : 1));
}