PageRenderTime 55ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/Wrapping/vtkParseHierarchy.c

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