summaryrefslogtreecommitdiffstats
path: root/tools/lint/yl_opt.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lint/yl_opt.c')
-rw-r--r--tools/lint/yl_opt.c344
1 files changed, 344 insertions, 0 deletions
diff --git a/tools/lint/yl_opt.c b/tools/lint/yl_opt.c
new file mode 100644
index 0000000..7cd855f
--- /dev/null
+++ b/tools/lint/yl_opt.c
@@ -0,0 +1,344 @@
+/**
+ * @file yl_opt.c
+ * @author Adam Piecek <piecek@cesnet.cz>
+ * @brief Settings options for the libyang context.
+ *
+ * Copyright (c) 2020 - 2023 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <getopt.h>
+#include <strings.h>
+
+#include "in.h" /* ly_in_free */
+
+#include "common.h"
+#include "yl_opt.h"
+#include "yl_schema_features.h"
+
+struct cmdline_file *
+fill_cmdline_file(struct ly_set *set, struct ly_in *in, const char *path, LYD_FORMAT format)
+{
+ struct cmdline_file *rec;
+
+ rec = malloc(sizeof *rec);
+ if (!rec) {
+ YLMSG_E("Allocating memory for data file information failed.");
+ return NULL;
+ }
+ rec->in = in;
+ rec->path = path;
+ rec->format = format;
+
+ if (set && ly_set_add(set, rec, 1, NULL)) {
+ free(rec);
+ YLMSG_E("Storing data file information failed.");
+ return NULL;
+ }
+
+ return rec;
+}
+
+void
+free_cmdline_file_items(struct cmdline_file *rec)
+{
+ if (rec && rec->in) {
+ ly_in_free(rec->in, 1);
+ }
+}
+
+void
+free_cmdline_file(void *cmdline_file)
+{
+ struct cmdline_file *rec = (struct cmdline_file *)cmdline_file;
+
+ if (rec) {
+ free_cmdline_file_items(rec);
+ free(rec);
+ }
+}
+
+void
+yl_opt_erase(struct yl_opt *yo)
+{
+ ly_bool interactive;
+
+ interactive = yo->interactive;
+
+ /* data */
+ ly_set_erase(&yo->data_inputs, free_cmdline_file);
+ ly_in_free(yo->data_operational.in, 1);
+ ly_set_erase(&yo->data_xpath, NULL);
+
+ /* schema */
+ ly_set_erase(&yo->schema_features, yl_schema_features_free);
+ ly_set_erase(&yo->schema_modules, NULL);
+
+ /* context */
+ free(yo->searchpaths);
+
+ /* --reply-rpc */
+ ly_in_free(yo->reply_rpc.in, 1);
+
+ ly_out_free(yo->out, NULL, yo->out_stdout ? 0 : 1);
+
+ free_cmdline(yo->argv);
+
+ *yo = (const struct yl_opt) {
+ 0
+ };
+ yo->interactive = interactive;
+}
+
+int
+yl_opt_update_schema_out_format(const char *arg, struct yl_opt *yo)
+{
+ if (!strcasecmp(arg, "yang")) {
+ yo->schema_out_format = LYS_OUT_YANG;
+ yo->data_out_format = 0;
+ } else if (!strcasecmp(arg, "yin")) {
+ yo->schema_out_format = LYS_OUT_YIN;
+ yo->data_out_format = 0;
+ } else if (!strcasecmp(arg, "info")) {
+ yo->schema_out_format = LYS_OUT_YANG_COMPILED;
+ yo->data_out_format = 0;
+ } else if (!strcasecmp(arg, "tree")) {
+ yo->schema_out_format = LYS_OUT_TREE;
+ yo->data_out_format = 0;
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+yl_opt_update_data_out_format(const char *arg, struct yl_opt *yo)
+{
+ if (!strcasecmp(arg, "xml")) {
+ yo->schema_out_format = 0;
+ yo->data_out_format = LYD_XML;
+ } else if (!strcasecmp(arg, "json")) {
+ yo->schema_out_format = 0;
+ yo->data_out_format = LYD_JSON;
+ } else if (!strcasecmp(arg, "lyb")) {
+ yo->schema_out_format = 0;
+ yo->data_out_format = LYD_LYB;
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+yl_opt_update_other_out_format(const char *arg, struct yl_opt *yo)
+{
+ if (!strcasecmp(arg, "feature-param")) {
+ yo->feature_param_format = 1;
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+yl_opt_update_out_format(const char *arg, struct yl_opt *yo)
+{
+ if (!yl_opt_update_schema_out_format(arg, yo)) {
+ return 0;
+ }
+ if (!yl_opt_update_data_out_format(arg, yo)) {
+ return 0;
+ }
+ if (!yl_opt_update_other_out_format(arg, yo)) {
+ return 0;
+ }
+
+ YLMSG_E("Unknown output format %s.", arg);
+ return 1;
+}
+
+int
+yl_opt_update_data_type(const char *arg, struct yl_opt *yo)
+{
+ if (!strcasecmp(arg, "config")) {
+ yo->data_parse_options |= LYD_PARSE_NO_STATE;
+ yo->data_validate_options |= LYD_VALIDATE_NO_STATE;
+ } else if (!strcasecmp(arg, "get")) {
+ yo->data_parse_options |= LYD_PARSE_ONLY;
+ } else if (!strcasecmp(arg, "getconfig") || !strcasecmp(arg, "get-config") || !strcasecmp(arg, "edit")) {
+ yo->data_parse_options |= LYD_PARSE_ONLY | LYD_PARSE_NO_STATE;
+ } else if (!strcasecmp(arg, "rpc") || !strcasecmp(arg, "action")) {
+ yo->data_type = LYD_TYPE_RPC_YANG;
+ } else if (!strcasecmp(arg, "nc-rpc")) {
+ yo->data_type = LYD_TYPE_RPC_NETCONF;
+ } else if (!strcasecmp(arg, "reply") || !strcasecmp(arg, "rpcreply")) {
+ yo->data_type = LYD_TYPE_REPLY_YANG;
+ } else if (!strcasecmp(arg, "nc-reply")) {
+ yo->data_type = LYD_TYPE_REPLY_NETCONF;
+ } else if (!strcasecmp(arg, "notif") || !strcasecmp(arg, "notification")) {
+ yo->data_type = LYD_TYPE_NOTIF_YANG;
+ } else if (!strcasecmp(arg, "nc-notif")) {
+ yo->data_type = LYD_TYPE_NOTIF_NETCONF;
+ } else if (!strcasecmp(arg, "data")) {
+ /* default option */
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+yo_opt_update_data_default(const char *arg, struct yl_opt *yo)
+{
+ if (!strcasecmp(arg, "all")) {
+ yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL;
+ } else if (!strcasecmp(arg, "all-tagged")) {
+ yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_ALL_TAG;
+ } else if (!strcasecmp(arg, "trim")) {
+ yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_TRIM;
+ } else if (!strcasecmp(arg, "implicit-tagged")) {
+ yo->data_print_options = (yo->data_print_options & ~LYD_PRINT_WD_MASK) | LYD_PRINT_WD_IMPL_TAG;
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+yo_opt_update_data_in_format(const char *arg, struct yl_opt *yo)
+{
+ if (!strcasecmp(arg, "xml")) {
+ yo->data_in_format = LYD_XML;
+ } else if (!strcasecmp(arg, "json")) {
+ yo->data_in_format = LYD_JSON;
+ } else if (!strcasecmp(arg, "lyb")) {
+ yo->data_in_format = LYD_LYB;
+ } else {
+ return 1;
+ }
+
+ return 0;
+}
+
+void
+yo_opt_update_make_implemented(struct yl_opt *yo)
+{
+ if (yo->ctx_options & LY_CTX_REF_IMPLEMENTED) {
+ yo->ctx_options &= ~LY_CTX_REF_IMPLEMENTED;
+ yo->ctx_options |= LY_CTX_ALL_IMPLEMENTED;
+ } else {
+ yo->ctx_options |= LY_CTX_REF_IMPLEMENTED;
+ }
+}
+
+void
+yo_opt_update_disable_searchdir(struct yl_opt *yo)
+{
+ if (yo->ctx_options & LY_CTX_DISABLE_SEARCHDIR_CWD) {
+ yo->ctx_options &= ~LY_CTX_DISABLE_SEARCHDIR_CWD;
+ yo->ctx_options |= LY_CTX_DISABLE_SEARCHDIRS;
+ } else {
+ yo->ctx_options |= LY_CTX_DISABLE_SEARCHDIR_CWD;
+ }
+}
+
+void
+free_cmdline(char *argv[])
+{
+ if (argv) {
+ free(argv[0]);
+ free(argv);
+ }
+}
+
+int
+parse_cmdline(const char *cmdline, int *argc_p, char **argv_p[])
+{
+ int count;
+ char **vector;
+ char *ptr;
+ char qmark = 0;
+
+ assert(cmdline);
+ assert(argc_p);
+ assert(argv_p);
+
+ /* init */
+ optind = 0; /* reinitialize getopt() */
+ count = 1;
+ vector = malloc((count + 1) * sizeof *vector);
+ vector[0] = strdup(cmdline);
+
+ /* command name */
+ strtok(vector[0], " ");
+
+ /* arguments */
+ while ((ptr = strtok(NULL, " "))) {
+ size_t len;
+ void *r;
+
+ len = strlen(ptr);
+
+ if (qmark) {
+ /* still in quotated text */
+ /* remove NULL termination of the previous token since it is not a token,
+ * but a part of the quotation string */
+ ptr[-1] = ' ';
+
+ if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
+ /* end of quotation */
+ qmark = 0;
+ /* shorten the argument by the terminating quotation mark */
+ ptr[len - 1] = '\0';
+ }
+ continue;
+ }
+
+ /* another token in cmdline */
+ ++count;
+ r = realloc(vector, (count + 1) * sizeof *vector);
+ if (!r) {
+ YLMSG_E("Memory allocation failed (%s:%d, %s).", __FILE__, __LINE__, strerror(errno));
+ free(vector);
+ return -1;
+ }
+ vector = r;
+ vector[count - 1] = ptr;
+
+ if ((ptr[0] == '"') || (ptr[0] == '\'')) {
+ /* remember the quotation mark to identify end of quotation */
+ qmark = ptr[0];
+
+ /* move the remembered argument after the quotation mark */
+ ++vector[count - 1];
+
+ /* check if the quotation is terminated within this token */
+ if ((ptr[len - 1] == qmark) && (ptr[len - 2] != '\\')) {
+ /* end of quotation */
+ qmark = 0;
+ /* shorten the argument by the terminating quotation mark */
+ ptr[len - 1] = '\0';
+ }
+ }
+ }
+ vector[count] = NULL;
+
+ *argc_p = count;
+ *argv_p = vector;
+
+ return 0;
+}