Viewing: yaml-event-dump.c
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2023 James Simmons <jsimmons@infradead.org>
*
* Writing libyaml C code can be very difficult to get right. So I wrote
* this application that takes a YAML file and creates pseudo user land
* libyaml C code. This will speed up development greatly. Note its not
* 100% promised that the YAML config file that works with the libyaml
* is valid. Please always test your YAML file with http://www.yamllint.com
*
* To build this application just run : gcc -lyaml yaml-event-dump.c
*
* This application just takes one argument which is the file path to
* the YAML config file. Example ./a.out lnet.conf
*
* Once you run this application against the YAML config file you will
* see C libyaml pseudocode that using the libyaml API will build
* a proper YAML document. You can then cut and paste the C code
* ouput to your C function, thus saving time. At the end of the
* pseudo code we also prints out the YAML document in the style
* of the libyaml API.
*/
#include <errno.h>
#include <yaml.h>
int main(int argc, char **argv)
{
yaml_emitter_t output;
yaml_parser_t setup;
yaml_event_t event;
FILE *file;
int i = 1;
int rc;
if (argc != 2) {
fprintf(stderr, "usage: %s /path/to/yaml.conf\n", argv[0]);
return -1;
}
file = fopen(argv[1], "r");
if (!file)
return -errno;
/* Initialize configuration parser */
rc = yaml_parser_initialize(&setup);
if (rc == 0)
return -EINVAL;
yaml_parser_set_input_file(&setup, file);
rc = yaml_emitter_initialize(&output);
if (rc == 0)
goto free_results;
yaml_emitter_set_output_file(&output, stdout);
puts("\tyaml_emitter_t request;");
puts("\tyaml_event_t event;\n");
do {
/* Get the next event. */
if (!yaml_parser_parse(&setup, &event))
goto emitter_error;
switch (event.type) {
case YAML_STREAM_START_EVENT:
puts("\tyaml_emitter_open(&request);");
break;
case YAML_DOCUMENT_START_EVENT:
puts("\tyaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);");
puts("\trc = yaml_emitter_emit(&request, &event);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
break;
case YAML_DOCUMENT_END_EVENT:
puts("\tyaml_document_end_event_initialize(&event, 0);");
/* YAML_STREAM_END_EVENT will be next */
puts("\trc = yaml_emitter_close(&request);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
break;
case YAML_ALIAS_EVENT:
break;
case YAML_SCALAR_EVENT: {
char *value = (char *)event.data.scalar.value;
puts("\tyaml_scalar_event_initialize(&event, NULL,");
if (!strlen(value)) {
puts("\t\t\t\t (yaml_char_t *)YAML_NULL_TAG,");
} else if (strcasecmp(value, "yes") == 0 ||
strcasecmp(value, "no") == 0 ||
strcasecmp(value, "true") == 0 ||
strcasecmp(value, "false") == 0 ||
strcasecmp(value, "on") == 0 ||
strcasecmp(value, "off") == 0 ||
strcasecmp(value, "y") == 0 ||
strcasecmp(value, "n") == 0) {
puts("\t\t\t\t (yaml_char_t *)YAML_BOOL_TAG,");
} else if (strspn(value, "0123456789abcdefABCDEF") ==
strlen(value)) {
puts("\t\t\t\t (yaml_char_t *)YAML_INT_TAG,");
} else {
puts("\t\t\t\t (yaml_char_t *)YAML_STR_TAG,");
}
//printf("\t\t\t\t (yaml_char_t *)\"%s\",\n",
// event.data.scalar.tag);
printf("\t\t\t\t (yaml_char_t *)\"%s\",\n", value);
printf("\t\t\t\t strlen(\"%s\"), 1, 0,\n", value);
switch (event.data.scalar.style) {
case YAML_PLAIN_SCALAR_STYLE:
puts("\t\t\t\t YAML_PLAIN_SCALAR_STYLE);");
break;
case YAML_SINGLE_QUOTED_SCALAR_STYLE:
puts("\t\t\t\t YAML_SINGLE_QUOTED_SCALAR_STYLE);");
break;
case YAML_DOUBLE_QUOTED_SCALAR_STYLE:
puts("\t\t\t\t YAML_DOUBLE_QUOTED_SCALAR_STYLE);");
break;
case YAML_LITERAL_SCALAR_STYLE:
puts("\t\t\t\t YAML_LITERAL_SCALAR_STYLE);");
break;
case YAML_FOLDED_SCALAR_STYLE:
puts("\t\t\t\t YAML_FOLDER_SCALAR_STYLE);");
break;
case YAML_ANY_SCALAR_STYLE:
default:
puts("\t\t\t\t YAML_ANY_SCALAR_STYLE);");
break;
}
puts("\trc = yaml_emitter_emit(&request, &event);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
}
break;
case YAML_SEQUENCE_START_EVENT:
puts("\tyaml_sequence_start_event_initialize(&event, NULL,");
puts("\t\t\t\t\t (yaml_char_t *)YAML_SEQ_TAG,");
printf("\t\t\t\t\t 1, %s);\n",
(event.data.sequence_start.style == YAML_BLOCK_SEQUENCE_STYLE) ?
"YAML_BLOCK_SEQUENCE_STYLE" : "YAML_FLOW_SEQUENCE_STYLE");
puts("\trc = yaml_emitter_emit(&request, &event);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
break;
case YAML_SEQUENCE_END_EVENT:
puts("\tyaml_sequence_end_event_initialize(&event);");
puts("\trc = yaml_emitter_emit(&request, &event);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
break;
case YAML_MAPPING_START_EVENT:
puts("\tyaml_mapping_start_event_initialize(&event, NULL,");
puts("\t\t\t\t\t (yaml_char_t *)YAML_MAP_TAG,"),
printf("\t\t\t\t\t 1, %s);\n",
(event.data.mapping_start.style == YAML_BLOCK_MAPPING_STYLE) ?
"YAML_BLOCK_MAPPING_STYLE" : "YAML_FLOW_MAPPING_STYLE");
puts("\trc = yaml_emitter_emit(&request, &event);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
break;
case YAML_MAPPING_END_EVENT:
puts("\tyaml_mapping_end_event_initialize(&event);");
puts("\trc = yaml_emitter_emit(&request, &event);");
puts("\tif (rc == 0)");
puts("\t\tgoto emitter_error;");
puts("");
default:
break;
}
/* Emit the event. */
if (!yaml_emitter_emit(&output, &event))
goto emitter_error;
} while (event.type != YAML_STREAM_END_EVENT);
rc = yaml_emitter_flush(&output);
if (rc == 0)
fprintf(stderr, "dump failed\n");
emitter_error:
yaml_emitter_delete(&output);
free_results:
yaml_parser_delete(&setup);
return 0;
}