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 attributes;
310 unsigned int tmp1, tmp2;
311 int i;
312
313 classname = typedefinfo->Class;
314 baseType = (typedefinfo->Type & VTK_PARSE_BASE_TYPE);
315 pointers = (typedefinfo->Type & VTK_PARSE_POINTER_MASK);
316 refbit = (valinfo->Type & VTK_PARSE_REF);
317 qualifiers = (typedefinfo->Type & VTK_PARSE_CONST);
318 attributes = (valinfo->Type & VTK_PARSE_ATTRIBUTES);
319
320 /* handle const */
321 if ((valinfo->Type & VTK_PARSE_CONST) != 0)
322 {
323 if ((pointers & VTK_PARSE_POINTER_LOWMASK) != 0)
324 {
325 if ((pointers & VTK_PARSE_POINTER_LOWMASK) != VTK_PARSE_ARRAY)
326 {
327 /* const turns into const pointer */
328 pointers = (pointers & ~VTK_PARSE_POINTER_LOWMASK);
329 pointers = (pointers | VTK_PARSE_CONST_POINTER);
330 }
331 }
332 else
333 {
334 /* const remains as const value */
335 qualifiers = (qualifiers | VTK_PARSE_CONST);
336 }
337 }
338
339 /* make a reversed copy of the pointer bitfield */
340 tmp1 = (valinfo->Type & VTK_PARSE_POINTER_MASK);
341 tmp2 = 0;
342 while (tmp1)
343 {
344 tmp2 = ((tmp2 << 2) | (tmp1 & VTK_PARSE_POINTER_LOWMASK));
345 tmp1 = ((tmp1 >> 2) & VTK_PARSE_POINTER_MASK);
346 }
347
348 /* turn pointers into zero-element arrays where necessary */
349 if ((pointers & VTK_PARSE_POINTER_LOWMASK) == VTK_PARSE_ARRAY)
350 {
351 tmp2 = ((tmp2 >> 2) & VTK_PARSE_POINTER_MASK);
352 while (tmp2)
353 {
354 vtkParse_AddStringToArray(
355 &valinfo->Dimensions, &valinfo->NumberOfDimensions, "");
356 tmp2 = ((tmp2 >> 2) & VTK_PARSE_POINTER_MASK);
357 }
358 }
359 else
360 {
361 /* combine the pointers */
362 while (tmp2)
363 {
364 pointers = ((pointers << 2) | (tmp2 & VTK_PARSE_POINTER_LOWMASK));
365 tmp2 = ((tmp2 >> 2) & VTK_PARSE_POINTER_MASK);
366 }
367 }
368
369 /* combine the arrays */
370 for (i = 0; i < typedefinfo->NumberOfDimensions; i++)
371 {
372 vtkParse_AddStringToArray(
373 &valinfo->Dimensions, &valinfo->NumberOfDimensions,
374 typedefinfo->Dimensions[i]);
375 }
376 if (valinfo->NumberOfDimensions > 1)
377 {
378 pointers = ((pointers & ~VTK_PARSE_POINTER_LOWMASK) | VTK_PARSE_ARRAY);
379 }
380
381 /* put everything together */
382 valinfo->Type = (baseType | pointers | refbit | qualifiers | attributes);
383 valinfo->Class = classname;
384 valinfo->Function = typedefinfo->Function;
385 valinfo->Count *= typedefinfo->Count;
386 }
387
388 /* Expand any unrecognized types within a variable, parameter, or typedef
389 * that match any of the supplied typedefs. The expansion is done in-place. */
vtkParse_ExpandTypedefs(ValueInfo * valinfo,StringCache * cache,int n,const char * name[],const char * val[],ValueInfo * typedefinfo[])390 void vtkParse_ExpandTypedefs(
391 ValueInfo *valinfo, StringCache *cache,
392 int n, const char *name[], const char *val[],
393 ValueInfo *typedefinfo[])
394 {
395 int i;
396
397 if (((valinfo->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_OBJECT ||
398 (valinfo->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_UNKNOWN) &&
399 valinfo->Class != 0)
400 {
401 for (i = 0; i < n; i++)
402 {
403 if (typedefinfo[i] && strcmp(valinfo->Class, typedefinfo[i]->Name) == 0)
404 {
405 vtkParse_ExpandTypedef(valinfo, typedefinfo[i]);
406 break;
407 }
408 }
409 if (i == n)
410 {
411 /* in case type appears as a template arg of another type */
412 valinfo->Class = vtkparse_string_replace(
413 cache, valinfo->Class, n, name, val);
414 }
415 }
416 }
417
418 /* Helper struct for VTK-specific types */
419 struct vtk_type_struct
420 {
421 size_t len;
422 const char *name;
423 unsigned int type;
424 };
425
426 /* Simple utility for mapping VTK types to VTK_PARSE types */
vtkParse_MapType(int vtktype)427 unsigned int vtkParse_MapType(int vtktype)
428 {
429 static unsigned int typemap[] =
430 {
431 VTK_PARSE_VOID, /* VTK_VOID 0 */
432 0, /* VTK_BIT 1 */
433 VTK_PARSE_CHAR, /* VTK_CHAR 2 */
434 VTK_PARSE_UNSIGNED_CHAR, /* VTK_UNSIGNED_CHAR 3 */
435 VTK_PARSE_SHORT, /* VTK_SHORT 4 */
436 VTK_PARSE_UNSIGNED_SHORT, /* VTK_UNSIGNED_SHORT 5 */
437 VTK_PARSE_INT, /* VTK_INT 6 */
438 VTK_PARSE_UNSIGNED_INT, /* VTK_UNSIGNED_INT 7 */
439 VTK_PARSE_LONG, /* VTK_LONG 8 */
440 VTK_PARSE_UNSIGNED_LONG, /* VTK_UNSIGNED_LONG 9 */
441 VTK_PARSE_FLOAT, /* VTK_FLOAT 10 */
442 VTK_PARSE_DOUBLE, /* VTK_DOUBLE 11 */
443 VTK_PARSE_ID_TYPE, /* VTK_ID_TYPE 12 */
444 VTK_PARSE_STRING, /* VTK_STRING 13 */
445 0, /* VTK_OPAQUE 14 */
446 VTK_PARSE_SIGNED_CHAR, /* VTK_SIGNED_CHAR 15 */
447 VTK_PARSE_LONG_LONG, /* VTK_LONG_LONG 16 */
448 VTK_PARSE_UNSIGNED_LONG_LONG, /* VTK_UNSIGNED_LONG_LONG 17 */
449 VTK_PARSE___INT64, /* VTK___INT64 18 */
450 VTK_PARSE_UNSIGNED___INT64, /* VTK_UNSIGNED___INT64 19 */
451 0, /* VTK_VARIANT 20 */
452 0, /* VTK_OBJECT 21 */
453 VTK_PARSE_UNICODE_STRING /* VTK_UNICODE_STRING 22 */
454 };
455
456 if (vtktype > 0 && vtktype <= VTK_UNICODE_STRING)
457 {
458 return typemap[vtktype];
459 }
460 return 0;
461 }
462
463 /* Get a type from a type name, and return the number of characters used.
464 * If the "classname" argument is not NULL, then it is used to return
465 * the short name for the type, e.g. "long int" becomes "long", while
466 * typedef names and class names are returned unchanged. If "const"
467 * appears in the type name, then the const bit flag is set for the
468 * 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)469 size_t vtkParse_BasicTypeFromString(
470 const char *text, unsigned int *type_ptr,
471 const char **classname_ptr, size_t *len_ptr)
472 {
473 /* The various typedefs and types specific to VTK */
474 static struct vtk_type_struct vtktypes[] = {
475 { 9, "vtkIdType", VTK_ID_TYPE },
476 { 12, "vtkStdString", VTK_STRING },
477 { 16, "vtkUnicodeString", VTK_UNICODE_STRING },
478 { 11, "vtkTypeInt8", VTK_TYPE_INT8 },
479 { 12, "vtkTypeUInt8", VTK_TYPE_UINT8 },
480 { 12, "vtkTypeInt16", VTK_TYPE_INT16 },
481 { 13, "vtkTypeUInt16", VTK_TYPE_UINT16 },
482 { 12, "vtkTypeInt32", VTK_TYPE_INT32 },
483 { 13, "vtkTypeUInt32", VTK_TYPE_UINT32 },
484 { 12, "vtkTypeInt64", VTK_TYPE_INT64 },
485 { 13, "vtkTypeUInt64", VTK_TYPE_UINT64 },
486 { 14, "vtkTypeFloat32", VTK_TYPE_FLOAT32 },
487 { 14, "vtkTypeFloat64", VTK_TYPE_FLOAT64 },
488 { 0, 0, 0 } };
489
490 /* Other typedefs and types */
491 static struct vtk_type_struct stdtypes[] = {
492 { 6, "size_t", VTK_PARSE_SIZE_T },
493 { 7, "ssize_t", VTK_PARSE_SSIZE_T },
494 { 7, "ostream", VTK_PARSE_OSTREAM },
495 { 7, "istream", VTK_PARSE_ISTREAM },
496 { 6, "string", VTK_PARSE_STRING },
497 { 0, 0, 0 } };
498
499 const char *cp = text;
500 const char *tmpcp;
501 size_t k, n, m;
502 int i;
503 unsigned int const_bits = 0;
504 unsigned int static_bits = 0;
505 unsigned int unsigned_bits = 0;
506 unsigned int base_bits = 0;
507 const char *classname = NULL;
508 size_t len = 0;
509
510 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
511
512 while (vtkParse_CharType(*cp, CPRE_ID) ||
513 (cp[0] == ':' && cp[1] == ':'))
514 {
515 /* skip all chars that are part of a name */
516 n = vtkParse_NameLength(cp);
517
518 if ((n == 6 && strncmp("static", cp, n) == 0) ||
519 (n == 4 && strncmp("auto", cp, n) == 0) ||
520 (n == 8 && strncmp("register", cp, n) == 0) ||
521 (n == 8 && strncmp("volatile", cp, n) == 0))
522 {
523 if (strncmp("static", cp, n) == 0)
524 {
525 static_bits = VTK_PARSE_STATIC;
526 }
527 }
528 else if (n == 5 && strncmp(cp, "const", n) == 0)
529 {
530 const_bits |= VTK_PARSE_CONST;
531 }
532 else if (n == 8 && strncmp(cp, "unsigned", n) == 0)
533 {
534 unsigned_bits |= VTK_PARSE_UNSIGNED;
535 if (base_bits == 0)
536 {
537 classname = "int";
538 base_bits = VTK_PARSE_INT;
539 }
540 }
541 else if (n == 6 && strncmp(cp, "signed", n) == 0)
542 {
543 if (base_bits == VTK_PARSE_CHAR)
544 {
545 classname = "signed char";
546 base_bits = VTK_PARSE_SIGNED_CHAR;
547 }
548 else
549 {
550 classname = "int";
551 base_bits = VTK_PARSE_INT;
552 }
553 }
554 else if (n == 3 && strncmp(cp, "int", n) == 0)
555 {
556 if (base_bits == 0)
557 {
558 classname = "int";
559 base_bits = VTK_PARSE_INT;
560 }
561 }
562 else if (n == 4 && strncmp(cp, "long", n) == 0)
563 {
564 if (base_bits == VTK_PARSE_DOUBLE)
565 {
566 classname = "long double";
567 base_bits = VTK_PARSE_LONG_DOUBLE;
568 }
569 else if (base_bits == VTK_PARSE_LONG)
570 {
571 classname = "long long";
572 base_bits = VTK_PARSE_LONG_LONG;
573 }
574 else
575 {
576 classname = "long";
577 base_bits = VTK_PARSE_LONG;
578 }
579 }
580 else if (n == 5 && strncmp(cp, "short", n) == 0)
581 {
582 classname = "short";
583 base_bits = VTK_PARSE_SHORT;
584 }
585 else if (n == 4 && strncmp(cp, "char", n) == 0)
586 {
587 if (base_bits == VTK_PARSE_INT && unsigned_bits != VTK_PARSE_UNSIGNED)
588 {
589 classname = "signed char";
590 base_bits = VTK_PARSE_SIGNED_CHAR;
591 }
592 else
593 {
594 classname = "char";
595 base_bits = VTK_PARSE_CHAR;
596 }
597 }
598 else if (n == 5 && strncmp(cp, "float", n) == 0)
599 {
600 classname = "float";
601 base_bits = VTK_PARSE_FLOAT;
602 }
603 else if (n == 6 && strncmp(cp, "double", n) == 0)
604 {
605 if (base_bits == VTK_PARSE_LONG)
606 {
607 classname = "long double";
608 base_bits = VTK_PARSE_LONG_DOUBLE;
609 }
610 else
611 {
612 classname = "double";
613 base_bits = VTK_PARSE_DOUBLE;
614 }
615 }
616 else if (n == 4 && strncmp(cp, "bool", n) == 0)
617 {
618 classname = "bool";
619 base_bits = VTK_PARSE_BOOL;
620 }
621 else if (n == 4 && strncmp(cp, "void", n) == 0)
622 {
623 classname = "void";
624 base_bits = VTK_PARSE_VOID;
625 }
626 else if (n == 7 && strncmp(cp, "__int64", n) == 0)
627 {
628 classname = "__int64";
629 base_bits = VTK_PARSE___INT64;
630 }
631 else
632 {
633 /* if type already found, break */
634 if (base_bits != 0)
635 {
636 break;
637 }
638
639 /* check vtk typedefs */
640 if (strncmp(cp, "vtk", 3) == 0)
641 {
642 for (i = 0; vtktypes[i].len != 0; i++)
643 {
644 if (n == vtktypes[i].len && strncmp(cp, vtktypes[i].name, n) == 0)
645 {
646 classname = vtktypes[i].name;
647 base_bits = vtkParse_MapType((int)vtktypes[i].type);
648 }
649 }
650 }
651
652 /* check standard typedefs */
653 if (base_bits == 0)
654 {
655 m = 0;
656 if (strncmp(cp, "::", 2) == 0) { m = 2; }
657 else if (strncmp(cp, "std::", 5) == 0) { m = 5; }
658
659 /* advance past the namespace */
660 tmpcp = cp + m;
661
662 for (i = 0; stdtypes[i].len != 0; i++)
663 {
664 if (n == m + stdtypes[i].len &&
665 strncmp(tmpcp, stdtypes[i].name, n - m) == 0)
666 {
667 classname = stdtypes[i].name;
668 base_bits = stdtypes[i].type;
669 }
670 }
671
672 /* include the namespace if present */
673 if (base_bits != 0 && m > 0)
674 {
675 classname = cp;
676 len = n;
677 }
678 }
679
680 /* anything else is assumed to be a class, enum, or who knows */
681 if (base_bits == 0)
682 {
683 base_bits = VTK_PARSE_UNKNOWN;
684 classname = cp;
685 len = n;
686
687 /* VTK classes all start with vtk */
688 if (strncmp(classname, "vtk", 3) == 0)
689 {
690 base_bits = VTK_PARSE_OBJECT;
691 /* make sure the "vtk" isn't just part of the namespace */
692 for (k = 0; k < n; k++)
693 {
694 if (cp[k] == ':')
695 {
696 base_bits = VTK_PARSE_UNKNOWN;
697 break;
698 }
699 }
700 }
701 /* Qt objects and enums */
702 else if (classname[0] == 'Q' &&
703 ((classname[1] >= 'A' && classname[2] <= 'Z') ||
704 strncmp(classname, "Qt::", 4) == 0))
705 {
706 base_bits = VTK_PARSE_QOBJECT;
707 }
708 }
709 }
710
711 cp += n;
712 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
713 }
714
715 if ((unsigned_bits & VTK_PARSE_UNSIGNED) != 0)
716 {
717 switch (base_bits)
718 {
719 case VTK_PARSE_CHAR:
720 classname = "unsigned char";
721 break;
722 case VTK_PARSE_SHORT:
723 classname = "unsigned short";
724 break;
725 case VTK_PARSE_INT:
726 classname = "unsigned int";
727 break;
728 case VTK_PARSE_LONG:
729 classname = "unsigned long";
730 break;
731 case VTK_PARSE_LONG_LONG:
732 classname = "unsigned long long";
733 break;
734 case VTK_PARSE___INT64:
735 classname = "unsigned __int64";
736 break;
737 }
738 }
739
740 *type_ptr = (static_bits | const_bits | unsigned_bits | base_bits);
741
742 if (classname_ptr)
743 {
744 *classname_ptr = classname;
745 if (classname && len == 0)
746 {
747 len = strlen(classname);
748 }
749 *len_ptr = len;
750 }
751
752 return (size_t)(cp - text);
753 }
754
755 /* Parse a type description in "text" and generate a typedef named "name" */
vtkParse_ValueInfoFromString(ValueInfo * data,StringCache * cache,const char * text)756 size_t vtkParse_ValueInfoFromString(
757 ValueInfo *data, StringCache *cache, const char *text)
758 {
759 const char *cp = text;
760 size_t n;
761 int m, count;
762 unsigned int base_bits = 0;
763 unsigned int pointer_bits = 0;
764 unsigned int ref_bits = 0;
765 const char *classname = NULL;
766
767 /* get the basic type with qualifiers */
768 cp += vtkParse_BasicTypeFromString(cp, &base_bits, &classname, &n);
769
770 data->Class = vtkParse_CacheString(cache, classname, n);
771
772 if ((base_bits & VTK_PARSE_STATIC) != 0)
773 {
774 data->IsStatic = 1;
775 }
776
777 /* look for pointers (and const pointers) */
778 while (*cp == '*')
779 {
780 cp++;
781 pointer_bits = (pointer_bits << 2);
782 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
783 if (strncmp(cp, "const", 5) == 0 &&
784 !vtkParse_CharType(cp[5], CPRE_XID))
785 {
786 cp += 5;
787 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
788 pointer_bits = (pointer_bits | VTK_PARSE_CONST_POINTER);
789 }
790 else
791 {
792 pointer_bits = (pointer_bits | VTK_PARSE_POINTER);
793 }
794 pointer_bits = (pointer_bits & VTK_PARSE_POINTER_MASK);
795 }
796
797 /* look for ref */
798 if (*cp == '&')
799 {
800 cp++;
801 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
802 ref_bits = VTK_PARSE_REF;
803 }
804
805 /* look for the variable name */
806 if (vtkParse_CharType(*cp, CPRE_ID))
807 {
808 /* skip all chars that are part of a name */
809 n = vtkParse_SkipId(cp);
810 data->Name = vtkParse_CacheString(cache, cp, n);
811 cp += n;
812 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
813 }
814
815 /* look for array brackets */
816 /* (should also look for parenthesized parameter list, for func types) */
817 if (*cp == '[')
818 {
819 count = 1;
820
821 while (*cp == '[')
822 {
823 n = vtkparse_bracket_len(cp);
824 if (n > 1)
825 {
826 cp++;
827 n -= 2;
828 }
829 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; n--; }
830 while (n > 0 && vtkParse_CharType(cp[n-1], CPRE_HSPACE)) { n--; }
831 vtkParse_AddStringToArray(
832 &data->Dimensions,
833 &data->NumberOfDimensions,
834 vtkParse_CacheString(cache, cp, n));
835 m = 0;
836 if (vtkParse_CharType(*cp, CPRE_DIGIT) &&
837 vtkParse_SkipNumber(cp) == n)
838 {
839 m = (int)strtol(cp, NULL, 0);
840 }
841 count *= m;
842
843 cp += n;
844 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
845 if (*cp == ']') { cp++; }
846 while (vtkParse_CharType(*cp, CPRE_HSPACE)) { cp++; }
847 }
848 }
849
850 /* add pointer indirection to correspond to first array dimension */
851 if (data->NumberOfDimensions > 1)
852 {
853 pointer_bits = ((pointer_bits << 2) | VTK_PARSE_ARRAY);
854 }
855 else if (data->NumberOfDimensions == 1)
856 {
857 pointer_bits = ((pointer_bits << 2) | VTK_PARSE_POINTER);
858 }
859 pointer_bits = (pointer_bits & VTK_PARSE_POINTER_MASK);
860
861 /* (Add code here to look for "=" followed by a value ) */
862
863 data->Type = (pointer_bits | ref_bits | base_bits);
864
865 return (cp - text);
866 }
867
868 /* Generate a C++ declaration string from a ValueInfo struct */
vtkParse_ValueInfoToString(ValueInfo * data,char * text,unsigned int flags)869 size_t vtkParse_ValueInfoToString(
870 ValueInfo *data, char *text, unsigned int flags)
871 {
872 unsigned int pointer_bits = (data->Type & VTK_PARSE_POINTER_MASK);
873 unsigned int ref_bits = (data->Type & (VTK_PARSE_REF | VTK_PARSE_RVALUE));
874 unsigned int qualifier_bits = (data->Type & VTK_PARSE_CONST);
875 unsigned int reverse_bits = 0;
876 unsigned int pointer_type = 0;
877 const char *tpname = data->Class;
878 int dimensions = data->NumberOfDimensions;
879 int pointer_dimensions = 0;
880 size_t i = 0;
881 int j = 0;
882
883 /* check if this is a type parameter for a template */
884 if (!tpname)
885 {
886 tpname = "class";
887 }
888
889 /* don't shown anything that isn't in the flags */
890 ref_bits &= flags;
891 qualifier_bits &= flags;
892
893 /* if this is to be a return value, [] becomes * */
894 if ((flags & VTK_PARSE_ARRAY) == 0 &&
895 pointer_bits == VTK_PARSE_POINTER)
896 {
897 if (dimensions == 1)
898 {
899 dimensions = 0;
900 }
901 }
902
903 if (!data->Function && (qualifier_bits & VTK_PARSE_CONST) != 0)
904 {
905 if (text)
906 {
907 strcpy(&text[i], "const ");
908 }
909 i += 6;
910 }
911
912 if (data->Function)
913 {
914 if (text)
915 {
916 i += vtkParse_FunctionInfoToString(
917 data->Function, &text[i], VTK_PARSE_RETURN_VALUE);
918 text[i++] = '(';
919 if (data->Function->Class)
920 {
921 strcpy(&text[i], data->Function->Class);
922 i += strlen(data->Function->Class);
923 text[i++] = ':';
924 text[i++] = ':';
925 }
926 }
927 else
928 {
929 i += vtkParse_FunctionInfoToString(
930 data->Function, NULL, VTK_PARSE_RETURN_VALUE);
931 i += 1;
932 if (data->Function->Class)
933 {
934 i += strlen(data->Function->Class);
935 i += 2;
936 }
937 }
938 }
939 else
940 {
941 if (text)
942 {
943 strcpy(&text[i], tpname);
944 }
945 i += strlen(tpname);
946 if (text)
947 {
948 text[i] = ' ';
949 }
950 i++;
951 }
952
953 while (pointer_bits != 0)
954 {
955 reverse_bits <<= 2;
956 reverse_bits |= (pointer_bits & VTK_PARSE_POINTER_LOWMASK);
957 pointer_bits = ((pointer_bits >> 2) & VTK_PARSE_POINTER_MASK);
958 }
959
960 while (reverse_bits != 0)
961 {
962 pointer_type = (reverse_bits & VTK_PARSE_POINTER_LOWMASK);
963 if (pointer_type == VTK_PARSE_ARRAY ||
964 (reverse_bits == VTK_PARSE_POINTER && dimensions > 0))
965 {
966 if ((flags & VTK_PARSE_ARRAY) == 0)
967 {
968 pointer_dimensions = 1;
969 if (text)
970 {
971 text[i] = '(';
972 text[i+1] = '*';
973 }
974 i += 2;
975 }
976 break;
977 }
978 else if (pointer_type == VTK_PARSE_POINTER)
979 {
980 if (text)
981 {
982 text[i] = '*';
983 }
984 i++;
985 }
986 else if (pointer_type == VTK_PARSE_CONST_POINTER)
987 {
988 if (text)
989 {
990 strcpy(&text[i], "*const ");
991 }
992 i += 7;
993 }
994
995 reverse_bits = ((reverse_bits >> 2) & VTK_PARSE_POINTER_MASK);
996 }
997
998 if ((ref_bits & VTK_PARSE_REF) != 0)
999 {
1000 if ((ref_bits & VTK_PARSE_RVALUE) != 0)
1001 {
1002 if (text)
1003 {
1004 text[i] = '&';
1005 }
1006 i++;
1007 }
1008 if (text)
1009 {
1010 text[i] = '&';
1011 }
1012 i++;
1013 }
1014
1015 if (data->Name && (flags & VTK_PARSE_NAMES) != 0)
1016 {
1017 if (text)
1018 {
1019 strcpy(&text[i], data->Name);
1020 }
1021 i += strlen(data->Name);
1022 if (data->Value && (flags & VTK_PARSE_VALUES) != 0)
1023 {
1024 if (text)
1025 {
1026 text[i] = '=';
1027 }
1028 i++;
1029 if (text)
1030 {
1031 strcpy(&text[i], data->Value);
1032 }
1033 i += strlen(data->Value);
1034 }
1035 }
1036
1037 for (j = 0; j < pointer_dimensions; j++)
1038 {
1039 if (text)
1040 {
1041 text[i] = ')';
1042 }
1043 i++;
1044 }
1045
1046 for (j = pointer_dimensions; j < dimensions; j++)
1047 {
1048 if (text)
1049 {
1050 text[i] = '[';
1051 }
1052 i++;
1053 if (data->Dimensions[j])
1054 {
1055 if (text)
1056 {
1057 strcpy(&text[i], data->Dimensions[j]);
1058 }
1059 i += strlen(data->Dimensions[j]);
1060 }
1061 if (text)
1062 {
1063 text[i] = ']';
1064 }
1065 i++;
1066 }
1067
1068 if (data->Function)
1069 {
1070 if (text)
1071 {
1072 text[i++] = ')';
1073 i += vtkParse_FunctionInfoToString(
1074 data->Function, &text[i],
1075 VTK_PARSE_CONST | VTK_PARSE_PARAMETER_LIST);
1076 }
1077 else
1078 {
1079 i++;
1080 i += vtkParse_FunctionInfoToString(
1081 data->Function, NULL,
1082 VTK_PARSE_CONST | VTK_PARSE_PARAMETER_LIST);
1083 }
1084 }
1085
1086 if (text)
1087 {
1088 text[i] = '\0';
1089 }
1090
1091 return i;
1092 }
1093
1094 /* Generate a template declaration string */
vtkParse_TemplateInfoToString(TemplateInfo * data,char * text,unsigned int flags)1095 size_t vtkParse_TemplateInfoToString(
1096 TemplateInfo *data, char *text, unsigned int flags)
1097 {
1098 int i;
1099 size_t k = 0;
1100
1101 if (text)
1102 {
1103 strcpy(&text[k], "template<");
1104 }
1105 k += 9;
1106 for (i = 0; i < data->NumberOfParameters; i++)
1107 {
1108 if (i != 0)
1109 {
1110 if (text)
1111 {
1112 text[k] = ',';
1113 text[k+1] = ' ';
1114 }
1115 k += 2;
1116 }
1117 if (text)
1118 {
1119 k += vtkParse_ValueInfoToString(data->Parameters[i], &text[k], flags);
1120 while (k > 0 && text[k-1] == ' ')
1121 {
1122 k--;
1123 }
1124 }
1125 else
1126 {
1127 k += vtkParse_ValueInfoToString(data->Parameters[i], NULL, flags);
1128 }
1129 }
1130 if (text)
1131 {
1132 text[k] = '>';
1133 text[k+1] = '\0';
1134 }
1135 k++;
1136
1137 return k;
1138 }
1139
1140 /* generate a function signature for a FunctionInfo struct */
vtkParse_FunctionInfoToString(FunctionInfo * func,char * text,unsigned int flags)1141 size_t vtkParse_FunctionInfoToString(
1142 FunctionInfo *func, char *text, unsigned int flags)
1143 {
1144 int i;
1145 size_t k = 0;
1146
1147 if (func->Template && (flags & VTK_PARSE_TEMPLATES) != 0)
1148 {
1149 if (text)
1150 {
1151 k += vtkParse_TemplateInfoToString(func->Template, &text[k], flags);
1152 text[k++] = ' ';
1153 }
1154 else
1155 {
1156 k += vtkParse_TemplateInfoToString(func->Template, NULL, flags);
1157 k++;
1158 }
1159 }
1160
1161 if (func->IsStatic && (flags & VTK_PARSE_STATIC) != 0)
1162 {
1163 if (text)
1164 {
1165 strcpy(&text[k], "static ");
1166 }
1167 k += 7;
1168 }
1169 if (func->IsVirtual && (flags & VTK_PARSE_VIRTUAL) != 0)
1170 {
1171 if (text)
1172 {
1173 strcpy(&text[k], "virtual ");
1174 }
1175 k += 8;
1176 }
1177 if (func->IsExplicit && (flags & VTK_PARSE_EXPLICIT) != 0)
1178 {
1179 if (text)
1180 {
1181 strcpy(&text[k], "explicit ");
1182 }
1183 k += 9;
1184 }
1185
1186 if (func->ReturnValue && (flags & VTK_PARSE_RETURN_VALUE) != 0)
1187 {
1188 if (text)
1189 {
1190 k += vtkParse_ValueInfoToString(
1191 func->ReturnValue, &text[k],
1192 VTK_PARSE_EVERYTHING ^ (VTK_PARSE_ARRAY | VTK_PARSE_NAMES));
1193 }
1194 else
1195 {
1196 k += vtkParse_ValueInfoToString(
1197 func->ReturnValue, NULL,
1198 VTK_PARSE_EVERYTHING ^ (VTK_PARSE_ARRAY | VTK_PARSE_NAMES));
1199 }
1200 }
1201
1202 if ((flags & VTK_PARSE_RETURN_VALUE) != 0 &&
1203 (flags & VTK_PARSE_PARAMETER_LIST) != 0)
1204 {
1205 if (func->Name)
1206 {
1207 if (text)
1208 {
1209 strcpy(&text[k], func->Name);
1210 }
1211 k += strlen(func->Name);
1212 }
1213 else
1214 {
1215 if (text)
1216 {
1217 text[k++] = '(';
1218 if (func->Class)
1219 {
1220 strcpy(&text[k], func->Class);
1221 k += strlen(func->Class);
1222 text[k++] = ':';
1223 text[k++] = ':';
1224 }
1225 text[k++] = '*';
1226 text[k++] = ')';
1227 }
1228 else
1229 {
1230 k++;
1231 if (func->Class)
1232 {
1233 k += strlen(func->Class);
1234 k += 2;
1235 }
1236 k += 2;
1237 }
1238 }
1239 }
1240 if ((flags & VTK_PARSE_PARAMETER_LIST) != 0)
1241 {
1242 if (text)
1243 {
1244 text[k] = '(';
1245 }
1246 k++;
1247 for (i = 0; i < func->NumberOfParameters; i++)
1248 {
1249 if (i != 0)
1250 {
1251 if (text)
1252 {
1253 text[k] = ',';
1254 text[k+1] = ' ';
1255 }
1256 k += 2;
1257 }
1258 if (text)
1259 {
1260 k += vtkParse_ValueInfoToString(
1261 func->Parameters[i], &text[k],
1262 (VTK_PARSE_EVERYTHING ^ (VTK_PARSE_NAMES | VTK_PARSE_VALUES)) |
1263 (flags & (VTK_PARSE_NAMES | VTK_PARSE_VALUES)));
1264 while (k > 0 && text[k-1] == ' ')
1265 {
1266 k--;
1267 }
1268 }
1269 else
1270 {
1271 k += vtkParse_ValueInfoToString(
1272 func->Parameters[i], NULL,
1273 (VTK_PARSE_EVERYTHING ^ (VTK_PARSE_NAMES | VTK_PARSE_VALUES)) |
1274 (flags & (VTK_PARSE_NAMES | VTK_PARSE_VALUES)));
1275 }
1276 }
1277 if (text)
1278 {
1279 text[k] = ')';
1280 }
1281 k++;
1282 }
1283 if (func->IsConst && (flags & VTK_PARSE_CONST) != 0)
1284 {
1285 if (text)
1286 {
1287 strcpy(&text[k], " const");
1288 }
1289 k += 6;
1290 }
1291 if (func->IsFinal && (flags & VTK_PARSE_TRAILERS) != 0)
1292 {
1293 if (text)
1294 {
1295 strcpy(&text[k], " final");
1296 }
1297 k += 6;
1298 }
1299 if (func->IsPureVirtual && (flags & VTK_PARSE_TRAILERS) != 0)
1300 {
1301 if (text)
1302 {
1303 strcpy(&text[k], " = 0");
1304 }
1305 k += 4;
1306 }
1307 if (text)
1308 {
1309 text[k] = '\0';
1310 }
1311
1312 return k;
1313 }
1314
1315 /* compare two types to see if they are equivalent */
override_compatible(unsigned int t1,unsigned int t2)1316 static int override_compatible(unsigned int t1, unsigned int t2)
1317 {
1318 /* const and virtual qualifiers are part of the type for the
1319 sake of method resolution, but only if the type is a pointer
1320 or reference */
1321 unsigned int typebits = (VTK_PARSE_UNQUALIFIED_TYPE |
1322 VTK_PARSE_CONST |
1323 VTK_PARSE_VOLATILE |
1324 VTK_PARSE_RVALUE);
1325 unsigned int diff = (t1 ^ t2) & typebits;
1326 return (diff == 0 ||
1327 ((t1 & VTK_PARSE_INDIRECT) == 0 &&
1328 (diff & VTK_PARSE_UNQUALIFIED_TYPE) == 0));
1329 }
1330
1331 /* Compare two functions */
vtkParse_CompareFunctionSignature(const FunctionInfo * func1,const FunctionInfo * func2)1332 int vtkParse_CompareFunctionSignature(
1333 const FunctionInfo *func1, const FunctionInfo *func2)
1334 {
1335 ValueInfo *p1;
1336 ValueInfo *p2;
1337 int j;
1338 int k;
1339 int match = 0;
1340
1341 /* uninstantiated templates cannot be compared */
1342 if (func1->Template || func2->Template)
1343 {
1344 return 0;
1345 }
1346
1347 /* check the parameters */
1348 if (func2->NumberOfParameters == func1->NumberOfParameters)
1349 {
1350 for (k = 0; k < func2->NumberOfParameters; k++)
1351 {
1352 p1 = func1->Parameters[k];
1353 p2 = func2->Parameters[k];
1354 if (!override_compatible(p2->Type, p1->Type) ||
1355 strcmp(p2->Class, p1->Class) != 0)
1356 {
1357 break;
1358 }
1359 if (p1->Function && p2->Function)
1360 {
1361 if (vtkParse_CompareFunctionSignature(p1->Function, p2->Function) < 7)
1362 {
1363 break;
1364 }
1365 }
1366 if (p1->NumberOfDimensions > 1 || p2->NumberOfDimensions > 1)
1367 {
1368 if (p1->NumberOfDimensions != p2->NumberOfDimensions)
1369 {
1370 break;
1371 }
1372 for (j = 1; j < p1->NumberOfDimensions; j++)
1373 {
1374 if (strcmp(p1->Dimensions[j], p2->Dimensions[j]) != 0)
1375 {
1376 break;
1377 }
1378 }
1379 }
1380 }
1381 if (k == func2->NumberOfParameters)
1382 {
1383 match = 1;
1384 }
1385 }
1386
1387 /* check the return value */
1388 if (match && func1->ReturnValue && func2->ReturnValue)
1389 {
1390 p1 = func1->ReturnValue;
1391 p2 = func2->ReturnValue;
1392 if (override_compatible(p2->Type, p1->Type) &&
1393 strcmp(p2->Class, p1->Class) == 0)
1394 {
1395 if (p1->Function && p2->Function)
1396 {
1397 if (vtkParse_CompareFunctionSignature(p1->Function, p2->Function) < 7)
1398 {
1399 match |= 2;
1400 }
1401 }
1402 else
1403 {
1404 match |= 2;
1405 }
1406 }
1407 }
1408
1409 /* check the class */
1410 if (match &&
1411 func1->Class && func2->Class && strcmp(func1->Class, func2->Class) == 0)
1412 {
1413 if (func1->IsConst == func2->IsConst)
1414 {
1415 match |= 4;
1416 }
1417 }
1418
1419 return match;
1420 }
1421
1422 /* Search and replace, return the initial string if no replacements
1423 * occurred, otherwise return a new string allocated with malloc. */
vtkParse_StringReplace(const char * str1,int n,const char * name[],const char * val[])1424 const char *vtkParse_StringReplace(
1425 const char *str1, int n, const char *name[], const char *val[])
1426 {
1427 return vtkparse_string_replace(NULL, str1, n, name, val);
1428 }
1429
1430 /* substitute generic types and values with actual types and values */
1431 static void func_substitution(
1432 FunctionInfo *data, StringCache *cache,
1433 int m, const char *arg_names[],
1434 const char *arg_values[], ValueInfo *arg_types[]);
1435
value_substitution(ValueInfo * data,StringCache * cache,int m,const char * arg_names[],const char * arg_values[],ValueInfo * arg_types[])1436 static void value_substitution(
1437 ValueInfo *data, StringCache *cache,
1438 int m, const char *arg_names[],
1439 const char *arg_values[], ValueInfo *arg_types[])
1440 {
1441 vtkParse_ExpandTypedefs(data, cache, m, arg_names, arg_values, arg_types);
1442 vtkParse_ExpandValues(data, cache, m, arg_names, arg_values);
1443
1444 if (data->Function)
1445 {
1446 func_substitution(
1447 data->Function, cache, m, arg_names, arg_values, arg_types);
1448 }
1449 }
1450
func_substitution(FunctionInfo * data,StringCache * cache,int m,const char * arg_names[],const char * arg_values[],ValueInfo * arg_types[])1451 static void func_substitution(
1452 FunctionInfo *data, StringCache *cache,
1453 int m, const char *arg_names[],
1454 const char *arg_values[], ValueInfo *arg_types[])
1455 {
1456 int i, n;
1457
1458 n = data->NumberOfParameters;
1459 for (i = 0; i < n; i++)
1460 {
1461 value_substitution(
1462 data->Parameters[i], cache, m, arg_names, arg_values, arg_types);
1463 }
1464
1465 if (data->ReturnValue)
1466 {
1467 value_substitution(
1468 data->ReturnValue, cache, m, arg_names, arg_values, arg_types);
1469 }
1470
1471 if (data->Signature)
1472 {
1473 data->Signature =
1474 vtkparse_string_replace(
1475 cache, data->Signature, m, arg_names, arg_values);
1476 }
1477
1478 /* legacy information for old wrappers */
1479 #ifndef VTK_PARSE_LEGACY_REMOVE
1480 n = data->NumberOfArguments;
1481 for (i = 0; i < n; i++)
1482 {
1483 data->ArgTypes[i] = data->Parameters[i]->Type;
1484 data->ArgClasses[i] = data->Parameters[i]->Class;
1485 if (data->Parameters[i]->NumberOfDimensions == 1 &&
1486 data->Parameters[i]->Count > 0)
1487 {
1488 data->ArgCounts[i] = data->Parameters[i]->Count;
1489 }
1490 }
1491
1492 if (data->ReturnValue)
1493 {
1494 data->ReturnType = data->ReturnValue->Type;
1495 data->ReturnClass = data->ReturnValue->Class;
1496 if (data->ReturnValue->NumberOfDimensions == 1 &&
1497 data->ReturnValue->Count > 0)
1498 {
1499 data->HintSize = data->ReturnValue->Count;
1500 data->HaveHint = 1;
1501 }
1502 }
1503 #endif /* VTK_PARSE_LEGACY_REMOVE */
1504 }
1505
class_substitution(ClassInfo * data,StringCache * cache,int m,const char * arg_names[],const char * arg_values[],ValueInfo * arg_types[])1506 static void class_substitution(
1507 ClassInfo *data, StringCache *cache,
1508 int m, const char *arg_names[],
1509 const char *arg_values[], ValueInfo *arg_types[])
1510 {
1511 int i, n;
1512
1513 /* superclasses may be templated */
1514 n = data->NumberOfSuperClasses;
1515 for (i = 0; i < n; i++)
1516 {
1517 data->SuperClasses[i] = vtkparse_string_replace(
1518 cache, data->SuperClasses[i], m, arg_names, arg_values);
1519 }
1520
1521 n = data->NumberOfClasses;
1522 for (i = 0; i < n; i++)
1523 {
1524 class_substitution(
1525 data->Classes[i], cache, m, arg_names, arg_values, arg_types);
1526 }
1527
1528 n = data->NumberOfFunctions;
1529 for (i = 0; i < n; i++)
1530 {
1531 func_substitution(
1532 data->Functions[i], cache, m, arg_names, arg_values, arg_types);
1533 }
1534
1535 n = data->NumberOfConstants;
1536 for (i = 0; i < n; i++)
1537 {
1538 value_substitution(
1539 data->Constants[i], cache, m, arg_names, arg_values, arg_types);
1540 }
1541
1542 n = data->NumberOfVariables;
1543 for (i = 0; i < n; i++)
1544 {
1545 value_substitution(
1546 data->Variables[i], cache, m, arg_names, arg_values, arg_types);
1547 }
1548
1549 n = data->NumberOfTypedefs;
1550 for (i = 0; i < n; i++)
1551 {
1552 value_substitution(
1553 data->Typedefs[i], cache, m, arg_names, arg_values, arg_types);
1554 }
1555 }
1556
1557 /* Extract template args from a comma-separated list enclosed
1558 * 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[])1559 size_t vtkParse_DecomposeTemplatedType(
1560 const char *text, const char **classname,
1561 int nargs, const char ***argp, const char *defaults[])
1562 {
1563 size_t i, j, k, n;
1564 const char *arg;
1565 char *new_text;
1566 const char **template_args = NULL;
1567 int template_arg_count = 0;
1568
1569 n = vtkParse_NameLength(text);
1570
1571 /* is the class templated? */
1572 for (i = 0; i < n; i++)
1573 {
1574 if (text[i] == '<')
1575 {
1576 break;
1577 }
1578 }
1579
1580 if (classname)
1581 {
1582 new_text = (char *)malloc(i + 1);
1583 strncpy(new_text, text, i);
1584 new_text[i] = '\0';
1585 *classname = new_text;
1586 }
1587
1588 if (text[i] == '<')
1589 {
1590 i++;
1591 /* extract the template arguments */
1592 for (;;)
1593 {
1594 while (vtkParse_CharType(text[i], CPRE_HSPACE)) { i++; }
1595 j = i;
1596 while (text[j] != ',' && text[j] != '>' &&
1597 text[j] != '\n' && text[j] != '\0')
1598 {
1599 if (text[j] == '<' || text[j] == '(' ||
1600 text[j] == '[' || text[j] == '{')
1601 {
1602 j += vtkparse_bracket_len(&text[j]);
1603 }
1604 else if (vtkParse_CharType(text[j], CPRE_QUOTE))
1605 {
1606 j += vtkParse_SkipQuotes(&text[j]);
1607 }
1608 else
1609 {
1610 j++;
1611 }
1612 }
1613
1614 k = j;
1615 while (vtkParse_CharType(text[k-1], CPRE_HSPACE)) { --k; }
1616
1617 new_text = (char *)malloc(k-i + 1);
1618 strncpy(new_text, &text[i], k-i);
1619 new_text[k-i] = '\0';
1620 vtkParse_AddStringToArray(&template_args, &template_arg_count,
1621 new_text);
1622
1623 assert(template_arg_count <= nargs);
1624
1625 i = j + 1;
1626
1627 if (text[j] != ',')
1628 {
1629 break;
1630 }
1631 }
1632 }
1633
1634 while (template_arg_count < nargs)
1635 {
1636 assert(defaults != NULL);
1637 arg = defaults[template_arg_count];
1638 assert(arg != NULL);
1639 new_text = (char *)malloc(strlen(arg) + 1);
1640 strcpy(new_text, arg);
1641 vtkParse_AddStringToArray(&template_args, &template_arg_count, new_text);
1642 }
1643
1644 *argp = template_args;
1645
1646 return i;
1647 }
1648
1649 /* Free the list of strings returned by ExtractTemplateArgs. */
vtkParse_FreeTemplateDecomposition(const char * name,int n,const char ** args)1650 void vtkParse_FreeTemplateDecomposition(
1651 const char *name, int n, const char **args)
1652 {
1653 int i;
1654
1655 if (name)
1656 {
1657 free((char *)name);
1658 }
1659
1660 if (n > 0)
1661 {
1662 for (i = 0; i < n; i++)
1663 {
1664 free((char *)args[i]);
1665 }
1666
1667 free((char **)args);
1668 }
1669 }
1670
1671 /* Instantiate a class template by substituting the provided arguments. */
vtkParse_InstantiateClassTemplate(ClassInfo * data,StringCache * cache,int n,const char * args[])1672 void vtkParse_InstantiateClassTemplate(
1673 ClassInfo *data, StringCache *cache, int n, const char *args[])
1674 {
1675 TemplateInfo *t = data->Template;
1676 const char **new_args = NULL;
1677 const char **arg_names = NULL;
1678 ValueInfo **arg_types = NULL;
1679 int i, m;
1680 char *new_name;
1681 size_t k;
1682
1683 if (t == NULL)
1684 {
1685 fprintf(stderr, "vtkParse_InstantiateClassTemplate: "
1686 "this class is not templated.\n");
1687 return;
1688 }
1689
1690 m = t->NumberOfParameters;
1691 if (n > m)
1692 {
1693 fprintf(stderr, "vtkParse_InstantiateClassTemplate: "
1694 "too many template args.\n");
1695 return;
1696 }
1697
1698 for (i = n; i < m; i++)
1699 {
1700 if (t->Parameters[i]->Value == NULL ||
1701 t->Parameters[i]->Value[0] == '\0')
1702 {
1703 fprintf(stderr, "vtkParse_InstantiateClassTemplate: "
1704 "too few template args.\n");
1705 return;
1706 }
1707 }
1708
1709 new_args = (const char **)malloc(m*sizeof(char **));
1710 for (i = 0; i < n; i++)
1711 {
1712 new_args[i] = args[i];
1713 }
1714 for (i = n; i < m; i++)
1715 {
1716 new_args[i] = t->Parameters[i]->Value;
1717 }
1718 args = new_args;
1719
1720 arg_names = (const char **)malloc(m*sizeof(char **));
1721 arg_types = (ValueInfo **)malloc(m*sizeof(ValueInfo *));
1722 for (i = 0; i < m; i++)
1723 {
1724 arg_names[i] = t->Parameters[i]->Name;
1725 arg_types[i] = NULL;
1726 if (t->Parameters[i]->Type == 0)
1727 {
1728 arg_types[i] = (ValueInfo *)malloc(sizeof(ValueInfo));
1729 vtkParse_InitValue(arg_types[i]);
1730 vtkParse_ValueInfoFromString(arg_types[i], cache, args[i]);
1731 arg_types[i]->ItemType = VTK_TYPEDEF_INFO;
1732 arg_types[i]->Name = arg_names[i];
1733 }
1734 }
1735
1736 /* no longer a template (has been instantiated) */
1737 if (data->Template)
1738 {
1739 vtkParse_FreeTemplate(data->Template);
1740 }
1741 data->Template = NULL;
1742
1743 /* append template args to class name */
1744 k = strlen(data->Name) + 2;
1745 for (i = 0; i < m; i++)
1746 {
1747 k += strlen(args[i]) + 2;
1748 }
1749 new_name = (char *)malloc(k);
1750 strcpy(new_name, data->Name);
1751 k = strlen(new_name);
1752 new_name[k++] = '<';
1753 for (i = 0; i < m; i++)
1754 {
1755 strcpy(&new_name[k], args[i]);
1756 k += strlen(args[i]);
1757 if (i+1 < m)
1758 {
1759 new_name[k++] = ',';
1760 new_name[k++] = ' ';
1761 }
1762 }
1763 if (new_name[k-1] == '>')
1764 {
1765 new_name[k++] = ' ';
1766 }
1767 new_name[k++] = '>';
1768 new_name[k] = '\0';
1769
1770 data->Name = vtkParse_CacheString(cache, new_name, k);
1771 free(new_name);
1772
1773 /* do the template arg substitution */
1774 class_substitution(data, cache, m, arg_names, args, arg_types);
1775
1776 /* free all allocated arrays */
1777 free((char **)new_args);
1778 free((char **)arg_names);
1779
1780 for (i = 0; i < m; i++)
1781 {
1782 if (arg_types[i])
1783 {
1784 vtkParse_FreeValue(arg_types[i]);
1785 }
1786 }
1787 free(arg_types);
1788 }
1789
1790 /* Get a zero-terminated array of the types in vtkTemplateMacro. */
vtkParse_GetTemplateMacroTypes(void)1791 const char **vtkParse_GetTemplateMacroTypes(void)
1792 {
1793 static const char *types[] = {
1794 "char", "signed char", "unsigned char", "short", "unsigned short",
1795 "int", "unsigned int", "long", "unsigned long",
1796 "long long", "unsigned long long",
1797 "float", "double", NULL };
1798
1799 return types;
1800 }
1801
1802 /* Get a zero-terminated array of the types in vtkArray. */
vtkParse_GetArrayTypes(void)1803 const char **vtkParse_GetArrayTypes(void)
1804 {
1805 static const char *types[] = {
1806 "char", "signed char", "unsigned char", "short", "unsigned short",
1807 "int", "unsigned int", "long", "unsigned long",
1808 "long long", "unsigned long long",
1809 "float", "double",
1810 "vtkStdString", "vtkUnicodeString", "vtkVariant", NULL };
1811
1812 return types;
1813 }
1814