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