V10/cmd/revpag.c
#include <stdio.h>
#include <signal.h>
#define Signal(s, f) if (signal(s, SIG_IGN) != SIG_IGN) (void)signal(s, f)
#define PARGVAL ((*argv)[2] ? *argv+2 : --argc ? *++argv : (char *)0)
#define PUTI(n) if (debug) fprintf(stderr," %d ",n); \
if (index >= indend) index = getind(); \
*index++ = 2*(n) + inrange()
#define Malloc(type,size) ((type *)malloc((size)*sizeof(type)))
#define Realloc(type,ptr,size) ((type *)realloc(ptr,(size)*sizeof(type)))
#define NLIST 32
#define BSIZE 4096
#define ISIZE 1024
typedef struct Range {
int lo, hi;
} Range;
char *buf, *malloc(), *realloc(), tmpnam[32];
int indsize, bufsiz, nchsrc, infd, outfd, sighup();
Range *olist, *oindex; int nolist, npages;
long *indbase, *indend, *index;
main(argc,argv)
int argc; char **argv;
{
register int nchin, lcount, nlflag; register char *src;
long *getind(); int nlpage = 66, dcan = 0, termff = 0, debug = 0;
Signal(SIGHUP, sighup);
Signal(SIGINT, sighup);
Signal(SIGQUIT, sighup);
Signal(SIGPIPE, sighup);
if ((buf = malloc(bufsiz = BSIZE)) == NULL)
fatal("cannot malloc buf","");
while (--argc > 0 && (*++argv)[0] == '-' && (*argv)[1])
switch ((*argv)[1]) {
case 'd':
dcan++; break;
case 'f':
termff++; break;
case 'l':
nlpage = atoi(PARGVAL); break;
case 'o':
minuso(PARGVAL); break;
case 'D':
debug++; break;
default:
fatal("unknown option ",*argv);
}
++argc; --argv;
if (debug) {
register Range *l;
for (l=olist; l->lo < l->hi; l++)
fprintf(stderr, "[%d, %d)\n", l->lo, l->hi);
}
if ((infd = (argc > 1) ? Open(&argc, &argv) : 0) < 0)
exit(0);
if ((outfd = creat(mktemp(strcpy(tmpnam,"/tmp/revpXXXXXX")),0644)) < 0)
fatal("cannot open ",tmpnam);
lcount = nchin = nlflag = 0;
if (!dcan) { PUTI(0); }
for (;;) {
while ((nchsrc = read(infd, buf, bufsiz)) <= 0) {
if (infd) close(infd);
infd = Open(&argc,&argv);
if (infd < 0) break;
}
if (nchsrc <= 0) break;
write(outfd, buf, nchsrc);
src = buf;
if (!dcan) do switch (*src++) {
case '\n':
++nchin;
if (++lcount >= nlpage) {
PUTI(nchin);
lcount = 0; nlflag++;
}
break;
case '\014':
nchin++;
if (!nlflag) {
if (nchin) { PUTI(nchin); }
lcount = 0;
}
nlflag = 0;
break;
default:
nlflag = 0;
nchin++;
} while (--nchsrc > 0);
else do switch (*src++) {
case '\n':
if (lcount > 2) { PUTI(nlflag); }
nlflag = ++nchin;
lcount = 1;
break;
case 'p':
if (lcount == 1) lcount++;
else lcount = 0;
++nchin;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (lcount >= 2) lcount++;
else lcount = 0;
++nchin;
break;
default:
lcount = 0;
++nchin;
} while (--nchsrc > 0);
}
if (!dcan && termff && lcount != 0) {
write(outfd,"\014",1);
nchin++;
}
if (dcan || !nlflag) { PUTI(nchin); }
close(outfd); outfd = 1;
if ((infd = open(tmpnam,0)) < 0)
fatal("cannot reopen ",tmpnam);
if (dcan) {
nchin = *indbase/2;
while (nchin > bufsiz)
if ((buf = realloc(buf,bufsiz += BSIZE)) == NULL)
fatal("cannot realloc buffer","");
read(infd,buf,nchin);
write(outfd,buf,nchin);
}
if (debug) fprintf(stderr,"\n");
while (--index > indbase) {
if (*(index-1) % 2 == 0)
continue;
nchin = *index/2 - *(index-1)/2;
while (nchin > bufsiz)
if ((buf = realloc(buf,bufsiz += BSIZE)) == NULL)
fatal("cannot realloc buffer","");
if (debug) fprintf(stderr,"(%d,%d) ",*(index-1)/2,nchin);
if (nchin > 0) {
lseek(infd, *(index-1)/2, 0);
read(infd,buf,nchin);
write(outfd,buf,nchin);
}
}
close(infd);
unlink(tmpnam);
exit(0);
}
minuso(str)
char *str;
{
register int dash = 0, i = 0, lo = 0, c;
do switch (c = *str++) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
i = 10*i + c - '0';
break;
case '-':
++dash; lo = i; i = 0;
break;
case ',':
case '\0':
merge(dash ? lo : i, i);
dash = lo = i = 0;
break;
} while (c);
}
merge(lo,hi)
{
Range new, temp; register Range *source, *dest;
if (lo == 0) lo = 1;
if (hi == 0) hi = 99999;
if (lo <= hi) {
new.lo = lo; new.hi = hi + 1;
} else {
new.lo = hi; new.hi = lo + 1;
}
if (olist == 0) {
olist = oindex = Malloc(Range, nolist = NLIST);
olist->lo = 0;
olist->hi = -1;
}
for (dest=source=olist;;) {
if (source->lo >= source->hi) {
*dest++ = new;
dest->lo = 0;
dest->hi = -1;
break;
} else if (source->hi < new.lo) {
*dest++ = *source++;
} else if (new.hi < source->lo) {
temp = *source++;
*dest++ = new;
new = temp;
} else {
temp.lo = min(new.lo, source->lo);
temp.hi = max(new.hi, source->hi);
new = temp;
source++;
}
}
if (dest - olist >= nolist)
olist = Realloc(Range, olist, nolist += NLIST);
}
inrange()
{
++npages;
if (olist == 0)
return 1;
if (oindex == 0)
return 0;
for (; oindex->lo < oindex->hi; oindex++) {
if (npages < oindex->lo)
return 0;
if (npages < oindex->hi)
return 1;
}
oindex = 0;
return 0;
}
Open(pargc,pargv)
int *pargc; char ***pargv;
{
int infd = -1;
while (--(*pargc) > 0) {
if (strcmp("-",*++(*pargv)) == 0) infd = 0;
else infd = open(**pargv,0);
if (infd >= 0) break;
fprintf(stderr,"cannot open %s\n",**pargv);
fflush(stderr);
}
return infd;
}
long *
getind()
{
register long *index;
if (indsize == 0)
indbase = Malloc(long, ISIZE);
else
indbase = Realloc(long, indbase, indsize+ISIZE);
if (indbase == (long *)0)
fatal("cannot allocate index","");
index = indbase + indsize;
indsize += ISIZE;
indend = indbase + indsize;
return index;
}
fatal(str1,str2)
char *str1, *str2;
{
fprintf(stderr,"%s%s\n",str1,str2);
if (tmpnam[0]) unlink(tmpnam);
exit(1);
}
sighup(s)
{
if (tmpnam[0]) unlink(tmpnam);
exit(1);
}