1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkParseExtras.c
5
6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7 All rights reserved.
8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9
10 This software is distributed WITHOUT ANY WARRANTY; without even
11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12 PURPOSE. See the above copyright notice for more information.
13
14 =========================================================================*/
15 /*-------------------------------------------------------------------------
16 Copyright (c) 2011 David Gobbi.
17
18 Contributed to the VisualizationToolkit by the author in May 2011
19 under the terms of the Visualization Toolkit 2008 copyright.
20 -------------------------------------------------------------------------*/
21
22 #include "vtkParseExtras.h"
23 #include "vtkParseString.h"
24 #include "vtkType.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <ctype.h>
29 #include <assert.h>
30
31 /* skip over an expression in brackets */
vtkparse_bracket_len(const char * text)32 static size_t vtkparse_bracket_len(const char *text)
33 {
34 size_t i = 0;
35 size_t j = 1;
36 char bc = text[0];
37 char tc = 0;
38 char semi = ';';
39 char c;
40
41 if (bc == '(') { tc = ')'; }
42 else if (bc == '[') { tc = ']'; }
43 else if (bc == '{') { tc = '}'; semi = '\0'; }
44 else if (bc == '<') { tc = '>'; }
45 else { return 0; }
46
47 do
48 {
49 i += j;
50 j = 1;
51 c = text[i];
52 if (vtkParse_CharType(c, CPRE_QUOTE))
53 {
54 j = vtkParse_SkipQuotes(&text[i]);
55 }
56 else if (c == bc || c == '(' || c == '[' || c == '{')
57 {
58 j = vtkparse_bracket_len(&text[i]);
59 }
60 }
61 while (c != tc && c != ')' && c != ']' && c != '}' &&
62 c != '\0' && c != '\n' && c != semi && j != 0);
63
64 if (c == tc)
65 {
66 i++;
67 }
68
69 return i;
70 }
71
72 /* skip over a name that is neither scoped or templated, return the
73 * total number of characters in the name */
vtkParse_IdentifierLength(const char * text)74 size_t vtkParse_IdentifierLength(const char *text)
75 {
76 return vtkParse_SkipId(text);
77 }
78
79 /* skip over a name that might be templated, return the
80 * total number of characters in the name */
vtkParse_UnscopedNameLength(const char * text)81 size_t vtkParse_UnscopedNameLength(const char *text)
82 {
83 size_t i = 0;
84
85 i += vtkParse_SkipId(text);
86 if (text[i] == '<')
87 {
88 i += vtkparse_bracket_len(&text[i]);
89 if (text[i-1] != '>')
90 {
91 fprintf(stderr, "Bad template args %*.*s\n", (int)i, (int)i, text);
92 assert(text[i-1] == '>');
93 return 0;
94 }
95 }
96
97 return i;
98 }
99
100 /* skip over a name that might be scoped or templated, return the
101 * total number of characters in the name */
vtkParse_NameLength(const char * text)102 size_t vtkParse_NameLength(const char *text)
103 {
104 size_t i = 0;
105 do
106 {
107 if (text[i] == ':' && text[i+1] == ':') { i += 2; }
108 i += vtkParse_UnscopedNameLength(&text[i]);
109 }
110 while (text[i] == ':' && text[i+1] == ':');
111 return i;
112 }
113
114 /* Search and replace, return the initial string if no replacements
115 * occurred, otherwise return a new string. */
vtkparse_string_replace(StringCache * cache,const char * str1,int n,const char * name[],const char * val[])116 static const char *vtkparse_string_replace(
117 StringCache *cache, const char *str1,
118 int n, const char *name[], const char *val[])
119 {
120 const char *cp = str1;
121 char result_store[1024];
122 size_t resultMaxLen = 1024;
123 char *result, *tmp;
124 int k;
125 size_t i, j, l, m;
126 size_t lastPos, nameBegin, nameEnd;
127 int replaced = 0;
128 int any_replaced = 0;
129
130 result = result_store;
131
132 if (n == 0)
133 {
134 return str1;
135 }
136
137 i = 0;
138 j = 0;
139 result[j] = '\0';
140
141 while (cp[i] != '\0')
142 {
143 lastPos = i;
144
145 /* skip all chars that aren't part of a name */
146 while (!vtkParse_CharType(cp[i], CPRE_ID) && cp[i] != '\0')
147 {
148 if (vtkParse_CharType(cp[i], CPRE_QUOTE))
149 {
150 i += vtkParse_SkipQuotes(&cp[i]);
151 }
152 else if (vtkParse_CharType(cp[i], CPRE_QUOTE))
153 {
154 i += vtkParse_SkipNumber(&cp[i]);
155 }
156 else
157 {
158 i++;
159 }
160 }
161 nameBegin = i;
162
163 /* skip all chars that are part of a name */
164 i += vtkParse_SkipId(&cp[i]);
165 nameEnd = i;
166
167 /* search through the list of names to replace */
168 replaced = 0;
169 m = nameEnd - nameBegin;
170 for (k = 0; k < n; k++)
171 {
172 l = strlen(name[k]);
173 if (l > 0 && l == m && strncmp(&cp[nameBegin], name[k], l) == 0)
174 {
175 m = strlen(val[k]);
176 replaced = 1;
177 any_replaced = 1;
178 break;
179 }
180 }
181
182 /* expand the storage space if needed */
183 if (j + m + (nameBegin - lastPos) + 1 >= resultMaxLen)
184 {
185 resultMaxLen *= 2;
186 tmp = (char *)malloc(resultMaxLen);
187 strcpy(tmp, result);
188 if (result != result_store)
189 {
190 free(result);
191 }
192 result = tmp;
193 }
194
195 /* copy the old bits */
196 if (nameBegin > lastPos)
197 {
198 strncpy(&result[j], &cp[lastPos], nameBegin - lastPos);
199 j += (nameBegin - lastPos);
200 }
201
202 /* do the replacement */
203 if (replaced)
204 {
205 strncpy(&result[j], val[k], m);
206 j += m;
207 /* guard against creating double ">>" */
208 if (val[k][m-1] == '>' && cp[nameEnd] == '>')
209 {
210 result[j++] = ' ';
211 }
212 }
213 else if (nameEnd > nameBegin)
214 {
215 strncpy(&result[j], &cp[nameBegin], nameEnd - nameBegin);
216 j += (nameEnd - nameBegin);
217 }
218
219 result[j] = '\0';
220 }
221
222 if (cache)
223 {
224 if (any_replaced)
225 {
226 /* use the efficient CacheString method */
227 cp = vtkParse_CacheString(cache, result, j);
228 if (result != result_store)
229 {
230 free(result);
231 }
232 }
233 }
234 else
235 {
236 if (any_replaced)
237 {
238 /* return a string that was allocated with malloc */
239 if (result == result_store)
240 {
241 tmp = (char *)malloc(strlen(result) + 1);
242 strcpy(tmp, result);
243 result = tmp;
244 }
245 cp = result;
246 }
247 }
248
249 return cp;
250 }
251
252 /* Wherever one of the specified names exists inside a Value or inside
253 * a Dimension size, replace it with the corresponding val string. */
vtkParse_ExpandValues(ValueInfo * valinfo,StringCache * cache,int n,const char * name[],const char * val[])254 void vtkParse_ExpandValues(
255 ValueInfo *valinfo, StringCache *cache,
256 int n, const char *name[], const char *val[])
257 {
258 int j, m, dim, count;
259 const char *cp;
260
261 if (valinfo->Value)
262 {
263 valinfo->Value = vtkparse_string_replace(
264 cache, valinfo->Value, n, name, val);
265 }
266
267 m = valinfo->NumberOfDimensions;
268 if (m)
269 {
270 count = 1;
271 for (j = 0; j < m; j++)
272 {
273 cp = valinfo->Dimensions[j];
274 if (cp)
275 {
276 cp = vtkparse_string_replace(cache, cp, n, name, val);
277 valinfo->Dimensions[j] = cp;
278
279 /* check whether dimension has become an integer literal */
280 if (cp[0] == '0' && (cp[1] == 'x' || cp[1] == 'X')) { cp += 2; }
281 while (*cp >= '0' && *cp <= '9') { cp++; }
282 while (*cp == 'u' || *cp == 'l' || *cp == 'U' || *cp == 'L') { cp++; }
283 dim = 0;
284 if (*cp == '\0')
285 {
286 dim = (int)strtol(valinfo->Dimensions[j], NULL, 0);
287 }
288 count *= dim;
289 }
290 }
291
292 /* update count if all values are integer literals */
293 if (count)
294 {
295 valinfo->Count = count;
296 }
297 }
298 }
299
300 /* Expand a typedef within a type declaration. */
vtkParse_ExpandTypedef(ValueInfo * valinfo,ValueInfo * typedefinfo)301 void vtkParse_ExpandTypedef(
302 ValueInfo *valinfo, ValueInfo *typedefinfo)
303 {
304 const char *classname;
305 unsigned int baseType;
306 unsigned int pointers;
307 unsigned int refbit;
308 unsigned int qualifiers;
309 unsigned int tmp1, tmp2;
310 int i;
311
312 classname = typedefinfo->Class;
313 baseType = (typedefinfo->Type & VTK_PARSE_BASE_TYPE);
314 pointers = (typedefinfo->Type & VTK_PARSE_POINTER_MASK);
315 refbit = (valinfo->Type & VTK_PARSE_REF);
316 qualifiers = (typedefinfo->Type & VTK_PARSE_CONST);
317
318 /* handle const */
319 if ((valinfo->Type & VTK_PARSE_CONST) != 0)
320 {
321 if ((pointers & VTK_PARSE_POINTER_LOWMASK) != 0)
322 {
323 if ((pointers & VTK_PARSE_POINTER_LOWMASK) != VTK_PARSE_ARRAY)
324 {
325 /* const turns into const pointer */
326 pointers = (pointers & ~VTK_PARSE_POINTER_LOWMASK);
327 pointers = (pointers | VTK_PARSE_CONST_POINTER);
328 }
329 }
330 else
331 {
332 /* const remains as const value */
333 qualifiers = (qualifiers | VTK_PARSE_CONST);
334 }
335 }
336
337 /* make a reversed copy of the pointer bitfield */
338 tmp1 = (valinfo->Type & VTK_PARSE_POINTER_MASK);
339 tmp2 = 0;
340 while (tmp1)
341 {
342 tmp2 = ((tmp2 << 2) | (tmp1 & VTK_PARSE_POINTER_LOWMASK));
343 tmp1 = ((tmp1 >> 2) & VTK_PARSE_POINTER_MASK);
344 }
345
346 /* turn pointers into zero-element arrays where necessary */
347 if ((pointers & VTK_PARSE_POINTER_LOWMASK) == VTK_PARSE_ARRAY)
348 {
349 tmp2 = ((tmp2 >> 2) & VTK_PARSE_POINTER_MASK);
350 while (tmp2)
351 {
352 vtkParse_AddStringToArray(
353 &valinfo->Dimensions, &valinfo->NumberOfDimensions, "");
354 tmp2 = ((tmp2 >> 2) & VTK_PARSE_POINTER_MASK);
355 }
356 }
357 else
358 {
359 /* combine the pointers */
360 while (tmp2)
361 {
362 pointers = ((pointers << 2) | (tmp2 & VTK_PARSE_POINTER_LOWMASK));
363 tmp2 = ((tmp2 >> 2) & VTK_PARSE_POINTER_MASK);
364 }
365 }
366
367 /* combine the arrays */
368 for (i = 0; i < typedefinfo->NumberOfDimensions; i++)
369 {
370 vtkParse_AddStringToArray(
371 &valinfo->Dimensions, &valinfo->NumberOfDimensions,
372 typedefinfo->Dimensions[i]);
373 }
374 if (valinfo->NumberOfDimensions > 1)
375 {
376 pointers = ((pointers & ~VTK_PARSE_POINTER_LOWMASK) | VTK_PARSE_ARRAY);
377 }
378
379 /* put everything together */
380 valinfo->Type = (baseType | pointers | refbit | qualifiers);
381 valinfo->Class = classname;
382 valinfo->Function = typedefinfo->Function;
383 valinfo->Count *= typedefinfo->Count;
384 }
385
386 /* Expand any unrecognized types within a variable, parameter, or typedef
387 * that match any of the supplied typedefs. The expansion is done in-place. */
vtkParse_ExpandTypedefs(ValueInfo * val,StringCache * cache,int n,const char * names[],const char * values[],ValueInfo * typedefinfo[])388 void vtkParse_ExpandTypedefs(
389 ValueInfo *val, StringCache *cache,
390 int n, const char *names[], const char *values[],
391 ValueInfo *typedefinfo[])
392 {
393 int i;
394
395 if (((val->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_OBJECT ||
396 (val->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_UNKNOWN) &&
397 val->Class != 0)
398 {
399 for (i = 0; i < n; i++)
400 {
401 if (typedefinfo[i] && strcmp(val->Class, typedefinfo[i]->Name) == 0)
402 {
403 vtkParse_ExpandTypedef(val, typedefinfo[i]);
404 break;
405 }
406 }
407 if (i == n)
408 {
409 /* in case type appears as a template arg of another type */
410 val->Class = vtkparse_string_replace(
411 cache, val->Class, n, names, values);
412 }
413 }
414 }
415
416 /* Helper struct for VTK-specific types */
417 struct vtk_type_struct
418 {
419 size_t len;
420 const char *name;
421 unsigned int type;
422 };
423
424 /* Simple utility for mapping VTK types to VTK_PARSE types */
vtkParse_MapType(int vtktype)425 unsigned int vtkParse_MapType(int vtktype)
426 {
427 static unsigned int typemap[] =
428 {
429 VTK_PARSE_VOID, /* VTK_VOID 0 */
430 0, /* VTK_BIT 1 */
431 VTK_PARSE_CHAR, /* VTK_CHAR 2 */
432 VTK_PARSE_UNSIGNED_CHAR, /* VTK_UNSIGNED_CHAR 3 */
433 VTK_PARSE_SHORT, /* VTK_SHORT 4 */
434 VTK_PARSE_UNSIGNED_SHORT, /* VTK_UNSIGNED_SHORT 5 */
435 VTK_PARSE_INT, /* VTK_INT 6 */
436 VTK_PARSE_UNSIGNED_INT, /* VTK_UNSIGNED_INT 7 */
437 VTK_PARSE_LONG, /* VTK_LONG 8 */
438 VTK_PARSE_UNSIGNED_LONG, /* VTK_UNSIGNED_LONG 9 */
439 VTK_PARSE_FLOAT, /* VTK_FLOAT 10 */
440 VTK_PARSE_DOUBLE, /* VTK_DOUBLE 11 */
441 VTK_PARSE_ID_TYPE, /* VTK_ID_TYPE 12 */
442 VTK_PARSE_STRING, /* VTK_STRING 13 */
443 0, /* VTK_OPAQUE 14 */
444 VTK_PARSE_SIGNED_CHAR, /* VTK_SIGNED_CHAR 15 */
445 VTK_PARSE_LONG_LONG, /* VTK_LONG_LONG 16 */
446 VTK_PARSE_UNSIGNED_LONG_LONG, /* VTK_UNSIGNED_LONG_LONG 17 */
447 VTK_PARSE___INT64, /* VTK___INT64 18 */
448 VTK_PARSE_UNSIGNED___INT64, /* VTK_UNSIGNED___INT64 19 */
449 0, /* VTK_VARIANT 20 */
450 0, /* VTK_OBJECT 21 */
451 VTK_PARSE_UNICODE_STRING /* VTK_UNICODE_STRING 22 */
452 };
453
454 if (vtktype > 0 && vtktype <= VTK_UNICODE_STRING)
455 {
456 return typemap[vtktype];
457 }
458 return 0;
459 }
460
461 /* Get a type from a type name, and return the number of characters used.
462 * If the "classname" argument is not NULL, then it is used to return
463 * the short name for the type, e.g. "long int" becomes "long", while
464 * typedef names and class names are returned unchanged. If "const"
465 * appears in the type name, then the const bit flag is set for the
466 * type, but "const" will not appear in the returned classname. */
vtkParse_BasicTypeFromString(const char * text,unsigned int * type_ptr,const char ** classname_ptr,size_t * len_ptr)467 size_t vtkParse_BasicTypeFromString(
468 const char *text, unsigned int *type_ptr,
469 const char **classname_ptr, size_t *len_ptr)
470 {
471 /* The various typedefs and types specific to VTK */
472 static struct vtk_type_struct vtktypes[] = {
473 { 9, "vtkIdType", VTK_ID_TYPE },
474 { 12, "vtkStdString", VTK_STRING },
475 { 16, "vtkUnicodeString", VTK_UNICODE_STRING },
476 { 11, "vtkTypeInt8", VTK_TYPE_INT8 },
477 { 12, "vtkTypeUInt8", VTK_TYPE_UINT8 },
478 { 12, "vtkTypeInt16", VTK_TYPE_INT16 },
479 { 13, "vtkTypeUInt16", VTK_TYPE_UINT16 },
480 { 12, "vtkTypeInt32", VTK_TYPE_INT32 },
481 { 13, "vtkTypeUInt32", VTK_TYPE_UINT32 },
482 { 12, "vtkTypeInt64", VTK_TYPE_INT64 },
483 { 13, "vtkTypeUInt64", VTK_TYPE_UINT64 },
484 { 14, "vtkTypeFloat32", VTK_TYPE_FLOAT32 },
485 { 14, "vtkTypeFloat64", VTK_TYPE_FLOAT64 },
486 { 0, 0, 0 } };
487
488 /* Other typedefs and types */
489 static struct vtk_type_struct stdtypes[] = {
490 { 6, "size_t", VTK_PARSE_SIZE_T },
491 { 7, "ssize_t", VTK_PARSE_SSIZE_T },
492 { 7, "ostream", VTK_PARSE_OSTREAM },
493 { 7, "istream", VTK_PARSE_ISTREAM },
494 { 8, "string", VTK_PARSE_STRING },
495 { 0, 0, 0 } };
496
497 const char *cp = text;
498 const char *tmpcp;
499 size_t k, n, m;
500 int i;
501 unsigned int const_bits = 0;
502 unsigned int static_bits = 0;
503 unsigned int unsigned_bits = 0;
504 unsigned int base_bits = 0;
505 const char *classname = NULL;
506 size_t len = 0;
507
508 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
509
510 while (vtkParse_CharType(*cp, CPRE_ID) ||
511 (cp[0] == ':' && cp[1] == ':'))
512 {
513 /* skip all chars that are part of a name */
514 n = vtkParse_NameLength(cp);
515
516 if ((n == 6 && strncmp("static", cp, n) == 0) ||
517 (n == 4 && strncmp("auto", cp, n) == 0) ||
518 (n == 8 && strncmp("register", cp, n) == 0) ||
519 (n == 8 && strncmp("volatile", cp, n) == 0))
520 {
521 if (strncmp("static", cp, n) == 0)
522 {
523 static_bits = VTK_PARSE_STATIC;
524 }
525 }
526 else if (n == 5 && strncmp(cp, "const", n) == 0)
527 {
528 const_bits |= VTK_PARSE_CONST;
529 }
530 else if (n == 8 && strncmp(cp, "unsigned", n) == 0)
531 {
532 unsigned_bits |= VTK_PARSE_UNSIGNED;
533 if (base_bits == 0)
534 {
535 classname = "int";
536 base_bits = VTK_PARSE_INT;
537 }
538 }
539 else if (n == 6 && strncmp(cp, "signed", n) == 0)
540 {
541 if (base_bits == VTK_PARSE_CHAR)
542 {
543 classname = "signed char";
544 base_bits = VTK_PARSE_SIGNED_CHAR;
545 }
546 else
547 {
548 classname = "int";
549 base_bits = VTK_PARSE_INT;
550 }
551 }
552 else if (n == 3 && strncmp(cp, "int", n) == 0)
553 {
554 if (base_bits == 0)
555 {
556 classname = "int";
557 base_bits = VTK_PARSE_INT;
558 }
559 }
560 else if (n == 4 && strncmp(cp, "long", n) == 0)
561 {
562 if (base_bits == VTK_PARSE_DOUBLE)
563 {
564 classname = "long double";
565 base_bits = VTK_PARSE_LONG_DOUBLE;
566 }
567 else if (base_bits == VTK_PARSE_LONG)
568 {
569 classname = "long long";
570 base_bits = VTK_PARSE_LONG_LONG;
571 }
572 else
573 {
574 classname = "long";
575 base_bits = VTK_PARSE_LONG;
576 }
577 }
578 else if (n == 5 && strncmp(cp, "short", n) == 0)
579 {
580 classname = "short";
581 base_bits = VTK_PARSE_SHORT;
582 }
583 else if (n == 4 && strncmp(cp, "char", n) == 0)
584 {
585 if (base_bits == VTK_PARSE_INT && unsigned_bits != VTK_PARSE_UNSIGNED)
586 {
587 classname = "signed char";
588 base_bits = VTK_PARSE_SIGNED_CHAR;
589 }
590 else
591 {
592 classname = "char";
593 base_bits = VTK_PARSE_CHAR;
594 }
595 }
596 else if (n == 5 && strncmp(cp, "float", n) == 0)
597 {
598 classname = "float";
599 base_bits = VTK_PARSE_FLOAT;
600 }
601 else if (n == 6 && strncmp(cp, "double", n) == 0)
602 {
603 if (base_bits == VTK_PARSE_LONG)
604 {
605 classname = "long double";
606 base_bits = VTK_PARSE_LONG_DOUBLE;
607 }
608 else
609 {
610 classname = "double";
611 base_bits = VTK_PARSE_DOUBLE;
612 }
613 }
614 else if (n == 4 && strncmp(cp, "bool", n) == 0)
615 {
616 classname = "bool";
617 base_bits = VTK_PARSE_BOOL;
618 }
619 else if (n == 4 && strncmp(cp, "void", n) == 0)
620 {
621 classname = "void";
622 base_bits = VTK_PARSE_VOID;
623 }
624 else if (n == 7 && strncmp(cp, "__int64", n) == 0)
625 {
626 classname = "__int64";
627 base_bits = VTK_PARSE___INT64;
628 }
629 else
630 {
631 /* if type already found, break */
632 if (base_bits != 0)
633 {
634 break;
635 }
636
637 /* check vtk typedefs */
638 if (strncmp(cp, "vtk", 3) == 0)
639 {
640 for (i = 0; vtktypes[i].len != 0; i++)
641 {
642 if (n == vtktypes[i].len && strncmp(cp, vtktypes[i].name, n) == 0)
643 {
644 classname = vtktypes[i].name;
645 base_bits = vtkParse_MapType((int)vtktypes[i].type);
646 }
647 }
648 }
649
650 /* check standard typedefs */
651 if (base_bits == 0)
652 {
653 m = 0;
654 if (strncmp(cp, "::", 2) == 0) { m = 2; }
655 else if (strncmp(cp, "std::", 5) == 0) { m = 5; }
656 else if (strncmp(cp, "vtkstd::", 8) == 0) { m = 8; }
657
658 /* advance past the namespace */
659 tmpcp = cp + m;
660
661 for (i = 0; stdtypes[i].len != 0; i++)
662 {
663 if (n == stdtypes[i].len && strncmp(tmpcp, stdtypes[i].name, n) == 0)
664 {
665 classname = stdtypes[i].name;
666 base_bits = stdtypes[i].type;
667 }
668 }
669
670 /* include the namespace if present */
671 if (base_bits != 0 && m > 0)
672 {
673 classname = cp;
674 len = n;
675 }
676 }
677
678 /* anything else is assumed to be a class, enum, or who knows */
679 if (base_bits == 0)
680 {
681 base_bits = VTK_PARSE_UNKNOWN;
682 classname = cp;
683 len = n;
684
685 /* VTK classes all start with vtk */
686 if (strncmp(classname, "vtk", 3) == 0)
687 {
688 base_bits = VTK_PARSE_OBJECT;
689 /* make sure the "vtk" isn't just part of the namespace */
690 for (k = 0; k < n; k++)
691 {
692 if (cp[k] == ':')
693 {
694 base_bits = VTK_PARSE_UNKNOWN;
695 break;
696 }
697 }
698 }
699 /* Qt objects and enums */
700 else if (classname[0] == 'Q' &&
701 ((classname[1] >= 'A' && classname[2] <= 'Z') ||
702 strncmp(classname, "Qt::", 4) == 0))
703 {
704 base_bits = VTK_PARSE_QOBJECT;
705 }
706 }
707 }
708
709 cp += n;
710 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
711 }
712
713 if ((unsigned_bits & VTK_PARSE_UNSIGNED) != 0)
714 {
715 switch (base_bits)
716 {
717 case VTK_PARSE_CHAR:
718 classname = "unsigned char";
719 break;
720 case VTK_PARSE_SHORT:
721 classname = "unsigned short";
722 break;
723 case VTK_PARSE_INT:
724 classname = "unsigned int";
725 break;
726 case VTK_PARSE_LONG:
727 classname = "unsigned long";
728 break;
729 case VTK_PARSE_LONG_LONG:
730 classname = "unsigned long long";
731 break;
732 case VTK_PARSE___INT64:
733 classname = "unsigned __int64";
734 break;
735 }
736 }
737
738 *type_ptr = (static_bits | const_bits | unsigned_bits | base_bits);
739
740 if (classname_ptr)
741 {
742 *classname_ptr = classname;
743 if (len == 0)
744 {
745 len = strlen(classname);
746 }
747 *len_ptr = len;
748 }
749
750 return (size_t)(cp - text);
751 }
752
753 /* Parse a type description in "text" and generate a typedef named "name" */
vtkParse_ValueInfoFromString(ValueInfo * data,StringCache * cache,const char * text)754 size_t vtkParse_ValueInfoFromString(
755 ValueInfo *data, StringCache *cache, const char *text)
756 {
757 const char *cp = text;
758 size_t n;
759 int m, count;
760 unsigned int base_bits = 0;
761 unsigned int pointer_bits = 0;
762 unsigned int ref_bits = 0;
763 const char *classname = NULL;
764
765 /* get the basic type with qualifiers */
766 cp += vtkParse_BasicTypeFromString(cp, &base_bits, &classname, &n);
767
768 data->Class = vtkParse_CacheString(cache, classname, n);
769
770 if ((base_bits & VTK_PARSE_STATIC) != 0)
771 {
772 data->IsStatic = 1;
773 }
774
775 /* look for pointers (and const pointers) */
776 while (*cp == '*')
777 {
778 cp++;
779 pointer_bits = (pointer_bits << 2);
780 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
781 if (strncmp(cp, "const", 5) == 0 &&
782 !vtkParse_CharType(cp[5], CPRE_IDGIT))
783 {
784 cp += 5;
785 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
786 pointer_bits = (pointer_bits | VTK_PARSE_CONST_POINTER);
787 }
788 else
789 {
790 pointer_bits = (pointer_bits | VTK_PARSE_POINTER);
791 }
792 pointer_bits = (pointer_bits & VTK_PARSE_POINTER_MASK);
793 }
794
795 /* look for ref */
796 if (*cp == '&')
797 {
798 cp++;
799 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
800 ref_bits = VTK_PARSE_REF;
801 }
802
803 /* look for the variable name */
804 if (vtkParse_CharType(*cp, CPRE_ID))
805 {
806 /* skip all chars that are part of a name */
807 n = vtkParse_SkipId(cp);
808 data->Name = vtkParse_CacheString(cache, cp, n);
809 cp += n;
810 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
811 }
812
813 /* look for array brackets */
814 if (*cp == '[')
815 {
816 count = 1;
817
818 while (*cp == '[')
819 {
820 n = vtkparse_bracket_len(cp);
821 if (n > 1)
822 {
823 cp++;
824 n -= 2;
825 }
826 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; n--; }
827 while (n > 0 && vtkParse_CharType(cp[n-1], CPRE_HSPACE)) { n--; }
828 vtkParse_AddStringToArray(
829 &data->Dimensions,
830 &data->NumberOfDimensions,
831 vtkParse_CacheString(cache, cp, n));
832 m = 0;
833 if (vtkParse_CharType(*cp, CPRE_DIGIT) &&
834 vtkParse_SkipNumber(cp) == n)
835 {
836 m = (int)strtol(cp, NULL, 0);
837 }
838 count *= m;
839
840 cp += n;
841 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
842 if (*cp == ']') { cp++; }
843 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
844 }
845 }
846
847 /* add pointer indirection to correspond to first array dimension */
848 if (data->NumberOfDimensions > 1)
849 {
850 pointer_bits = ((pointer_bits << 2) | VTK_PARSE_ARRAY);
851 }
852 else if (data->NumberOfDimensions == 1)
853 {
854 pointer_bits = ((pointer_bits << 2) | VTK_PARSE_POINTER);
855 }
856 pointer_bits = (pointer_bits & VTK_PARSE_POINTER_MASK);
857
858 /* (Add code here to look for "=" followed by a value ) */
859
860 data->Type = (pointer_bits | ref_bits | base_bits);
861
862 return (cp - text);
863 }
864
865 /* Generate a C++ declaration string from a ValueInfo struct */
vtkParse_ValueInfoToString(ValueInfo * data,int * needs_free)866 const char *vtkParse_ValueInfoToString(
867 ValueInfo *data, int *needs_free)
868 {
869 unsigned int pointer_bits = (data->Type & VTK_PARSE_POINTER_MASK);
870 unsigned int ref_bits = (data->Type & VTK_PARSE_REF);
871 unsigned int qualifier_bits = (data->Type & VTK_PARSE_CONST);
872 unsigned int reverse_bits = 0;
873 unsigned int pointer_type = 0;
874 const char *classname = data->Class;
875 const char *name = data->Name;
876 char *text = NULL;
877 size_t i = 0;
878 size_t l;
879 int j = 0;
880
881 if (pointer_bits == 0 && ref_bits == 0 && qualifier_bits == 0 &&
882 name == NULL)
883 {
884 if (needs_free)
885 {
886 *needs_free = 0;
887 }
888 return classname;
889 }
890
891 /* compute the length of string to allocate */
892 l = 6; /* for const */
893 l += 4*7; /* for pointers */
894 l += 1; /* for ref */
895 l += strlen(classname) + 1; /* for type */
896 for (j = 0; j < data->NumberOfDimensions; j++)
897 {
898 l += 2 + strlen(data->Dimensions[j]);
899 }
900 l++; /* for NULL */
901 l += 4; /* for safety */
902
903 text = (char *)malloc(l);
904
905 if ((qualifier_bits & VTK_PARSE_CONST) != 0)
906 {
907 strcpy(&text[i], "const ");
908 i += 6;
909 }
910
911 strcpy(&text[i], classname);
912 i += strlen(classname);
913 text[i++] = ' ';
914
915 while (pointer_bits != 0)
916 {
917 reverse_bits <<= 2;
918 reverse_bits |= (pointer_bits & VTK_PARSE_POINTER_LOWMASK);
919 pointer_bits = ((pointer_bits >> 2) & VTK_PARSE_POINTER_MASK);
920 }
921
922 while (reverse_bits != 0)
923 {
924 pointer_type = (reverse_bits & VTK_PARSE_POINTER_LOWMASK);
925 if (pointer_type == VTK_PARSE_ARRAY ||
926 (reverse_bits == VTK_PARSE_POINTER &&
927 data->NumberOfDimensions > 0))
928 {
929 break;
930 }
931 else if (pointer_type == VTK_PARSE_POINTER)
932 {
933 text[i++] = '*';
934 }
935 else if (pointer_type == VTK_PARSE_CONST_POINTER)
936 {
937 strcpy(&text[i], "*const ");
938 i += 7;
939 }
940
941 reverse_bits = ((reverse_bits >> 2) & VTK_PARSE_POINTER_MASK);
942 }
943
944 if (ref_bits)
945 {
946 text[i++] = '&';
947 }
948
949 if (name)
950 {
951 strcpy(&text[i], name);
952 i += strlen(name);
953 }
954
955 for (j = 0; j < data->NumberOfDimensions; j++)
956 {
957 text[i++] = '[';
958 if (data->Dimensions[j])
959 {
960 strcpy(&text[i], data->Dimensions[j]);
961 i += strlen(data->Dimensions[j]);
962 }
963 text[i++] = ']';
964 }
965
966 text[i] = '\0';
967
968 /* make sure enough space was allocated */
969 assert(i < l);
970
971 if (needs_free)
972 {
973 *needs_free = 1;
974 }
975
976 return text;
977 }
978
979 /* Search and replace, return the initial string if no replacements
980 * occurred, otherwise return a new string allocated with malloc. */
vtkParse_StringReplace(const char * str1,int n,const char * name[],const char * val[])981 const char *vtkParse_StringReplace(
982 const char *str1, int n, const char *name[], const char *val[])
983 {
984 return vtkparse_string_replace(NULL, str1, n, name, val);
985 }
986
987 /* substitute generic types and values with actual types and values */
988 static void func_substitution(
989 FunctionInfo *data, StringCache *cache,
990 int m, const char *arg_names[],
991 const char *arg_values[], ValueInfo *arg_types[]);
992
value_substitution(ValueInfo * data,StringCache * cache,int m,const char * arg_names[],const char * arg_values[],ValueInfo * arg_types[])993 static void value_substitution(
994 ValueInfo *data, StringCache *cache,
995 int m, const char *arg_names[],
996 const char *arg_values[], ValueInfo *arg_types[])
997 {
998 vtkParse_ExpandTypedefs(data, cache, m, arg_names, arg_values, arg_types);
999 vtkParse_ExpandValues(data, cache, m, arg_names, arg_values);
1000
1001 if (data->Function)
1002 {
1003 func_substitution(
1004 data->Function, cache, m, arg_names, arg_values, arg_types);
1005 }
1006 }
1007
func_substitution(FunctionInfo * data,StringCache * cache,int m,const char * arg_names[],const char * arg_values[],ValueInfo * arg_types[])1008 static void func_substitution(
1009 FunctionInfo *data, StringCache *cache,
1010 int m, const char *arg_names[],
1011 const char *arg_values[], ValueInfo *arg_types[])
1012 {
1013 int i, n;
1014
1015 n = data->NumberOfParameters;
1016 for (i = 0; i < n; i++)
1017 {
1018 value_substitution(
1019 data->Parameters[i], cache, m, arg_names, arg_values, arg_types);
1020 }
1021
1022 if (data->ReturnValue)
1023 {
1024 value_substitution(
1025 data->ReturnValue, cache, m, arg_names, arg_values, arg_types);
1026 }
1027
1028 if (data->Signature)
1029 {
1030 data->Signature =
1031 vtkparse_string_replace(
1032 cache, data->Signature, m, arg_names, arg_values);
1033 }
1034
1035 /* legacy information for old wrappers */
1036 #ifndef VTK_PARSE_LEGACY_REMOVE
1037 n = data->NumberOfArguments;
1038 for (i = 0; i < n; i++)
1039 {
1040 data->ArgTypes[i] = data->Parameters[i]->Type;
1041 data->ArgClasses[i] = data->Parameters[i]->Class;
1042 if (data->Parameters[i]->NumberOfDimensions == 1 &&
1043 data->Parameters[i]->Count > 0)
1044 {
1045 data->ArgCounts[i] = data->Parameters[i]->Count;
1046 }
1047 }
1048
1049 if (data->ReturnValue)
1050 {
1051 data->ReturnType = data->ReturnValue->Type;
1052 data->ReturnClass = data->ReturnValue->Class;
1053 if (data->ReturnValue->NumberOfDimensions == 1 &&
1054 data->ReturnValue->Count > 0)
1055 {
1056 data->HintSize = data->ReturnValue->Count;
1057 data->HaveHint = 1;
1058 }
1059 }
1060 #endif /* VTK_PARSE_LEGACY_REMOVE */
1061 }
1062
class_substitution(ClassInfo * data,StringCache * cache,int m,const char * arg_names[],const char * arg_values[],ValueInfo * arg_types[])1063 static void class_substitution(
1064 ClassInfo *data, StringCache *cache,
1065 int m, const char *arg_names[],
1066 const char *arg_values[], ValueInfo *arg_types[])
1067 {
1068 int i, n;
1069
1070 /* superclasses may be templated */
1071 n = data->NumberOfSuperClasses;
1072 for (i = 0; i < n; i++)
1073 {
1074 data->SuperClasses[i] = vtkparse_string_replace(
1075 cache, data->SuperClasses[i], m, arg_names, arg_values);
1076 }
1077
1078 n = data->NumberOfClasses;
1079 for (i = 0; i < n; i++)
1080 {
1081 class_substitution(
1082 data->Classes[i], cache, m, arg_names, arg_values, arg_types);
1083 }
1084
1085 n = data->NumberOfFunctions;
1086 for (i = 0; i < n; i++)
1087 {
1088 func_substitution(
1089 data->Functions[i], cache, m, arg_names, arg_values, arg_types);
1090 }
1091
1092 n = data->NumberOfConstants;
1093 for (i = 0; i < n; i++)
1094 {
1095 value_substitution(
1096 data->Constants[i], cache, m, arg_names, arg_values, arg_types);
1097 }
1098
1099 n = data->NumberOfVariables;
1100 for (i = 0; i < n; i++)
1101 {
1102 value_substitution(
1103 data->Variables[i], cache, m, arg_names, arg_values, arg_types);
1104 }
1105
1106 n = data->NumberOfTypedefs;
1107 for (i = 0; i < n; i++)
1108 {
1109 value_substitution(
1110 data->Typedefs[i], cache, m, arg_names, arg_values, arg_types);
1111 }
1112 }
1113
1114 /* Extract template args from a comma-separated list enclosed
1115 * in angle brackets. Returns zero if no angle brackets found. */
vtkParse_DecomposeTemplatedType(const char * text,const char ** classname,int nargs,const char *** argp,const char * defaults[])1116 size_t vtkParse_DecomposeTemplatedType(
1117 const char *text, const char **classname,
1118 int nargs, const char ***argp, const char *defaults[])
1119 {
1120 size_t i, j, k, n;
1121 const char *arg;
1122 char *new_text;
1123 const char **template_args = NULL;
1124 int template_arg_count = 0;
1125
1126 n = vtkParse_NameLength(text);
1127
1128 /* is the class templated? */
1129 for (i = 0; i < n; i++)
1130 {
1131 if (text[i] == '<')
1132 {
1133 break;
1134 }
1135 }
1136
1137 if (classname)
1138 {
1139 new_text = (char *)malloc(i + 1);
1140 strncpy(new_text, text, i);
1141 new_text[i] = '\0';
1142 *classname = new_text;
1143 }
1144
1145 if (text[i] == '<')
1146 {
1147 i++;
1148 /* extract the template arguments */
1149 for (;;)
1150 {
1151 while (vtkParse_CharType(text[i], CPRE_HSPACE)) { i++; }
1152 j = i;
1153 while (text[j] != ',' && text[j] != '>' &&
1154 text[j] != '\n' && text[j] != '\0')
1155 {
1156 if (text[j] == '<' || text[j] == '(' ||
1157 text[j] == '[' || text[j] == '{')
1158 {
1159 j += vtkparse_bracket_len(&text[j]);
1160 }
1161 else if (vtkParse_CharType(text[j], CPRE_QUOTE))
1162 {
1163 j += vtkParse_SkipQuotes(&text[j]);
1164 }
1165 else
1166 {
1167 j++;
1168 }
1169 }
1170
1171 k = j;
1172 while (vtkParse_CharType(text[k-1], CPRE_HSPACE)) { --k; }
1173
1174 new_text = (char *)malloc(k-i + 1);
1175 strncpy(new_text, &text[i], k-i);
1176 new_text[k-i] = '\0';
1177 vtkParse_AddStringToArray(&template_args, &template_arg_count,
1178 new_text);
1179
1180 assert(template_arg_count <= nargs);
1181
1182 i = j + 1;
1183
1184 if (text[j] != ',')
1185 {
1186 break;
1187 }
1188 }
1189 }
1190
1191 while (template_arg_count < nargs)
1192 {
1193 assert(defaults != NULL);
1194 arg = defaults[template_arg_count];
1195 assert(arg != NULL);
1196 new_text = (char *)malloc(strlen(arg + 1));
1197 strcpy(new_text, arg);
1198 vtkParse_AddStringToArray(&template_args, &template_arg_count, new_text);
1199 }
1200
1201 *argp = template_args;
1202
1203 return i;
1204 }
1205
1206 /* Free the list of strings returned by ExtractTemplateArgs. */
vtkParse_FreeTemplateDecomposition(const char * name,int n,const char ** args)1207 void vtkParse_FreeTemplateDecomposition(
1208 const char *name, int n, const char **args)
1209 {
1210 int i;
1211
1212 if (name)
1213 {
1214 free((char *)name);
1215 }
1216
1217 if (n > 0)
1218 {
1219 for (i = 0; i < n; i++)
1220 {
1221 free((char *)args[i]);
1222 }
1223
1224 free((char **)args);
1225 }
1226 }
1227
1228 /* Instantiate a class template by substituting the provided arguments. */
vtkParse_InstantiateClassTemplate(ClassInfo * data,StringCache * cache,int n,const char * args[])1229 void vtkParse_InstantiateClassTemplate(
1230 ClassInfo *data, StringCache *cache, int n, const char *args[])
1231 {
1232 TemplateInfo *t = data->Template;
1233 const char **new_args = NULL;
1234 const char **arg_names = NULL;
1235 ValueInfo **arg_types = NULL;
1236 int i, m;
1237 char *new_name;
1238 size_t k;
1239
1240 if (t == NULL)
1241 {
1242 fprintf(stderr, "vtkParse_InstantiateClassTemplate: "
1243 "this class is not templated.\n");
1244 return;
1245 }
1246
1247 m = t->NumberOfParameters;
1248 if (n > m)
1249 {
1250 fprintf(stderr, "vtkParse_InstantiateClassTemplate: "
1251 "too many template args.\n");
1252 return;
1253 }
1254
1255 for (i = n; i < m; i++)
1256 {
1257 if (t->Parameters[i]->Value == NULL ||
1258 t->Parameters[i]->Value[0] == '\0')
1259 {
1260 fprintf(stderr, "vtkParse_InstantiateClassTemplate: "
1261 "too few template args.\n");
1262 return;
1263 }
1264 }
1265
1266 new_args = (const char **)malloc(m*sizeof(char **));
1267 for (i = 0; i < n; i++)
1268 {
1269 new_args[i] = args[i];
1270 }
1271 for (i = n; i < m; i++)
1272 {
1273 new_args[i] = t->Parameters[i]->Value;
1274 }
1275 args = new_args;
1276
1277 arg_names = (const char **)malloc(m*sizeof(char **));
1278 arg_types = (ValueInfo **)malloc(m*sizeof(ValueInfo *));
1279 for (i = 0; i < m; i++)
1280 {
1281 arg_names[i] = t->Parameters[i]->Name;
1282 arg_types[i] = NULL;
1283 if (t->Parameters[i]->Type == 0)
1284 {
1285 arg_types[i] = (ValueInfo *)malloc(sizeof(ValueInfo));
1286 vtkParse_InitValue(arg_types[i]);
1287 vtkParse_ValueInfoFromString(arg_types[i], cache, args[i]);
1288 arg_types[i]->ItemType = VTK_TYPEDEF_INFO;
1289 arg_types[i]->Name = arg_names[i];
1290 }
1291 }
1292
1293 /* no longer a template (has been instantiated) */
1294 if (data->Template)
1295 {
1296 vtkParse_FreeTemplate(data->Template);
1297 }
1298 data->Template = NULL;
1299
1300 /* append template args to class name */
1301 k = strlen(data->Name) + 2;
1302 for (i = 0; i < m; i++)
1303 {
1304 k += strlen(args[i]) + 2;
1305 }
1306 new_name = (char *)malloc(k);
1307 strcpy(new_name, data->Name);
1308 k = strlen(new_name);
1309 new_name[k++] = '<';
1310 for (i = 0; i < m; i++)
1311 {
1312 strcpy(&new_name[k], args[i]);
1313 k += strlen(args[i]);
1314 if (i+1 < m)
1315 {
1316 new_name[k++] = ',';
1317 new_name[k++] = ' ';
1318 }
1319 }
1320 if (new_name[k-1] == '>')
1321 {
1322 new_name[k++] = ' ';
1323 }
1324 new_name[k++] = '>';
1325 new_name[k] = '\0';
1326
1327 data->Name = vtkParse_CacheString(cache, new_name, k);
1328 free(new_name);
1329
1330 /* do the template arg substitution */
1331 class_substitution(data, cache, m, arg_names, args, arg_types);
1332
1333 /* free all allocated arrays */
1334 free((char **)new_args);
1335 free((char **)arg_names);
1336
1337 for (i = 0; i < m; i++)
1338 {
1339 if (arg_types[i])
1340 {
1341 vtkParse_FreeValue(arg_types[i]);
1342 }
1343 }
1344 free(arg_types);
1345 }
1346
1347 /* Get a zero-terminated array of the types in vtkTemplateMacro. */
vtkParse_GetTemplateMacroTypes()1348 const char **vtkParse_GetTemplateMacroTypes()
1349 {
1350 static const char *types[] = {
1351 "char", "signed char", "unsigned char", "short", "unsigned short",
1352 "int", "unsigned int", "long", "unsigned long",
1353 #ifdef VTK_TYPE_USE_LONG_LONG
1354 "long long", "unsigned long long",
1355 #endif
1356 #ifdef VTK_TYPE_USE___INT64
1357 "__int64", "unsigned __int64",
1358 #endif
1359 "float", "double", NULL };
1360
1361 return types;
1362 }
1363
1364 /* Get a zero-terminated array of the types in vtkArray. */
vtkParse_GetArrayTypes()1365 const char **vtkParse_GetArrayTypes()
1366 {
1367 static const char *types[] = {
1368 "char", "signed char", "unsigned char", "short", "unsigned short",
1369 "int", "unsigned int", "long", "unsigned long",
1370 #ifdef VTK_TYPE_USE_LONG_LONG
1371 "long long", "unsigned long long",
1372 #endif
1373 #ifdef VTK_TYPE_USE___INT64
1374 "__int64", "unsigned __int64",
1375 #endif
1376 "float", "double",
1377 "vtkStdString", "vtkUnicodeString", "vtkVariant", NULL };
1378
1379 return types;
1380 }
1381