Back to index

salome-paravis  6.5.0
vtkParseHierarchy.c
Go to the documentation of this file.
00001 /*=========================================================================
00002 
00003   Program:   Visualization Toolkit
00004   Module:    vtkParseHierarchy.c
00005 
00006   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
00007   All rights reserved.
00008   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
00009 
00010      This software is distributed WITHOUT ANY WARRANTY; without even
00011      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
00012      PURPOSE.  See the above copyright notice for more information.
00013 
00014 =========================================================================*/
00015 /*-------------------------------------------------------------------------
00016   Copyright (c) 2010 David Gobbi.
00017 
00018   Contributed to the VisualizationToolkit by the author in June 2010
00019   under the terms of the Visualization Toolkit 2008 copyright.
00020 -------------------------------------------------------------------------*/
00021 
00022 #include "vtkParseHierarchy.h"
00023 #include "vtkParseInternal.h"
00024 #include "vtkParseExtras.h"
00025 #include "vtkType.h"
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <stdlib.h>
00029 #include <ctype.h>
00030 #include <assert.h>
00031 
00032 static size_t skip_space(const char *text)
00033 {
00034   size_t i = 0;
00035   while (isspace(text[i]) && text[i] != '\n') { i++; }
00036   return i;
00037 }
00038 
00039 /* helper: comparison of entries */
00040 static int compare_hierarchy_entries(const void *vp1, const void *vp2)
00041 {
00042   const HierarchyEntry *entry1 = (const HierarchyEntry *)vp1;
00043   const HierarchyEntry *entry2 = (const HierarchyEntry *)vp2;
00044 
00045   return strcmp(entry1->Name, entry2->Name);
00046 }
00047 
00048 /* helper: sort the entries to facilitate searching */
00049 static void sort_hierarchy_entries(HierarchyInfo *info)
00050 {
00051   qsort(info->Entries, info->NumberOfEntries, sizeof(HierarchyEntry),
00052         &compare_hierarchy_entries);
00053 }
00054 
00055 /* Find an entry with a binary search */
00056 HierarchyEntry *vtkParseHierarchy_FindEntry(
00057   const HierarchyInfo *info, const char *classname)
00058 {
00059   HierarchyEntry key;
00060   HierarchyEntry *entry;
00061   size_t i, n;
00062   char name[32];
00063   char *cp;
00064 
00065   /* use classname as-is for the search if possible */
00066   cp = (char *)classname;
00067 
00068   /* get portion of name before final template parameters */
00069   n = vtkParse_UnscopedNameLength(classname);
00070   i = 0;
00071   while (classname[i+n] == ':' && classname[i+n+1] == ':')
00072     {
00073     i += n + 2;
00074     n = vtkParse_UnscopedNameLength(&classname[i]);
00075     }
00076   i += vtkParse_IdentifierLength(&classname[i]);
00077       
00078   /* create a new (shorter) search string if necessary */
00079   if (classname[i] != '\0')
00080     {
00081     /* use stack space if possible */
00082     cp = name;
00083     /* otherwise, use malloc */
00084     if (i > 31)
00085       {
00086       cp = (char *)malloc(i+1);
00087       }
00088     strncpy(cp, classname, i);
00089     cp[i] = '\0';
00090     }
00091 
00092   key.Name = cp;
00093 
00094   entry = (HierarchyEntry *)bsearch(&key, info->Entries,
00095     info->NumberOfEntries, sizeof(HierarchyEntry),
00096     &compare_hierarchy_entries);
00097 
00098   if (cp != classname && cp != name)
00099     {
00100     free(cp);
00101     }
00102 
00103   return entry;
00104 }
00105 
00106 
00107 /* read a hierarchy file into a HeirarchyInfo struct, or return NULL */
00108 HierarchyInfo *vtkParseHierarchy_ReadFile(const char *filename)
00109 {
00110   HierarchyInfo *info;
00111   HierarchyEntry *entry;
00112   int maxClasses = 500;
00113   FILE *fp;
00114   char *line;
00115   char *cp;
00116   const char *ccp;
00117   size_t maxlen = 15;
00118   size_t i, j, n, m;
00119   unsigned int bits, pointers;
00120 
00121   line = (char *)malloc(maxlen);
00122 
00123   fp = fopen(filename, "r");
00124 
00125   if (fp == NULL)
00126     {
00127     return NULL;
00128     }
00129 
00130   info = (HierarchyInfo *)malloc(sizeof(HierarchyInfo));
00131   info->NumberOfEntries = 0;
00132   info->Entries = (HierarchyEntry *)malloc(maxClasses*sizeof(HierarchyEntry));
00133 
00134   while (fgets(line, (int)maxlen, fp))
00135     {
00136     n = strlen(line);
00137 
00138     /* if buffer not long enough, increase it */
00139     while (n == maxlen-1 && line[n-1] != '\n' && !feof(fp))
00140       {
00141       maxlen *= 2;
00142       line = (char *)realloc(line, maxlen);
00143       if (!fgets(&line[n], (int)(maxlen-n), fp)) { break; }
00144       n += strlen(&line[n]);
00145       }
00146 
00147     while (n > 0 && isspace(line[n-1]))
00148       {
00149       n--;
00150       }
00151     line[n] = '\0';
00152 
00153     if (line[0] == '\0')
00154       {
00155       continue;
00156       }
00157 
00158     if (info->NumberOfEntries == maxClasses)
00159       {
00160       maxClasses *= 2;
00161       info->Entries = (HierarchyEntry *)realloc(
00162         info->Entries, sizeof(HierarchyEntry)*maxClasses*2);
00163       }
00164 
00165     entry = &info->Entries[info->NumberOfEntries++];
00166     entry->Name = NULL;
00167     entry->HeaderFile = NULL;
00168     entry->Module = NULL;
00169     entry->NumberOfTemplateArgs = 0;
00170     entry->TemplateArgs = NULL;
00171     entry->TemplateArgDefaults = NULL;
00172     entry->NumberOfProperties = 0;
00173     entry->Properties = NULL;
00174     entry->NumberOfSuperClasses = 0;
00175     entry->SuperClasses = NULL;
00176     entry->SuperClassIndex = NULL;
00177     entry->Typedef = NULL;
00178     entry->IsTypedef = 0;
00179     entry->IsEnum = 0;
00180 
00181     i = skip_space(line);
00182     n = vtkParse_NameLength(&line[i]);
00183     for (m = 0; m < n; m++)
00184       {
00185       if (line[i+m] == '<') { break; }
00186       }
00187 
00188     cp = (char *)malloc(m+1);
00189     strncpy(cp, &line[i], m);
00190     cp[m] = '\0';
00191     entry->Name = cp;
00192     i += m;
00193 
00194     if (line[i] == '<')
00195       {
00196       i++;
00197       i += skip_space(&line[i]);
00198 
00199       for (j = 0; line[i] != '>' && line[i] != '\0'; j++)
00200         {
00201         if (j == 0)
00202           {
00203           entry->TemplateArgs = (const char **)malloc(sizeof(char *));
00204           entry->TemplateArgDefaults = (const char **)malloc(sizeof(char *));
00205           }
00206         else
00207           {
00208           entry->TemplateArgs = (const char **)realloc(
00209             (char **)entry->TemplateArgs, (j+1)*sizeof(char *));
00210           entry->TemplateArgDefaults = (const char **)realloc(
00211             (char **)entry->TemplateArgDefaults, (j+1)*sizeof(char *));
00212           }
00213         entry->NumberOfTemplateArgs++;
00214         entry->TemplateArgDefaults[j] = NULL;
00215 
00216         m = vtkParse_NameLength(&line[i]);
00217 
00218         cp = (char *)malloc(m+1);
00219         strncpy(cp, &line[i], m);
00220         cp[m] = '\0';
00221         entry->TemplateArgs[j] = cp;
00222         i += m;
00223         i += skip_space(&line[i]);
00224 
00225         if (line[i] == '=')
00226           {
00227           i++;
00228           i += skip_space(&line[i]);
00229           m = vtkParse_NameLength(&line[i]);
00230 
00231           cp = (char *)malloc(m+1);
00232           strncpy(cp, &line[i], m);
00233           cp[m] = '\0';
00234           entry->TemplateArgDefaults[j] = cp;
00235           i += m;
00236           i += skip_space(&line[i]);
00237           }
00238 
00239         if (line[i] == ',')
00240           {
00241           i++;
00242           i += skip_space(&line[i]);
00243           }
00244         }
00245 
00246       if (line[i] == '>')
00247         {
00248         i++;
00249         i += skip_space(&line[i]);
00250         }
00251 
00252       if (line[i] == ':' && line[i+1] == ':')
00253         {
00254         i += 2;
00255         m = vtkParse_NameLength(&line[i]);
00256         n = strlen(entry->Name);
00257         cp = (char *)malloc(n+m+3);
00258         strcpy(cp, entry->Name);
00259         strcpy(&cp[n], "::");
00260         strncpy(&cp[n+2], &line[i], m);
00261         i += m;
00262         cp[n+m+2] = '\0';
00263         free((char *)entry->Name);
00264         entry->Name = cp;
00265         }
00266       }
00267 
00268     i += skip_space(&line[i]);
00269 
00270     /* classes (and possibly enums) */
00271     if (line[i] == ':')
00272       {
00273       i++;
00274       i += skip_space(&line[i]);
00275       n = vtkParse_NameLength(&line[i]);
00276       /* check for enum indicators */
00277       if ((n == 3 && strncmp(&line[i], "int", n)) ||
00278           (n == 4 && strncmp(&line[i], "enum", n)))
00279         {
00280         entry->IsEnum = 1;
00281         i += n;
00282         i += skip_space(&line[i]);
00283         }
00284       /* else check for superclasses */
00285       else for (j = 0; ; j++)
00286         {
00287         if (j == 0)
00288           {
00289           entry->SuperClasses = (const char **)malloc(sizeof(char *));
00290           entry->SuperClassIndex = (int *)malloc(sizeof(int));
00291           }
00292         else
00293           {
00294           entry->SuperClasses = (const char **)realloc(
00295             (char **)entry->SuperClasses, (j+1)*sizeof(char *));
00296           entry->SuperClassIndex = (int *)realloc(
00297             entry->SuperClassIndex, (j+1)*sizeof(int));
00298           }
00299         entry->NumberOfSuperClasses++;
00300 
00301         i += skip_space(&line[i]);
00302         n = vtkParse_NameLength(&line[i]);
00303         cp = (char *)malloc(n+1);
00304         strncpy(cp, &line[i], n);
00305         cp[n] = '\0';
00306         entry->SuperClasses[j] = cp;
00307         entry->SuperClassIndex[j] = -1;
00308         i += n;
00309 
00310         i += skip_space(&line[i]);
00311         if (line[i] != ',')
00312           {
00313           break;
00314           }
00315         i++;
00316         }
00317       }
00318 
00319     /* read typedefs */
00320     else if (line[i] == '=')
00321       {
00322       i++;
00323       i += skip_space(&line[i]);
00324       entry->IsTypedef = 1;
00325       entry->Typedef = (ValueInfo *)malloc(sizeof(ValueInfo));
00326       vtkParse_InitValue(entry->Typedef);
00327 
00328       /* type is a reference (does this ever occur?) */
00329       if (line[i] == '&')
00330         {
00331         i++;
00332         i += skip_space(&line[i]);
00333         entry->Typedef->Type |= VTK_PARSE_REF;
00334         }
00335 
00336       /* type has array dimensions */
00337       if (line[i] == '[')
00338         {
00339         entry->Typedef->Count = 1;
00340         }
00341 
00342       while (line[i] == '[')
00343         {
00344         i++;
00345         n = 0;
00346         while (line[i+n] != ']' && line[i+n] != '\n' && line[i+n] != '\0')
00347           {
00348           n++;
00349           }
00350         ccp = vtkParse_DuplicateString(&line[i], n);
00351         vtkParse_AddStringToArray(&entry->Typedef->Dimensions,
00352                                   &entry->Typedef->NumberOfDimensions, ccp);
00353         if (ccp[0] >= '0' && ccp[0] <= '9')
00354           {
00355           entry->Typedef->Count *= (int)strtol(ccp, NULL, 0);
00356           }
00357         else
00358           {
00359           entry->Typedef->Count = 0;
00360           }
00361         i += n;
00362         if (line[i] == ']')
00363           {
00364           i++;
00365           }
00366         }
00367       i += skip_space(&line[i]);
00368 
00369       /* look for pointers (and const pointers) */
00370       bits = 0;
00371       while (line[i] == '*' || strncmp(&line[i], "const*", 6) == 0)
00372         {
00373         bits = (bits << 2);
00374         if (line[i] == '*')
00375           {
00376           bits = (bits | VTK_PARSE_POINTER);
00377           }
00378         else
00379           {
00380           bits = (bits | VTK_PARSE_CONST_POINTER);
00381           i += 5;
00382           }
00383         bits = (bits & VTK_PARSE_POINTER_MASK);
00384         i++;
00385         i += skip_space(&line[i]);
00386         }
00387 
00388       /* need to reverse to get correct pointer order */
00389       pointers = 0;
00390       while (bits)
00391         {
00392         pointers = (pointers << 2);
00393         pointers = (pointers | (bits & VTK_PARSE_POINTER_LOWMASK));
00394         bits = ((bits >> 2) & VTK_PARSE_POINTER_MASK);
00395         }
00396 
00397       /* add pointer indirection to correspond to first array dimension */
00398       if (entry->Typedef->NumberOfDimensions > 1)
00399         {
00400         pointers = ((pointers << 2) | VTK_PARSE_ARRAY);
00401         }
00402       else if (entry->Typedef->NumberOfDimensions == 1)
00403         {
00404         pointers = ((pointers << 2) | VTK_PARSE_POINTER);
00405         }
00406 
00407       /* include the pointers in the type */
00408       entry->Typedef->Type |= (pointers & VTK_PARSE_POINTER_MASK);
00409 
00410       /* read the base type (and const) */
00411       bits = 0;
00412       i += vtkParse_BasicTypeFromString(&line[i], &bits, &ccp, &n);
00413       entry->Typedef->Class = vtkParse_DuplicateString(ccp, n);
00414       entry->Typedef->Type |= bits;
00415       }
00416 
00417     /* get the header file */
00418     if (line[i] == ';')
00419       {
00420       i++;
00421       i += skip_space(&line[i]);
00422       n = 0;
00423       while(line[i+n] != '\0' && line[i+n] != ';' &&
00424             !isspace(line[i+n])) { n++; };
00425       cp = (char *)malloc(n+1);
00426       strncpy(cp, &line[i], n);
00427       cp[n] = '\0';
00428       entry->HeaderFile = cp;
00429 
00430       i += n;
00431       i += skip_space(&line[i]);
00432 
00433       /* get the module */
00434       if (line[i] == ';')
00435         {
00436         i++;
00437         i += skip_space(&line[i]);
00438         n = 0;
00439         while(line[i+n] != '\0' && line[i+n] != ';' &&
00440               !isspace(line[i+n])) { n++; };
00441         cp = (char *)malloc(n+1);
00442         strncpy(cp, &line[i], n);
00443         cp[n] = '\0';
00444         entry->Module = cp;
00445 
00446         i += n;
00447         i += skip_space(&line[i]);
00448         }
00449 
00450       /* get all flags */
00451       while (line[i] == ';')
00452         {
00453         i++;
00454         i += skip_space(&line[i]);
00455         if (entry->NumberOfProperties == 0)
00456           {
00457           entry->Properties = (const char **)malloc(sizeof(char **));
00458           }
00459         else
00460           {
00461           entry->Properties = (const char **)realloc(
00462             (char **)entry->Properties,
00463             (entry->NumberOfProperties+1)*sizeof(char **));
00464           }
00465         n = 0;
00466         while (line[i+n] != '\0' && line[i+n] != '\n' && line[i+n] != ';')
00467           { n++; }
00468         if (n && skip_space(&line[i]) != n)
00469           {
00470           cp = (char *)malloc((n+1)*sizeof(char *));
00471           strncpy(cp, &line[i], n);
00472           cp[n] = '\0';
00473           entry->Properties[entry->NumberOfProperties++] = cp;
00474           }
00475         i += n;
00476         }
00477       }
00478     }
00479 
00480   if (!feof(fp))
00481     {
00482     vtkParseHierarchy_Free(info);
00483     info = NULL;
00484     }
00485 
00486   free(line);
00487 
00488   sort_hierarchy_entries(info);
00489 
00490   return info;
00491 }
00492 
00493 /* free a HierarchyInfo struct */
00494 void vtkParseHierarchy_Free(HierarchyInfo *info)
00495 {
00496   HierarchyEntry *entry;
00497   int i, j;
00498 
00499   for (i = 0; i < info->NumberOfEntries; i++)
00500     {
00501     entry = &info->Entries[i];
00502     free((char *)entry->Name);
00503     free((char *)entry->HeaderFile);
00504     for (j = 0; j < entry->NumberOfTemplateArgs; j++)
00505       {
00506       free((char *)entry->TemplateArgs[j]);
00507       if (entry->TemplateArgDefaults[j])
00508         {
00509         free((char *)entry->TemplateArgDefaults[j]);
00510         }
00511       }
00512     if (entry->NumberOfTemplateArgs)
00513       {
00514       free((char **)entry->TemplateArgs);
00515       free((char **)entry->TemplateArgDefaults);
00516       }
00517     for (j = 0; j < entry->NumberOfSuperClasses; j++)
00518       {
00519       free((char *)entry->SuperClasses[j]);
00520       }
00521     if (entry->NumberOfSuperClasses)
00522       {
00523       free((char **)entry->SuperClasses);
00524       free(entry->SuperClassIndex);
00525       }
00526     for (j = 0; j < entry->NumberOfProperties; j++)
00527       {
00528       free((char *)entry->Properties[j]);
00529       }
00530     if (entry->NumberOfProperties)
00531       {
00532       free((char **)entry->Properties);
00533       }
00534     }
00535 
00536   free(info->Entries);
00537   free(info);
00538 }
00539 
00540 
00541 /* Check whether class is derived from baseclass.  You must supply
00542  * the entry for the class (returned by FindEntry) as well as the
00543  * classname.  If the class is templated, the classname can include 
00544  * template args in angle brackets.  If you provide a pointer for
00545  * baseclass_with_args, then it will be used to return the name of
00546  * name of the baseclass with template args in angle brackets. */
00547 
00548 int vtkParseHierarchy_IsTypeOfTemplated(
00549   const HierarchyInfo *info,
00550   const HierarchyEntry *entry, const char *classname,
00551   const char *baseclass, const char **baseclass_with_args)
00552 {
00553   HierarchyEntry *tmph;
00554   const char *name;
00555   const char *supername;
00556   char *tmp;
00557   int templated;
00558   int baseclass_is_template_parameter;
00559   int supername_needs_free = 0;
00560   int classname_needs_free = 0;
00561   int i, j, k;
00562   int nargs;
00563   const char **args;
00564   size_t m;
00565   int iterating = 1;
00566   int rval = 0;
00567 
00568   while (iterating)
00569     {
00570     iterating = 0;
00571     templated = 0;
00572     baseclass_is_template_parameter = 0;
00573     nargs = 0;
00574     args = NULL;
00575 
00576     /* if classname is the same as baseclass, done! */
00577     if (strcmp(entry->Name, baseclass) == 0)
00578       {
00579       if (baseclass_with_args)
00580         {
00581         if (!classname_needs_free)
00582           {
00583           tmp = (char *)malloc(strlen(classname) + 1);
00584           strcpy(tmp, classname);
00585           classname = tmp;
00586           }
00587         *baseclass_with_args = classname;
00588         classname_needs_free = 0;
00589         }
00590       rval = 1;
00591       break;
00592       }
00593     else if (entry->NumberOfSuperClasses == 0)
00594       {
00595       rval = 0;
00596       break;
00597       }
00598 
00599     /* if class is templated */
00600     if (entry->NumberOfTemplateArgs)
00601       {
00602       /* check for template args for classname */
00603       m = strlen(entry->Name);
00604       if (classname[m] == '<')
00605         {
00606         templated = 1;
00607 
00608         nargs = entry->NumberOfTemplateArgs;
00609         vtkParse_DecomposeTemplatedType(classname, &name, nargs, &args,
00610           entry->TemplateArgDefaults);
00611         }
00612       }
00613 
00614     /* check all baseclasses */
00615     for (j = 0; j < entry->NumberOfSuperClasses && rval == 0; j++)
00616       {
00617       supername = entry->SuperClasses[j];
00618 
00619       if (templated)
00620         {
00621         for (k = 0; k < entry->NumberOfTemplateArgs; k++)
00622           {
00623           /* check if the baseclass itself is a template parameter */
00624           m = strlen(entry->TemplateArgs[k]);
00625           if (strncmp(entry->TemplateArgs[k], supername, m) == 0 &&
00626               !isalnum(supername[m]) && supername[m] != '_')
00627             {
00628             baseclass_is_template_parameter = 1;
00629             break;
00630             }
00631           }
00632 
00633         /* use the class template args to find baseclass template args */
00634         supername = vtkParse_StringReplace(
00635           supername, entry->NumberOfTemplateArgs, entry->TemplateArgs, args);
00636         if (supername != entry->SuperClasses[j])
00637           {
00638           supername_needs_free = 1;
00639           }
00640         }
00641 
00642       /* check the cached index for the baseclass entry */
00643       i = entry->SuperClassIndex[j];
00644       if (i == -1)
00645         {
00646         /* index was not set yet, so search for the entry */
00647         tmph = vtkParseHierarchy_FindEntry(info, supername);
00648         while (tmph && tmph->IsTypedef)
00649           {
00650           if (tmph->Typedef->Class)
00651             {
00652             tmph = vtkParseHierarchy_FindEntry(info, tmph->Typedef->Class);
00653             continue;
00654             }
00655           break;
00656           }
00657 
00658         if (tmph)
00659           {
00660           i = (int)(tmph - info->Entries);
00661           }
00662         else
00663           {
00664           /* entry not found, don't try again */
00665           /* i = -2; messes things up for templates */
00666           /* fprintf(stderr, "not found \"%s\"\n", entry->SuperClasses[j]); */
00667           }
00668 
00669         /* if baseclass is a template parameter, its entry cannot be cached */
00670         if (!baseclass_is_template_parameter)
00671           {
00672           /* cache the position of the baseclass */
00673           ((HierarchyEntry *)entry)->SuperClassIndex[j] = i;
00674           }
00675         }
00676 
00677       /* if entry was found, continue down the chain */
00678       if (i >= 0)
00679         {
00680         if (classname_needs_free)
00681           {
00682           free((char *)classname);
00683           }
00684         classname = supername;
00685         classname_needs_free = supername_needs_free;
00686         supername_needs_free = 0;
00687 
00688         /* use the iteration loop instead of recursion */
00689         if (j+1 >= entry->NumberOfSuperClasses)
00690           {
00691           entry = &info->Entries[i];
00692           iterating = 1;
00693           }
00694 
00695         /* recurse for multiple inheritance */
00696         else
00697           {
00698           rval = vtkParseHierarchy_IsTypeOfTemplated(
00699                    info, &info->Entries[i], classname, baseclass,
00700                    baseclass_with_args);
00701           }
00702         }
00703 
00704       if (supername_needs_free)
00705         {
00706         free((char *)supername);
00707         supername_needs_free = 0;
00708         }
00709 
00710       } /* end of loop over superclasses */
00711 
00712     if (templated)
00713       {
00714       vtkParse_FreeTemplateDecomposition(name, nargs, args);
00715       }
00716 
00717     } /* end of "while (iterating)" */
00718 
00719   if (classname_needs_free)
00720     {
00721     free((char *)classname);
00722     }
00723 
00724   if (baseclass_with_args && !rval)
00725     {
00726     *baseclass_with_args = NULL;
00727     }
00728 
00729   return rval;
00730 }
00731 
00732 int vtkParseHierarchy_IsTypeOf(
00733   const HierarchyInfo *info, const HierarchyEntry *entry,
00734   const char *baseclass)
00735 {
00736   return vtkParseHierarchy_IsTypeOfTemplated(
00737     info, entry, entry->Name, baseclass, NULL);
00738 }
00739 
00740 /* Free args returned by IsTypeOfTemplated */
00741 void vtkParseHierarchy_FreeTemplateArgs(int n, const char *args[])
00742 {
00743   int i;
00744 
00745   for (i = 0; i < n; i++)
00746     {
00747     free((char *)args[i]);
00748     }
00749 
00750   free((char **)args);
00751 }
00752 
00753 /* Given a classname with template parameters, get the superclass name
00754  * with corresponding template parameters.  Returns null if 'i' is out
00755  * of range, i.e. greater than or equal to the number of superclasses.
00756  * The returned classname must be freed with "free()". */
00757 const char *vtkParseHierarchy_TemplatedSuperClass(
00758   const HierarchyEntry *entry, const char *classname, int i)
00759 {
00760   const char *supername = NULL;
00761   const char *name;
00762   const char **args;
00763   char *cp;
00764   size_t j;
00765 
00766   if (i < entry->NumberOfSuperClasses)
00767     {
00768     supername = entry->SuperClasses[i];
00769     j = vtkParse_IdentifierLength(classname);
00770 
00771     if (classname[j] == '<')
00772       {
00773       vtkParse_DecomposeTemplatedType(classname, &name,
00774         entry->NumberOfTemplateArgs, &args, entry->TemplateArgDefaults);
00775       supername = vtkParse_StringReplace(entry->SuperClasses[i],
00776         entry->NumberOfTemplateArgs, entry->TemplateArgs, args);
00777       vtkParse_FreeTemplateDecomposition(
00778         name, entry->NumberOfTemplateArgs, args);
00779       }
00780 
00781     if (supername == entry->SuperClasses[i])
00782       {
00783       cp = (char *)malloc(strlen(supername) + 1);
00784       strcpy(cp, supername);
00785       supername = cp;
00786       }
00787     }
00788 
00789   return supername;
00790 }
00791 
00792 /* get the specified property, or return NULL */
00793 const char *vtkParseHierarchy_GetProperty(
00794   const HierarchyEntry *entry, const char *property)
00795 {
00796   int i;
00797   size_t k;
00798 
00799   if (entry)
00800     {
00801     for (i = 0; i < entry->NumberOfProperties; i++)
00802       {
00803       /* skip the property name, everything after is the property */
00804       k = vtkParse_NameLength(entry->Properties[i]);
00805       if (k == strlen(property) &&
00806           strncmp(entry->Properties[i], property, k) == 0)
00807         {
00808         if (entry->Properties[i][k] == ' ' ||
00809             entry->Properties[i][k] == '=') { k++; }
00810         return &entry->Properties[i][k];
00811         }
00812       }
00813     }
00814 
00815   return NULL;
00816 }
00817 
00818 /* Expand all unrecognized types in a ValueInfo struct by
00819  * using the typedefs in the HierarchyInfo struct. */
00820 int vtkParseHierarchy_ExpandTypedefsInValue(
00821   const HierarchyInfo *info, ValueInfo *val, const char *scope)
00822 {
00823   char text[128];
00824   char *cp;
00825   const char *newclass;
00826   size_t n, m;
00827   int i;
00828   HierarchyEntry *entry;
00829   int scope_needs_free = 0;
00830   int result = 1;
00831 
00832   while (((val->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_OBJECT ||
00833           (val->Type & VTK_PARSE_BASE_TYPE) == VTK_PARSE_UNKNOWN) &&
00834          val->Class != 0)
00835     {
00836     entry = 0;
00837 
00838     /* search for the type in the provided scope */
00839     while (entry == 0 && scope != 0)
00840       {
00841       cp = text;
00842       n = strlen(scope);
00843       m = strlen(val->Class);
00844       /* only malloc if more than 128 chars needed */
00845       if (n + m + 2 >= 128)
00846         {
00847         cp = (char *)malloc(n+m+3);
00848         }
00849 
00850       /* scope the name */
00851       strncpy(cp, scope, n);
00852       cp[n++] = ':';
00853       cp[n++] = ':';
00854       strncpy(&cp[n], val->Class, m);
00855       cp[n+m] = '\0';
00856 
00857       entry = vtkParseHierarchy_FindEntry(info, cp);
00858 
00859       if (cp != text) { free(cp); }
00860 
00861       /* if not found, try inherited scopes */
00862       if (entry == 0)
00863         {
00864         entry = vtkParseHierarchy_FindEntry(info, scope);
00865         scope = 0;
00866         scope_needs_free = 0;
00867         if (entry && entry->NumberOfSuperClasses)
00868           {
00869           for (i = 0; i+1 < entry->NumberOfSuperClasses; i++)
00870             {
00871             if (scope_needs_free) { free((char *)scope); }
00872             scope = vtkParseHierarchy_ExpandTypedefsInName(
00873               info, entry->SuperClasses[i], NULL);
00874             scope_needs_free = (scope != entry->SuperClasses[i]);
00875             /* recurse if more than one superclass */
00876             if (vtkParseHierarchy_ExpandTypedefsInValue(info, val, scope))
00877               {
00878               if (scope_needs_free) { free((char *)scope); }
00879               return 1;
00880               }
00881             }
00882           if (scope_needs_free) { free((char *)scope); }
00883           scope = vtkParseHierarchy_ExpandTypedefsInName(
00884             info, entry->SuperClasses[i], NULL);
00885           scope_needs_free = (scope != entry->SuperClasses[i]);
00886           }
00887         entry = 0;
00888         }
00889       }
00890 
00891     /* if not found, try again with no scope */
00892     if (entry == 0)
00893       {
00894       entry = vtkParseHierarchy_FindEntry(info, val->Class);
00895       }
00896 
00897     if (entry && entry->IsTypedef)
00898       {
00899       vtkParse_ExpandTypedef(val, entry->Typedef);
00900       }
00901     else if (entry)
00902       {
00903       newclass = vtkParseHierarchy_ExpandTypedefsInName(
00904          info, val->Class, scope);
00905       if (newclass != val->Class)
00906         {
00907         val->Class = vtkParse_DuplicateString(newclass, strlen(newclass));
00908         free((char *)newclass);
00909         }
00910       result = 1;
00911       break;
00912       }
00913     else
00914       {
00915       result = 0;
00916       break;
00917       }
00918     }
00919 
00920   if (scope_needs_free) { free((char *)scope); }
00921 
00922   return result;
00923 }
00924 
00925 /* Expand typedefs found in an expression stored as a string.
00926  * The value of "text" will be returned if no expansion occurred,
00927  * else a new string is returned that must be freed with "free()". */
00928 const char *vtkParseHierarchy_ExpandTypedefsInName(
00929   const HierarchyInfo *info, const char *name, const char *scope)
00930 {
00931   char text[128];
00932   char *cp;
00933   size_t n, m;
00934   const char *newname = name;
00935   HierarchyEntry *entry = NULL;
00936 
00937   /* note: unlike ExpandTypedefsInValue, this does not yet recurse
00938    * or look in superclass scopes */
00939 
00940   /* doesn't yet handle names that are scoped or templated */
00941   m = vtkParse_IdentifierLength(name);
00942   if (name[m] != '\0')
00943     {
00944     return name;
00945     }
00946 
00947   if (scope)
00948     {
00949     cp = text;
00950     n = strlen(scope);
00951     m = strlen(name);
00952     /* only malloc if more than 128 chars needed */
00953     if (n + m + 2 >= 128)
00954       {
00955       cp = (char *)malloc(n+m+3);
00956       }
00957 
00958     /* scope the name */
00959     strncpy(cp, scope, n);
00960     cp[n++] = ':';
00961     cp[n++] = ':';
00962     strncpy(&cp[n], name, m);
00963     cp[n+m] = '\0';
00964 
00965     entry = vtkParseHierarchy_FindEntry(info, cp);
00966 
00967     if (cp != text) { free(cp); }
00968     }
00969 
00970   if (!entry)
00971     {
00972     entry = vtkParseHierarchy_FindEntry(info, name);
00973     }
00974 
00975   newname = NULL;
00976   if (entry && entry->IsTypedef && entry->Typedef->Class)
00977     {
00978     newname = entry->Typedef->Class;
00979     }
00980   if (newname)
00981     {
00982     cp = (char *)malloc(strlen(newname) + 1);
00983     strcpy(cp, newname);
00984     name = cp;
00985     }
00986 
00987   return name;
00988 }