1: /* $Header: optpath.c,v 1.2 85/05/06 13:32:05 nicklin Exp $ */
2:
3: /*
4: * Author: Peter J. Nicklin
5: */
6:
7: /*
8: * optpath() condenses a pathname by eliminating adjacent separator
9: * characters, and current and parent directory names. If optpath()
10: * encounters a parent directory, it backtracks to eliminate the
11: * previous directory. If the beginning of the pathname is reached
12: * during backtracking, then if the pathname is absolute, the parent
13: * directory is purged, otherwise it is shifted to the beginning of
14: * pathname. Special care is taken not to clobber a shifted parent
15: * by using a guard pointer. Returns pathname.
16: */
17: #include "path.h"
18:
19: #define absolute_path (*pathname == _RDIRC)
20:
21: static char parentdir[] = PARENTDIR; /* parent directory name */
22:
23: char *
24: optpath(pathname)
25: register char *pathname; /* pathname to be optimized */
26: {
27: register char *bp; /* back pathname pointer */
28: register char *fp; /* forward pathname pointer */
29: register char *up; /* pathname update guard pointer */
30: char p1; /* 1st parent directory character */
31: char p2; /* 2nd parent directory character */
32:
33: p1 = parentdir[0];
34: p2 = parentdir[1];
35:
36: bp = fp = up = pathname;
37:
38: /* elimination of initial "./" causes no harmful side-effects */
39: if (fp[0] == _CDIRC && fp[1] == _PSC) fp += 2;
40:
41: while (*fp != '\0')
42: if (fp[0] == _PSC)
43: if (fp[1] == _PSC || fp[1] == '\0')
44: fp += 1; /* "//" or trailing `/' */
45: else if (fp[1]==_CDIRC && (fp[2]==_PSC || fp[2]=='\0'))
46: fp += 2; /* `.' */
47: else if ((fp[1] == p1 && fp[2] == p2) &&
48: (fp[3] == _PSC || fp[3] == '\0'))
49: { /* ".." (don't backtrack over a "..") */
50: if (absolute_path ||
51: (bp > up && bp-2 < pathname) ||
52: (bp > up && (bp[-2] != p1 || bp[-1] != p2)))
53: {
54: while (bp > up && *--bp != _PSC)
55: continue;
56: }
57: else {
58: /* don't clobber separator character */
59: if (bp[0] == _PSC) bp++;
60: bp[0] = fp[1];
61: bp[1] = fp[2];
62: bp[2] = fp[3];
63: up = bp += 2;
64: }
65: fp += 3;
66: }
67: else {
68: *bp++ = *fp++;
69: }
70: else {
71: *bp++ = *fp++;
72: }
73: if (bp == pathname && *pathname != '\0')
74: *bp++ = (absolute_path) ? _RDIRC : _CDIRC;
75: *bp = '\0';
76: return(pathname);
77: }
Defined functions
Defined variables
Defined macros