1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1989-2012 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Eclipse Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.eclipse.org/org/documents/epl-v10.html *
11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Eduardo Krell <ekrell@adexus.cl> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
23
24 #include "3d.h"
25
26 /*
27 * get next view for path sp
28 */
29
30 char*
pathnext(char * sp,char * extra,long * visits)31 pathnext(char* sp, char* extra, long* visits)
32 {
33 register char* ep = sp + strlen(sp);
34 register char* cp;
35 register char* tmp;
36 register int shift;
37 Map_t* vpath;
38 int vpathlen;
39
40 message((-4, "pathnext: ++ %s%s%s [0x%08x]", sp, extra ? " + " : state.null, extra ? extra : state.null, visits ? *visits : 0L));
41
42 /*
43 * check for next layer and previous visit
44 */
45
46 if (state.path.level + 1 >= state.limit)
47 {
48 message((-4, "pathnext: -- %s [limit=%d]", NiL, state.limit));
49 return 0;
50 }
51 ep = sp + (shift = strlen(sp));
52 if (!(vpath = search(state.path.table ? state.path.table : &state.vpath, sp, shift, (const char*)visits, T_PREFIX)))
53 {
54 message((-4, "pathnext: -- %s [0x%08x]", NiL, visits ? *visits : 0L));
55 return 0;
56 }
57
58 /*
59 * we found a viewpath entry
60 * check if stuff after extra needs to be shifted
61 */
62
63 vpathlen = T_VALSIZE(vpath);
64 cp = sp + vpath->keysize;
65 shift = vpathlen - (cp - sp);
66 if (shift < 0)
67 {
68 /*
69 * shift left
70 */
71
72 if (cp < ep)
73 strcopy(sp + vpathlen + 1, cp + 1);
74 }
75 else if (shift > 0)
76 {
77 /*
78 * shift right extra
79 */
80
81 if (extra)
82 {
83 for (tmp = extra + strlen(extra); tmp >= extra; tmp--)
84 tmp[shift] = *tmp;
85 extra += shift;
86 }
87
88 /*
89 * shift right cp
90 */
91
92 if (cp < ep)
93 {
94 for (tmp = ep; tmp > cp; tmp--)
95 tmp[shift] = *tmp;
96 strcopy(sp + vpathlen + 1, cp + shift + 1);
97 }
98 }
99
100 /*
101 * insert vpath
102 */
103
104 strncpy(sp, vpath->val, vpathlen);
105 sp[vpathlen] = cp < ep ? '/' : 0;
106 cp = sp;
107 if (extra)
108 strcpy(sp = ep + shift, extra);
109 state.path.level++;
110 message((-4, "pathnext: -- %s [level=%d visits=0x%08x]", cp, state.path.level, visits ? *visits : 0L));
111 return sp;
112 }
113
114 /*
115 * search for the instance name for path sp
116 * and place in instname
117 * 0 returned when instances exhausted
118 * if create is non-zero, use name before the first slash as instance
119 * name, and do not check existence.
120 */
121
122 int
instance(register char * sp,char * instname,struct stat * st,int create)123 instance(register char* sp, char* instname, struct stat* st, int create)
124 {
125 register char* cp;
126 register char* mp;
127 register char* mapnext;
128 register int size;
129 int maps;
130 char* mapend;
131 Map_t* map;
132
133 cp = instname++;
134 mapnext = mapend = 0;
135 maps = 0;
136 if (state.vmap.size)
137 {
138 while (*--cp != '/');
139 if (!create) cp -= 4;
140 }
141 else cp = sp;
142 for (;;)
143 {
144 if ((mp = mapnext) >= mapend)
145 {
146 /*
147 * look for next vmap
148 */
149
150 while (cp > sp)
151 {
152 map = search(&state.vmap, sp, cp - sp, NiL, 0);
153 if (cp > sp + 1)
154 {
155 while (*--cp != '/');
156 while (cp > sp && cp[-1] == '/') cp--;
157 if (cp == sp) cp++;
158 }
159 else cp = sp;
160 if (map && (!create || *map->val != '/'))
161 goto match;
162 }
163 if (!create)
164 {
165 strcpy(instname, state.vdefault);
166 maps++;
167 if (!LSTAT(sp, st))
168 goto found;
169 }
170 return 0;
171 match:
172 mp = map->val;
173 size = T_VALSIZE(map);
174 mapend = mp + size;
175 if (create)
176 {
177 while (mp < mapend && *mp!='/') mp++;
178 if ((size = mp - map->val) <= 0)
179 return 0;
180 memcpy(instname, map->val, size);
181 instname[size] = 0;
182 maps++;
183 goto found;
184 }
185 if (*mp == '/') mp++;
186 }
187 for (mapnext = mp; mapnext < mapend; mapnext++)
188 if (*mapnext == '/')
189 break;
190 if ((size = mapnext - mp) <= 0) continue;
191 memcpy(instname, mp, size = mapnext - mp);
192 instname[size] = 0;
193 while (mapnext < mapend && *mapnext == '/') mapnext++;
194 maps++;
195 if (!LSTAT(sp, st))
196 goto found;
197 }
198 /*NOTREACHED*/
199 found:
200 if (maps > 1)
201 state.path.level |= INSTANCE;
202 return 1;
203 }
204