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