/* * Sort input by size. Uses a horrid bubble insertion sort, because * otherwise those cpu cycles would go to waste. */ #include #include #include #include /* double linked list; next points at the next size, list points at * things the same size. */ typedef struct String { char *text; struct String *next; } String; typedef struct Item { struct Item *next; String *list; int size; } Item; Item *head = 0; char endofline = '\n'; int r_flag = 0; char *line; int szline; int skip(Item *p, int size) { return r_flag ? (p->size < size) : (p->size > size); } void abend(char *why) { fprintf(stderr, "ABEND: "); if (errno != 0) perror(why); else fprintf(stderr, "%s\n", why); exit(1); } int getline() { register c; int sz = 0; while ((c = getchar()) != EOF) { if (c == endofline) { line[sz++] = '\n'; line[sz] = 0; return sz; } line[sz++] = c; if ((sz >= szline-1) && (line = realloc(line, szline *= 2)) == 0) abend("REALLOC"); } if (sz) line[sz++] = '\n'; line[sz] = 0; return sz; } main(int argc, char **argv) { int size; Item *i, *p; String *q; int c; int n_flag = 0; int max = -1; int min = -1; extern int optopt; extern int opterr; extern char *optarg; extern int getopt(int,char**,char*); opterr = 1; while ( (c = getopt(argc, argv, "u:l:F:rn")) != EOF) { switch (c) { case 'u': max = atoi(optarg); break; case 'l': min = atoi(optarg); break; case 'F': endofline = optarg[0]; break; case 'n': n_flag = 1; break; case 'r': r_flag = 1; break; default: abend("Usage: sbs -u max -l min -Fsep -rn"); } } if ( (line = malloc(szline = 80)) == 0) abend("MALLOC"); while (size = getline()) { for (i=0,p=head; p && skip(p, size); i = p, p = p->next) ; if (p == 0) { if ( (p = malloc(sizeof *p)) == 0) abend("LIST APPEND"); p->next = 0; p->list = 0; p->size = size; if (i) i->next = p; else head = p; } else if (p->size != size) { Item *elem; if ( (elem = malloc(sizeof *elem)) == 0) abend("LIST INSERT"); if (i) i->next = elem; else head = elem; elem->next = p; elem->list = 0; elem->size = size; p = elem; } /* p points at the pretend hash we want to add to */ if ( (q = malloc(1 + size + sizeof *q)) == 0) abend("STRING MALLOC"); q->text = (char*)(q+1); strcpy(q->text, line); q->next = p->list; p->list = q; } for (p = head; p; p = p->next) { if (max >= 0 && max < p->size) continue; if (min >= 0 && min > p->size) continue; for (q = p->list; q; q = q->next) { if (n_flag) printf("%7d ", (p->size)-1); printf("%s", q->text); } } }