#pragma prototyped
#include <cmdlib.h>
#include <wc.h>
#include <ctype.h>
#define endline(c) (((signed char)-1)<0?(c)<0:(c)==((char)-1))
Wc_t *wc_init(char *space)
{
register int n;
Wc_t *wp;
if(!(wp = (Wc_t*)stakalloc(sizeof(Wc_t))))
return(0);
if(space)
memcpy(wp->space, space, (1<<CHAR_BIT));
else
{
for(n=(1<<CHAR_BIT);--n >=0;)
wp->space[n] = (isspace(n)!=0);
wp->space['\n'] = -1;
}
return(wp);
}
int wc_count(Wc_t *wp, Sfio_t *fd)
{
register signed char *space = wp->space;
register unsigned char *cp;
register Sfoff_t nwords;
register Sfoff_t nlines;
register ssize_t c;
register unsigned char *endbuff;
register int lasttype = 1;
unsigned int lastchar;
unsigned char *buff;
nlines = nwords = wp->chars = 0;
sfset(fd,SF_WRITE,1);
for (;;)
{
if (!(buff = (unsigned char*)sfreserve(fd, 0, 0)) || (c = sfvalue(fd)) <= 0)
break;
sfread(fd,(char*)(cp=buff),c);
wp->chars += c;
if(c==1)
{
if(endline(lasttype))
nlines++;
if((c = space[*cp]) && !lasttype)
nwords++;
lasttype = c;
continue;
}
if(!lasttype && space[*cp])
nwords++;
lastchar = cp[--c];
cp[c] = '\n';
endbuff = cp+c;
c = lasttype;
for (;;)
{
do if (endline(c))
{
for (;;)
{
if (cp > endbuff)
goto eob;
nlines++;
if (*cp != '\n')
break;
cp++;
}
} while (c = space[*cp++]);
while(!(c = space[*cp++]));
nwords++;
}
eob:
if((cp -= 2) >= buff)
c = space[*cp];
else
c = lasttype;
lasttype = space[lastchar];
if(!c && !lasttype)
nwords--;
}
if(endline(lasttype))
nlines++;
else if(!lasttype)
nwords++;
wp->words = nwords;
wp->lines = nlines;
return(0);
}