yaml_parser.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #include <string.h>
  2. #include <yaml.h>
  3. #include <regex.h>
  4. #include "yaml_parser.h"
  5. void parse_yaml(FILE* fp, hoedown_latex_title_data *td) {
  6. yaml_parser_t parser;
  7. if(!yaml_parser_initialize(&parser)) {
  8. fputs("Failed to initialize parser!\n", stderr);
  9. return;
  10. }
  11. if(fp) {
  12. yaml_parser_set_input_file(&parser, fp);
  13. } else {
  14. fprintf(stderr, "No input detected.\n");
  15. exit(1);
  16. }
  17. token_t state = key;
  18. bool end_yaml_frontmatter = false;
  19. yaml_token_t token;
  20. bool valid_field = false;
  21. do {
  22. char **datap;
  23. char *tok;
  24. yaml_parser_scan(&parser, &token);
  25. if(&token) {
  26. switch (token.type) {
  27. case YAML_KEY_TOKEN:
  28. state = key;
  29. break;
  30. case YAML_VALUE_TOKEN:
  31. state = value;
  32. break;
  33. case YAML_SCALAR_TOKEN:
  34. tok = token.data.scalar.value;
  35. if (state == key) {
  36. if (!strcmp(tok, "title")) {
  37. valid_field = true;
  38. datap = &(td->title);
  39. } else if (!strcmp(tok, "author")) {
  40. valid_field = true;
  41. datap = &(td->author);
  42. } else if (!strcmp(tok, "date")) {
  43. valid_field = true;
  44. td->date_given = true;
  45. datap = &(td->date);
  46. } else {
  47. valid_field = false;
  48. }
  49. } else {
  50. if(valid_field) {
  51. *datap = strdup(tok);
  52. }
  53. }
  54. break;
  55. case YAML_BLOCK_END_TOKEN:
  56. end_yaml_frontmatter = true;
  57. break;
  58. default:
  59. break;
  60. }
  61. }
  62. yaml_token_delete(&token);
  63. } while(!end_yaml_frontmatter);
  64. yaml_parser_delete(&parser);
  65. }
  66. yaml_block* tangle_yaml(FILE* src) {
  67. char msgbuf[100];
  68. const char* tomatch = "---";
  69. regex_t* yaml_block_delim = (regex_t*)malloc(sizeof(regex_t));
  70. if(!yaml_block_delim) {
  71. fprintf(stderr, "Failed to allocate memory for yaml block delimiter regex.\n");
  72. return NULL;
  73. }
  74. if(regcomp(yaml_block_delim, tomatch, 0) != 0) {
  75. fprintf(stderr, "Failed to compile regex '%s' for detecting yaml blocks.\n", tomatch);
  76. return NULL;
  77. }
  78. char line[IUNIT];
  79. if(fgets(line, 8, src) == NULL) {
  80. return NULL; // EOF
  81. }
  82. yaml_block* yaml = (yaml_block*)malloc(sizeof(yaml_block));
  83. if(!yaml) {
  84. fprintf(stderr, "Failed to allocate memory for yaml block.\n");
  85. return NULL;
  86. }
  87. yaml->length = 0;
  88. yaml->data = (char*)malloc(sizeof(line)+1);
  89. if(!yaml->data) {
  90. fprintf(stderr, "Failed to allocate memory for yaml data.\n");
  91. return NULL;
  92. }
  93. if(regexec(yaml_block_delim, line, 0, NULL, 0) == 0) { // Test for yaml
  94. yaml->length += strlen(line);
  95. yaml->data = (char*)realloc(yaml->data, yaml->length);
  96. if(!yaml->data) {
  97. fprintf(stderr, "Failed to allocate memory for yaml data.\n");
  98. return NULL;
  99. }
  100. strcpy(yaml->data, line);
  101. if(fgets(line, IUNIT, src) == NULL) {
  102. regfree(yaml_block_delim);
  103. return NULL; // EOF
  104. }
  105. while(regexec(yaml_block_delim, line, 0, NULL, 0) != 0) {
  106. yaml->length += strlen(line);
  107. yaml->data = (char*)realloc(yaml->data, yaml->length);
  108. if(!yaml->data) {
  109. fprintf(stderr, "Failed to allocate memory for yaml data.\n");
  110. return NULL;
  111. }
  112. strcat(yaml->data, line);
  113. if(fgets(line, IUNIT, src) == NULL) {
  114. regfree(yaml_block_delim);
  115. return NULL; // EOF
  116. }
  117. }
  118. yaml->length += strlen(line);
  119. yaml->data = (char*)realloc(yaml->data, yaml->length);
  120. if(!yaml->data) {
  121. fprintf(stderr, "Failed to allocate memory for yaml data.\n");
  122. return NULL;
  123. }
  124. strcat(yaml->data, line);
  125. }
  126. regfree(yaml_block_delim);
  127. return yaml;
  128. }