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