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