recent; a sort of sideways uniq
Alan Lee Wendt
wendt at arizona.edu
Sun Nov 20 07:19:42 AEST 1988
recent.c reads a file and throws out all but the last occurrence
of each line, leaving the remainder of the lines in order. It is
a useful filter for history lists and directory stacks, because
it shortens the list without changing its meaning. Also, if you
feed a page trace through it, "recent < pagetrace | tail -n", will
give you n most-recently used pages (which an lru replacement
algorithm would leave resident).
BUGS:
It should really have a "-f" option to throw out all but the first,
then it would look like "uniq" except not require sorting.
Max of 5000 lines of input (enough for history and directories but
not for page traces).
#include <stdio.h>
#define NBUCKETS 569
struct Hnode {
struct Hnode *ptr;
int number;
char *txt;
} *Buckets[NBUCKETS];
struct Hnode *install(s)
register char *s;
{
register char *p1, *p2;
register unsigned h;
register int *p, *q, n;
register struct Hnode *hnode;
char *strcpy(), *sbrk();
static unsigned mask[] = { ~0, 0 };
q = (p = (int *) s) + (n = strlen(s))/sizeof(int);
h = *q & *((unsigned *)((char *)mask + (sizeof(int) - n%sizeof(int))));
while ( p < q ) h ^= *p++;
h %= NBUCKETS;
/* for each entry on the chain */
for (hnode = Buckets[h]; hnode; hnode = hnode->ptr) {
for (p1 = s, p2 = hnode->txt; *p1++ == *p2++;)
if (p1[-1] == 0) {
hnode->number++; /* count occurrences */
return hnode;
}
}
/* not found, add another entry */
hnode = (struct Hnode *)sbrk((unsigned)sizeof(struct Hnode) + n + 1);
hnode->txt = (char *)hnode + sizeof(struct Hnode);
strcpy(hnode->txt, s);
hnode->ptr = Buckets[h]; /* link at head */
hnode->number = 1;
Buckets[h] = hnode;
return hnode;
}
main()
{
char bf[10000];
struct Hnode *vec[5000];
int vsize = 0, i;
while (fgets(bf, sizeof(bf), stdin) && vsize < 5000)
vec[vsize++] = install(bf);
for (i = 0; i < vsize; i++) {
if (--vec[i]->number == 0)
fputs(vec[i]->txt, stdout);
}
}
More information about the Alt.sources
mailing list