Salome HOME
Merge from V6_main 11/02/2013
[modules/paravis.git] / src / ParaView / vtkParseHierarchy.c
1 /*=========================================================================
2
3   Program:   Visualization Toolkit
4   Module:    vtkParseHierarchy.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) 2010 David Gobbi.
17
18   Contributed to the VisualizationToolkit by the author in June 2010
19   under the terms of the Visualization Toolkit 2008 copyright.
20 -------------------------------------------------------------------------*/
21
22 #include "vtkParseHierarchy.h"
23 #include "vtkParseInternal.h"
24 #include "vtkParseExtras.h"
25 #include "vtkType.h"
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <assert.h>
31
32 static size_t skip_space(const char *text)
33 {
34   size_t i = 0;
35   while (isspace(text[i]) && text[i] != '\n') { i++; }
36   return i;
37 }
38
39 /* helper: comparison of entries */
40 static int compare_hierarchy_entries(const void *vp1, const void *vp2)
41 {
42   const HierarchyEntry *entry1 = (const HierarchyEntry *)vp1;
43   const HierarchyEntry *entry2 = (const HierarchyEntry *)vp2;
44
45   return strcmp(entry1->Name, entry2->Name);
46 }
47
48 /* helper: sort the entries to facilitate searching */
49 static void sort_hierarchy_entries(HierarchyInfo *info)
50 {
51   qsort(info->Entries, info->NumberOfEntries, sizeof(HierarchyEntry),
52         &compare_hierarchy_entries);
53 }
54
55 /* Find an entry with a binary search */
56 HierarchyEntry *vtkParseHierarchy_FindEntry(
57   const HierarchyInfo *info, const char *classname)
58 {
59   HierarchyEntry key;
60   HierarchyEntry *entry;
61   size_t i, n;
62   char name[32];
63   char *cp;
64
65   /* use classname as-is for the search if possible */
66   cp = (char *)classname;
67
68   /* get portion of name before final template parameters */
69   n = vtkParse_UnscopedNameLength(classname);
70   i = 0;
71   while (classname[i+n] == ':' && classname[i+n+1] == ':')
72     {
73     i += n + 2;
74     n = vtkParse_UnscopedNameLength(&classname[i]);
75     }
76   i += vtkParse_IdentifierLength(&classname[i]);
77       
78   /* create a new (shorter) search string if necessary */
79   if (classname[i] != '\0')
80     {
81     /* use stack space if possible */
82     cp = name;
83     /* otherwise, use malloc */
84     if (i > 31)
85       {
86       cp = (char *)malloc(i+1);
87       }
88     strncpy(cp, classname, i);
89     cp[i] = '\0';
90     }
91
92   key.Name = cp;
93
94   entry = (HierarchyEntry *)bsearch(&key, info->Entries,
95     info->NumberOfEntries, sizeof(HierarchyEntry),
96     &compare_hierarchy_entries);
97
98   if (cp != classname && cp != name)
99     {
100     free(cp);
101     }
102
103   return entry;
104 }
105
106
107 /* read a hierarchy file into a HeirarchyInfo struct, or return NULL */
108 HierarchyInfo *vtkParseHierarchy_ReadFile(const char *filename)
109 {
110   HierarchyInfo *info;
111   HierarchyEntry *entry;
112   int maxClasses = 500;
113   FILE *fp;
114   char *line;
115   char *cp;
116   const char *ccp;
117   size_t maxlen = 15;
118   size_t i, j, n, m;
119   unsigned int bits, pointers;
120
121   line = (char *)malloc(maxlen);
122
123   fp = fopen(filename, "r");
124
125   if (fp == NULL)
126     {
127     return NULL;
128     }
129
130   info = (HierarchyInfo *)malloc(sizeof(HierarchyInfo));
131   info->NumberOfEntries = 0;
132   info->Entries = (HierarchyEntry *)malloc(maxClasses*sizeof(HierarchyEntry));
133
134   while (fgets(line, (int)maxlen, fp))
135     {
136     n = strlen(line);
137
138     /* if buffer not long enough, increase it */
139     while (n == maxlen-1 && line[n-1] != '\n' && !feof(fp))
140       {
141       maxlen *= 2;
142       line = (char *)realloc(line, maxlen);
143       if (!fgets(&line[n], (int)(maxlen-n), fp)) { break; }
144       n += strlen(&line[n]);
145       }
146
147     while (n > 0 && isspace(line[n-1]))
148       {
149       n--;
150       }
151     line[n] = '\0';
152
153     if (line[0] == '\0')
154       {
155       continue;
156       }
157
158     if (info->NumberOfEntries == maxClasses)
159       {
160       maxClasses *= 2;
161       info->Entries = (HierarchyEntry *)realloc(
162         info->Entries, sizeof(HierarchyEntry)*maxClasses*2);
163       }
164
165     entry = &info->Entries[info->NumberOfEntries++];
166     entry->Name = NULL;
167     entry->HeaderFile = NULL;
168     entry->Module = NULL;
169     entry->NumberOfTemplateArgs = 0;
170     entry->TemplateArgs = NULL;
171     entry->TemplateArgDefaults = NULL;
172     entry->NumberOfProperties = 0;
173     entry->Properties = NULL;
174     entry->NumberOfSuperClasses = 0;
175     entry->SuperClasses = NULL;
176     entry->SuperClassIndex = NULL;
177     entry->Typedef = NULL;
178     entry->IsTypedef = 0;
179     entry->IsEnum = 0;
180
181     i = skip_space(line);
182     n = vtkParse_NameLength(&line[i]);
183     for (m = 0; m < n; m++)
184       {
185       if (line[i+m] == '<') { break; }
186       }
187
188     cp = (char *)malloc(m+1);
189     strncpy(cp, &line[i], m);
190     cp[m] = '\0';
191     entry->Name = cp;
192     i += m;
193
194     if (line[i] == '<')
195       {
196       i++;
197       i += skip_space(&line[i]);
198
199       for (j = 0; line[i] != '>' && line[i] != '\0'; j++)
200         {
201         if (j == 0)
202           {
203           entry->TemplateArgs = (const char **)malloc(sizeof(char *));
204           entry->TemplateArgDefaults = (const char **)malloc(sizeof(char *));
205           }
206         else
207           {
208           entry->TemplateArgs = (const char **)realloc(
209             (char **)entry->TemplateArgs, (j+1)*sizeof(char *));
210           entry->TemplateArgDefaults = (const char **)realloc(
211             (char **)entry->TemplateArgDefaults, (j+1)*sizeof(char *));
212           }
213         entry->NumberOfTemplateArgs++;
214         entry->TemplateArgDefaults[j] = NULL;
215
216         m = vtkParse_NameLength(&line[i]);
217
218         cp = (char *)malloc(m+1);
219         strncpy(cp, &line[i], m);
220         cp[m] = '\0';
221         entry->TemplateArgs[j] = cp;
222         i += m;
223         i += skip_space(&line[i]);
224
225         if (line[i] == '=')
226           {
227           i++;
228           i += skip_space(&line[i]);
229           m = vtkParse_NameLength(&line[i]);
230
231           cp = (char *)malloc(m+1);
232           strncpy(cp, &line[i], m);
233           cp[m] = '\0';
234           entry->TemplateArgDefaults[j] = cp;
235           i += m;
236           i += skip_space(&line[i]);
237           }
238
239         if (line[i] == ',')
240           {
241           i++;
242           i += skip_space(&line[i]);
243           }
244         }
245
246       if (line[i] == '>')
247         {
248         i++;
249         i += skip_space(&line[i]);
250         }
251
252       if (line[i] == ':' && line[i+1] == ':')
253         {
254         i += 2;
255         m = vtkParse_NameLength(&line[i]);
256         n = strlen(entry->Name);
257         cp = (char *)malloc(n+m+3);
258         strcpy(cp, entry->Name);
259         strcpy(&cp[n], "::");
260         strncpy(&cp[n+2], &line[i], m);
261         i += m;
262         cp[n+m+2] = '\0';
263         free((char *)entry->Name);
264         entry->Name = cp;
265         }
266       }
267
268     i += skip_space(&line[i]);
269
270     /* classes (and possibly enums) */
271     if (line[i] == ':')
272       {
273       i++;
274       i += skip_space(&line[i]);
275       n = vtkParse_NameLength(&line[i]);
276       /* check for enum indicators */
277       if ((n == 3 && strncmp(&line[i], "int", n)) ||
278           (n == 4 && strncmp(&line[i], "enum", n)))
279         {
280         entry->IsEnum = 1;
281         i += n;
282         i += skip_space(&line[i]);
283         }
284       /* else check for superclasses */
285       else for (j = 0; ; j++)
286         {
287         if (j == 0)
288           {
289           entry->SuperClasses = (const char **)malloc(sizeof(char *));
290           entry->SuperClassIndex = (int *)malloc(sizeof(int));
291           }
292         else
293           {
294           entry->SuperClasses = (const char **)realloc(
295             (char **)entry->SuperClasses, (j+1)*sizeof(char *));
296           entry->SuperClassIndex = (int *)realloc(
297             entry->SuperClassIndex, (j+1)*sizeof(int));
298           }
299         entry->NumberOfSuperClasses++;
300
301         i += skip_space(&line[i]);
302         n = vtkParse_NameLength(&line[i]);
303         cp = (char *)malloc(n+1);
304         strncpy(cp, &line[i], n);
305         cp[n] = '\0';
306         entry->SuperClasses[j] = cp;
307         entry->SuperClassIndex[j] = -1;
308         i += n;
309
310         i += skip_space(&line[i]);
311         if (line[i] != ',')
312           {
313           break;
314           }
315         i++;
316         }
317       }
318
319     /* read typedefs */
320     else if (line[i] == '=')
321       {
322       i++;
323       i += skip_space(&line[i]);
324       entry->IsTypedef = 1;
325       entry->Typedef = (ValueInfo *)malloc(sizeof(ValueInfo));
326       vtkParse_InitValue(entry->Typedef);
327
328       /* type is a reference (does this ever occur?) */
329       if (line[i] == '&')
330         {
331         i++;
332         i += skip_space(&line[i]);
333         entry->Typedef->Type |= VTK_PARSE_REF;
334         }
335
336       /* type has array dimensions */
337       if (line[i] == '[')
338         {
339         entry->Typedef->Count = 1;
340         }
341
342       while (line[i] == '[')
343         {
344         i++;
345         n = 0;
346         while (line[i+n] != ']' && line[i+n] != '\n' && line[i+n] != '\0')
347           {
348           n++;
349           }
350         ccp = vtkParse_DuplicateString(&line[i], n);
351         vtkParse_AddStringToArray(&entry->Typedef->Dimensions,
352                                   &entry->Typedef->NumberOfDimensions, ccp);
353         if (ccp[0] >= '0' && ccp[0] <= '9')
354           {
355           entry->Typedef->Count *= (int)strtol(ccp, NULL, 0);
356           }
357         else
358           {
359           entry->Typedef->Count = 0;
360           }
361         i += n;
362         if (line[i] == ']')
363           {
364           i++;
365           }
366         }
367       i += skip_space(&line[i]);
368
369       /* look for pointers (and const pointers) */
370       bits = 0;
371       while (line[i] == '*' || strncmp(&line[i], "const*", 6) == 0)
372         {
373         bits = (bits << 2);
374         if (line[i] == '*')
375           {
376           bits = (bits | VTK_PARSE_POINTER);
377           }
378         else
379           {
380           bits = (bits | VTK_PARSE_CONST_POINTER);
381           i += 5;
382           }
383         bits = (bits & VTK_PARSE_POINTER_MASK);
384         i++;
385         i += skip_space(&line[i]);
386         }
387
388       /* need to reverse to get correct pointer order */
389       pointers = 0;
390       while (bits)
391         {
392         pointers = (pointers << 2);
393         pointers = (pointers | (bits & VTK_PARSE_POINTER_LOWMASK));
394         bits = ((bits >> 2) & VTK_PARSE_POINTER_MASK);
395         }
396
397       /* add pointer indirection to correspond to first array dimension */
398       if (entry->Typedef->NumberOfDimensions > 1)
399         {
400         pointers = ((pointers << 2) | VTK_PARSE_ARRAY);
401         }
402       else if (entry->Typedef->NumberOfDimensions == 1)
403         {
404         pointers = ((pointers << 2) | VTK_PARSE_POINTER);
405         }
406
407       /* include the pointers in the type */
408       entry->Typedef->Type |= (pointers & VTK_PARSE_POINTER_MASK);
409
410       /* read the base type (and const) */
411       bits = 0;
412       i += vtkParse_BasicTypeFromString(&line[i], &bits, &ccp, &n);
413       entry->Typedef->Class = vtkParse_DuplicateString(ccp, n);
414       entry->Typedef->Type |= bits;
415       }
416
417     /* get the header file */
418     if (line[i] == ';')
419       {
420       i++;
421       i += skip_space(&line[i]);
422       n = 0;
423       while(line[i+n] != '\0' && line[i+n] != ';' &&
424             !isspace(line[i+n])) { n++; };
425       cp = (char *)malloc(n+1);
426       strncpy(cp, &line[i], n);
427       cp[n] = '\0';
428       entry->HeaderFile = cp;
429
430       i += n;
431       i += skip_space(&line[i]);
432
433       /* get the module */
434       if (line[i] == ';')
435         {
436         i++;
437         i += skip_space(&line[i]);
438         n = 0;
439         while(line[i+n] != '\0' && line[i+n] != ';' &&
440               !isspace(line[i+n])) { n++; };
441         cp = (char *)malloc(n+1);
442         strncpy(cp, &line[i], n);
443         cp[n] = '\0';
444         entry->Module = cp;
445
446         i += n;
447         i += skip_space(&line[i]);
448         }
449
450       /* get all flags */
451       while (line[i] == ';')
452         {
453         i++;
454         i += skip_space(&line[i]);
455         if (entry->NumberOfProperties == 0)
456           {
457           entry->Properties = (const char **)malloc(sizeof(char **));
458           }
459         else
460           {
461           entry->Properties = (const char **)realloc(
462             (char **)entry->Properties,
463             (entry->NumberOfProperties+1)*sizeof(char **));
464           }
465         n = 0;
466         while (line[i+n] != '\0' && line[i+n] != '\n' && line[i+n] != ';')
467           { n++; }
468         if (n && skip_space(&line[i]) != n)
469           {
470           cp = (char *)malloc((n+1)*sizeof(char *));
471           strncpy(cp, &line[i], n);
472           cp[n] = '\0';
473           entry->Properties[entry->NumberOfProperties++] = cp;
474           }
475         i += n;
476         }
477       }
478     }
479
480   if (!feof(fp))
481     {
482     vtkParseHierarchy_Free(info);
483     info = NULL;
484     }
485
486   free(line);
487
488   sort_hierarchy_entries(info);
489
490   return info;
491 }
492
493 /* free a HierarchyInfo struct */
494 void vtkParseHierarchy_Free(HierarchyInfo *info)
495 {
496   HierarchyEntry *entry;
497   int i, j;
498
499   for (i = 0; i < info->NumberOfEntries; i++)
500     {
501     entry = &info->Entries[i];
502     free((char *)entry->Name);
503     free((char *)entry->HeaderFile);
504     for (j = 0; j < entry->NumberOfTemplateArgs; j++)
505       {
506       free((char *)entry->TemplateArgs[j]);
507       if (entry->TemplateArgDefaults[j])
508         {
509         free((char *)entry->TemplateArgDefaults[j]);
510         }
511       }
512     if (entry->NumberOfTemplateArgs)
513       {
514       free((char **)entry->TemplateArgs);
515       free((char **)entry->TemplateArgDefaults);
516       }
517     for (j = 0; j < entry->NumberOfSuperClasses; j++)
518       {
519       free((char *)entry->SuperClasses[j]);
520       }
521     if (entry->NumberOfSuperClasses)
522       {
523       free((char **)entry->SuperClasses);
524       free(entry->SuperClassIndex);
525       }
526     for (j = 0; j < entry->NumberOfProperties; j++)
527       {
528       free((char *)entry->Properties[j]);
529       }
530     if (entry->NumberOfProperties)
531       {
532       free((char **)entry->Properties);
533       }
534     }
535
536   free(info->Entries);
537   free(info);
538 }
539
540
541 /* Check whether class is derived from baseclass.  You must supply
542  * the entry for the class (returned by FindEntry) as well as the
543  * classname.  If the class is templated, the classname can include 
544  * template args in angle brackets.  If you provide a pointer for
545  * baseclass_with_args, then it will be used to return the name of
546  * name of the baseclass with template args in angle brackets. */
547
548 int vtkParseHierarchy_IsTypeOfTemplated(
549   const HierarchyInfo *info,
550   const HierarchyEntry *entry, const char *classname,
551   const char *baseclass, const char **baseclass_with_args)
552 {
553   HierarchyEntry *tmph;
554   const char *name;
555   const char *supername;
556   char *tmp;
557   int templated;
558   int baseclass_is_template_parameter;
559   int supername_needs_free = 0;
560   int classname_needs_free = 0;
561   int i, j, k;
562   int nargs;
563   const char **args;
564   size_t m;
565   int iterating = 1;
566   int rval = 0;
567
568   while (iterating)
569     {
570     iterating = 0;
571     templated = 0;
572     baseclass_is_template_parameter = 0;
573     nargs = 0;
574     args = NULL;
575
576     /* if classname is the same as baseclass, done! */
577     if (strcmp(entry->Name, baseclass) == 0)
578       {
579       if (baseclass_with_args)
580         {
581         if (!classname_needs_free)
582           {
583           tmp = (char *)malloc(strlen(classname) + 1);
584           strcpy(tmp, classname);
585           classname = tmp;
586           }
587         *baseclass_with_args = classname;
588         classname_needs_free = 0;
589         }
590       rval = 1;
591       break;
592       }
593     else if (entry->NumberOfSuperClasses == 0)
594       {
595       rval = 0;
596       break;
597       }
598
599     /* if class is templated */
600     if (entry->NumberOfTemplateArgs)
601       {
602       /* check for template args for classname */
603       m = strlen(entry->Name);
604       if (classname[m] == '<')
605         {
606         templated = 1;
607
608         nargs = entry->NumberOfTemplateArgs;
609         vtkParse_DecomposeTemplatedType(classname, &name, nargs, &args,
610           entry->TemplateArgDefaults);
611         }
612       }
613
614     /* check all baseclasses */
615     for (j = 0; j < entry->NumberOfSuperClasses && rval == 0; j++)
616       {
617       supername = entry->SuperClasses[j];
618
619       if (templated)
620         {
621         for (k = 0; k < entry->NumberOfTemplateArgs; k++)
622           {
623           /* check if the baseclass itself is a template parameter */
624           m = strlen(entry->TemplateArgs[k]);
625           if (strncmp(entry->TemplateArgs[k], supername, m) == 0 &&
626               !isalnum(supername[m]) && supername[m] != '_')
627             {
628             baseclass_is_template_parameter = 1;
629             break;
630             }
631           }
632
633         /* use the class template args to find baseclass template args */
634         supername = vtkParse_StringReplace(
635           supername, entry->NumberOfTemplateArgs, entry->TemplateArgs, args);
636         if (supername != entry->SuperClasses[j])
637           {
638           supername_needs_free = 1;
639           }
640         }
641
642       /* check the cached index for the baseclass entry */
643       i = entry->SuperClassIndex[j];
644       if (i == -1)
645         {
646         /* index was not set yet, so search for the entry */
647         tmph = vtkParseHierarchy_FindEntry(info, supername);
648         while (tmph && tmph->IsTypedef)
649           {
650           if (tmph->Typedef->Class)
651             {
652             tmph = vtkParseHierarchy_FindEntry(info, tmph->Typedef->Class);
653             continue;
654             }
655           break;
656           }
657
658         if (tmph)
659           {
660           i = (int)(tmph - info->Entries);
661           }
662         else
663           {
664           /* entry not found, don't try again */
665           /* i = -2; messes things up for templates */
666           /* fprintf(stderr, "not found \"%s\"\n", entry->SuperClasses[j]); */
667           }
668
669         /* if baseclass is a template parameter, its entry cannot be cached */
670         if (!baseclass_is_template_parameter)
671           {
672           /* cache the position of the baseclass */
673           ((HierarchyEntry *)entry)->SuperClassIndex[j] = i;
674           }
675         }
676
677       /* if entry was found, continue down the chain */
678       if (i >= 0)
679         {
680         if (classname_needs_free)
681           {
682           free((char *)classname);
683           }
684         classname = supername;
685         classname_needs_free = supername_needs_free;
686         supername_needs_free = 0;
687
688         /* use the iteration loop instead of recursion */
689         if (j+1 >= entry->NumberOfSuperClasses)
690           {
691           entry = &info->Entries[i];
692           iterating = 1;
693           }
694
695         /* recurse for multiple inheritance */
696         else
697           {
698           rval = vtkParseHierarchy_IsTypeOfTemplated(
699                    info, &info->Entries[i], classname, baseclass,
700                    baseclass_with_args);
701           }
702         }
703
704       if (supername_needs_free)
705         {
706         free((char *)supername);
707         supername_needs_free = 0;
708         }
709
710       } /* end of loop over superclasses */
711
712     if (templated)
713       {
714       vtkParse_FreeTemplateDecomposition(name, nargs, args);
715       }
716
717     } /* end of "while (iterating)" */
718
719   if (classname_needs_free)
720     {
721     free((char *)classname);
722     }
723
724   if (baseclass_with_args && !rval)
725     {
726     *baseclass_with_args = NULL;
727     }
728
729   return rval;
730 }
731
732 int vtkParseHierarchy_IsTypeOf(
733   const HierarchyInfo *info, const HierarchyEntry *entry,
734   const char *baseclass)
735 {
736   return vtkParseHierarchy_IsTypeOfTemplated(
737     info, entry, entry->Name, baseclass, NULL);
738 }
739
740 /* Free args returned by IsTypeOfTemplated */
741 void vtkParseHierarchy_FreeTemplateArgs(int n, const char *args[])
742 {
743   int i;
744
745   for (i = 0; i < n; i++)
746     {
747     free((char *)args[i]);
748     }
749
750   free((char **)args);
751 }
752
753 /* Given a classname with template parameters, get the superclass name
754  * with corresponding template parameters.  Returns null if 'i' is out
755  * of range, i.e. greater than or equal to the number of superclasses.
756  * The returned classname must be freed with "free()". */
757 const char *vtkParseHierarchy_TemplatedSuperClass(
758   const HierarchyEntry *entry, const char *classname, int i)
759 {
760   const char *supername = NULL;
761   const char *name;
762   const char **args;
763   char *cp;
764   size_t j;
765
766   if (i < entry->NumberOfSuperClasses)
767     {
768     supername = entry->SuperClasses[i];
769     j = vtkParse_IdentifierLength(classname);
770
771     if (classname[j] == '<')
772       {
773       vtkParse_DecomposeTemplatedType(classname, &name,
774         entry->NumberOfTemplateArgs, &args, entry->TemplateArgDefaults);
775       supername = vtkParse_StringReplace(entry->SuperClasses[i],
776         entry->NumberOfTemplateArgs, entry->TemplateArgs, args);
777       vtkParse_FreeTemplateDecomposition(
778         name, entry->NumberOfTemplateArgs, args);
779       }
780
781     if (supername == entry->SuperClasses[i])
782       {
783       cp = (char *)malloc(strlen(supername) + 1);
784       strcpy(cp, supername);
785       supername = cp;
786       }
787     }
788
789   return supername;
790 }
791
792 /* get the specified property, or return NULL */
793 const char *vtkParseHierarchy_GetProperty(
794   const HierarchyEntry *entry, const char *property)
795 {
796   int i;
797   size_t k;
798
799   if (entry)
800     {
801     for (i = 0; i < entry->NumberOfProperties; i++)
802       {
803       /* skip the property name, everything after is the property */
804       k = vtkParse_NameLength(entry->Properties[i]);
805       if (k == strlen(property) &&
806           strncmp(entry->Properties[i], property, k) == 0)
807         {
808         if (entry->Properties[i][k] == ' ' ||
809             entry->Properties[i][k] == '=') { k++; }
810         return &entry->Properties[i][k];
811         }
812       }
813     }
814
815   return NULL;
816 }
817
818 /* Expand all unrecognized types in a ValueInfo struct by
819  * using the typedefs in the HierarchyInfo struct. */
820 int vtkParseHierarchy_ExpandTypedefsInValue(
821   const HierarchyInfo *info, ValueInfo *val, const char *scope)
822 {
823   char text[128];
824   char *cp;
825   const char *newclass;
826   size_t n, m;
827   int i;
828   HierarchyEntry *entry;
829   int scope_needs_free = 0;
830   int result = 1;
831
832   while (((val->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_OBJECT ||
833           (val->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_UNKNOWN) &&
834          val->Class != 0)
835     {
836     entry = 0;
837
838     /* search for the type in the provided scope */
839     while (entry == 0 && scope != 0)
840       {
841       cp = text;
842       n = strlen(scope);
843       m = strlen(val->Class);
844       /* only malloc if more than 128 chars needed */
845       if (n + m + 2 >= 128)
846         {
847         cp = (char *)malloc(n+m+3);
848         }
849
850       /* scope the name */
851       strncpy(cp, scope, n);
852       cp[n++] = ':';
853       cp[n++] = ':';
854       strncpy(&cp[n], val->Class, m);
855       cp[n+m] = '\0';
856
857       entry = vtkParseHierarchy_FindEntry(info, cp);
858
859       if (cp != text) { free(cp); }
860
861       /* if not found, try inherited scopes */
862       if (entry == 0)
863         {
864         entry = vtkParseHierarchy_FindEntry(info, scope);
865         scope = 0;
866         scope_needs_free = 0;
867         if (entry && entry->NumberOfSuperClasses)
868           {
869           for (i = 0; i+1 < entry->NumberOfSuperClasses; i++)
870             {
871             if (scope_needs_free) { free((char *)scope); }
872             scope = vtkParseHierarchy_ExpandTypedefsInName(
873               info, entry->SuperClasses[i], NULL);
874             scope_needs_free = (scope != entry->SuperClasses[i]);
875             /* recurse if more than one superclass */
876             if (vtkParseHierarchy_ExpandTypedefsInValue(info, val, scope))
877               {
878               if (scope_needs_free) { free((char *)scope); }
879               return 1;
880               }
881             }
882           if (scope_needs_free) { free((char *)scope); }
883           scope = vtkParseHierarchy_ExpandTypedefsInName(
884             info, entry->SuperClasses[i], NULL);
885           scope_needs_free = (scope != entry->SuperClasses[i]);
886           }
887         entry = 0;
888         }
889       }
890
891     /* if not found, try again with no scope */
892     if (entry == 0)
893       {
894       entry = vtkParseHierarchy_FindEntry(info, val->Class);
895       }
896
897     if (entry && entry->IsTypedef)
898       {
899       vtkParse_ExpandTypedef(val, entry->Typedef);
900       }
901     else if (entry)
902       {
903       newclass = vtkParseHierarchy_ExpandTypedefsInName(
904          info, val->Class, scope);
905       if (newclass != val->Class)
906         {
907         val->Class = vtkParse_DuplicateString(newclass, strlen(newclass));
908         free((char *)newclass);
909         }
910       result = 1;
911       break;
912       }
913     else
914       {
915       result = 0;
916       break;
917       }
918     }
919
920   if (scope_needs_free) { free((char *)scope); }
921
922   return result;
923 }
924
925 /* Expand typedefs found in an expression stored as a string.
926  * The value of "text" will be returned if no expansion occurred,
927  * else a new string is returned that must be freed with "free()". */
928 const char *vtkParseHierarchy_ExpandTypedefsInName(
929   const HierarchyInfo *info, const char *name, const char *scope)
930 {
931   char text[128];
932   char *cp;
933   size_t n, m;
934   const char *newname = name;
935   HierarchyEntry *entry = NULL;
936
937   /* note: unlike ExpandTypedefsInValue, this does not yet recurse
938    * or look in superclass scopes */
939
940   /* doesn't yet handle names that are scoped or templated */
941   m = vtkParse_IdentifierLength(name);
942   if (name[m] != '\0')
943     {
944     return name;
945     }
946
947   if (scope)
948     {
949     cp = text;
950     n = strlen(scope);
951     m = strlen(name);
952     /* only malloc if more than 128 chars needed */
953     if (n + m + 2 >= 128)
954       {
955       cp = (char *)malloc(n+m+3);
956       }
957
958     /* scope the name */
959     strncpy(cp, scope, n);
960     cp[n++] = ':';
961     cp[n++] = ':';
962     strncpy(&cp[n], name, m);
963     cp[n+m] = '\0';
964
965     entry = vtkParseHierarchy_FindEntry(info, cp);
966
967     if (cp != text) { free(cp); }
968     }
969
970   if (!entry)
971     {
972     entry = vtkParseHierarchy_FindEntry(info, name);
973     }
974
975   newname = NULL;
976   if (entry && entry->IsTypedef && entry->Typedef->Class)
977     {
978     newname = entry->Typedef->Class;
979     }
980   if (newname)
981     {
982     cp = (char *)malloc(strlen(newname) + 1);
983     strcpy(cp, newname);
984     name = cp;
985     }
986
987   return name;
988 }