New directory tree, with preprocessor/ inside interpretor/.
[Faustine.git] / interpretor / preprocessor / faust-0.9.47mr3 / compiler / propagate / labels.cpp
1 #include "labels.hh"
2 #include "compatibility.hh"
3
4 //=========================== PATHNAME ===============================
5
6 /**
7 * Grammar for labels with pathnames
8 *-----------------------------------
9 * <label> = <name> | <path> <name>
10 * <name> = [^/]+
11 * <path> = <apath> | <rpath>
12 * <apath> = '/' | '/' <rpath>
13 * <rpath> = (<gname> '/')+
14 * <gname> = ".." | "." | <gtype> <name>
15 * <gtype> = "h:" | "H:" | "v:" | V:" | "t:" | "T:"
16 *
17 */
18
19 Sym PATHROOT = symbol ("/");
20 Tree pathRoot() { return tree(PATHROOT); }
21 bool isPathRoot(Tree t) { return isTree(t, PATHROOT); }
22
23 Sym PATHPARENT = symbol ("..");
24 Tree pathParent() { return tree(PATHPARENT); }
25 bool isPathParent(Tree t) { return isTree(t, PATHPARENT); }
26
27 Sym PATHCURRENT = symbol (".");
28 Tree pathCurrent() { return tree(PATHCURRENT); }
29 bool isPathCurrent(Tree t) { return isTree(t, PATHCURRENT); }
30
31
32
33 /**
34 * analyze name for "H:name" | "V:name" etc
35 */
36
37 static Tree encodeName(char g, const string& name)
38 {
39 switch (g) {
40 case 'v':
41 case 'V': return cons(tree(0), tree(name));
42
43 case 'h':
44 case 'H': return cons(tree(1), tree(name));
45
46 case 't':
47 case 'T': return cons(tree(2), tree(name));
48
49 default : return cons(tree(0), tree(name));
50 }
51 }
52
53
54 /**
55 * Analyzes a label and converts it as a path
56 */
57
58 static Tree label2path(const char* label)
59 {
60 if (label[0] == 0) {
61 return cons(tree(""), nil);
62
63 } else if (label[0] == '/') {
64 return cons(pathRoot(), label2path(&label[1]));
65
66 } else if ((label[0] == '.') && (label[1] == '/')) {
67 return label2path(&label[2]);
68
69 } else if ((label[0] == '.') && (label[1] == '.') && (label[2] == '/')) {
70 return cons(pathParent(), label2path(&label[3]));
71
72 } else if (label[1] == ':') {
73 char g = label[0];
74 string s;
75 int i = 2;
76 while ((label[i] != 0) && (label[i] != '/')) {
77 s.push_back(label[i]);
78 i++;
79 }
80 if (label[i] == '/') i++;
81 return cons(encodeName(g,s), label2path(&label[i]));
82
83 } else {
84 return cons(tree(label),nil);
85 }
86 }
87
88
89 /**
90 * Concatenate the relative path to the absolute path
91 * Note that the relpath is top-down while the abspath
92 * is bottom-up
93 */
94
95 static Tree concatPath(Tree relpath, Tree abspath)
96 {
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));
105 } else {
106 return concatPath(tl(relpath), tl(abspath));
107 }
108 } else if (isPathCurrent(head)) {
109 return concatPath(tl(relpath), abspath);
110 } else {
111 return concatPath(tl(relpath), cons(head,abspath));
112 }
113 } else {
114 assert(isNil(relpath));
115 return abspath;
116 }
117 }
118
119
120 static Tree normalizeLabel(Tree label, Tree path)
121 {
122 // we suppose label = "../label" ou "name/label" ou "name"
123 //cout << "Normalize Label " << *label << " with path " << *path << endl;
124 if (isList(label)) {
125 return cons(label, path);
126 } else {
127 Sym s;
128 assert (isSym(label->node(),&s));
129 return concatPath(label2path(name(s)),path);
130 }
131 }
132
133 Tree normalizePath(Tree path)
134 {
135 //cout << "Normalize Path [[" << *path << "]]" << endl;
136 Tree npath;
137 if (isNil(path)) {
138 npath = path;
139 } else {
140 npath = normalizeLabel(hd(path), normalizePath(tl(path)));
141 }
142 //cout << " -> [[" << *npath << "]]" << endl;
143 return npath;
144 }
145