/* * (c) Copyright David Cusimano, 1989 * * Program: spellsrt * Usage: spellsrt [-q] [wordsfile] * Purpose: Read words from a file or the standard input, sort * them using a case-insensitive sort, and send the * result to the standard output. The output is * suitable as a dictionary for the spell utility. * "APPLE" appears before "orange" even though the * ASCII value of "A" is after the ASCII value of * "o". * Version: 1.00 * Author: David Cusimano * Date Created: May 28, 1989 * Date Revised: September 3, 1989 */ #include #include #define NOTICE "SPELLSRT v1.00, (C)1989 David Cusimano" #define MAXWORDS 5000 /* maximum words to sort */ #define LENWORD 32 /* maximum words length */ #define TRUE 1 #define FALSE 0 /* * Read words from the standard input, sort the words, and display * the list to the standard output. */ main(argc, argv) int argc; char *argv[]; { char *words[MAXWORDS]; unsigned int numwords; FILE *fp; int quiet; unsigned int readfile(); FILE *openfile(); chkusage(argc); quiet = FALSE; argc--; argv++; while (argc > 0 && argv[0][0] == '-') { switch (argv[0][1]) { case 'q': case 'Q': quiet = TRUE; break; default: fputs("unknown option\n", stderr); showusage(); break; } argc--; argv++; } if (argc >= 1) fp = openfile(argv[0]); else fp = stdin; if (!quiet) fputs("Reading", stderr); numwords = readfile(fp, words); if (numwords != 0) { if (!quiet) fprintf(stderr, ", sorting %u words", numwords); sortwords(words, numwords); if (!quiet) fputs(", writing", stderr); putwords(words, numwords); } if (!quiet) fputs(", done.\n", stderr); fclose(fp); exit(0); } /* * Check and display program usage. */ chkusage(argc) int argc; { if (argc > 3) showusage(); } showusage() { fputs(NOTICE, stderr); fputs("\nusage: spellsrt [-q] [wordsfile]\n", stderr); exit(1); } /* * Open specified file for read-only mode. If the file cannot be * opened, an error message is displayed and the program halts. */ FILE * openfile(name) char *name; { register FILE *fp; FILE *fopen(); if ((fp = fopen(name, "r")) == NULL) { fputs(name, stderr); fputs(": can't open file\n", stderr); exit(1); } return (fp); } /* * Alphabetically sort a list of words given an array of pointers * to the start of each word. */ sortwords(words, numwords) char *words[]; unsigned int numwords; { int cmpword(); qsort(words, numwords, sizeof(words[0]), cmpword); } /* * Compare two words for qsort(). */ cmpword(a, b) char **a; char **b; { return (strlcmp(*a, *b)); } /* * Compare two strings as strcmp() would except ignore the case * of the two strings. */ strlcmp(s, t) register char *s; register char *t; { for ( ; tolower(*s) == tolower(*t); s++, t++) if (*s == '\0') return (0); return (tolower(*s) - tolower(*t)); } /* * Read words from the specified file, allocate memory for them, * and save pointers to the start of the words in an array. */ unsigned int readfile(fp, words) FILE *fp; char *words[]; { unsigned int numwords; char bufr[LENWORD]; int len; char *ptr; char *savstr(); numwords = 0; while ((len = getword(fp, bufr, sizeof(bufr))) != EOF) { if (len == 0) continue; else if ((ptr = savstr(bufr)) == NULL) { fclose(fp); fputs("\ncan't allocate memory\n", stderr); exit(1); } else { words[numwords++] = ptr; if (numwords >= MAXWORDS) { fclose(fp); fputs("\ntoo many words\n", stderr); exit(1); } } } return (numwords); } /* * Save a string in memory by allocating storage for it and * copying it to the newly allocated memory. */ char * savstr(str) register char *str; { register char *mem; char *malloc(); mem = malloc(strlen(str) + 1); if (mem != NULL) strcpy(mem, str); return (mem); } /* * Read a word from the specified file. A word is delimited by any * non-alphabetic character which include numerals and punctuation. * The returned word contains only alphabetics. The length of the * word read is returned. */ getword(fp, bufr, max) FILE *fp; char *bufr; int max; { register int ch; register int len; len = 0; while (1) { ch = getc(fp); if (ch == EOF) { if (len == 0) return (EOF); else { bufr[len] = '\0'; return (len); } } else if (!isalpha(ch)) { bufr[len] = '\0'; return (len); } else { bufr[len++] = ch; if (len >= max) { bufr[max - 1] = '\0'; return (max - 1); } } } } /* * Print list of words. */ putwords(words, numwords) register char *words[]; unsigned int numwords; { register unsigned int index; unsigned int nxtwrd(); index = nxtwrd(words, numwords, 0); while (index < numwords) { puts(words[index]); index = nxtwrd(words, numwords, index + 1); } } /* * Compare adjacent words in a sorted list and return the index of * the last occurrence of duplicate words. For example: * nxtwrd({a,a,a,b,b,c,d}, 7, 0) == 2 * nxtwrd({a,a,a,b,b,c,d}, 7, 2) == 2 * nxtwrd({a,a,a,b,b,c,d}, 7, 3) == 4 */ unsigned int nxtwrd(words, numwords, index) register char *words[]; unsigned int numwords; register unsigned int index; { for (; index + 1 < numwords; index++) if (strlcmp(words[index], words[index + 1]) != 0) break; return (index); }