-
-/*
- * `spname' and its helpers are inspired by the code in "The UNIX
- * Programming Environment, Kernighan & Pike, Prentice-Hall 1984",
- * pages 209 - 213.
- */
-
-/*
- * `spname' -- return a correctly spelled filename
- *
- * int spname(char * oldname, char * newname)
- * Returns: -1 if no reasonable match found
- * 0 if exact match found
- * 1 if corrected
- * Stores corrected name in `newname'.
- */
-static int
-spname(oldname, newname)
- char *oldname;
- char *newname;
-{
- char *op, *np, *p;
- char guess[PATH_MAX + 1], best[PATH_MAX + 1];
-
- op = oldname;
- np = newname;
- for (;;)
- {
- while (*op == '/') /* Skip slashes */
- *np++ = *op++;
- *np = '\0';
-
- if (*op == '\0') /* Exact or corrected */
- {
- /* `.' is rarely the right thing. */
- if (oldname[1] == '\0' && newname[1] == '\0' &&
- oldname[0] != '.' && newname[0] == '.')
- return -1;
- return strcmp(oldname, newname) != 0;
- }
-
- /* Copy next component into guess */
- for (p = guess; *op != '/' && *op != '\0'; op++)
- if (p < guess + PATH_MAX)
- *p++ = *op;
- *p = '\0';
-
- if (mindist(newname, guess, best) >= 3)
- return -1; /* Hopeless */
-
- /*
- * Add to end of newname
- */
- for (p = best; *np = *p++; np++)
- ;
- }
-}
-
-/*
- * Search directory for a guess
- */
-static int
-mindist(dir, guess, best)
- char *dir;
- char *guess;
- char *best;
-{
- DIR *fd;
- struct dirent *dp;
- int dist, x;
-
- dist = 3; /* Worst distance */
- if (*dir == '\0')
- dir = ".";
-
- if ((fd = opendir(dir)) == NULL)
- return dist;
-
- while ((dp = readdir(fd)) != NULL)
- {
- /*
- * Look for a better guess. If the new guess is as
- * good as the current one, we take it. This way,
- * any single character match will be a better match
- * than ".".
- */
- x = spdist(dp->d_name, guess);
- if (x <= dist && x != 3)
- {
- strcpy(best, dp->d_name);
- dist = x;
- if (dist == 0) /* Exact match */
- break;
- }
- }
- (void)closedir(fd);
-
- /* Don't return `.' */
- if (best[0] == '.' && best[1] == '\0')
- dist = 3;
- return dist;
-}
-
-/*
- * `spdist' -- return the "distance" between two names.
- *
- * int spname(char * oldname, char * newname)
- * Returns: 0 if strings are identical
- * 1 if two characters are transposed
- * 2 if one character is wrong, added or deleted
- * 3 otherwise
- */
-static int
-spdist(cur, new)
- char *cur, *new;
-{
- while (*cur == *new)
- {
- if (*cur == '\0')
- return 0; /* Exact match */
- cur++;
- new++;
- }
-
- if (*cur)
- {
- if (*new)
- {
- if (cur[1] && new[1] && cur[0] == new[1] && cur[1] == new[0] && strcmp (cur + 2, new + 2) == 0)
- return 1; /* Transposition */
-
- if (strcmp (cur + 1, new + 1) == 0)
- return 2; /* One character mismatch */
- }
-
- if (strcmp(&cur[1], &new[0]) == 0)
- return 2; /* Extra character */
- }
-
- if (*new && strcmp(cur, new + 1) == 0)
- return 2; /* Missing character */
-
- return 3;
-}