#pragma prototyped
#include <cmd.h>
#include <wc.h>
#include <ctype.h>
#if _hdr_wchar && _hdr_wctype
#include <wchar.h>
#include <wctype.h>
#else
#ifndef iswspace
#define iswspace(x) isspace(x)
#endif
#endif
#define endline(c) (((signed char)-1)<0?(c)<0:(c)==((char)-1))
#define mbok(p,n) (((n)<1)?0:mbwide()?((*ast.mb_towc)(NiL,(char*)(p),n)>=0):1)
Wc_t *wc_init(int mode)
{
register int n;
register int w;
Wc_t* wp;
if(!(wp = (Wc_t*)stakalloc(sizeof(Wc_t))))
return(0);
wp->mode = mode;
w = mode & WC_WORDS;
for(n=(1<<CHAR_BIT);--n >=0;)
wp->space[n] = w ? !!isspace(n) : 0;
wp->space['\n'] = -1;
return(wp);
}
int wc_count(Wc_t *wp, Sfio_t *fd, const char* file)
{
register signed char *space = wp->space;
register unsigned char *cp;
register Sfoff_t nchars;
register Sfoff_t nwords;
register Sfoff_t nlines;
register Sfoff_t eline;
register Sfoff_t longest;
register ssize_t c;
register unsigned char *endbuff;
register int lasttype = 1;
unsigned int lastchar;
unsigned char *buff;
wchar_t x;
sfset(fd,SF_WRITE,1);
nlines = nwords = nchars = 0;
wp->longest = 0;
if (wp->mode & (WC_LONGEST|WC_MBYTE))
{
longest = 0;
eline = -1;
cp = buff = endbuff = 0;
for (;;)
{
if (!mbok(cp, endbuff-cp))
{
if (buff)
sfread(fd, buff, cp-buff);
if (!(buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, SF_LOCKR)))
break;
endbuff = (cp = buff) + sfvalue(fd);
}
nchars++;
x = mbchar(cp);
if (x == -1)
{
if (eline != nlines && !(wp->mode & WC_QUIET))
{
error_info.file = (char*)file;
error_info.line = eline = nlines;
error(ERROR_SYSTEM|1, "invalid multibyte character");
error_info.file = 0;
error_info.line = 0;
}
}
else if (x == '\n')
{
if ((nchars - longest) > wp->longest)
wp->longest = nchars - longest;
longest = nchars;
nlines++;
lasttype = 1;
}
else if (iswspace(x))
lasttype = 1;
else if (lasttype)
{
lasttype = 0;
nwords++;
}
}
}
else
{
for (;;)
{
if (!(buff = (unsigned char*)sfreserve(fd, 0, 0)) || (c = sfvalue(fd)) <= 0)
break;
sfread(fd,(char*)(cp=buff),c);
nchars += 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->chars = nchars;
wp->words = nwords;
wp->lines = nlines;
return(0);
}