]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - db/flist.c
Update copyright/license notices to match SGI legal prefered boilerplate.
[thirdparty/xfsprogs-dev.git] / db / flist.c
1 /*
2 * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it would be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <xfs/libxfs.h>
20 #include "type.h"
21 #include "faddr.h"
22 #include "fprint.h"
23 #include "field.h"
24 #include "flist.h"
25 #include "debug.h"
26 #include "output.h"
27 #include "malloc.h"
28
29 static void flist_expand_arrays(flist_t *fl);
30 static void flist_expand_structs(flist_t *fl, void *obj);
31 static flist_t *flist_replicate(flist_t *fl);
32 static ftok_t *flist_split(char *s);
33 static void ftok_free(ftok_t *ft);
34
35 static void
36 flist_expand_arrays(
37 flist_t *fl)
38 {
39 const field_t *f;
40 #ifdef DEBUG
41 const ftattr_t *fa;
42 #endif
43 int high;
44 int idx;
45 int low;
46 flist_t *new;
47 flist_t *prev;
48 flist_t *sib;
49
50 f = fl->fld;
51 #ifdef DEBUG
52 fa = &ftattrtab[f->ftyp];
53 #endif
54 ASSERT(fa->ftyp == f->ftyp);
55 ASSERT(f->flags & FLD_ARRAY);
56 low = fl->low;
57 high = fl->high;
58 fl->high = fl->low;
59 sib = fl->sibling;
60 for (idx = low + 1, prev = fl; idx <= high; idx++) {
61 new = flist_make(f->name);
62 new->fld = f;
63 new->low = new->high = idx;
64 new->flags |= FL_OKLOW | FL_OKHIGH;
65 new->child = flist_replicate(fl->child);
66 prev->sibling = new;
67 prev = new;
68 }
69 prev->sibling = sib;
70 }
71
72 static void
73 flist_expand_structs(
74 flist_t *fl,
75 void *obj)
76 {
77 const field_t *cf;
78 const field_t *f;
79 const ftattr_t *fa;
80 flist_t *new;
81 flist_t *prev;
82
83 f = fl->fld;
84 fa = &ftattrtab[f->ftyp];
85 ASSERT(fa->ftyp == f->ftyp);
86 ASSERT(fa->subfld != NULL);
87 ASSERT(fl->child == NULL);
88 for (cf = fa->subfld, prev = NULL; cf->name != NULL; cf++) {
89 if (fcount(cf, obj, fl->offset) == 0)
90 continue;
91 if (cf->flags & FLD_SKIPALL)
92 continue;
93 new = flist_make(cf->name);
94 new->fld = cf;
95 if (prev)
96 prev->sibling = new;
97 else
98 fl->child = new;
99 prev = new;
100 }
101 }
102
103 void
104 flist_free(
105 flist_t *fl)
106 {
107 if (fl->child)
108 flist_free(fl->child);
109 if (fl->sibling)
110 flist_free(fl->sibling);
111 if (fl->name)
112 xfree(fl->name);
113 xfree(fl);
114 }
115
116 flist_t *
117 flist_make(
118 char *name)
119 {
120 flist_t *fl;
121
122 fl = xmalloc(sizeof(*fl));
123 fl->name = xstrdup(name);
124 fl->fld = NULL;
125 fl->child = NULL;
126 fl->sibling = NULL;
127 fl->low = 0;
128 fl->high = 0;
129 fl->flags = 0;
130 fl->offset = 0;
131 return fl;
132 }
133
134 int
135 flist_parse(
136 const field_t *fields,
137 flist_t *fl,
138 void *obj,
139 int startoff)
140 {
141 const field_t *f;
142 const ftattr_t *fa;
143 int high;
144 int low;
145
146 while (fl) {
147 f = findfield(fl->name, fields, obj, startoff);
148 if (f == NULL) {
149 dbprintf("field %s not found\n", fl->name);
150 return 0;
151 }
152 fl->fld = f;
153 fa = &ftattrtab[f->ftyp];
154 ASSERT(fa->ftyp == f->ftyp);
155 if (f->flags & FLD_ARRAY) {
156 low = (f->flags & FLD_ABASE1) != 0;
157 high = fcount(f, obj, startoff) + low - 1;
158 if (low > high) {
159 dbprintf("no elements in %s\n", fl->name);
160 return 0;
161 }
162 if (fl->flags & FL_OKHIGH) {
163 if (fl->low < low || fl->low > high ||
164 fl->high < low || fl->high > high) {
165 dbprintf("indices %d-%d for field %s "
166 "out of range %d-%d\n",
167 fl->low, fl->high, fl->name,
168 low, high);
169 return 0;
170 }
171 } else if (fl->flags & FL_OKLOW) {
172 if (fl->low < low || fl->low > high) {
173 dbprintf("index %d for field %s out of "
174 "range %d-%d\n",
175 fl->low, fl->name, low, high);
176 return 0;
177 }
178 fl->high = fl->low;
179 fl->flags |= FL_OKHIGH;
180 } else {
181 fl->low = low;
182 fl->high = high;
183 fl->flags |= FL_OKLOW | FL_OKHIGH;
184 }
185 } else {
186 if (fl->flags & FL_OKLOW) {
187 dbprintf("field %s is not an array\n",
188 fl->name);
189 return 0;
190 }
191 }
192 fl->offset = startoff + bitoffset(f, obj, startoff, fl->low);
193 if ((fl->child != NULL || fa->prfunc == NULL) &&
194 (f->flags & FLD_ARRAY) && fl->low != fl->high)
195 flist_expand_arrays(fl);
196 if (fa->prfunc == NULL && fl->child == NULL)
197 flist_expand_structs(fl, obj);
198 if (fl->child) {
199 if (fa->subfld == NULL) {
200 dbprintf("field %s has no subfields\n",
201 fl->name);
202 return 0;
203 }
204 if (!flist_parse(fa->subfld, fl->child, obj,
205 fl->offset))
206 return 0;
207 }
208 fl = fl->sibling;
209 }
210 return 1;
211 }
212
213 void
214 flist_print(
215 flist_t *fl)
216 {
217 if (!(debug_state & DEBUG_FLIST))
218 return;
219 while (fl) {
220 dbprintf("fl@%p:\n", fl);
221 dbprintf("\tname=%s, fld=%p, child=%p, sibling=%p\n",
222 fl->name, fl->fld, fl->child, fl->sibling);
223 dbprintf("\tlow=%d, high=%d, flags=%d (%s%s), offset=%d\n",
224 fl->low, fl->high, fl->flags,
225 fl->flags & FL_OKLOW ? "oklow " : "",
226 fl->flags & FL_OKHIGH ? "okhigh" : "", fl->offset);
227 dbprintf("\tfld->name=%s, fld->ftyp=%d (%s)\n",
228 fl->fld->name, fl->fld->ftyp,
229 ftattrtab[fl->fld->ftyp].name);
230 dbprintf("\tfld->flags=%d (%s%s%s%s%s)\n", fl->fld->flags,
231 fl->fld->flags & FLD_ABASE1 ? "abase1 " : "",
232 fl->fld->flags & FLD_SKIPALL ? "skipall " : "",
233 fl->fld->flags & FLD_ARRAY ? "array " : "",
234 fl->fld->flags & FLD_OFFSET ? "offset " : "",
235 fl->fld->flags & FLD_COUNT ? "count " : "");
236 if (fl->child)
237 flist_print(fl->child);
238 fl = fl->sibling;
239 }
240 }
241
242 static flist_t *
243 flist_replicate(
244 flist_t *f)
245 {
246 flist_t *new;
247
248 if (f == NULL)
249 return NULL;
250 new = flist_make(f->name);
251 new->fld = f->fld;
252 new->child = flist_replicate(f->child);
253 new->sibling = flist_replicate(f->sibling);
254 new->low = f->low;
255 new->high = f->high;
256 new->flags = f->flags;
257 new->offset = f->offset;
258 return new;
259 }
260
261 flist_t *
262 flist_scan(
263 char *name)
264 {
265 flist_t *fl;
266 flist_t *lfl;
267 flist_t *nfl;
268 int num;
269 ftok_t *p;
270 ftok_t *v;
271 char *x;
272
273 v = flist_split(name);
274 if (!v)
275 return NULL;
276 p = v;
277 fl = lfl = NULL;
278 while (p->tokty != TT_END) {
279 if (p->tokty != TT_NAME)
280 goto bad;
281 nfl = flist_make(p->tok);
282 if (lfl)
283 lfl->child = nfl;
284 else
285 fl = nfl;
286 lfl = nfl;
287 p++;
288 if (p->tokty == TT_LB) {
289 p++;
290 if (p->tokty != TT_NUM)
291 goto bad;
292 num = (int)strtoul(p->tok, &x, 0);
293 if (*x != '\0')
294 goto bad;
295 nfl->flags |= FL_OKLOW;
296 nfl->low = num;
297 p++;
298 if (p->tokty == TT_DASH) {
299 p++;
300 if (p->tokty != TT_NUM)
301 goto bad;
302 num = (int)strtoul(p->tok, &x, 0);
303 if (*x != '\0')
304 goto bad;
305 nfl->flags |= FL_OKHIGH;
306 nfl->high = num;
307 p++;
308 }
309 if (p->tokty != TT_RB)
310 goto bad;
311 p++;
312 }
313 if (p->tokty == TT_DOT) {
314 p++;
315 if (p->tokty == TT_END)
316 goto bad;
317 }
318 }
319 ftok_free(v);
320 return fl;
321 bad:
322 dbprintf("bad syntax in field name %s\n", name);
323 ftok_free(v);
324 if (fl)
325 flist_free(fl);
326 return NULL;
327 }
328
329 static ftok_t *
330 flist_split(
331 char *s)
332 {
333 char *a;
334 int i;
335 static char *idchars;
336 static char *initidchar;
337 int l;
338 int tailskip = 0;
339 static char *numchars;
340 static char *xnumchars; /* extended for hex conversion */
341 int nv;
342 static char punctchars[] = "[-].";
343 static tokty_t puncttypes[] = { TT_LB, TT_DASH, TT_RB, TT_DOT };
344 tokty_t t;
345 ftok_t *v;
346
347 if (idchars == NULL) {
348 idchars = xmalloc(26 + 10 + 1 + 1);
349 initidchar = xmalloc(26 + 1);
350 numchars = xmalloc(10 + 1);
351 xnumchars = xmalloc(12 + 1);
352 for (i = 'a'; i <= 'z'; i++) {
353 idchars[i - 'a'] = i;
354 initidchar[i - 'a'] = i;
355 }
356
357 for (i = '0'; i <= '9'; i++) {
358 idchars[26 + (i - '0')] = i;
359 numchars[i - '0'] = i;
360 xnumchars[i - '0'] = i;
361 }
362 idchars[26 + 10] = '_';
363 idchars[26 + 10 + 1] = '\0';
364 initidchar[26] = '\0';
365 numchars[10] = '\0';
366 xnumchars[10] = 'x';
367 xnumchars[11] = 'X';
368 xnumchars[12] = '\0';
369 }
370 nv = 0;
371 v = xmalloc(sizeof(*v));
372 v->tok = NULL;
373 while (*s) {
374 /* need to add string handling */
375 if (*s == '\"') {
376 s++; /* skip first quote */
377 if ((a = strrchr(s, '\"')) == NULL) {
378 dbprintf("missing closing quote %s\n", s);
379 ftok_free(v);
380 return NULL;
381 }
382 tailskip = 1; /* skip remaing quote */
383 l = (int)(a - s);
384 t = TT_STRING;
385 } else if (strchr(initidchar, *s)) {
386 l = (int)strspn(s, idchars);
387 t = TT_NAME;
388 } else if (strchr(numchars, *s)) {
389 l = (int)strspn(s, xnumchars);
390 t = TT_NUM;
391 } else if ((a = strchr(punctchars, *s))) {
392 l = 1;
393 t = puncttypes[a - punctchars];
394 } else {
395 dbprintf("bad character in field %s\n", s);
396 ftok_free(v);
397 return NULL;
398 }
399 a = xmalloc(l + 1);
400 strncpy(a, s, l);
401 a[l] = '\0';
402 v = xrealloc(v, (nv + 2) * sizeof(*v));
403 v[nv].tok = a;
404 v[nv].tokty = t;
405 nv++;
406 s += l + tailskip;
407 tailskip = 0;
408 }
409 v[nv].tok = NULL;
410 v[nv].tokty = TT_END;
411 return v;
412 }
413
414 static void
415 ftok_free(
416 ftok_t *ft)
417 {
418 ftok_t *p;
419
420 for (p = ft; p->tok; p++)
421 xfree(p->tok);
422 xfree(ft);
423 }