--- /dev/null
+// 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;
+}