8 #define DEFAULT_DICT_PATH "/usr/share/dict/linux.words"
9 #define STARTING_SZ 8192
10 #define MAX_ARRAY_SZ 1073741824
18 static int alloc_dict(struct dict **d, int array_sz)
22 if (array_sz > MAX_ARRAY_SZ) {
23 fprintf(stderr, "can't allocate a words array bigger "
24 "than %d\n", MAX_ARRAY_SZ);
28 num_bytes = sizeof(struct dict) + (array_sz * sizeof(char*));
29 nd = realloc(*d, num_bytes);
31 fprintf(stderr, "failed to realloc to size %d\n",
37 nd->array_sz = array_sz;
41 static struct dict* read_dict(FILE *fp)
45 malloc(sizeof(struct dict) + (STARTING_SZ * sizeof(char*)));
47 fprintf(stderr, "failed to allocate dict\n");
51 d->array_sz = STARTING_SZ;
54 if (! fgets(word, sizeof(word), fp)) {
57 fprintf(stderr, "%s: error reading line %d: "
59 __func__, d->num_words + 1,
66 d->words[d->num_words] = strdup(word);
67 if (!d->words[d->num_words]) {
68 fprintf(stderr, "failed to allocate word %d\n",
74 if (d->num_words >= d->array_sz) {
75 if (alloc_dict(&d, d->array_sz * 2)) {
83 static const char* choose_random_word(struct dict *dict)
85 int choice = random() % dict->num_words;
87 return dict->words[choice];
90 static void print_usage(char *program_name)
92 printf("%s: prints a random word from a linebreak-delimited file.\n",
95 printf("\t-d: the dictionary file to use. Default: %s.\n",
97 printf("\t-h: this help message.\n");
100 static void parse_args(char **argv, int argc, char **dict_path)
103 *dict_path = DEFAULT_DICT_PATH;
105 while ((c = getopt(argc, argv, "d:h")) != -1) {
111 print_usage(argv[0]);
115 fprintf (stderr, "Argument parsing error.\n");
121 int main(int argc, char **argv)
129 parse_args(argv, argc, &dict_path);
130 gettimeofday(&tv, NULL);
131 srandom(tv.tv_usec * tv.tv_sec);
133 fp = fopen(dict_path, "r");
136 fprintf(stderr, "failed to open %s: %s (%d).\n",
137 dict_path, strerror(err), err);
140 dict = read_dict(fp);
145 word = choose_random_word(dict);