Blame tools/yang2yin/main.c

Packit 8fb591
/**
Packit 8fb591
 * @file main.c
Packit 8fb591
 * @author Michal Vasko <mvasko@cesnet.cz>
Packit 8fb591
 * @brief libyang's yang2yin converter tool
Packit 8fb591
 *
Packit 8fb591
 * Copyright (c) 2016 CESNET, z.s.p.o.
Packit 8fb591
 *
Packit 8fb591
 * This source code is licensed under BSD 3-Clause License (the "License").
Packit 8fb591
 * You may not use this file except in compliance with the License.
Packit 8fb591
 * You may obtain a copy of the License at
Packit 8fb591
 *
Packit 8fb591
 *     https://opensource.org/licenses/BSD-3-Clause
Packit 8fb591
 */
Packit 8fb591
Packit 8fb591
#include <stdio.h>
Packit 8fb591
#include <stdlib.h>
Packit 8fb591
#include <errno.h>
Packit 8fb591
#include <ctype.h>
Packit 8fb591
#include <string.h>
Packit 8fb591
#include <dirent.h>
Packit 8fb591
Packit 8fb591
#define INDENT(x) (x ? " " : "")
Packit 8fb591
#define LEVEL(x) (x * 2)
Packit 8fb591
Packit 8fb591
enum yang_arg {
Packit 8fb591
    Y_NO_ARG,
Packit 8fb591
    Y_IDENTIF_ARG,
Packit 8fb591
    Y_STR_ARG
Packit 8fb591
};
Packit 8fb591
Packit 8fb591
enum yang_token {
Packit 8fb591
    YANG_UNKNOWN = 0,
Packit 8fb591
    YANG_ANYXML,
Packit 8fb591
    YANG_ARGUMENT,
Packit 8fb591
    YANG_AUGMENT,
Packit 8fb591
    YANG_BASE,
Packit 8fb591
    YANG_BELONGS_TO,
Packit 8fb591
    YANG_BIT,
Packit 8fb591
    YANG_CASE,
Packit 8fb591
    YANG_CHOICE,
Packit 8fb591
    YANG_CONFIG,
Packit 8fb591
    YANG_CONTACT,
Packit 8fb591
    YANG_CONTAINER,
Packit 8fb591
    YANG_DEFAULT,
Packit 8fb591
    YANG_DESCRIPTION,
Packit 8fb591
    YANG_DEVIATE,
Packit 8fb591
    YANG_DEVIATION,
Packit 8fb591
    YANG_ENUM,
Packit 8fb591
    YANG_ERROR_APP_TAG,
Packit 8fb591
    YANG_ERROR_MESSAGE,
Packit 8fb591
    YANG_EXTENSION,
Packit 8fb591
    YANG_FEATURE,
Packit 8fb591
    YANG_FRACTION_DIGITS,
Packit 8fb591
    YANG_GROUPING,
Packit 8fb591
    YANG_IDENTITY,
Packit 8fb591
    YANG_IF_FEATURE,
Packit 8fb591
    YANG_IMPORT,
Packit 8fb591
    YANG_INCLUDE,
Packit 8fb591
    YANG_INPUT,
Packit 8fb591
    YANG_KEY,
Packit 8fb591
    YANG_LEAF,
Packit 8fb591
    YANG_LEAF_LIST,
Packit 8fb591
    YANG_LENGTH,
Packit 8fb591
    YANG_LIST,
Packit 8fb591
    YANG_MANDATORY,
Packit 8fb591
    YANG_MAX_ELEMENTS,
Packit 8fb591
    YANG_MIN_ELEMENTS,
Packit 8fb591
    YANG_MODULE,
Packit 8fb591
    YANG_MUST,
Packit 8fb591
    YANG_NAMESPACE,
Packit 8fb591
    YANG_NOTIFICATION,
Packit 8fb591
    YANG_ORDERED_BY,
Packit 8fb591
    YANG_ORGANIZATION,
Packit 8fb591
    YANG_OUTPUT,
Packit 8fb591
    YANG_PATH,
Packit 8fb591
    YANG_PATTERN,
Packit 8fb591
    YANG_POSITION,
Packit 8fb591
    YANG_PREFIX,
Packit 8fb591
    YANG_PRESENCE,
Packit 8fb591
    YANG_RANGE,
Packit 8fb591
    YANG_REFERENCE,
Packit 8fb591
    YANG_REFINE,
Packit 8fb591
    YANG_REQUIRE_INSTANCE,
Packit 8fb591
    YANG_REVISION,
Packit 8fb591
    YANG_REVISION_DATE,
Packit 8fb591
    YANG_RPC,
Packit 8fb591
    YANG_STATUS,
Packit 8fb591
    YANG_SUBMODULE,
Packit 8fb591
    YANG_TYPE,
Packit 8fb591
    YANG_TYPEDEF,
Packit 8fb591
    YANG_UNIQUE,
Packit 8fb591
    YANG_UNITS,
Packit 8fb591
    YANG_USES,
Packit 8fb591
    YANG_VALUE,
Packit 8fb591
    YANG_WHEN,
Packit 8fb591
    YANG_YANG_VERSION,
Packit 8fb591
    YANG_YIN_ELEMENT,
Packit 8fb591
Packit 8fb591
    YANG_SEMICOLON,
Packit 8fb591
    YANG_LEFT_BRACE,
Packit 8fb591
    YANG_RIGHT_BRACE,
Packit 8fb591
    YANG_CUSTOM             /* simple extension with prefix */
Packit 8fb591
};
Packit 8fb591
Packit 8fb591
static const char *
Packit 8fb591
keyword2str(enum yang_token keyword)
Packit 8fb591
{
Packit 8fb591
    switch (keyword) {
Packit 8fb591
    case YANG_ANYXML:
Packit 8fb591
        return "anyxml";
Packit 8fb591
    case YANG_ARGUMENT:
Packit 8fb591
        return "argument";
Packit 8fb591
    case YANG_AUGMENT:
Packit 8fb591
        return "augment";
Packit 8fb591
    case YANG_BASE:
Packit 8fb591
        return "base";
Packit 8fb591
    case YANG_BELONGS_TO:
Packit 8fb591
        return "belongs-to";
Packit 8fb591
    case YANG_BIT:
Packit 8fb591
        return "bit";
Packit 8fb591
    case YANG_CASE:
Packit 8fb591
        return "case";
Packit 8fb591
    case YANG_CHOICE:
Packit 8fb591
        return "choice";
Packit 8fb591
    case YANG_CONFIG:
Packit 8fb591
        return "config";
Packit 8fb591
    case YANG_CONTACT:
Packit 8fb591
        return "contact";
Packit 8fb591
    case YANG_CONTAINER:
Packit 8fb591
        return "container";
Packit 8fb591
    case YANG_DEFAULT:
Packit 8fb591
        return "default";
Packit 8fb591
    case YANG_DESCRIPTION:
Packit 8fb591
        return "description";
Packit 8fb591
    case YANG_DEVIATE:
Packit 8fb591
        return "deviate";
Packit 8fb591
    case YANG_DEVIATION:
Packit 8fb591
        return "deviation";
Packit 8fb591
    case YANG_ENUM:
Packit 8fb591
        return "enum";
Packit 8fb591
    case YANG_ERROR_APP_TAG:
Packit 8fb591
        return "error-app-tag";
Packit 8fb591
    case YANG_ERROR_MESSAGE:
Packit 8fb591
        return "error-message";
Packit 8fb591
    case YANG_EXTENSION:
Packit 8fb591
        return "extension";
Packit 8fb591
    case YANG_FEATURE:
Packit 8fb591
        return "feature";
Packit 8fb591
    case YANG_FRACTION_DIGITS:
Packit 8fb591
        return "fraction-digits";
Packit 8fb591
    case YANG_GROUPING:
Packit 8fb591
        return "grouping";
Packit 8fb591
    case YANG_IDENTITY:
Packit 8fb591
        return "identitiy";
Packit 8fb591
    case YANG_IF_FEATURE:
Packit 8fb591
        return "if-feature";
Packit 8fb591
    case YANG_IMPORT:
Packit 8fb591
        return "import";
Packit 8fb591
    case YANG_INCLUDE:
Packit 8fb591
        return "include";
Packit 8fb591
    case YANG_INPUT:
Packit 8fb591
        return "input";
Packit 8fb591
    case YANG_KEY:
Packit 8fb591
        return "key";
Packit 8fb591
    case YANG_LEAF:
Packit 8fb591
        return "leaf";
Packit 8fb591
    case YANG_LEAF_LIST:
Packit 8fb591
        return "leaf-list";
Packit 8fb591
    case YANG_LENGTH:
Packit 8fb591
        return "length";
Packit 8fb591
    case YANG_LIST:
Packit 8fb591
        return "list";
Packit 8fb591
    case YANG_MANDATORY:
Packit 8fb591
        return "mandatory";
Packit 8fb591
    case YANG_MAX_ELEMENTS:
Packit 8fb591
        return "max-elements";
Packit 8fb591
    case YANG_MIN_ELEMENTS:
Packit 8fb591
        return "min-elements";
Packit 8fb591
    case YANG_MODULE:
Packit 8fb591
        return "module";
Packit 8fb591
    case YANG_MUST:
Packit 8fb591
        return "must";
Packit 8fb591
    case YANG_NAMESPACE:
Packit 8fb591
        return "namespace";
Packit 8fb591
    case YANG_NOTIFICATION:
Packit 8fb591
        return "notification";
Packit 8fb591
    case YANG_ORDERED_BY:
Packit 8fb591
        return "ordered-by";
Packit 8fb591
    case YANG_ORGANIZATION:
Packit 8fb591
        return "organization";
Packit 8fb591
    case YANG_OUTPUT:
Packit 8fb591
        return "output";
Packit 8fb591
    case YANG_PATH:
Packit 8fb591
        return "path";
Packit 8fb591
    case YANG_PATTERN:
Packit 8fb591
        return "pattern";
Packit 8fb591
    case YANG_POSITION:
Packit 8fb591
        return "position";
Packit 8fb591
    case YANG_PREFIX:
Packit 8fb591
        return "prefix";
Packit 8fb591
    case YANG_PRESENCE:
Packit 8fb591
        return "presence";
Packit 8fb591
    case YANG_RANGE:
Packit 8fb591
        return "range";
Packit 8fb591
    case YANG_REFERENCE:
Packit 8fb591
        return "reference";
Packit 8fb591
    case YANG_REFINE:
Packit 8fb591
        return "refine";
Packit 8fb591
    case YANG_REQUIRE_INSTANCE:
Packit 8fb591
        return "require-instance";
Packit 8fb591
    case YANG_REVISION:
Packit 8fb591
        return "revision";
Packit 8fb591
    case YANG_REVISION_DATE:
Packit 8fb591
        return "revision-date";
Packit 8fb591
    case YANG_RPC:
Packit 8fb591
        return "rpc";
Packit 8fb591
    case YANG_STATUS:
Packit 8fb591
        return "status";
Packit 8fb591
    case YANG_SUBMODULE:
Packit 8fb591
        return "submodule";
Packit 8fb591
    case YANG_TYPE:
Packit 8fb591
        return "type";
Packit 8fb591
    case YANG_TYPEDEF:
Packit 8fb591
        return "typedef";
Packit 8fb591
    case YANG_UNIQUE:
Packit 8fb591
        return "unique";
Packit 8fb591
    case YANG_UNITS:
Packit 8fb591
        return "units";
Packit 8fb591
    case YANG_USES:
Packit 8fb591
        return "uses";
Packit 8fb591
    case YANG_VALUE:
Packit 8fb591
        return "value";
Packit 8fb591
    case YANG_WHEN:
Packit 8fb591
        return "when";
Packit 8fb591
    case YANG_YANG_VERSION:
Packit 8fb591
        return "yang-version";
Packit 8fb591
    case YANG_YIN_ELEMENT:
Packit 8fb591
        return "yin-element";
Packit 8fb591
    case YANG_SEMICOLON:
Packit 8fb591
        return ";";
Packit 8fb591
    case YANG_LEFT_BRACE:
Packit 8fb591
        return "{";
Packit 8fb591
    case YANG_RIGHT_BRACE:
Packit 8fb591
        return "}";
Packit 8fb591
    default:
Packit 8fb591
        return "";
Packit 8fb591
    }
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static int
Packit 8fb591
store_char(char c, char **buf, int *buf_len, int *used)
Packit 8fb591
{
Packit 8fb591
    char *new_buf;
Packit 8fb591
Packit 8fb591
    if (*used == *buf_len) {
Packit 8fb591
        *buf_len += 16;
Packit 8fb591
        new_buf = realloc(*buf, *buf_len * sizeof *new_buf);
Packit 8fb591
        if (!new_buf) {
Packit 8fb591
            fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
        *buf = new_buf;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    (*buf)[*used] = c;
Packit 8fb591
    ++(*used);
Packit 8fb591
    return 0;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static FILE *
Packit 8fb591
open_module(const char *name, const char *search_dir)
Packit 8fb591
{
Packit 8fb591
    DIR *dir;
Packit 8fb591
    struct dirent *dirent;
Packit 8fb591
    char *path;
Packit 8fb591
    FILE *ret = NULL;
Packit 8fb591
Packit 8fb591
    dir = opendir(search_dir);
Packit 8fb591
    if (!dir) {
Packit 8fb591
        fprintf(stderr, "Opening the directory \"%s\" failed (%s).\n", search_dir, strerror(errno));
Packit 8fb591
        return NULL;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    while ((dirent = readdir(dir))) {
Packit 8fb591
        if (!strncmp(dirent->d_name, name, strlen(name))
Packit 8fb591
                && ((dirent->d_name[strlen(name)] == '.') || (dirent->d_name[strlen(name)] == '@'))
Packit 8fb591
                && !strcmp(dirent->d_name + strlen(dirent->d_name) - 5, ".yang")) {
Packit 8fb591
            path = malloc(strlen(search_dir) + 1 + strlen(dirent->d_name) + 1);
Packit 8fb591
            if (!path) {
Packit 8fb591
                fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                break;
Packit 8fb591
            }
Packit 8fb591
            sprintf(path, "%s/%s", search_dir, dirent->d_name);
Packit 8fb591
            ret = fopen(path, "r");
Packit 8fb591
            free(path);
Packit 8fb591
Packit 8fb591
            if (!ret) {
Packit 8fb591
                fprintf(stderr, "Opening file \"%s\" failed (%s).\n", dirent->d_name, strerror(errno));
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    closedir(dir);
Packit 8fb591
    return ret;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
/* read another word - character sequence without whitespaces (logs directly)
Packit 8fb591
 * - words are basically YANG tokens
Packit 8fb591
 * - there can be whitespaces if they are a part of string
Packit 8fb591
 * - strings are always returned separately even if not separated by whitespaces
Packit 8fb591
 * - strings are returned without ' or "
Packit 8fb591
 * - strings divided by + are returned concatenated
Packit 8fb591
 * - comments are skipped
Packit 8fb591
 */
Packit 8fb591
static char *
Packit 8fb591
get_word(FILE *in, char **buf, int *buf_len)
Packit 8fb591
{
Packit 8fb591
    char c;
Packit 8fb591
    /* comment: 0 - nothing, 1 - in line comment, 2 - in block comment, 3 - in block comment with last read character '*'
Packit 8fb591
     * slash: 0 - nothing, 1 - last character was '/'
Packit 8fb591
     * string: 0 - nothing, 1 - string with ', 2 - string with ", 3 - string with " with last character \,
Packit 8fb591
     *         4 - string finished, now skipping whitespaces looking for +,
Packit 8fb591
     *         5 - string continues after +, skipping whitespaces
Packit 8fb591
     * indent: number of spaces of the indent, needed for double-quoted string, if following
Packit 8fb591
     * str_nl_indent: can be non-zero only if string == 2, number of spaces to skip as the indent
Packit 8fb591
     */
Packit 8fb591
    int used = 0, ret, slash = 0, comment = 0, string = 0, indent = 0, str_nl_indent = 0;
Packit 8fb591
Packit 8fb591
    do {
Packit 8fb591
        ret = fread(&c, sizeof c, 1, in);
Packit 8fb591
        if (ret < 1) {
Packit 8fb591
            if (feof(in)) {
Packit 8fb591
                break;
Packit 8fb591
            } else if (ferror(in)) {
Packit 8fb591
                fprintf(stderr, "Read error (%s).\n", strerror(errno));
Packit 8fb591
            } else {
Packit 8fb591
                fprintf(stderr, "Int error (%d).\n", __LINE__);
Packit 8fb591
            }
Packit 8fb591
            return NULL;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        if (string == 4) {
Packit 8fb591
            if (c == '+') {
Packit 8fb591
                /* string continues */
Packit 8fb591
                string = 5;
Packit 8fb591
            } else if (!isspace(c)) {
Packit 8fb591
                /* nope, string is finished */
Packit 8fb591
                if (ungetc(c, in) != c) {
Packit 8fb591
                    fprintf(stderr, "ungetc() failed.\n");
Packit 8fb591
                    return NULL;
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            }
Packit 8fb591
        } else if (string == 5) {
Packit 8fb591
            if (!isspace(c)) {
Packit 8fb591
                if (c == '\'') {
Packit 8fb591
                    string = 1;
Packit 8fb591
                } else if (c == '\"') {
Packit 8fb591
                    string = 2;
Packit 8fb591
                } else {
Packit 8fb591
                    /* it must be quoted again */
Packit 8fb591
                    fprintf(stderr, "Both string parts divided by '+' must be quoted.\n");
Packit 8fb591
                    return NULL;
Packit 8fb591
                }
Packit 8fb591
            }
Packit 8fb591
        } else if (((c == '\'') || (c == '\"')) && !string) {
Packit 8fb591
            if (used) {
Packit 8fb591
                /* we want strings always in a separate word, leave it */
Packit 8fb591
                if (ungetc(c, in) != c) {
Packit 8fb591
                    fprintf(stderr, "ungetc() failed.\n");
Packit 8fb591
                    return NULL;
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            }
Packit 8fb591
            if (c == '\'') {
Packit 8fb591
                string = 1;
Packit 8fb591
            } else {
Packit 8fb591
                string = 2;
Packit 8fb591
                /* for the " itself */
Packit 8fb591
                ++indent;
Packit 8fb591
            }
Packit 8fb591
        } else if (comment) {
Packit 8fb591
            switch (comment) {
Packit 8fb591
            case 1:
Packit 8fb591
                if (c == '\n') {
Packit 8fb591
                    comment = 0;
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            case 2:
Packit 8fb591
                if (c == '*') {
Packit 8fb591
                    comment = 3;
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            case 3:
Packit 8fb591
                if (c == '/') {
Packit 8fb591
                    comment = 0;
Packit 8fb591
                } else {
Packit 8fb591
                    comment = 2;
Packit 8fb591
                }
Packit 8fb591
                break;
Packit 8fb591
            default:
Packit 8fb591
                fprintf(stderr, "Int error (%d).\n", __LINE__);
Packit 8fb591
                return NULL;
Packit 8fb591
            }
Packit 8fb591
        } else if (slash) {
Packit 8fb591
            if (c == '/') {
Packit 8fb591
                comment = 1;
Packit 8fb591
            } else if (c == '*') {
Packit 8fb591
                comment = 2;
Packit 8fb591
            } else {
Packit 8fb591
                if (store_char('/', buf, buf_len, &used) || store_char(c, buf, buf_len, &used)) {
Packit 8fb591
                    return NULL;
Packit 8fb591
                }
Packit 8fb591
            }
Packit 8fb591
            slash = 0;
Packit 8fb591
        } else if ((c == '/') && !string) {
Packit 8fb591
            slash = 1;
Packit 8fb591
        } else if (((string == 1) && (c == '\'')) || ((string == 2) && (c == '\"'))) {
Packit 8fb591
            /* string may be finished, but check for + */
Packit 8fb591
            string = 4;
Packit 8fb591
        } else if ((string == 2) && (c == '\\')) {
Packit 8fb591
            /* special character following */
Packit 8fb591
            string = 3;
Packit 8fb591
        } else if (((c == ';') || (c == '{') || (c == '}')) && !string && used) {
Packit 8fb591
            /* another keyword, leave it for later */
Packit 8fb591
            if (ungetc(c, in) != c) {
Packit 8fb591
                fprintf(stderr, "ungetc() failed.\n");
Packit 8fb591
                return NULL;
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        } else if (!string && !used && ((c == ' ') || (c == '\t'))) {
Packit 8fb591
            if (c == ' ') {
Packit 8fb591
                ++indent;
Packit 8fb591
            } else {
Packit 8fb591
                indent += 8;
Packit 8fb591
            }
Packit 8fb591
        } else if (!isspace(c) || string) {
Packit 8fb591
            if (string == 2) {
Packit 8fb591
                if (isspace(c)) {
Packit 8fb591
                    /* skipping indent spaces */
Packit 8fb591
                    if (str_nl_indent && (c != '\n')) {
Packit 8fb591
                        if (c == ' ') {
Packit 8fb591
                            --str_nl_indent;
Packit 8fb591
                        } else if (c == '\t') {
Packit 8fb591
                            if (str_nl_indent < 9) {
Packit 8fb591
                                str_nl_indent = 0;
Packit 8fb591
                            } else {
Packit 8fb591
                                str_nl_indent -= 8;
Packit 8fb591
                            }
Packit 8fb591
                        }
Packit 8fb591
                        /* we just ignore other whitespace characters */
Packit 8fb591
                        continue;
Packit 8fb591
                    } else if (c == '\n') {
Packit 8fb591
                        str_nl_indent = indent;
Packit 8fb591
                    }
Packit 8fb591
                } else if (str_nl_indent) {
Packit 8fb591
                    /* first non-whitespace character, clear current indent */
Packit 8fb591
                    str_nl_indent = 0;
Packit 8fb591
                }
Packit 8fb591
            } else if (string == 3) {
Packit 8fb591
                /* string encoded characters */
Packit 8fb591
                switch (c) {
Packit 8fb591
                case 'n':
Packit 8fb591
                    c = '\n';
Packit 8fb591
                    break;
Packit 8fb591
                case 't':
Packit 8fb591
                    c = '\t';
Packit 8fb591
                    break;
Packit 8fb591
                case '\"':
Packit 8fb591
                    /* c is correct */
Packit 8fb591
                    break;
Packit 8fb591
                case '\\':
Packit 8fb591
                    /* c is correct */
Packit 8fb591
                    break;
Packit 8fb591
                default:
Packit 8fb591
                    /* so let this one slide just like pyang and yanglint >:-|
Packit 8fb591
                    fprintf(stderr, "Double-quoted string unknown special character '\\%c'.\n", c);
Packit 8fb591
                    return NULL;*/
Packit 8fb591
                    if (store_char('\\', buf, buf_len, &used)) {
Packit 8fb591
                        return NULL;
Packit 8fb591
                    }
Packit 8fb591
                }
Packit 8fb591
                string = 2;
Packit 8fb591
            }
Packit 8fb591
            if (store_char(c, buf, buf_len, &used)) {
Packit 8fb591
                return NULL;
Packit 8fb591
            }
Packit 8fb591
            /* this is a keyword */
Packit 8fb591
            if (((c == ';') || (c == '{') || (c == '}')) && !string) {
Packit 8fb591
                break;
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
    } while (!isspace(c) || !used || string);
Packit 8fb591
Packit 8fb591
    if (store_char('\0', buf, buf_len, &used)) {
Packit 8fb591
        return NULL;
Packit 8fb591
    }
Packit 8fb591
    return *buf;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
/* (does not log) */
Packit 8fb591
static enum yang_token
Packit 8fb591
get_keyword(char *word, enum yang_arg *arg)
Packit 8fb591
{
Packit 8fb591
    enum yang_token ret = YANG_UNKNOWN;
Packit 8fb591
Packit 8fb591
    switch (word[0]) {
Packit 8fb591
    case 'a':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "nyxml", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            ret = YANG_ANYXML;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "rgument", 7)) {
Packit 8fb591
            word += 7;
Packit 8fb591
            ret = YANG_ARGUMENT;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "ugment", 6)) {
Packit 8fb591
            word += 6;
Packit 8fb591
            ret = YANG_AUGMENT;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'b':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ase", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_BASE;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "elongs-to", 9)) {
Packit 8fb591
            word += 9;
Packit 8fb591
            ret = YANG_BELONGS_TO;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "it", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            ret = YANG_BIT;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'c':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ase", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_CASE;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "hoice", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            ret = YANG_CHOICE;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "on", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            if (!strncmp(word, "fig", 3)) {
Packit 8fb591
                word += 3;
Packit 8fb591
                ret = YANG_CONFIG;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "ta", 2)) {
Packit 8fb591
                word += 2;
Packit 8fb591
                if (!strncmp(word, "ct", 2)) {
Packit 8fb591
                    word += 2;
Packit 8fb591
                    ret = YANG_CONTACT;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                } else if (!strncmp(word, "iner", 4)) {
Packit 8fb591
                    word += 4;
Packit 8fb591
                    ret = YANG_CONTAINER;
Packit 8fb591
                    *arg = Y_IDENTIF_ARG;
Packit 8fb591
                }
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'd':
Packit 8fb591
        ++word;
Packit 8fb591
        if (word[0] == 'e') {
Packit 8fb591
            ++word;
Packit 8fb591
            if (!strncmp(word, "fault", 5)) {
Packit 8fb591
                word += 5;
Packit 8fb591
                ret = YANG_DEFAULT;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "scription", 9)) {
Packit 8fb591
                word += 9;
Packit 8fb591
                ret = YANG_DESCRIPTION;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "viat", 4)) {
Packit 8fb591
                word += 4;
Packit 8fb591
                if (word[0] == 'e') {
Packit 8fb591
                    ++word;
Packit 8fb591
                    ret = YANG_DEVIATE;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                } else if (!strncmp(word, "ion", 3)) {
Packit 8fb591
                    word += 3;
Packit 8fb591
                    ret = YANG_DEVIATION;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                }
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'e':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "num", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_ENUM;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "rror-", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            if (!strncmp(word, "app-tag", 7)) {
Packit 8fb591
                word += 7;
Packit 8fb591
                ret = YANG_ERROR_APP_TAG;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "message", 7)) {
Packit 8fb591
                word += 7;
Packit 8fb591
                ret = YANG_ERROR_MESSAGE;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "xtension", 8)) {
Packit 8fb591
            word += 8;
Packit 8fb591
            ret = YANG_EXTENSION;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'f':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "eature", 6)) {
Packit 8fb591
            word += 6;
Packit 8fb591
            ret = YANG_FEATURE;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "raction-digits", 14)) {
Packit 8fb591
            word += 14;
Packit 8fb591
            ret = YANG_FRACTION_DIGITS;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'g':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "rouping", 7)) {
Packit 8fb591
            word += 7;
Packit 8fb591
            ret = YANG_GROUPING;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'i':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "dentity", 7)) {
Packit 8fb591
            word += 7;
Packit 8fb591
            ret = YANG_IDENTITY;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "f-feature", 9)) {
Packit 8fb591
            word += 9;
Packit 8fb591
            ret = YANG_IF_FEATURE;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "mport", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            ret = YANG_IMPORT;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (word[0] == 'n') {
Packit 8fb591
            ++word;
Packit 8fb591
            if (!strncmp(word, "clude", 5)) {
Packit 8fb591
                word += 5;
Packit 8fb591
                ret = YANG_INCLUDE;
Packit 8fb591
                *arg = Y_IDENTIF_ARG;
Packit 8fb591
            } else if (!strncmp(word, "put", 3)) {
Packit 8fb591
                word += 3;
Packit 8fb591
                ret = YANG_INPUT;
Packit 8fb591
                *arg = Y_NO_ARG;
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'k':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ey", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            ret = YANG_KEY;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'l':
Packit 8fb591
        ++word;
Packit 8fb591
        if (word[0] == 'e') {
Packit 8fb591
            ++word;
Packit 8fb591
            if (!strncmp(word, "af", 2)) {
Packit 8fb591
                word += 2;
Packit 8fb591
                if (word[0] != '-') {
Packit 8fb591
                    ret = YANG_LEAF;
Packit 8fb591
                    *arg = Y_IDENTIF_ARG;
Packit 8fb591
                } else if (!strncmp(word, "-list", 5)) {
Packit 8fb591
                    word += 5;
Packit 8fb591
                    ret = YANG_LEAF_LIST;
Packit 8fb591
                    *arg = Y_IDENTIF_ARG;
Packit 8fb591
                }
Packit 8fb591
            } else if (!strncmp(word, "ngth", 4)) {
Packit 8fb591
                word += 4;
Packit 8fb591
                ret = YANG_LENGTH;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "ist", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_LIST;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'm':
Packit 8fb591
        ++word;
Packit 8fb591
        if (word[0] == 'a') {
Packit 8fb591
            ++word;
Packit 8fb591
            if (!strncmp(word, "ndatory", 7)) {
Packit 8fb591
                word += 7;
Packit 8fb591
                ret = YANG_MANDATORY;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "x-elements", 10)) {
Packit 8fb591
                word += 10;
Packit 8fb591
                ret = YANG_MAX_ELEMENTS;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "in-elements", 11)) {
Packit 8fb591
            word += 11;
Packit 8fb591
            ret = YANG_MIN_ELEMENTS;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "odule", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            ret = YANG_MODULE;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        } else if (!strncmp(word, "ust", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_MUST;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'n':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "amespace", 8)) {
Packit 8fb591
            word += 8;
Packit 8fb591
            ret = YANG_NAMESPACE;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "otification", 11)) {
Packit 8fb591
            word += 11;
Packit 8fb591
            ret = YANG_NOTIFICATION;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'o':
Packit 8fb591
        ++word;
Packit 8fb591
        if (word[0] == 'r') {
Packit 8fb591
            ++word;
Packit 8fb591
            if (!strncmp(word, "dered-by", 8)) {
Packit 8fb591
                word += 8;
Packit 8fb591
                ret = YANG_ORDERED_BY;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "ganization", 10)) {
Packit 8fb591
                word += 10;
Packit 8fb591
                ret = YANG_ORGANIZATION;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "utput", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            ret = YANG_OUTPUT;
Packit 8fb591
            *arg = Y_NO_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'p':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "at", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            if (word[0] == 'h') {
Packit 8fb591
                ++word;
Packit 8fb591
                ret = YANG_PATH;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "tern", 4)) {
Packit 8fb591
                word += 4;
Packit 8fb591
                ret = YANG_PATTERN;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "osition", 7)) {
Packit 8fb591
            word += 7;
Packit 8fb591
            ret = YANG_POSITION;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "re", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            if (!strncmp(word, "fix", 3)) {
Packit 8fb591
                word += 3;
Packit 8fb591
                ret = YANG_PREFIX;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "sence", 5)) {
Packit 8fb591
                word += 5;
Packit 8fb591
                ret = YANG_PRESENCE;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'r':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ange", 4)) {
Packit 8fb591
            word += 4;
Packit 8fb591
            ret = YANG_RANGE;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (word[0] == 'e') {
Packit 8fb591
            ++word;
Packit 8fb591
            if (word[0] == 'f') {
Packit 8fb591
                ++word;
Packit 8fb591
                if (!strncmp(word, "erence", 6)) {
Packit 8fb591
                    word += 6;
Packit 8fb591
                    ret = YANG_REFERENCE;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                } else if (!strncmp(word, "ine", 3)) {
Packit 8fb591
                    word += 3;
Packit 8fb591
                    ret = YANG_REFINE;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                }
Packit 8fb591
            } else if (!strncmp(word, "quire-instance", 14)) {
Packit 8fb591
                word += 14;
Packit 8fb591
                ret = YANG_REQUIRE_INSTANCE;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "vision", 6)) {
Packit 8fb591
                word += 6;
Packit 8fb591
                if (word[0] != '-') {
Packit 8fb591
                    ret = YANG_REVISION;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                } else if (!strncmp(word, "-date", 5)) {
Packit 8fb591
                    word += 5;
Packit 8fb591
                    ret = YANG_REVISION_DATE;
Packit 8fb591
                    *arg = Y_STR_ARG;
Packit 8fb591
                }
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "pc", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            ret = YANG_RPC;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 's':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "tatus", 5)) {
Packit 8fb591
            word += 5;
Packit 8fb591
            ret = YANG_STATUS;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "ubmodule", 8)) {
Packit 8fb591
            word += 8;
Packit 8fb591
            ret = YANG_SUBMODULE;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 't':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ype", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            if (word[0] != 'd') {
Packit 8fb591
                ret = YANG_TYPE;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "def", 3)) {
Packit 8fb591
                word += 3;
Packit 8fb591
                ret = YANG_TYPEDEF;
Packit 8fb591
                *arg = Y_IDENTIF_ARG;
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'u':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ni", 2)) {
Packit 8fb591
            word += 2;
Packit 8fb591
            if (!strncmp(word, "que", 3)) {
Packit 8fb591
                word += 3;
Packit 8fb591
                ret = YANG_UNIQUE;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            } else if (!strncmp(word, "ts", 2)) {
Packit 8fb591
                word += 2;
Packit 8fb591
                ret = YANG_UNITS;
Packit 8fb591
                *arg = Y_STR_ARG;
Packit 8fb591
            }
Packit 8fb591
        } else if (!strncmp(word, "ses", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_USES;
Packit 8fb591
            *arg = Y_IDENTIF_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'v':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "alue", 4)) {
Packit 8fb591
            word += 4;
Packit 8fb591
            ret = YANG_VALUE;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'w':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "hen", 3)) {
Packit 8fb591
            word += 3;
Packit 8fb591
            ret = YANG_WHEN;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case 'y':
Packit 8fb591
        ++word;
Packit 8fb591
        if (!strncmp(word, "ang-version", 11)) {
Packit 8fb591
            word += 11;
Packit 8fb591
            ret = YANG_YANG_VERSION;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        } else if (!strncmp(word, "in-element", 10)) {
Packit 8fb591
            word += 10;
Packit 8fb591
            ret = YANG_YIN_ELEMENT;
Packit 8fb591
            *arg = Y_STR_ARG;
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
    case ';':
Packit 8fb591
        ++word;
Packit 8fb591
        ret = YANG_SEMICOLON;
Packit 8fb591
        *arg = Y_NO_ARG;
Packit 8fb591
        break;
Packit 8fb591
    case '{':
Packit 8fb591
        ++word;
Packit 8fb591
        ret = YANG_LEFT_BRACE;
Packit 8fb591
        *arg = Y_NO_ARG;
Packit 8fb591
        break;
Packit 8fb591
    case '}':
Packit 8fb591
        ++word;
Packit 8fb591
        ret = YANG_RIGHT_BRACE;
Packit 8fb591
        *arg = Y_NO_ARG;
Packit 8fb591
        break;
Packit 8fb591
    default:
Packit 8fb591
        break;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if ((ret == YANG_UNKNOWN) && strchr(word, ':') && (strchr(word, ':') == strrchr(word, ':'))) {
Packit 8fb591
        /* some string with one ':', let's say it's an extension */
Packit 8fb591
        word += strlen(word);
Packit 8fb591
        ret = YANG_CUSTOM;
Packit 8fb591
        *arg = Y_NO_ARG;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* not a keyword after all */
Packit 8fb591
    if ((ret != YANG_UNKNOWN) && word[0]) {
Packit 8fb591
        ret = YANG_UNKNOWN;
Packit 8fb591
    }
Packit 8fb591
    return ret;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static void
Packit 8fb591
print_text_xml_encode(FILE *out, const char *word)
Packit 8fb591
{
Packit 8fb591
    const char *ptr;
Packit 8fb591
Packit 8fb591
    for (ptr = word; ptr[0]; ++ptr) {
Packit 8fb591
        switch (ptr[0]) {
Packit 8fb591
        case '<':
Packit 8fb591
            fputs("<", out);
Packit 8fb591
            break;
Packit 8fb591
        case '>':
Packit 8fb591
            fputs(">", out);
Packit 8fb591
            break;
Packit 8fb591
        case '&':
Packit 8fb591
            fputs("&", out);
Packit 8fb591
            break;
Packit 8fb591
        /* not really necessary, I guess... */
Packit 8fb591
        /*case '\'':
Packit 8fb591
            fputs("'", out);
Packit 8fb591
            break;
Packit 8fb591
        case '\"':
Packit 8fb591
            fputs(""", out);
Packit 8fb591
            break;*/
Packit 8fb591
        default:
Packit 8fb591
            fputc(ptr[0], out);
Packit 8fb591
            break;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static void
Packit 8fb591
print_attr_val_xml_encode(FILE *out, const char *word)
Packit 8fb591
{
Packit 8fb591
    const char *ptr;
Packit 8fb591
Packit 8fb591
    for (ptr = word; ptr[0]; ++ptr) {
Packit 8fb591
        switch (ptr[0]) {
Packit 8fb591
        case '<':
Packit 8fb591
            fputs("<", out);
Packit 8fb591
            break;
Packit 8fb591
        case '>':
Packit 8fb591
            fputs(">", out);
Packit 8fb591
            break;
Packit 8fb591
        case '&':
Packit 8fb591
            fputs("&", out);
Packit 8fb591
            break;
Packit 8fb591
        /* we always use ", so ' is fine */
Packit 8fb591
        /*case '\'':
Packit 8fb591
            fputs("'", out);
Packit 8fb591
            break;*/
Packit 8fb591
        case '\"':
Packit 8fb591
            fputs(""", out);
Packit 8fb591
            break;
Packit 8fb591
        default:
Packit 8fb591
            fputc(ptr[0], out);
Packit 8fb591
            break;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static int
Packit 8fb591
print_keyword(enum yang_token keyword, enum yang_arg arg, FILE *out, int level, FILE *in, char **buf, int *buf_len)
Packit 8fb591
{
Packit 8fb591
    char *word;
Packit 8fb591
    const char *yin_element = NULL, *close_tag;
Packit 8fb591
Packit 8fb591
    switch (keyword) {
Packit 8fb591
    case YANG_ANYXML:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "anyxml";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_ARGUMENT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "argument";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_AUGMENT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "augment";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_BASE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "base";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_BELONGS_TO:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "belongs-to";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_BIT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "bit";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_CASE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "case";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_CHOICE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "choice";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_CONFIG:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "config";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_CONTACT:
Packit 8fb591
        fprintf(out, "%*s<contact>\n", LEVEL(level), INDENT(level));
Packit 8fb591
        yin_element = "text";
Packit 8fb591
        close_tag = "contact";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_CONTAINER:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "container";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_DEFAULT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "default";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_DESCRIPTION:
Packit 8fb591
        fprintf(out, "%*s<description>\n", LEVEL(level), INDENT(level));
Packit 8fb591
        yin_element = "text";
Packit 8fb591
        close_tag = "description";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_DEVIATE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "deviate";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_DEVIATION:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "deviation";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_ENUM:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "enum";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_ERROR_APP_TAG:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "error-app-tag";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_ERROR_MESSAGE:
Packit 8fb591
        fprintf(out, "%*s<error-message>\n", LEVEL(level), INDENT(level));
Packit 8fb591
        yin_element = "value";
Packit 8fb591
        close_tag = "error-message";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_EXTENSION:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "extension";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_FEATURE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "feature";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_FRACTION_DIGITS:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "fraction-digits";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_GROUPING:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "grouping";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_IDENTITY:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "identity";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_IF_FEATURE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "if-feature";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_IMPORT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "import";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_INCLUDE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "include";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_INPUT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "input";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_KEY:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "key";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_LEAF:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "leaf";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_LEAF_LIST:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "leaf-list";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_LENGTH:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "length";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_LIST:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "list";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_MANDATORY:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "mandatory";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_MAX_ELEMENTS:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "max-elements";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_MIN_ELEMENTS:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "min-elements";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_MUST:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "must";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_NAMESPACE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "namespace";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_NOTIFICATION:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "notification";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_ORDERED_BY:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "ordered-by";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_ORGANIZATION:
Packit 8fb591
        fprintf(out, "%*s<organization>\n", LEVEL(level), INDENT(level));
Packit 8fb591
        yin_element = "text";
Packit 8fb591
        close_tag = "organization";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_OUTPUT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "output";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_PATH:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "path";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_PATTERN:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "pattern";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_POSITION:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "value";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_PREFIX:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "prefix";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_PRESENCE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "presence";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_RANGE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "range";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_REFERENCE:
Packit 8fb591
        fprintf(out, "%*s<reference>\n", LEVEL(level), INDENT(level));
Packit 8fb591
        yin_element = "text";
Packit 8fb591
        close_tag = "reference";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_REFINE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "refine";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_REQUIRE_INSTANCE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "require-instance";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_REVISION:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "revision";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_REVISION_DATE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "revision-date";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_RPC:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "rpc";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_STATUS:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "status";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_TYPE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "type";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_TYPEDEF:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "typedef";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_UNIQUE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "unique";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_UNITS:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "units";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_USES:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "uses";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_VALUE:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "value";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_WHEN:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "condition";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_YANG_VERSION:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "yang-version";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_YIN_ELEMENT:
Packit 8fb591
        fprintf(out, "%*s
Packit 8fb591
        close_tag = "yin-element";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_CUSTOM:
Packit 8fb591
        /* it must still be stored in buf */
Packit 8fb591
        fprintf(out, "%*s<%s", LEVEL(level), INDENT(level), *buf);
Packit 8fb591
        /* will be printed in case of some nested extension elements, we don't support that */
Packit 8fb591
        close_tag = "!!error!!";
Packit 8fb591
        break;
Packit 8fb591
    default:
Packit 8fb591
        fprintf(stderr, "Unexpected keyword \"%s\".\n", keyword2str(keyword));
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* keyword followed by a child element */
Packit 8fb591
    if (yin_element) {
Packit 8fb591
        ++level;
Packit 8fb591
        fprintf(out, "%*s<%s>", LEVEL(level), INDENT(level), yin_element);
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* keyword argument */
Packit 8fb591
    switch (arg) {
Packit 8fb591
    case Y_IDENTIF_ARG:
Packit 8fb591
        word = get_word(in, buf, buf_len);
Packit 8fb591
        if (!word) {
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        /* word is the identifier (after some changes) */
Packit 8fb591
        fprintf(out, "%s%s", word, (yin_element ? "" : "\""));
Packit 8fb591
        break;
Packit 8fb591
Packit 8fb591
    case Y_STR_ARG:
Packit 8fb591
        word = get_word(in, buf, buf_len);
Packit 8fb591
        if (!word) {
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
        /* word is the string */
Packit 8fb591
        if (yin_element) {
Packit 8fb591
            print_text_xml_encode(out, word);
Packit 8fb591
        } else {
Packit 8fb591
            print_attr_val_xml_encode(out, word);
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        if (!yin_element) {
Packit 8fb591
            fprintf(out, "\"");
Packit 8fb591
        }
Packit 8fb591
        break;
Packit 8fb591
Packit 8fb591
    case Y_NO_ARG:
Packit 8fb591
        break;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if (yin_element) {
Packit 8fb591
        fprintf(out, "</%s>\n", yin_element);
Packit 8fb591
        --level;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    word = get_word(in, buf, buf_len);
Packit 8fb591
    if (!word) {
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
    keyword = get_keyword(word, &arg;;
Packit 8fb591
    if (!keyword) {
Packit 8fb591
        fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if (keyword == YANG_LEFT_BRACE) {
Packit 8fb591
        if (!yin_element) {
Packit 8fb591
            fprintf(out, ">\n");
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        while (1) {
Packit 8fb591
            word = get_word(in, buf, buf_len);
Packit 8fb591
            if (!word) {
Packit 8fb591
                return -1;
Packit 8fb591
            }
Packit 8fb591
            keyword = get_keyword(word, &arg;;
Packit 8fb591
            if (!keyword) {
Packit 8fb591
                fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
                return -1;
Packit 8fb591
            }
Packit 8fb591
Packit 8fb591
            if (keyword == YANG_RIGHT_BRACE) {
Packit 8fb591
                break;
Packit 8fb591
            }
Packit 8fb591
Packit 8fb591
            if (print_keyword(keyword, arg, out, level + 1, in, buf, buf_len)) {
Packit 8fb591
                return -1;
Packit 8fb591
            }
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        fprintf(out, "%*s</%s>\n", LEVEL(level), INDENT(level), close_tag);
Packit 8fb591
    }
Packit 8fb591
    if ((keyword != YANG_SEMICOLON) && (keyword != YANG_RIGHT_BRACE)) {
Packit 8fb591
        fprintf(stderr, "Unexpected keyword \"%s\".\n", keyword2str(keyword));
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
    if (keyword == YANG_SEMICOLON) {
Packit 8fb591
        if (yin_element) {
Packit 8fb591
            fprintf(out, "%*s</%s>\n", LEVEL(level), INDENT(level), close_tag);
Packit 8fb591
        } else {
Packit 8fb591
            fprintf(out, "/>\n");
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    return 0;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static int
Packit 8fb591
print_sub_module(enum yang_token keyword, enum yang_arg arg, FILE *out, FILE *in, char **buf, int *buf_len,
Packit 8fb591
                 const char *namespace, const char *prefix, char **import_namespaces, char **import_prefixes, int import_count)
Packit 8fb591
{
Packit 8fb591
    char *word;
Packit 8fb591
    const char *close_tag;
Packit 8fb591
    int i;
Packit 8fb591
Packit 8fb591
    switch (keyword) {
Packit 8fb591
    case YANG_MODULE:
Packit 8fb591
        fprintf(out, "
Packit 8fb591
        close_tag = "module";
Packit 8fb591
        break;
Packit 8fb591
    case YANG_SUBMODULE:
Packit 8fb591
        fprintf(out, "
Packit 8fb591
        close_tag = "submodule";
Packit 8fb591
        break;
Packit 8fb591
    default:
Packit 8fb591
        fprintf(stderr, "Unexpected keyword \"%s\".\n", keyword2str(keyword));
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* (sub)module name */
Packit 8fb591
    switch (arg) {
Packit 8fb591
    case Y_IDENTIF_ARG:
Packit 8fb591
        word = get_word(in, buf, buf_len);
Packit 8fb591
        if (!word) {
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        fprintf(out, "%s\"", word);
Packit 8fb591
        break;
Packit 8fb591
Packit 8fb591
    default:
Packit 8fb591
        fprintf(stderr, "Int error (%d).\n", __LINE__);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* namespaces */
Packit 8fb591
    fprintf(out, "\n%*sxmlns=\"urn:ietf:params:xml:ns:yang:yin:1\"", (keyword == YANG_MODULE ? 8 : 11), " ");
Packit 8fb591
    fprintf(out, "\n%*sxmlns:%s=\"%s\"", (keyword == YANG_MODULE ? 8 : 11), " ", prefix, namespace);
Packit 8fb591
    for (i = 0; i < import_count; ++i) {
Packit 8fb591
        fprintf(out, "\n%*sxmlns:%s=\"%s\"", (keyword == YANG_MODULE ? 8 : 11), " ", import_prefixes[i], import_namespaces[i]);
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    word = get_word(in, buf, buf_len);
Packit 8fb591
    if (!word) {
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
    keyword = get_keyword(word, &arg;;
Packit 8fb591
    if (!keyword) {
Packit 8fb591
        fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if (keyword != YANG_LEFT_BRACE) {
Packit 8fb591
        fprintf(stderr, "Unexpected keyword \"%s\".\n", keyword2str(keyword));
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    fprintf(out, ">\n");
Packit 8fb591
Packit 8fb591
    while (1) {
Packit 8fb591
        word = get_word(in, buf, buf_len);
Packit 8fb591
        if (!word) {
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
        keyword = get_keyword(word, &arg;;
Packit 8fb591
        if (!keyword) {
Packit 8fb591
            fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        if (keyword == YANG_RIGHT_BRACE) {
Packit 8fb591
            break;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        if (print_keyword(keyword, arg, out, 1, in, buf, buf_len)) {
Packit 8fb591
            return -1;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    fprintf(out, "</%s>\n", close_tag);
Packit 8fb591
Packit 8fb591
    return 0;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static int
Packit 8fb591
find_namespace_imports(FILE *in, char **buf, int *buf_len, char **name_space, char **prefix, char ***import_modules,
Packit 8fb591
                       char ***import_prefixes, int *import_count)
Packit 8fb591
{
Packit 8fb591
    char *word;
Packit 8fb591
    void *new_buf;
Packit 8fb591
    enum yang_token keyword;
Packit 8fb591
    enum yang_arg arg;
Packit 8fb591
    int i, want_prefix = 0;
Packit 8fb591
Packit 8fb591
    *name_space = NULL;
Packit 8fb591
    if (prefix) {
Packit 8fb591
        *prefix = NULL;
Packit 8fb591
    }
Packit 8fb591
    if (import_modules && import_prefixes && import_count) {
Packit 8fb591
        *import_modules = NULL;
Packit 8fb591
        *import_prefixes = NULL;
Packit 8fb591
        *import_count = 0;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    while (1) {
Packit 8fb591
        word = get_word(in, buf, buf_len);
Packit 8fb591
        if (!word) {
Packit 8fb591
            goto error;
Packit 8fb591
        } else if (!word[0]) {
Packit 8fb591
            /* EOF */
Packit 8fb591
            goto success;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        keyword = get_keyword(word, &arg;;
Packit 8fb591
        if (!keyword) {
Packit 8fb591
            fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
            goto error;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        switch (arg) {
Packit 8fb591
        case Y_IDENTIF_ARG:
Packit 8fb591
        case Y_STR_ARG:
Packit 8fb591
            word = get_word(in, buf, buf_len);
Packit 8fb591
            if (!word) {
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        case Y_NO_ARG:
Packit 8fb591
            break;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        switch (keyword) {
Packit 8fb591
        case YANG_NAMESPACE:
Packit 8fb591
            /* module */
Packit 8fb591
            if (want_prefix) {
Packit 8fb591
                fprintf(stderr, "Unexpected keyword \"%s\", expected \"prefix\".\n", keyword2str(keyword));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            if (*name_space) {
Packit 8fb591
                fprintf(stderr, "Unexpected keyword \"%s\", already encountered.\n", keyword2str(keyword));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            *name_space = strdup(word);
Packit 8fb591
            if (!*name_space) {
Packit 8fb591
                fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        case YANG_IMPORT:
Packit 8fb591
            if (want_prefix) {
Packit 8fb591
                fprintf(stderr, "Unexpected keyword \"%s\", expected \"prefix\".\n", keyword2str(keyword));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            if (import_modules && import_prefixes && import_count) {
Packit 8fb591
                new_buf = realloc(*import_modules, (*import_count + 1) * sizeof **import_modules);
Packit 8fb591
                if (!new_buf) {
Packit 8fb591
                    fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                    goto error;
Packit 8fb591
                }
Packit 8fb591
                *import_modules = new_buf;
Packit 8fb591
Packit 8fb591
                new_buf = realloc(*import_prefixes, (*import_count + 1) * sizeof **import_prefixes);
Packit 8fb591
                if (!new_buf) {
Packit 8fb591
                    fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                    goto error;
Packit 8fb591
                }
Packit 8fb591
                *import_prefixes = new_buf;
Packit 8fb591
Packit 8fb591
                (*import_modules)[*import_count] = strdup(word);
Packit 8fb591
                if (!(*import_modules)[*import_count]) {
Packit 8fb591
                    fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                    goto error;
Packit 8fb591
                }
Packit 8fb591
                (*import_prefixes)[*import_count] = NULL;
Packit 8fb591
                ++(*import_count);
Packit 8fb591
            }
Packit 8fb591
            want_prefix = 1;
Packit 8fb591
            break;
Packit 8fb591
        case YANG_BELONGS_TO:
Packit 8fb591
            /* submodule */
Packit 8fb591
            if (want_prefix) {
Packit 8fb591
                fprintf(stderr, "Unexpected keyword \"%s\", expected \"prefix\".\n", keyword2str(keyword));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            if (*name_space) {
Packit 8fb591
                fprintf(stderr, "Unexpected keyword \"%s\", already encountered.\n", keyword2str(keyword));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            *name_space = strdup(word);
Packit 8fb591
            if (!*name_space) {
Packit 8fb591
                fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        case YANG_PREFIX:
Packit 8fb591
            if (!want_prefix) {
Packit 8fb591
                /* main (sub)module prefix */
Packit 8fb591
                if (prefix) {
Packit 8fb591
                    *prefix = strdup(word);
Packit 8fb591
                    if (!*prefix) {
Packit 8fb591
                        fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                        goto error;
Packit 8fb591
                    }
Packit 8fb591
                }
Packit 8fb591
            } else {
Packit 8fb591
                if (import_modules && import_prefixes && import_count) {
Packit 8fb591
                    (*import_prefixes)[*import_count - 1] = strdup(word);
Packit 8fb591
                    if (!(*import_prefixes)[*import_count - 1]) {
Packit 8fb591
                        fprintf(stderr, "Memory allocation error (%s).\n", strerror(errno));
Packit 8fb591
                        goto error;
Packit 8fb591
                    }
Packit 8fb591
                }
Packit 8fb591
                want_prefix = 0;
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        case YANG_SEMICOLON:
Packit 8fb591
        case YANG_LEFT_BRACE:
Packit 8fb591
        case YANG_RIGHT_BRACE:
Packit 8fb591
        case YANG_REVISION_DATE:
Packit 8fb591
            /* the only ones that can appear before prefix */
Packit 8fb591
            break;
Packit 8fb591
        case YANG_CONTACT:
Packit 8fb591
        case YANG_DESCRIPTION:
Packit 8fb591
        case YANG_REFERENCE:
Packit 8fb591
        case YANG_REVISION:
Packit 8fb591
        case YANG_EXTENSION:
Packit 8fb591
        case YANG_FEATURE:
Packit 8fb591
        case YANG_IDENTITY:
Packit 8fb591
        case YANG_TYPEDEF:
Packit 8fb591
        case YANG_GROUPING:
Packit 8fb591
        case YANG_CONTAINER:
Packit 8fb591
        case YANG_LEAF:
Packit 8fb591
        case YANG_LEAF_LIST:
Packit 8fb591
        case YANG_LIST:
Packit 8fb591
        case YANG_CHOICE:
Packit 8fb591
        case YANG_ANYXML:
Packit 8fb591
        case YANG_USES:
Packit 8fb591
        case YANG_AUGMENT:
Packit 8fb591
        case YANG_RPC:
Packit 8fb591
        case YANG_NOTIFICATION:
Packit 8fb591
        case YANG_DEVIATION:
Packit 8fb591
            /* no import can follow */
Packit 8fb591
            goto success;
Packit 8fb591
        default:
Packit 8fb591
            if (want_prefix) {
Packit 8fb591
                fprintf(stderr, "Unexpected keyword \"%s\", expected \"prefix\".\n", keyword2str(keyword));
Packit 8fb591
                goto error;
Packit 8fb591
            }
Packit 8fb591
            break;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
success:
Packit 8fb591
    if (want_prefix) {
Packit 8fb591
        fprintf(stderr, "Unexpected EOF/keyword, expected \"prefix\".\n");
Packit 8fb591
        goto error;
Packit 8fb591
    }
Packit 8fb591
    if (prefix && !(*prefix)) {
Packit 8fb591
        fprintf(stderr, "Module prefix/submodule \"belongs-to\" prefix not found.\n");
Packit 8fb591
        goto error;
Packit 8fb591
    }
Packit 8fb591
    if (!(*name_space)) {
Packit 8fb591
        fprintf(stderr, "Module namespace/submodule \"belongs-to\" module not found.\n");
Packit 8fb591
        goto error;
Packit 8fb591
    }
Packit 8fb591
    return 0;
Packit 8fb591
Packit 8fb591
error:
Packit 8fb591
    if (import_modules && import_prefixes && import_count) {
Packit 8fb591
        for (i = 0; i < *import_count; ++i) {
Packit 8fb591
            free((*import_modules)[i]);
Packit 8fb591
            free((*import_prefixes)[i]);
Packit 8fb591
        }
Packit 8fb591
        free(*import_modules);
Packit 8fb591
        free(*import_prefixes);
Packit 8fb591
    }
Packit 8fb591
    if (prefix) {
Packit 8fb591
        free(*prefix);
Packit 8fb591
    }
Packit 8fb591
    free(*name_space);
Packit 8fb591
    return -1;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
static int
Packit 8fb591
convert_yang2yin(FILE *out, FILE *in, const char *search_dir)
Packit 8fb591
{
Packit 8fb591
    char *buf = NULL, *word, *name_space, *prefix, **import_modules, **import_prefixes;
Packit 8fb591
    int buf_len = 0, ret = 0, import_count, i;
Packit 8fb591
    enum yang_token keyword;
Packit 8fb591
    enum yang_arg arg;
Packit 8fb591
    FILE *mod_file = NULL;
Packit 8fb591
Packit 8fb591
    /*
Packit 8fb591
     * 1st module parsing
Packit 8fb591
     */
Packit 8fb591
Packit 8fb591
    /* learn whther it's a module or submodule */
Packit 8fb591
    word = get_word(in, &buf, &buf_len);
Packit 8fb591
    if (!word) {
Packit 8fb591
        free(buf);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    keyword = get_keyword(word, &arg;;
Packit 8fb591
    if (!keyword) {
Packit 8fb591
        fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
        free(buf);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if ((keyword != YANG_MODULE) && (keyword != YANG_SUBMODULE)) {
Packit 8fb591
        fprintf(stderr, "Unexpected keyword \"%s\".\n", keyword2str(keyword));
Packit 8fb591
        free(buf);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    word = get_word(in, &buf, &buf_len);
Packit 8fb591
    if (!word) {
Packit 8fb591
        free(buf);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* learn namespace, imports of the (sub)module being converted */
Packit 8fb591
    if (find_namespace_imports(in, &buf, &buf_len, &name_space, &prefix, &import_modules, &import_prefixes, &import_count)) {
Packit 8fb591
        free(buf);
Packit 8fb591
        return -1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* learn the main module namespace */
Packit 8fb591
    if (keyword == YANG_SUBMODULE) {
Packit 8fb591
        mod_file = open_module(name_space, search_dir);
Packit 8fb591
        if (!mod_file) {
Packit 8fb591
            fprintf(stderr, "Failed to open the module \"%s\".\n", name_space);
Packit 8fb591
            ret = -1;
Packit 8fb591
            goto cleanup;
Packit 8fb591
        }
Packit 8fb591
        free(name_space);
Packit 8fb591
        name_space = NULL;
Packit 8fb591
Packit 8fb591
        if (find_namespace_imports(mod_file, &buf, &buf_len, &name_space, NULL, NULL, NULL, NULL)) {
Packit 8fb591
            ret = -1;
Packit 8fb591
            goto cleanup;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        fclose(mod_file);
Packit 8fb591
        mod_file = NULL;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    /* learn the namespaces of import modules */
Packit 8fb591
    for (i = 0; i < import_count; ++i) {
Packit 8fb591
        mod_file = open_module(import_modules[i], search_dir);
Packit 8fb591
        if (!mod_file) {
Packit 8fb591
            fprintf(stderr, "Failed to open the module \"%s\".\n", import_modules[i]);
Packit 8fb591
            ret = -1;
Packit 8fb591
            goto cleanup;
Packit 8fb591
        }
Packit 8fb591
        free(import_modules[i]);
Packit 8fb591
        import_modules[i] = NULL;
Packit 8fb591
Packit 8fb591
        if (find_namespace_imports(mod_file, &buf, &buf_len, &import_modules[i], NULL, NULL, NULL, NULL)) {
Packit 8fb591
            ret = -1;
Packit 8fb591
            goto cleanup;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        fclose(mod_file);
Packit 8fb591
        mod_file = NULL;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    rewind(in);
Packit 8fb591
Packit 8fb591
    /*
Packit 8fb591
     * 2nd module parsing
Packit 8fb591
     */
Packit 8fb591
Packit 8fb591
    /* print xml header */
Packit 8fb591
    fprintf(out, "\n");
Packit 8fb591
Packit 8fb591
    word = get_word(in, &buf, &buf_len);
Packit 8fb591
    if (!word) {
Packit 8fb591
        ret = -1;
Packit 8fb591
        goto cleanup;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    keyword = get_keyword(word, &arg;;
Packit 8fb591
    if (!keyword) {
Packit 8fb591
        fprintf(stderr, "Unexpected characters (\"%.20s\"...).\n", word);
Packit 8fb591
        ret = -1;
Packit 8fb591
        goto cleanup;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if ((keyword == YANG_MODULE) || (keyword == YANG_SUBMODULE)) {
Packit 8fb591
        ret = print_sub_module(keyword, arg, out, in, &buf, &buf_len, name_space, prefix, import_modules,
Packit 8fb591
                               import_prefixes, import_count);
Packit 8fb591
    } else {
Packit 8fb591
        fprintf(stderr, "Unexpected keyword \"%s\".\n", keyword2str(keyword));
Packit 8fb591
        ret = -1;
Packit 8fb591
        goto cleanup;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
cleanup:
Packit 8fb591
    free(name_space);
Packit 8fb591
    free(prefix);
Packit 8fb591
    for (i = 0; i < import_count; ++i) {
Packit 8fb591
        free(import_modules[i]);
Packit 8fb591
        free(import_prefixes[i]);
Packit 8fb591
    }
Packit 8fb591
    free(import_modules);
Packit 8fb591
    free(import_prefixes);
Packit 8fb591
    if (mod_file) {
Packit 8fb591
        fclose(mod_file);
Packit 8fb591
    }
Packit 8fb591
    free(buf);
Packit 8fb591
    return ret;
Packit 8fb591
}
Packit 8fb591
Packit 8fb591
int
Packit 8fb591
main(int argc, char **argv)
Packit 8fb591
{
Packit 8fb591
    const char *in_file = NULL, *out_file = NULL, *search_dir = ".";
Packit 8fb591
    char *ptr;
Packit 8fb591
    FILE *input = NULL, *output = NULL;
Packit 8fb591
    int ret = 1;
Packit 8fb591
Packit 8fb591
    switch (argc) {
Packit 8fb591
    case 1:
Packit 8fb591
        break;
Packit 8fb591
    case 2:
Packit 8fb591
        if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
Packit 8fb591
            fprintf(stdout, "Usage:\n\t%s [input-file] [output-file]\n", argv[0]);
Packit 8fb591
            return 0;
Packit 8fb591
        }
Packit 8fb591
        in_file = argv[1];
Packit 8fb591
        break;
Packit 8fb591
    case 3:
Packit 8fb591
        in_file = argv[1];
Packit 8fb591
        out_file = argv[2];
Packit 8fb591
        break;
Packit 8fb591
    default:
Packit 8fb591
        fprintf(stderr, "Invalid arguments.\n");
Packit 8fb591
        return 1;
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    if (in_file) {
Packit 8fb591
        input = fopen(in_file, "r");
Packit 8fb591
        if (!input) {
Packit 8fb591
            fprintf(stderr, "Failed to open \"%s\" for reading (%s).\n", in_file, strerror(errno));
Packit 8fb591
            goto cleanup;
Packit 8fb591
        }
Packit 8fb591
Packit 8fb591
        if ((ptr = strrchr(in_file, '/'))) {
Packit 8fb591
            *ptr = '\0';
Packit 8fb591
            search_dir = in_file;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
    if (out_file) {
Packit 8fb591
        output = fopen(out_file, "w");
Packit 8fb591
        if (!input) {
Packit 8fb591
            fprintf(stderr, "Failed to open \"%s\" for writing (%s).\n", out_file, strerror(errno));
Packit 8fb591
            goto cleanup;
Packit 8fb591
        }
Packit 8fb591
    }
Packit 8fb591
Packit 8fb591
    ret = convert_yang2yin(output ? output : stdout, input ? input : stdin, search_dir);
Packit 8fb591
Packit 8fb591
cleanup:
Packit 8fb591
    if (input) {
Packit 8fb591
        fclose(input);
Packit 8fb591
    }
Packit 8fb591
    if (output) {
Packit 8fb591
        fclose(output);
Packit 8fb591
    }
Packit 8fb591
    return ret;
Packit 8fb591
}