/src/sys/yaml/yamlimpls.c

https://bitbucket.org/alexei-matveev/petsc-debian-pkg · C · 780 lines · 706 code · 41 blank · 33 comment · 216 complexity · 38f229483e7178d52d0c92b83aae1ce7 MD5 · raw file

  1. #include "yamlimpls.h"
  2. void options_list_delete(options_list_t *options_list) {
  3. int i, j;
  4. for(i=0; i<(*options_list).count; i++)
  5. {
  6. for(j=0; j<(*options_list).options[i].arguments.count; j++) {
  7. if((*options_list).options[i].arguments.args[j]) {
  8. free((*options_list).options[i].arguments.args[j]);
  9. }
  10. }
  11. if((*options_list).options[i].arguments.args) {
  12. free((*options_list).options[i].arguments.args);
  13. }
  14. if((*options_list).options[i].name) {
  15. free((*options_list).options[i].name);
  16. }
  17. if((*options_list).options[i].group) {
  18. free((*options_list).options[i].group);
  19. }
  20. }
  21. if((*options_list).options) {
  22. free((*options_list).options);
  23. }
  24. }
  25. int options_list_populate_yaml(char *str, options_list_t *options_list) {
  26. yaml_parser_t parser;
  27. yaml_event_t event, *events=0;
  28. int i, j, k, ii; /* generic counters */
  29. int alias_count, events_length, sequence_stack, mapping_stack, mapping_end_index;; /* named counters */
  30. alias_list_t list;
  31. grouping_stack_t grouping_stack;
  32. const int MAX_NESTED_GROUPS = 10;
  33. /* This can be edited later as needed, this is for memory allocation purposes for the grouping_stack */
  34. /* Initialize objects and check for errors. */
  35. if (!yaml_parser_initialize(&parser)) {
  36. fprintf(stderr, "Failed to initialize parser. (%s:%d)\n", __FILE__, __LINE__-1);
  37. return 0;
  38. }
  39. yaml_parser_set_input_string(&parser, (unsigned char*) str, strlen(str));
  40. /* Counting things for memory allocation purposes */
  41. if(!yaml_parser_parse(&parser, &event)) {
  42. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  43. return 0;
  44. }
  45. i=0;
  46. while(event.type != YAML_STREAM_END_EVENT) {
  47. if(event.type == YAML_DOCUMENT_START_EVENT) {
  48. yaml_event_delete(&event);
  49. if(!yaml_parser_parse(&parser, &event)) {
  50. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  51. return 0;
  52. }
  53. if(event.type == YAML_MAPPING_START_EVENT) {
  54. yaml_event_delete(&event);
  55. if(!yaml_parser_parse(&parser, &event)) {
  56. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  57. return 0;
  58. }
  59. if(event.type == YAML_SCALAR_EVENT) {
  60. if(strcmp((char*) event.data.scalar.value, "Options") == 0
  61. || strcmp((char*) event.data.scalar.value, "options") == 0) {
  62. i=3;alias_count=0;
  63. while(event.type != YAML_DOCUMENT_END_EVENT) {
  64. yaml_event_delete(&event);
  65. if(!yaml_parser_parse(&parser, &event)) {
  66. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  67. return 0;
  68. }
  69. i++;
  70. }
  71. }
  72. }
  73. }
  74. }
  75. yaml_event_delete(&event);
  76. if(!yaml_parser_parse(&parser, &event)) {
  77. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  78. return 0;
  79. }
  80. }
  81. yaml_event_delete(&event);
  82. yaml_parser_delete(&parser);
  83. /* Populating the alias list. */
  84. if(!alias_list_populate_yaml(str, &list)) {
  85. fprintf(stderr, "error alias_list_populate_yaml (%s:%d)", __FILE__, __LINE__-1);
  86. return 0;
  87. }
  88. /* Allocating memory based on counts from above */
  89. events = (yaml_event_t*) calloc((i+1)*4, sizeof(yaml_event_t));
  90. /* Multiplied by four because I am not counting the alias events this needs to be worked on later */
  91. /* We could overallocate by a lot and realloc once we get the actual number of events in the array later */
  92. /* Time to load the events to an array so I can better play with them */
  93. yaml_parser_initialize(&parser);
  94. yaml_parser_set_input_string(&parser, (unsigned char*) str, strlen(str));
  95. if(!yaml_parser_parse(&parser, &event)) {
  96. fprintf(stderr, "Parser error. (%s:%d)\n", __FILE__, __LINE__-1);
  97. return 0;
  98. }
  99. while(event.type != YAML_STREAM_END_EVENT) {
  100. i=0;j=0;sequence_stack=0;
  101. if(event.type == YAML_DOCUMENT_START_EVENT) {
  102. if(!yaml_event_initialize(&events[i], &event)) {
  103. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n",__FILE__,__LINE__-1);
  104. return 0;
  105. }
  106. yaml_event_delete(&event);
  107. if(!yaml_parser_parse(&parser, &event)) {
  108. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  109. return 0;
  110. }
  111. i++;
  112. if(event.type == YAML_MAPPING_START_EVENT) {
  113. if(!yaml_event_initialize(&events[i], &event)) {
  114. fprintf(stderr, "error, yamL_event_initialize (%s:%d)\n", __FILE__, __LINE__);
  115. return 0;
  116. }
  117. yaml_event_delete(&event);
  118. if(!yaml_parser_parse(&parser, &event)) {
  119. fprintf(stderr, "Parser error. (%s:%d)\n", __FILE__, __LINE__-1);
  120. return 0;
  121. }
  122. i++;
  123. if(event.type == YAML_SCALAR_EVENT) {
  124. if(!yaml_event_initialize(&events[i], &event)) {
  125. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  126. return 0;
  127. }
  128. i++;
  129. if(strcmp((char*) event.data.scalar.value, "options") == 0
  130. || strcmp((char*) event.data.scalar.value, "Options") == 0) {
  131. yaml_event_delete(&event);
  132. if(!yaml_parser_parse(&parser, &event)) {
  133. fprintf(stderr, "Parser error. (%s:%d)\n", __FILE__, __LINE__-1);
  134. return 0;
  135. }
  136. while(event.type != YAML_DOCUMENT_END_EVENT) {
  137. switch(event.type) {
  138. case YAML_ALIAS_EVENT:
  139. /* Copy all of the alias event info from the alias list */
  140. for(j=0; j<list.count; j++) {
  141. if(strcmp(list.list[j].alias, (char*) event.data.alias.anchor) == 0) {
  142. if(!yaml_event_initialize(&events[i], &list.list[j].event)) {
  143. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  144. return 0;
  145. }
  146. i++;
  147. }
  148. }
  149. break;
  150. default:
  151. yaml_event_initialize(&events[i], &event);
  152. i++;
  153. break;
  154. }
  155. yaml_event_delete(&event);
  156. if(!yaml_parser_parse(&parser, &event)) {
  157. fprintf(stderr, "Parser error. (%s:%d)\n", __FILE__, __LINE__-1);
  158. return 0;
  159. }
  160. if(event.type == YAML_DOCUMENT_END_EVENT) {
  161. if(!yaml_event_initialize(&events[i], &event)) {
  162. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  163. return 0;
  164. }
  165. i++;
  166. }
  167. }
  168. events_length = i;
  169. break;
  170. } else {
  171. for(i--; i>=0; i--) {
  172. yaml_event_delete(&events[i]);
  173. }
  174. }
  175. } else {
  176. for(i--; i>=0; i--) {
  177. yaml_event_delete(&events[i]);
  178. }
  179. }
  180. } else {
  181. for(i--; i>=0; i--) {
  182. yaml_event_delete(&events[i]);
  183. }
  184. }
  185. }
  186. yaml_event_delete(&event);
  187. if(!yaml_parser_parse(&parser, &event)) {
  188. fprintf(stderr, "Parser error. (%s:%d)", __FILE__, __LINE__-1);
  189. return 0;
  190. }
  191. }
  192. yaml_event_delete(&event);
  193. yaml_parser_delete(&parser);
  194. alias_list_delete(&list);
  195. /* Making sure the last block of code ran properly and my config file was written properly */
  196. if(events[0].type != YAML_DOCUMENT_START_EVENT
  197. || events[1].type != YAML_MAPPING_START_EVENT
  198. || events[2].type != YAML_SCALAR_EVENT
  199. ||(strcmp((char*) events[2].data.scalar.value, "options") != 0
  200. && strcmp((char*) events[2].data.scalar.value, "Options") != 0)
  201. || events[3].type != YAML_SEQUENCE_START_EVENT) {
  202. fprintf(stderr, "Events did not load properly. (%s:%d)\n", __FILE__, __LINE__);
  203. return 0;
  204. }
  205. for(i=0; i<events_length; i++) {
  206. if(events[i].type == YAML_NO_EVENT) {
  207. fprintf(stderr, "Events did not load properly. (%s:%d)\n", __FILE__, __LINE__);
  208. return 0;
  209. }
  210. }
  211. /* Getting the number of options */
  212. j=0;
  213. for(i=0; i<events_length; i++) {
  214. if(events[i].type == YAML_MAPPING_START_EVENT
  215. && events[i+1].type == YAML_SCALAR_EVENT
  216. &&(events[i+2].type == YAML_SCALAR_EVENT
  217. ||(events[i+2].type == YAML_SEQUENCE_START_EVENT
  218. && events[i+3].type == YAML_SCALAR_EVENT))) {
  219. j++;
  220. }
  221. }
  222. (*options_list).count = j;
  223. /* Allocating memory for the options_list options */
  224. (*options_list).options = (option_t*) calloc((*options_list).count+30, sizeof(option_t));
  225. /* Time to populate the options_list */
  226. /* Start out by putting a fork in the garbage disposal */
  227. /* Set up the grouping stack before use */
  228. grouping_stack.count = 0;
  229. grouping_stack.groups = (grouping_stack_group_t*) calloc(MAX_NESTED_GROUPS, sizeof(grouping_stack_group_t));
  230. for(i=0; i<MAX_NESTED_GROUPS; i++) {
  231. grouping_stack.groups[i].name = 0;
  232. grouping_stack.groups[i].start = 0;
  233. grouping_stack.groups[i].end = 0;
  234. }
  235. grouping_stack.groups[0].name = (char*) calloc(8, sizeof(char));
  236. strcpy(grouping_stack.groups[0].name, "default");
  237. grouping_stack.groups[0].start = 0;
  238. grouping_stack.groups[0].end = 0;
  239. grouping_stack.count = 1;
  240. j=0; mapping_end_index = 0;
  241. for(i=3; i<events_length; i++) {
  242. if(grouping_stack.groups[grouping_stack.count-1].end == i) {
  243. if(grouping_stack.groups[grouping_stack.count-1].name) {
  244. free(grouping_stack.groups[grouping_stack.count-1].name);
  245. grouping_stack.groups[grouping_stack.count-1].name = 0;
  246. }
  247. grouping_stack.groups[grouping_stack.count-1].end = 0;
  248. grouping_stack.groups[grouping_stack.count-1].start = 0;
  249. grouping_stack.count--;
  250. if(grouping_stack.count == 0) {
  251. grouping_stack.count = 1;
  252. grouping_stack.groups[0].name = (char*) calloc(8, sizeof(char));
  253. strcpy(grouping_stack.groups[0].name, "default");
  254. grouping_stack.groups[0].start = 0;
  255. grouping_stack.groups[0].end = 0;
  256. }
  257. }
  258. if(events[i].type == YAML_MAPPING_START_EVENT
  259. && events[i+1].type == YAML_SCALAR_EVENT) {
  260. if(events[i+2].type == YAML_SCALAR_EVENT
  261. && events[i+3].type == YAML_MAPPING_END_EVENT) {
  262. /* We have an option with only one arg */
  263. ii=0;
  264. for(k=0; k<grouping_stack.count; k++) {
  265. if(grouping_stack.groups[k].name) {
  266. ii+=strlen(grouping_stack.groups[k].name);
  267. }
  268. }
  269. (*options_list).options[j].name = (char*) calloc(events[i+1].data.scalar.length+1, sizeof(char));
  270. strcpy((*options_list).options[j].name, (char*)events[i+1].data.scalar.value);
  271. (*options_list).options[j].group = (char*) calloc(ii + grouping_stack.count, sizeof(char));
  272. strcpy((*options_list).options[j].group, grouping_stack.groups[0].name);
  273. for(k=1; k<grouping_stack.count; k++) {
  274. strcat((*options_list).options[j].group, "_");
  275. strcat((*options_list).options[j].group, grouping_stack.groups[k].name);
  276. }
  277. (*options_list).options[j].arguments.count = 1;
  278. (*options_list).options[j].arguments.args = (char**) calloc(
  279. (*options_list).options[j].arguments.count+1, sizeof(char*));
  280. (*options_list).options[j].arguments.args[0] = (char*) calloc(
  281. events[i+2].data.scalar.length+1, sizeof(char));
  282. strcpy((*options_list).options[j].arguments.args[0], (char*) events[i+2].data.scalar.value);
  283. j++;i+=2;
  284. } else if(events[i+2].type == YAML_SEQUENCE_START_EVENT) {
  285. if(events[i+3].type == YAML_SCALAR_EVENT) {
  286. /* We have an option that has a sequence of args */
  287. /* First lets do what we can before performing a count of the args */
  288. ii=0;
  289. for(k=0; k<grouping_stack.count; k++) {
  290. if(grouping_stack.groups[k].name) {
  291. ii+=strlen(grouping_stack.groups[k].name);
  292. }
  293. }
  294. (*options_list).options[j].name = (char*) calloc(events[i+1].data.scalar.length+1, sizeof(char));
  295. strcpy((*options_list).options[j].name, (char*) events[i+1].data.scalar.value);
  296. (*options_list).options[j].group = (char*) calloc(ii + grouping_stack.count, sizeof(char));
  297. strcpy((*options_list).options[j].group, grouping_stack.groups[0].name);
  298. for(k=1; k<grouping_stack.count; k++) {
  299. strcat((*options_list).options[j].group, "_");
  300. strcat((*options_list).options[j].group, grouping_stack.groups[k].name);
  301. }
  302. k=i+2+1;
  303. /* 2+1 for clear thought. i+2 is the first sequence start event, so I will start at i+2+1 */
  304. sequence_stack=1;
  305. (*options_list).options[j].arguments.count = 0;
  306. while(sequence_stack != 0) {
  307. switch(events[k].type) {
  308. case YAML_SEQUENCE_START_EVENT:
  309. sequence_stack++;
  310. break;
  311. case YAML_SEQUENCE_END_EVENT:
  312. sequence_stack--;
  313. break;
  314. case YAML_SCALAR_EVENT:
  315. if(sequence_stack == 1) {
  316. (*options_list).options[j].arguments.count++;
  317. }
  318. break;
  319. default: break;
  320. }
  321. k++;
  322. }
  323. (*options_list).options[j].arguments.args = (char**) calloc(
  324. (*options_list).options[j].arguments.count+1, sizeof(char*));
  325. for(ii=i+2+1; ii < k; ii++) {
  326. if(events[ii].type == YAML_SCALAR_EVENT) {
  327. (*options_list).options[j].arguments.args[ii-i-2-1] = (char*) calloc(
  328. events[ii].data.scalar.length+1, sizeof(char));
  329. strcpy((*options_list).options[j].arguments.args[ii-i-2-1],
  330. (char*) events[ii].data.scalar.value);
  331. }
  332. }
  333. j++;
  334. } else if(events[i+3].type == YAML_MAPPING_START_EVENT) {
  335. /* We have a group of options coming up. */
  336. if(grouping_stack.count == 1 && strcmp(grouping_stack.groups[0].name, "default") == 0) {
  337. grouping_stack.count--;
  338. }
  339. if(grouping_stack.groups[grouping_stack.count].name) {
  340. free(grouping_stack.groups[grouping_stack.count].name);
  341. grouping_stack.groups[grouping_stack.count].name = 0;
  342. }
  343. grouping_stack.groups[grouping_stack.count].name = (char*) calloc(
  344. events[i+1].data.scalar.length+1, sizeof(char));
  345. strcpy(grouping_stack.groups[grouping_stack.count].name, (char*) events[i+1].data.scalar.value);
  346. grouping_stack.groups[grouping_stack.count].start = i+3;
  347. k=i+1;
  348. mapping_stack=1;
  349. while(mapping_stack!=0) {
  350. switch(events[k].type) {
  351. case YAML_MAPPING_START_EVENT:
  352. mapping_stack++;
  353. break;
  354. case YAML_MAPPING_END_EVENT:
  355. mapping_stack--;
  356. break;
  357. default: break;
  358. }
  359. k++;
  360. }
  361. mapping_end_index = k-1;
  362. grouping_stack.groups[grouping_stack.count].end = k-1;
  363. grouping_stack.count++;
  364. i+=2;
  365. }
  366. }
  367. }
  368. }
  369. /* Cleanup */
  370. for(i=0; i<MAX_NESTED_GROUPS; i++) {
  371. if(grouping_stack.groups[i].name) free(grouping_stack.groups[i].name);
  372. }
  373. if(grouping_stack.groups) free(grouping_stack.groups);
  374. for(i=0; i<events_length; i++) {
  375. yaml_event_delete(&events[i]);
  376. }
  377. if(events) free(events);
  378. return 1;
  379. }
  380. int yaml_event_initialize(yaml_event_t *out, yaml_event_t *in) {
  381. switch((*in).type) {
  382. case YAML_STREAM_START_EVENT:
  383. if(!yaml_stream_start_event_initialize(&(*out), (*in).data.stream_start.encoding)) {
  384. fprintf(stderr, "error yaml_stream_start_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  385. return 0;
  386. }
  387. break;
  388. case YAML_STREAM_END_EVENT:
  389. if(!yaml_stream_end_event_initialize(&(*out))) {
  390. fprintf(stderr, "error yaml_stream_end_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  391. return 0;
  392. }
  393. break;
  394. case YAML_DOCUMENT_START_EVENT:
  395. if(!yaml_document_start_event_initialize(&(*out), (*in).data.document_start.version_directive,
  396. (*in).data.document_start.tag_directives.start, (*in).data.document_start.tag_directives.end,
  397. (*in).data.document_start.implicit)) {
  398. fprintf(stderr, "error yaml_document_start_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  399. return 0;
  400. }
  401. break;
  402. case YAML_DOCUMENT_END_EVENT:
  403. if(!yaml_document_end_event_initialize(&(*out), (*in).data.document_end.implicit)) {
  404. fprintf(stderr, "error yaml_document_end_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  405. return 0;
  406. }
  407. break;
  408. case YAML_ALIAS_EVENT:
  409. if(!yaml_alias_event_initialize(&(*out), (*in).data.alias.anchor)) {
  410. fprintf(stderr, "error yaml_alias_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  411. return 0;
  412. }
  413. break;
  414. case YAML_SCALAR_EVENT:
  415. if(!yaml_scalar_event_initialize(&(*out), (*in).data.scalar.anchor,
  416. (*in).data.scalar.tag, (*in).data.scalar.value, (*in).data.scalar.length,
  417. (*in).data.scalar.plain_implicit, (*in).data.scalar.quoted_implicit,
  418. (*in).data.scalar.style)) {
  419. fprintf(stderr, "error yaml_scalar_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  420. return 0;
  421. }
  422. break;
  423. case YAML_SEQUENCE_START_EVENT:
  424. if(!yaml_sequence_start_event_initialize(&(*out), (*in).data.sequence_start.anchor,
  425. (*in).data.sequence_start.tag, (*in).data.sequence_start.implicit,
  426. (*in).data.sequence_start.style)) {
  427. fprintf(stderr, "error yaml_sequence_start_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  428. return 0;
  429. }
  430. break;
  431. case YAML_SEQUENCE_END_EVENT:
  432. if(!yaml_sequence_end_event_initialize(&(*out))) {
  433. fprintf(stderr, "error yaml_sequence_end_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  434. return 0;
  435. }
  436. break;
  437. case YAML_MAPPING_START_EVENT:
  438. if(!yaml_mapping_start_event_initialize(&(*out), (*in).data.mapping_start.anchor,
  439. (*in).data.mapping_start.tag, (*in).data.mapping_start.implicit,
  440. (*in).data.mapping_start.style)) {
  441. fprintf(stderr, "error yaml_mapping_start_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  442. return 0;
  443. }
  444. break;
  445. case YAML_MAPPING_END_EVENT:
  446. if(!yaml_mapping_end_event_initialize(&(*out))) {
  447. fprintf(stderr, "error yaml_mapping_end_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  448. return 0;
  449. }
  450. break;
  451. default:
  452. fprintf(stderr, "unexpected event (%s:%d)\n", __FILE__, __LINE__);
  453. return 0;
  454. break;
  455. }
  456. return 1;
  457. }
  458. int alias_list_populate_yaml(char *str, alias_list_t *list) {
  459. yaml_parser_t parser;
  460. yaml_event_t event, *events=0;
  461. int i, j, k, stacknumber, events_length;
  462. if(!yaml_parser_initialize(&parser)) {
  463. fprintf(stderr, "error initializing parser (%s:%d)\n", __FILE__, __LINE__-1);
  464. return 0;
  465. }
  466. yaml_parser_set_input_string(&parser, (unsigned char*) str, strlen(str));
  467. /* Getting count to allocate memory for the events array. */
  468. i=0;
  469. if(!yaml_parser_parse(&parser, &event)) {
  470. fprintf(stderr, "error yaml_parser_parse (%s:%d)\n", __FILE__, __LINE__-1);
  471. return 0;
  472. }
  473. while(event.type != YAML_STREAM_END_EVENT) {
  474. i++;
  475. yaml_event_delete(&event);
  476. if(!yaml_parser_parse(&parser, &event)) {
  477. fprintf(stderr, "error yaml_parser_parse (%s:%d)\n", __FILE__, __LINE__-1);
  478. return 0;
  479. }
  480. }
  481. events_length = i;
  482. yaml_event_delete(&event);
  483. yaml_parser_delete(&parser);
  484. /* Allocate memory for the events array */
  485. events = (yaml_event_t*) calloc(events_length+1, sizeof(yaml_event_t));
  486. /* Now to copy everything to the events array */
  487. yaml_parser_initialize(&parser);
  488. yaml_parser_set_input_string(&parser, (unsigned char*) str, strlen(str));
  489. for(i=0; i<events_length; i++) {
  490. if(!yaml_parser_parse(&parser, &event)) {
  491. fprintf(stderr, "error yaml_parser_parse (%s:%d)\n", __FILE__, __LINE__-1);
  492. return 0;
  493. }
  494. if(!yaml_event_initialize(&events[i], &event)) {
  495. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  496. return 0;
  497. }
  498. yaml_event_delete(&event);
  499. }
  500. yaml_parser_delete(&parser);
  501. /* Lets count so I can later allocate memory for the alias list */
  502. stacknumber = 0;
  503. (*list).count = 0;
  504. for(i=0; i<events_length; i++) {
  505. switch(events[i].type) {
  506. case YAML_SCALAR_EVENT:
  507. if(events[i].data.scalar.anchor != NULL) {
  508. (*list).count++;
  509. }
  510. break;
  511. case YAML_SEQUENCE_START_EVENT:
  512. if(events[i].data.sequence_start.anchor != NULL) {
  513. (*list).count++;
  514. stacknumber = 1;
  515. j=i;j++;
  516. while(stacknumber != 0) {
  517. switch(events[j].type) {
  518. case YAML_SEQUENCE_START_EVENT:
  519. stacknumber++;
  520. break;
  521. case YAML_SEQUENCE_END_EVENT:
  522. stacknumber--;
  523. break;
  524. default: break;
  525. }
  526. j++;
  527. (*list).count++;
  528. }
  529. }
  530. break;
  531. case YAML_MAPPING_START_EVENT:
  532. if(events[i].data.mapping_start.anchor != NULL) {
  533. (*list).count++;
  534. stacknumber = 1;
  535. j=i;j++;
  536. while(stacknumber != 0) {
  537. switch(events[j].type) {
  538. case YAML_MAPPING_START_EVENT:
  539. stacknumber++;
  540. break;
  541. case YAML_MAPPING_END_EVENT:
  542. stacknumber--;
  543. break;
  544. default: break;
  545. }
  546. j++;
  547. (*list).count++;
  548. }
  549. }
  550. break;
  551. default: break;
  552. }
  553. }
  554. /* Lets allocate memory for the alias list */
  555. (*list).list = (alias_key_value_t*) calloc((*list).count+1, sizeof(alias_key_value_t));
  556. /* Now to run through the same algorithm to populate the list */
  557. j=0;
  558. for(i=0; i<events_length; i++) {
  559. switch(events[i].type) {
  560. case YAML_SCALAR_EVENT:
  561. if(events[i].data.scalar.anchor != NULL) {
  562. (*list).list[j].alias = (char*) calloc(
  563. strlen((char*) events[i].data.scalar.anchor)+1, sizeof(char));
  564. strcpy((*list).list[j].alias, (char*) events[i].data.scalar.anchor);
  565. if(!yaml_event_initialize(&(*list).list[j].event, &events[i])) {
  566. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  567. return 0;
  568. }
  569. j++;
  570. }
  571. break;
  572. case YAML_SEQUENCE_START_EVENT:
  573. if(events[i].data.sequence_start.anchor != NULL) {
  574. (*list).list[j].alias = (char*) calloc(
  575. strlen((char*) events[i].data.sequence_start.anchor)+1, sizeof(char));
  576. strcpy((*list).list[j].alias, (char*) events[i].data.sequence_start.anchor);
  577. if(!yaml_event_initialize(&(*list).list[j].event, &events[i])) {
  578. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  579. return 0;
  580. }
  581. stacknumber = 1;
  582. j++;
  583. k=i;k++;
  584. while(stacknumber != 0) {
  585. switch(events[k].type) {
  586. case YAML_SEQUENCE_START_EVENT:
  587. stacknumber++;
  588. break;
  589. case YAML_SEQUENCE_END_EVENT:
  590. stacknumber--;
  591. break;
  592. default: break;
  593. }
  594. (*list).list[j].alias = (char*) calloc(strlen((*list).list[j-1].alias)+1, sizeof(char));
  595. strcpy((*list).list[j].alias, (*list).list[j-1].alias);
  596. if(!yaml_event_initialize(&(*list).list[j].event, &events[k])) {
  597. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  598. return 0;
  599. }
  600. j++;k++;
  601. }
  602. }
  603. break;
  604. case YAML_MAPPING_START_EVENT:
  605. if(events[i].data.mapping_start.anchor != NULL) {
  606. (*list).list[j].alias = (char*) calloc(
  607. strlen((char*) events[i].data.mapping_start.anchor)+1, sizeof(char));
  608. strcpy((*list).list[j].alias, (char*) events[i].data.mapping_start.anchor);
  609. if(!yaml_event_initialize(&(*list).list[j].event, &events[i])) {
  610. fprintf(stderr, "error yaml_event_initialize (%s:%d)\n", __FILE__, __LINE__-1);
  611. return 0;
  612. }
  613. stacknumber = 1;
  614. j++;
  615. k=i;k++;
  616. while(stacknumber != 0) {
  617. switch(events[k].type) {
  618. case YAML_MAPPING_START_EVENT:
  619. stacknumber++;
  620. break;
  621. case YAML_SEQUENCE_END_EVENT:
  622. stacknumber--;
  623. break;
  624. default: break;
  625. }
  626. (*list).list[j].alias = (char*) calloc(strlen((*list).list[j-1].alias)+1, sizeof(char));
  627. strcpy((*list).list[j].alias, (*list).list[j-1].alias);
  628. if(!yaml_event_initialize(&(*list).list[j].event, &events[i])) {
  629. fprintf(stderr, "error yaml_event_initialize(%s:%d)\n", __FILE__, __LINE__-1);
  630. return 0;
  631. }
  632. j++;k++;
  633. }
  634. }
  635. break;
  636. default: break;
  637. }
  638. }
  639. /* Cleanup */
  640. for(i=0; i<events_length; i++) {
  641. yaml_event_delete(&events[i]);
  642. }
  643. if(events) free(events);
  644. return 1;
  645. }
  646. void alias_list_delete(alias_list_t *list) {
  647. int i;
  648. for(i=0; i<(*list).count; i++) {
  649. if((*list).list[i].alias) free((*list).list[i].alias);
  650. yaml_event_delete(&(*list).list[i].event);
  651. }
  652. if((*list).list) free((*list).list);
  653. (*list).count = 0;
  654. }
  655. #undef __FUNCT__
  656. #define __FUNCT__ "file_to_string"
  657. PetscErrorCode file_to_string(char* filename, char** str) {
  658. FILE *fh;
  659. char *line;
  660. PetscErrorCode ierr;
  661. PetscFunctionBegin;
  662. if((*str) != NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"argument: str is not NULL");
  663. fh = fopen(filename, "r");
  664. if(!fh) PetscFunctionReturn(1); /* Return error code , and let calling function decide about the error */
  665. ierr = PetscMalloc(64000*sizeof(char), &line);CHKERRQ(ierr);
  666. ierr = PetscMalloc(128000*sizeof(char), str);CHKERRQ(ierr);
  667. /* might change to dynamically allocate this at a later time */
  668. while(fgets(line, 64000, fh) != NULL) strcat((*str), line);
  669. ierr = PetscFree(line);CHKERRQ(ierr);
  670. if(fh) fclose(fh);
  671. PetscFunctionReturn(0);
  672. }
  673. #undef __FUNCT__
  674. #define __FUNCT__ "PetscOptionsInsertFile_YAML"
  675. PetscErrorCode PetscOptionsInsertFile_YAML(MPI_Comm comm, const char file[], PetscBool require)
  676. {
  677. PetscErrorCode ierr, ierr_file;
  678. options_list_t options_list;
  679. PetscMPIInt rank,cnt=0;
  680. char *vstring = 0, fname[PETSC_MAX_PATH_LEN], *ostring = 0;
  681. size_t i, len;
  682. PetscBool match;
  683. PetscFunctionBegin;
  684. ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr);
  685. if (!rank) {
  686. /* Warning: assume a maximum size for all options in a string */
  687. ierr = PetscMalloc(128000*sizeof(char),&vstring);CHKERRQ(ierr);
  688. vstring[0] = 0;
  689. cnt = 0;
  690. ierr = PetscFixFilename(file,fname);CHKERRQ(ierr);
  691. ierr_file = file_to_string(fname, &ostring);
  692. if (ierr_file && require) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Unable to open YAML Options File %s",fname);
  693. if (ierr_file) PetscFunctionReturn(0);
  694. if (options_list_populate_yaml(ostring,&options_list)) {
  695. ierr = PetscInfo1(0,"Read YAML options file %s\n",file);CHKERRQ(ierr);
  696. for (i=0;i<options_list.count;i++) {
  697. if (options_list.options[i].arguments.count == 1) {
  698. ierr = PetscStrcasecmp(options_list.options[i].arguments.args[0], "false", &match);CHKERRQ(ierr);
  699. if (!match) {
  700. /* The current option has one argument it is not false. Something will have to be copied */
  701. ierr = PetscStrcat(vstring,"-");CHKERRQ(ierr);
  702. ierr = PetscStrcasecmp(options_list.options[i].group, "default", &match);CHKERRQ(ierr);
  703. if (!match) {
  704. /* The current option is not in the default group. The group name and option name needs to be copied. */
  705. ierr = PetscStrcat(vstring,options_list.options[i].group);CHKERRQ(ierr);
  706. ierr = PetscStrcat(vstring,"_");CHKERRQ(ierr);
  707. }
  708. ierr = PetscStrcat(vstring,options_list.options[i].name);CHKERRQ(ierr);
  709. ierr = PetscStrcat(vstring," ");CHKERRQ(ierr);
  710. ierr = PetscStrcasecmp(options_list.options[i].arguments.args[0], "true", &match);CHKERRQ(ierr);
  711. if (!match) {
  712. /*The argument needs to be copied. */
  713. ierr = PetscStrcat(vstring,options_list.options[i].arguments.args[0]);CHKERRQ(ierr);
  714. ierr = PetscStrcat(vstring," ");CHKERRQ(ierr);
  715. }
  716. }
  717. } else {
  718. SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid number of arguments (%s: %s)",options_list.options[i].group,options_list.options[i].name);
  719. }
  720. }
  721. options_list_delete(&options_list);
  722. ierr = PetscStrlen(vstring,&len);CHKERRQ(ierr);
  723. cnt = PetscMPIIntCast(len);CHKERRQ(ierr);
  724. } else if (require) {
  725. SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Unable to process YAML Options File %s",fname);
  726. }
  727. }
  728. ierr = MPI_Bcast(&cnt,1,MPI_INT,0,comm);CHKERRQ(ierr);
  729. if (cnt) {
  730. if (rank) {
  731. ierr = PetscMalloc((cnt+1)*sizeof(char),&vstring);CHKERRQ(ierr);
  732. }
  733. ierr = MPI_Bcast(vstring,cnt,MPI_CHAR,0,comm);CHKERRQ(ierr);
  734. vstring[cnt] = 0;
  735. ierr = PetscOptionsInsertString(vstring);CHKERRQ(ierr);
  736. }
  737. ierr = PetscFree(vstring);CHKERRQ(ierr);
  738. PetscFunctionReturn(0);
  739. }