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