Coverage Report

Created: 2024-02-29 06:11

/src/libyang/src/parser_yin.c
Line
Count
Source (jump to first uncovered line)
1
/**
2
 * @file parser_yin.c
3
 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
4
 * @author Michal Vasko <mvasko@cesnet.cz>
5
 * @brief YIN parser.
6
 *
7
 * Copyright (c) 2015 - 2022 CESNET, z.s.p.o.
8
 *
9
 * This source code is licensed under BSD 3-Clause License (the "License").
10
 * You may not use this file except in compliance with the License.
11
 * You may obtain a copy of the License at
12
 *
13
 *     https://opensource.org/licenses/BSD-3-Clause
14
 */
15
#define _GNU_SOURCE
16
17
#include <assert.h>
18
#include <ctype.h>
19
#include <errno.h>
20
#include <stdarg.h>
21
#include <stdbool.h>
22
#include <stdint.h>
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <string.h>
26
27
#include "compat.h"
28
#include "context.h"
29
#include "dict.h"
30
#include "in.h"
31
#include "in_internal.h"
32
#include "log.h"
33
#include "ly_common.h"
34
#include "parser_internal.h"
35
#include "parser_schema.h"
36
#include "path.h"
37
#include "set.h"
38
#include "tree.h"
39
#include "tree_data_internal.h"
40
#include "tree_edit.h"
41
#include "tree_schema.h"
42
#include "tree_schema_internal.h"
43
#include "xml.h"
44
45
struct lys_glob_unres;
46
47
/**
48
 * @brief check if given string is URI of yin namespace.
49
 *
50
 * @param ns Namespace URI to check.
51
 *
52
 * @return true if ns equals YIN_NS_URI false otherwise.
53
 */
54
0
#define IS_YIN_NS(ns) (strcmp(ns, YIN_NS_URI) == 0)
55
56
enum yin_argument {
57
    YIN_ARG_UNKNOWN = 0,   /**< parsed argument can not be matched with any supported yin argument keyword */
58
    YIN_ARG_NAME,          /**< argument name */
59
    YIN_ARG_TARGET_NODE,   /**< argument target-node */
60
    YIN_ARG_MODULE,        /**< argument module */
61
    YIN_ARG_VALUE,         /**< argument value */
62
    YIN_ARG_TEXT,          /**< argument text */
63
    YIN_ARG_CONDITION,     /**< argument condition */
64
    YIN_ARG_URI,           /**< argument uri */
65
    YIN_ARG_DATE,          /**< argument data */
66
    YIN_ARG_TAG,           /**< argument tag */
67
    YIN_ARG_NONE           /**< empty (special value) */
68
};
69
70
const char * const yin_attr_list[] = {
71
    [YIN_ARG_NAME] = "name",
72
    [YIN_ARG_TARGET_NODE] = "target-node",
73
    [YIN_ARG_MODULE] = "module",
74
    [YIN_ARG_VALUE] = "value",
75
    [YIN_ARG_TEXT] = "text",
76
    [YIN_ARG_CONDITION] = "condition",
77
    [YIN_ARG_URI] = "uri",
78
    [YIN_ARG_DATE] = "date",
79
    [YIN_ARG_TAG] = "tag",
80
    [YIN_ARG_NONE] = "none",
81
};
82
83
#define yin_attr2str(STMT) yin_attr_list[STMT]
84
85
#define VALID_VALS1 " Only valid value is \"%s\"."
86
#define VALID_VALS2 " Valid values are \"%s\" and \"%s\"."
87
#define VALID_VALS3 " Valid values are \"%s\", \"%s\" and \"%s\"."
88
#define VALID_VALS4 " Valid values are \"%s\", \"%s\", \"%s\" and \"%s\"."
89
90
/* shortcut to determin if keyword can in general be subelement of deviation regardles of it's type */
91
0
#define isdevsub(kw) (kw == LY_STMT_CONFIG || kw == LY_STMT_DEFAULT || kw == LY_STMT_MANDATORY || \
92
0
                      kw == LY_STMT_MAX_ELEMENTS || kw == LY_STMT_MIN_ELEMENTS ||              \
93
0
                      kw == LY_STMT_MUST || kw == LY_STMT_TYPE || kw == LY_STMT_UNIQUE ||         \
94
0
                      kw == LY_STMT_UNITS || kw == LY_STMT_EXTENSION_INSTANCE)
95
96
/* flags to set constraints of subelements */
97
0
#define YIN_SUBELEM_MANDATORY   0x01    /**< is set when subelement is mandatory */
98
0
#define YIN_SUBELEM_UNIQUE      0x02    /**< is set when subelement is unique */
99
0
#define YIN_SUBELEM_FIRST       0x04    /**< is set when subelement is actually yang argument mapped to yin element */
100
0
#define YIN_SUBELEM_VER2        0x08    /**< subelemnt is allowed only in modules with version at least 2 (YANG 1.1) */
101
102
0
#define YIN_SUBELEM_PARSED      0x80    /**< is set during parsing when given subelement is encountered for the first
103
                                             time to simply check validity of given constraints */
104
105
struct yin_subelement {
106
    enum ly_stmt type;      /**< type of keyword */
107
    void *dest;             /**< meta infromation passed to responsible function (mostly information about where parsed
108
                                 subelement should be stored) */
109
    uint16_t flags;         /**< describes constraints of subelement can be set to YIN_SUBELEM_MANDATORY,
110
                                 YIN_SUBELEM_UNIQUE, YIN_SUBELEM_FIRST, YIN_SUBELEM_VER2, and YIN_SUBELEM_DEFAULT_TEXT */
111
};
112
113
/* Meta information passed to yin_parse_argument function,
114
   holds information about where content of argument element will be stored. */
115
struct yin_argument_meta {
116
    uint16_t *flags;        /**< Argument flags */
117
    const char **argument;  /**< Argument value */
118
};
119
120
/**
121
 * @brief Meta information passed to functions working with tree_schema,
122
 *        that require additional information about parent node.
123
 */
124
struct tree_node_meta {
125
    struct lysp_node *parent;       /**< parent node */
126
    struct lysp_node **nodes;    /**< linked list of siblings */
127
};
128
129
/**
130
 * @brief Meta information passed to yin_parse_import function.
131
 */
132
struct import_meta {
133
    const char *prefix;             /**< module prefix. */
134
    struct lysp_import **imports;   /**< imports to add to. */
135
};
136
137
/**
138
 * @brief Meta information passed to yin_parse_include function.
139
 */
140
struct include_meta {
141
    const char *name;               /**< Module/submodule name. */
142
    struct lysp_include **includes; /**< [Sized array](@ref sizedarrays) of parsed includes to add to. */
143
};
144
145
/**
146
 * @brief Meta information passed to yin_parse_inout function.
147
 */
148
struct inout_meta {
149
    struct lysp_node *parent;          /**< Parent node. */
150
    struct lysp_node_action_inout *inout_p; /**< inout_p Input/output pointer to write to. */
151
};
152
153
/**
154
 * @brief Meta information passed to yin_parse_minmax function.
155
 */
156
struct minmax_dev_meta {
157
    uint32_t *lim;                      /**< min/max value to write to. */
158
    uint16_t *flags;                    /**< min/max flags to write to. */
159
    struct lysp_ext_instance **exts;    /**< extension instances to add to. */
160
};
161
162
LY_ERR yin_parse_content(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
163
        const void *parent, enum ly_stmt parent_stmt, const char **text_content, struct lysp_ext_instance **exts);
164
165
/**
166
 * @brief Match yang keyword from yin data.
167
 *
168
 * @param[in,out] ctx Yin parser context for logging and to store current state.
169
 * @param[in] name Start of keyword name
170
 * @param[in] name_len Lenght of keyword name.
171
 * @param[in] prefix Start of keyword prefix.
172
 * @param[in] prefix_len Lenght of prefix.
173
 * @param[in] parent Identification of parent element, use LY_STMT_NONE for elements without parent.
174
 * @return yang_keyword values.
175
 */
176
enum ly_stmt
177
yin_match_keyword(struct lysp_yin_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len,
178
        enum ly_stmt parent)
179
0
{
180
0
    const char *start = NULL;
181
0
    enum ly_stmt kw = LY_STMT_NONE;
182
0
    const struct lyxml_ns *ns = NULL;
183
0
    struct ly_in *in;
184
185
0
    if (!name || (name_len == 0)) {
186
0
        return LY_STMT_NONE;
187
0
    }
188
189
0
    ns = lyxml_ns_get(&ctx->xmlctx->ns, prefix, prefix_len);
190
0
    if (ns) {
191
0
        if (!IS_YIN_NS(ns->uri)) {
192
0
            return LY_STMT_EXTENSION_INSTANCE;
193
0
        }
194
0
    } else {
195
        /* elements without namespace are automatically unknown */
196
0
        return LY_STMT_NONE;
197
0
    }
198
199
0
    LY_CHECK_RET(ly_in_new_memory(name, &in), LY_STMT_NONE);
200
0
    start = in->current;
201
0
    kw = lysp_match_kw(in, NULL);
202
0
    name = in->current;
203
0
    ly_in_free(in, 0);
204
205
0
    if (name - start == (long)name_len) {
206
        /* this is done because of collision in yang statement value and yang argument mapped to yin element value */
207
0
        if ((kw == LY_STMT_VALUE) && (parent == LY_STMT_ERROR_MESSAGE)) {
208
0
            return LY_STMT_ARG_VALUE;
209
0
        }
210
0
        return kw;
211
0
    } else {
212
0
        if (strncmp(start, "text", name_len) == 0) {
213
0
            return LY_STMT_ARG_TEXT;
214
0
        } else {
215
0
            return LY_STMT_NONE;
216
0
        }
217
0
    }
218
0
}
219
220
/**
221
 * @brief Match argument name.
222
 *
223
 * @param[in] name String representing name.
224
 * @param[in] len Lenght of the name.
225
 * @return yin_argument values.
226
 */
227
enum yin_argument
228
yin_match_argument_name(const char *name, size_t len)
229
0
{
230
0
    enum yin_argument arg = YIN_ARG_UNKNOWN;
231
0
    size_t already_read = 0;
232
233
0
    LY_CHECK_RET(len == 0, YIN_ARG_NONE);
234
235
0
#define READ_INC(LEN) already_read += LEN
236
0
#define ARG_SET(STMT) arg=STMT
237
0
#define ARG_CHECK(STR, LEN) (!strncmp((name) + already_read, STR, LEN) && (READ_INC(LEN)))
238
239
0
    switch (*name) {
240
0
    case 'c':
241
0
        READ_INC(1);
242
0
        if (ARG_CHECK("ondition", 8)) {
243
0
            ARG_SET(YIN_ARG_CONDITION);
244
0
        }
245
0
        break;
246
247
0
    case 'd':
248
0
        READ_INC(1);
249
0
        if (ARG_CHECK("ate", 3)) {
250
0
            ARG_SET(YIN_ARG_DATE);
251
0
        }
252
0
        break;
253
254
0
    case 'm':
255
0
        READ_INC(1);
256
0
        if (ARG_CHECK("odule", 5)) {
257
0
            ARG_SET(YIN_ARG_MODULE);
258
0
        }
259
0
        break;
260
261
0
    case 'n':
262
0
        READ_INC(1);
263
0
        if (ARG_CHECK("ame", 3)) {
264
0
            ARG_SET(YIN_ARG_NAME);
265
0
        }
266
0
        break;
267
268
0
    case 't':
269
0
        READ_INC(1);
270
0
        if (ARG_CHECK("a", 1)) {
271
0
            if (ARG_CHECK("g", 1)) {
272
0
                ARG_SET(YIN_ARG_TAG);
273
0
            } else if (ARG_CHECK("rget-node", 9)) {
274
0
                ARG_SET(YIN_ARG_TARGET_NODE);
275
0
            }
276
0
        } else if (ARG_CHECK("ext", 3)) {
277
0
            ARG_SET(YIN_ARG_TEXT);
278
0
        }
279
0
        break;
280
281
0
    case 'u':
282
0
        READ_INC(1);
283
0
        if (ARG_CHECK("ri", 2)) {
284
0
            ARG_SET(YIN_ARG_URI);
285
0
        }
286
0
        break;
287
288
0
    case 'v':
289
0
        READ_INC(1);
290
0
        if (ARG_CHECK("alue", 4)) {
291
0
            ARG_SET(YIN_ARG_VALUE);
292
0
        }
293
0
        break;
294
0
    }
295
296
    /* whole argument must be matched */
297
0
    if (already_read != len) {
298
0
        arg = YIN_ARG_UNKNOWN;
299
0
    }
300
301
0
#undef ARG_CHECK
302
0
#undef ARG_SET
303
0
#undef READ_INC
304
305
0
    return arg;
306
0
}
307
308
0
#define IS_NODE_ELEM(kw) (kw == LY_STMT_ANYXML || kw == LY_STMT_ANYDATA || kw == LY_STMT_LEAF || kw == LY_STMT_LEAF_LIST || \
309
0
                          kw == LY_STMT_TYPEDEF || kw == LY_STMT_USES || kw == LY_STMT_LIST || kw == LY_STMT_NOTIFICATION || \
310
0
                          kw == LY_STMT_GROUPING || kw == LY_STMT_CONTAINER || kw == LY_STMT_CASE || kw == LY_STMT_CHOICE || \
311
0
                          kw == LY_STMT_ACTION || kw == LY_STMT_RPC || kw == LY_STMT_AUGMENT)
312
313
0
#define HAS_META(kw) (IS_NODE_ELEM(kw) || kw == LY_STMT_IMPORT || kw == LY_STMT_INCLUDE || kw == LY_STMT_INPUT || kw == LY_STMT_OUTPUT)
314
315
/**
316
 * @brief Free subelems information allocated on heap.
317
 *
318
 * @param[in] count Size of subelems array.
319
 * @param[in] subelems Subelems array to free.
320
 */
321
static void
322
subelems_deallocator(size_t count, struct yin_subelement *subelems)
323
0
{
324
0
    for (size_t i = 0; i < count; ++i) {
325
0
        if (HAS_META(subelems[i].type)) {
326
0
            free(subelems[i].dest);
327
0
        }
328
0
    }
329
330
0
    free(subelems);
331
0
}
332
333
/**
334
 * @brief Allocate subelems information on heap.
335
 *
336
 * @param[in] ctx YIN parser context, used for logging.
337
 * @param[in] count Number of subelements.
338
 * @param[in] parent Parent node if any.
339
 * @param[out] result Allocated subelems array.
340
 * @return LY_ERR values.
341
 */
342
static LY_ERR
343
subelems_allocator(struct lysp_yin_ctx *ctx, size_t count, struct lysp_node *parent,
344
        struct yin_subelement **result, ...)
345
0
{
346
0
    va_list ap;
347
348
0
    *result = calloc(count, sizeof **result);
349
0
    LY_CHECK_GOTO(!(*result), mem_err);
350
351
0
    va_start(ap, result);
352
0
    for (size_t i = 0; i < count; ++i) {
353
        /* TYPE */
354
0
        (*result)[i].type = va_arg(ap, enum ly_stmt);
355
        /* DEST */
356
0
        if (IS_NODE_ELEM((*result)[i].type)) {
357
0
            struct tree_node_meta *node_meta = NULL;
358
359
0
            node_meta = calloc(1, sizeof *node_meta);
360
0
            LY_CHECK_GOTO(!node_meta, mem_err);
361
0
            node_meta->parent = parent;
362
0
            node_meta->nodes = va_arg(ap, void *);
363
0
            (*result)[i].dest = node_meta;
364
0
        } else if ((*result)[i].type == LY_STMT_IMPORT) {
365
0
            struct import_meta *imp_meta = NULL;
366
367
0
            imp_meta = calloc(1, sizeof *imp_meta);
368
0
            LY_CHECK_GOTO(!imp_meta, mem_err);
369
0
            imp_meta->prefix = va_arg(ap, const char *);
370
0
            imp_meta->imports = va_arg(ap, struct lysp_import **);
371
0
            (*result)[i].dest = imp_meta;
372
0
        } else if ((*result)[i].type == LY_STMT_INCLUDE) {
373
0
            struct include_meta *inc_meta = NULL;
374
375
0
            inc_meta = calloc(1, sizeof *inc_meta);
376
0
            LY_CHECK_GOTO(!inc_meta, mem_err);
377
0
            inc_meta->name = va_arg(ap, const char *);
378
0
            inc_meta->includes = va_arg(ap, struct lysp_include **);
379
0
            (*result)[i].dest = inc_meta;
380
0
        } else if (((*result)[i].type == LY_STMT_INPUT) || ((*result)[i].type == LY_STMT_OUTPUT)) {
381
0
            struct inout_meta *inout_meta = NULL;
382
383
0
            inout_meta = calloc(1, sizeof *inout_meta);
384
0
            LY_CHECK_GOTO(!inout_meta, mem_err);
385
0
            inout_meta->parent = parent;
386
0
            inout_meta->inout_p = va_arg(ap, struct lysp_node_action_inout *);
387
0
            (*result)[i].dest = inout_meta;
388
0
        } else {
389
0
            (*result)[i].dest = va_arg(ap, void *);
390
0
        }
391
        /* FLAGS */
392
0
        (*result)[i].flags = va_arg(ap, int);
393
0
    }
394
0
    va_end(ap);
395
396
0
    return LY_SUCCESS;
397
398
0
mem_err:
399
0
    subelems_deallocator(count, *result);
400
0
    LOGMEM(ctx->xmlctx->ctx);
401
0
    return LY_EMEM;
402
0
}
403
404
/**
405
 * @brief Check that val is valid UTF8 character sequence of val_type.
406
 *        Doesn't check empty string, only character validity.
407
 *
408
 * @param[in] ctx Yin parser context for logging.
409
 * @param[in] val_type Type of the input string to select method of checking character validity.
410
 * @return LY_ERR values.
411
 */
412
LY_ERR
413
yin_validate_value(struct lysp_yin_ctx *ctx, enum yang_arg val_type)
414
0
{
415
0
    uint8_t prefix = 0;
416
0
    uint32_t c;
417
0
    size_t utf8_char_len, already_read = 0;
418
0
    const char *val;
419
420
0
    assert((ctx->xmlctx->status == LYXML_ELEM_CONTENT) || (ctx->xmlctx->status == LYXML_ATTR_CONTENT));
421
422
0
    val = ctx->xmlctx->value;
423
0
    while (already_read < ctx->xmlctx->value_len) {
424
0
        LY_CHECK_ERR_RET(ly_getutf8((const char **)&val, &c, &utf8_char_len),
425
0
                LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INCHAR, (val)[-utf8_char_len]), LY_EVALID);
426
427
0
        switch (val_type) {
428
0
        case Y_IDENTIF_ARG:
429
0
            LY_CHECK_RET(lysp_check_identifierchar((struct lysp_ctx *)ctx, c, already_read ? 0 : 1, NULL));
430
0
            break;
431
0
        case Y_PREF_IDENTIF_ARG:
432
0
            LY_CHECK_RET(lysp_check_identifierchar((struct lysp_ctx *)ctx, c, already_read ? 0 : 1, &prefix));
433
0
            break;
434
0
        case Y_STR_ARG:
435
0
        case Y_MAYBE_STR_ARG:
436
0
            LY_CHECK_RET(lysp_check_stringchar((struct lysp_ctx *)ctx, c));
437
0
            break;
438
0
        }
439
440
0
        already_read += utf8_char_len;
441
0
        LY_CHECK_ERR_RET(already_read > ctx->xmlctx->value_len, LOGINT(ctx->xmlctx->ctx), LY_EINT);
442
0
    }
443
444
0
    if ((already_read == 0) &&
445
0
            ((val_type == Y_PREF_IDENTIF_ARG) || (val_type == Y_IDENTIF_ARG))) {
446
        /* Empty identifier or prefix*/
447
0
        LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Empty identifier is not allowed.");
448
0
        return LY_EVALID;
449
0
    }
450
451
0
    return LY_SUCCESS;
452
0
}
453
454
/**
455
 * @brief Parse yin attributes.
456
 *
457
 * @param[in,out] ctx YIN parser context for logging and to store current state.
458
 * @param[in] arg_type Type of argument that is expected in parsed element (use YIN_ARG_NONE for elements without
459
 *            special argument).
460
 * @param[out] arg_val Where value of argument should be stored. Can be NULL iff arg_type is specified as YIN_ARG_NONE.
461
 * @param[in] val_type Type of expected value of attribute.
462
 * @param[in] current_element Identification of current element, used for logging.
463
 * @return LY_ERR values.
464
 */
465
static LY_ERR
466
yin_parse_attribute(struct lysp_yin_ctx *ctx, enum yin_argument arg_type, const char **arg_val, enum yang_arg val_type,
467
        enum ly_stmt current_element)
468
0
{
469
0
    enum yin_argument arg = YIN_ARG_UNKNOWN;
470
0
    bool found = false;
471
472
    /* validation of attributes */
473
0
    while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
474
        /* yin arguments represented as attributes have no namespace, which in this case means no prefix */
475
0
        if (!ctx->xmlctx->prefix) {
476
0
            arg = yin_match_argument_name(ctx->xmlctx->name, ctx->xmlctx->name_len);
477
0
            if (arg == YIN_ARG_NONE) {
478
                /* skip it */
479
0
                LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
480
0
            } else if (arg == arg_type) {
481
0
                LY_CHECK_ERR_RET(found, LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_DUP_ATTR,
482
0
                        yin_attr2str(arg), lyplg_ext_stmt2str(current_element)), LY_EVALID);
483
0
                found = true;
484
485
                /* go to value */
486
0
                LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
487
0
                LY_CHECK_RET(yin_validate_value(ctx, val_type));
488
0
                INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg_val);
489
0
                LY_CHECK_RET(!(*arg_val), LY_EMEM);
490
0
            } else {
491
0
                LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_ATTR, (int)ctx->xmlctx->name_len,
492
0
                        ctx->xmlctx->name, lyplg_ext_stmt2str(current_element));
493
0
                return LY_EVALID;
494
0
            }
495
0
        } else {
496
            /* skip it */
497
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
498
0
        }
499
500
        /* next attribute */
501
0
        LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
502
0
    }
503
504
    /* anything else than Y_MAYBE_STR_ARG is mandatory */
505
0
    if ((val_type != Y_MAYBE_STR_ARG) && !found) {
506
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LYVE_SYNTAX_YIN, "Missing mandatory attribute %s of %s element.",
507
0
                yin_attr2str(arg_type), lyplg_ext_stmt2str(current_element));
508
0
        return LY_EVALID;
509
0
    }
510
511
0
    return LY_SUCCESS;
512
0
}
513
514
/**
515
 * @brief Get record with given type.
516
 *
517
 * @param[in] type Type of wanted record.
518
 * @param[in] array_size Size of array.
519
 * @param[in] array Searched array.
520
 * @return Pointer to desired record on success, NULL if element is not in the array.
521
 */
522
static struct yin_subelement *
523
get_record(enum ly_stmt type, LY_ARRAY_COUNT_TYPE array_size, struct yin_subelement *array)
524
0
{
525
0
    for (LY_ARRAY_COUNT_TYPE u = 0; u < array_size; ++u) {
526
0
        if (array[u].type == type) {
527
0
            return &array[u];
528
0
        }
529
0
    }
530
0
    return NULL;
531
0
}
532
533
/**
534
 * @brief Helper function to check mandatory constraint of subelement.
535
 *
536
 * @param[in,out] ctx YIN parser context for logging and to store current state.
537
 * @param[in] subelem_info Array of information about subelements.
538
 * @param[in] subelem_info_size Size of subelem_info array.
539
 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
540
 * @return LY_ERR values.
541
 */
542
static LY_ERR
543
yin_check_subelem_mandatory_constraint(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info,
544
        signed char subelem_info_size, enum ly_stmt current_element)
545
0
{
546
0
    for (signed char i = 0; i < subelem_info_size; ++i) {
547
        /* if there is element that is mandatory and isn't parsed log error and return LY_EVALID */
548
0
        if ((subelem_info[i].flags & YIN_SUBELEM_MANDATORY) && !(subelem_info[i].flags & YIN_SUBELEM_PARSED)) {
549
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_MAND_SUBELEM,
550
0
                    lyplg_ext_stmt2str(subelem_info[i].type), lyplg_ext_stmt2str(current_element));
551
0
            return LY_EVALID;
552
0
        }
553
0
    }
554
555
0
    return LY_SUCCESS;
556
0
}
557
558
/**
559
 * @brief Helper function to check "first" constraint of subelement.
560
 *
561
 * @param[in,out] ctx YIN parser context for logging and to store current state.
562
 * @param[in] subelem_info Array of information about subelements.
563
 * @param[in] subelem_info_size Size of subelem_info array.
564
 * @param[in] current_element Identification of element that is currently being parsed, used for logging.
565
 * @param[in] exp_first Record in subelem_info array that is expected to be defined as first subelement, used for logging.
566
 * @return LY_ERR values.
567
 */
568
static LY_ERR
569
yin_check_subelem_first_constraint(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info,
570
        signed char subelem_info_size, enum ly_stmt current_element,
571
        struct yin_subelement *exp_first)
572
0
{
573
0
    for (signed char i = 0; i < subelem_info_size; ++i) {
574
0
        if (subelem_info[i].flags & YIN_SUBELEM_PARSED) {
575
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
576
0
                    lyplg_ext_stmt2str(exp_first->type), lyplg_ext_stmt2str(current_element));
577
0
            return LY_EVALID;
578
0
        }
579
0
    }
580
581
0
    return LY_SUCCESS;
582
0
}
583
584
/**
585
 * @brief Parse simple element without any special constraints and argument mapped to yin attribute,
586
 * for example prefix or namespace element.
587
 *
588
 * @param[in,out] ctx YIN parser context for logging and to store current state.
589
 * @param[in] parent Current statement parent.
590
 * @param[in] parent_stmt Type of @p parent statement.
591
 * @param[out] value Where value of attribute should be stored.
592
 * @param[in] arg_type Expected type of attribute.
593
 * @param[in] arg_val_type Type of expected value of attribute.
594
 * @param[in,out] exts Extension instances to add to.
595
 * @return LY_ERR values.
596
 */
597
static LY_ERR
598
yin_parse_simple_element(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt, const char **value,
599
        enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
600
0
{
601
0
    struct yin_subelement subelems[] = {
602
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
603
0
    };
604
605
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
606
0
    LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, parent_stmt));
607
608
0
    return yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, parent_stmt, NULL, exts);
609
0
}
610
611
/**
612
 * @brief Parse path element.
613
 *
614
 * @param[in,out] ctx YIN parser context for logging and to store current state.
615
 * @param[out] type Type structure to store parsed value, flags and extension instances.
616
 * @return LY_ERR values.
617
 */
618
static LY_ERR
619
yin_parse_path(struct lysp_yin_ctx *ctx, struct lysp_type *type)
620
0
{
621
0
    LY_ERR ret;
622
0
    const char *str_path;
623
624
0
    LY_CHECK_RET(yin_parse_simple_element(ctx, type, LY_STMT_PATH, &str_path, YIN_ARG_VALUE, Y_STR_ARG, &type->exts));
625
626
0
    ret = ly_path_parse(ctx->xmlctx->ctx, NULL, str_path, 0, 1, LY_PATH_BEGIN_EITHER,
627
0
            LY_PATH_PREFIX_OPTIONAL, LY_PATH_PRED_LEAFREF, &type->path);
628
0
    lydict_remove(ctx->xmlctx->ctx, str_path);
629
0
    LY_CHECK_RET(ret);
630
0
    type->flags |= LYS_SET_PATH;
631
632
0
    return LY_SUCCESS;
633
0
}
634
635
/**
636
 * @brief Add extension array to context exts instances.
637
 *
638
 * @param[in] ctx YIN parser context.
639
 * @param[in] exts Parsed extension array that is final (no realloc anymore).
640
 * @return LY_ERR value.
641
 */
642
static LY_ERR
643
yin_unres_exts_add(struct lysp_yin_ctx *ctx, struct lysp_ext_instance *exts)
644
0
{
645
0
    if (!exts) {
646
0
        return LY_SUCCESS;
647
0
    }
648
649
0
    return ly_set_add(&ctx->main_ctx->ext_inst, exts, 1, NULL);
650
0
}
651
652
/**
653
 * @brief Parse pattern element.
654
 *
655
 * @param[in,out] ctx YIN parser context for logging and to store current state.
656
 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
657
 * @return LY_ERR values.
658
 */
659
static LY_ERR
660
yin_parse_pattern(struct lysp_yin_ctx *ctx, struct lysp_type *type)
661
0
{
662
0
    const char *real_value = NULL;
663
0
    char *saved_value = NULL;
664
0
    struct lysp_restr *restr;
665
666
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->patterns, restr, LY_EMEM);
667
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
668
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &real_value, Y_STR_ARG, LY_STMT_PATTERN));
669
0
    size_t len = strlen(real_value);
670
671
0
    saved_value = malloc(len + 2);
672
0
    LY_CHECK_ERR_RET(!saved_value, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
673
0
    memmove(saved_value + 1, real_value, len);
674
0
    lydict_remove(ctx->xmlctx->ctx, real_value);
675
0
    saved_value[0] = LYSP_RESTR_PATTERN_ACK;
676
0
    saved_value[len + 1] = '\0';
677
0
    LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, saved_value, &restr->arg.str));
678
0
    restr->arg.mod = PARSER_CUR_PMOD(ctx);
679
0
    type->flags |= LYS_SET_PATTERN;
680
681
0
    struct yin_subelement subelems[] = {
682
0
        {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
683
0
        {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
684
0
        {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
685
0
        {LY_STMT_MODIFIER, &restr->arg, YIN_SUBELEM_UNIQUE},
686
0
        {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
687
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
688
0
    };
689
690
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr, LY_STMT_PATTERN, NULL, &restr->exts));
691
692
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
693
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, restr->exts));
694
695
0
    return LY_SUCCESS;
696
0
}
697
698
/**
699
 * @brief Parse fraction-digits element.
700
 *
701
 * @param[in,out] ctx YIN parser context for logging and to store current state.
702
 * @param[in,out] type Type structure to store value, flags and extension instances.
703
 * @return LY_ERR values.
704
 */
705
static LY_ERR
706
yin_parse_fracdigits(struct lysp_yin_ctx *ctx, struct lysp_type *type)
707
0
{
708
0
    const char *temp_val = NULL;
709
0
    char *ptr;
710
0
    unsigned long long num;
711
712
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
713
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_FRACTION_DIGITS));
714
715
0
    if ((temp_val[0] == '\0') || (temp_val[0] == '0') || !isdigit(temp_val[0])) {
716
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
717
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
718
0
        return LY_EVALID;
719
0
    }
720
721
0
    errno = 0;
722
0
    num = strtoull(temp_val, &ptr, LY_BASE_DEC);
723
0
    if (*ptr != '\0') {
724
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
725
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
726
0
        return LY_EVALID;
727
0
    }
728
0
    if ((errno == ERANGE) || (num > LY_TYPE_DEC64_FD_MAX)) {
729
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "fraction-digits");
730
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
731
0
        return LY_EVALID;
732
0
    }
733
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
734
0
    type->fraction_digits = num;
735
0
    type->flags |= LYS_SET_FRDIGITS;
736
0
    struct yin_subelement subelems[] = {
737
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
738
0
    };
739
740
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_FRACTION_DIGITS, NULL, &type->exts));
741
742
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
743
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, type->exts));
744
745
0
    return LY_SUCCESS;
746
0
}
747
748
/**
749
 * @brief Parse enum element.
750
 *
751
 * @param[in,out] ctx YIN parser context for logging and to store current state.
752
 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
753
 * @return LY_ERR values.
754
 */
755
static LY_ERR
756
yin_parse_enum(struct lysp_yin_ctx *ctx, struct lysp_type *type)
757
0
{
758
0
    struct lysp_type_enum *en;
759
760
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->enums, en, LY_EMEM);
761
0
    type->flags |= LYS_SET_ENUM;
762
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
763
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_STR_ARG, LY_STMT_ENUM));
764
0
    LY_CHECK_RET(lysp_check_enum_name((struct lysp_ctx *)ctx, en->name, strlen(en->name)));
765
0
    CHECK_NONEMPTY((struct lysp_ctx *)ctx, strlen(en->name), "enum");
766
0
    CHECK_UNIQUENESS((struct lysp_ctx *)ctx, type->enums, name, "enum", en->name);
767
768
0
    struct yin_subelement subelems[] = {
769
0
        {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
770
0
        {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
771
0
        {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
772
0
        {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
773
0
        {LY_STMT_VALUE, en, YIN_SUBELEM_UNIQUE},
774
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
775
0
    };
776
777
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), en, LY_STMT_ENUM, NULL, &en->exts));
778
779
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
780
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, en->exts));
781
782
0
    return LY_SUCCESS;
783
0
}
784
785
/**
786
 * @brief Parse bit element.
787
 *
788
 * @param[in,out] ctx YIN parser context for logging and to store current state.
789
 * @param[in,out] type Type structure to store parsed value, flags and extension instances.
790
 * @return LY_ERR values.
791
 */
792
static LY_ERR
793
yin_parse_bit(struct lysp_yin_ctx *ctx, struct lysp_type *type)
794
0
{
795
0
    struct lysp_type_enum *en;
796
797
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->bits, en, LY_EMEM);
798
0
    type->flags |= LYS_SET_BIT;
799
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
800
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &en->name, Y_IDENTIF_ARG, LY_STMT_BIT));
801
0
    CHECK_UNIQUENESS((struct lysp_ctx *)ctx, type->bits, name, "bit", en->name);
802
803
0
    struct yin_subelement subelems[] = {
804
0
        {LY_STMT_DESCRIPTION, &en->dsc, YIN_SUBELEM_UNIQUE},
805
0
        {LY_STMT_IF_FEATURE, &en->iffeatures, 0},
806
0
        {LY_STMT_POSITION, en, YIN_SUBELEM_UNIQUE},
807
0
        {LY_STMT_REFERENCE, &en->ref, YIN_SUBELEM_UNIQUE},
808
0
        {LY_STMT_STATUS, &en->flags, YIN_SUBELEM_UNIQUE},
809
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
810
0
    };
811
812
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), en, LY_STMT_BIT, NULL, &en->exts));
813
814
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
815
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, en->exts));
816
817
0
    return LY_SUCCESS;
818
0
}
819
820
/**
821
 * @brief Parse simple element without any special constraints and argument mapped to yin attribute, that can have
822
 * more instances, such as base or if-feature.
823
 *
824
 * @param[in,out] ctx YIN parser context for logging and to store current state.
825
 * @param[in] parent_stmt Type of parent statement.
826
 * @param[out] values Parsed values to add to.
827
 * @param[in] arg_type Expected type of attribute.
828
 * @param[in] arg_val_type Type of expected value of attribute.
829
 * @param[in,out] exts Extension instances to add to.
830
 * @return LY_ERR values.
831
 */
832
static LY_ERR
833
yin_parse_simple_elements(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, const char ***values,
834
        enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
835
0
{
836
0
    const char **value;
837
0
    LY_ARRAY_COUNT_TYPE index = LY_ARRAY_COUNT(*values);
838
0
    struct yin_subelement subelems[] = {
839
0
        {LY_STMT_EXTENSION_INSTANCE, &index, 0}
840
0
    };
841
842
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *values, value, LY_EMEM);
843
844
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
845
0
    LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, value, arg_val_type, parent_stmt));
846
847
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), *values, parent_stmt, NULL, exts));
848
849
0
    return LY_SUCCESS;
850
0
}
851
852
/**
853
 * @brief Parse simple element without any special constraints and argument mapped to yin attribute.
854
 *
855
 * @param[in,out] ctx YIN parser context for logging and to store current state.
856
 * @param[in] parent Current statement parent.
857
 * @param[in] parent_stmt Type of @p parent statement.
858
 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
859
 * @param[in] arg_type Expected type of attribute.
860
 * @param[in] arg_val_type Type of expected value of attribute.
861
 * @param[in,out] exts Extension instances to add to.
862
 * @return LY_ERR values.
863
 */
864
static LY_ERR
865
yin_parse_simple_elem(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt, struct yin_subelement *subinfo,
866
        enum yin_argument arg_type, enum yang_arg arg_val_type, struct lysp_ext_instance **exts)
867
0
{
868
0
    if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
869
0
        LY_CHECK_RET(yin_parse_simple_element(ctx, parent, parent_stmt, (const char **)subinfo->dest, arg_type,
870
0
                arg_val_type, exts));
871
0
    } else {
872
0
        LY_CHECK_RET(yin_parse_simple_elements(ctx, parent_stmt, (const char ***)subinfo->dest, arg_type,
873
0
                arg_val_type, exts));
874
0
    }
875
876
0
    return LY_SUCCESS;
877
0
}
878
879
/**
880
 * @brief Parse base element.
881
 *
882
 * @param[in,out] ctx YIN parser context for logging and to store current state.
883
 * @param[in] parent_stmt Type of parent statement.
884
 * @param[out] dest Where parsed values should be stored.
885
 * @param[in,out] exts Extension instances to add to.
886
 * @return LY_ERR values.
887
 */
888
static LY_ERR
889
yin_parse_base(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, void *dest, struct lysp_ext_instance **exts)
890
0
{
891
0
    struct lysp_type *type;
892
893
0
    if (parent_stmt == LY_STMT_TYPE) {
894
0
        type = (struct lysp_type *)dest;
895
0
        LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, &type->bases, YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
896
0
        type->flags |= LYS_SET_BASE;
897
0
    } else if (parent_stmt == LY_STMT_IDENTITY) {
898
0
        LY_CHECK_RET(yin_parse_simple_elements(ctx, LY_STMT_BASE, (const char ***)dest, YIN_ARG_NAME, Y_PREF_IDENTIF_ARG, exts));
899
0
    } else {
900
0
        LOGINT(ctx->xmlctx->ctx);
901
0
        return LY_EINT;
902
0
    }
903
904
0
    return LY_SUCCESS;
905
0
}
906
907
/**
908
 * @brief Parse require-instance element.
909
 *
910
 * @param[in,out] ctx YIN parser context for logging and to store current state.
911
 * @param[out] type Type structure to store value, flag and extensions.
912
 * @return LY_ERR values.
913
 */
914
static LY_ERR
915
yin_pasrse_reqinstance(struct lysp_yin_ctx *ctx, struct lysp_type *type)
916
0
{
917
0
    const char *temp_val = NULL;
918
0
    struct yin_subelement subelems[] = {
919
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
920
0
    };
921
922
0
    type->flags |= LYS_SET_REQINST;
923
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
924
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_REQUIRE_INSTANCE));
925
0
    if (strcmp(temp_val, "true") == 0) {
926
0
        type->require_instance = 1;
927
0
    } else if (strcmp(temp_val, "false") != 0) {
928
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
929
0
                "require-instance", "true", "false");
930
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
931
0
        return LY_EVALID;
932
0
    }
933
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
934
935
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_REQUIRE_INSTANCE, NULL, &type->exts));
936
937
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
938
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, type->exts));
939
940
0
    return LY_SUCCESS;
941
0
}
942
943
/**
944
 * @brief Parse modifier element.
945
 *
946
 * @param[in,out] ctx YIN parser context for logging and to store current state.
947
 * @param[in] parent Current statement parent.
948
 * @param[in,out] pat Value to write to.
949
 * @param[in,out] exts Extension instances to add to.
950
 * @return LY_ERR values.
951
 */
952
static LY_ERR
953
yin_parse_modifier(struct lysp_yin_ctx *ctx, const void *parent, const char **pat, struct lysp_ext_instance **exts)
954
0
{
955
0
    const char *temp_val;
956
0
    char *modified_val;
957
0
    struct yin_subelement subelems[] = {
958
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
959
0
    };
960
961
0
    assert(**pat == 0x06);
962
963
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
964
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MODIFIER));
965
0
    if (strcmp(temp_val, "invert-match") != 0) {
966
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS1, temp_val, "value",
967
0
                "modifier", "invert-match");
968
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
969
0
        return LY_EVALID;
970
0
    }
971
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
972
973
    /* allocate new value */
974
0
    modified_val = malloc(strlen(*pat) + 1);
975
0
    LY_CHECK_ERR_RET(!modified_val, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
976
0
    strcpy(modified_val, *pat);
977
0
    lydict_remove(ctx->xmlctx->ctx, *pat);
978
979
    /* modify the new value */
980
0
    modified_val[0] = LYSP_RESTR_PATTERN_NACK;
981
0
    LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, modified_val, pat));
982
983
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_MODIFIER, NULL, exts));
984
985
0
    return LY_SUCCESS;
986
0
}
987
988
/**
989
 * @brief Parse a restriction element (length, range or one instance of must).
990
 *
991
 * @param[in,out] ctx YIN parser context for logging and to store current state.
992
 * @param[in] restr_kw Identificaton of element that is being parsed, can be set to LY_STMT_MUST, LY_STMT_LENGTH or LY_STMT_RANGE.
993
 * @param[in] restr Value to write to.
994
 * @return LY_ERR values.
995
 */
996
static LY_ERR
997
yin_parse_restriction(struct lysp_yin_ctx *ctx, enum ly_stmt restr_kw, struct lysp_restr *restr)
998
0
{
999
0
    struct yin_subelement subelems[] = {
1000
0
        {LY_STMT_DESCRIPTION, &restr->dsc, YIN_SUBELEM_UNIQUE},
1001
0
        {LY_STMT_ERROR_APP_TAG, &restr->eapptag, YIN_SUBELEM_UNIQUE},
1002
0
        {LY_STMT_ERROR_MESSAGE, &restr->emsg, YIN_SUBELEM_UNIQUE},
1003
0
        {LY_STMT_REFERENCE, &restr->ref, YIN_SUBELEM_UNIQUE},
1004
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1005
0
    };
1006
    /* argument of must is called condition, but argument of length and range is called value */
1007
0
    enum yin_argument arg_type = (restr_kw == LY_STMT_MUST) ? YIN_ARG_CONDITION : YIN_ARG_VALUE;
1008
1009
0
    assert(restr_kw == LY_STMT_MUST || restr_kw == LY_STMT_LENGTH || restr_kw == LY_STMT_RANGE);
1010
1011
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1012
0
    LY_CHECK_RET(yin_parse_attribute(ctx, arg_type, &restr->arg.str, Y_STR_ARG, restr_kw));
1013
0
    restr->arg.mod = PARSER_CUR_PMOD(ctx);
1014
1015
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), restr, restr_kw, NULL, &restr->exts));
1016
1017
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1018
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, restr->exts));
1019
1020
0
    return LY_SUCCESS;
1021
0
}
1022
1023
/**
1024
 * @brief Parse range element.
1025
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1026
 * @param[out] type Type structure to store parsed value and flags.
1027
 * @return LY_ERR values.
1028
 */
1029
static LY_ERR
1030
yin_parse_range(struct lysp_yin_ctx *ctx, struct lysp_type *type)
1031
0
{
1032
0
    type->range = calloc(1, sizeof *type->range);
1033
0
    LY_CHECK_ERR_RET(!type->range, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1034
0
    LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_RANGE, type->range));
1035
0
    type->flags |= LYS_SET_RANGE;
1036
1037
0
    return LY_SUCCESS;
1038
0
}
1039
1040
/**
1041
 * @brief Parse length element.
1042
 *
1043
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1044
 * @param[out] type Type structure to store parsed value and flags.
1045
 * @return LY_ERR values.
1046
 */
1047
static LY_ERR
1048
yin_parse_length(struct lysp_yin_ctx *ctx, struct lysp_type *type)
1049
0
{
1050
0
    type->length = calloc(1, sizeof *type->length);
1051
0
    LY_CHECK_ERR_RET(!type->length, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1052
0
    LY_CHECK_RET(yin_parse_restriction(ctx, LY_STMT_LENGTH, type->length));
1053
0
    type->flags |= LYS_SET_LENGTH;
1054
1055
0
    return LY_SUCCESS;
1056
0
}
1057
1058
/**
1059
 * @brief Parse must element.
1060
 *
1061
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1062
 * @param[in,out] restrs Restrictions to add to.
1063
 * @return LY_ERR values.
1064
 */
1065
static LY_ERR
1066
yin_parse_must(struct lysp_yin_ctx *ctx, struct lysp_restr **restrs)
1067
0
{
1068
0
    struct lysp_restr *restr;
1069
1070
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *restrs, restr, LY_EMEM);
1071
0
    return yin_parse_restriction(ctx, LY_STMT_MUST, restr);
1072
0
}
1073
1074
/**
1075
 * @brief Parse a node id into an array.
1076
 *
1077
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1078
 * @param[in] parent_stmt Type of parent statement.
1079
 * @param[in] subinfo Information about subelement, is used to determin which function should be called and where to store parsed value.
1080
 * @param[in,out] exts Extension instances to add to.
1081
 * @return LY_ERR values.
1082
 */
1083
static LY_ERR
1084
yin_parse_qname(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct yin_subelement *subinfo,
1085
        struct lysp_ext_instance **exts)
1086
0
{
1087
0
    struct lysp_qname *qname, **qnames;
1088
1089
0
    switch (parent_stmt) {
1090
0
    case LY_STMT_DEFAULT:
1091
0
        if (subinfo->flags & YIN_SUBELEM_UNIQUE) {
1092
0
            qname = (struct lysp_qname *)subinfo->dest;
1093
0
        } else {
1094
0
            qnames = (struct lysp_qname **)subinfo->dest;
1095
0
            LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1096
0
        }
1097
0
        qname->mod = PARSER_CUR_PMOD(ctx);
1098
0
        return yin_parse_simple_element(ctx, qname, parent_stmt, &qname->str, YIN_ARG_VALUE, Y_STR_ARG, exts);
1099
0
    case LY_STMT_UNIQUE:
1100
0
        assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1101
1102
0
        qnames = (struct lysp_qname **)subinfo->dest;
1103
0
        LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1104
0
        qname->mod = PARSER_CUR_PMOD(ctx);
1105
0
        return yin_parse_simple_element(ctx, *qnames, parent_stmt, &qname->str, YIN_ARG_TAG, Y_STR_ARG, exts);
1106
0
    case LY_STMT_IF_FEATURE:
1107
0
        assert(!(subinfo->flags & YIN_SUBELEM_UNIQUE));
1108
1109
0
        qnames = (struct lysp_qname **)subinfo->dest;
1110
0
        LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *qnames, qname, LY_EMEM);
1111
0
        qname->mod = PARSER_CUR_PMOD(ctx);
1112
0
        return yin_parse_simple_element(ctx, *qnames, parent_stmt, &qname->str, YIN_ARG_NAME, Y_STR_ARG, exts);
1113
0
    default:
1114
0
        break;
1115
0
    }
1116
1117
0
    LOGINT(ctx->xmlctx->ctx);
1118
0
    return LY_EINT;
1119
0
}
1120
1121
/**
1122
 * @brief Parse position or value element.
1123
 *
1124
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1125
 * @param[in] parent_stmt Type of parent statement.
1126
 * @param[out] enm Enum structure to save value, flags and extension instances.
1127
 * @return LY_ERR values.
1128
 */
1129
static LY_ERR
1130
yin_parse_value_pos(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct lysp_type_enum *enm)
1131
0
{
1132
0
    LY_ERR ret = LY_SUCCESS;
1133
0
    const char *temp_val = NULL;
1134
0
    char *ptr;
1135
0
    long long num = 0;
1136
0
    unsigned long long unum = 0;
1137
1138
0
    assert(parent_stmt == LY_STMT_POSITION || parent_stmt == LY_STMT_VALUE);
1139
1140
    /* set value flag */
1141
0
    enm->flags |= LYS_SET_VALUE;
1142
1143
    /* get attribute value */
1144
0
    LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
1145
0
    LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, parent_stmt), cleanup);
1146
0
    if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '+') ||
1147
0
            ((temp_val[0] == '0') && (temp_val[1] != '\0')) || ((parent_stmt == LY_STMT_POSITION) && !strcmp(temp_val, "-0"))) {
1148
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
1149
0
        ret = LY_EVALID;
1150
0
        goto cleanup;
1151
0
    }
1152
1153
    /* convert value */
1154
0
    errno = 0;
1155
0
    if (parent_stmt == LY_STMT_VALUE) {
1156
0
        num = strtoll(temp_val, &ptr, LY_BASE_DEC);
1157
0
        if ((num < INT64_C(-2147483648)) || (num > INT64_C(2147483647))) {
1158
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
1159
0
            ret = LY_EVALID;
1160
0
            goto cleanup;
1161
0
        }
1162
0
    } else {
1163
0
        unum = strtoull(temp_val, &ptr, LY_BASE_DEC);
1164
0
        if (unum > UINT64_C(4294967295)) {
1165
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
1166
0
            ret = LY_EVALID;
1167
0
            goto cleanup;
1168
0
        }
1169
0
    }
1170
    /* check if whole argument value was converted */
1171
0
    if (*ptr != '\0') {
1172
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
1173
0
        ret = LY_EVALID;
1174
0
        goto cleanup;
1175
0
    }
1176
0
    if (errno == ERANGE) {
1177
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", lyplg_ext_stmt2str(parent_stmt));
1178
0
        ret = LY_EVALID;
1179
0
        goto cleanup;
1180
0
    }
1181
    /* save correctly ternary operator can't be used because num and unum have different signes */
1182
0
    if (parent_stmt == LY_STMT_VALUE) {
1183
0
        enm->value = num;
1184
0
    } else {
1185
0
        enm->value = unum;
1186
0
    }
1187
1188
    /* parse subelements */
1189
0
    struct yin_subelement subelems[] = {
1190
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1191
0
    };
1192
1193
0
    LY_CHECK_GOTO(ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), enm, parent_stmt, NULL, &enm->exts), cleanup);
1194
1195
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1196
0
    LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, enm->exts), cleanup);
1197
1198
0
cleanup:
1199
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
1200
0
    return ret;
1201
0
}
1202
1203
/**
1204
 * @brief Parse belongs-to element.
1205
 *
1206
 * @param[in] ctx YIN parser context for logging and to store current state.
1207
 * @param[out] submod Structure of submodule that is being parsed.
1208
 * @param[in,out] exts Extension instances to add to.
1209
 * @return LY_ERR values
1210
 */
1211
static LY_ERR
1212
yin_parse_belongs_to(struct lysp_yin_ctx *ctx, struct lysp_submodule *submod, struct lysp_ext_instance **exts)
1213
0
{
1214
0
    const char *belongsto;
1215
0
    struct yin_subelement subelems[] = {
1216
0
        {LY_STMT_PREFIX, &submod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
1217
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1218
0
    };
1219
1220
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1221
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &belongsto, Y_IDENTIF_ARG, LY_STMT_BELONGS_TO));
1222
0
    if (PARSER_CUR_PMOD(ctx)->mod->name != belongsto) {
1223
0
        LOGVAL_PARSER(ctx, LYVE_SYNTAX_YIN, "Submodule \"belongs-to\" value \"%s\" does not match its module name \"%s\".",
1224
0
                belongsto, PARSER_CUR_PMOD(ctx)->mod->name);
1225
0
        lydict_remove(ctx->xmlctx->ctx, belongsto);
1226
0
        return LY_EVALID;
1227
0
    }
1228
0
    lydict_remove(ctx->xmlctx->ctx, belongsto);
1229
1230
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), submod, LY_STMT_BELONGS_TO, NULL, exts));
1231
1232
0
    return LY_SUCCESS;
1233
0
}
1234
1235
/**
1236
 * @brief Function to parse meta tags (description, contact, ...) eg. elements with
1237
 * text element as child.
1238
 *
1239
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1240
 * @param[in] parent Current statement parent.
1241
 * @param[in] parent_stmt Type of @p parent statement.
1242
 * @param[out] value Where the content of meta element should be stored.
1243
 * @param[in,out] exts Extension instances to add to.
1244
 * @return LY_ERR values.
1245
 */
1246
static LY_ERR
1247
yin_parse_meta(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt, const char **value,
1248
        struct lysp_ext_instance **exts)
1249
0
{
1250
0
    struct yin_subelement subelems[] = {
1251
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1252
0
        {LY_STMT_ARG_TEXT, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1253
0
    };
1254
1255
0
    assert(parent_stmt == LY_STMT_ORGANIZATION || parent_stmt == LY_STMT_CONTACT || parent_stmt == LY_STMT_DESCRIPTION ||
1256
0
            parent_stmt == LY_STMT_REFERENCE);
1257
1258
    /* check attributes */
1259
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1260
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, parent_stmt));
1261
1262
    /* parse content */
1263
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, parent_stmt, NULL, exts));
1264
1265
0
    return LY_SUCCESS;
1266
0
}
1267
1268
/**
1269
 * @brief Parse error-message element.
1270
 *
1271
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1272
 * @param[in] parent Current statement parent.
1273
 * @param[out] value Where the content of error-message element should be stored.
1274
 * @param[in,out] exts Extension instances to add to.
1275
 * @return LY_ERR values.
1276
 */
1277
static LY_ERR
1278
yin_parse_err_msg(struct lysp_yin_ctx *ctx, const void *parent, const char **value, struct lysp_ext_instance **exts)
1279
0
{
1280
0
    struct yin_subelement subelems[] = {
1281
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1282
0
        {LY_STMT_ARG_VALUE, value, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE | YIN_SUBELEM_FIRST}
1283
0
    };
1284
1285
    /* check attributes */
1286
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1287
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, LY_STMT_ERROR_MESSAGE));
1288
1289
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ERROR_MESSAGE, NULL, exts));
1290
1291
0
    return LY_SUCCESS;
1292
0
}
1293
1294
/**
1295
 * @brief Parse type element.
1296
 *
1297
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1298
 * @param[in] parent_stmt Type of parent statement.
1299
 * @param[in,out] subinfo Information about subelement, is used to determin which function should be called and where
1300
 * to store parsed value.
1301
 * @return LY_ERR values.
1302
 */
1303
static LY_ERR
1304
yin_parse_type(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct yin_subelement *subinfo)
1305
0
{
1306
0
    struct lysp_type *type = NULL;
1307
1308
0
    if (parent_stmt == LY_STMT_DEVIATE) {
1309
0
        *(struct lysp_type **)subinfo->dest = calloc(1, sizeof **(struct lysp_type **)subinfo->dest);
1310
0
        LY_CHECK_ERR_RET(!(*(struct lysp_type **)subinfo->dest), LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
1311
0
        type = *((struct lysp_type **)subinfo->dest);
1312
0
    } else {
1313
0
        type = (struct lysp_type *)subinfo->dest;
1314
0
    }
1315
1316
    /* type as child of another type */
1317
0
    if (parent_stmt == LY_STMT_TYPE) {
1318
0
        struct lysp_type *nested_type = NULL;
1319
1320
0
        LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, type->types, nested_type, LY_EMEM);
1321
0
        type->flags |= LYS_SET_TYPE;
1322
0
        type = nested_type;
1323
0
    }
1324
1325
0
    type->pmod = PARSER_CUR_PMOD(ctx);
1326
1327
0
    struct yin_subelement subelems[] = {
1328
0
        {LY_STMT_BASE, type, 0},
1329
0
        {LY_STMT_BIT, type, 0},
1330
0
        {LY_STMT_ENUM, type, 0},
1331
0
        {LY_STMT_FRACTION_DIGITS, type, YIN_SUBELEM_UNIQUE},
1332
0
        {LY_STMT_LENGTH, type, YIN_SUBELEM_UNIQUE},
1333
0
        {LY_STMT_PATH, type, YIN_SUBELEM_UNIQUE},
1334
0
        {LY_STMT_PATTERN, type, 0},
1335
0
        {LY_STMT_RANGE, type, YIN_SUBELEM_UNIQUE},
1336
0
        {LY_STMT_REQUIRE_INSTANCE, type, YIN_SUBELEM_UNIQUE},
1337
0
        {LY_STMT_TYPE, type, 0},
1338
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1339
0
    };
1340
1341
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1342
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &type->name, Y_PREF_IDENTIF_ARG, LY_STMT_TYPE));
1343
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), type, LY_STMT_TYPE, NULL, &type->exts));
1344
1345
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1346
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, type->exts));
1347
1348
0
    return LY_SUCCESS;
1349
0
}
1350
1351
/**
1352
 * @brief Parse max-elements element.
1353
 *
1354
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1355
 * @param[in,out] max Value to write to.
1356
 * @param[in] flags Flags to write to.
1357
 * @param[in,out] exts Extension instances to add to.
1358
 * @return LY_ERR values.
1359
 */
1360
static LY_ERR
1361
yin_parse_maxelements(struct lysp_yin_ctx *ctx, uint32_t *max, uint16_t *flags, struct lysp_ext_instance **exts)
1362
0
{
1363
0
    LY_ERR ret = LY_SUCCESS;
1364
0
    const char *temp_val = NULL;
1365
0
    char *ptr;
1366
0
    unsigned long long num;
1367
0
    struct yin_subelement subelems[] = {
1368
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1369
0
    };
1370
1371
0
    *flags |= LYS_SET_MAX;
1372
0
    LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
1373
0
    LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MAX_ELEMENTS), cleanup);
1374
0
    if (!temp_val || (temp_val[0] == '\0') || (temp_val[0] == '0') || ((temp_val[0] != 'u') && !isdigit(temp_val[0]))) {
1375
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
1376
0
        ret = LY_EVALID;
1377
0
        goto cleanup;
1378
0
    }
1379
1380
0
    if (strcmp(temp_val, "unbounded")) {
1381
0
        errno = 0;
1382
0
        num = strtoull(temp_val, &ptr, LY_BASE_DEC);
1383
0
        if (*ptr != '\0') {
1384
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "max-elements");
1385
0
            ret = LY_EVALID;
1386
0
            goto cleanup;
1387
0
        }
1388
0
        if ((errno == ERANGE) || (num > UINT32_MAX)) {
1389
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "max-elements");
1390
0
            ret = LY_EVALID;
1391
0
            goto cleanup;
1392
0
        }
1393
0
        *max = num;
1394
0
    }
1395
1396
0
    ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), max, LY_STMT_MAX_ELEMENTS, NULL, exts);
1397
0
    LY_CHECK_GOTO(ret, cleanup);
1398
1399
0
cleanup:
1400
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
1401
0
    return ret;
1402
0
}
1403
1404
/**
1405
 * @brief Parse min-elements element.
1406
 *
1407
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1408
 * @param[in,out] min Value to write to.
1409
 * @param[in] flags Flags to write to.
1410
 * @param[in,out] exts Extension instances to add to.
1411
 * @return LY_ERR values.
1412
 */
1413
static LY_ERR
1414
yin_parse_minelements(struct lysp_yin_ctx *ctx, uint32_t *min, uint16_t *flags, struct lysp_ext_instance **exts)
1415
0
{
1416
0
    const char *temp_val = NULL;
1417
0
    char *ptr;
1418
0
    unsigned long long num;
1419
0
    struct yin_subelement subelems[] = {
1420
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1421
0
    };
1422
1423
0
    *flags |= LYS_SET_MIN;
1424
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1425
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MIN_ELEMENTS));
1426
1427
0
    if (!temp_val || (temp_val[0] == '\0') || ((temp_val[0] == '0') && (temp_val[1] != '\0'))) {
1428
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
1429
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
1430
0
        return LY_EVALID;
1431
0
    }
1432
1433
0
    errno = 0;
1434
0
    num = strtoull(temp_val, &ptr, LY_BASE_DEC);
1435
0
    if (ptr[0] != 0) {
1436
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN, temp_val, "value", "min-elements");
1437
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
1438
0
        return LY_EVALID;
1439
0
    }
1440
0
    if ((errno == ERANGE) || (num > UINT32_MAX)) {
1441
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_OOB_YIN, temp_val, "value", "min-elements");
1442
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
1443
0
        return LY_EVALID;
1444
0
    }
1445
0
    *min = num;
1446
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
1447
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), min, LY_STMT_MIN_ELEMENTS, NULL, exts));
1448
1449
0
    return LY_SUCCESS;
1450
0
}
1451
1452
/**
1453
 * @brief Parse min-elements or max-elements element.
1454
 *
1455
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1456
 * @param[in] parent_stmt Type of parent statement.
1457
 * @param[in] cur_stmt Type of current element.
1458
 * @param[in] dest Where the parsed value and flags should be stored.
1459
 * @return LY_ERR values.
1460
 */
1461
static LY_ERR
1462
yin_parse_minmax(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, enum ly_stmt cur_stmt, void *dest)
1463
0
{
1464
0
    uint32_t *lim;
1465
0
    uint16_t *flags;
1466
0
    struct lysp_ext_instance **exts;
1467
1468
0
    assert(cur_stmt == LY_STMT_MAX_ELEMENTS || cur_stmt == LY_STMT_MIN_ELEMENTS);
1469
0
    assert(parent_stmt == LY_STMT_LEAF_LIST || parent_stmt == LY_STMT_REFINE || parent_stmt == LY_STMT_LIST ||
1470
0
            parent_stmt == LY_STMT_DEVIATE);
1471
1472
0
    if (parent_stmt == LY_STMT_LEAF_LIST) {
1473
0
        lim = (cur_stmt == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_leaflist *)dest)->max : &((struct lysp_node_leaflist *)dest)->min;
1474
0
        flags = &((struct lysp_node_leaflist *)dest)->flags;
1475
0
        exts = &((struct lysp_node_leaflist *)dest)->exts;
1476
0
    } else if (parent_stmt == LY_STMT_REFINE) {
1477
0
        lim = (cur_stmt == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_refine *)dest)->max : &((struct lysp_refine *)dest)->min;
1478
0
        flags = &((struct lysp_refine *)dest)->flags;
1479
0
        exts = &((struct lysp_refine *)dest)->exts;
1480
0
    } else if (parent_stmt == LY_STMT_LIST) {
1481
0
        lim = (cur_stmt == LY_STMT_MAX_ELEMENTS) ? &((struct lysp_node_list *)dest)->max : &((struct lysp_node_list *)dest)->min;
1482
0
        flags = &((struct lysp_node_list *)dest)->flags;
1483
0
        exts = &((struct lysp_node_list *)dest)->exts;
1484
0
    } else {
1485
0
        lim = ((struct minmax_dev_meta *)dest)->lim;
1486
0
        flags = ((struct minmax_dev_meta *)dest)->flags;
1487
0
        exts = ((struct minmax_dev_meta *)dest)->exts;
1488
0
    }
1489
1490
0
    if (cur_stmt == LY_STMT_MAX_ELEMENTS) {
1491
0
        LY_CHECK_RET(yin_parse_maxelements(ctx, lim, flags, exts));
1492
0
    } else {
1493
0
        LY_CHECK_RET(yin_parse_minelements(ctx, lim, flags, exts));
1494
0
    }
1495
1496
0
    return LY_SUCCESS;
1497
0
}
1498
1499
/**
1500
 * @brief Parse ordered-by element.
1501
 *
1502
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1503
 * @param[in] parent Current statement parent.
1504
 * @param[out] flags Flags to write to.
1505
 * @param[in,out] exts Extension instances to add to.
1506
 * @return LY_ERR values.
1507
 */
1508
static LY_ERR
1509
yin_parse_orderedby(struct lysp_yin_ctx *ctx, const void *parent, uint16_t *flags, struct lysp_ext_instance **exts)
1510
0
{
1511
0
    const char *temp_val;
1512
0
    struct yin_subelement subelems[] = {
1513
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1514
0
    };
1515
1516
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1517
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_ORDERED_BY));
1518
0
    if (strcmp(temp_val, "system") == 0) {
1519
0
        *flags |= LYS_ORDBY_SYSTEM;
1520
0
    } else if (strcmp(temp_val, "user") == 0) {
1521
0
        *flags |= LYS_ORDBY_USER;
1522
0
    } else {
1523
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
1524
0
                "ordered-by", "system", "user");
1525
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
1526
0
        return LY_EVALID;
1527
0
    }
1528
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
1529
1530
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ORDERED_BY, NULL, exts));
1531
1532
0
    return LY_SUCCESS;
1533
0
}
1534
1535
/**
1536
 * @brief Parse any-data or any-xml element.
1537
 *
1538
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1539
 * @param[in] any_stmt Type of current statement, can be set to LY_STMT_ANYDATA or LY_STMT_ANYXML
1540
 * @param[in] node_meta Meta information about parent node and siblings to add to.
1541
 * @return LY_ERR values.
1542
 */
1543
static LY_ERR
1544
yin_parse_any(struct lysp_yin_ctx *ctx, enum ly_stmt any_kw, struct tree_node_meta *node_meta)
1545
0
{
1546
0
    struct lysp_node_anydata *any;
1547
1548
    /* create new sibling */
1549
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, any, next, LY_EMEM);
1550
0
    any->nodetype = (any_kw == LY_STMT_ANYDATA) ? LYS_ANYDATA : LYS_ANYXML;
1551
0
    any->parent = node_meta->parent;
1552
1553
    /* parse argument */
1554
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1555
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &any->name, Y_IDENTIF_ARG, any_kw));
1556
1557
0
    struct yin_subelement subelems[] = {
1558
0
        {LY_STMT_CONFIG, &any->flags, YIN_SUBELEM_UNIQUE},
1559
0
        {LY_STMT_DESCRIPTION, &any->dsc, YIN_SUBELEM_UNIQUE},
1560
0
        {LY_STMT_IF_FEATURE, &any->iffeatures, 0},
1561
0
        {LY_STMT_MANDATORY, &any->flags, YIN_SUBELEM_UNIQUE},
1562
0
        {LY_STMT_MUST, &any->musts, 0},
1563
0
        {LY_STMT_REFERENCE, &any->ref, YIN_SUBELEM_UNIQUE},
1564
0
        {LY_STMT_STATUS, &any->flags, YIN_SUBELEM_UNIQUE},
1565
0
        {LY_STMT_WHEN, &any->when, YIN_SUBELEM_UNIQUE},
1566
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1567
0
    };
1568
1569
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), any, any_kw, NULL, &any->exts));
1570
1571
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1572
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, any->exts));
1573
1574
0
    return LY_SUCCESS;
1575
0
}
1576
1577
/**
1578
 * @brief parse leaf element.
1579
 *
1580
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1581
 * @param[in] node_meta Meta information about parent node and siblings to add to.
1582
 * @return LY_ERR values.
1583
 */
1584
static LY_ERR
1585
yin_parse_leaf(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
1586
0
{
1587
0
    struct lysp_node_leaf *leaf;
1588
1589
    /* create structure new leaf */
1590
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, leaf, next, LY_EMEM);
1591
0
    leaf->nodetype = LYS_LEAF;
1592
0
    leaf->parent = node_meta->parent;
1593
1594
    /* parser argument */
1595
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1596
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &leaf->name, Y_IDENTIF_ARG, LY_STMT_LEAF));
1597
1598
    /* parse content */
1599
0
    struct yin_subelement subelems[] = {
1600
0
        {LY_STMT_CONFIG, &leaf->flags, YIN_SUBELEM_UNIQUE},
1601
0
        {LY_STMT_DEFAULT, &leaf->dflt, YIN_SUBELEM_UNIQUE},
1602
0
        {LY_STMT_DESCRIPTION, &leaf->dsc, YIN_SUBELEM_UNIQUE},
1603
0
        {LY_STMT_IF_FEATURE, &leaf->iffeatures, 0},
1604
0
        {LY_STMT_MANDATORY, &leaf->flags, YIN_SUBELEM_UNIQUE},
1605
0
        {LY_STMT_MUST, &leaf->musts, 0},
1606
0
        {LY_STMT_REFERENCE, &leaf->ref, YIN_SUBELEM_UNIQUE},
1607
0
        {LY_STMT_STATUS, &leaf->flags, YIN_SUBELEM_UNIQUE},
1608
0
        {LY_STMT_TYPE, &leaf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1609
0
        {LY_STMT_UNITS, &leaf->units, YIN_SUBELEM_UNIQUE},
1610
0
        {LY_STMT_WHEN, &leaf->when, YIN_SUBELEM_UNIQUE},
1611
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1612
0
    };
1613
1614
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), leaf, LY_STMT_LEAF, NULL, &leaf->exts));
1615
1616
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1617
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, leaf->exts));
1618
1619
0
    return LY_SUCCESS;
1620
0
}
1621
1622
/**
1623
 * @brief Parse leaf-list element.
1624
 *
1625
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1626
 * @param[in] node_meta Meta information about parent node and siblings to add to.
1627
 * @return LY_ERR values.
1628
 */
1629
static LY_ERR
1630
yin_parse_leaflist(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
1631
0
{
1632
0
    struct lysp_node_leaflist *llist;
1633
1634
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, llist, next, LY_EMEM);
1635
1636
0
    llist->nodetype = LYS_LEAFLIST;
1637
0
    llist->parent = node_meta->parent;
1638
1639
    /* parse argument */
1640
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1641
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &llist->name, Y_IDENTIF_ARG, LY_STMT_LEAF_LIST));
1642
1643
    /* parse content */
1644
0
    struct yin_subelement subelems[] = {
1645
0
        {LY_STMT_CONFIG, &llist->flags, YIN_SUBELEM_UNIQUE},
1646
0
        {LY_STMT_DEFAULT, &llist->dflts, 0},
1647
0
        {LY_STMT_DESCRIPTION, &llist->dsc, YIN_SUBELEM_UNIQUE},
1648
0
        {LY_STMT_IF_FEATURE, &llist->iffeatures, 0},
1649
0
        {LY_STMT_MAX_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1650
0
        {LY_STMT_MIN_ELEMENTS, llist, YIN_SUBELEM_UNIQUE},
1651
0
        {LY_STMT_MUST, &llist->musts, 0},
1652
0
        {LY_STMT_ORDERED_BY, &llist->flags, YIN_SUBELEM_UNIQUE},
1653
0
        {LY_STMT_REFERENCE, &llist->ref, YIN_SUBELEM_UNIQUE},
1654
0
        {LY_STMT_STATUS, &llist->flags, YIN_SUBELEM_UNIQUE},
1655
0
        {LY_STMT_TYPE, &llist->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1656
0
        {LY_STMT_UNITS, &llist->units, YIN_SUBELEM_UNIQUE},
1657
0
        {LY_STMT_WHEN, &llist->when, YIN_SUBELEM_UNIQUE},
1658
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1659
0
    };
1660
1661
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), llist, LY_STMT_LEAF_LIST, NULL, &llist->exts));
1662
1663
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1664
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, llist->exts));
1665
1666
    /* check invalid combination of subelements */
1667
0
    if ((llist->min) && (llist->dflts)) {
1668
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INCHILDSTMSCOMB_YIN, "min-elements", "default", "leaf-list");
1669
0
        return LY_EVALID;
1670
0
    }
1671
0
    if (llist->max && (llist->min > llist->max)) {
1672
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_MINMAX, llist->min, llist->max);
1673
0
        return LY_EVALID;
1674
0
    }
1675
1676
0
    return LY_SUCCESS;
1677
0
}
1678
1679
/**
1680
 * @brief Parse typedef element.
1681
 *
1682
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1683
 * @param[in] typedef_meta Meta information about parent node and typedefs to add to.
1684
 * @return LY_ERR values.
1685
 */
1686
static LY_ERR
1687
yin_parse_typedef(struct lysp_yin_ctx *ctx, struct tree_node_meta *typedef_meta)
1688
0
{
1689
0
    struct lysp_tpdf *tpdf;
1690
0
    struct lysp_tpdf **tpdfs = (struct lysp_tpdf **)typedef_meta->nodes;
1691
1692
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *tpdfs, tpdf, LY_EMEM);
1693
1694
    /* parse argument */
1695
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1696
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &tpdf->name, Y_IDENTIF_ARG, LY_STMT_TYPEDEF));
1697
1698
    /* parse content */
1699
0
    struct yin_subelement subelems[] = {
1700
0
        {LY_STMT_DEFAULT, &tpdf->dflt, YIN_SUBELEM_UNIQUE},
1701
0
        {LY_STMT_DESCRIPTION, &tpdf->dsc, YIN_SUBELEM_UNIQUE},
1702
0
        {LY_STMT_REFERENCE, &tpdf->ref, YIN_SUBELEM_UNIQUE},
1703
0
        {LY_STMT_STATUS, &tpdf->flags, YIN_SUBELEM_UNIQUE},
1704
0
        {LY_STMT_TYPE, &tpdf->type, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_MANDATORY},
1705
0
        {LY_STMT_UNITS, &tpdf->units, YIN_SUBELEM_UNIQUE},
1706
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1707
0
    };
1708
1709
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), tpdf, LY_STMT_TYPEDEF, NULL, &tpdf->exts));
1710
1711
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1712
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, tpdf->exts));
1713
1714
    /* store data for collision check */
1715
0
    if (typedef_meta->parent) {
1716
0
        assert(ctx->main_ctx);
1717
0
        LY_CHECK_RET(ly_set_add(&ctx->main_ctx->tpdfs_nodes, typedef_meta->parent, 0, NULL));
1718
0
    }
1719
1720
0
    return LY_SUCCESS;
1721
0
}
1722
1723
/**
1724
 * @brief Parse refine element.
1725
 *
1726
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1727
 * @param[in,out] refines Refines to add to.
1728
 * @return LY_ERR values.
1729
 */
1730
static LY_ERR
1731
yin_parse_refine(struct lysp_yin_ctx *ctx, struct lysp_refine **refines)
1732
0
{
1733
0
    struct lysp_refine *rf;
1734
1735
    /* allocate new refine */
1736
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *refines, rf, LY_EMEM);
1737
1738
    /* parse attribute */
1739
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1740
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &rf->nodeid, Y_STR_ARG, LY_STMT_REFINE));
1741
0
    CHECK_NONEMPTY(ctx, strlen(rf->nodeid), "refine");
1742
1743
    /* parse content */
1744
0
    struct yin_subelement subelems[] = {
1745
0
        {LY_STMT_CONFIG, &rf->flags, YIN_SUBELEM_UNIQUE},
1746
0
        {LY_STMT_DEFAULT, &rf->dflts, 0},
1747
0
        {LY_STMT_DESCRIPTION, &rf->dsc, YIN_SUBELEM_UNIQUE},
1748
0
        {LY_STMT_IF_FEATURE, &rf->iffeatures, 0},
1749
0
        {LY_STMT_MANDATORY, &rf->flags, YIN_SUBELEM_UNIQUE},
1750
0
        {LY_STMT_MAX_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1751
0
        {LY_STMT_MIN_ELEMENTS, rf, YIN_SUBELEM_UNIQUE},
1752
0
        {LY_STMT_MUST, &rf->musts, 0},
1753
0
        {LY_STMT_PRESENCE, &rf->presence, YIN_SUBELEM_UNIQUE},
1754
0
        {LY_STMT_REFERENCE, &rf->ref, YIN_SUBELEM_UNIQUE},
1755
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1756
0
    };
1757
1758
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rf, LY_STMT_REFINE, NULL, &rf->exts));
1759
1760
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1761
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, rf->exts));
1762
1763
0
    return LY_SUCCESS;
1764
0
}
1765
1766
/**
1767
 * @brief Parse uses element.
1768
 *
1769
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1770
 * @param[in] node_meta Meta information about parent node and siblings to add to.
1771
 * @return LY_ERR values.
1772
 */
1773
static LY_ERR
1774
yin_parse_uses(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
1775
0
{
1776
0
    struct lysp_node_uses *uses;
1777
1778
    /* create new uses */
1779
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, uses, next, LY_EMEM);
1780
0
    uses->nodetype = LYS_USES;
1781
0
    uses->parent = node_meta->parent;
1782
1783
    /* parse argument */
1784
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1785
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &uses->name, Y_PREF_IDENTIF_ARG, LY_STMT_USES));
1786
1787
    /* parse content */
1788
0
    struct tree_node_meta augments = {(struct lysp_node *)uses, (struct lysp_node **)&uses->augments};
1789
0
    struct yin_subelement subelems[] = {
1790
0
        {LY_STMT_AUGMENT, &augments, 0},
1791
0
        {LY_STMT_DESCRIPTION, &uses->dsc, YIN_SUBELEM_UNIQUE},
1792
0
        {LY_STMT_IF_FEATURE, &uses->iffeatures, 0},
1793
0
        {LY_STMT_REFERENCE, &uses->ref, YIN_SUBELEM_UNIQUE},
1794
0
        {LY_STMT_REFINE, &uses->refines, 0},
1795
0
        {LY_STMT_STATUS, &uses->flags, YIN_SUBELEM_UNIQUE},
1796
0
        {LY_STMT_WHEN, &uses->when, YIN_SUBELEM_UNIQUE},
1797
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1798
0
    };
1799
1800
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), uses, LY_STMT_USES, NULL, &uses->exts));
1801
1802
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1803
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, uses->exts));
1804
1805
0
    return LY_SUCCESS;
1806
0
}
1807
1808
/**
1809
 * @brief Parse revision element.
1810
 *
1811
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1812
 * @param[in,out] revs Parsed revisions to add to.
1813
 * @return LY_ERR values.
1814
 */
1815
static LY_ERR
1816
yin_parse_revision(struct lysp_yin_ctx *ctx, struct lysp_revision **revs)
1817
0
{
1818
0
    struct lysp_revision *rev;
1819
0
    const char *temp_date = NULL;
1820
1821
    /* allocate new reivison */
1822
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *revs, rev, LY_EMEM);
1823
1824
    /* parse argument */
1825
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1826
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_date, Y_STR_ARG, LY_STMT_REVISION));
1827
    /* check value */
1828
0
    if (lysp_check_date((struct lysp_ctx *)ctx, temp_date, strlen(temp_date), "revision")) {
1829
0
        lydict_remove(ctx->xmlctx->ctx, temp_date);
1830
0
        return LY_EVALID;
1831
0
    }
1832
0
    memcpy(rev->date, temp_date, LY_REV_SIZE);
1833
0
    lydict_remove(ctx->xmlctx->ctx, temp_date);
1834
1835
    /* parse content */
1836
0
    struct yin_subelement subelems[] = {
1837
0
        {LY_STMT_DESCRIPTION, &rev->dsc, YIN_SUBELEM_UNIQUE},
1838
0
        {LY_STMT_REFERENCE, &rev->ref, YIN_SUBELEM_UNIQUE},
1839
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1840
0
    };
1841
1842
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rev, LY_STMT_REVISION, NULL, &rev->exts));
1843
1844
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1845
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, rev->exts));
1846
1847
0
    return LY_SUCCESS;
1848
0
}
1849
1850
/**
1851
 * @brief Parse include element.
1852
 *
1853
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1854
 * @param[in,out] inc_meta Meta informatinou about module/submodule name and includes to add to.
1855
 * @return LY_ERR values.
1856
 */
1857
static LY_ERR
1858
yin_parse_include(struct lysp_yin_ctx *ctx, struct include_meta *inc_meta)
1859
0
{
1860
0
    struct lysp_include *inc;
1861
1862
    /* allocate new include */
1863
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *inc_meta->includes, inc, LY_EMEM);
1864
1865
    /* parse argument */
1866
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1867
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &inc->name, Y_IDENTIF_ARG, LY_STMT_INCLUDE));
1868
1869
    /* submodules share the namespace with the module names, so there must not be
1870
     * a module of the same name in the context, no need for revision matching */
1871
0
    if (!strcmp(inc_meta->name, inc->name) || ly_ctx_get_module_latest(ctx->xmlctx->ctx, inc->name)) {
1872
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", inc->name);
1873
0
        return LY_EVALID;
1874
0
    }
1875
1876
    /* parse content */
1877
0
    struct yin_subelement subelems[] = {
1878
0
        {LY_STMT_DESCRIPTION, &inc->dsc, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1879
0
        {LY_STMT_REFERENCE, &inc->ref, YIN_SUBELEM_UNIQUE | YIN_SUBELEM_VER2},
1880
0
        {LY_STMT_REVISION_DATE, &inc->rev, YIN_SUBELEM_UNIQUE},
1881
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
1882
0
    };
1883
1884
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), inc, LY_STMT_INCLUDE, NULL, &inc->exts));
1885
1886
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
1887
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, inc->exts));
1888
1889
0
    return LY_SUCCESS;
1890
0
}
1891
1892
/**
1893
 * @brief Parse revision-date element.
1894
 *
1895
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1896
 * @param[in,out] rev Array to store the parsed value in.
1897
 * @param[in,out] exts Extension instances to add to.
1898
 * @return LY_ERR values.
1899
 */
1900
static LY_ERR
1901
yin_parse_revision_date(struct lysp_yin_ctx *ctx, char *rev, struct lysp_ext_instance **exts)
1902
0
{
1903
0
    const char *temp_rev;
1904
0
    struct yin_subelement subelems[] = {
1905
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1906
0
    };
1907
1908
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1909
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, &temp_rev, Y_STR_ARG, LY_STMT_REVISION_DATE));
1910
0
    LY_CHECK_ERR_RET(lysp_check_date((struct lysp_ctx *)ctx, temp_rev, strlen(temp_rev), "revision-date") != LY_SUCCESS,
1911
0
            lydict_remove(ctx->xmlctx->ctx, temp_rev), LY_EVALID);
1912
1913
0
    strcpy(rev, temp_rev);
1914
0
    lydict_remove(ctx->xmlctx->ctx, temp_rev);
1915
1916
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), rev, LY_STMT_REVISION_DATE, NULL, exts));
1917
1918
0
    return LY_SUCCESS;
1919
0
}
1920
1921
/**
1922
 * @brief Parse config element.
1923
 *
1924
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1925
 * @param[in,out] flags Flags to add to.
1926
 * @param[in,out] exts Extension instances to add to.
1927
 * @return LY_ERR values.
1928
 */
1929
static LY_ERR
1930
yin_parse_config(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
1931
0
{
1932
0
    const char *temp_val = NULL;
1933
0
    struct yin_subelement subelems[] = {
1934
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1935
0
    };
1936
1937
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1938
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_CONFIG));
1939
0
    if (strcmp(temp_val, "true") == 0) {
1940
0
        *flags |= LYS_CONFIG_W;
1941
0
    } else if (strcmp(temp_val, "false") == 0) {
1942
0
        *flags |= LYS_CONFIG_R;
1943
0
    } else {
1944
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value", "config",
1945
0
                "true", "false");
1946
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
1947
0
        return LY_EVALID;
1948
0
    }
1949
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
1950
1951
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_CONFIG, NULL, exts));
1952
1953
0
    return LY_SUCCESS;
1954
0
}
1955
1956
/**
1957
 * @brief Parse yang-version element.
1958
 *
1959
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1960
 * @param[in] parent Current statement parent.
1961
 * @param[out] version Storage for the parsed information.
1962
 * @param[in,out] exts Extension instances to add to.
1963
 * @return LY_ERR values.
1964
 */
1965
static LY_ERR
1966
yin_parse_yangversion(struct lysp_yin_ctx *ctx, const void *parent, uint8_t *version, struct lysp_ext_instance **exts)
1967
0
{
1968
0
    const char *temp_version = NULL;
1969
0
    struct yin_subelement subelems[] = {
1970
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
1971
0
    };
1972
1973
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
1974
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_version, Y_STR_ARG, LY_STMT_YANG_VERSION));
1975
0
    if (strcmp(temp_version, "1") == 0) {
1976
0
        *version = LYS_VERSION_1_0;
1977
0
    } else if (strcmp(temp_version, "1.1") == 0) {
1978
0
        *version = LYS_VERSION_1_1;
1979
0
    } else {
1980
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_version, "value",
1981
0
                "yang-version", "1", "1.1");
1982
0
        lydict_remove(ctx->xmlctx->ctx, temp_version);
1983
0
        return LY_EVALID;
1984
0
    }
1985
0
    lydict_remove(ctx->xmlctx->ctx, temp_version);
1986
1987
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_YANG_VERSION, NULL, exts));
1988
1989
0
    return LY_SUCCESS;
1990
0
}
1991
1992
/**
1993
 * @brief Parse import element.
1994
 *
1995
 * @param[in,out] ctx YIN parser context for logging and to store current state.
1996
 * @param[in,out] imp_meta Meta information about prefix and imports to add to.
1997
 * @return LY_ERR values.
1998
 */
1999
static LY_ERR
2000
yin_parse_import(struct lysp_yin_ctx *ctx, struct import_meta *imp_meta)
2001
0
{
2002
0
    struct lysp_import *imp;
2003
2004
    /* allocate new element in sized array for import */
2005
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *imp_meta->imports, imp, LY_EMEM);
2006
2007
0
    struct yin_subelement subelems[] = {
2008
0
        {LY_STMT_DESCRIPTION, &imp->dsc, YIN_SUBELEM_UNIQUE},
2009
0
        {LY_STMT_PREFIX, &imp->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE},
2010
0
        {LY_STMT_REFERENCE, &imp->ref, YIN_SUBELEM_UNIQUE},
2011
0
        {LY_STMT_REVISION_DATE, imp->rev, YIN_SUBELEM_UNIQUE},
2012
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2013
0
    };
2014
2015
    /* parse import attributes */
2016
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2017
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, &imp->name, Y_IDENTIF_ARG, LY_STMT_IMPORT));
2018
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), imp, LY_STMT_IMPORT, NULL, &imp->exts));
2019
2020
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2021
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, imp->exts));
2022
2023
    /* check prefix validity */
2024
0
    LY_CHECK_RET(lysp_check_prefix((struct lysp_ctx *)ctx, *imp_meta->imports, imp_meta->prefix, &imp->prefix), LY_EVALID);
2025
2026
0
    return LY_SUCCESS;
2027
0
}
2028
2029
/**
2030
 * @brief Parse mandatory element.
2031
 *
2032
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2033
 * @param[in,out] flags Flags to add to.
2034
 * @param[in,out] exts Extension instances to add to.
2035
 * @return LY_ERR values.
2036
 */
2037
static LY_ERR
2038
yin_parse_mandatory(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
2039
0
{
2040
0
    const char *temp_val = NULL;
2041
0
    struct yin_subelement subelems[] = {
2042
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2043
0
    };
2044
2045
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2046
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_MANDATORY));
2047
0
    if (strcmp(temp_val, "true") == 0) {
2048
0
        *flags |= LYS_MAND_TRUE;
2049
0
    } else if (strcmp(temp_val, "false") == 0) {
2050
0
        *flags |= LYS_MAND_FALSE;
2051
0
    } else {
2052
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
2053
0
                "mandatory", "true", "false");
2054
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
2055
0
        return LY_EVALID;
2056
0
    }
2057
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
2058
2059
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_MANDATORY, NULL, exts));
2060
2061
0
    return LY_SUCCESS;
2062
0
}
2063
2064
/**
2065
 * @brief Parse status element.
2066
 *
2067
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2068
 * @param[in,out] flags Flags to add to.
2069
 * @param[in,out] exts Extension instances to add to.
2070
 * @return LY_ERR values.
2071
 */
2072
static LY_ERR
2073
yin_parse_status(struct lysp_yin_ctx *ctx, uint16_t *flags, struct lysp_ext_instance **exts)
2074
0
{
2075
0
    const char *value = NULL;
2076
0
    struct yin_subelement subelems[] = {
2077
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2078
0
    };
2079
2080
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2081
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &value, Y_STR_ARG, LY_STMT_STATUS));
2082
0
    if (strcmp(value, "current") == 0) {
2083
0
        *flags |= LYS_STATUS_CURR;
2084
0
    } else if (strcmp(value, "deprecated") == 0) {
2085
0
        *flags |= LYS_STATUS_DEPRC;
2086
0
    } else if (strcmp(value, "obsolete") == 0) {
2087
0
        *flags |= LYS_STATUS_OBSLT;
2088
0
    } else {
2089
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS3, value, "value",
2090
0
                "status", "current", "deprecated", "obsolete");
2091
0
        lydict_remove(ctx->xmlctx->ctx, value);
2092
0
        return LY_EVALID;
2093
0
    }
2094
0
    lydict_remove(ctx->xmlctx->ctx, value);
2095
2096
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), flags, LY_STMT_STATUS, NULL, exts));
2097
2098
0
    return LY_SUCCESS;
2099
0
}
2100
2101
/**
2102
 * @brief Parse when element.
2103
 *
2104
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2105
 * @param[out] when_p When pointer to parse to.
2106
 * @return LY_ERR values.
2107
 */
2108
static LY_ERR
2109
yin_parse_when(struct lysp_yin_ctx *ctx, struct lysp_when **when_p)
2110
0
{
2111
0
    struct lysp_when *when;
2112
0
    LY_ERR ret = LY_SUCCESS;
2113
2114
0
    when = calloc(1, sizeof *when);
2115
0
    LY_CHECK_ERR_RET(!when, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
2116
2117
0
    ret = lyxml_ctx_next(ctx->xmlctx);
2118
0
    LY_CHECK_ERR_RET(ret, free(when), ret);
2119
2120
0
    ret = yin_parse_attribute(ctx, YIN_ARG_CONDITION, &when->cond, Y_STR_ARG, LY_STMT_WHEN);
2121
0
    LY_CHECK_ERR_RET(ret, free(when), ret);
2122
2123
0
    *when_p = when;
2124
0
    struct yin_subelement subelems[] = {
2125
0
        {LY_STMT_DESCRIPTION, &when->dsc, YIN_SUBELEM_UNIQUE},
2126
0
        {LY_STMT_REFERENCE, &when->ref, YIN_SUBELEM_UNIQUE},
2127
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2128
0
    };
2129
2130
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), when, LY_STMT_WHEN, NULL, &when->exts));
2131
2132
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2133
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, when->exts));
2134
2135
0
    return LY_SUCCESS;
2136
0
}
2137
2138
/**
2139
 * @brief Parse yin-elemenet element.
2140
 *
2141
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2142
 * @param[in] parent Current statement parent.
2143
 * @param[in,out] flags Flags to add to.
2144
 * @param[in,out] exts Extension instances to add to.
2145
 * @return LY_ERR values.
2146
 */
2147
static LY_ERR
2148
yin_parse_yin_element(struct lysp_yin_ctx *ctx, const void *parent, uint16_t *flags, struct lysp_ext_instance **exts)
2149
0
{
2150
0
    const char *temp_val = NULL;
2151
0
    struct yin_subelement subelems[] = {
2152
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2153
0
    };
2154
2155
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2156
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_YIN_ELEMENT));
2157
0
    if (strcmp(temp_val, "true") == 0) {
2158
0
        *flags |= LYS_YINELEM_TRUE;
2159
0
    } else if (strcmp(temp_val, "false") == 0) {
2160
0
        *flags |= LYS_YINELEM_FALSE;
2161
0
    } else {
2162
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS2, temp_val, "value",
2163
0
                "yin-element", "true", "false");
2164
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
2165
0
        return LY_EVALID;
2166
0
    }
2167
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
2168
2169
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_YIN_ELEMENT, NULL, exts));
2170
2171
0
    return LY_SUCCESS;
2172
0
}
2173
2174
/**
2175
 * @brief Parse argument element.
2176
 *
2177
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2178
 * @param[in] parent Current statement parent.
2179
 * @param[in,out] arg_meta Meta information about destination of parsed data.
2180
 * @param[in,out] exts Extension instances to add to.
2181
 * @return LY_ERR values.
2182
 */
2183
static LY_ERR
2184
yin_parse_argument(struct lysp_yin_ctx *ctx, const void *parent, struct yin_argument_meta *arg_meta, struct lysp_ext_instance **exts)
2185
0
{
2186
0
    struct yin_subelement subelems[] = {
2187
0
        {LY_STMT_YIN_ELEMENT, arg_meta->flags, YIN_SUBELEM_UNIQUE},
2188
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2189
0
    };
2190
2191
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2192
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg_meta->argument, Y_IDENTIF_ARG, LY_STMT_ARGUMENT));
2193
2194
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), parent, LY_STMT_ARGUMENT, NULL, exts));
2195
2196
0
    return LY_SUCCESS;
2197
0
}
2198
2199
/**
2200
 * @brief Parse the extension statement.
2201
 *
2202
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2203
 * @param[in,out] extensions Extensions to add to.
2204
 * @return LY_ERR values.
2205
 */
2206
static LY_ERR
2207
yin_parse_extension(struct lysp_yin_ctx *ctx, struct lysp_ext **extensions)
2208
0
{
2209
0
    struct lysp_ext *ex;
2210
2211
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *extensions, ex, LY_EMEM);
2212
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2213
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &ex->name, Y_IDENTIF_ARG, LY_STMT_EXTENSION));
2214
2215
0
    struct yin_argument_meta arg_info = {&ex->flags, &ex->argname};
2216
0
    struct yin_subelement subelems[] = {
2217
0
        {LY_STMT_ARGUMENT, &arg_info, YIN_SUBELEM_UNIQUE},
2218
0
        {LY_STMT_DESCRIPTION, &ex->dsc, YIN_SUBELEM_UNIQUE},
2219
0
        {LY_STMT_REFERENCE, &ex->ref, YIN_SUBELEM_UNIQUE},
2220
0
        {LY_STMT_STATUS, &ex->flags, YIN_SUBELEM_UNIQUE},
2221
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2222
0
    };
2223
2224
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), ex, LY_STMT_EXTENSION, NULL, &ex->exts));
2225
2226
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2227
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, ex->exts));
2228
2229
0
    return LY_SUCCESS;
2230
0
}
2231
2232
/**
2233
 * @brief Parse feature element.
2234
 *
2235
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2236
 * @param[in,out] features Features to add to.
2237
 * @return LY_ERR values.
2238
 */
2239
static LY_ERR
2240
yin_parse_feature(struct lysp_yin_ctx *ctx, struct lysp_feature **features)
2241
0
{
2242
0
    struct lysp_feature *feat;
2243
2244
    /* allocate new feature */
2245
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *features, feat, LY_EMEM);
2246
2247
    /* parse argument */
2248
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2249
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &feat->name, Y_IDENTIF_ARG, LY_STMT_FEATURE));
2250
2251
    /* parse content */
2252
0
    struct yin_subelement subelems[] = {
2253
0
        {LY_STMT_DESCRIPTION, &feat->dsc, YIN_SUBELEM_UNIQUE},
2254
0
        {LY_STMT_IF_FEATURE, &feat->iffeatures, 0},
2255
0
        {LY_STMT_REFERENCE, &feat->ref, YIN_SUBELEM_UNIQUE},
2256
0
        {LY_STMT_STATUS, &feat->flags, YIN_SUBELEM_UNIQUE},
2257
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2258
0
    };
2259
2260
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), feat, LY_STMT_FEATURE, NULL, &feat->exts));
2261
2262
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2263
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, feat->exts));
2264
2265
0
    return LY_SUCCESS;
2266
0
}
2267
2268
/**
2269
 * @brief Parse identity element.
2270
 *
2271
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2272
 * @param[in,out] identities Identities to add to.
2273
 * @return LY_ERR values.
2274
 */
2275
static LY_ERR
2276
yin_parse_identity(struct lysp_yin_ctx *ctx, struct lysp_ident **identities)
2277
0
{
2278
0
    struct lysp_ident *ident;
2279
2280
    /* allocate new identity */
2281
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *identities, ident, LY_EMEM);
2282
2283
    /* parse argument */
2284
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2285
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &ident->name, Y_IDENTIF_ARG, LY_STMT_IDENTITY));
2286
2287
    /* parse content */
2288
0
    struct yin_subelement subelems[] = {
2289
0
        {LY_STMT_BASE, &ident->bases, 0},
2290
0
        {LY_STMT_DESCRIPTION, &ident->dsc, YIN_SUBELEM_UNIQUE},
2291
0
        {LY_STMT_IF_FEATURE, &ident->iffeatures, YIN_SUBELEM_VER2},
2292
0
        {LY_STMT_REFERENCE, &ident->ref, YIN_SUBELEM_UNIQUE},
2293
0
        {LY_STMT_STATUS, &ident->flags, YIN_SUBELEM_UNIQUE},
2294
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2295
0
    };
2296
2297
0
    LY_CHECK_RET(yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), ident, LY_STMT_IDENTITY, NULL, &ident->exts));
2298
2299
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2300
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, ident->exts));
2301
2302
0
    return LY_SUCCESS;
2303
0
}
2304
2305
/**
2306
 * @brief Parse list element.
2307
 *
2308
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2309
 * @param[in] node_meta Meta information about parent node and siblings to add to.
2310
 * @return LY_ERR values.
2311
 */
2312
static LY_ERR
2313
yin_parse_list(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
2314
0
{
2315
0
    struct lysp_node_list *list;
2316
0
    LY_ERR ret = LY_SUCCESS;
2317
0
    struct yin_subelement *subelems = NULL;
2318
0
    size_t subelems_size;
2319
2320
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, list, next, LY_EMEM);
2321
0
    list->nodetype = LYS_LIST;
2322
0
    list->parent = node_meta->parent;
2323
2324
    /* parse argument */
2325
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2326
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &list->name, Y_IDENTIF_ARG, LY_STMT_LIST));
2327
2328
    /* parse list content */
2329
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 25, (struct lysp_node *)list, &subelems,
2330
0
            LY_STMT_ACTION, &list->actions, 0,
2331
0
            LY_STMT_ANYDATA, &list->child, 0,
2332
0
            LY_STMT_ANYXML, &list->child, 0,
2333
0
            LY_STMT_CHOICE, &list->child, 0,
2334
0
            LY_STMT_CONFIG, &list->flags, YIN_SUBELEM_UNIQUE,
2335
0
            LY_STMT_CONTAINER, &list->child, 0,
2336
0
            LY_STMT_DESCRIPTION, &list->dsc, YIN_SUBELEM_UNIQUE,
2337
0
            LY_STMT_GROUPING, &list->groupings, 0,
2338
0
            LY_STMT_IF_FEATURE, &list->iffeatures, 0,
2339
0
            LY_STMT_KEY, &list->key, YIN_SUBELEM_UNIQUE,
2340
0
            LY_STMT_LEAF, &list->child, 0,
2341
0
            LY_STMT_LEAF_LIST, &list->child, 0,
2342
0
            LY_STMT_LIST, &list->child, 0,
2343
0
            LY_STMT_MAX_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2344
0
            LY_STMT_MIN_ELEMENTS, list, YIN_SUBELEM_UNIQUE,
2345
0
            LY_STMT_MUST, &list->musts, 0,
2346
0
            LY_STMT_NOTIFICATION, &list->notifs, 0,
2347
0
            LY_STMT_ORDERED_BY, &list->flags, YIN_SUBELEM_UNIQUE,
2348
0
            LY_STMT_REFERENCE, &list->ref, YIN_SUBELEM_UNIQUE,
2349
0
            LY_STMT_STATUS, &list->flags, YIN_SUBELEM_UNIQUE,
2350
0
            LY_STMT_TYPEDEF, &list->typedefs, 0,
2351
0
            LY_STMT_UNIQUE, &list->uniques, 0,
2352
0
            LY_STMT_USES, &list->child, 0,
2353
0
            LY_STMT_WHEN, &list->when, YIN_SUBELEM_UNIQUE,
2354
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2355
0
    ret = yin_parse_content(ctx, subelems, subelems_size, list, LY_STMT_LIST, NULL, &list->exts);
2356
0
    subelems_deallocator(subelems_size, subelems);
2357
0
    LY_CHECK_RET(ret);
2358
2359
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2360
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, list->exts));
2361
2362
0
    if (list->max && (list->min > list->max)) {
2363
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_MINMAX, list->min, list->max);
2364
0
        return LY_EVALID;
2365
0
    }
2366
2367
0
    return LY_SUCCESS;
2368
0
}
2369
2370
/**
2371
 * @brief Parse notification element.
2372
 *
2373
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2374
 * @param[in,out] notif_meta Meta information about parent node and notifications to add to.
2375
 * @return LY_ERR values.
2376
 */
2377
static LY_ERR
2378
yin_parse_notification(struct lysp_yin_ctx *ctx, struct tree_node_meta *notif_meta)
2379
0
{
2380
0
    struct lysp_node_notif *notif;
2381
0
    struct lysp_node_notif **notifs = (struct lysp_node_notif **)notif_meta->nodes;
2382
0
    LY_ERR ret = LY_SUCCESS;
2383
0
    struct yin_subelement *subelems = NULL;
2384
0
    size_t subelems_size;
2385
2386
    /* allocate new notification */
2387
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, notifs, notif, next, LY_EMEM);
2388
0
    notif->nodetype = LYS_NOTIF;
2389
0
    notif->parent = notif_meta->parent;
2390
2391
    /* parse argument */
2392
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2393
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &notif->name, Y_IDENTIF_ARG, LY_STMT_NOTIFICATION));
2394
2395
    /* parse notification content */
2396
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, (struct lysp_node *)notif, &subelems,
2397
0
            LY_STMT_ANYDATA, &notif->child, 0,
2398
0
            LY_STMT_ANYXML, &notif->child, 0,
2399
0
            LY_STMT_CHOICE, &notif->child, 0,
2400
0
            LY_STMT_CONTAINER, &notif->child, 0,
2401
0
            LY_STMT_DESCRIPTION, &notif->dsc, YIN_SUBELEM_UNIQUE,
2402
0
            LY_STMT_GROUPING, &notif->groupings, 0,
2403
0
            LY_STMT_IF_FEATURE, &notif->iffeatures, 0,
2404
0
            LY_STMT_LEAF, &notif->child, 0,
2405
0
            LY_STMT_LEAF_LIST, &notif->child, 0,
2406
0
            LY_STMT_LIST, &notif->child, 0,
2407
0
            LY_STMT_MUST, &notif->musts, YIN_SUBELEM_VER2,
2408
0
            LY_STMT_REFERENCE, &notif->ref, YIN_SUBELEM_UNIQUE,
2409
0
            LY_STMT_STATUS, &notif->flags, YIN_SUBELEM_UNIQUE,
2410
0
            LY_STMT_TYPEDEF, &notif->typedefs, 0,
2411
0
            LY_STMT_USES, &notif->child, 0,
2412
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2413
2414
0
    ret = yin_parse_content(ctx, subelems, subelems_size, notif, LY_STMT_NOTIFICATION, NULL, &notif->exts);
2415
0
    subelems_deallocator(subelems_size, subelems);
2416
0
    LY_CHECK_RET(ret);
2417
2418
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2419
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, notif->exts));
2420
2421
0
    return LY_SUCCESS;
2422
0
}
2423
2424
/**
2425
 * @brief Parse grouping element.
2426
 *
2427
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2428
 * @param[in,out] gr_meta Meta information about parent node and groupings to add to.
2429
 * @return LY_ERR values.
2430
 */
2431
static LY_ERR
2432
yin_parse_grouping(struct lysp_yin_ctx *ctx, struct tree_node_meta *gr_meta)
2433
0
{
2434
0
    struct lysp_node_grp *grp;
2435
0
    struct lysp_node_grp **grps = (struct lysp_node_grp **)gr_meta->nodes;
2436
0
    LY_ERR ret = LY_SUCCESS;
2437
0
    struct yin_subelement *subelems = NULL;
2438
0
    size_t subelems_size;
2439
2440
    /* create new grouping */
2441
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, grps, grp, next, LY_EMEM);
2442
0
    grp->nodetype = LYS_GROUPING;
2443
0
    grp->parent = gr_meta->parent;
2444
2445
    /* parse argument */
2446
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2447
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &grp->name, Y_IDENTIF_ARG, LY_STMT_GROUPING));
2448
2449
    /* parse grouping content */
2450
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 16, &grp->node, &subelems,
2451
0
            LY_STMT_ACTION, &grp->actions, 0,
2452
0
            LY_STMT_ANYDATA, &grp->child, 0,
2453
0
            LY_STMT_ANYXML, &grp->child, 0,
2454
0
            LY_STMT_CHOICE, &grp->child, 0,
2455
0
            LY_STMT_CONTAINER, &grp->child, 0,
2456
0
            LY_STMT_DESCRIPTION, &grp->dsc, YIN_SUBELEM_UNIQUE,
2457
0
            LY_STMT_GROUPING, &grp->groupings, 0,
2458
0
            LY_STMT_LEAF, &grp->child, 0,
2459
0
            LY_STMT_LEAF_LIST, &grp->child, 0,
2460
0
            LY_STMT_LIST, &grp->child, 0,
2461
0
            LY_STMT_NOTIFICATION, &grp->notifs, 0,
2462
0
            LY_STMT_REFERENCE, &grp->ref, YIN_SUBELEM_UNIQUE,
2463
0
            LY_STMT_STATUS, &grp->flags, YIN_SUBELEM_UNIQUE,
2464
0
            LY_STMT_TYPEDEF, &grp->typedefs, 0,
2465
0
            LY_STMT_USES, &grp->child, 0,
2466
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2467
0
    ret = yin_parse_content(ctx, subelems, subelems_size, grp, LY_STMT_GROUPING, NULL, &grp->exts);
2468
0
    subelems_deallocator(subelems_size, subelems);
2469
2470
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2471
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, grp->exts));
2472
2473
    /* store data for collision check */
2474
0
    if (!ret && grp->parent) {
2475
0
        assert(ctx->main_ctx);
2476
0
        LY_CHECK_RET(ly_set_add(&ctx->main_ctx->grps_nodes, grp->parent, 0, NULL));
2477
0
    }
2478
2479
0
    return ret;
2480
0
}
2481
2482
/**
2483
 * @brief Parse container element.
2484
 *
2485
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2486
 * @param[in] node_meta Meta information about parent node and siblings to add to.
2487
 * @return LY_ERR values.
2488
 */
2489
static LY_ERR
2490
yin_parse_container(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
2491
0
{
2492
0
    struct lysp_node_container *cont;
2493
0
    LY_ERR ret = LY_SUCCESS;
2494
0
    struct yin_subelement *subelems = NULL;
2495
0
    size_t subelems_size;
2496
2497
    /* create new container */
2498
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cont, next, LY_EMEM);
2499
0
    cont->nodetype = LYS_CONTAINER;
2500
0
    cont->parent = node_meta->parent;
2501
2502
    /* parse aegument */
2503
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2504
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME,  &cont->name, Y_IDENTIF_ARG, LY_STMT_CONTAINER));
2505
2506
    /* parse container content */
2507
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 21, (struct lysp_node *)cont, &subelems,
2508
0
            LY_STMT_ACTION, &cont->actions, YIN_SUBELEM_VER2,
2509
0
            LY_STMT_ANYDATA, &cont->child, YIN_SUBELEM_VER2,
2510
0
            LY_STMT_ANYXML, &cont->child, 0,
2511
0
            LY_STMT_CHOICE, &cont->child, 0,
2512
0
            LY_STMT_CONFIG, &cont->flags, YIN_SUBELEM_UNIQUE,
2513
0
            LY_STMT_CONTAINER, &cont->child, 0,
2514
0
            LY_STMT_DESCRIPTION, &cont->dsc, YIN_SUBELEM_UNIQUE,
2515
0
            LY_STMT_GROUPING, &cont->groupings, 0,
2516
0
            LY_STMT_IF_FEATURE, &cont->iffeatures, 0,
2517
0
            LY_STMT_LEAF, &cont->child, 0,
2518
0
            LY_STMT_LEAF_LIST, &cont->child, 0,
2519
0
            LY_STMT_LIST, &cont->child, 0,
2520
0
            LY_STMT_MUST, &cont->musts, 0,
2521
0
            LY_STMT_NOTIFICATION, &cont->notifs, YIN_SUBELEM_VER2,
2522
0
            LY_STMT_PRESENCE, &cont->presence, YIN_SUBELEM_UNIQUE,
2523
0
            LY_STMT_REFERENCE, &cont->ref, YIN_SUBELEM_UNIQUE,
2524
0
            LY_STMT_STATUS, &cont->flags, YIN_SUBELEM_UNIQUE,
2525
0
            LY_STMT_TYPEDEF, &cont->typedefs, 0,
2526
0
            LY_STMT_USES, &cont->child, 0,
2527
0
            LY_STMT_WHEN, &cont->when, YIN_SUBELEM_UNIQUE,
2528
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2529
0
    ret = yin_parse_content(ctx, subelems, subelems_size, cont, LY_STMT_CONTAINER, NULL, &cont->exts);
2530
0
    subelems_deallocator(subelems_size, subelems);
2531
0
    LY_CHECK_RET(ret);
2532
2533
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2534
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, cont->exts));
2535
2536
0
    return LY_SUCCESS;
2537
0
}
2538
2539
/**
2540
 * @brief Parse case element.
2541
 *
2542
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2543
 * @param[in] node_meta Meta information about parent node and siblings to add to.
2544
 * @return LY_ERR values.
2545
 */
2546
static LY_ERR
2547
yin_parse_case(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
2548
0
{
2549
0
    struct lysp_node_case *cas;
2550
0
    LY_ERR ret = LY_SUCCESS;
2551
0
    struct yin_subelement *subelems = NULL;
2552
0
    size_t subelems_size;
2553
2554
    /* create new case */
2555
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, cas, next, LY_EMEM);
2556
0
    cas->nodetype = LYS_CASE;
2557
0
    cas->parent = node_meta->parent;
2558
2559
    /* parse argument */
2560
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2561
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &cas->name, Y_IDENTIF_ARG, LY_STMT_CASE));
2562
2563
    /* parse case content */
2564
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 14, (struct lysp_node *)cas, &subelems,
2565
0
            LY_STMT_ANYDATA, &cas->child, YIN_SUBELEM_VER2,
2566
0
            LY_STMT_ANYXML, &cas->child, 0,
2567
0
            LY_STMT_CHOICE, &cas->child, 0,
2568
0
            LY_STMT_CONTAINER, &cas->child, 0,
2569
0
            LY_STMT_DESCRIPTION, &cas->dsc, YIN_SUBELEM_UNIQUE,
2570
0
            LY_STMT_IF_FEATURE, &cas->iffeatures, 0,
2571
0
            LY_STMT_LEAF, &cas->child, 0,
2572
0
            LY_STMT_LEAF_LIST, &cas->child, 0,
2573
0
            LY_STMT_LIST, &cas->child, 0,
2574
0
            LY_STMT_REFERENCE, &cas->ref, YIN_SUBELEM_UNIQUE,
2575
0
            LY_STMT_STATUS, &cas->flags, YIN_SUBELEM_UNIQUE,
2576
0
            LY_STMT_USES, &cas->child, 0,
2577
0
            LY_STMT_WHEN, &cas->when, YIN_SUBELEM_UNIQUE,
2578
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2579
0
    ret = yin_parse_content(ctx, subelems, subelems_size, cas, LY_STMT_CASE, NULL, &cas->exts);
2580
0
    subelems_deallocator(subelems_size, subelems);
2581
0
    LY_CHECK_RET(ret);
2582
2583
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2584
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, cas->exts));
2585
2586
0
    return LY_SUCCESS;
2587
0
}
2588
2589
/**
2590
 * @brief Parse choice element.
2591
 *
2592
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2593
 * @param[in] node_meta Meta information about parent node and siblings to add to.
2594
 * @return LY_ERR values.
2595
 */
2596
LY_ERR
2597
yin_parse_choice(struct lysp_yin_ctx *ctx, struct tree_node_meta *node_meta)
2598
0
{
2599
0
    LY_ERR ret = LY_SUCCESS;
2600
0
    struct yin_subelement *subelems = NULL;
2601
0
    struct lysp_node_choice *choice;
2602
0
    size_t subelems_size;
2603
2604
    /* create new choice */
2605
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, node_meta->nodes, choice, next, LY_EMEM);
2606
2607
0
    choice->nodetype = LYS_CHOICE;
2608
0
    choice->parent = node_meta->parent;
2609
2610
    /* parse argument */
2611
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2612
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &choice->name, Y_IDENTIF_ARG, LY_STMT_CHOICE));
2613
2614
    /* parse choice content */
2615
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)choice, &subelems,
2616
0
            LY_STMT_ANYDATA, &choice->child, YIN_SUBELEM_VER2,
2617
0
            LY_STMT_ANYXML, &choice->child, 0,
2618
0
            LY_STMT_CASE, &choice->child, 0,
2619
0
            LY_STMT_CHOICE, &choice->child, YIN_SUBELEM_VER2,
2620
0
            LY_STMT_CONFIG, &choice->flags, YIN_SUBELEM_UNIQUE,
2621
0
            LY_STMT_CONTAINER, &choice->child, 0,
2622
0
            LY_STMT_DEFAULT, &choice->dflt, YIN_SUBELEM_UNIQUE,
2623
0
            LY_STMT_DESCRIPTION, &choice->dsc, YIN_SUBELEM_UNIQUE,
2624
0
            LY_STMT_IF_FEATURE, &choice->iffeatures, 0,
2625
0
            LY_STMT_LEAF, &choice->child, 0,
2626
0
            LY_STMT_LEAF_LIST, &choice->child, 0,
2627
0
            LY_STMT_LIST, &choice->child, 0,
2628
0
            LY_STMT_MANDATORY, &choice->flags, YIN_SUBELEM_UNIQUE,
2629
0
            LY_STMT_REFERENCE, &choice->ref, YIN_SUBELEM_UNIQUE,
2630
0
            LY_STMT_STATUS, &choice->flags, YIN_SUBELEM_UNIQUE,
2631
0
            LY_STMT_WHEN, &choice->when, YIN_SUBELEM_UNIQUE,
2632
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2633
0
    ret = yin_parse_content(ctx, subelems, subelems_size, choice, LY_STMT_CHOICE, NULL, &choice->exts);
2634
0
    subelems_deallocator(subelems_size, subelems);
2635
0
    LY_CHECK_RET(ret);
2636
2637
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2638
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, choice->exts));
2639
2640
0
    return ret;
2641
0
}
2642
2643
/**
2644
 * @brief Parse input or output element.
2645
 *
2646
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2647
 * @param[in] inout_kw Identification of input/output element.
2648
 * @param[in] inout_meta Meta information about parent node and siblings and input/output pointer to write to.
2649
 * @return LY_ERR values.
2650
 */
2651
static LY_ERR
2652
yin_parse_inout(struct lysp_yin_ctx *ctx, enum ly_stmt inout_kw, struct inout_meta *inout_meta)
2653
0
{
2654
0
    LY_ERR ret = LY_SUCCESS;
2655
0
    struct yin_subelement *subelems = NULL;
2656
0
    size_t subelems_size;
2657
2658
    /* initiate structure */
2659
0
    LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), (inout_kw == LY_STMT_INPUT) ? "input" : "output", 0, &inout_meta->inout_p->name));
2660
0
    inout_meta->inout_p->nodetype = (inout_kw == LY_STMT_INPUT) ? LYS_INPUT : LYS_OUTPUT;
2661
0
    inout_meta->inout_p->parent = inout_meta->parent;
2662
2663
    /* check attributes */
2664
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2665
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, NULL, Y_MAYBE_STR_ARG, inout_kw));
2666
2667
    /* parser input/output content */
2668
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 12, (struct lysp_node *)inout_meta->inout_p, &subelems,
2669
0
            LY_STMT_ANYDATA, &inout_meta->inout_p->child, YIN_SUBELEM_VER2,
2670
0
            LY_STMT_ANYXML, &inout_meta->inout_p->child, 0,
2671
0
            LY_STMT_CHOICE, &inout_meta->inout_p->child, 0,
2672
0
            LY_STMT_CONTAINER, &inout_meta->inout_p->child, 0,
2673
0
            LY_STMT_GROUPING, &inout_meta->inout_p->groupings, 0,
2674
0
            LY_STMT_LEAF, &inout_meta->inout_p->child, 0,
2675
0
            LY_STMT_LEAF_LIST, &inout_meta->inout_p->child, 0,
2676
0
            LY_STMT_LIST, &inout_meta->inout_p->child, 0,
2677
0
            LY_STMT_MUST, &inout_meta->inout_p->musts, YIN_SUBELEM_VER2,
2678
0
            LY_STMT_TYPEDEF, &inout_meta->inout_p->typedefs, 0,
2679
0
            LY_STMT_USES, &inout_meta->inout_p->child, 0,
2680
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2681
0
    ret = yin_parse_content(ctx, subelems, subelems_size, inout_meta->inout_p, inout_kw, NULL, &inout_meta->inout_p->exts);
2682
0
    subelems_deallocator(subelems_size, subelems);
2683
0
    LY_CHECK_RET(ret);
2684
2685
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2686
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, inout_meta->inout_p->exts));
2687
2688
0
    if (!inout_meta->inout_p->child) {
2689
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_MISSTMT, "data-def-stmt", lyplg_ext_stmt2str(inout_kw));
2690
0
        return LY_EVALID;
2691
0
    }
2692
2693
0
    return LY_SUCCESS;
2694
0
}
2695
2696
/**
2697
 * @brief Parse action element.
2698
 *
2699
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2700
 * @param[in] act_meta Meta information about parent node and actions to add to.
2701
 * @return LY_ERR values.
2702
 */
2703
static LY_ERR
2704
yin_parse_action(struct lysp_yin_ctx *ctx, struct tree_node_meta *act_meta)
2705
0
{
2706
0
    struct lysp_node_action *act, **acts = (struct lysp_node_action **)act_meta->nodes;
2707
0
    LY_ERR ret = LY_SUCCESS;
2708
0
    struct yin_subelement *subelems = NULL;
2709
0
    size_t subelems_size;
2710
0
    enum ly_stmt kw = act_meta->parent ? LY_STMT_ACTION : LY_STMT_RPC;
2711
2712
    /* create new action */
2713
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, acts, act, next, LY_EMEM);
2714
0
    act->nodetype = act_meta->parent ? LYS_ACTION : LYS_RPC;
2715
0
    act->parent = act_meta->parent;
2716
2717
    /* parse argument */
2718
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2719
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &act->name, Y_IDENTIF_ARG, kw));
2720
2721
    /* parse content */
2722
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 9, (struct lysp_node *)act, &subelems,
2723
0
            LY_STMT_DESCRIPTION, &act->dsc, YIN_SUBELEM_UNIQUE,
2724
0
            LY_STMT_GROUPING, &act->groupings, 0,
2725
0
            LY_STMT_IF_FEATURE, &act->iffeatures, 0,
2726
0
            LY_STMT_INPUT, &act->input, YIN_SUBELEM_UNIQUE,
2727
0
            LY_STMT_OUTPUT, &act->output, YIN_SUBELEM_UNIQUE,
2728
0
            LY_STMT_REFERENCE, &act->ref, YIN_SUBELEM_UNIQUE,
2729
0
            LY_STMT_STATUS, &act->flags, YIN_SUBELEM_UNIQUE,
2730
0
            LY_STMT_TYPEDEF, &act->typedefs, 0,
2731
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2732
0
    ret = (yin_parse_content(ctx, subelems, subelems_size, act, kw, NULL, &act->exts));
2733
0
    subelems_deallocator(subelems_size, subelems);
2734
0
    LY_CHECK_RET(ret);
2735
2736
    /* always initialize inout, they are technically present (needed for later deviations/refines) */
2737
0
    if (!act->input.nodetype) {
2738
0
        act->input.nodetype = LYS_INPUT;
2739
0
        act->input.parent = (struct lysp_node *)act;
2740
0
        LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "input", 0, &act->input.name));
2741
0
    }
2742
0
    if (!act->output.nodetype) {
2743
0
        act->output.nodetype = LYS_OUTPUT;
2744
0
        act->output.parent = (struct lysp_node *)act;
2745
0
        LY_CHECK_RET(lydict_insert(PARSER_CTX(ctx), "output", 0, &act->output.name));
2746
0
    }
2747
2748
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2749
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, act->exts));
2750
2751
0
    return LY_SUCCESS;
2752
0
}
2753
2754
/**
2755
 * @brief Parse augment element.
2756
 *
2757
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2758
 * @param[in] aug_meta Meta information about parent node and augments to add to.
2759
 * @return LY_ERR values.
2760
 */
2761
static LY_ERR
2762
yin_parse_augment(struct lysp_yin_ctx *ctx, struct tree_node_meta *aug_meta)
2763
0
{
2764
0
    struct lysp_node_augment *aug;
2765
0
    struct lysp_node_augment **augs = (struct lysp_node_augment **)aug_meta->nodes;
2766
0
    LY_ERR ret = LY_SUCCESS;
2767
0
    struct yin_subelement *subelems = NULL;
2768
0
    size_t subelems_size;
2769
2770
    /* create new augment */
2771
0
    LY_LIST_NEW_RET(ctx->xmlctx->ctx, augs, aug, next, LY_EMEM);
2772
0
    aug->nodetype = LYS_AUGMENT;
2773
0
    aug->parent = aug_meta->parent;
2774
2775
    /* parse argument */
2776
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2777
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &aug->nodeid, Y_STR_ARG, LY_STMT_AUGMENT));
2778
0
    CHECK_NONEMPTY((struct lysp_ctx *)ctx, strlen(aug->nodeid), "augment");
2779
2780
    /* parser augment content */
2781
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 17, (struct lysp_node *)aug, &subelems,
2782
0
            LY_STMT_ACTION, &aug->actions, YIN_SUBELEM_VER2,
2783
0
            LY_STMT_ANYDATA, &aug->child, YIN_SUBELEM_VER2,
2784
0
            LY_STMT_ANYXML, &aug->child, 0,
2785
0
            LY_STMT_CASE, &aug->child, 0,
2786
0
            LY_STMT_CHOICE, &aug->child, 0,
2787
0
            LY_STMT_CONTAINER, &aug->child, 0,
2788
0
            LY_STMT_DESCRIPTION, &aug->dsc, YIN_SUBELEM_UNIQUE,
2789
0
            LY_STMT_IF_FEATURE, &aug->iffeatures, 0,
2790
0
            LY_STMT_LEAF, &aug->child, 0,
2791
0
            LY_STMT_LEAF_LIST, &aug->child, 0,
2792
0
            LY_STMT_LIST, &aug->child, 0,
2793
0
            LY_STMT_NOTIFICATION, &aug->notifs, YIN_SUBELEM_VER2,
2794
0
            LY_STMT_REFERENCE, &aug->ref, YIN_SUBELEM_UNIQUE,
2795
0
            LY_STMT_STATUS, &aug->flags, YIN_SUBELEM_UNIQUE,
2796
0
            LY_STMT_USES, &aug->child, 0,
2797
0
            LY_STMT_WHEN, &aug->when, YIN_SUBELEM_UNIQUE,
2798
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
2799
0
    ret = yin_parse_content(ctx, subelems, subelems_size, aug, LY_STMT_AUGMENT, NULL, &aug->exts);
2800
0
    subelems_deallocator(subelems_size, subelems);
2801
0
    LY_CHECK_RET(ret);
2802
2803
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2804
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, aug->exts));
2805
2806
0
    return LY_SUCCESS;
2807
0
}
2808
2809
/**
2810
 * @brief Parse deviate element.
2811
 *
2812
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2813
 * @param[in] deviates Deviates to add to.
2814
 * @return LY_ERR values.
2815
 */
2816
static LY_ERR
2817
yin_parse_deviate(struct lysp_yin_ctx *ctx, struct lysp_deviate **deviates)
2818
0
{
2819
0
    LY_ERR ret = LY_SUCCESS;
2820
0
    uint8_t dev_mod;
2821
0
    const char *temp_val;
2822
0
    struct lysp_deviate *d;
2823
0
    struct lysp_deviate_add *d_add = NULL;
2824
0
    struct lysp_deviate_rpl *d_rpl = NULL;
2825
0
    struct lysp_deviate_del *d_del = NULL;
2826
2827
    /* parse argument */
2828
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
2829
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, &temp_val, Y_STR_ARG, LY_STMT_DEVIATE));
2830
2831
0
    if (strcmp(temp_val, "not-supported") == 0) {
2832
0
        dev_mod = LYS_DEV_NOT_SUPPORTED;
2833
0
    } else if (strcmp(temp_val, "add") == 0) {
2834
0
        dev_mod = LYS_DEV_ADD;
2835
0
    } else if (strcmp(temp_val, "replace") == 0) {
2836
0
        dev_mod = LYS_DEV_REPLACE;
2837
0
    } else if (strcmp(temp_val, "delete") == 0) {
2838
0
        dev_mod = LYS_DEV_DELETE;
2839
0
    } else {
2840
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INVAL_YIN VALID_VALS4, temp_val, "value", "deviate",
2841
0
                "not-supported", "add", "replace", "delete");
2842
0
        lydict_remove(ctx->xmlctx->ctx, temp_val);
2843
0
        return LY_EVALID;
2844
0
    }
2845
0
    lydict_remove(ctx->xmlctx->ctx, temp_val);
2846
2847
0
    if (dev_mod == LYS_DEV_NOT_SUPPORTED) {
2848
0
        d = calloc(1, sizeof *d);
2849
0
        LY_CHECK_ERR_RET(!d, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
2850
0
        struct yin_subelement subelems[] = {
2851
0
            {LY_STMT_EXTENSION_INSTANCE, NULL, 0}
2852
0
        };
2853
2854
0
        ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
2855
2856
0
    } else if (dev_mod == LYS_DEV_ADD) {
2857
0
        d_add = calloc(1, sizeof *d_add);
2858
0
        LY_CHECK_ERR_RET(!d_add, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
2859
0
        d = (struct lysp_deviate *)d_add;
2860
0
        struct minmax_dev_meta min = {&d_add->min, &d_add->flags, &d_add->exts};
2861
0
        struct minmax_dev_meta max = {&d_add->max, &d_add->flags, &d_add->exts};
2862
0
        struct yin_subelement subelems[] = {
2863
0
            {LY_STMT_CONFIG, &d_add->flags, YIN_SUBELEM_UNIQUE},
2864
0
            {LY_STMT_DEFAULT, &d_add->dflts, 0},
2865
0
            {LY_STMT_MANDATORY, &d_add->flags, YIN_SUBELEM_UNIQUE},
2866
0
            {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2867
0
            {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2868
0
            {LY_STMT_MUST, &d_add->musts, 0},
2869
0
            {LY_STMT_UNIQUE, &d_add->uniques, 0},
2870
0
            {LY_STMT_UNITS, &d_add->units, YIN_SUBELEM_UNIQUE},
2871
0
            {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2872
0
        };
2873
2874
0
        ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
2875
2876
0
    } else if (dev_mod == LYS_DEV_REPLACE) {
2877
0
        d_rpl = calloc(1, sizeof *d_rpl);
2878
0
        LY_CHECK_ERR_RET(!d_rpl, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
2879
0
        d = (struct lysp_deviate *)d_rpl;
2880
0
        struct minmax_dev_meta min = {&d_rpl->min, &d_rpl->flags, &d_rpl->exts};
2881
0
        struct minmax_dev_meta max = {&d_rpl->max, &d_rpl->flags, &d_rpl->exts};
2882
0
        struct yin_subelement subelems[] = {
2883
0
            {LY_STMT_CONFIG, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2884
0
            {LY_STMT_DEFAULT, &d_rpl->dflt, YIN_SUBELEM_UNIQUE},
2885
0
            {LY_STMT_MANDATORY, &d_rpl->flags, YIN_SUBELEM_UNIQUE},
2886
0
            {LY_STMT_MAX_ELEMENTS, &max, YIN_SUBELEM_UNIQUE},
2887
0
            {LY_STMT_MIN_ELEMENTS, &min, YIN_SUBELEM_UNIQUE},
2888
0
            {LY_STMT_TYPE, &d_rpl->type, YIN_SUBELEM_UNIQUE},
2889
0
            {LY_STMT_UNITS, &d_rpl->units, YIN_SUBELEM_UNIQUE},
2890
0
            {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2891
0
        };
2892
2893
0
        ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
2894
2895
0
    } else {
2896
0
        d_del = calloc(1, sizeof *d_del);
2897
0
        LY_CHECK_ERR_RET(!d_del, LOGMEM(ctx->xmlctx->ctx), LY_EMEM);
2898
0
        d = (struct lysp_deviate *)d_del;
2899
0
        struct yin_subelement subelems[] = {
2900
0
            {LY_STMT_DEFAULT, &d_del->dflts, 0},
2901
0
            {LY_STMT_MUST, &d_del->musts, 0},
2902
0
            {LY_STMT_UNIQUE, &d_del->uniques, 0},
2903
0
            {LY_STMT_UNITS, &d_del->units, YIN_SUBELEM_UNIQUE},
2904
0
            {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2905
0
        };
2906
2907
0
        ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), d, LY_STMT_DEVIATE, NULL, &d->exts);
2908
0
    }
2909
0
    LY_CHECK_GOTO(ret, cleanup);
2910
2911
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2912
0
    LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, d->exts), cleanup);
2913
2914
0
    d->mod = dev_mod;
2915
    /* insert into siblings */
2916
0
    LY_LIST_INSERT(deviates, d, next);
2917
2918
0
    return ret;
2919
2920
0
cleanup:
2921
0
    free(d);
2922
0
    return ret;
2923
0
}
2924
2925
/**
2926
 * @brief Parse deviation element.
2927
 *
2928
 * @param[in,out] ctx YIN parser context for logging and to store current state.
2929
 * @param[in] deviations Deviations to add to.
2930
 * @return LY_ERR values.
2931
 */
2932
static LY_ERR
2933
yin_parse_deviation(struct lysp_yin_ctx *ctx, struct lysp_deviation **deviations)
2934
0
{
2935
0
    LY_ERR ret = LY_SUCCESS;
2936
0
    struct lysp_deviation *dev = NULL;
2937
0
    struct lysf_ctx fctx = {.ctx = PARSER_CTX(ctx)};
2938
2939
    /* create new deviation */
2940
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *deviations, dev, LY_EMEM);
2941
2942
    /* parse argument */
2943
0
    LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
2944
0
    LY_CHECK_GOTO(ret = yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, &dev->nodeid, Y_STR_ARG, LY_STMT_DEVIATION), cleanup);
2945
0
    CHECK_NONEMPTY((struct lysp_ctx *)ctx, strlen(dev->nodeid), "deviation");
2946
0
    struct yin_subelement subelems[] = {
2947
0
        {LY_STMT_DESCRIPTION, &dev->dsc, YIN_SUBELEM_UNIQUE},
2948
0
        {LY_STMT_DEVIATE, &dev->deviates, YIN_SUBELEM_MANDATORY},
2949
0
        {LY_STMT_REFERENCE, &dev->ref, YIN_SUBELEM_UNIQUE},
2950
0
        {LY_STMT_EXTENSION_INSTANCE, NULL, 0},
2951
0
    };
2952
2953
0
    ret = yin_parse_content(ctx, subelems, ly_sizeofarray(subelems), dev, LY_STMT_DEVIATION, NULL, &dev->exts);
2954
0
    LY_CHECK_GOTO(ret, cleanup);
2955
2956
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
2957
0
    LY_CHECK_GOTO(ret = yin_unres_exts_add(ctx, dev->exts), cleanup);
2958
2959
0
cleanup:
2960
0
    if (ret) {
2961
0
        lysp_deviation_free(&fctx, dev);
2962
0
        LY_ARRAY_DECREMENT_FREE(*deviations);
2963
0
    }
2964
0
    return ret;
2965
0
}
2966
2967
/**
2968
 * @brief map keyword to keyword-group.
2969
 *
2970
 * @param[in] ctx YIN parser context used for logging.
2971
 * @param[in] kw Keyword that is child of module or submodule.
2972
 * @param[out] group Group of keyword.
2973
 * @return LY_SUCCESS on success LY_EINT if kw can't be mapped to kw_group, should not happen if called correctly.
2974
 */
2975
static LY_ERR
2976
kw2kw_group(struct lysp_yin_ctx *ctx, enum ly_stmt kw, enum yang_module_stmt *group)
2977
0
{
2978
0
    switch (kw) {
2979
    /* module header */
2980
0
    case LY_STMT_NONE:
2981
0
    case LY_STMT_NAMESPACE:
2982
0
    case LY_STMT_PREFIX:
2983
0
    case LY_STMT_BELONGS_TO:
2984
0
    case LY_STMT_YANG_VERSION:
2985
0
        *group = Y_MOD_MODULE_HEADER;
2986
0
        break;
2987
    /* linkage */
2988
0
    case LY_STMT_INCLUDE:
2989
0
    case LY_STMT_IMPORT:
2990
0
        *group = Y_MOD_LINKAGE;
2991
0
        break;
2992
    /* meta */
2993
0
    case LY_STMT_ORGANIZATION:
2994
0
    case LY_STMT_CONTACT:
2995
0
    case LY_STMT_DESCRIPTION:
2996
0
    case LY_STMT_REFERENCE:
2997
0
        *group = Y_MOD_META;
2998
0
        break;
2999
    /* revision */
3000
0
    case LY_STMT_REVISION:
3001
0
        *group = Y_MOD_REVISION;
3002
0
        break;
3003
    /* body */
3004
0
    case LY_STMT_ANYDATA:
3005
0
    case LY_STMT_ANYXML:
3006
0
    case LY_STMT_AUGMENT:
3007
0
    case LY_STMT_CHOICE:
3008
0
    case LY_STMT_CONTAINER:
3009
0
    case LY_STMT_DEVIATION:
3010
0
    case LY_STMT_EXTENSION:
3011
0
    case LY_STMT_FEATURE:
3012
0
    case LY_STMT_GROUPING:
3013
0
    case LY_STMT_IDENTITY:
3014
0
    case LY_STMT_LEAF:
3015
0
    case LY_STMT_LEAF_LIST:
3016
0
    case LY_STMT_LIST:
3017
0
    case LY_STMT_NOTIFICATION:
3018
0
    case LY_STMT_RPC:
3019
0
    case LY_STMT_TYPEDEF:
3020
0
    case LY_STMT_USES:
3021
0
    case LY_STMT_EXTENSION_INSTANCE:
3022
0
        *group = Y_MOD_BODY;
3023
0
        break;
3024
0
    default:
3025
0
        LOGINT(ctx->xmlctx->ctx);
3026
0
        return LY_EINT;
3027
0
    }
3028
3029
0
    return LY_SUCCESS;
3030
0
}
3031
3032
/**
3033
 * @brief Check if relative order of two keywords is valid.
3034
 *
3035
 * @param[in] ctx YIN parser context used for logging.
3036
 * @param[in] cur_stmt Type of current statement.
3037
 * @param[in] next_stmt Type of next statement.
3038
 * @param[in] parent_stmt Type of parent statement, can be se to to LY_STMT_MODULE of LY_STMT_SUBMODULE,
3039
 *            because relative order is required only in module and submodule sub-elements, used for logging.
3040
 * @return LY_SUCCESS on success and LY_EVALID if relative order is invalid.
3041
 */
3042
static LY_ERR
3043
yin_check_relative_order(struct lysp_yin_ctx *ctx, enum ly_stmt cur_stmt, enum ly_stmt next_stmt, enum ly_stmt parent_stmt)
3044
0
{
3045
0
    enum yang_module_stmt gr, next_gr;
3046
3047
0
    assert(parent_stmt == LY_STMT_MODULE || parent_stmt == LY_STMT_SUBMODULE);
3048
3049
0
    if (cur_stmt == LY_STMT_EXTENSION_INSTANCE) {
3050
        /* no order defined */
3051
0
        return LY_SUCCESS;
3052
0
    }
3053
3054
0
    LY_CHECK_RET(kw2kw_group(ctx, cur_stmt, &gr));
3055
0
    LY_CHECK_RET(kw2kw_group(ctx, next_stmt, &next_gr));
3056
3057
0
    if (gr > next_gr) {
3058
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INORDER_YIN, lyplg_ext_stmt2str(parent_stmt), lyplg_ext_stmt2str(next_stmt),
3059
0
                lyplg_ext_stmt2str(cur_stmt));
3060
0
        return LY_EVALID;
3061
0
    }
3062
3063
0
    return LY_SUCCESS;
3064
0
}
3065
3066
/**
3067
 * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
3068
 *
3069
 * @param[in,out] ctx Yin parser context for logging and to store current state.
3070
 * @param[in] parent_stmt Type of parent statement.
3071
 * @param[out] arg Value to write to.
3072
 * @return LY_ERR values.
3073
 */
3074
static LY_ERR
3075
yin_parse_extension_instance_arg(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, const char **arg)
3076
0
{
3077
0
    enum ly_stmt child;
3078
3079
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3080
3081
0
    switch (parent_stmt) {
3082
0
    case LY_STMT_ACTION:
3083
0
    case LY_STMT_ANYDATA:
3084
0
    case LY_STMT_ANYXML:
3085
0
    case LY_STMT_ARGUMENT:
3086
0
    case LY_STMT_BASE:
3087
0
    case LY_STMT_BIT:
3088
0
    case LY_STMT_CASE:
3089
0
    case LY_STMT_CHOICE:
3090
0
    case LY_STMT_CONTAINER:
3091
0
    case LY_STMT_ENUM:
3092
0
    case LY_STMT_EXTENSION:
3093
0
    case LY_STMT_FEATURE:
3094
0
    case LY_STMT_GROUPING:
3095
0
    case LY_STMT_IDENTITY:
3096
0
    case LY_STMT_IF_FEATURE:
3097
0
    case LY_STMT_LEAF:
3098
0
    case LY_STMT_LEAF_LIST:
3099
0
    case LY_STMT_LIST:
3100
0
    case LY_STMT_MODULE:
3101
0
    case LY_STMT_NOTIFICATION:
3102
0
    case LY_STMT_RPC:
3103
0
    case LY_STMT_SUBMODULE:
3104
0
    case LY_STMT_TYPE:
3105
0
    case LY_STMT_TYPEDEF:
3106
0
    case LY_STMT_UNITS:
3107
0
    case LY_STMT_USES:
3108
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, parent_stmt));
3109
0
        break;
3110
0
    case LY_STMT_AUGMENT:
3111
0
    case LY_STMT_DEVIATION:
3112
0
    case LY_STMT_REFINE:
3113
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, parent_stmt));
3114
0
        break;
3115
0
    case LY_STMT_CONFIG:
3116
0
    case LY_STMT_DEFAULT:
3117
0
    case LY_STMT_DEVIATE:
3118
0
    case LY_STMT_ERROR_APP_TAG:
3119
0
    case LY_STMT_FRACTION_DIGITS:
3120
0
    case LY_STMT_KEY:
3121
0
    case LY_STMT_LENGTH:
3122
0
    case LY_STMT_MANDATORY:
3123
0
    case LY_STMT_MAX_ELEMENTS:
3124
0
    case LY_STMT_MIN_ELEMENTS:
3125
0
    case LY_STMT_MODIFIER:
3126
0
    case LY_STMT_ORDERED_BY:
3127
0
    case LY_STMT_PATH:
3128
0
    case LY_STMT_PATTERN:
3129
0
    case LY_STMT_POSITION:
3130
0
    case LY_STMT_PREFIX:
3131
0
    case LY_STMT_PRESENCE:
3132
0
    case LY_STMT_RANGE:
3133
0
    case LY_STMT_REQUIRE_INSTANCE:
3134
0
    case LY_STMT_STATUS:
3135
0
    case LY_STMT_VALUE:
3136
0
    case LY_STMT_YANG_VERSION:
3137
0
    case LY_STMT_YIN_ELEMENT:
3138
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, parent_stmt));
3139
0
        break;
3140
0
    case LY_STMT_IMPORT:
3141
0
    case LY_STMT_INCLUDE:
3142
0
    case LY_STMT_BELONGS_TO:
3143
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, parent_stmt));
3144
0
        break;
3145
0
    case LY_STMT_INPUT:
3146
0
    case LY_STMT_OUTPUT:
3147
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, parent_stmt));
3148
0
        break;
3149
0
    case LY_STMT_MUST:
3150
0
    case LY_STMT_WHEN:
3151
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, parent_stmt));
3152
0
        break;
3153
0
    case LY_STMT_NAMESPACE:
3154
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, parent_stmt));
3155
0
        break;
3156
0
    case LY_STMT_REVISION:
3157
0
    case LY_STMT_REVISION_DATE:
3158
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, parent_stmt));
3159
0
        break;
3160
0
    case LY_STMT_UNIQUE:
3161
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, parent_stmt));
3162
0
        break;
3163
    /* argument is mapped to yin element */
3164
0
    case LY_STMT_CONTACT:
3165
0
    case LY_STMT_DESCRIPTION:
3166
0
    case LY_STMT_ORGANIZATION:
3167
0
    case LY_STMT_REFERENCE:
3168
0
    case LY_STMT_ERROR_MESSAGE:
3169
        /* there shouldn't be any attribute, argument is supposed to be first subelement */
3170
0
        LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, parent_stmt));
3171
3172
        /* no content */
3173
0
        assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3174
0
        if (ctx->xmlctx->ws_only) {
3175
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3176
0
        }
3177
0
        if (((ctx->xmlctx->status == LYXML_ELEM_CONTENT) && !ctx->xmlctx->ws_only) || (ctx->xmlctx->status != LYXML_ELEMENT)) {
3178
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
3179
0
                    parent_stmt == LY_STMT_ERROR_MESSAGE ? "value" : "text", lyplg_ext_stmt2str(parent_stmt));
3180
0
            return LY_EVALID;
3181
0
        }
3182
3183
        /* parse child element */
3184
0
        child = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3185
0
                ctx->xmlctx->prefix_len, parent_stmt);
3186
0
        if (((parent_stmt == LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_VALUE)) ||
3187
0
                ((parent_stmt != LY_STMT_ERROR_MESSAGE) && (child != LY_STMT_ARG_TEXT))) {
3188
0
            LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, (int)ctx->xmlctx->name_len, ctx->xmlctx->name,
3189
0
                    lyplg_ext_stmt2str(parent_stmt));
3190
0
            return LY_EVALID;
3191
0
        }
3192
0
        LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3193
3194
        /* no attributes expected */
3195
0
        while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3196
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3197
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3198
0
        }
3199
3200
        /* load and save content */
3201
0
        INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *arg);
3202
0
        LY_CHECK_RET(!*arg, LY_EMEM);
3203
3204
        /* load closing tag of subelement */
3205
0
        LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3206
0
        break;
3207
0
    default:
3208
0
        LOGINT(ctx->xmlctx->ctx);
3209
0
        return LY_EINT;
3210
0
    }
3211
3212
0
    return LY_SUCCESS;
3213
0
}
3214
3215
/**
3216
 * @brief Parse yin element into generic structure.
3217
 *
3218
 * @param[in,out] ctx Yin parser context for XML context, logging, and to store current state.
3219
 * @param[in] parent_stmt Type of parent statement.
3220
 * @param[out] element Where the element structure should be stored.
3221
 * @return LY_ERR values.
3222
 */
3223
LY_ERR
3224
yin_parse_element_generic(struct lysp_yin_ctx *ctx, enum ly_stmt parent_stmt, struct lysp_stmt **element)
3225
0
{
3226
0
    LY_ERR ret = LY_SUCCESS;
3227
0
    struct lysp_stmt *last = NULL, *new = NULL;
3228
0
    char *id;
3229
3230
0
    assert(ctx->xmlctx->status == LYXML_ELEMENT);
3231
3232
    /* allocate new structure for element */
3233
0
    *element = calloc(1, sizeof(**element));
3234
0
    LY_CHECK_ERR_GOTO(!(*element), LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3235
3236
    /* store identifier */
3237
0
    if (ctx->xmlctx->prefix_len) {
3238
0
        if (asprintf(&id, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3239
0
                ctx->xmlctx->name) == -1) {
3240
0
            LOGMEM(ctx->xmlctx->ctx);
3241
0
            ret = LY_EMEM;
3242
0
            goto cleanup;
3243
0
        }
3244
0
        LY_CHECK_GOTO(ret = lydict_insert_zc(ctx->xmlctx->ctx, id, &(*element)->stmt), cleanup);
3245
3246
        /* store prefix data for the statement */
3247
0
        LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->stmt, strlen((*element)->stmt), LY_VALUE_XML,
3248
0
                &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3249
0
    } else {
3250
0
        LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &(*element)->stmt), cleanup);
3251
0
    }
3252
3253
0
    (*element)->kw = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3254
0
            ctx->xmlctx->prefix_len, parent_stmt);
3255
3256
0
    last = (*element)->child;
3257
0
    if ((*element)->kw == LY_STMT_NONE) {
3258
        /* unrecognized element */
3259
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, (int)ctx->xmlctx->name_len, ctx->xmlctx->name,
3260
0
                lyplg_ext_stmt2str(parent_stmt));
3261
0
        ret = LY_EVALID;
3262
0
        goto cleanup;
3263
0
    } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
3264
        /* element is known yang keyword, which means argument can be parsed correctly. */
3265
0
        ret = yin_parse_extension_instance_arg(ctx, (*element)->kw, &(*element)->arg);
3266
0
        LY_CHECK_GOTO(ret, cleanup);
3267
0
    } else {
3268
0
        LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3269
3270
        /* load attributes in generic way, save all attributes in linked list */
3271
0
        while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3272
0
            new = calloc(1, sizeof(*last));
3273
0
            LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xmlctx->ctx); ret = LY_EMEM, cleanup);
3274
0
            if (!(*element)->child) {
3275
                /* save first */
3276
0
                (*element)->child = new;
3277
0
            } else {
3278
0
                last->next = new;
3279
0
            }
3280
0
            last = new;
3281
3282
0
            last->flags |= LYS_YIN_ATTR;
3283
0
            LY_CHECK_GOTO(ret = lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last->stmt), cleanup);
3284
0
            last->kw = LY_STMT_NONE;
3285
            /* attributes with prefix are ignored */
3286
0
            if (!ctx->xmlctx->prefix) {
3287
0
                LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3288
3289
0
                INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, last->arg);
3290
0
                LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
3291
0
            } else {
3292
0
                LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3293
0
            }
3294
0
            LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3295
0
        }
3296
0
    }
3297
3298
0
    if ((ctx->xmlctx->status != LYXML_ELEM_CONTENT) || ctx->xmlctx->ws_only) {
3299
0
        LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3300
0
        while (ctx->xmlctx->status == LYXML_ELEMENT) {
3301
            /* parse subelements */
3302
0
            ret = yin_parse_element_generic(ctx, (*element)->kw, &new);
3303
0
            LY_CHECK_GOTO(ret, cleanup);
3304
0
            if (!(*element)->child) {
3305
                /* save first */
3306
0
                (*element)->child = new;
3307
0
            } else {
3308
0
                last->next = new;
3309
0
            }
3310
0
            last = new;
3311
3312
0
            assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3313
0
            LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3314
0
        }
3315
0
    } else {
3316
        /* save element content */
3317
0
        if (ctx->xmlctx->value_len) {
3318
0
            INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, (*element)->arg);
3319
0
            LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
3320
3321
            /* store prefix data for the argument as well */
3322
0
            LY_CHECK_GOTO(ret = ly_store_prefix_data(ctx->xmlctx->ctx, (*element)->arg, strlen((*element)->arg), LY_VALUE_XML,
3323
0
                    &ctx->xmlctx->ns, &(*element)->format, &(*element)->prefix_data), cleanup);
3324
0
        }
3325
3326
        /* read closing tag */
3327
0
        LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3328
0
    }
3329
3330
0
cleanup:
3331
0
    return ret;
3332
0
}
3333
3334
/**
3335
 * @brief Parse instance of extension.
3336
 *
3337
 * @param[in,out] ctx Yin parser context for logging and to store current state.
3338
 * @param[in] parent Current statement parent.
3339
 * @param[in] parent_stmt Type of @p parent statement.
3340
 * @param[in] parent_stmt_index In case of several @p parent_stmt, index of the relevant @p parent statement.
3341
 * @param[in,out] exts Extension instance to add to.
3342
 * @return LY_ERR values.
3343
 */
3344
LY_ERR
3345
yin_parse_extension_instance(struct lysp_yin_ctx *ctx, const void *parent, enum ly_stmt parent_stmt,
3346
        LY_ARRAY_COUNT_TYPE parent_stmt_index, struct lysp_ext_instance **exts)
3347
0
{
3348
0
    struct lysp_ext_instance *e;
3349
0
    struct lysp_stmt *last_subelem = NULL, *new_subelem = NULL;
3350
0
    char *ext_name;
3351
3352
0
    assert(ctx->xmlctx->status == LYXML_ELEMENT);
3353
0
    assert(exts);
3354
3355
0
    LY_ARRAY_NEW_RET(ctx->xmlctx->ctx, *exts, e, LY_EMEM);
3356
3357
0
    if (!ctx->xmlctx->prefix_len) {
3358
0
        LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%*.s\" without the mandatory prefix.",
3359
0
                (int)ctx->xmlctx->name_len, ctx->xmlctx->name);
3360
0
        return LY_EVALID;
3361
0
    }
3362
3363
    /* store prefixed name */
3364
0
    if (asprintf(&ext_name, "%.*s:%.*s", (int)ctx->xmlctx->prefix_len, ctx->xmlctx->prefix, (int)ctx->xmlctx->name_len,
3365
0
            ctx->xmlctx->name) == -1) {
3366
0
        LOGMEM(ctx->xmlctx->ctx);
3367
0
        return LY_EMEM;
3368
0
    }
3369
0
    LY_CHECK_RET(lydict_insert_zc(ctx->xmlctx->ctx, ext_name, &e->name));
3370
3371
    /* store prefix data for the name */
3372
0
    LY_CHECK_RET(ly_store_prefix_data(ctx->xmlctx->ctx, e->name, strlen(e->name), LY_VALUE_XML, &ctx->xmlctx->ns,
3373
0
            &e->format, &e->prefix_data));
3374
3375
0
    e->parent = (void *)parent;
3376
0
    e->parent_stmt = parent_stmt;
3377
0
    e->parent_stmt_index = parent_stmt_index;
3378
3379
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3380
3381
    /* store attributes as subelements */
3382
0
    while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3383
0
        if (!ctx->xmlctx->prefix) {
3384
0
            new_subelem = calloc(1, sizeof(*new_subelem));
3385
0
            if (!e->child) {
3386
0
                e->child = new_subelem;
3387
0
            } else {
3388
0
                last_subelem->next = new_subelem;
3389
0
            }
3390
0
            last_subelem = new_subelem;
3391
3392
0
            last_subelem->flags |= LYS_YIN_ATTR;
3393
0
            LY_CHECK_RET(lydict_insert(ctx->xmlctx->ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, &last_subelem->stmt));
3394
0
            LY_CHECK_RET(!last_subelem->stmt, LY_EMEM);
3395
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3396
3397
0
            INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic,
3398
0
                    last_subelem->arg);
3399
0
            LY_CHECK_RET(!last_subelem->arg, LY_EMEM);
3400
0
        } else {
3401
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3402
0
        }
3403
3404
0
        LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3405
0
    }
3406
3407
    /* parse subelements */
3408
0
    assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3409
0
    if (ctx->xmlctx->ws_only) {
3410
0
        LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3411
0
        while (ctx->xmlctx->status == LYXML_ELEMENT) {
3412
0
            LY_CHECK_RET(yin_parse_element_generic(ctx, LY_STMT_EXTENSION_INSTANCE, &new_subelem));
3413
0
            if (!e->child) {
3414
0
                e->child = new_subelem;
3415
0
            } else {
3416
0
                last_subelem->next = new_subelem;
3417
0
            }
3418
0
            last_subelem = new_subelem;
3419
3420
0
            assert(ctx->xmlctx->status == LYXML_ELEM_CLOSE);
3421
0
            LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3422
0
        }
3423
0
    } else if (ctx->xmlctx->value_len) {
3424
        /* invalid text content */
3425
0
        LOGVAL_PARSER(ctx, LYVE_SYNTAX, "Extension instance \"%s\" with unexpected text content \"%.*s\".", ext_name,
3426
0
                (int)ctx->xmlctx->value_len, ctx->xmlctx->value);
3427
0
        return LY_EVALID;
3428
0
    }
3429
3430
0
    e->parsed = NULL;
3431
3432
0
    return LY_SUCCESS;
3433
0
}
3434
3435
/**
3436
 * @brief Generic function for content parsing
3437
 *
3438
 * @param[in,out] ctx Yin parser context for logging and to store current state.
3439
 * @param[in] subelem_info array of valid subelement types and meta information
3440
 * @param[in] subelem_info_size Size of subelem_info array.
3441
 * @param[in] parent Current statement parent.
3442
 * @param[in] parent_stmt Type of @p parent statement.
3443
 * @param[out] text_content Where the text content of element should be stored if any. Text content is ignored if set to NULL.
3444
 * @param[in,out] exts Extension instance to add to. Can be set to null if element cannot have extension as subelements.
3445
 * @return LY_ERR values.
3446
 */
3447
LY_ERR
3448
yin_parse_content(struct lysp_yin_ctx *ctx, struct yin_subelement *subelem_info, size_t subelem_info_size,
3449
        const void *parent, enum ly_stmt parent_stmt, const char **text_content, struct lysp_ext_instance **exts)
3450
0
{
3451
0
    LY_ERR ret = LY_SUCCESS;
3452
0
    enum LYXML_PARSER_STATUS next_status;
3453
0
    enum ly_stmt cur_stmt = LY_STMT_NONE, last_stmt = LY_STMT_NONE;
3454
0
    struct yin_subelement *subelem = NULL;
3455
3456
0
    assert(ctx->xmlctx->status == LYXML_ELEM_CONTENT);
3457
3458
0
    if (ctx->xmlctx->ws_only) {
3459
        /* check whether there are any children */
3460
0
        LY_CHECK_GOTO(ret = lyxml_ctx_peek(ctx->xmlctx, &next_status), cleanup);
3461
0
    } else {
3462
        /* we want to parse the value */
3463
0
        next_status = LYXML_ELEM_CLOSE;
3464
0
    }
3465
3466
0
    if (next_status == LYXML_ELEMENT) {
3467
0
        LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3468
3469
        /* current element has subelements as content */
3470
0
        while (ctx->xmlctx->status == LYXML_ELEMENT) {
3471
            /* match keyword */
3472
0
            last_stmt = cur_stmt;
3473
0
            cur_stmt = yin_match_keyword(ctx, ctx->xmlctx->name, ctx->xmlctx->name_len, ctx->xmlctx->prefix,
3474
0
                    ctx->xmlctx->prefix_len, parent_stmt);
3475
3476
            /* check if this element can be child of current element */
3477
0
            subelem = get_record(cur_stmt, subelem_info_size, subelem_info);
3478
0
            if (!subelem) {
3479
0
                if ((parent_stmt == LY_STMT_DEVIATE) && isdevsub(cur_stmt)) {
3480
0
                    LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INDEV_YIN, lyplg_ext_stmt2str(cur_stmt));
3481
0
                } else {
3482
0
                    LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, (int)ctx->xmlctx->name_len,
3483
0
                            ctx->xmlctx->name, lyplg_ext_stmt2str(parent_stmt));
3484
0
                }
3485
0
                ret = LY_EVALID;
3486
0
                goto cleanup;
3487
0
            }
3488
3489
            /* relative order is required only in module and submodule sub-elements */
3490
0
            if ((parent_stmt == LY_STMT_MODULE) || (parent_stmt == LY_STMT_SUBMODULE)) {
3491
0
                ret = yin_check_relative_order(ctx, last_stmt, cur_stmt, parent_stmt);
3492
0
                LY_CHECK_GOTO(ret, cleanup);
3493
0
            }
3494
3495
            /* flag check */
3496
0
            if ((subelem->flags & YIN_SUBELEM_UNIQUE) && (subelem->flags & YIN_SUBELEM_PARSED)) {
3497
                /* subelement uniquenes */
3498
0
                LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_SUBELEM_REDEF, lyplg_ext_stmt2str(cur_stmt), lyplg_ext_stmt2str(parent_stmt));
3499
0
                return LY_EVALID;
3500
0
            }
3501
0
            if (subelem->flags & YIN_SUBELEM_FIRST) {
3502
                /* subelement is supposed to be defined as first subelement */
3503
0
                ret = yin_check_subelem_first_constraint(ctx, subelem_info, subelem_info_size, parent_stmt, subelem);
3504
0
                LY_CHECK_GOTO(ret, cleanup);
3505
0
            }
3506
0
            if (subelem->flags & YIN_SUBELEM_VER2) {
3507
                /* subelement is supported only in version 1.1 or higher */
3508
0
                if (PARSER_CUR_PMOD(ctx)->version < LYS_VERSION_1_1) {
3509
0
                    LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_INSUBELEM2, lyplg_ext_stmt2str(cur_stmt), lyplg_ext_stmt2str(parent_stmt));
3510
0
                    ret = LY_EVALID;
3511
0
                    goto cleanup;
3512
0
                }
3513
0
            }
3514
            /* note that element was parsed for easy uniqueness check in next iterations */
3515
0
            subelem->flags |= YIN_SUBELEM_PARSED;
3516
3517
0
            switch (cur_stmt) {
3518
            /* call responsible function */
3519
0
            case LY_STMT_EXTENSION_INSTANCE:
3520
0
                ret = yin_parse_extension_instance(ctx, parent, parent_stmt,
3521
0
                        (subelem->dest) ? *((LY_ARRAY_COUNT_TYPE *)subelem->dest) : 0, exts);
3522
0
                break;
3523
0
            case LY_STMT_ACTION:
3524
0
            case LY_STMT_RPC:
3525
0
                ret = yin_parse_action(ctx, (struct tree_node_meta *)subelem->dest);
3526
0
                break;
3527
0
            case LY_STMT_ANYDATA:
3528
0
            case LY_STMT_ANYXML:
3529
0
                ret = yin_parse_any(ctx, cur_stmt, (struct tree_node_meta *)subelem->dest);
3530
0
                break;
3531
0
            case LY_STMT_ARGUMENT:
3532
0
                ret = yin_parse_argument(ctx, parent, (struct yin_argument_meta *)subelem->dest, exts);
3533
0
                break;
3534
0
            case LY_STMT_AUGMENT:
3535
0
                ret = yin_parse_augment(ctx, (struct tree_node_meta *)subelem->dest);
3536
0
                break;
3537
0
            case LY_STMT_BASE:
3538
0
                ret = yin_parse_base(ctx, parent_stmt, subelem->dest, exts);
3539
0
                break;
3540
0
            case LY_STMT_BELONGS_TO:
3541
0
                ret = yin_parse_belongs_to(ctx, (struct lysp_submodule *)subelem->dest, exts);
3542
0
                break;
3543
0
            case LY_STMT_BIT:
3544
0
                ret = yin_parse_bit(ctx, (struct lysp_type *)subelem->dest);
3545
0
                break;
3546
0
            case LY_STMT_CASE:
3547
0
                ret = yin_parse_case(ctx, (struct tree_node_meta *)subelem->dest);
3548
0
                break;
3549
0
            case LY_STMT_CHOICE:
3550
0
                ret = yin_parse_choice(ctx, (struct tree_node_meta *)subelem->dest);
3551
0
                break;
3552
0
            case LY_STMT_CONFIG:
3553
0
                ret = yin_parse_config(ctx, (uint16_t *)subelem->dest, exts);
3554
0
                break;
3555
0
            case LY_STMT_CONTACT:
3556
0
            case LY_STMT_DESCRIPTION:
3557
0
            case LY_STMT_ORGANIZATION:
3558
0
            case LY_STMT_REFERENCE:
3559
0
                ret = yin_parse_meta(ctx, parent, cur_stmt, (const char **)subelem->dest, exts);
3560
0
                break;
3561
0
            case LY_STMT_CONTAINER:
3562
0
                ret = yin_parse_container(ctx, (struct tree_node_meta *)subelem->dest);
3563
0
                break;
3564
0
            case LY_STMT_DEFAULT:
3565
0
                ret = yin_parse_qname(ctx, cur_stmt, subelem, exts);
3566
0
                break;
3567
0
            case LY_STMT_ERROR_APP_TAG:
3568
0
            case LY_STMT_KEY:
3569
0
                ret = yin_parse_simple_elem(ctx, parent, cur_stmt, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3570
0
                break;
3571
0
            case LY_STMT_PRESENCE:
3572
0
                ret = yin_parse_simple_elem(ctx, *(const char **)subelem->dest, cur_stmt, subelem, YIN_ARG_VALUE, Y_STR_ARG, exts);
3573
0
                break;
3574
0
            case LY_STMT_DEVIATE:
3575
0
                ret = yin_parse_deviate(ctx, (struct lysp_deviate **)subelem->dest);
3576
0
                break;
3577
0
            case LY_STMT_DEVIATION:
3578
0
                ret = yin_parse_deviation(ctx, (struct lysp_deviation **)subelem->dest);
3579
0
                break;
3580
0
            case LY_STMT_ENUM:
3581
0
                ret = yin_parse_enum(ctx, (struct lysp_type *)subelem->dest);
3582
0
                break;
3583
0
            case LY_STMT_ERROR_MESSAGE:
3584
0
                ret = yin_parse_err_msg(ctx, parent, (const char **)subelem->dest, exts);
3585
0
                break;
3586
0
            case LY_STMT_EXTENSION:
3587
0
                ret = yin_parse_extension(ctx, (struct lysp_ext **)subelem->dest);
3588
0
                break;
3589
0
            case LY_STMT_FEATURE:
3590
0
                ret = yin_parse_feature(ctx, (struct lysp_feature **)subelem->dest);
3591
0
                break;
3592
0
            case LY_STMT_FRACTION_DIGITS:
3593
0
                ret = yin_parse_fracdigits(ctx, (struct lysp_type *)subelem->dest);
3594
0
                break;
3595
0
            case LY_STMT_GROUPING:
3596
0
                ret = yin_parse_grouping(ctx, (struct tree_node_meta *)subelem->dest);
3597
0
                break;
3598
0
            case LY_STMT_IDENTITY:
3599
0
                ret = yin_parse_identity(ctx, (struct lysp_ident **)subelem->dest);
3600
0
                break;
3601
0
            case LY_STMT_UNIQUE:
3602
0
            case LY_STMT_IF_FEATURE:
3603
0
                ret = yin_parse_qname(ctx, cur_stmt, subelem, exts);
3604
0
                break;
3605
0
            case LY_STMT_UNITS:
3606
0
                ret = yin_parse_simple_elem(ctx, *(const char **)subelem->dest, cur_stmt, subelem, YIN_ARG_NAME, Y_STR_ARG, exts);
3607
0
                break;
3608
0
            case LY_STMT_IMPORT:
3609
0
                ret = yin_parse_import(ctx, (struct import_meta *)subelem->dest);
3610
0
                break;
3611
0
            case LY_STMT_INCLUDE:
3612
0
                if ((parent_stmt == LY_STMT_SUBMODULE) && (PARSER_CUR_PMOD(ctx)->version == LYS_VERSION_1_1)) {
3613
0
                    LOGWRN(PARSER_CTX(ctx), "YANG version 1.1 expects all includes in main module, includes in "
3614
0
                            "submodules (%s) are not necessary.", ((struct lysp_submodule *)PARSER_CUR_PMOD(ctx))->name);
3615
0
                }
3616
0
                ret = yin_parse_include(ctx, (struct include_meta *)subelem->dest);
3617
0
                break;
3618
0
            case LY_STMT_INPUT:
3619
0
            case LY_STMT_OUTPUT:
3620
0
                ret = yin_parse_inout(ctx, cur_stmt, (struct inout_meta *)subelem->dest);
3621
0
                break;
3622
0
            case LY_STMT_LEAF:
3623
0
                ret = yin_parse_leaf(ctx, (struct tree_node_meta *)subelem->dest);
3624
0
                break;
3625
0
            case LY_STMT_LEAF_LIST:
3626
0
                ret = yin_parse_leaflist(ctx, (struct tree_node_meta *)subelem->dest);
3627
0
                break;
3628
0
            case LY_STMT_LENGTH:
3629
0
                ret = yin_parse_length(ctx, (struct lysp_type *)subelem->dest);
3630
0
                break;
3631
0
            case LY_STMT_LIST:
3632
0
                ret = yin_parse_list(ctx, (struct tree_node_meta *)subelem->dest);
3633
0
                break;
3634
0
            case LY_STMT_MANDATORY:
3635
0
                ret = yin_parse_mandatory(ctx, (uint16_t *)subelem->dest, exts);
3636
0
                break;
3637
0
            case LY_STMT_MAX_ELEMENTS:
3638
0
            case LY_STMT_MIN_ELEMENTS:
3639
0
                ret = yin_parse_minmax(ctx, parent_stmt, cur_stmt, subelem->dest);
3640
0
                break;
3641
0
            case LY_STMT_MODIFIER:
3642
0
                ret = yin_parse_modifier(ctx, parent, (const char **)subelem->dest, exts);
3643
0
                break;
3644
0
            case LY_STMT_MUST:
3645
0
                ret = yin_parse_must(ctx, (struct lysp_restr **)subelem->dest);
3646
0
                break;
3647
0
            case LY_STMT_NAMESPACE:
3648
0
                ret = yin_parse_simple_elem(ctx, parent, cur_stmt, subelem, YIN_ARG_URI, Y_STR_ARG, exts);
3649
0
                break;
3650
0
            case LY_STMT_NOTIFICATION:
3651
0
                ret = yin_parse_notification(ctx, (struct tree_node_meta *)subelem->dest);
3652
0
                break;
3653
0
            case LY_STMT_ORDERED_BY:
3654
0
                ret = yin_parse_orderedby(ctx, parent, (uint16_t *)subelem->dest, exts);
3655
0
                break;
3656
0
            case LY_STMT_PATH:
3657
0
                ret = yin_parse_path(ctx, (struct lysp_type *)subelem->dest);
3658
0
                break;
3659
0
            case LY_STMT_PATTERN:
3660
0
                ret = yin_parse_pattern(ctx, (struct lysp_type *)subelem->dest);
3661
0
                break;
3662
0
            case LY_STMT_VALUE:
3663
0
            case LY_STMT_POSITION:
3664
0
                ret = yin_parse_value_pos(ctx, cur_stmt, (struct lysp_type_enum *)subelem->dest);
3665
0
                break;
3666
0
            case LY_STMT_PREFIX:
3667
0
                ret = yin_parse_simple_elem(ctx, *(const char **)subelem->dest, cur_stmt, subelem, YIN_ARG_VALUE,
3668
0
                        Y_IDENTIF_ARG, exts);
3669
0
                break;
3670
0
            case LY_STMT_RANGE:
3671
0
                ret = yin_parse_range(ctx, (struct lysp_type *)subelem->dest);
3672
0
                break;
3673
0
            case LY_STMT_REFINE:
3674
0
                ret = yin_parse_refine(ctx, (struct lysp_refine **)subelem->dest);
3675
0
                break;
3676
0
            case LY_STMT_REQUIRE_INSTANCE:
3677
0
                ret = yin_pasrse_reqinstance(ctx, (struct lysp_type *)subelem->dest);
3678
0
                break;
3679
0
            case LY_STMT_REVISION:
3680
0
                ret = yin_parse_revision(ctx, (struct lysp_revision **)subelem->dest);
3681
0
                break;
3682
0
            case LY_STMT_REVISION_DATE:
3683
0
                ret = yin_parse_revision_date(ctx, (char *)subelem->dest, exts);
3684
0
                break;
3685
0
            case LY_STMT_STATUS:
3686
0
                ret = yin_parse_status(ctx, (uint16_t *)subelem->dest, exts);
3687
0
                break;
3688
0
            case LY_STMT_TYPE:
3689
0
                ret = yin_parse_type(ctx, parent_stmt, subelem);
3690
0
                break;
3691
0
            case LY_STMT_TYPEDEF:
3692
0
                ret = yin_parse_typedef(ctx, (struct tree_node_meta *)subelem->dest);
3693
0
                break;
3694
0
            case LY_STMT_USES:
3695
0
                ret = yin_parse_uses(ctx, (struct tree_node_meta *)subelem->dest);
3696
0
                break;
3697
0
            case LY_STMT_WHEN:
3698
0
                ret = yin_parse_when(ctx, (struct lysp_when **)subelem->dest);
3699
0
                break;
3700
0
            case LY_STMT_YANG_VERSION:
3701
0
                ret = yin_parse_yangversion(ctx, parent, (uint8_t *)subelem->dest, exts);
3702
0
                break;
3703
0
            case LY_STMT_YIN_ELEMENT:
3704
0
                ret = yin_parse_yin_element(ctx, parent, (uint16_t *)subelem->dest, exts);
3705
0
                break;
3706
0
            case LY_STMT_ARG_TEXT:
3707
0
            case LY_STMT_ARG_VALUE:
3708
                /* TODO what to do with content/attributes? */
3709
0
                LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3710
0
                while (ctx->xmlctx->status == LYXML_ATTRIBUTE) {
3711
0
                    LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3712
0
                    LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3713
0
                }
3714
0
                ret = yin_parse_content(ctx, NULL, 0, parent, cur_stmt, (const char **)subelem->dest, NULL);
3715
0
                break;
3716
0
            default:
3717
0
                LOGINT(ctx->xmlctx->ctx);
3718
0
                ret = LY_EINT;
3719
0
            }
3720
0
            LY_CHECK_GOTO(ret, cleanup);
3721
3722
0
            LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3723
0
        }
3724
0
    } else {
3725
0
        LY_CHECK_RET(ret);
3726
        /* elements with text or none content */
3727
        /* save text content, if text_content isn't set, it's just ignored */
3728
        /* no resources are allocated in this branch, no need to use cleanup label */
3729
0
        LY_CHECK_RET(yin_validate_value(ctx, Y_STR_ARG));
3730
0
        if (text_content) {
3731
0
            INSERT_STRING_RET(ctx->xmlctx->ctx, ctx->xmlctx->value, ctx->xmlctx->value_len, ctx->xmlctx->dynamic, *text_content);
3732
0
            LY_CHECK_RET(!*text_content, LY_EMEM);
3733
0
        }
3734
3735
0
        LY_CHECK_GOTO(ret = lyxml_ctx_next(ctx->xmlctx), cleanup);
3736
0
    }
3737
3738
    /* mandatory subelements are checked only after whole element was succesfully parsed */
3739
0
    LY_CHECK_RET(yin_check_subelem_mandatory_constraint(ctx, subelem_info, subelem_info_size, parent_stmt));
3740
3741
0
cleanup:
3742
0
    return ret;
3743
0
}
3744
3745
/**
3746
 * @brief Parse module element.
3747
 *
3748
 * @param[in,out] ctx Yin parser context for logging and to store current state.
3749
 * @param[out] mod Parsed module structure.
3750
 * @return LY_ERR values.
3751
 */
3752
LY_ERR
3753
yin_parse_mod(struct lysp_yin_ctx *ctx, struct lysp_module *mod)
3754
0
{
3755
0
    LY_ERR ret = LY_SUCCESS;
3756
0
    struct yin_subelement *subelems = NULL;
3757
0
    const struct lysp_submodule *dup;
3758
0
    size_t subelems_size;
3759
3760
0
    mod->is_submod = 0;
3761
3762
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3763
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &mod->mod->name, Y_IDENTIF_ARG, LY_STMT_MODULE));
3764
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 28, NULL, &subelems,
3765
0
            LY_STMT_ANYDATA, &mod->data, YIN_SUBELEM_VER2,
3766
0
            LY_STMT_ANYXML, &mod->data, 0,
3767
0
            LY_STMT_AUGMENT, &mod->augments, 0,
3768
0
            LY_STMT_CHOICE, &mod->data, 0,
3769
0
            LY_STMT_CONTACT, &mod->mod->contact, YIN_SUBELEM_UNIQUE,
3770
0
            LY_STMT_CONTAINER, &mod->data, 0,
3771
0
            LY_STMT_DESCRIPTION, &mod->mod->dsc, YIN_SUBELEM_UNIQUE,
3772
0
            LY_STMT_DEVIATION, &mod->deviations, 0,
3773
0
            LY_STMT_EXTENSION, &mod->extensions, 0,
3774
0
            LY_STMT_FEATURE, &mod->features, 0,
3775
0
            LY_STMT_GROUPING, &mod->groupings, 0,
3776
0
            LY_STMT_IDENTITY, &mod->identities, 0,
3777
0
            LY_STMT_IMPORT, mod->mod->prefix, &mod->imports, 0,
3778
0
            LY_STMT_INCLUDE, mod->mod->name, &mod->includes, 0,
3779
0
            LY_STMT_LEAF, &mod->data, 0,
3780
0
            LY_STMT_LEAF_LIST, &mod->data, 0,
3781
0
            LY_STMT_LIST, &mod->data, 0,
3782
0
            LY_STMT_NAMESPACE, &mod->mod->ns, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3783
0
            LY_STMT_NOTIFICATION, &mod->notifs, 0,
3784
0
            LY_STMT_ORGANIZATION, &mod->mod->org, YIN_SUBELEM_UNIQUE,
3785
0
            LY_STMT_PREFIX, &mod->mod->prefix, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3786
0
            LY_STMT_REFERENCE, &mod->mod->ref, YIN_SUBELEM_UNIQUE,
3787
0
            LY_STMT_REVISION, &mod->revs, 0,
3788
0
            LY_STMT_RPC, &mod->rpcs, 0,
3789
0
            LY_STMT_TYPEDEF, &mod->typedefs, 0,
3790
0
            LY_STMT_USES, &mod->data, 0,
3791
0
            LY_STMT_YANG_VERSION, &mod->version, YIN_SUBELEM_UNIQUE,
3792
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
3793
3794
0
    ret = yin_parse_content(ctx, subelems, subelems_size, mod, LY_STMT_MODULE, NULL, &mod->exts);
3795
0
    subelems_deallocator(subelems_size, subelems);
3796
0
    LY_CHECK_RET(ret);
3797
3798
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
3799
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, mod->exts));
3800
3801
    /* submodules share the namespace with the module names, so there must not be
3802
     * a submodule of the same name in the context, no need for revision matching */
3803
0
    dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, mod->mod->name);
3804
0
    if (dup) {
3805
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_NAME2_COL, "module", "submodule", mod->mod->name);
3806
0
        return LY_EVALID;
3807
0
    }
3808
3809
0
    return LY_SUCCESS;
3810
0
}
3811
3812
/**
3813
 * @brief Parse submodule element.
3814
 *
3815
 * @param[in,out] ctx Yin parser context for logging and to store current state.
3816
 * @param[in] mod_attrs Attributes of submodule element.
3817
 * @param[out] submod Parsed submodule structure.
3818
 * @return LY_ERR values.
3819
 */
3820
LY_ERR
3821
yin_parse_submod(struct lysp_yin_ctx *ctx, struct lysp_submodule *submod)
3822
0
{
3823
0
    LY_ERR ret = LY_SUCCESS;
3824
0
    struct yin_subelement *subelems = NULL;
3825
0
    const struct lysp_submodule *dup;
3826
0
    size_t subelems_size;
3827
3828
0
    submod->is_submod = 1;
3829
3830
0
    LY_CHECK_RET(lyxml_ctx_next(ctx->xmlctx));
3831
0
    LY_CHECK_RET(yin_parse_attribute(ctx, YIN_ARG_NAME, &submod->name, Y_IDENTIF_ARG, LY_STMT_SUBMODULE));
3832
0
    LY_CHECK_RET(subelems_allocator(ctx, subelems_size = 27, NULL, &subelems,
3833
0
            LY_STMT_ANYDATA, &submod->data, YIN_SUBELEM_VER2,
3834
0
            LY_STMT_ANYXML, &submod->data, 0,
3835
0
            LY_STMT_AUGMENT, &submod->augments, 0,
3836
0
            LY_STMT_BELONGS_TO, submod, YIN_SUBELEM_MANDATORY | YIN_SUBELEM_UNIQUE,
3837
0
            LY_STMT_CHOICE, &submod->data, 0,
3838
0
            LY_STMT_CONTACT, &submod->contact, YIN_SUBELEM_UNIQUE,
3839
0
            LY_STMT_CONTAINER, &submod->data, 0,
3840
0
            LY_STMT_DESCRIPTION, &submod->dsc, YIN_SUBELEM_UNIQUE,
3841
0
            LY_STMT_DEVIATION, &submod->deviations, 0,
3842
0
            LY_STMT_EXTENSION, &submod->extensions, 0,
3843
0
            LY_STMT_FEATURE, &submod->features, 0,
3844
0
            LY_STMT_GROUPING, &submod->groupings, 0,
3845
0
            LY_STMT_IDENTITY, &submod->identities, 0,
3846
0
            LY_STMT_IMPORT, submod->prefix, &submod->imports, 0,
3847
0
            LY_STMT_INCLUDE, submod->name, &submod->includes, 0,
3848
0
            LY_STMT_LEAF, &submod->data, 0,
3849
0
            LY_STMT_LEAF_LIST, &submod->data, 0,
3850
0
            LY_STMT_LIST, &submod->data, 0,
3851
0
            LY_STMT_NOTIFICATION, &submod->notifs, 0,
3852
0
            LY_STMT_ORGANIZATION, &submod->org, YIN_SUBELEM_UNIQUE,
3853
0
            LY_STMT_REFERENCE, &submod->ref, YIN_SUBELEM_UNIQUE,
3854
0
            LY_STMT_REVISION, &submod->revs, 0,
3855
0
            LY_STMT_RPC, &submod->rpcs, 0,
3856
0
            LY_STMT_TYPEDEF, &submod->typedefs, 0,
3857
0
            LY_STMT_USES, &submod->data, 0,
3858
0
            LY_STMT_YANG_VERSION, &submod->version, YIN_SUBELEM_UNIQUE,
3859
0
            LY_STMT_EXTENSION_INSTANCE, NULL, 0));
3860
3861
0
    ret = yin_parse_content(ctx, subelems, subelems_size, submod, LY_STMT_SUBMODULE, NULL, &submod->exts);
3862
0
    subelems_deallocator(subelems_size, subelems);
3863
0
    LY_CHECK_RET(ret);
3864
3865
    /* store extension instance array (no realloc anymore) to find the plugin records and finish parsing */
3866
0
    LY_CHECK_RET(yin_unres_exts_add(ctx, submod->exts));
3867
3868
    /* submodules share the namespace with the module names, so there must not be
3869
     * a submodule of the same name in the context, no need for revision matching */
3870
0
    dup = ly_ctx_get_submodule_latest(ctx->xmlctx->ctx, submod->name);
3871
0
    if (dup && strcmp(dup->mod->name, submod->mod->name)) {
3872
0
        LOGVAL_PARSER((struct lysp_ctx *)ctx, LY_VCODE_NAME_COL, "submodules", dup->name);
3873
0
        return LY_EVALID;
3874
0
    }
3875
3876
0
    return LY_SUCCESS;
3877
0
}
3878
3879
LY_ERR
3880
yin_parse_submodule(struct lysp_yin_ctx **yin_ctx, struct ly_ctx *ctx, struct lysp_ctx *main_ctx,
3881
        struct ly_in *in, struct lysp_submodule **submod)
3882
0
{
3883
0
    enum ly_stmt kw = LY_STMT_NONE;
3884
0
    LY_ERR ret = LY_SUCCESS;
3885
0
    struct lysp_submodule *mod_p = NULL;
3886
0
    struct lysf_ctx fctx = {.ctx = ctx};
3887
3888
0
    assert(yin_ctx && ctx && main_ctx && in && submod);
3889
3890
    /* create context */
3891
0
    *yin_ctx = calloc(1, sizeof **yin_ctx);
3892
0
    LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(ctx), LY_EMEM);
3893
0
    (*yin_ctx)->format = LYS_IN_YIN;
3894
0
    (*yin_ctx)->main_ctx = main_ctx;
3895
0
    LY_CHECK_RET(lyxml_ctx_new(ctx, in, &(*yin_ctx)->xmlctx));
3896
3897
0
    mod_p = calloc(1, sizeof *mod_p);
3898
0
    LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(ctx); ret = LY_EMEM, cleanup);
3899
0
    mod_p->mod = PARSER_CUR_PMOD(main_ctx)->mod;
3900
0
    mod_p->parsing = 1;
3901
3902
    /* use main context parsed mods adding the current one */
3903
0
    (*yin_ctx)->parsed_mods = main_ctx->parsed_mods;
3904
0
    ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
3905
3906
    /* check submodule */
3907
0
    kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3908
0
            (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
3909
0
    if (kw == LY_STMT_MODULE) {
3910
0
        LOGERR(ctx, LY_EDENIED, "Input data contains module when a submodule is expected.");
3911
0
        ret = LY_EINVAL;
3912
0
        goto cleanup;
3913
0
    } else if (kw != LY_STMT_SUBMODULE) {
3914
0
        LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, lyplg_ext_stmt2str(kw));
3915
0
        ret = LY_EVALID;
3916
0
        goto cleanup;
3917
0
    }
3918
3919
0
    ret = yin_parse_submod(*yin_ctx, mod_p);
3920
0
    LY_CHECK_GOTO(ret, cleanup);
3921
3922
    /* skip possible trailing whitespaces at end of the input */
3923
0
    while (isspace(in->current[0])) {
3924
0
        if (in->current[0] == '\n') {
3925
0
            LY_IN_NEW_LINE(in);
3926
0
        }
3927
0
        ly_in_skip(in, 1);
3928
0
    }
3929
0
    if (in->current[0]) {
3930
0
        LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_TRAILING_SUBMOD, 15, in->current,
3931
0
                strlen(in->current) > 15 ? "..." : "");
3932
0
        ret = LY_EVALID;
3933
0
        goto cleanup;
3934
0
    }
3935
3936
0
    mod_p->parsing = 0;
3937
0
    *submod = mod_p;
3938
3939
0
cleanup:
3940
0
    ly_log_location_revert(0, 0, 0, 1);
3941
0
    if (ret) {
3942
0
        lysp_module_free(&fctx, (struct lysp_module *)mod_p);
3943
0
        lysp_yin_ctx_free(*yin_ctx);
3944
0
        *yin_ctx = NULL;
3945
0
    }
3946
0
    return ret;
3947
0
}
3948
3949
LY_ERR
3950
yin_parse_module(struct lysp_yin_ctx **yin_ctx, struct ly_in *in, struct lys_module *mod)
3951
0
{
3952
0
    LY_ERR ret = LY_SUCCESS;
3953
0
    enum ly_stmt kw = LY_STMT_NONE;
3954
0
    struct lysp_module *mod_p = NULL;
3955
0
    struct lysf_ctx fctx = {.ctx = mod->ctx};
3956
3957
    /* create context */
3958
0
    *yin_ctx = calloc(1, sizeof **yin_ctx);
3959
0
    LY_CHECK_ERR_RET(!(*yin_ctx), LOGMEM(mod->ctx), LY_EMEM);
3960
0
    (*yin_ctx)->format = LYS_IN_YIN;
3961
0
    LY_CHECK_ERR_RET(ly_set_new(&(*yin_ctx)->parsed_mods), free(*yin_ctx); LOGMEM(mod->ctx), LY_EMEM);
3962
0
    LY_CHECK_RET(lyxml_ctx_new(mod->ctx, in, &(*yin_ctx)->xmlctx));
3963
0
    (*yin_ctx)->main_ctx = (struct lysp_ctx *)(*yin_ctx);
3964
3965
0
    mod_p = calloc(1, sizeof *mod_p);
3966
0
    LY_CHECK_ERR_GOTO(!mod_p, LOGMEM(mod->ctx), cleanup);
3967
0
    mod_p->mod = mod;
3968
0
    ly_set_add((*yin_ctx)->parsed_mods, mod_p, 1, NULL);
3969
3970
    /* check module */
3971
0
    kw = yin_match_keyword(*yin_ctx, (*yin_ctx)->xmlctx->name, (*yin_ctx)->xmlctx->name_len, (*yin_ctx)->xmlctx->prefix,
3972
0
            (*yin_ctx)->xmlctx->prefix_len, LY_STMT_NONE);
3973
0
    if (kw == LY_STMT_SUBMODULE) {
3974
0
        LOGERR(mod->ctx, LY_EDENIED, "Input data contains submodule which cannot be parsed directly without its main module.");
3975
0
        ret = LY_EINVAL;
3976
0
        goto cleanup;
3977
0
    } else if (kw != LY_STMT_MODULE) {
3978
0
        LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_MOD_SUBOMD, lyplg_ext_stmt2str(kw));
3979
0
        ret = LY_EVALID;
3980
0
        goto cleanup;
3981
0
    }
3982
3983
    /* parse module substatements */
3984
0
    ret = yin_parse_mod(*yin_ctx, mod_p);
3985
0
    LY_CHECK_GOTO(ret, cleanup);
3986
3987
    /* skip possible trailing whitespaces at end of the input */
3988
0
    while (isspace(in->current[0])) {
3989
0
        if (in->current[0] == '\n') {
3990
0
            LY_IN_NEW_LINE(in);
3991
0
        }
3992
0
        ly_in_skip(in, 1);
3993
0
    }
3994
0
    if (in->current[0]) {
3995
0
        LOGVAL_PARSER((struct lysp_ctx *)*yin_ctx, LY_VCODE_TRAILING_MOD, 15, in->current,
3996
0
                strlen(in->current) > 15 ? "..." : "");
3997
0
        ret = LY_EVALID;
3998
0
        goto cleanup;
3999
0
    }
4000
4001
0
    mod->parsed = mod_p;
4002
4003
0
cleanup:
4004
0
    ly_log_location_revert(0, 0, 0, 1);
4005
0
    if (ret) {
4006
0
        lysp_module_free(&fctx, mod_p);
4007
0
        lysp_yin_ctx_free(*yin_ctx);
4008
0
        *yin_ctx = NULL;
4009
0
    }
4010
0
    return ret;
4011
0
}