Coverage Report

Created: 2025-11-11 06:17

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