2 #include "compatibility.hh"
4 //=========================== PATHNAME ===============================
7 * Grammar for labels with pathnames
8 *-----------------------------------
9 * <label> = <name> | <path> <name>
11 * <path> = <apath> | <rpath>
12 * <apath> = '/' | '/' <rpath>
13 * <rpath> = (<gname> '/')+
14 * <gname> = ".." | "." | <gtype> <name>
15 * <gtype> = "h:" | "H:" | "v:" | V:" | "t:" | "T:"
19 Sym PATHROOT
= symbol ("/");
20 Tree
pathRoot() { return tree(PATHROOT
); }
21 bool isPathRoot(Tree t
) { return isTree(t
, PATHROOT
); }
23 Sym PATHPARENT
= symbol ("..");
24 Tree
pathParent() { return tree(PATHPARENT
); }
25 bool isPathParent(Tree t
) { return isTree(t
, PATHPARENT
); }
27 Sym PATHCURRENT
= symbol (".");
28 Tree
pathCurrent() { return tree(PATHCURRENT
); }
29 bool isPathCurrent(Tree t
) { return isTree(t
, PATHCURRENT
); }
34 * analyze name for "H:name" | "V:name" etc
37 static Tree
encodeName(char g
, const string
& name
)
41 case 'V': return cons(tree(0), tree(name
));
44 case 'H': return cons(tree(1), tree(name
));
47 case 'T': return cons(tree(2), tree(name
));
49 default : return cons(tree(0), tree(name
));
55 * Analyzes a label and converts it as a path
58 static Tree
label2path(const char* label
)
61 return cons(tree(""), nil
);
63 } else if (label
[0] == '/') {
64 return cons(pathRoot(), label2path(&label
[1]));
66 } else if ((label
[0] == '.') && (label
[1] == '/')) {
67 return label2path(&label
[2]);
69 } else if ((label
[0] == '.') && (label
[1] == '.') && (label
[2] == '/')) {
70 return cons(pathParent(), label2path(&label
[3]));
72 } else if (label
[1] == ':') {
76 while ((label
[i
] != 0) && (label
[i
] != '/')) {
77 s
.push_back(label
[i
]);
80 if (label
[i
] == '/') i
++;
81 return cons(encodeName(g
,s
), label2path(&label
[i
]));
84 return cons(tree(label
),nil
);
90 * Concatenate the relative path to the absolute path
91 * Note that the relpath is top-down while the abspath
95 static Tree
concatPath(Tree relpath
, Tree abspath
)
97 if (isList(relpath
)) {
98 Tree head
= hd(relpath
);
99 if (isPathRoot(head
)) {
100 return concatPath(tl(relpath
), nil
);
101 } else if (isPathParent(head
)) {
102 if (!isList(abspath
)) {
103 //cerr << "abspath : " << *abspath << endl;
104 return concatPath(tl(relpath
), hd(relpath
));
106 return concatPath(tl(relpath
), tl(abspath
));
108 } else if (isPathCurrent(head
)) {
109 return concatPath(tl(relpath
), abspath
);
111 return concatPath(tl(relpath
), cons(head
,abspath
));
114 assert(isNil(relpath
));
120 static Tree
normalizeLabel(Tree label
, Tree path
)
122 // we suppose label = "../label" ou "name/label" ou "name"
123 //cout << "Normalize Label " << *label << " with path " << *path << endl;
125 return cons(label
, path
);
128 assert (isSym(label
->node(),&s
));
129 return concatPath(label2path(name(s
)),path
);
133 Tree
normalizePath(Tree path
)
135 //cout << "Normalize Path [[" << *path << "]]" << endl;
140 npath
= normalizeLabel(hd(path
), normalizePath(tl(path
)));
142 //cout << " -> [[" << *npath << "]]" << endl;