Whamcloud - gitweb
LU-9680 contrib: share libyaml C code generator 08/51508/5
authorJames Simmons <jsimmons@infradead.org>
Mon, 24 Jul 2023 16:10:17 +0000 (12:10 -0400)
committerOleg Drokin <green@whamcloud.com>
Tue, 1 Aug 2023 06:12:10 +0000 (06:12 +0000)
Writing proper libyaml C code is not easy. So I wrote an
application that generates the C code to help the developer not
struggle starting from scratch. It wouldn't be a one to one
copy and paste but it greatly helps. The build the application
just do gcc -lyaml yaml-event-dump.c

Test-Parameters: trivial
Change-Id: I1b570dbfc3ea2e6a7ec77b3743aa4cd80aba2acb
Signed-off-by: James Simmons <jsimmons@infradead.org>
Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/51508
Tested-by: jenkins <devops@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Timothy Day <timday@amazon.com>
Reviewed-by: Alex Deiter <alex.deiter@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
contrib/yaml-event-dump.c [new file with mode: 0644]

diff --git a/contrib/yaml-event-dump.c b/contrib/yaml-event-dump.c
new file mode 100644 (file)
index 0000000..780c586
--- /dev/null
@@ -0,0 +1,192 @@
+// 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;
+}