# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# include <ctype.h>
# include "table.h"
# include "getword.h"
# define MAX 65
# define HINT 256
static void nomem (void)
{
fputs ("Fatal: out of memory\n", stderr);
exit (1);
}
static void *allocate (size_t s)
{
void *x = malloc (s);
if (!x)
nomem ();
return x;
}
static void enter_word (char *word, Table_T table)
{
int *i = Table_get (table, word);
if (i == NULL) {
i = allocate (sizeof (int));
*i = 0;
Table_put (table, word, i);
}
(*i)++;
}
static int first (char c)
{
return isalpha (c) || (c == '_');
}
static int rest (char c)
{
return first (c) || isdigit (c);
}
static void process_file (FILE *fp, Table_T table)
{
char buf [MAX];
while (getword (fp, buf, MAX, first, rest) != EOF)
enter_word (buf, table);
}
struct assoc {
char *word;
int count;
};
static void apply (char *word, void **value, void *cl)
{
struct assoc **a = cl;
int *i = *value;
(*a)->word = word;
(*a)->count = *i;
(*a)++;
free (i);
}
static struct assoc *table2array (Table_T table, int len)
{
struct assoc *a, *tmp;
a = allocate (len * sizeof (struct assoc));
tmp = a;
Table_map (table, apply, &tmp);
return a;
}
static int cmpa (const void *x, const void *y)
{
const struct assoc *a = x, *b = y;
return a->count - b->count;
}
static void sorta (struct assoc *a, int len)
{
qsort (a, len, sizeof (struct assoc), cmpa);
}
static void print1 (struct assoc *a)
{
printf ("%s\t%d\n", a->word, a->count);
}
static void printa (struct assoc *a, int len, int n)
{
int i;
if (n >= 0)
for (i = len - 1; i >= 0 && a[i].count >= n; i--)
print1 (a + i);
else {
n = -n;
for (i = 0; i < len && a[i].count <= n; i++)
print1 (a + i);
}
}
int main (int argc, char **argv)
{
Table_T table;
int n = 0;
int len;
if ((table = Table_new (HINT, strcmp)) == NULL)
nomem ();
if (argc > 1 && (argv[1][0] == '+' || argv[1][0] == '-')) {
char *endptr;
int x = strtol (argv [1], &endptr, 10);
if (*endptr == '\0') {
n = x;
argc--;
argv++;
}
}
if (argc > 1)
while (--argc > 0) {
FILE *fp = fopen (*++argv, "r");
if (fp) {
process_file (fp, table);
fclose (fp);
} else
fprintf (stderr, "Can't open `%s'\n", *argv);
}
else
process_file (stdin, table);
if ((len = Table_length (table)) != 0) {
struct assoc *a = table2array (table, len);
sorta (a, len);
printa (a, len, n);
free (a);
}
Table_free (&table);
return 0;
}
Matthias Blume,
CS Department,
Princeton University