+static int
+pl_compare(v1, v2)
+ const void *v1;
+ const void *v2;
+{
+ const struct path_list * const *p1 = v1;
+ const struct path_list * const *p2 = v2;
+
+ return(strcmp((*p1)->path, (*p2)->path));
+}
+
+static char *
+switch_dir(stack, dirpath)
+ struct include_stack *stack;
+ char *dirpath;
+{
+ DIR *dir;
+ int i, count = 0;
+ char *path = NULL;
+ struct dirent *dent;
+ struct stat sb;
+ struct path_list *pl, *first = NULL;
+ struct path_list **sorted = NULL;
+
+ if (!(dir = opendir(dirpath))) {
+ yyerror(dirpath);
+ return(NULL);
+ }
+ while ((dent = readdir(dir))) {
+ /* Ignore files that end in '~' or have a '.' in them. */
+ if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~'
+ || strchr(dent->d_name, '.') != NULL) {
+ continue;
+ }
+ if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) {
+ closedir(dir);
+ goto bad;
+ }
+ if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) {
+ efree(path);
+ continue;
+ }
+ pl = malloc(sizeof(*pl));
+ if (pl == NULL)
+ goto bad;
+ pl->path = path;
+ pl->next = first;
+ first = pl;
+ count++;
+ }
+ closedir(dir);
+
+ if (count == 0)
+ goto done;
+
+ /* Sort the list as an array. */
+ sorted = malloc(sizeof(*sorted) * count);
+ if (sorted == NULL)
+ goto bad;
+ pl = first;
+ for (i = 0; i < count; i++) {
+ sorted[i] = pl;
+ pl = pl->next;
+ }
+ qsort(sorted, count, sizeof(*sorted), pl_compare);
+
+ /* Apply sorting to the list. */
+ first = sorted[0];
+ sorted[count - 1]->next = NULL;
+ for (i = 1; i < count; i++)
+ sorted[i - 1]->next = sorted[i];
+ efree(sorted);
+
+ /* Pull out the first element for parsing, leave the rest for later. */
+ if (count) {
+ path = first->path;
+ pl = first->next;
+ efree(first);
+ stack->more = pl;
+ } else {
+ path = NULL;
+ }
+done:
+ efree(dirpath);
+ return(path);
+bad:
+ while (first != NULL) {
+ pl = first;
+ first = pl->next;
+ free(pl->path);
+ free(pl);
+ }
+ efree(sorted);
+ efree(dirpath);
+ efree(path);
+ return(NULL);
+}
+