1/**
2 * @file yang.y
3 * @author Pavol Vican
4 * @brief YANG parser for libyang (bison grammar)
5 *
6 * Copyright (c) 2015 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
15%define api.pure full
16%locations
17
18%parse-param {void *scanner}
19%parse-param {struct yang_parameter *param}
20
21%lex-param {void *scanner}
22
23%{
24#include <stdio.h>
25#include <stdarg.h>
26#include <string.h>
27#include <stdlib.h>
28#include "libyang.h"
29#include "common.h"
30#include "context.h"
31#include "resolve.h"
32#include "parser_yang.h"
33#include "parser_yang_lex.h"
34#include "parser.h"
35
36#define YANG_ADDELEM(current_ptr, size, array_name)                                      \
37    if ((size) == LY_ARRAY_MAX(size)) {                                                  \
38         LOGERR(trg->ctx, LY_EINT, "Reached limit (%"PRIu64") for storing %s.", LY_ARRAY_MAX(size), array_name); \
39         free(s);                                                                        \
40         YYABORT;                                                                        \
41    } else if (!((size) % LY_YANG_ARRAY_SIZE)) {                                         \
42        void *tmp;                                                                       \
43                                                                                         \
44        tmp = realloc((current_ptr), (sizeof *(current_ptr)) * ((size) + LY_YANG_ARRAY_SIZE)); \
45        if (!tmp) {                                                                      \
46            LOGMEM(trg->ctx);                                                            \
47            free(s);                                                                     \
48            YYABORT;                                                                     \
49        }                                                                                \
50        memset((char *)tmp + (sizeof *(current_ptr)) * (size), 0, (sizeof *(current_ptr)) * LY_YANG_ARRAY_SIZE); \
51        (current_ptr) = tmp;                                                             \
52    }                                                                                    \
53    (size)++;                                                                            \
54    actual = &(current_ptr)[(size)-1];                                                   \
55
56void yyerror(YYLTYPE *yylloc, void *scanner, struct yang_parameter *param, ...);
57/* pointer on the current parsed element 'actual' */
58%}
59
60%union {
61  int64_t i;
62  uint32_t uint;
63  char *str;
64  char **p_str;
65  void *v;
66  char ch;
67  struct yang_type *type;
68  struct lys_deviation *dev;
69  struct lys_deviate *deviate;
70  union {
71    uint32_t index;
72    struct lys_node_container *container;
73    struct lys_node_anydata *anydata;
74    struct type_node node;
75    struct lys_node_case *cs;
76    struct lys_node_grp *grouping;
77    struct lys_refine *refine;
78    struct lys_node_notif *notif;
79    struct lys_node_uses *uses;
80    struct lys_node_inout *inout;
81    struct lys_node_augment *augment;
82  } nodes;
83  enum yytokentype token;
84  struct {
85    void *actual;
86    enum yytokentype token;
87  } backup_token;
88  struct {
89    struct lys_revision **revision;
90    int index;
91  } revisions;
92}
93
94%token UNION_KEYWORD
95%token ANYXML_KEYWORD
96%token WHITESPACE
97%token ERROR
98%token EOL
99%token STRING
100%token STRINGS
101%token IDENTIFIER
102%token IDENTIFIERPREFIX
103%token REVISION_DATE
104%token TAB
105%token DOUBLEDOT
106%token URI
107%token INTEGER
108%token NON_NEGATIVE_INTEGER
109%token ZERO
110%token DECIMAL
111%token ARGUMENT_KEYWORD
112%token AUGMENT_KEYWORD
113%token BASE_KEYWORD
114%token BELONGS_TO_KEYWORD
115%token BIT_KEYWORD
116%token CASE_KEYWORD
117%token CHOICE_KEYWORD
118%token CONFIG_KEYWORD
119%token CONTACT_KEYWORD
120%token CONTAINER_KEYWORD
121%token DEFAULT_KEYWORD
122%token DESCRIPTION_KEYWORD
123%token ENUM_KEYWORD
124%token ERROR_APP_TAG_KEYWORD
125%token ERROR_MESSAGE_KEYWORD
126%token EXTENSION_KEYWORD
127%token DEVIATION_KEYWORD
128%token DEVIATE_KEYWORD
129%token FEATURE_KEYWORD
130%token FRACTION_DIGITS_KEYWORD
131%token GROUPING_KEYWORD
132%token IDENTITY_KEYWORD
133%token IF_FEATURE_KEYWORD
134%token IMPORT_KEYWORD
135%token INCLUDE_KEYWORD
136%token INPUT_KEYWORD
137%token KEY_KEYWORD
138%token LEAF_KEYWORD
139%token LEAF_LIST_KEYWORD
140%token LENGTH_KEYWORD
141%token LIST_KEYWORD
142%token MANDATORY_KEYWORD
143%token MAX_ELEMENTS_KEYWORD
144%token MIN_ELEMENTS_KEYWORD
145%token MODULE_KEYWORD
146%token MUST_KEYWORD
147%token NAMESPACE_KEYWORD
148%token NOTIFICATION_KEYWORD
149%token ORDERED_BY_KEYWORD
150%token ORGANIZATION_KEYWORD
151%token OUTPUT_KEYWORD
152%token PATH_KEYWORD
153%token PATTERN_KEYWORD
154%token POSITION_KEYWORD
155%token PREFIX_KEYWORD
156%token PRESENCE_KEYWORD
157%token RANGE_KEYWORD
158%token REFERENCE_KEYWORD
159%token REFINE_KEYWORD
160%token REQUIRE_INSTANCE_KEYWORD
161%token REVISION_KEYWORD
162%token REVISION_DATE_KEYWORD
163%token RPC_KEYWORD
164%token STATUS_KEYWORD
165%token SUBMODULE_KEYWORD
166%token TYPE_KEYWORD
167%token TYPEDEF_KEYWORD
168%token UNIQUE_KEYWORD
169%token UNITS_KEYWORD
170%token USES_KEYWORD
171%token VALUE_KEYWORD
172%token WHEN_KEYWORD
173%token YANG_VERSION_KEYWORD
174%token YIN_ELEMENT_KEYWORD
175%token ADD_KEYWORD
176%token CURRENT_KEYWORD
177%token DELETE_KEYWORD
178%token DEPRECATED_KEYWORD
179%token FALSE_KEYWORD
180%token NOT_SUPPORTED_KEYWORD
181%token OBSOLETE_KEYWORD
182%token REPLACE_KEYWORD
183%token SYSTEM_KEYWORD
184%token TRUE_KEYWORD
185%token UNBOUNDED_KEYWORD
186%token USER_KEYWORD
187%token ACTION_KEYWORD
188%token MODIFIER_KEYWORD
189%token ANYDATA_KEYWORD
190%token NODE
191%token NODE_PRINT
192%token EXTENSION_INSTANCE
193%token SUBMODULE_EXT_KEYWORD
194
195%type <uint> positive_integer_value
196%type <uint> non_negative_integer_value
197%type <uint> max_value_arg_str
198%type <uint> max_value_arg
199%type <uint> max_elements_stmt
200%type <uint> min_value_arg_str
201%type <uint> min_value_arg
202%type <uint> min_elements_stmt
203%type <uint> fraction_digits_arg_str
204%type <uint> fraction_digits_arg
205%type <uint> position_value_arg_str
206%type <uint> position_value_arg
207%type <uint> yin_element_arg_str
208%type <uint> yin_element_arg
209%type <uint> fraction_digits_stmt
210%type <uint> position_stmt
211%type <i> value_stmt
212%type <i> require_instance_stmt
213%type <i> require_instance_arg_str
214%type <i> require_instance_arg
215%type <i> import_opt_stmt
216%type <i> include_opt_stmt
217%type <i> module_header_stmt
218%type <i> submodule_header_stmt
219%type <str> message_opt_stmt
220%type <i> status_stmt
221%type <i> status_arg_str
222%type <i> status_arg
223%type <i> config_stmt
224%type <i> config_arg_str
225%type <i> config_arg
226%type <i> mandatory_stmt
227%type <i> mandatory_arg_str
228%type <i> mandatory_arg
229%type <i> ordered_by_stmt
230%type <i> ordered_by_arg_str
231%type <i> ordered_by_arg
232%type <i> integer_value_arg_str
233%type <i> value_arg
234%type <i> integer_value
235%type <i> ext_substatements
236%type <str> pattern_arg_str
237%type <nodes> container_opt_stmt
238%type <nodes> anyxml_opt_stmt
239%type <nodes> choice_opt_stmt
240%type <nodes> case_opt_stmt
241%type <nodes> grouping_opt_stmt
242%type <nodes> leaf_opt_stmt
243%type <nodes> leaf_list_opt_stmt
244%type <nodes> list_opt_stmt
245%type <nodes> type_opt_stmt
246%type <nodes> uses_opt_stmt
247%type <nodes> refine_body_opt_stmts
248%type <nodes> augment_opt_stmt
249%type <nodes> rpc_opt_stmt
250%type <nodes> notification_opt_stmt
251%type <dev> deviation_opt_stmt
252%type <deviate> deviate_add_opt_stmt
253%type <deviate> deviate_delete_opt_stmt
254%type <deviate> deviate_replace_opt_stmt
255%type <ch> pattern_opt_stmt
256%type <ch> pattern_end
257%type <ch> modifier_stmt
258%type <p_str> tmp_string
259%type <str> string_opt_part1
260%type <str> semicolom
261%type <str> curly_bracket_open
262%type <str> unknown_statement2_yang_stmt
263%type <str> unknown_statement2_module_stmt
264%type <v> type_ext_alloc
265%type <v> typedef_ext_alloc
266%type <v> iffeature_ext_alloc
267%type <v> restriction_ext_alloc
268%type <v> when_ext_alloc
269%type <revisions> revision_ext_alloc
270%type <token> import_arg_str
271%type <token> include_arg_str
272%type <token> argument_str
273%type <token> belongs_to_arg_str
274%type <backup_token> revision_arg_stmt
275%type <backup_token> grouping_arg_str
276%type <backup_token> container_arg_str
277%type <backup_token> leaf_arg_str
278%type <backup_token> leaf_list_arg_str
279%type <backup_token> list_arg_str
280%type <backup_token> choice_arg_str
281%type <backup_token> case_arg_str
282%type <backup_token> anyxml_arg_str
283%type <backup_token> anydata_arg_str
284%type <backup_token> uses_arg_str
285%type <backup_token> uses_augment_arg
286%type <backup_token> augment_arg
287%type <backup_token> action_arg_str
288%type <backup_token> rpc_arg_str
289%type <backup_token> input_arg
290%type <backup_token> output_arg
291%type <backup_token> notification_arg_str
292%type <backup_token> extension_arg_str
293%type <backup_token> feature_arg_str
294%type <backup_token> identity_arg_str
295%type <backup_token> if_feature_arg
296%type <backup_token> typedef_arg_str
297%type <backup_token> type_arg_str
298%type <backup_token> length_arg_str
299%type <backup_token> pattern_sep
300%type <backup_token> range_arg_str
301%type <backup_token> union_spec
302%type <backup_token> enum_arg_str
303%type <backup_token> bit_arg_str
304%type <backup_token> when_arg_str
305%type <backup_token> must_agr_str
306%type <backup_token> refine_arg_str
307%type <backup_token> deviation_arg
308%type <backup_token> deviate_not_supported
309%type <backup_token> deviate_add
310%type <backup_token> deviate_delete
311%type <backup_token> deviate_replace
312%type <backup_token> string_opt
313
314%destructor { free($$); } pattern_arg_str string_opt_part1 semicolom curly_bracket_open
315%destructor { free(($$) ? *$$ : NULL); } tmp_string
316%destructor { yang_type_free(param->module->ctx, $$); } type_ext_alloc
317%destructor { yang_type_free(param->module->ctx, &((struct lys_tpdf *)$$)->type); } typedef_ext_alloc
318
319%initial-action { yylloc.last_column = 0;
320                  if (param->flags & EXT_INSTANCE_SUBSTMT) {
321                    is_ext_instance = 1;
322                    ext_instance = (struct lys_ext_instance_complex *)param->actual_node;
323                    ext_name = (char *)param->data_node;
324                  } else {
325                    is_ext_instance = 0;
326                  }
327                  yylloc.last_line = is_ext_instance;     /* HACK for flex - return SUBMODULE_KEYWORD or SUBMODULE_EXT_KEYWORD */
328                  param->value = &s;
329                  param->data_node = (void **)&data_node;
330                  param->actual_node = &actual;
331                  backup_type = NODE;
332                  trg = (param->submodule) ? (struct lys_module *)param->submodule : param->module;
333                }
334
335%%
336
337/* to simplify code, store the module/submodule being processed as trg */
338
339start: module_stmt
340 |  submodule_stmt
341 |  ext_substatements
342
343tmp_string: STRING { if (yyget_text(scanner)[0] == '"') {
344                      char *tmp;
345
346                      s = malloc(yyget_leng(scanner) - 1 + 7 * yylval.i);
347                      if (!s) {
348                        LOGMEM(trg->ctx);
349                        YYABORT;
350                      }
351                      if (!(tmp = yang_read_string(trg->ctx, yyget_text(scanner) + 1, s, yyget_leng(scanner) - 2, 0, yylloc.first_column))) {
352                        YYABORT;
353                      }
354                      s = tmp;
355                    } else {
356                      s = calloc(1, yyget_leng(scanner) - 1);
357                      if (!s) {
358                        LOGMEM(trg->ctx);
359                        YYABORT;
360                      }
361                      memcpy(s, yyget_text(scanner) + 1, yyget_leng(scanner) - 2);
362                    }
363                    $$ = &s;
364                  }
365
366string_1: tmp_string optsep string_2
367
368
369string_2: @EMPTYDIR@
370  |  string_2 '+' optsep
371     STRING { if (yyget_leng(scanner) > 2) {
372                int length_s = strlen(s), length_tmp = yyget_leng(scanner);
373                char *tmp;
374
375                tmp = realloc(s, length_s + length_tmp - 1);
376                if (!tmp) {
377                  LOGMEM(trg->ctx);
378                  YYABORT;
379                }
380                s = tmp;
381                if (yyget_text(scanner)[0] == '"') {
382                  if (!(tmp = yang_read_string(trg->ctx, yyget_text(scanner) + 1, s, length_tmp - 2, length_s, yylloc.first_column))) {
383                    YYABORT;
384                  }
385                  s = tmp;
386                } else {
387                  memcpy(s + length_s, yyget_text(scanner) + 1, length_tmp - 2);
388                  s[length_s + length_tmp - 2] = '\0';
389                }
390              }
391            }
392     optsep;
393
394module_arg_str: identifier_arg_str { if (param->submodule) {
395                                       free(s);
396                                       LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "module");
397                                       YYABORT;
398                                     }
399                                     trg = param->module;
400                                     if (yang_read_common(trg,s,MODULE_KEYWORD)) {
401                                       YYABORT;
402                                     }
403                                     s = NULL;
404                                     actual_type = MODULE_KEYWORD;
405                                   }
406
407module_stmt: optsep MODULE_KEYWORD sep module_arg_str
408             '{' stmtsep
409                 module_header_stmts
410                 linkage_stmts
411                 meta_stmts
412                 revision_stmts
413                 body_stmts_end
414             '}' optsep
415
416
417module_header_stmts: module_header_stmt { if (!param->module->ns) {
418                                            LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module");
419                                            YYABORT;
420                                          }
421                                          if (!param->module->prefix) {
422                                            LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module");
423                                            YYABORT;
424                                          }
425                                        }
426
427module_header_stmt: @EMPTYDIR@  { $$ = 0; }
428  |  module_header_stmt yang_version_stmt { if (yang_check_version(param->module, param->submodule, s, $1)) {
429                                              YYABORT;
430                                            }
431                                            $$ = 1;
432                                            s = NULL;
433                                          }
434  |  module_header_stmt namespace_stmt { if (yang_read_common(param->module, s, NAMESPACE_KEYWORD)) {
435                                           YYABORT;
436                                         }
437                                         s = NULL;
438                                       }
439  |  module_header_stmt prefix_stmt { if (yang_read_prefix(trg, NULL, s)) {
440                                        YYABORT;
441                                      }
442                                      s = NULL;
443                                    }
444
445submodule_arg_str: identifier_arg_str { if (!param->submodule) {
446                                          free(s);
447                                          LOGVAL(trg->ctx, LYE_SUBMODULE, LY_VLOG_NONE, NULL);
448                                          YYABORT;
449                                        }
450                                        trg = (struct lys_module *)param->submodule;
451                                        if (yang_read_common(trg,s,MODULE_KEYWORD)) {
452                                          YYABORT;
453                                        }
454                                        s = NULL;
455                                        actual_type = SUBMODULE_KEYWORD;
456                                      }
457
458submodule_stmt: optsep SUBMODULE_KEYWORD sep submodule_arg_str
459                '{' stmtsep
460                    submodule_header_stmts
461                    linkage_stmts
462                    meta_stmts
463                    revision_stmts
464                    body_stmts_end
465                '}' optsep
466
467
468submodule_header_stmts: submodule_header_stmt { if (!param->submodule->prefix) {
469                                                  LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
470                                                  YYABORT;
471                                                }
472                                                if (!$1) {
473                                                  /* check version compatibility with the main module */
474                                                  if (param->module->version > 1) {
475                                                      LOGVAL(trg->ctx, LYE_INVER, LY_VLOG_NONE, NULL);
476                                                      YYABORT;
477                                                  }
478                                                }
479                                              }
480
481submodule_header_stmt: @EMPTYDIR@ { $$ = 0; }
482  |  submodule_header_stmt yang_version_stmt { if (yang_check_version(param->module, param->submodule, s, $1)) {
483                                                 YYABORT;
484                                               }
485                                               $$ = 1;
486                                               s = NULL;
487                                             }
488  |  submodule_header_stmt belongs_to_stmt stmtsep
489
490yang_version_arg: string { backup_type = actual_type;
491                           actual_type = YANG_VERSION_KEYWORD;
492                         }
493
494yang_version_stmt: YANG_VERSION_KEYWORD sep yang_version_arg stmtend
495
496namespace_arg_str: string { backup_type = actual_type;
497                            actual_type = NAMESPACE_KEYWORD;
498                          }
499
500namespace_stmt: NAMESPACE_KEYWORD sep namespace_arg_str stmtend
501
502linkage_stmts: @EMPTYDIR@
503 |  linkage_stmts import_stmt stmtsep
504 |  linkage_stmts include_stmt stmtsep
505
506import_stmt: IMPORT_KEYWORD sep import_arg_str
507             '{' stmtsep
508                 import_opt_stmt
509             '}' { actual_type = $3;
510                   backup_type = NODE;
511                   actual = NULL;
512                 }
513
514import_arg_str: identifier_arg_str { YANG_ADDELEM(trg->imp, trg->imp_size, "imports");
515                                     /* HACK for unres */
516                                     ((struct lys_import *)actual)->module = (struct lys_module *)s;
517                                     s = NULL;
518                                     $$ = actual_type;
519                                     actual_type = IMPORT_KEYWORD;
520                                   }
521
522import_opt_stmt: @EMPTYDIR@ { $$ = 0; }
523  |  import_opt_stmt prefix_stmt { if (yang_read_prefix(trg, actual, s)) {
524                                     YYABORT;
525                                   }
526                                   s = NULL;
527                                 }
528  |  import_opt_stmt description_stmt { if (trg->version != 2) {
529                                          LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "description");
530                                          free(s);
531                                          YYABORT;
532                                        }
533                                        if (yang_read_description(trg, actual, s, "import", IMPORT_KEYWORD)) {
534                                          YYABORT;
535                                        }
536                                        s = NULL;
537                                        $$ = $1;
538                                      }
539  |  import_opt_stmt reference_stmt { if (trg->version != 2) {
540                                        LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "reference");
541                                        free(s);
542                                        YYABORT;
543                                      }
544                                      if (yang_read_reference(trg, actual, s, "import", IMPORT_KEYWORD)) {
545                                        YYABORT;
546                                      }
547                                      s = NULL;
548                                      $$ = $1;
549                                    }
550  |  import_opt_stmt revision_date_stmt { if ($1) {
551                                            LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", "import");
552                                            free(s);
553                                            YYABORT;
554                                          }
555                                          memcpy(((struct lys_import *)actual)->rev, s, LY_REV_SIZE-1);
556                                          free(s);
557                                          s = NULL;
558                                          $$ = 1;
559                                        }
560
561include_arg_str: identifier_arg_str { YANG_ADDELEM(trg->inc, trg->inc_size, "includes");
562                                     /* HACK for unres */
563                                     ((struct lys_include *)actual)->submodule = (struct lys_submodule *)s;
564                                     s = NULL;
565                                     $$ = actual_type;
566                                     actual_type = INCLUDE_KEYWORD;
567                                   }
568
569include_stmt: INCLUDE_KEYWORD sep include_arg_str include_end { actual_type = $3;
570                                                                backup_type = NODE;
571                                                                actual = NULL;
572                                                              }
573
574include_end: ';'
575  | '{' stmtsep
576        include_opt_stmt
577    '}'
578
579include_opt_stmt: @EMPTYDIR@ { $$ = 0; }
580  |  include_opt_stmt description_stmt { if (trg->version != 2) {
581                                           LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "description");
582                                           free(s);
583                                           YYABORT;
584                                         }
585                                         if (yang_read_description(trg, actual, s, "include", INCLUDE_KEYWORD)) {
586                                            YYABORT;
587                                         }
588                                         s = NULL;
589                                         $$ = $1;
590                                       }
591  |  include_opt_stmt reference_stmt { if (trg->version != 2) {
592                                         LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "reference");
593                                         free(s);
594                                         YYABORT;
595                                       }
596                                       if (yang_read_reference(trg, actual, s, "include", INCLUDE_KEYWORD)) {
597                                         YYABORT;
598                                       }
599                                       s = NULL;
600                                       $$ = $1;
601                                     }
602  |  include_opt_stmt revision_date_stmt { if ($1) {
603                                             LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "revision-date", "include");
604                                             free(s);
605                                             YYABORT;
606                                           }
607                                           memcpy(((struct lys_include *)actual)->rev, s, LY_REV_SIZE-1);
608                                           free(s);
609                                           s = NULL;
610                                           $$ = 1;
611                                         }
612
613revision_date_arg: date_arg_str { backup_type = actual_type;
614                                  actual_type = REVISION_DATE_KEYWORD;
615                                }
616
617revision_date_stmt: REVISION_DATE_KEYWORD sep revision_date_arg stmtend
618
619belongs_to_arg_str: identifier_arg_str { $$ = actual_type;
620                                         if (is_ext_instance) {
621                                           if (yang_read_extcomplex_str(trg, ext_instance, "belongs-to", ext_name, &s,
622                                                                        0, LY_STMT_BELONGSTO)) {
623                                             YYABORT;
624                                           }
625                                         } else {
626                                           if (param->submodule->prefix) {
627                                             LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "belongs-to", "submodule");
628                                             free(s);
629                                             YYABORT;
630                                           }
631                                           if (!ly_strequal(s, param->submodule->belongsto->name, 0)) {
632                                             LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "belongs-to");
633                                             free(s);
634                                             YYABORT;
635                                           }
636                                           free(s);
637                                         }
638                                         s = NULL;
639                                         actual_type = BELONGS_TO_KEYWORD;
640                                       }
641
642belongs_to_stmt: BELONGS_TO_KEYWORD sep belongs_to_arg_str
643                 '{' stmtsep
644                     prefix_stmt
645                 '}' { if (is_ext_instance) {
646                         if (yang_read_extcomplex_str(trg, ext_instance, "prefix", "belongs-to", &s,
647                                                      LY_STMT_BELONGSTO, LY_STMT_PREFIX)) {
648                           YYABORT;
649                         }
650                       } else {
651                         if (yang_read_prefix(trg, NULL, s)) {
652                           YYABORT;
653                         }
654                       }
655                       s = NULL;
656                       actual_type = $3;
657                     }
658
659prefix_arg: prefix_arg_str { backup_type = actual_type;
660                             actual_type = PREFIX_KEYWORD;
661                           }
662
663prefix_stmt: PREFIX_KEYWORD sep prefix_arg stmtend
664
665meta_stmts: @EMPTYDIR@
666  |  meta_stmts organization_stmt { if (yang_read_common(trg, s, ORGANIZATION_KEYWORD)) {
667                                      YYABORT;
668                                    }
669                                    s = NULL;
670                                  }
671  |  meta_stmts contact_stmt { if (yang_read_common(trg, s, CONTACT_KEYWORD)) {
672                                 YYABORT;
673                               }
674                               s = NULL;
675                             }
676  |  meta_stmts description_stmt { if (yang_read_description(trg, NULL, s, NULL, MODULE_KEYWORD)) {
677                                     YYABORT;
678                                   }
679                                   s = NULL;
680                                 }
681  |  meta_stmts reference_stmt { if (yang_read_reference(trg, NULL, s, NULL, MODULE_KEYWORD)) {
682                                   YYABORT;
683                                 }
684                                 s=NULL;
685                               }
686
687organization_arg: string { backup_type = actual_type;
688                           actual_type = ORGANIZATION_KEYWORD;
689                         }
690
691organization_stmt: ORGANIZATION_KEYWORD sep organization_arg stmtend
692
693contact_arg: string { backup_type = actual_type;
694                      actual_type = CONTACT_KEYWORD;
695                    }
696
697contact_stmt: CONTACT_KEYWORD sep contact_arg stmtend
698
699description_arg: string { backup_type = actual_type;
700                          actual_type = DESCRIPTION_KEYWORD;
701                        }
702
703description_stmt: DESCRIPTION_KEYWORD sep description_arg stmtend
704
705reference_arg: string { backup_type = actual_type;
706                        actual_type = REFERENCE_KEYWORD;
707                      }
708
709reference_stmt: REFERENCE_KEYWORD sep reference_arg stmtend
710
711revision_stmts: revision_stmts_opt { if (trg->rev_size) {
712                                      struct lys_revision *tmp;
713
714                                      tmp = realloc(trg->rev, trg->rev_size * sizeof *trg->rev);
715                                      if (!tmp) {
716                                        LOGMEM(trg->ctx);
717                                        YYABORT;
718                                      }
719                                      trg->rev = tmp;
720                                    }
721                                  }
722
723
724revision_arg_stmt: date_arg_str { $$.token = actual_type;
725                                  $$.actual = actual;
726                                  if (!is_ext_instance) {
727                                    YANG_ADDELEM(trg->rev, trg->rev_size, "revisions");
728                                  }
729                                  memcpy(((struct lys_revision *)actual)->date, s, LY_REV_SIZE);
730                                  free(s);
731                                  s = NULL;
732                                  actual_type = REVISION_KEYWORD;
733                                }
734
735revision_stmts_opt: @EMPTYDIR@
736  |  revision_stmts_opt revision_stmt stmtsep { int i;
737
738                                                /* check uniqueness of the revision date - not required by RFC */
739                                                for (i = 0; i < (trg->rev_size - 1); i++) {
740                                                  if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
741                                                    LOGWRN(trg->ctx, "Module's revisions are not unique (%s).",
742                                                           trg->rev[trg->rev_size - 1].date);
743                                                    break;
744                                                  }
745                                                }
746                                              }
747
748revision_stmt: REVISION_KEYWORD sep revision_arg_stmt revision_end { actual_type = $3.token;
749                                                                     actual = $3.actual;
750                                                                   }
751
752revision_end: ';'
753  | '{' stmtsep
754        revision_opt_stmt
755    '}'
756
757revision_opt_stmt: @EMPTYDIR@
758  |  revision_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "revision",REVISION_KEYWORD)) {
759                                            YYABORT;
760                                          }
761                                          s = NULL;
762                                        }
763  |  revision_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "revision", REVISION_KEYWORD)) {
764                                          YYABORT;
765                                        }
766                                        s = NULL;
767                                      }
768  ;
769
770date_arg_str: REVISION_DATE { s = strdup(yyget_text(scanner));
771                              if (!s) {
772                                LOGMEM(trg->ctx);
773                                YYABORT;
774                              }
775                              if (lyp_check_date(trg->ctx, s)) {
776                                  free(s);
777                                  YYABORT;
778                              }
779                            }
780              optsep
781  | string_1 { if (lyp_check_date(trg->ctx, s)) {
782                   free(s);
783                   YYABORT;
784               }
785             }
786
787body_stmts_end: body_stmts { void *tmp;
788
789                             if (trg->tpdf_size) {
790                               tmp = realloc(trg->tpdf, trg->tpdf_size * sizeof *trg->tpdf);
791                               if (!tmp) {
792                                 LOGMEM(trg->ctx);
793                                 YYABORT;
794                               }
795                               trg->tpdf = tmp;
796                             }
797
798                             if (trg->features_size) {
799                               tmp = realloc(trg->features, trg->features_size * sizeof *trg->features);
800                               if (!tmp) {
801                                 LOGMEM(trg->ctx);
802                                 YYABORT;
803                               }
804                               trg->features = tmp;
805                             }
806
807                             if (trg->ident_size) {
808                               tmp = realloc(trg->ident, trg->ident_size * sizeof *trg->ident);
809                               if (!tmp) {
810                                 LOGMEM(trg->ctx);
811                                 YYABORT;
812                               }
813                               trg->ident = tmp;
814                             }
815
816                             if (trg->augment_size) {
817                               tmp = realloc(trg->augment, trg->augment_size * sizeof *trg->augment);
818                               if (!tmp) {
819                                 LOGMEM(trg->ctx);
820                                 YYABORT;
821                               }
822                               trg->augment = tmp;
823                             }
824
825                             if (trg->extensions_size) {
826                               tmp = realloc(trg->extensions, trg->extensions_size * sizeof *trg->extensions);
827                               if (!tmp) {
828                                 LOGMEM(trg->ctx);
829                                 YYABORT;
830                               }
831                               trg->extensions = tmp;
832                             }
833                           }
834
835body_stmts: @EMPTYDIR@ { /* check the module with respect to the context now */
836                         if (!param->submodule) {
837                           switch (lyp_ctx_check_module(trg)) {
838                           case -1:
839                             YYABORT;
840                           case 0:
841                             break;
842                           case 1:
843                             /* it's already there */
844                             param->flags |= YANG_EXIST_MODULE;
845                             YYABORT;
846                           }
847                         }
848                         param->flags &= (~YANG_REMOVE_IMPORT);
849                         if (yang_check_imports(trg, param->unres)) {
850                           YYABORT;
851                         }
852                         actual = NULL;
853                       }
854  | body_stmts body_stmt stmtsep { actual = NULL; }
855
856
857body_stmt: extension_stmt
858  | feature_stmt
859  | identity_stmt
860  | typedef_stmt
861  | grouping_stmt
862  | data_def_stmt
863  | augment_stmt
864  | rpc_stmt
865  | notification_stmt
866  | deviation_stmt
867
868
869extension_arg_str: identifier_arg_str { $$.token = actual_type;
870                                        $$.actual = actual;
871                                        YANG_ADDELEM(trg->extensions, trg->extensions_size, "extensions");
872                                        trg->extensions_size--;
873                                        ((struct lys_ext *)actual)->name = lydict_insert_zc(param->module->ctx, s);
874                                        ((struct lys_ext *)actual)->module = trg;
875                                        if (lyp_check_identifier(trg->ctx, ((struct lys_ext *)actual)->name, LY_IDENT_EXTENSION, trg, NULL)) {
876                                          trg->extensions_size++;
877                                          YYABORT;
878                                        }
879                                        trg->extensions_size++;
880                                        s = NULL;
881                                        actual_type = EXTENSION_KEYWORD;
882                                      }
883
884extension_stmt: EXTENSION_KEYWORD sep extension_arg_str extension_end
885                { struct lys_ext *ext = actual;
886                  ext->plugin = ext_get_plugin(ext->name, ext->module->name, ext->module->rev ? ext->module->rev[0].date : NULL);
887                  actual_type = $3.token;
888                  actual = $3.actual;
889                }
890
891extension_end: ';'
892  | '{' stmtsep
893        extension_opt_stmt
894    '}'
895
896extension_opt_stmt: @EMPTYDIR@
897  |  extension_opt_stmt argument_stmt stmtsep
898  |  extension_opt_stmt status_stmt { if (((struct lys_ext *)actual)->flags & LYS_STATUS_MASK) {
899                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "extension");
900                                        YYABORT;
901                                      }
902                                      ((struct lys_ext *)actual)->flags |= $2;
903                                    }
904  |  extension_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "extension", NODE)) {
905                                             YYABORT;
906                                           }
907                                           s = NULL;
908                                         }
909  |  extension_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "extension", NODE)) {
910                                           YYABORT;
911                                         }
912                                         s = NULL;
913                                       }
914
915argument_str: identifier_arg_str { $$ = actual_type;
916                                   if (is_ext_instance) {
917                                     if (yang_read_extcomplex_str(trg, ext_instance, "argument", ext_name, &s,
918                                                                  0, LY_STMT_ARGUMENT)) {
919                                       YYABORT;
920                                     }
921                                   } else {
922                                     if (((struct lys_ext *)actual)->argument) {
923                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "argument", "extension");
924                                        free(s);
925                                        YYABORT;
926                                     }
927                                     ((struct lys_ext *)actual)->argument = lydict_insert_zc(param->module->ctx, s);
928                                   }
929                                   s = NULL;
930                                   actual_type = ARGUMENT_KEYWORD;
931                                 }
932
933argument_stmt: ARGUMENT_KEYWORD sep  argument_str argument_end { actual_type = $3; }
934
935argument_end: ';'
936  | '{' stmtsep
937        yin_element_stmt
938    '}'
939
940yin_element_arg: yin_element_arg_str { $$ = $1;
941                                       backup_type = actual_type;
942                                       actual_type = YIN_ELEMENT_KEYWORD;
943                                     }
944
945yin_element_stmt: @EMPTYDIR@
946  |  YIN_ELEMENT_KEYWORD sep yin_element_arg stmtend
947     { if (is_ext_instance) {
948         int c;
949         const char ***p;
950         uint8_t *val;
951         struct lyext_substmt *info;
952
953         c = 0;
954         p = lys_ext_complex_get_substmt(LY_STMT_ARGUMENT, ext_instance, &info);
955         if (info->cardinality >= LY_STMT_CARD_SOME) {
956           /* get the index in the array to add new item */
957           for (c = 0; p[0][c + 1]; c++);
958           val = (uint8_t *)p[1];
959         } else {
960           val = (uint8_t *)(p + 1);
961         }
962         val[c] = ($3 == LYS_YINELEM) ? 1 : 2;
963       } else {
964         ((struct lys_ext *)actual)->flags |= $3;
965       }
966     }
967
968yin_element_arg_str: TRUE_KEYWORD optsep { $$ = LYS_YINELEM; }
969  | FALSE_KEYWORD optsep { $$ = 0; }
970  | string_1 { if (!strcmp(s, "true")) {
971                 $$ = LYS_YINELEM;
972               } else if (!strcmp(s, "false")) {
973                 $$ = 0;
974               } else {
975                 LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, s);
976                 free(s);
977                 YYABORT;
978               }
979               free(s);
980               s = NULL;
981             }
982
983status_arg: status_arg_str { $$ = $1;
984                             backup_type = actual_type;
985                             actual_type = STATUS_KEYWORD;
986                           }
987
988status_stmt:  STATUS_KEYWORD sep status_arg stmtend { $$ = $3; }
989
990status_arg_str: CURRENT_KEYWORD optsep { $$ = LYS_STATUS_CURR; }
991  | OBSOLETE_KEYWORD optsep { $$ = LYS_STATUS_OBSLT; }
992  | DEPRECATED_KEYWORD optsep { $$ = LYS_STATUS_DEPRC; }
993  | string_1 { if (!strcmp(s, "current")) {
994                 $$ = LYS_STATUS_CURR;
995               } else if (!strcmp(s, "obsolete")) {
996                 $$ = LYS_STATUS_OBSLT;
997               } else if (!strcmp(s, "deprecated")) {
998                 $$ = LYS_STATUS_DEPRC;
999               } else {
1000                 LOGVAL(trg->ctx,LYE_INSTMT, LY_VLOG_NONE, NULL, s);
1001                 free(s);
1002                 YYABORT;
1003               }
1004               free(s);
1005               s = NULL;
1006             }
1007
1008feature_arg_str: identifier_arg_str { /* check uniqueness of feature's names */
1009                                      if (lyp_check_identifier(trg->ctx, s, LY_IDENT_FEATURE, trg, NULL)) {
1010                                        free(s);
1011                                        YYABORT;
1012                                      }
1013                                      $$.token = actual_type;
1014                                      $$.actual = actual;
1015                                      YANG_ADDELEM(trg->features, trg->features_size, "features");
1016                                      ((struct lys_feature *)actual)->name = lydict_insert_zc(trg->ctx, s);
1017                                      ((struct lys_feature *)actual)->module = trg;
1018                                      s = NULL;
1019                                      actual_type = FEATURE_KEYWORD;
1020                                    }
1021
1022feature_stmt: FEATURE_KEYWORD sep feature_arg_str feature_end
1023              { actual = $3.actual;
1024                actual_type = $3.token;
1025              }
1026
1027feature_end: ';'
1028  | '{' stmtsep
1029        feature_opt_stmt
1030    '}' { struct lys_iffeature *tmp;
1031
1032          if (((struct lys_feature *)actual)->iffeature_size) {
1033            tmp = realloc(((struct lys_feature *)actual)->iffeature,
1034                          ((struct lys_feature *)actual)->iffeature_size * sizeof *tmp);
1035            if (!tmp) {
1036              LOGMEM(trg->ctx);
1037              YYABORT;
1038            }
1039            ((struct lys_feature *)actual)->iffeature = tmp;
1040          }
1041        }
1042
1043feature_opt_stmt: @EMPTYDIR@
1044  |  feature_opt_stmt if_feature_stmt stmtsep
1045  |  feature_opt_stmt status_stmt { if (((struct lys_feature *)actual)->flags & LYS_STATUS_MASK) {
1046                                      LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "feature");
1047                                      YYABORT;
1048                                    }
1049                                    ((struct lys_feature *)actual)->flags |= $2;
1050                                  }
1051  |  feature_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "feature", NODE)) {
1052                                           YYABORT;
1053                                         }
1054                                         s = NULL;
1055                                       }
1056  |  feature_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "feature", NODE)) {
1057                                         YYABORT;
1058                                       }
1059                                       s = NULL;
1060                                     }
1061
1062if_feature_arg: string { $$.token = actual_type;
1063                         $$.actual = actual;
1064                         switch (actual_type) {
1065                         case FEATURE_KEYWORD:
1066                           YANG_ADDELEM(((struct lys_feature *)actual)->iffeature,
1067                                        ((struct lys_feature *)actual)->iffeature_size, "if-features");
1068                           break;
1069                         case IDENTITY_KEYWORD:
1070                           if (trg->version < 2) {
1071                             LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "if-feature", "identity");
1072                             free(s);
1073                             YYABORT;
1074                           }
1075                           YANG_ADDELEM(((struct lys_ident *)actual)->iffeature,
1076                                        ((struct lys_ident *)actual)->iffeature_size, "if-features");
1077                           break;
1078                         case ENUM_KEYWORD:
1079                           if (trg->version < 2) {
1080                             LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "if-feature");
1081                             free(s);
1082                             YYABORT;
1083                           }
1084                           YANG_ADDELEM(((struct lys_type_enum *)actual)->iffeature,
1085                                        ((struct lys_type_enum *)actual)->iffeature_size, "if-features");
1086                           break;
1087                         case BIT_KEYWORD:
1088                           if (trg->version < 2) {
1089                             LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "if-feature", "bit");
1090                             free(s);
1091                             YYABORT;
1092                           }
1093                           YANG_ADDELEM(((struct lys_type_bit *)actual)->iffeature,
1094                                        ((struct lys_type_bit *)actual)->iffeature_size, "if-features");
1095                           break;
1096                         case REFINE_KEYWORD:
1097                           if (trg->version < 2) {
1098                             LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "if-feature");
1099                             free(s);
1100                             YYABORT;
1101                           }
1102                           YANG_ADDELEM(((struct lys_refine *)actual)->iffeature,
1103                                        ((struct lys_refine *)actual)->iffeature_size, "if-features");
1104                           break;
1105                         case EXTENSION_INSTANCE:
1106                           /* nothing change */
1107                           break;
1108                         default:
1109                           /* lys_node_* */
1110                           YANG_ADDELEM(((struct lys_node *)actual)->iffeature,
1111                                        ((struct lys_node *)actual)->iffeature_size, "if-features");
1112                           break;
1113                         }
1114                         ((struct lys_iffeature *)actual)->features = (struct lys_feature **)s;
1115                         s = NULL;
1116                         actual_type = IF_FEATURE_KEYWORD;
1117                       }
1118
1119if_feature_stmt: IF_FEATURE_KEYWORD sep if_feature_arg if_feature_end
1120                 { actual = $3.actual;
1121                   actual_type = $3.token;
1122                 }
1123
1124if_feature_end: ';'
1125  | '{' stmtsep '}'
1126
1127identity_arg_str: identifier_arg_str { const char *tmp;
1128
1129                                       tmp = lydict_insert_zc(trg->ctx, s);
1130                                       s = NULL;
1131                                       if (dup_identities_check(tmp, trg)) {
1132                                         lydict_remove(trg->ctx, tmp);
1133                                         YYABORT;
1134                                       }
1135                                       $$.token = actual_type;
1136                                       $$.actual = actual;
1137                                       YANG_ADDELEM(trg->ident, trg->ident_size, "identities");
1138                                       ((struct lys_ident *)actual)->name = tmp;
1139                                       ((struct lys_ident *)actual)->module = trg;
1140                                       actual_type = IDENTITY_KEYWORD;
1141                                     }
1142
1143identity_stmt: IDENTITY_KEYWORD sep identity_arg_str identity_end
1144               { actual = $3.actual;
1145                 actual_type = $3.token;
1146               }
1147
1148identity_end: ';'
1149  |  '{' stmtsep
1150         identity_opt_stmt
1151     '}' { void *tmp;
1152
1153           if (((struct lys_ident *)actual)->base_size) {
1154             tmp = realloc(((struct lys_ident *)actual)->base,
1155                           ((struct lys_ident *)actual)->base_size * sizeof *((struct lys_ident *)actual)->base);
1156             if (!tmp) {
1157               LOGMEM(trg->ctx);
1158               YYABORT;
1159             }
1160             ((struct lys_ident *)actual)->base = tmp;
1161           }
1162
1163           if (((struct lys_ident *)actual)->iffeature_size) {
1164             tmp = realloc(((struct lys_ident *)actual)->iffeature,
1165                           ((struct lys_ident *)actual)->iffeature_size * sizeof *((struct lys_ident *)actual)->iffeature);
1166             if (!tmp) {
1167               LOGMEM(trg->ctx);
1168               YYABORT;
1169             }
1170             ((struct lys_ident *)actual)->iffeature = tmp;
1171           }
1172         }
1173
1174identity_opt_stmt: @EMPTYDIR@
1175  |  identity_opt_stmt base_stmt { void *identity;
1176
1177                                   if ((trg->version < 2) && ((struct lys_ident *)actual)->base_size) {
1178                                     free(s);
1179                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity");
1180                                     YYABORT;
1181                                   }
1182                                   identity = actual;
1183                                   YANG_ADDELEM(((struct lys_ident *)actual)->base,
1184                                                ((struct lys_ident *)actual)->base_size, "bases");
1185                                   *((struct lys_ident **)actual) = (struct lys_ident *)s;
1186                                   s = NULL;
1187                                   actual = identity;
1188                                 }
1189  |  identity_opt_stmt if_feature_stmt stmtsep
1190  |  identity_opt_stmt status_stmt { if (((struct lys_ident *)actual)->flags & LYS_STATUS_MASK) {
1191                                       LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "identity");
1192                                       YYABORT;
1193                                     }
1194                                     ((struct lys_ident *)actual)->flags |= $2;
1195                                   }
1196  |  identity_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "identity", NODE)) {
1197                                            YYABORT;
1198                                          }
1199                                          s = NULL;
1200                                        }
1201  |  identity_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "identity", NODE)) {
1202                                          YYABORT;
1203                                        }
1204                                        s = NULL;
1205                                      }
1206
1207base_arg: identifier_ref_arg_str { backup_type = actual_type;
1208                                   actual_type = BASE_KEYWORD;
1209                                 }
1210
1211base_stmt: BASE_KEYWORD sep base_arg stmtend
1212
1213typedef_arg_str: identifier_arg_str { tpdf_parent = (actual_type == EXTENSION_INSTANCE) ? ext_instance : actual;
1214                                      $$.token = actual_type;
1215                                      $$.actual = actual;
1216                                      if (lyp_check_identifier(trg->ctx, s, LY_IDENT_TYPE, trg, tpdf_parent)) {
1217                                        free(s);
1218                                        YYABORT;
1219                                      }
1220                                      switch (actual_type) {
1221                                      case MODULE_KEYWORD:
1222                                      case SUBMODULE_KEYWORD:
1223                                        YANG_ADDELEM(trg->tpdf, trg->tpdf_size, "typedefs");
1224                                        break;
1225                                      case GROUPING_KEYWORD:
1226                                        YANG_ADDELEM(((struct lys_node_grp *)tpdf_parent)->tpdf,
1227                                                     ((struct lys_node_grp *)tpdf_parent)->tpdf_size, "typedefs");
1228                                        break;
1229                                      case CONTAINER_KEYWORD:
1230                                        YANG_ADDELEM(((struct lys_node_container *)tpdf_parent)->tpdf,
1231                                                     ((struct lys_node_container *)tpdf_parent)->tpdf_size, "typedefs");
1232                                        break;
1233                                      case LIST_KEYWORD:
1234                                        YANG_ADDELEM(((struct lys_node_list *)tpdf_parent)->tpdf,
1235                                                     ((struct lys_node_list *)tpdf_parent)->tpdf_size, "typedefs");
1236                                        break;
1237                                      case RPC_KEYWORD:
1238                                      case ACTION_KEYWORD:
1239                                        YANG_ADDELEM(((struct lys_node_rpc_action *)tpdf_parent)->tpdf,
1240                                                     ((struct lys_node_rpc_action *)tpdf_parent)->tpdf_size, "typedefs");
1241                                        break;
1242                                      case INPUT_KEYWORD:
1243                                      case OUTPUT_KEYWORD:
1244                                        YANG_ADDELEM(((struct lys_node_inout *)tpdf_parent)->tpdf,
1245                                                     ((struct lys_node_inout *)tpdf_parent)->tpdf_size, "typedefs");
1246                                        break;
1247                                      case NOTIFICATION_KEYWORD:
1248                                        YANG_ADDELEM(((struct lys_node_notif *)tpdf_parent)->tpdf,
1249                                                     ((struct lys_node_notif *)tpdf_parent)->tpdf_size, "typedefs");
1250                                        break;
1251                                      case EXTENSION_INSTANCE:
1252                                        /* typedef is already allocated */
1253                                        break;
1254                                      default:
1255                                        /* another type of nodetype is error*/
1256                                        LOGINT(trg->ctx);
1257                                        free(s);
1258                                        YYABORT;
1259                                      }
1260                                      ((struct lys_tpdf *)actual)->name = lydict_insert_zc(param->module->ctx, s);
1261                                      ((struct lys_tpdf *)actual)->module = trg;
1262                                      s = NULL;
1263                                      actual_type = TYPEDEF_KEYWORD;
1264                                    }
1265
1266typedef_stmt: TYPEDEF_KEYWORD sep typedef_arg_str
1267              '{' stmtsep
1268                  type_opt_stmt
1269              '}' { if (!($6.node.flag & LYS_TYPE_DEF)) {
1270                      LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "typedef");
1271                      YYABORT;
1272                    }
1273                    actual_type = $3.token;
1274                    actual = $3.actual;
1275                  }
1276
1277type_opt_stmt: @EMPTYDIR@ { $$.node.ptr_tpdf = actual;
1278                            $$.node.flag = 0;
1279                          }
1280  |  type_opt_stmt type_stmt stmtsep { $1.node.flag |= LYS_TYPE_DEF;
1281                                       $$ = $1;
1282                                     }
1283  |  type_opt_stmt units_stmt { if (yang_read_units(trg, $1.node.ptr_tpdf, s, TYPEDEF_KEYWORD)) {
1284                                  YYABORT;
1285                                }
1286                                s = NULL;
1287                              }
1288  |  type_opt_stmt default_stmt { if (yang_read_default(trg, $1.node.ptr_tpdf, s, TYPEDEF_KEYWORD)) {
1289                                    YYABORT;
1290                                  }
1291                                  s = NULL;
1292                                }
1293  |  type_opt_stmt status_stmt { if ($1.node.ptr_tpdf->flags & LYS_STATUS_MASK) {
1294                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "typedef");
1295                                   YYABORT;
1296                                 }
1297                                 $1.node.ptr_tpdf->flags |= $2;
1298                               }
1299  |  type_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_tpdf, s, "typedef", NODE)) {
1300                                        YYABORT;
1301                                      }
1302                                      s = NULL;
1303                                    }
1304  |  type_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_tpdf, s, "typedef", NODE)) {
1305                                      YYABORT;
1306                                    }
1307                                    s = NULL;
1308                                  }
1309
1310type_stmt: TYPE_KEYWORD sep type_arg_str type_end
1311           { actual_type = $3.token;
1312             actual = $3.actual;
1313           }
1314
1315type_arg_str: identifier_ref_arg_str { $$.token = actual_type;
1316                                       $$.actual = actual;
1317                                       if (!(actual = yang_read_type(trg->ctx, actual, s, actual_type))) {
1318                                         YYABORT;
1319                                       }
1320                                       s = NULL;
1321                                       actual_type = TYPE_KEYWORD;
1322                                     }
1323
1324type_end: ';'
1325  |  '{' stmtsep
1326         type_body_stmts
1327      '}'
1328
1329type_body_stmts: some_restrictions { if (((struct yang_type *)actual)->base == LY_TYPE_STRING &&
1330                                         ((struct yang_type *)actual)->type->info.str.pat_count) {
1331                                       void *tmp;
1332
1333                                       tmp = realloc(((struct yang_type *)actual)->type->info.str.patterns,
1334                                                     ((struct yang_type *)actual)->type->info.str.pat_count * sizeof *((struct yang_type *)actual)->type->info.str.patterns);
1335                                       if (!tmp) {
1336                                         LOGMEM(trg->ctx);
1337                                         YYABORT;
1338                                       }
1339                                       ((struct yang_type *)actual)->type->info.str.patterns = tmp;
1340
1341#ifdef LY_ENABLED_CACHE
1342                                       if (!(trg->ctx->models.flags & LY_CTX_TRUSTED) && ((struct yang_type *)actual)->type->info.str.patterns_pcre) {
1343                                         tmp = realloc(((struct yang_type *)actual)->type->info.str.patterns_pcre,
1344                                                       2 * ((struct yang_type *)actual)->type->info.str.pat_count * sizeof *((struct yang_type *)actual)->type->info.str.patterns_pcre);
1345                                         if (!tmp) {
1346                                           LOGMEM(trg->ctx);
1347                                           YYABORT;
1348                                         }
1349                                         ((struct yang_type *)actual)->type->info.str.patterns_pcre = tmp;
1350                                       }
1351#endif
1352                                     }
1353                                     if (((struct yang_type *)actual)->base == LY_TYPE_UNION) {
1354                                       struct lys_type *tmp;
1355
1356                                       tmp = realloc(((struct yang_type *)actual)->type->info.uni.types,
1357                                                     ((struct yang_type *)actual)->type->info.uni.count * sizeof *tmp);
1358                                       if (!tmp) {
1359                                         LOGMEM(trg->ctx);
1360                                         YYABORT;
1361                                       }
1362                                       ((struct yang_type *)actual)->type->info.uni.types = tmp;
1363                                     }
1364                                     if (((struct yang_type *)actual)->base == LY_TYPE_IDENT) {
1365                                       struct lys_ident **tmp;
1366
1367                                       tmp = realloc(((struct yang_type *)actual)->type->info.ident.ref,
1368                                                     ((struct yang_type *)actual)->type->info.ident.count* sizeof *tmp);
1369                                       if (!tmp) {
1370                                         LOGMEM(trg->ctx);
1371                                         YYABORT;
1372                                       }
1373                                       ((struct yang_type *)actual)->type->info.ident.ref = tmp;
1374                                     }
1375                                   }
1376  | enum_specification
1377  | bits_specification
1378
1379some_restrictions: @EMPTYDIR@
1380  |  some_restrictions require_instance_stmt { if (yang_read_require_instance(trg->ctx, actual, $2)) {
1381                                                 YYABORT;
1382                                               }
1383                                             }
1384  |  some_restrictions path_stmt { /* leafref_specification */
1385                                   if (yang_read_leafref_path(trg, actual, s)) {
1386                                     YYABORT;
1387                                   }
1388                                   s = NULL;
1389                                 }
1390  |  some_restrictions base_stmt { /* identityref_specification */
1391                                   if (((struct yang_type *)actual)->base && ((struct yang_type *)actual)->base != LY_TYPE_IDENT) {
1392                                     LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "base");
1393                                     return EXIT_FAILURE;
1394                                   }
1395                                   ((struct yang_type *)actual)->base = LY_TYPE_IDENT;
1396                                   yang_type = actual;
1397                                   YANG_ADDELEM(((struct yang_type *)actual)->type->info.ident.ref,
1398                                                ((struct yang_type *)actual)->type->info.ident.count, "identity refs");
1399                                   *((struct lys_ident **)actual) = (struct lys_ident *)s;
1400                                   actual = yang_type;
1401                                   s = NULL;
1402                                 }
1403  |  some_restrictions length_stmt stmtsep
1404  |  some_restrictions pattern_stmt stmtsep
1405  |  some_restrictions fraction_digits_stmt { if (yang_read_fraction(trg->ctx, actual, $2)) {
1406                                                YYABORT;
1407                                              }
1408                                            }
1409  |  some_restrictions range_stmt stmtsep
1410  |  some_restrictions union_stmt stmtsep
1411
1412union_stmt: union_spec type_stmt { actual_type = $1.token;
1413                                   actual = $1.actual;
1414                                 }
1415
1416union_spec: @EMPTYDIR@ { struct yang_type *stype = (struct yang_type *)actual;
1417
1418                         $$.token = actual_type;
1419                         $$.actual = actual;
1420                         if (stype->base != 0 && stype->base != LY_TYPE_UNION) {
1421                           LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected type statement.");
1422                           YYABORT;
1423                         }
1424                         stype->base = LY_TYPE_UNION;
1425                         if (strcmp(stype->name, "union")) {
1426                           /* type can be a substatement only in "union" type, not in derived types */
1427                           LOGVAL(trg->ctx, LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "type", "derived type");
1428                           YYABORT;
1429                         }
1430                         YANG_ADDELEM(stype->type->info.uni.types, stype->type->info.uni.count, "union types")
1431                         actual_type = UNION_KEYWORD;
1432                       }
1433
1434fraction_digits_arg: fraction_digits_arg_str { $$ = $1;
1435                                               backup_type = actual_type;
1436                                               actual_type = FRACTION_DIGITS_KEYWORD;
1437                                             }
1438
1439fraction_digits_stmt: FRACTION_DIGITS_KEYWORD sep fraction_digits_arg stmtend { $$ = $3; }
1440
1441fraction_digits_arg_str: positive_integer_value optsep { $$ = $1; }
1442  | string_1 { char *endptr = NULL;
1443               unsigned long val;
1444               errno = 0;
1445
1446               val = strtoul(s, &endptr, 10);
1447               if (*endptr || s[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
1448                 LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "fraction-digits");
1449                 free(s);
1450                 s = NULL;
1451                 YYABORT;
1452               }
1453               $$ = (uint32_t) val;
1454               free(s);
1455               s =NULL;
1456             }
1457
1458length_stmt: LENGTH_KEYWORD sep length_arg_str length_end
1459             { actual = $3.actual;
1460               actual_type = $3.token;
1461             }
1462
1463length_arg_str: string { $$.token = actual_type;
1464                         $$.actual = actual;
1465                         if (!(actual = yang_read_length(trg->ctx, actual, s, is_ext_instance))) {
1466                           YYABORT;
1467                         }
1468                         actual_type = LENGTH_KEYWORD;
1469                         s = NULL;
1470                       }
1471
1472length_end: ';'
1473  |  '{' stmtsep
1474         message_opt_stmt
1475      '}'
1476
1477message_opt_stmt: @EMPTYDIR@ { switch (actual_type) {
1478                               case MUST_KEYWORD:
1479                                 $$ = "must";
1480                                 break;
1481                               case LENGTH_KEYWORD:
1482                                 $$ = "length";
1483                                 break;
1484                               case RANGE_KEYWORD:
1485                                 $$ = "range";
1486                                 break;
1487                               default:
1488                                 LOGINT(trg->ctx);
1489                                 YYABORT;
1490                                 break;
1491                               }
1492                             }
1493  |  message_opt_stmt error_message_stmt { if (yang_read_message(trg, actual, s, $1, ERROR_MESSAGE_KEYWORD)) {
1494                                             YYABORT;
1495                                           }
1496                                           s = NULL;
1497                                         }
1498  |  message_opt_stmt error_app_tag_stmt { if (yang_read_message(trg, actual, s, $1, ERROR_APP_TAG_KEYWORD)) {
1499                                             YYABORT;
1500                                           }
1501                                           s = NULL;
1502                                         }
1503  |  message_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, $1, NODE)) {
1504                                           YYABORT;
1505                                          }
1506                                          s = NULL;
1507                                        }
1508  |  message_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, $1, NODE)) {
1509                                         YYABORT;
1510                                       }
1511                                       s = NULL;
1512                                     }
1513
1514pattern_sep: sep { $$.token = actual_type;
1515                   $$.actual = actual;
1516                 }
1517
1518pattern_stmt: PATTERN_KEYWORD pattern_sep pattern_arg_str pattern_end  {struct lys_restr *pattern = actual;
1519                                                                        actual = NULL;
1520#ifdef LY_ENABLED_CACHE
1521                                                                        if ($2.token != EXTENSION_INSTANCE &&
1522                                                                            !(data_node && data_node->nodetype != LYS_GROUPING && lys_ingrouping(data_node))) {
1523                                                                          unsigned int c = 2 * (((struct yang_type *)$2.actual)->type->info.str.pat_count - 1);
1524                                                                          YANG_ADDELEM(((struct yang_type *)$2.actual)->type->info.str.patterns_pcre, c, "patterns");
1525                                                                          ++c;
1526                                                                          YANG_ADDELEM(((struct yang_type *)$2.actual)->type->info.str.patterns_pcre, c, "patterns");
1527                                                                          actual = &(((struct yang_type *)$2.actual)->type->info.str.patterns_pcre)[2 * (((struct yang_type *)$2.actual)->type->info.str.pat_count - 1)];
1528                                                                        }
1529#endif
1530                                                                        if (yang_read_pattern(trg->ctx, pattern, actual, $3, $4)) {
1531                                                                          YYABORT;
1532                                                                        }
1533                                                                        actual_type = $2.token;
1534                                                                        actual = $2.actual;
1535                                                                      }
1536
1537pattern_arg_str: string { if (actual_type != EXTENSION_INSTANCE) {
1538                            if (((struct yang_type *)actual)->base != 0 && ((struct yang_type *)actual)->base != LY_TYPE_STRING) {
1539                              free(s);
1540                              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Unexpected pattern statement.");
1541                              YYABORT;
1542                            }
1543                            ((struct yang_type *)actual)->base = LY_TYPE_STRING;
1544                            YANG_ADDELEM(((struct yang_type *)actual)->type->info.str.patterns,
1545                                         ((struct yang_type *)actual)->type->info.str.pat_count, "patterns");
1546                          }
1547                          $$ = s;
1548                          s = NULL;
1549                          actual_type = PATTERN_KEYWORD;
1550                        }
1551
1552pattern_end: ';' { $$ = 0x06; }
1553  |  '{' stmtsep
1554         pattern_opt_stmt
1555     '}' { $$ = $3; }
1556
1557pattern_opt_stmt: @EMPTYDIR@ { $$ = 0x06; /* ACK */ }
1558  |  pattern_opt_stmt modifier_stmt { if (trg->version < 2) {
1559                                        LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, "modifier");
1560                                        YYABORT;
1561                                      }
1562                                      if ($1 != 0x06) {
1563                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", "pattern");
1564                                        YYABORT;
1565                                      }
1566                                      $$ = $2;
1567                                    }
1568  |  pattern_opt_stmt error_message_stmt { if (yang_read_message(trg, actual, s, "pattern", ERROR_MESSAGE_KEYWORD)) {
1569                                             YYABORT;
1570                                           }
1571                                           s = NULL;
1572                                         }
1573  |  pattern_opt_stmt error_app_tag_stmt { if (yang_read_message(trg, actual, s, "pattern", ERROR_APP_TAG_KEYWORD)) {
1574                                             YYABORT;
1575                                           }
1576                                           s = NULL;
1577                                         }
1578  |  pattern_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "pattern", NODE)) {
1579                                           YYABORT;
1580                                          }
1581                                          s = NULL;
1582                                        }
1583  |  pattern_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "pattern", NODE)) {
1584                                         YYABORT;
1585                                       }
1586                                       s = NULL;
1587                                     }
1588
1589modifier_arg: string { backup_type = actual_type;
1590                       actual_type = MODIFIER_KEYWORD;
1591                     }
1592
1593modifier_stmt: MODIFIER_KEYWORD sep modifier_arg stmtend { if (!strcmp(s, "invert-match")) {
1594                                                             $$ = 0x15;
1595                                                             free(s);
1596                                                             s = NULL;
1597                                                           } else {
1598                                                             LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, s);
1599                                                             free(s);
1600                                                             YYABORT;
1601                                                           }
1602                                                         }
1603
1604enum_specification: enum_stmt stmtsep enum_stmts { struct lys_type_enum * tmp;
1605
1606                                                   cnt_val = 0;
1607                                                   tmp = realloc(((struct yang_type *)actual)->type->info.enums.enm,
1608                                                                 ((struct yang_type *)actual)->type->info.enums.count * sizeof *tmp);
1609                                                   if (!tmp) {
1610                                                     LOGMEM(trg->ctx);
1611                                                     YYABORT;
1612                                                   }
1613                                                   ((struct yang_type *)actual)->type->info.enums.enm = tmp;
1614                                                 }
1615
1616enum_stmts: @EMPTYDIR@
1617  | enum_stmts enum_stmt stmtsep;
1618
1619
1620enum_stmt: ENUM_KEYWORD sep enum_arg_str enum_end
1621           { if (yang_check_enum(trg->ctx, yang_type, actual, &cnt_val, is_value)) {
1622               YYABORT;
1623             }
1624             actual = $3.actual;
1625             actual_type = $3.token;
1626           }
1627
1628enum_arg_str: string { $$.token = actual_type;
1629                       $$.actual = yang_type = actual;
1630                       YANG_ADDELEM(((struct yang_type *)actual)->type->info.enums.enm, ((struct yang_type *)actual)->type->info.enums.count, "enums");
1631                       if (yang_read_enum(trg->ctx, yang_type, actual, s)) {
1632                         YYABORT;
1633                       }
1634                       s = NULL;
1635                       is_value = 0;
1636                       actual_type = ENUM_KEYWORD;
1637                     }
1638
1639enum_end: ';'
1640  |  '{' stmtsep
1641         enum_opt_stmt
1642     '}' { if (((struct lys_type_enum *)actual)->iffeature_size) {
1643             struct lys_iffeature *tmp;
1644
1645             tmp = realloc(((struct lys_type_enum *)actual)->iffeature,
1646                           ((struct lys_type_enum *)actual)->iffeature_size * sizeof *tmp);
1647             if (!tmp) {
1648               LOGMEM(trg->ctx);
1649               YYABORT;
1650             }
1651             ((struct lys_type_enum *)actual)->iffeature = tmp;
1652           }
1653         }
1654
1655enum_opt_stmt: @EMPTYDIR@
1656  |  enum_opt_stmt if_feature_stmt stmtsep
1657  |  enum_opt_stmt value_stmt { if (is_value) {
1658                                  LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "value", "enum");
1659                                  YYABORT;
1660                                }
1661                                ((struct lys_type_enum *)actual)->value = $2;
1662
1663                                /* keep the highest enum value for automatic increment */
1664                                if ($2 >= cnt_val) {
1665                                  cnt_val = $2 + 1;
1666                                }
1667                                is_value = 1;
1668                              }
1669  |  enum_opt_stmt status_stmt { if (((struct lys_type_enum *)actual)->flags & LYS_STATUS_MASK) {
1670                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "enum");
1671                                   YYABORT;
1672                                 }
1673                                 ((struct lys_type_enum *)actual)->flags |= $2;
1674                               }
1675  |  enum_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "enum", NODE)) {
1676                                        YYABORT;
1677                                      }
1678                                      s = NULL;
1679                                    }
1680  |  enum_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "enum", NODE)) {
1681                                      YYABORT;
1682                                    }
1683                                    s = NULL;
1684                                  }
1685
1686value_arg: integer_value_arg_str { $$ = $1;
1687                                   backup_type = actual_type;
1688                                   actual_type = VALUE_KEYWORD;
1689                                 }
1690
1691value_stmt: VALUE_KEYWORD sep value_arg stmtend { $$ = $3; }
1692
1693integer_value_arg_str: integer_value optsep { $$ = $1; }
1694  |  string_1 { /* convert it to int32_t */
1695                int64_t val;
1696                char *endptr;
1697
1698                val = strtoll(s, &endptr, 10);
1699                if (val < INT32_MIN || val > INT32_MAX || *endptr) {
1700                    LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "value");
1701                    free(s);
1702                    YYABORT;
1703                }
1704                free(s);
1705                s = NULL;
1706                $$ = (int32_t) val;
1707             }
1708
1709range_stmt: RANGE_KEYWORD sep range_arg_str range_end { actual_type = $3.token;
1710                                                        actual = $3.actual;
1711                                                      }
1712
1713
1714range_end: ';'
1715  |  '{' stmtsep
1716         message_opt_stmt
1717      '}'
1718   ;
1719
1720path_arg: path_arg_str { backup_type = actual_type;
1721                         actual_type = PATH_KEYWORD;
1722                       }
1723
1724path_stmt: PATH_KEYWORD sep path_arg stmtend
1725
1726require_instance_arg: require_instance_arg_str { $$ = $1;
1727                                                 backup_type = actual_type;
1728                                                 actual_type = REQUIRE_INSTANCE_KEYWORD;
1729                                               }
1730
1731require_instance_stmt: REQUIRE_INSTANCE_KEYWORD sep require_instance_arg stmtend { $$ = $3; }
1732
1733require_instance_arg_str: TRUE_KEYWORD optsep { $$ = 1; }
1734  |  FALSE_KEYWORD optsep { $$ = -1; }
1735  |  string_1 { if (!strcmp(s,"true")) {
1736                  $$ = 1;
1737                } else if (!strcmp(s,"false")) {
1738                  $$ = -1;
1739                } else {
1740                  LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "require-instance");
1741                  free(s);
1742                  YYABORT;
1743                }
1744                free(s);
1745                s = NULL;
1746              }
1747
1748bits_specification: bit_stmt bit_stmts { struct lys_type_bit * tmp;
1749
1750                                         cnt_val = 0;
1751                                         tmp = realloc(((struct yang_type *)actual)->type->info.bits.bit,
1752                                                       ((struct yang_type *)actual)->type->info.bits.count * sizeof *tmp);
1753                                         if (!tmp) {
1754                                           LOGMEM(trg->ctx);
1755                                           YYABORT;
1756                                         }
1757                                         ((struct yang_type *)actual)->type->info.bits.bit = tmp;
1758                                       }
1759
1760bit_stmts: @EMPTYDIR@
1761  | bit_stmts bit_stmt;
1762
1763bit_stmt: BIT_KEYWORD sep bit_arg_str bit_end
1764          stmtsep { if (yang_check_bit(trg->ctx, yang_type, actual, &cnt_val, is_value)) {
1765                      YYABORT;
1766                    }
1767                    actual = $3.actual;
1768                    actual_type = $3.token;
1769                  }
1770
1771bit_arg_str: identifier_arg_str { $$.token = actual_type;
1772                                  $$.actual = yang_type = actual;
1773                                  YANG_ADDELEM(((struct yang_type *)actual)->type->info.bits.bit,
1774                                               ((struct yang_type *)actual)->type->info.bits.count, "bits");
1775                                  if (yang_read_bit(trg->ctx, yang_type, actual, s)) {
1776                                    YYABORT;
1777                                  }
1778                                  s = NULL;
1779                                  is_value = 0;
1780                                  actual_type = BIT_KEYWORD;
1781                                }
1782
1783bit_end: ';'
1784  |  '{' stmtsep
1785         bit_opt_stmt
1786     '}' { if (((struct lys_type_bit *)actual)->iffeature_size) {
1787             struct lys_iffeature *tmp;
1788
1789             tmp = realloc(((struct lys_type_bit *)actual)->iffeature,
1790                           ((struct lys_type_bit *)actual)->iffeature_size * sizeof *tmp);
1791             if (!tmp) {
1792               LOGMEM(trg->ctx);
1793               YYABORT;
1794             }
1795             ((struct lys_type_bit *)actual)->iffeature = tmp;
1796           }
1797         }
1798
1799bit_opt_stmt: @EMPTYDIR@
1800  |  bit_opt_stmt if_feature_stmt stmtsep
1801  |  bit_opt_stmt position_stmt { if (is_value) {
1802                                    LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "position", "bit");
1803                                    YYABORT;
1804                                  }
1805                                  ((struct lys_type_bit *)actual)->pos = $2;
1806
1807                                  /* keep the highest position value for automatic increment */
1808                                  if ($2 >= cnt_val) {
1809                                    cnt_val = $2 + 1;
1810                                  }
1811                                  is_value = 1;
1812                                }
1813  |  bit_opt_stmt status_stmt { if (((struct lys_type_bit *)actual)->flags & LYS_STATUS_MASK) {
1814                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "bit");
1815                                   YYABORT;
1816                                 }
1817                                 ((struct lys_type_bit *)actual)->flags |= $2;
1818                              }
1819  |  bit_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "bit", NODE)) {
1820                                       YYABORT;
1821                                     }
1822                                     s = NULL;
1823                                   }
1824  |  bit_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "bit", NODE)) {
1825                                     YYABORT;
1826                                   }
1827                                   s = NULL;
1828                                 }
1829
1830position_value_arg: position_value_arg_str { $$ = $1;
1831                                             backup_type = actual_type;
1832                                             actual_type = POSITION_KEYWORD;
1833                                           }
1834
1835position_stmt: POSITION_KEYWORD sep position_value_arg stmtend { $$ = $3; }
1836
1837position_value_arg_str: non_negative_integer_value optsep { $$ = $1; }
1838  |  string_1 { /* convert it to uint32_t */
1839                unsigned long val;
1840                char *endptr = NULL;
1841                errno = 0;
1842
1843                val = strtoul(s, &endptr, 10);
1844                if (s[0] == '-' || *endptr || errno || val > UINT32_MAX) {
1845                  LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "position");
1846                  free(s);
1847                  YYABORT;
1848                }
1849                free(s);
1850                s = NULL;
1851                $$ = (uint32_t) val;
1852              }
1853
1854error_message_arg: string { backup_type = actual_type;
1855                            actual_type = ERROR_MESSAGE_KEYWORD;
1856                          }
1857
1858error_message_stmt: ERROR_MESSAGE_KEYWORD sep error_message_arg stmtend
1859
1860error_app_tag_arg: string { backup_type = actual_type;
1861                            actual_type = ERROR_APP_TAG_KEYWORD;
1862                          }
1863
1864error_app_tag_stmt: ERROR_APP_TAG_KEYWORD sep error_app_tag_arg stmtend
1865
1866units_arg: string { backup_type = actual_type;
1867                    actual_type = UNITS_KEYWORD;
1868                  }
1869
1870units_stmt: UNITS_KEYWORD sep units_arg stmtend
1871
1872default_arg: string { backup_type = actual_type;
1873                      actual_type = DEFAULT_KEYWORD;
1874                    }
1875
1876default_stmt: DEFAULT_KEYWORD sep default_arg stmtend
1877
1878grouping_arg_str: identifier_arg_str { $$.token = actual_type;
1879                                       $$.actual = actual;
1880                                       if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_GROUPING, sizeof(struct lys_node_grp)))) {
1881                                         YYABORT;
1882                                       }
1883                                       s = NULL;
1884                                       data_node = actual;
1885                                       actual_type = GROUPING_KEYWORD;
1886                                     }
1887
1888grouping_stmt: GROUPING_KEYWORD sep grouping_arg_str grouping_end
1889               { LOGDBG(LY_LDGYANG, "finished parsing grouping statement \"%s\"", data_node->name);
1890                 actual_type = $3.token;
1891                 actual = $3.actual;
1892                 data_node = $3.actual;
1893               }
1894
1895grouping_end: ';'
1896  |  '{' stmtsep
1897         grouping_opt_stmt
1898     '}'
1899
1900grouping_opt_stmt: @EMPTYDIR@ { $$.grouping = actual; }
1901  |  grouping_opt_stmt status_stmt { if ($1.grouping->flags & LYS_STATUS_MASK) {
1902                                       LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.grouping, "status", "grouping");
1903                                       YYABORT;
1904                                     }
1905                                     $1.grouping->flags |= $2;
1906                                   }
1907  |  grouping_opt_stmt description_stmt { if (yang_read_description(trg, $1.grouping, s, "grouping", NODE_PRINT)) {
1908                                            YYABORT;
1909                                          }
1910                                          s = NULL;
1911                                        }
1912  |  grouping_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.grouping, s, "grouping", NODE_PRINT)) {
1913                                          YYABORT;
1914                                        }
1915                                        s = NULL;
1916                                      }
1917  |  grouping_opt_stmt grouping_stmt stmtsep
1918  |  grouping_opt_stmt typedef_stmt stmtsep
1919  |  grouping_opt_stmt data_def_stmt stmtsep
1920  |  grouping_opt_stmt action_stmt stmtsep
1921  |  grouping_opt_stmt notification_stmt stmtsep { if (trg->version < 2) {
1922                                                     LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, $1.grouping, "notification");
1923                                                     YYABORT;
1924                                                   }
1925                                                 }
1926
1927data_def_stmt: container_stmt
1928  |  leaf_stmt
1929  |  leaf_list_stmt
1930  |  list_stmt
1931  |  choice_stmt
1932  |  anyxml_stmt
1933  |  anydata_stmt
1934  |  uses_stmt
1935  ;
1936
1937container_arg_str: identifier_arg_str { $$.token = actual_type;
1938                                        $$.actual = actual;
1939                                        if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_CONTAINER, sizeof(struct lys_node_container)))) {
1940                                          YYABORT;
1941                                        }
1942                                        data_node = actual;
1943                                        s = NULL;
1944                                        actual_type = CONTAINER_KEYWORD;
1945                                      }
1946
1947container_stmt: CONTAINER_KEYWORD sep container_arg_str container_end
1948                { LOGDBG(LY_LDGYANG, "finished parsing container statement \"%s\"", data_node->name);
1949                  actual_type = $3.token;
1950                  actual = $3.actual;
1951                  data_node = $3.actual;
1952                }
1953
1954container_end: ';'
1955  |  '{' stmtsep
1956         container_opt_stmt
1957      '}' { void *tmp;
1958
1959            if ($3.container->iffeature_size) {
1960              tmp = realloc($3.container->iffeature, $3.container->iffeature_size * sizeof *$3.container->iffeature);
1961              if (!tmp) {
1962                LOGMEM(trg->ctx);
1963                YYABORT;
1964              }
1965              $3.container->iffeature = tmp;
1966            }
1967
1968            if ($3.container->must_size) {
1969              tmp = realloc($3.container->must, $3.container->must_size * sizeof *$3.container->must);
1970              if (!tmp) {
1971                LOGMEM(trg->ctx);
1972                YYABORT;
1973              }
1974              $3.container->must = tmp;
1975            }
1976          }
1977
1978container_opt_stmt: @EMPTYDIR@ { $$.container = actual; }
1979  |  container_opt_stmt when_stmt stmtsep
1980  |  container_opt_stmt if_feature_stmt stmtsep
1981  |  container_opt_stmt must_stmt stmtsep
1982  |  container_opt_stmt presence_stmt { if (yang_read_presence(trg, $1.container, s)) {
1983                                          YYABORT;
1984                                        }
1985                                        s = NULL;
1986                                      }
1987  |  container_opt_stmt config_stmt { if ($1.container->flags & LYS_CONFIG_MASK) {
1988                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.container, "config", "container");
1989                                        YYABORT;
1990                                      }
1991                                      $1.container->flags |= $2;
1992                                    }
1993  |  container_opt_stmt status_stmt { if ($1.container->flags & LYS_STATUS_MASK) {
1994                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.container, "status", "container");
1995                                        YYABORT;
1996                                      }
1997                                      $1.container->flags |= $2;
1998                                    }
1999  |  container_opt_stmt description_stmt { if (yang_read_description(trg, $1.container, s, "container", NODE_PRINT)) {
2000                                             YYABORT;
2001                                           }
2002                                           s = NULL;
2003                                         }
2004  |  container_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.container, s, "container", NODE_PRINT)) {
2005                                           YYABORT;
2006                                         }
2007                                         s = NULL;
2008                                       }
2009  |  container_opt_stmt grouping_stmt stmtsep
2010  |  container_opt_stmt action_stmt stmtsep
2011  |  container_opt_stmt notification_stmt stmtsep { if (trg->version < 2) {
2012                                                      LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, $1.container, "notification");
2013                                                      YYABORT;
2014                                                    }
2015                                                  }
2016  |  container_opt_stmt typedef_stmt stmtsep
2017  |  container_opt_stmt data_def_stmt stmtsep
2018
2019leaf_stmt: LEAF_KEYWORD sep leaf_arg_str
2020           '{' stmtsep
2021               leaf_opt_stmt
2022            '}' { void *tmp;
2023
2024                  if (!($6.node.flag & LYS_TYPE_DEF)) {
2025                    LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, $6.node.ptr_leaf, "type", "leaf");
2026                    YYABORT;
2027                  }
2028                  if ($6.node.ptr_leaf->dflt && ($6.node.ptr_leaf->flags & LYS_MAND_TRUE)) {
2029                    /* RFC 6020, 7.6.4 - default statement must not with mandatory true */
2030                    LOGVAL(trg->ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, $6.node.ptr_leaf, "mandatory", "leaf");
2031                    LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $6.node.ptr_leaf, "The \"mandatory\" statement is forbidden on leaf with \"default\".");
2032                    YYABORT;
2033                  }
2034
2035                  if ($6.node.ptr_leaf->iffeature_size) {
2036                    tmp = realloc($6.node.ptr_leaf->iffeature, $6.node.ptr_leaf->iffeature_size * sizeof *$6.node.ptr_leaf->iffeature);
2037                    if (!tmp) {
2038                      LOGMEM(trg->ctx);
2039                      YYABORT;
2040                    }
2041                    $6.node.ptr_leaf->iffeature = tmp;
2042                  }
2043
2044                  if ($6.node.ptr_leaf->must_size) {
2045                    tmp = realloc($6.node.ptr_leaf->must, $6.node.ptr_leaf->must_size * sizeof *$6.node.ptr_leaf->must);
2046                    if (!tmp) {
2047                      LOGMEM(trg->ctx);
2048                      YYABORT;
2049                    }
2050                    $6.node.ptr_leaf->must = tmp;
2051                  }
2052
2053                  LOGDBG(LY_LDGYANG, "finished parsing leaf statement \"%s\"", data_node->name);
2054                  actual_type = $3.token;
2055                  actual = $3.actual;
2056                  data_node = $3.actual;
2057                }
2058
2059leaf_arg_str: identifier_arg_str { $$.token = actual_type;
2060                                   $$.actual = actual;
2061                                   if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_LEAF, sizeof(struct lys_node_leaf)))) {
2062                                     YYABORT;
2063                                   }
2064                                   data_node = actual;
2065                                   s = NULL;
2066                                   actual_type = LEAF_KEYWORD;
2067                                 }
2068
2069leaf_opt_stmt: @EMPTYDIR@ { $$.node.ptr_leaf = actual;
2070                            $$.node.flag = 0;
2071                          }
2072  |  leaf_opt_stmt when_stmt stmtsep
2073  |  leaf_opt_stmt if_feature_stmt stmtsep
2074  |  leaf_opt_stmt type_stmt stmtsep { $1.node.flag |= LYS_TYPE_DEF;
2075                                       $$ = $1;
2076                                     }
2077  |  leaf_opt_stmt units_stmt { if (yang_read_units(trg, $1.node.ptr_leaf, s, LEAF_KEYWORD)) {
2078                                  YYABORT;
2079                                }
2080                                s = NULL;
2081                              }
2082  |  leaf_opt_stmt must_stmt stmtsep
2083  |  leaf_opt_stmt default_stmt { if (yang_read_default(trg, $1.node.ptr_leaf, s, LEAF_KEYWORD)) {
2084                                    YYABORT;
2085                                  }
2086                                  s = NULL;
2087                                }
2088  |  leaf_opt_stmt config_stmt { if ($1.node.ptr_leaf->flags & LYS_CONFIG_MASK) {
2089                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaf, "config", "leaf");
2090                                   YYABORT;
2091                                 }
2092                                 $1.node.ptr_leaf->flags |= $2;
2093                               }
2094  |  leaf_opt_stmt mandatory_stmt { if ($1.node.ptr_leaf->flags & LYS_MAND_MASK) {
2095                                      LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaf, "mandatory", "leaf");
2096                                      YYABORT;
2097                                    }
2098                                    $1.node.ptr_leaf->flags |= $2;
2099                                  }
2100  |  leaf_opt_stmt status_stmt { if ($1.node.ptr_leaf->flags & LYS_STATUS_MASK) {
2101                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaf, "status", "leaf");
2102                                   YYABORT;
2103                                 }
2104                                 $1.node.ptr_leaf->flags |= $2;
2105                               }
2106  |  leaf_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_leaf, s, "leaf", NODE_PRINT)) {
2107                                        YYABORT;
2108                                      }
2109                                      s = NULL;
2110                                    }
2111  |  leaf_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_leaf, s, "leaf", NODE_PRINT)) {
2112                                      YYABORT;
2113                                    }
2114                                    s = NULL;
2115                                  }
2116
2117leaf_list_arg_str: identifier_arg_str { $$.token = actual_type;
2118                                        $$.actual = actual;
2119                                        if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_LEAFLIST, sizeof(struct lys_node_leaflist)))) {
2120                                          YYABORT;
2121                                        }
2122                                        data_node = actual;
2123                                        s = NULL;
2124                                        actual_type = LEAF_LIST_KEYWORD;
2125                                      }
2126
2127  leaf_list_stmt: LEAF_LIST_KEYWORD sep leaf_list_arg_str
2128                  '{' stmtsep
2129                      leaf_list_opt_stmt
2130                  '}' { void *tmp;
2131
2132                        if ($6.node.ptr_leaflist->flags & LYS_CONFIG_R) {
2133                          /* RFC 6020, 7.7.5 - ignore ordering when the list represents state data
2134                           * ignore oredering MASK - 0x7F
2135                           */
2136                          $6.node.ptr_leaflist->flags &= 0x7F;
2137                        }
2138                        if (!($6.node.flag & LYS_TYPE_DEF)) {
2139                          LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_LYS, $6.node.ptr_leaflist, "type", "leaf-list");
2140                          YYABORT;
2141                        }
2142                        if ($6.node.ptr_leaflist->dflt_size && $6.node.ptr_leaflist->min) {
2143                          LOGVAL(trg->ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, $6.node.ptr_leaflist, "min-elements", "leaf-list");
2144                          LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $6.node.ptr_leaflist,
2145                                 "The \"min-elements\" statement with non-zero value is forbidden on leaf-lists with the \"default\" statement.");
2146                          YYABORT;
2147                        }
2148
2149                        if ($6.node.ptr_leaflist->iffeature_size) {
2150                          tmp = realloc($6.node.ptr_leaflist->iffeature, $6.node.ptr_leaflist->iffeature_size * sizeof *$6.node.ptr_leaflist->iffeature);
2151                          if (!tmp) {
2152                            LOGMEM(trg->ctx);
2153                            YYABORT;
2154                          }
2155                          $6.node.ptr_leaflist->iffeature = tmp;
2156                        }
2157
2158                        if ($6.node.ptr_leaflist->must_size) {
2159                          tmp = realloc($6.node.ptr_leaflist->must, $6.node.ptr_leaflist->must_size * sizeof *$6.node.ptr_leaflist->must);
2160                          if (!tmp) {
2161                            LOGMEM(trg->ctx);
2162                            YYABORT;
2163                          }
2164                          $6.node.ptr_leaflist->must = tmp;
2165                        }
2166
2167                        if ($6.node.ptr_leaflist->dflt_size) {
2168                          tmp = realloc($6.node.ptr_leaflist->dflt, $6.node.ptr_leaflist->dflt_size * sizeof *$6.node.ptr_leaflist->dflt);
2169                          if (!tmp) {
2170                            LOGMEM(trg->ctx);
2171                            YYABORT;
2172                          }
2173                          $6.node.ptr_leaflist->dflt = tmp;
2174                        }
2175
2176                        LOGDBG(LY_LDGYANG, "finished parsing leaf-list statement \"%s\"", data_node->name);
2177                        actual_type = $3.token;
2178                        actual = $3.actual;
2179                        data_node = $3.actual;
2180                      }
2181
2182leaf_list_opt_stmt: @EMPTYDIR@ { $$.node.ptr_leaflist = actual;
2183                                 $$.node.flag = 0;
2184                               }
2185  |  leaf_list_opt_stmt when_stmt stmtsep
2186  |  leaf_list_opt_stmt if_feature_stmt stmtsep
2187  |  leaf_list_opt_stmt type_stmt stmtsep { $1.node.flag |= LYS_TYPE_DEF;
2188                                            $$ = $1;
2189                                          }
2190  |  leaf_list_opt_stmt default_stmt { if (trg->version < 2) {
2191                                         free(s);
2192                                         LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, $1.node.ptr_leaflist, "default");
2193                                         YYABORT;
2194                                       }
2195                                       YANG_ADDELEM($1.node.ptr_leaflist->dflt,
2196                                                    $1.node.ptr_leaflist->dflt_size, "defaults");
2197                                       (*(const char **)actual) = lydict_insert_zc(param->module->ctx, s);
2198                                       s = NULL;
2199                                       actual = $1.node.ptr_leaflist;
2200                                     }
2201  |  leaf_list_opt_stmt units_stmt { if (yang_read_units(trg, $1.node.ptr_leaflist, s, LEAF_LIST_KEYWORD)) {
2202                                       YYABORT;
2203                                     }
2204                                     s = NULL;
2205                                   }
2206  |  leaf_list_opt_stmt must_stmt stmtsep
2207  |  leaf_list_opt_stmt config_stmt { if ($1.node.ptr_leaflist->flags & LYS_CONFIG_MASK) {
2208                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "config", "leaf-list");
2209                                        YYABORT;
2210                                      }
2211                                      $1.node.ptr_leaflist->flags |= $2;
2212                                    }
2213  |  leaf_list_opt_stmt min_elements_stmt { if ($1.node.flag & LYS_MIN_ELEMENTS) {
2214                                              LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "min-elements", "leaf-list");
2215                                              YYABORT;
2216                                            }
2217                                            $1.node.ptr_leaflist->min = $2;
2218                                            $1.node.flag |= LYS_MIN_ELEMENTS;
2219                                            $$ = $1;
2220                                            if ($1.node.ptr_leaflist->max && ($1.node.ptr_leaflist->min > $1.node.ptr_leaflist->max)) {
2221                                              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_leaflist, "Invalid value \"%d\" of \"%s\".", $2, "min-elements");
2222                                              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_leaflist, "\"min-elements\" is bigger than \"max-elements\".");
2223                                              YYABORT;
2224                                            }
2225                                          }
2226  |  leaf_list_opt_stmt max_elements_stmt { if ($1.node.flag & LYS_MAX_ELEMENTS) {
2227                                              LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "max-elements", "leaf-list");
2228                                              YYABORT;
2229                                            }
2230                                            $1.node.ptr_leaflist->max = $2;
2231                                            $1.node.flag |= LYS_MAX_ELEMENTS;
2232                                            $$ = $1;
2233                                            if ($1.node.ptr_leaflist->max && ($1.node.ptr_leaflist->min > $1.node.ptr_leaflist->max)) {
2234                                              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_leaflist, "Invalid value \"%d\" of \"%s\".", $2, "max-elements");
2235                                              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_leaflist, "\"max-elements\" is smaller than \"min-elements\".");
2236                                              YYABORT;
2237                                            }
2238                                          }
2239  |  leaf_list_opt_stmt ordered_by_stmt { if ($1.node.flag & LYS_ORDERED_MASK) {
2240                                            LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "ordered by", "leaf-list");
2241                                            YYABORT;
2242                                          }
2243                                          if ($2 & LYS_USERORDERED) {
2244                                            $1.node.ptr_leaflist->flags |= LYS_USERORDERED;
2245                                          }
2246                                          $1.node.flag |= $2;
2247                                          $$ = $1;
2248                                        }
2249  |  leaf_list_opt_stmt status_stmt { if ($1.node.ptr_leaflist->flags & LYS_STATUS_MASK) {
2250                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "status", "leaf-list");
2251                                        YYABORT;
2252                                      }
2253                                      $1.node.ptr_leaflist->flags |= $2;
2254                                    }
2255  |  leaf_list_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_leaflist, s, "leaf-list", NODE_PRINT)) {
2256                                             YYABORT;
2257                                           }
2258                                           s = NULL;
2259                                         }
2260  |  leaf_list_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_leaflist, s, "leaf-list", NODE_PRINT)) {
2261                                           YYABORT;
2262                                         }
2263                                         s = NULL;
2264                                       }
2265
2266list_arg_str: identifier_arg_str { $$.token = actual_type;
2267                                   $$.actual = actual;
2268                                   if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_LIST, sizeof(struct lys_node_list)))) {
2269                                     YYABORT;
2270                                   }
2271                                   data_node = actual;
2272                                   s = NULL;
2273                                   actual_type = LIST_KEYWORD;
2274                                 }
2275
2276list_stmt: LIST_KEYWORD sep list_arg_str
2277           '{' stmtsep
2278               list_opt_stmt
2279            '}' { void *tmp;
2280
2281                  if ($6.node.ptr_list->iffeature_size) {
2282                    tmp = realloc($6.node.ptr_list->iffeature, $6.node.ptr_list->iffeature_size * sizeof *$6.node.ptr_list->iffeature);
2283                    if (!tmp) {
2284                      LOGMEM(trg->ctx);
2285                      YYABORT;
2286                    }
2287                    $6.node.ptr_list->iffeature = tmp;
2288                  }
2289
2290                  if ($6.node.ptr_list->must_size) {
2291                    tmp = realloc($6.node.ptr_list->must, $6.node.ptr_list->must_size * sizeof *$6.node.ptr_list->must);
2292                    if (!tmp) {
2293                      LOGMEM(trg->ctx);
2294                      YYABORT;
2295                    }
2296                    $6.node.ptr_list->must = tmp;
2297                  }
2298
2299                  if ($6.node.ptr_list->tpdf_size) {
2300                    tmp = realloc($6.node.ptr_list->tpdf, $6.node.ptr_list->tpdf_size * sizeof *$6.node.ptr_list->tpdf);
2301                    if (!tmp) {
2302                      LOGMEM(trg->ctx);
2303                      YYABORT;
2304                    }
2305                    $6.node.ptr_list->tpdf = tmp;
2306                  }
2307
2308                  if ($6.node.ptr_list->unique_size) {
2309                    tmp = realloc($6.node.ptr_list->unique, $6.node.ptr_list->unique_size * sizeof *$6.node.ptr_list->unique);
2310                    if (!tmp) {
2311                      LOGMEM(trg->ctx);
2312                      YYABORT;
2313                    }
2314                    $6.node.ptr_list->unique = tmp;
2315                  }
2316
2317                  LOGDBG(LY_LDGYANG, "finished parsing list statement \"%s\"", data_node->name);
2318                  actual_type = $3.token;
2319                  actual = $3.actual;
2320                  data_node = $3.actual;
2321                }
2322
2323list_opt_stmt: @EMPTYDIR@ { $$.node.ptr_list = actual;
2324                            $$.node.flag = 0;
2325                          }
2326  |  list_opt_stmt when_stmt stmtsep
2327  |  list_opt_stmt if_feature_stmt stmtsep
2328  |  list_opt_stmt must_stmt stmtsep
2329  |  list_opt_stmt key_stmt { if ($1.node.ptr_list->keys) {
2330                                  LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "key", "list");
2331                                  free(s);
2332                                  YYABORT;
2333                              }
2334                              $1.node.ptr_list->keys = (struct lys_node_leaf **)s;
2335                              $$ = $1;
2336                              s = NULL;
2337                            }
2338  |  list_opt_stmt unique_stmt { YANG_ADDELEM($1.node.ptr_list->unique, $1.node.ptr_list->unique_size, "uniques");
2339                                 ((struct lys_unique *)actual)->expr = (const char **)s;
2340                                 $$ = $1;
2341                                 s = NULL;
2342                                 actual = $1.node.ptr_list;
2343                               }
2344  |  list_opt_stmt config_stmt { if ($1.node.ptr_list->flags & LYS_CONFIG_MASK) {
2345                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "config", "list");
2346                                   YYABORT;
2347                                 }
2348                                 $1.node.ptr_list->flags |= $2;
2349                               }
2350  |  list_opt_stmt min_elements_stmt { if ($1.node.flag & LYS_MIN_ELEMENTS) {
2351                                         LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "min-elements", "list");
2352                                         YYABORT;
2353                                       }
2354                                       $1.node.ptr_list->min = $2;
2355                                       $1.node.flag |= LYS_MIN_ELEMENTS;
2356                                       $$ = $1;
2357                                       if ($1.node.ptr_list->max && ($1.node.ptr_list->min > $1.node.ptr_list->max)) {
2358                                         LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_list, "Invalid value \"%d\" of \"%s\".", $2, "min-elements");
2359                                         LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_list, "\"min-elements\" is bigger than \"max-elements\".");
2360                                         YYABORT;
2361                                       }
2362                                     }
2363  |  list_opt_stmt max_elements_stmt { if ($1.node.flag & LYS_MAX_ELEMENTS) {
2364                                         LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "max-elements", "list");
2365                                         YYABORT;
2366                                       }
2367                                       $1.node.ptr_list->max = $2;
2368                                       $1.node.flag |= LYS_MAX_ELEMENTS;
2369                                       $$ = $1;
2370                                       if ($1.node.ptr_list->max && ($1.node.ptr_list->min > $1.node.ptr_list->max)) {
2371                                         LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_list, "Invalid value \"%d\" of \"%s\".", $2, "min-elements");
2372                                         LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $1.node.ptr_list, "\"max-elements\" is smaller than \"min-elements\".");
2373                                         YYABORT;
2374                                       }
2375                                     }
2376  |  list_opt_stmt ordered_by_stmt { if ($1.node.flag & LYS_ORDERED_MASK) {
2377                                       LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "ordered by", "list");
2378                                       YYABORT;
2379                                     }
2380                                     if ($2 & LYS_USERORDERED) {
2381                                       $1.node.ptr_list->flags |= LYS_USERORDERED;
2382                                     }
2383                                     $1.node.flag |= $2;
2384                                     $$ = $1;
2385                                   }
2386  |  list_opt_stmt status_stmt { if ($1.node.ptr_list->flags & LYS_STATUS_MASK) {
2387                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "status", "list");
2388                                   YYABORT;
2389                                 }
2390                                 $1.node.ptr_list->flags |= $2;
2391                               }
2392  |  list_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_list, s, "list", NODE_PRINT)) {
2393                                        YYABORT;
2394                                      }
2395                                      s = NULL;
2396                                    }
2397  |  list_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_list, s, "list", NODE_PRINT)) {
2398                                      YYABORT;
2399                                    }
2400                                    s = NULL;
2401                                  }
2402  |  list_opt_stmt typedef_stmt stmtsep
2403  |  list_opt_stmt grouping_stmt stmtsep
2404  |  list_opt_stmt action_stmt stmtsep
2405  |  list_opt_stmt notification_stmt stmtsep { if (trg->version < 2) {
2406                                                 LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, $1.node.ptr_list, "notification");
2407                                                 YYABORT;
2408                                               }
2409                                             }
2410  |  list_opt_stmt data_def_stmt stmtsep
2411
2412choice_arg_str: identifier_arg_str { $$.token = actual_type;
2413                                     $$.actual = actual;
2414                                     if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_CHOICE, sizeof(struct lys_node_choice)))) {
2415                                       YYABORT;
2416                                     }
2417                                     data_node = actual;
2418                                     s = NULL;
2419                                     actual_type = CHOICE_KEYWORD;
2420                                   }
2421
2422choice_stmt: CHOICE_KEYWORD sep choice_arg_str choice_end
2423             { LOGDBG(LY_LDGYANG, "finished parsing choice statement \"%s\"", data_node->name);
2424               actual_type = $3.token;
2425               actual = $3.actual;
2426               data_node = $3.actual;
2427             }
2428
2429choice_end: ';'
2430  |  '{' stmtsep
2431         choice_opt_stmt
2432     '}' { struct lys_iffeature *tmp;
2433
2434           if (($3.node.ptr_choice->flags & LYS_MAND_TRUE) && $3.node.ptr_choice->dflt) {
2435              LOGVAL(trg->ctx, LYE_INCHILDSTMT, LY_VLOG_LYS, $3.node.ptr_choice, "default", "choice");
2436              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_LYS, $3.node.ptr_choice, "The \"default\" statement is forbidden on choices with \"mandatory\".");
2437              YYABORT;
2438            }
2439
2440           if ($3.node.ptr_choice->iffeature_size) {
2441             tmp = realloc($3.node.ptr_choice->iffeature, $3.node.ptr_choice->iffeature_size * sizeof *tmp);
2442             if (!tmp) {
2443               LOGMEM(trg->ctx);
2444               YYABORT;
2445             }
2446             $3.node.ptr_choice->iffeature = tmp;
2447           }
2448         }
2449
2450choice_opt_stmt: @EMPTYDIR@ { $$.node.ptr_choice = actual;
2451                              $$.node.flag = 0;
2452                            }
2453  |  choice_opt_stmt when_stmt stmtsep
2454  |  choice_opt_stmt if_feature_stmt stmtsep
2455  |  choice_opt_stmt default_stmt { if ($1.node.flag & LYS_CHOICE_DEFAULT) {
2456                                      LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_choice, "default", "choice");
2457                                      free(s);
2458                                      YYABORT;
2459                                    }
2460                                    $1.node.ptr_choice->dflt = (struct lys_node *) s;
2461                                    s = NULL;
2462                                    $$ = $1;
2463                                    $$.node.flag |= LYS_CHOICE_DEFAULT;
2464                                  }
2465  |  choice_opt_stmt config_stmt { if ($1.node.ptr_choice->flags & LYS_CONFIG_MASK) {
2466                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_choice, "config", "choice");
2467                                     YYABORT;
2468                                   }
2469                                   $1.node.ptr_choice->flags |= $2;
2470                                   $$ = $1;
2471                                 }
2472|  choice_opt_stmt mandatory_stmt { if ($1.node.ptr_choice->flags & LYS_MAND_MASK) {
2473                                      LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_choice, "mandatory", "choice");
2474                                      YYABORT;
2475                                    }
2476                                    $1.node.ptr_choice->flags |= $2;
2477                                    $$ = $1;
2478                                  }
2479  |  choice_opt_stmt status_stmt { if ($1.node.ptr_choice->flags & LYS_STATUS_MASK) {
2480                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_choice, "status", "choice");
2481                                     YYABORT;
2482                                   }
2483                                   $1.node.ptr_choice->flags |= $2;
2484                                   $$ = $1;
2485                                 }
2486  |  choice_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_choice, s, "choice", NODE_PRINT)) {
2487                                          YYABORT;
2488                                        }
2489                                        s = NULL;
2490                                        $$ = $1;
2491                                      }
2492  |  choice_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_choice, s, "choice", NODE_PRINT)) {
2493                                        YYABORT;
2494                                      }
2495                                      s = NULL;
2496                                      $$ = $1;
2497                                    }
2498  |  choice_opt_stmt short_case_case_stmt stmtsep
2499
2500short_case_case_stmt:  short_case_stmt
2501  |  case_stmt
2502
2503short_case_stmt: container_stmt
2504  |  leaf_stmt
2505  |  leaf_list_stmt
2506  |  list_stmt
2507  |  anyxml_stmt
2508  |  anydata_stmt
2509  |  choice_stmt { if (trg->version < 2 ) {
2510                     LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, actual, "choice");
2511                     YYABORT;
2512                   }
2513                 }
2514
2515case_arg_str: identifier_arg_str { $$.token = actual_type;
2516                                   $$.actual = actual;
2517                                   if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_CASE, sizeof(struct lys_node_case)))) {
2518                                     YYABORT;
2519                                   }
2520                                   data_node = actual;
2521                                   s = NULL;
2522                                   actual_type = CASE_KEYWORD;
2523                                 }
2524
2525case_stmt: CASE_KEYWORD sep case_arg_str case_end
2526           { LOGDBG(LY_LDGYANG, "finished parsing case statement \"%s\"", data_node->name);
2527             actual_type = $3.token;
2528             actual = $3.actual;
2529             data_node = $3.actual;
2530           }
2531
2532case_end: ';'
2533  |  '{' stmtsep
2534         case_opt_stmt
2535      '}' { struct lys_iffeature *tmp;
2536
2537           if ($3.cs->iffeature_size) {
2538             tmp = realloc($3.cs->iffeature, $3.cs->iffeature_size * sizeof *tmp);
2539             if (!tmp) {
2540               LOGMEM(trg->ctx);
2541               YYABORT;
2542             }
2543             $3.cs->iffeature = tmp;
2544           }
2545          }
2546
2547case_opt_stmt: @EMPTYDIR@ { $$.cs = actual; }
2548  |  case_opt_stmt when_stmt stmtsep
2549  |  case_opt_stmt if_feature_stmt stmtsep
2550  |  case_opt_stmt status_stmt { if ($1.cs->flags & LYS_STATUS_MASK) {
2551                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.cs, "status", "case");
2552                                   YYABORT;
2553                                 }
2554                                 $1.cs->flags |= $2;
2555                               }
2556  |  case_opt_stmt description_stmt { if (yang_read_description(trg, $1.cs, s, "case", NODE_PRINT)) {
2557                                        YYABORT;
2558                                      }
2559                                      s = NULL;
2560                                    }
2561  |  case_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.cs, s, "case", NODE_PRINT)) {
2562                                      YYABORT;
2563                                    }
2564                                    s = NULL;
2565                                  }
2566  |  case_opt_stmt data_def_stmt stmtsep
2567
2568
2569anyxml_arg_str: identifier_arg_str { $$.token = actual_type;
2570                                     $$.actual = actual;
2571                                     if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_ANYXML, sizeof(struct lys_node_anydata)))) {
2572                                       YYABORT;
2573                                     }
2574                                     data_node = actual;
2575                                     s = NULL;
2576                                     actual_type = ANYXML_KEYWORD;
2577                                   }
2578
2579anyxml_stmt: ANYXML_KEYWORD sep anyxml_arg_str anyxml_end
2580             { LOGDBG(LY_LDGYANG, "finished parsing anyxml statement \"%s\"", data_node->name);
2581               actual_type = $3.token;
2582               actual = $3.actual;
2583               data_node = $3.actual;
2584             }
2585
2586anydata_arg_str: identifier_arg_str { $$.token = actual_type;
2587                                      $$.actual = actual;
2588                                      if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_ANYDATA, sizeof(struct lys_node_anydata)))) {
2589                                        YYABORT;
2590                                      }
2591                                      data_node = actual;
2592                                      s = NULL;
2593                                      actual_type = ANYDATA_KEYWORD;
2594                                    }
2595
2596anydata_stmt: ANYDATA_KEYWORD sep anydata_arg_str anyxml_end
2597              { LOGDBG(LY_LDGYANG, "finished parsing anydata statement \"%s\"", data_node->name);
2598                actual_type = $3.token;
2599                actual = $3.actual;
2600                data_node = $3.actual;
2601              }
2602
2603anyxml_end: ';'
2604  |  '{' stmtsep
2605         anyxml_opt_stmt
2606     '}' { void *tmp;
2607
2608           if ($3.node.ptr_anydata->iffeature_size) {
2609             tmp = realloc($3.node.ptr_anydata->iffeature, $3.node.ptr_anydata->iffeature_size * sizeof *$3.node.ptr_anydata->iffeature);
2610             if (!tmp) {
2611               LOGMEM(trg->ctx);
2612               YYABORT;
2613             }
2614             $3.node.ptr_anydata->iffeature = tmp;
2615           }
2616
2617           if ($3.node.ptr_anydata->must_size) {
2618             tmp = realloc($3.node.ptr_anydata->must, $3.node.ptr_anydata->must_size * sizeof *$3.node.ptr_anydata->must);
2619             if (!tmp) {
2620               LOGMEM(trg->ctx);
2621               YYABORT;
2622             }
2623             $3.node.ptr_anydata->must = tmp;
2624           }
2625         }
2626
2627anyxml_opt_stmt: @EMPTYDIR@ { $$.node.ptr_anydata = actual;
2628                              $$.node.flag = actual_type;
2629                            }
2630  |  anyxml_opt_stmt when_stmt stmtsep
2631  |  anyxml_opt_stmt if_feature_stmt stmtsep
2632  |  anyxml_opt_stmt must_stmt stmtsep
2633  |  anyxml_opt_stmt config_stmt { if ($1.node.ptr_anydata->flags & LYS_CONFIG_MASK) {
2634                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_anydata, "config",
2635                                            ($1.node.flag == ANYXML_KEYWORD) ? "anyxml" : "anydata");
2636                                     YYABORT;
2637                                   }
2638                                   $1.node.ptr_anydata->flags |= $2;
2639                                 }
2640  |  anyxml_opt_stmt mandatory_stmt { if ($1.node.ptr_anydata->flags & LYS_MAND_MASK) {
2641                                        LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_anydata, "mandatory",
2642                                               ($1.node.flag == ANYXML_KEYWORD) ? "anyxml" : "anydata");
2643                                        YYABORT;
2644                                      }
2645                                      $1.node.ptr_anydata->flags |= $2;
2646                                    }
2647  |  anyxml_opt_stmt status_stmt { if ($1.node.ptr_anydata->flags & LYS_STATUS_MASK) {
2648                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_anydata, "status",
2649                                            ($1.node.flag == ANYXML_KEYWORD) ? "anyxml" : "anydata");
2650                                     YYABORT;
2651                                   }
2652                                   $1.node.ptr_anydata->flags |= $2;
2653                                 }
2654  |  anyxml_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_anydata, s, ($1.node.flag == ANYXML_KEYWORD) ? "anyxml" : "anydata", NODE_PRINT)) {
2655                                          YYABORT;
2656                                        }
2657                                        s = NULL;
2658                                      }
2659  |  anyxml_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_anydata, s, ($1.node.flag == ANYXML_KEYWORD) ? "anyxml" : "anydata", NODE_PRINT)) {
2660                                        YYABORT;
2661                                      }
2662                                      s = NULL;
2663                                    }
2664
2665uses_arg_str: identifier_ref_arg_str { $$.token = actual_type;
2666                                       $$.actual = actual;
2667                                       if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_USES, sizeof(struct lys_node_uses)))) {
2668                                         YYABORT;
2669                                       }
2670                                       data_node = actual;
2671                                       s = NULL;
2672                                       actual_type = USES_KEYWORD;
2673                                     }
2674
2675uses_stmt: USES_KEYWORD sep uses_arg_str uses_end
2676           { LOGDBG(LY_LDGYANG, "finished parsing uses statement \"%s\"", data_node->name);
2677             actual_type = $3.token;
2678             actual = $3.actual;
2679             data_node = $3.actual;
2680           }
2681
2682uses_end: ';'
2683  |  '{' stmtsep
2684         uses_opt_stmt
2685     '}' { void *tmp;
2686
2687           if ($3.uses->iffeature_size) {
2688             tmp = realloc($3.uses->iffeature, $3.uses->iffeature_size * sizeof *$3.uses->iffeature);
2689             if (!tmp) {
2690               LOGMEM(trg->ctx);
2691               YYABORT;
2692             }
2693             $3.uses->iffeature = tmp;
2694           }
2695
2696           if ($3.uses->refine_size) {
2697             tmp = realloc($3.uses->refine, $3.uses->refine_size * sizeof *$3.uses->refine);
2698             if (!tmp) {
2699               LOGMEM(trg->ctx);
2700               YYABORT;
2701             }
2702             $3.uses->refine = tmp;
2703           }
2704
2705           if ($3.uses->augment_size) {
2706             tmp = realloc($3.uses->augment, $3.uses->augment_size * sizeof *$3.uses->augment);
2707             if (!tmp) {
2708               LOGMEM(trg->ctx);
2709               YYABORT;
2710             }
2711             $3.uses->augment = tmp;
2712           }
2713         }
2714
2715uses_opt_stmt: @EMPTYDIR@ { $$.uses = actual; }
2716  |  uses_opt_stmt when_stmt stmtsep
2717  |  uses_opt_stmt if_feature_stmt stmtsep
2718  |  uses_opt_stmt status_stmt { if ($1.uses->flags & LYS_STATUS_MASK) {
2719                                   LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.uses, "status", "uses");
2720                                   YYABORT;
2721                                 }
2722                                 $1.uses->flags |= $2;
2723                               }
2724  |  uses_opt_stmt description_stmt { if (yang_read_description(trg, $1.uses, s, "uses", NODE_PRINT)) {
2725                                        YYABORT;
2726                                      }
2727                                      s = NULL;
2728                                    }
2729  |  uses_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.uses, s, "uses", NODE_PRINT)) {
2730                                      YYABORT;
2731                                    }
2732                                    s = NULL;
2733                                  }
2734  |  uses_opt_stmt refine_stmt stmtsep
2735  |  uses_opt_stmt uses_augment_stmt stmtsep
2736
2737refine_args_str: descendant_schema_nodeid optsep
2738  | string_1
2739
2740refine_arg_str: refine_args_str { $$.token = actual_type;
2741                                  $$.actual = actual;
2742                                  YANG_ADDELEM(((struct lys_node_uses *)actual)->refine,
2743                                               ((struct lys_node_uses *)actual)->refine_size, "refines");
2744                                  ((struct lys_refine *)actual)->target_name = transform_schema2json(trg, s);
2745                                  free(s);
2746                                  s = NULL;
2747                                  if (!((struct lys_refine *)actual)->target_name) {
2748                                    YYABORT;
2749                                  }
2750                                  actual_type = REFINE_KEYWORD;
2751                                }
2752
2753refine_stmt: REFINE_KEYWORD sep refine_arg_str refine_end
2754             { actual_type = $3.token;
2755               actual = $3.actual;
2756             }
2757
2758refine_end: ';'
2759  |  '{' stmtsep
2760         refine_body_opt_stmts
2761     '}' { void *tmp;
2762
2763           if ($3.refine->iffeature_size) {
2764             tmp = realloc($3.refine->iffeature, $3.refine->iffeature_size * sizeof *$3.refine->iffeature);
2765             if (!tmp) {
2766               LOGMEM(trg->ctx);
2767               YYABORT;
2768             }
2769             $3.refine->iffeature = tmp;
2770           }
2771
2772           if ($3.refine->must_size) {
2773             tmp = realloc($3.refine->must, $3.refine->must_size * sizeof *$3.refine->must);
2774             if (!tmp) {
2775               LOGMEM(trg->ctx);
2776               YYABORT;
2777             }
2778             $3.refine->must = tmp;
2779           }
2780
2781           if ($3.refine->dflt_size) {
2782             tmp = realloc($3.refine->dflt, $3.refine->dflt_size * sizeof *$3.refine->dflt);
2783             if (!tmp) {
2784               LOGMEM(trg->ctx);
2785               YYABORT;
2786             }
2787             $3.refine->dflt = tmp;
2788           }
2789         }
2790
2791refine_body_opt_stmts: @EMPTYDIR@ { $$.refine = actual;
2792                                    actual_type = REFINE_KEYWORD;
2793                                  }
2794  |  refine_body_opt_stmts must_stmt stmtsep { actual = $1.refine;
2795                                               actual_type = REFINE_KEYWORD;
2796                                               if ($1.refine->target_type) {
2797                                                 if ($1.refine->target_type & (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA)) {
2798                                                   $1.refine->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA);
2799                                                 } else {
2800                                                   LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "must", "refine");
2801                                                   LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2802                                                   YYABORT;
2803                                                 }
2804                                               } else {
2805                                                 $1.refine->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYDATA;
2806                                               }
2807                                             }
2808  |  refine_body_opt_stmts if_feature_stmt
2809     stmtsep { /* leaf, leaf-list, list, container, choice, case, anydata or anyxml */
2810               /* check possibility of statements combination */
2811               if ($1.refine->target_type) {
2812                 if ($1.refine->target_type & (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA)) {
2813                   $1.refine->target_type &= (LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA);
2814                 } else {
2815                   free(s);
2816                   LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "if-feature", "refine");
2817                   LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2818                   YYABORT;
2819                 }
2820               } else {
2821                 $1.refine->target_type = LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_CHOICE | LYS_CASE | LYS_ANYDATA;
2822               }
2823             }
2824  |  refine_body_opt_stmts presence_stmt { if ($1.refine->target_type) {
2825                                             if ($1.refine->target_type & LYS_CONTAINER) {
2826                                               if ($1.refine->mod.presence) {
2827                                                 LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "presence", "refine");
2828                                                 free(s);
2829                                                 YYABORT;
2830                                               }
2831                                               $1.refine->target_type = LYS_CONTAINER;
2832                                               $1.refine->mod.presence = lydict_insert_zc(trg->ctx, s);
2833                                             } else {
2834                                               free(s);
2835                                               LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "presence", "refine");
2836                                               LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2837                                               YYABORT;
2838                                             }
2839                                           } else {
2840                                             $1.refine->target_type = LYS_CONTAINER;
2841                                             $1.refine->mod.presence = lydict_insert_zc(trg->ctx, s);
2842                                           }
2843                                           s = NULL;
2844                                           $$ = $1;
2845                                         }
2846  |  refine_body_opt_stmts default_stmt { int i;
2847
2848                                          if ($1.refine->dflt_size) {
2849                                            if (trg->version < 2) {
2850                                              LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "refine");
2851                                              YYABORT;
2852                                            }
2853                                            if ($1.refine->target_type & LYS_LEAFLIST) {
2854                                              $1.refine->target_type = LYS_LEAFLIST;
2855                                            } else {
2856                                              free(s);
2857                                              LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "default", "refine");
2858                                              LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2859                                              YYABORT;
2860                                            }
2861                                          } else {
2862                                            if ($1.refine->target_type) {
2863                                              if (trg->version < 2 && ($1.refine->target_type & (LYS_LEAF | LYS_CHOICE))) {
2864                                                $1.refine->target_type &= (LYS_LEAF | LYS_CHOICE);
2865                                              } if (trg->version > 1 && ($1.refine->target_type & (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE))) {
2866                                                /* YANG 1.1 */
2867                                                $1.refine->target_type &= (LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE);
2868                                              } else {
2869                                                free(s);
2870                                                LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "default", "refine");
2871                                                LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2872                                                YYABORT;
2873                                              }
2874                                            } else {
2875                                              if (trg->version < 2) {
2876                                                $1.refine->target_type = LYS_LEAF | LYS_CHOICE;
2877                                              } else {
2878                                                /* YANG 1.1 */
2879                                                $1.refine->target_type = LYS_LEAF | LYS_LEAFLIST | LYS_CHOICE;
2880                                              }
2881                                            }
2882                                          }
2883                                          /* check for duplicity */
2884                                          for (i = 0; i < $1.refine->dflt_size; ++i) {
2885                                              if (ly_strequal($1.refine->dflt[i], s, 0)) {
2886                                                  LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "default");
2887                                                  LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Duplicated default value \"%s\".", s);
2888                                                  YYABORT;
2889                                              }
2890                                          }
2891                                          YANG_ADDELEM($1.refine->dflt, $1.refine->dflt_size, "defaults");
2892                                          *((const char **)actual) = lydict_insert_zc(trg->ctx, s);
2893                                          actual = $1.refine;
2894                                          s = NULL;
2895                                          $$ = $1;
2896                                        }
2897  |  refine_body_opt_stmts config_stmt { if ($1.refine->target_type) {
2898                                           if ($1.refine->target_type & (LYS_LEAF | LYS_CHOICE | LYS_LIST | LYS_CONTAINER | LYS_LEAFLIST)) {
2899                                             $1.refine->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_LIST | LYS_CONTAINER | LYS_LEAFLIST);
2900                                             if ($1.refine->flags & LYS_CONFIG_MASK) {
2901                                               LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "refine");
2902                                               YYABORT;
2903                                             }
2904                                             $1.refine->flags |= $2;
2905                                           } else {
2906                                             LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "config", "refine");
2907                                             LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2908                                             YYABORT;
2909                                           }
2910                                         } else {
2911                                           $1.refine->target_type = LYS_LEAF | LYS_CHOICE | LYS_LIST | LYS_CONTAINER | LYS_LEAFLIST;
2912                                           $1.refine->flags |= $2;
2913                                         }
2914                                         $$ = $1;
2915                                       }
2916  |  refine_body_opt_stmts mandatory_stmt { if ($1.refine->target_type) {
2917                                              if ($1.refine->target_type & (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA)) {
2918                                                $1.refine->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYDATA);
2919                                                if ($1.refine->flags & LYS_MAND_MASK) {
2920                                                  LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "refine");
2921                                                  YYABORT;
2922                                                }
2923                                                $1.refine->flags |= $2;
2924                                              } else {
2925                                                LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "refine");
2926                                                LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2927                                                YYABORT;
2928                                              }
2929                                            } else {
2930                                              $1.refine->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYDATA;
2931                                              $1.refine->flags |= $2;
2932                                            }
2933                                            $$ = $1;
2934                                          }
2935  |  refine_body_opt_stmts min_elements_stmt { if ($1.refine->target_type) {
2936                                                 if ($1.refine->target_type & (LYS_LIST | LYS_LEAFLIST)) {
2937                                                   $1.refine->target_type &= (LYS_LIST | LYS_LEAFLIST);
2938                                                   if ($1.refine->flags & LYS_RFN_MINSET) {
2939                                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "min-elements", "refine");
2940                                                     YYABORT;
2941                                                   }
2942                                                   $1.refine->flags |= LYS_RFN_MINSET;
2943                                                   $1.refine->mod.list.min = $2;
2944                                                 } else {
2945                                                   LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "refine");
2946                                                   LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2947                                                   YYABORT;
2948                                                 }
2949                                               } else {
2950                                                 $1.refine->target_type = LYS_LIST | LYS_LEAFLIST;
2951                                                 $1.refine->flags |= LYS_RFN_MINSET;
2952                                                 $1.refine->mod.list.min = $2;
2953                                               }
2954                                               $$ = $1;
2955                                             }
2956  |  refine_body_opt_stmts max_elements_stmt { if ($1.refine->target_type) {
2957                                                 if ($1.refine->target_type & (LYS_LIST | LYS_LEAFLIST)) {
2958                                                   $1.refine->target_type &= (LYS_LIST | LYS_LEAFLIST);
2959                                                   if ($1.refine->flags & LYS_RFN_MAXSET) {
2960                                                     LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "max-elements", "refine");
2961                                                     YYABORT;
2962                                                   }
2963                                                   $1.refine->flags |= LYS_RFN_MAXSET;
2964                                                   $1.refine->mod.list.max = $2;
2965                                                 } else {
2966                                                   LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "max-elements", "refine");
2967                                                   LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements.");
2968                                                   YYABORT;
2969                                                 }
2970                                               } else {
2971                                                 $1.refine->target_type = LYS_LIST | LYS_LEAFLIST;
2972                                                 $1.refine->flags |= LYS_RFN_MAXSET;
2973                                                 $1.refine->mod.list.max = $2;
2974                                               }
2975                                               $$ = $1;
2976                                             }
2977  |  refine_body_opt_stmts description_stmt { if (yang_read_description(trg, $1.refine, s, "refine", NODE)) {
2978                                                YYABORT;
2979                                              }
2980                                              s = NULL;
2981                                            }
2982  |  refine_body_opt_stmts reference_stmt { if (yang_read_reference(trg, $1.refine, s, "refine", NODE)) {
2983                                              YYABORT;
2984                                            }
2985                                            s = NULL;
2986                                          }
2987
2988uses_augment_arg_str: descendant_schema_nodeid optsep
2989  |  string_1
2990  ;
2991
2992uses_augment_arg: uses_augment_arg_str { void *parent;
2993
2994                                         $$.token = actual_type;
2995                                         $$.actual = actual;
2996                                         parent = actual;
2997                                         YANG_ADDELEM(((struct lys_node_uses *)actual)->augment,
2998                                                      ((struct lys_node_uses *)actual)->augment_size, "augments");
2999                                         if (yang_read_augment(trg, parent, actual, s)) {
3000                                           YYABORT;
3001                                         }
3002                                         data_node = actual;
3003                                         s = NULL;
3004                                         actual_type = AUGMENT_KEYWORD;
3005                                       }
3006
3007uses_augment_stmt: AUGMENT_KEYWORD sep uses_augment_arg
3008                   '{' stmtsep
3009                       augment_opt_stmt
3010                   '}' { LOGDBG(LY_LDGYANG, "finished parsing augment statement \"%s\"", data_node->name);
3011                         actual_type = $3.token;
3012                         actual = $3.actual;
3013                         data_node = $3.actual;
3014                       }
3015
3016augment_arg_str: absolute_schema_nodeids optsep
3017  |  string_1
3018
3019augment_arg: augment_arg_str { $$.token = actual_type;
3020                               $$.actual = actual;
3021                               YANG_ADDELEM(trg->augment, trg->augment_size, "augments");
3022                               if (yang_read_augment(trg, NULL, actual, s)) {
3023                                 YYABORT;
3024                               }
3025                               data_node = actual;
3026                               s = NULL;
3027                               actual_type = AUGMENT_KEYWORD;
3028                             }
3029
3030augment_stmt: AUGMENT_KEYWORD sep augment_arg
3031              '{' stmtsep
3032                  augment_opt_stmt
3033              '}' { LOGDBG(LY_LDGYANG, "finished parsing augment statement \"%s\"", data_node->name);
3034                    actual_type = $3.token;
3035                    actual = $3.actual;
3036                    data_node = $3.actual;
3037                  }
3038
3039augment_opt_stmt: @EMPTYDIR@ { $$.augment = actual; }
3040  |  augment_opt_stmt when_stmt stmtsep
3041  |  augment_opt_stmt if_feature_stmt stmtsep
3042  |  augment_opt_stmt status_stmt { if ($1.augment->flags & LYS_STATUS_MASK) {
3043                                      LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.augment, "status", "augment");
3044                                      YYABORT;
3045                                    }
3046                                    $1.augment->flags |= $2;
3047                                  }
3048  |  augment_opt_stmt description_stmt { if (yang_read_description(trg, $1.augment, s, "augment", NODE_PRINT)) {
3049                                           YYABORT;
3050                                         }
3051                                         s = NULL;
3052                                       }
3053  |  augment_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.augment, s, "augment", NODE_PRINT)) {
3054                                         YYABORT;
3055                                       }
3056                                       s = NULL;
3057                                     }
3058  |  augment_opt_stmt data_def_stmt stmtsep
3059  |  augment_opt_stmt action_stmt stmtsep
3060  |  augment_opt_stmt notification_stmt stmtsep { if (trg->version < 2) {
3061                                                    LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, $1.augment, "notification");
3062                                                    YYABORT;
3063                                                  }
3064                                                }
3065  |  augment_opt_stmt case_stmt stmtsep
3066
3067action_arg_str: identifier_arg_str { if (param->module->version != 2) {
3068                                       LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, actual, "action");
3069                                       free(s);
3070                                       YYABORT;
3071                                     }
3072                                     $$.token = actual_type;
3073                                     $$.actual = actual;
3074                                     if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_ACTION, sizeof(struct lys_node_rpc_action)))) {
3075                                       YYABORT;
3076                                     }
3077                                     data_node = actual;
3078                                     s = NULL;
3079                                     actual_type = ACTION_KEYWORD;
3080                                   }
3081
3082action_stmt: ACTION_KEYWORD sep action_arg_str rpc_end
3083             { LOGDBG(LY_LDGYANG, "finished parsing action statement \"%s\"", data_node->name);
3084               actual_type = $3.token;
3085               actual = $3.actual;
3086               data_node = $3.actual;
3087             }
3088
3089rpc_arg_str: identifier_arg_str { $$.token = actual_type;
3090                                  $$.actual = actual;
3091                                  if (!(actual = yang_read_node(trg, NULL, param->node, s, LYS_RPC, sizeof(struct lys_node_rpc_action)))) {
3092                                    YYABORT;
3093                                  }
3094                                  data_node = actual;
3095                                  s = NULL;
3096                                  actual_type = RPC_KEYWORD;
3097                                }
3098
3099rpc_stmt: RPC_KEYWORD sep rpc_arg_str rpc_end
3100          { LOGDBG(LY_LDGYANG, "finished parsing rpc statement \"%s\"", data_node->name);
3101            actual_type = $3.token;
3102            actual = $3.actual;
3103            data_node = $3.actual;
3104          }
3105
3106rpc_end: ';'
3107  |  '{' stmtsep
3108         rpc_opt_stmt
3109      '}' { void *tmp;
3110
3111            if ($3.node.ptr_rpc->iffeature_size) {
3112              tmp = realloc($3.node.ptr_rpc->iffeature, $3.node.ptr_rpc->iffeature_size * sizeof *$3.node.ptr_rpc->iffeature);
3113              if (!tmp) {
3114                LOGMEM(trg->ctx);
3115                YYABORT;
3116              }
3117              $3.node.ptr_rpc->iffeature = tmp;
3118            }
3119
3120            if ($3.node.ptr_rpc->tpdf_size) {
3121              tmp = realloc($3.node.ptr_rpc->tpdf, $3.node.ptr_rpc->tpdf_size * sizeof *$3.node.ptr_rpc->tpdf);
3122              if (!tmp) {
3123                LOGMEM(trg->ctx);
3124                YYABORT;
3125              }
3126              $3.node.ptr_rpc->tpdf = tmp;
3127            }
3128          }
3129
3130
3131rpc_opt_stmt: @EMPTYDIR@ { $$.node.ptr_rpc = actual;
3132                           $$.node.flag = 0;
3133                         }
3134  |  rpc_opt_stmt if_feature_stmt stmtsep
3135  |  rpc_opt_stmt status_stmt { if ($1.node.ptr_rpc->flags & LYS_STATUS_MASK) {
3136                                  LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_rpc, "status", "rpc");
3137                                  YYABORT;
3138                                }
3139                                $1.node.ptr_rpc->flags |= $2;
3140                             }
3141  |  rpc_opt_stmt description_stmt { if (yang_read_description(trg, $1.node.ptr_rpc, s, "rpc", NODE_PRINT)) {
3142                                       YYABORT;
3143                                     }
3144                                     s = NULL;
3145                                   }
3146  |  rpc_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.node.ptr_rpc, s, "rpc", NODE_PRINT)) {
3147                                     YYABORT;
3148                                   }
3149                                   s = NULL;
3150                                 }
3151  |  rpc_opt_stmt typedef_stmt stmtsep
3152  |  rpc_opt_stmt grouping_stmt stmtsep
3153  |  rpc_opt_stmt input_stmt stmtsep { if ($1.node.flag & LYS_RPC_INPUT) {
3154                                         LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_rpc, "input", "rpc");
3155                                         YYABORT;
3156                                       }
3157                                       $1.node.flag |= LYS_RPC_INPUT;
3158                                       $$ = $1;
3159                                     }
3160  |  rpc_opt_stmt output_stmt stmtsep { if ($1.node.flag & LYS_RPC_OUTPUT) {
3161                                          LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_rpc, "output", "rpc");
3162                                          YYABORT;
3163                                        }
3164                                        $1.node.flag |= LYS_RPC_OUTPUT;
3165                                        $$ = $1;
3166                                      }
3167
3168input_arg: INPUT_KEYWORD optsep { $$.token = actual_type;
3169                                  $$.actual = actual;
3170                                  s = strdup("input");
3171                                  if (!s) {
3172                                    LOGMEM(trg->ctx);
3173                                    YYABORT;
3174                                  }
3175                                  if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_INPUT, sizeof(struct lys_node_inout)))) {
3176                                    YYABORT;
3177                                  }
3178                                  data_node = actual;
3179                                  s = NULL;
3180                                  actual_type = INPUT_KEYWORD;
3181                                }
3182
3183input_stmt: input_arg
3184            '{' stmtsep
3185                input_output_opt_stmt
3186            '}' { void *tmp;
3187                  struct lys_node_inout *input = actual;
3188
3189                  if (input->must_size) {
3190                    tmp = realloc(input->must, input->must_size * sizeof *input->must);
3191                    if (!tmp) {
3192                      LOGMEM(trg->ctx);
3193                      YYABORT;
3194                    }
3195                    input->must = tmp;
3196                  }
3197
3198                  if (input->tpdf_size) {
3199                    tmp = realloc(input->tpdf, input->tpdf_size * sizeof *input->tpdf);
3200                    if (!tmp) {
3201                      LOGMEM(trg->ctx);
3202                      YYABORT;
3203                    }
3204                    input->tpdf = tmp;
3205                  }
3206
3207                  LOGDBG(LY_LDGYANG, "finished parsing input statement \"%s\"", data_node->name);
3208                  actual_type = $1.token;
3209                  actual = $1.actual;
3210                  data_node = $1.actual;
3211                }
3212
3213input_output_opt_stmt: @EMPTYDIR@
3214  |  input_output_opt_stmt must_stmt stmtsep
3215  |  input_output_opt_stmt typedef_stmt stmtsep
3216  |  input_output_opt_stmt grouping_stmt stmtsep
3217  |  input_output_opt_stmt data_def_stmt stmtsep
3218
3219output_arg: OUTPUT_KEYWORD optsep { $$.token = actual_type;
3220                                    $$.actual = actual;
3221                                    s = strdup("output");
3222                                    if (!s) {
3223                                      LOGMEM(trg->ctx);
3224                                      YYABORT;
3225                                    }
3226                                    if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_OUTPUT, sizeof(struct lys_node_inout)))) {
3227                                      YYABORT;
3228                                    }
3229                                    data_node = actual;
3230                                    s = NULL;
3231                                    actual_type = OUTPUT_KEYWORD;
3232                                  }
3233
3234output_stmt: output_arg
3235             '{' stmtsep
3236                 input_output_opt_stmt
3237             '}' { void *tmp;
3238                   struct lys_node_inout *output = actual;
3239
3240                   if (output->must_size) {
3241                     tmp = realloc(output->must, output->must_size * sizeof *output->must);
3242                     if (!tmp) {
3243                       LOGMEM(trg->ctx);
3244                       YYABORT;
3245                     }
3246                     output->must = tmp;
3247                   }
3248
3249                   if (output->tpdf_size) {
3250                     tmp = realloc(output->tpdf, output->tpdf_size * sizeof *output->tpdf);
3251                     if (!tmp) {
3252                       LOGMEM(trg->ctx);
3253                       YYABORT;
3254                     }
3255                     output->tpdf = tmp;
3256                   }
3257
3258                   LOGDBG(LY_LDGYANG, "finished parsing output statement \"%s\"", data_node->name);
3259                   actual_type = $1.token;
3260                   actual = $1.actual;
3261                   data_node = $1.actual;
3262                 }
3263
3264notification_arg_str: identifier_arg_str { $$.token = actual_type;
3265                                           $$.actual = actual;
3266                                           if (!(actual = yang_read_node(trg, actual, param->node, s, LYS_NOTIF, sizeof(struct lys_node_notif)))) {
3267                                             YYABORT;
3268                                           }
3269                                           data_node = actual;
3270                                           s = NULL;
3271                                           actual_type = NOTIFICATION_KEYWORD;
3272                                         }
3273
3274notification_stmt: NOTIFICATION_KEYWORD sep notification_arg_str notification_end
3275                   { LOGDBG(LY_LDGYANG, "finished parsing notification statement \"%s\"", data_node->name);
3276                     actual_type = $3.token;
3277                     actual = $3.actual;
3278                     data_node = $3.actual;
3279                   }
3280
3281notification_end: ';'
3282  |  '{' stmtsep
3283         notification_opt_stmt
3284      '}' { void *tmp;
3285
3286            if ($3.notif->must_size) {
3287              tmp = realloc($3.notif->must, $3.notif->must_size * sizeof *$3.notif->must);
3288              if (!tmp) {
3289                LOGMEM(trg->ctx);
3290                YYABORT;
3291              }
3292              $3.notif->must = tmp;
3293            }
3294
3295           if ($3.notif->iffeature_size) {
3296             tmp = realloc($3.notif->iffeature, $3.notif->iffeature_size * sizeof *$3.notif->iffeature);
3297             if (!tmp) {
3298               LOGMEM(trg->ctx);
3299               YYABORT;
3300             }
3301             $3.notif->iffeature = tmp;
3302           }
3303
3304           if ($3.notif->tpdf_size) {
3305             tmp = realloc($3.notif->tpdf, $3.notif->tpdf_size * sizeof *$3.notif->tpdf);
3306             if (!tmp) {
3307               LOGMEM(trg->ctx);
3308               YYABORT;
3309             }
3310             $3.notif->tpdf = tmp;
3311           }
3312          }
3313
3314notification_opt_stmt: @EMPTYDIR@ { $$.notif = actual; }
3315  |  notification_opt_stmt must_stmt stmtsep
3316  |  notification_opt_stmt if_feature_stmt stmtsep
3317  |  notification_opt_stmt status_stmt { if ($1.notif->flags & LYS_STATUS_MASK) {
3318                                           LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_LYS, $1.notif, "status", "notification");
3319                                           YYABORT;
3320                                         }
3321                                         $1.notif->flags |= $2;
3322                                       }
3323  |  notification_opt_stmt description_stmt { if (yang_read_description(trg, $1.notif, s, "notification", NODE_PRINT)) {
3324                                                YYABORT;
3325                                              }
3326                                              s = NULL;
3327                                            }
3328  |  notification_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.notif, s, "notification", NODE_PRINT)) {
3329                                              YYABORT;
3330                                            }
3331                                            s = NULL;
3332                                          }
3333  |  notification_opt_stmt typedef_stmt stmtsep
3334  |  notification_opt_stmt grouping_stmt stmtsep
3335  |  notification_opt_stmt data_def_stmt stmtsep
3336
3337deviation_arg: deviation_arg_str { $$.token = actual_type;
3338                                   $$.actual = actual;
3339                                   YANG_ADDELEM(trg->deviation, trg->deviation_size, "deviations");
3340                                   ((struct lys_deviation *)actual)->target_name = transform_schema2json(trg, s);
3341                                   free(s);
3342                                   if (!((struct lys_deviation *)actual)->target_name) {
3343                                     YYABORT;
3344                                   }
3345                                   s = NULL;
3346                                   actual_type = DEVIATION_KEYWORD;
3347                                 }
3348
3349deviation_stmt: DEVIATION_KEYWORD sep deviation_arg
3350                '{' stmtsep
3351                    deviation_opt_stmt
3352                '}' { void *tmp;
3353
3354                      if ($6->deviate_size) {
3355                        tmp = realloc($6->deviate, $6->deviate_size * sizeof *$6->deviate);
3356                        if (!tmp) {
3357                          LOGINT(trg->ctx);
3358                          YYABORT;
3359                        }
3360                        $6->deviate = tmp;
3361                      } else {
3362                        LOGVAL(trg->ctx, LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation");
3363                        YYABORT;
3364                      }
3365                      actual_type = $3.token;
3366                      actual = $3.actual;
3367                    }
3368
3369deviation_opt_stmt: @EMPTYDIR@ { $$ = actual; }
3370  |  deviation_opt_stmt description_stmt { if (yang_read_description(trg, $1, s, "deviation", NODE)) {
3371                                             YYABORT;
3372                                           }
3373                                           s = NULL;
3374                                           $$ = $1;
3375                                         }
3376  |  deviation_opt_stmt reference_stmt { if (yang_read_reference(trg, $1, s, "deviation", NODE)) {
3377                                           YYABORT;
3378                                         }
3379                                         s = NULL;
3380                                         $$ = $1;
3381                                       }
3382  |  deviation_opt_stmt DEVIATE_KEYWORD sep deviate_body_stmt stmtsep
3383
3384deviation_arg_str: absolute_schema_nodeids optsep
3385  | string_1
3386
3387deviate_body_stmt: deviate_not_supported_stmt
3388  |  deviate_stmts
3389
3390
3391deviate_not_supported: NOT_SUPPORTED_KEYWORD { $$.token = actual_type;
3392                                               $$.actual = actual;
3393                                               if (!(actual = yang_read_deviate_unsupported(trg->ctx, actual))) {
3394                                                 YYABORT;
3395                                               }
3396                                               actual_type = NOT_SUPPORTED_KEYWORD;
3397                                             }
3398
3399deviate_not_supported_stmt: deviate_not_supported optsep deviate_not_supported_end
3400                            { actual_type = $1.token;
3401                              actual = $1.actual;
3402                            }
3403
3404deviate_not_supported_end: ';'
3405  | '{' stmtsep '}'
3406
3407deviate_stmts: deviate_add_stmt
3408  |  deviate_replace_stmt
3409  |  deviate_delete_stmt
3410
3411deviate_add: ADD_KEYWORD { $$.token = actual_type;
3412                           $$.actual = actual;
3413                           if (!(actual = yang_read_deviate(trg->ctx, actual, LY_DEVIATE_ADD))) {
3414                             YYABORT;
3415                           }
3416                           actual_type = ADD_KEYWORD;
3417                         }
3418
3419deviate_add_stmt: deviate_add optsep deviate_add_end
3420                  { actual_type = $1.token;
3421                    actual = $1.actual;
3422                  }
3423
3424deviate_add_end: ';'
3425  |  '{' stmtsep
3426         deviate_add_opt_stmt
3427     '}' { void *tmp;
3428
3429           if ($3->must_size) {
3430             tmp = realloc($3->must, $3->must_size * sizeof *$3->must);
3431             if (!tmp) {
3432               LOGMEM(trg->ctx);
3433               YYABORT;
3434             }
3435             $3->must = tmp;
3436           }
3437
3438           if ($3->unique_size) {
3439             tmp = realloc($3->unique, $3->unique_size * sizeof *$3->unique);
3440             if (!tmp) {
3441               LOGMEM(trg->ctx);
3442               YYABORT;
3443             }
3444             $3->unique = tmp;
3445           }
3446
3447           if ($3->dflt_size) {
3448             tmp = realloc($3->dflt, $3->dflt_size * sizeof *$3->dflt);
3449             if (!tmp) {
3450               LOGMEM(trg->ctx);
3451               YYABORT;
3452             }
3453             $3->dflt = tmp;
3454           }
3455         }
3456
3457deviate_add_opt_stmt: @EMPTYDIR@ { $$ = actual; }
3458  |  deviate_add_opt_stmt units_stmt { if (yang_read_units(trg, actual, s, ADD_KEYWORD)) {
3459                                         YYABORT;
3460                                       }
3461                                       s = NULL;
3462                                       $$ = $1;
3463                                     }
3464  |  deviate_add_opt_stmt must_stmt stmtsep
3465  |  deviate_add_opt_stmt unique_stmt { YANG_ADDELEM($1->unique, $1->unique_size, "uniques");
3466                                        ((struct lys_unique *)actual)->expr = (const char **)s;
3467                                        s = NULL;
3468                                        actual = $1;
3469                                        $$= $1;
3470                                      }
3471  |  deviate_add_opt_stmt default_stmt { YANG_ADDELEM($1->dflt, $1->dflt_size, "defaults");
3472                                         *((const char **)actual) = lydict_insert_zc(trg->ctx, s);
3473                                         s = NULL;
3474                                         actual = $1;
3475                                         $$ = $1;
3476                                       }
3477  |  deviate_add_opt_stmt config_stmt { if ($1->flags & LYS_CONFIG_MASK) {
3478                                          LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
3479                                          YYABORT;
3480                                        }
3481                                        $1->flags = $2;
3482                                        $$ = $1;
3483                                      }
3484  |  deviate_add_opt_stmt mandatory_stmt { if ($1->flags & LYS_MAND_MASK) {
3485                                             LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
3486                                             YYABORT;
3487                                           }
3488                                           $1->flags = $2;
3489                                           $$ = $1;
3490                                         }
3491  |  deviate_add_opt_stmt min_elements_stmt { if ($1->min_set) {
3492                                                LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "min-elements", "deviation");
3493                                                YYABORT;
3494                                              }
3495                                              $1->min = $2;
3496                                              $1->min_set = 1;
3497                                              $$ =  $1;
3498                                            }
3499  |  deviate_add_opt_stmt max_elements_stmt { if ($1->max_set) {
3500                                                LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "max-elements", "deviation");
3501                                                YYABORT;
3502                                              }
3503                                              $1->max = $2;
3504                                              $1->max_set = 1;
3505                                              $$ =  $1;
3506                                            }
3507
3508deviate_delete: DELETE_KEYWORD { $$.token = actual_type;
3509                                 $$.actual = actual;
3510                                 if (!(actual = yang_read_deviate(trg->ctx, actual, LY_DEVIATE_DEL))) {
3511                                   YYABORT;
3512                                 }
3513                                 actual_type = DELETE_KEYWORD;
3514                               }
3515
3516deviate_delete_stmt: deviate_delete optsep deviate_delete_end
3517                     { actual_type = $1.token;
3518                       actual = $1.actual;
3519                     }
3520
3521deviate_delete_end: ';'
3522  |  '{' stmtsep
3523         deviate_delete_opt_stmt
3524      '}' { void *tmp;
3525
3526            if ($3->must_size) {
3527              tmp = realloc($3->must, $3->must_size * sizeof *$3->must);
3528              if (!tmp) {
3529                LOGMEM(trg->ctx);
3530                YYABORT;
3531              }
3532              $3->must = tmp;
3533            }
3534
3535            if ($3->unique_size) {
3536              tmp = realloc($3->unique, $3->unique_size * sizeof *$3->unique);
3537              if (!tmp) {
3538                LOGMEM(trg->ctx);
3539                YYABORT;
3540              }
3541              $3->unique = tmp;
3542            }
3543
3544            if ($3->dflt_size) {
3545              tmp = realloc($3->dflt, $3->dflt_size * sizeof *$3->dflt);
3546              if (!tmp) {
3547                LOGMEM(trg->ctx);
3548                YYABORT;
3549              }
3550              $3->dflt = tmp;
3551            }
3552          }
3553
3554deviate_delete_opt_stmt: @EMPTYDIR@ { $$ = actual; }
3555  |  deviate_delete_opt_stmt units_stmt { if (yang_read_units(trg, actual, s, DELETE_KEYWORD)) {
3556                                            YYABORT;
3557                                          }
3558                                          s = NULL;
3559                                          $$ = $1;
3560                                        }
3561  |  deviate_delete_opt_stmt must_stmt stmtsep
3562  |  deviate_delete_opt_stmt unique_stmt { YANG_ADDELEM($1->unique, $1->unique_size, "uniques");
3563                                           ((struct lys_unique *)actual)->expr = (const char **)s;
3564                                           s = NULL;
3565                                           actual = $1;
3566                                           $$ = $1;
3567                                         }
3568  |  deviate_delete_opt_stmt default_stmt { YANG_ADDELEM($1->dflt, $1->dflt_size, "defaults");
3569                                            *((const char **)actual) = lydict_insert_zc(trg->ctx, s);
3570                                            s = NULL;
3571                                            actual = $1;
3572                                            $$ = $1;
3573                                          }
3574
3575deviate_replace: REPLACE_KEYWORD { $$.token = actual_type;
3576                                   $$.actual = actual;
3577                                   if (!(actual = yang_read_deviate(trg->ctx, actual, LY_DEVIATE_RPL))) {
3578                                     YYABORT;
3579                                   }
3580                                   actual_type = REPLACE_KEYWORD;
3581                                 }
3582
3583deviate_replace_stmt: deviate_replace optsep deviate_replace_end
3584                      { actual_type = $1.token;
3585                        actual = $1.actual;
3586                      }
3587
3588deviate_replace_end: ';'
3589  |  '{' stmtsep
3590         deviate_replace_opt_stmt
3591     '}' { void *tmp;
3592
3593           if ($3->dflt_size) {
3594             tmp = realloc($3->dflt, $3->dflt_size * sizeof *$3->dflt);
3595             if (!tmp) {
3596               LOGMEM(trg->ctx);
3597               YYABORT;
3598             }
3599             $3->dflt = tmp;
3600           }
3601         }
3602
3603deviate_replace_opt_stmt: @EMPTYDIR@ { $$ = actual; }
3604  |  deviate_replace_opt_stmt type_stmt stmtsep
3605  |  deviate_replace_opt_stmt units_stmt { if (yang_read_units(trg, actual, s, DELETE_KEYWORD)) {
3606                                             YYABORT;
3607                                           }
3608                                           s = NULL;
3609                                           $$ = $1;
3610                                         }
3611  |  deviate_replace_opt_stmt default_stmt { YANG_ADDELEM($1->dflt, $1->dflt_size, "defaults");
3612                                             *((const char **)actual) = lydict_insert_zc(trg->ctx, s);
3613                                             s = NULL;
3614                                             actual = $1;
3615                                             $$ = $1;
3616                                           }
3617  |  deviate_replace_opt_stmt config_stmt { if ($1->flags & LYS_CONFIG_MASK) {
3618                                              LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "config", "deviate");
3619                                              YYABORT;
3620                                            }
3621                                            $1->flags = $2;
3622                                            $$ = $1;
3623                                          }
3624  |  deviate_replace_opt_stmt mandatory_stmt { if ($1->flags & LYS_MAND_MASK) {
3625                                                 LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "mandatory", "deviate");
3626                                                 YYABORT;
3627                                               }
3628                                               $1->flags = $2;
3629                                               $$ = $1;
3630                                             }
3631  |  deviate_replace_opt_stmt min_elements_stmt { if ($1->min_set) {
3632                                                    LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "min-elements", "deviation");
3633                                                    YYABORT;
3634                                                  }
3635                                                  $1->min = $2;
3636                                                  $1->min_set = 1;
3637                                                  $$ =  $1;
3638                                                }
3639  |  deviate_replace_opt_stmt max_elements_stmt { if ($1->max_set) {
3640                                                    LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "max-elements", "deviation");
3641                                                    YYABORT;
3642                                                  }
3643                                                  $1->max = $2;
3644                                                  $1->max_set = 1;
3645                                                  $$ =  $1;
3646                                                }
3647
3648when_arg_str: string  { $$.token = actual_type;
3649                        $$.actual = actual;
3650                        if (!(actual = yang_read_when(trg, actual, actual_type, s))) {
3651                          YYABORT;
3652                        }
3653                        s = NULL;
3654                        actual_type = WHEN_KEYWORD;
3655                      }
3656
3657when_stmt: WHEN_KEYWORD sep when_arg_str when_end
3658           { actual_type = $3.token;
3659             actual = $3.actual;
3660           }
3661
3662when_end: ';'
3663  |  '{' stmtsep
3664         when_opt_stmt
3665     '}'
3666
3667when_opt_stmt: @EMPTYDIR@
3668  |  when_opt_stmt description_stmt { if (yang_read_description(trg, actual, s, "when", NODE)) {
3669                                        YYABORT;
3670                                      }
3671                                      s = NULL;
3672                                    }
3673  |  when_opt_stmt reference_stmt { if (yang_read_reference(trg, actual, s, "when", NODE)) {
3674                                      YYABORT;
3675                                    }
3676                                    s = NULL;
3677                                  }
3678
3679config_arg: config_arg_str { $$ = $1;
3680                             backup_type = actual_type;
3681                             actual_type = CONFIG_KEYWORD;
3682                           }
3683
3684config_stmt: CONFIG_KEYWORD sep config_arg stmtend { $$ = $3; }
3685
3686config_arg_str: TRUE_KEYWORD optsep { $$ = LYS_CONFIG_W | LYS_CONFIG_SET; }
3687  |  FALSE_KEYWORD optsep { $$ = LYS_CONFIG_R | LYS_CONFIG_SET; }
3688  |  string_1 { if (!strcmp(s, "true")) {
3689                  $$ = LYS_CONFIG_W | LYS_CONFIG_SET;
3690                } else if (!strcmp(s, "false")) {
3691                  $$ = LYS_CONFIG_R | LYS_CONFIG_SET;
3692                } else {
3693                  LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "config");
3694                  free(s);
3695                  YYABORT;
3696                }
3697                free(s);
3698                s = NULL;
3699              }
3700
3701mandatory_arg: mandatory_arg_str { $$ = $1;
3702                                   backup_type = actual_type;
3703                                   actual_type = MANDATORY_KEYWORD;
3704                                 }
3705
3706mandatory_stmt: MANDATORY_KEYWORD sep mandatory_arg stmtend { $$ = $3; }
3707
3708mandatory_arg_str: TRUE_KEYWORD optsep { $$ = LYS_MAND_TRUE; }
3709  |  FALSE_KEYWORD optsep { $$ = LYS_MAND_FALSE; }
3710  |  string_1 { if (!strcmp(s, "true")) {
3711                  $$ = LYS_MAND_TRUE;
3712                } else if (!strcmp(s, "false")) {
3713                  $$ = LYS_MAND_FALSE;
3714                } else {
3715                  LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "mandatory");
3716                  free(s);
3717                  YYABORT;
3718                }
3719                free(s);
3720                s = NULL;
3721              }
3722
3723presence_arg: string { backup_type = actual_type;
3724                       actual_type = PRESENCE_KEYWORD;
3725                     }
3726
3727presence_stmt: PRESENCE_KEYWORD sep presence_arg stmtend
3728
3729min_value_arg: min_value_arg_str { $$ = $1;
3730                                   backup_type = actual_type;
3731                                   actual_type = MIN_ELEMENTS_KEYWORD;
3732                                 }
3733
3734min_elements_stmt: MIN_ELEMENTS_KEYWORD sep min_value_arg stmtend { $$ = $3; }
3735
3736min_value_arg_str: non_negative_integer_value optsep { $$ = $1; }
3737  |  string_1 { if (strlen(s) == 1 && s[0] == '0') {
3738                  $$ = 0;
3739                } else {
3740                  /* convert it to uint32_t */
3741                  uint64_t val;
3742                  char *endptr = NULL;
3743                  errno = 0;
3744
3745                  val = strtoul(s, &endptr, 10);
3746                  if (*endptr || s[0] == '-' || errno || val > UINT32_MAX) {
3747                      LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "min-elements");
3748                      free(s);
3749                      YYABORT;
3750                  }
3751                  $$ = (uint32_t) val;
3752                }
3753                free(s);
3754                s = NULL;
3755              }
3756
3757max_value_arg: max_value_arg_str { $$ = $1;
3758                                   backup_type = actual_type;
3759                                   actual_type = MAX_ELEMENTS_KEYWORD;
3760                                 }
3761
3762max_elements_stmt: MAX_ELEMENTS_KEYWORD sep max_value_arg stmtend { $$ = $3; }
3763
3764max_value_arg_str: UNBOUNDED_KEYWORD optsep { $$ = 0; }
3765  |  positive_integer_value optsep { $$ = $1; }
3766  |  string_1 { if (!strcmp(s, "unbounded")) {
3767                  $$ = 0;
3768                } else {
3769                  /* convert it to uint32_t */
3770                  uint64_t val;
3771                  char *endptr = NULL;
3772                  errno = 0;
3773
3774                  val = strtoul(s, &endptr, 10);
3775                  if (*endptr || s[0] == '-' || errno || val == 0 || val > UINT32_MAX) {
3776                      LOGVAL(trg->ctx, LYE_INARG, LY_VLOG_NONE, NULL, s, "max-elements");
3777                      free(s);
3778                      YYABORT;
3779                  }
3780                  $$ = (uint32_t) val;
3781                }
3782                free(s);
3783                s = NULL;
3784              }
3785
3786ordered_by_arg: ordered_by_arg_str { $$ = $1;
3787                                     backup_type = actual_type;
3788                                     actual_type = ORDERED_BY_KEYWORD;
3789                                   }
3790
3791ordered_by_stmt: ORDERED_BY_KEYWORD sep ordered_by_arg stmtend { $$ = $3; }
3792
3793ordered_by_arg_str: USER_KEYWORD optsep { $$ = LYS_USERORDERED; }
3794  |  SYSTEM_KEYWORD optsep { $$ = LYS_SYSTEMORDERED; }
3795  |  string_1 { if (!strcmp(s, "user")) {
3796                  $$ = LYS_USERORDERED;
3797                } else if (!strcmp(s, "system")) {
3798                  $$ = LYS_SYSTEMORDERED;
3799                } else {
3800                  free(s);
3801                  YYABORT;
3802                }
3803                free(s);
3804                s=NULL;
3805              }
3806
3807must_agr_str: string { $$.token = actual_type;
3808                       $$.actual = actual;
3809                       switch (actual_type) {
3810                       case CONTAINER_KEYWORD:
3811                         YANG_ADDELEM(((struct lys_node_container *)actual)->must,
3812                                     ((struct lys_node_container *)actual)->must_size, "musts");
3813                         break;
3814                       case ANYDATA_KEYWORD:
3815                       case ANYXML_KEYWORD:
3816                         YANG_ADDELEM(((struct lys_node_anydata *)actual)->must,
3817                                     ((struct lys_node_anydata *)actual)->must_size, "musts");
3818                         break;
3819                       case LEAF_KEYWORD:
3820                         YANG_ADDELEM(((struct lys_node_leaf *)actual)->must,
3821                                     ((struct lys_node_leaf *)actual)->must_size, "musts");
3822                         break;
3823                       case LEAF_LIST_KEYWORD:
3824                         YANG_ADDELEM(((struct lys_node_leaflist *)actual)->must,
3825                                     ((struct lys_node_leaflist *)actual)->must_size, "musts");
3826                         break;
3827                       case LIST_KEYWORD:
3828                         YANG_ADDELEM(((struct lys_node_list *)actual)->must,
3829                                     ((struct lys_node_list *)actual)->must_size, "musts");
3830                         break;
3831                       case REFINE_KEYWORD:
3832                         YANG_ADDELEM(((struct lys_refine *)actual)->must,
3833                                     ((struct lys_refine *)actual)->must_size, "musts");
3834                         break;
3835                       case ADD_KEYWORD:
3836                       case DELETE_KEYWORD:
3837                         YANG_ADDELEM(((struct lys_deviate *)actual)->must,
3838                                      ((struct lys_deviate *)actual)->must_size, "musts");
3839                         break;
3840                       case NOTIFICATION_KEYWORD:
3841                         if (trg->version < 2) {
3842                           free(s);
3843                           LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, actual, "must");
3844                           YYABORT;
3845                         }
3846                         YANG_ADDELEM(((struct lys_node_notif *)actual)->must,
3847                                     ((struct lys_node_notif *)actual)->must_size, "musts");
3848                         break;
3849                       case INPUT_KEYWORD:
3850                       case OUTPUT_KEYWORD:
3851                         if (trg->version < 2) {
3852                           free(s);
3853                           LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_LYS, actual, "must");
3854                           YYABORT;
3855                         }
3856                         YANG_ADDELEM(((struct lys_node_inout *)actual)->must,
3857                                     ((struct lys_node_inout *)actual)->must_size, "musts");
3858                         break;
3859                       case EXTENSION_INSTANCE:
3860                         /* must is already allocated */
3861                         break;
3862                       default:
3863                         free(s);
3864                         LOGINT(trg->ctx);
3865                         YYABORT;
3866                       }
3867                       ((struct lys_restr *)actual)->expr = transform_schema2json(trg, s);
3868                       free(s);
3869                       if (!((struct lys_restr *)actual)->expr) {
3870                         YYABORT;
3871                       }
3872                       s = NULL;
3873                       actual_type = MUST_KEYWORD;
3874                     }
3875
3876must_stmt: MUST_KEYWORD sep must_agr_str must_end
3877           { actual_type = $3.token;
3878             actual = $3.actual;
3879           }
3880
3881must_end: ';'
3882  |  '{' stmtsep
3883         message_opt_stmt
3884     '}'
3885
3886unique_arg: unique_arg_str { backup_type = actual_type;
3887                             actual_type = UNIQUE_KEYWORD;
3888                           }
3889
3890unique_stmt: UNIQUE_KEYWORD sep unique_arg stmtend
3891
3892unique_arg_str: descendant_schema_nodeid optsep
3893  |  string_1
3894
3895key_arg: key_arg_str { backup_type = actual_type;
3896                       actual_type = KEY_KEYWORD;
3897                     }
3898
3899key_stmt: KEY_KEYWORD sep key_arg stmtend;
3900
3901key_arg_str: node_identifier { s = strdup(yyget_text(scanner));
3902                               if (!s) {
3903                                 LOGMEM(trg->ctx);
3904                                 YYABORT;
3905                               }
3906                             }
3907             optsep
3908  |  string_1
3909  ;
3910
3911range_arg_str: string { $$.token = actual_type;
3912                        $$.actual = actual;
3913                        if (!(actual = yang_read_range(trg->ctx, actual, s, is_ext_instance))) {
3914                          YYABORT;
3915                        }
3916                        actual_type = RANGE_KEYWORD;
3917                        s = NULL;
3918                      }
3919
3920absolute_schema_nodeid: '/' node_identifier { if (s) {
3921                                                s = ly_realloc(s,strlen(s) + yyget_leng(scanner) + 2);
3922                                                if (!s) {
3923                                                  LOGMEM(trg->ctx);
3924                                                  YYABORT;
3925                                                }
3926                                                strcat(s,"/");
3927                                                strcat(s, yyget_text(scanner));
3928                                              } else {
3929                                                s = malloc(yyget_leng(scanner) + 2);
3930                                                if (!s) {
3931                                                  LOGMEM(trg->ctx);
3932                                                  YYABORT;
3933                                                }
3934                                                s[0]='/';
3935                                                memcpy(s + 1, yyget_text(scanner), yyget_leng(scanner) + 1);
3936                                              }
3937                                            }
3938
3939absolute_schema_nodeids: absolute_schema_nodeid absolute_schema_nodeid_opt;
3940
3941absolute_schema_nodeid_opt: @EMPTYDIR@
3942  |  absolute_schema_nodeid_opt absolute_schema_nodeid
3943  ;
3944
3945descendant_schema_nodeid: node_identifier { if (s) {
3946                                              s = ly_realloc(s,strlen(s) + yyget_leng(scanner) + 1);
3947                                              if (!s) {
3948                                                LOGMEM(trg->ctx);
3949                                                YYABORT;
3950                                              }
3951                                              strcat(s, yyget_text(scanner));
3952                                            } else {
3953                                              s = strdup(yyget_text(scanner));
3954                                              if (!s) {
3955                                                LOGMEM(trg->ctx);
3956                                                YYABORT;
3957                                              }
3958                                            }
3959                                          }
3960                          absolute_schema_nodeid_opt;
3961
3962path_arg_str: { tmp_s = yyget_text(scanner); } absolute_paths { s = strdup(tmp_s);
3963                                                                if (!s) {
3964                                                                  LOGMEM(trg->ctx);
3965                                                                  YYABORT;
3966                                                                }
3967                                                                s[strlen(s) - 1] = '\0';
3968                                                             }
3969  |  { tmp_s = yyget_text(scanner); } relative_path { s = strdup(tmp_s);
3970                                                      if (!s) {
3971                                                        LOGMEM(trg->ctx);
3972                                                        YYABORT;
3973                                                      }
3974                                                      s[strlen(s) - 1] = '\0';
3975                                                    }
3976  |  string_1
3977  ;
3978
3979absolute_path: '/' node_identifier path_predicate
3980
3981absolute_paths: absolute_path absolute_path_opt
3982
3983absolute_path_opt: @EMPTYDIR@
3984  |  absolute_path_opt absolute_path;
3985
3986relative_path: relative_path_part1 relative_path_part1_opt descendant_path
3987
3988relative_path_part1: DOUBLEDOT '/';
3989
3990relative_path_part1_opt: @EMPTYDIR@
3991  |  relative_path_part1_opt relative_path_part1;
3992
3993descendant_path: node_identifier descendant_path_opt
3994
3995descendant_path_opt: @EMPTYDIR@
3996  |  path_predicate absolute_paths;
3997
3998path_predicate: @EMPTYDIR@
3999  | path_predicate '[' whitespace_opt path_equality_expr ']'
4000
4001path_equality_expr: node_identifier whitespace_opt '=' whitespace_opt path_key_expr
4002
4003path_key_expr: current_function_invocation whitespace_opt '/' whitespace_opt
4004                     rel_path_keyexpr
4005
4006rel_path_keyexpr: rel_path_keyexpr_part1 rel_path_keyexpr_part1_opt
4007                    node_identifier rel_path_keyexpr_part2
4008
4009rel_path_keyexpr_part1: DOUBLEDOT whitespace_opt '/' whitespace_opt;
4010
4011rel_path_keyexpr_part1_opt: @EMPTYDIR@
4012  |  rel_path_keyexpr_part1_opt rel_path_keyexpr_part1;
4013
4014rel_path_keyexpr_part2: @EMPTYDIR@
4015  | rel_path_keyexpr_part2 whitespace_opt '/' whitespace_opt node_identifier;
4016
4017current_function_invocation: CURRENT_KEYWORD whitespace_opt '(' whitespace_opt ')'
4018
4019positive_integer_value: NON_NEGATIVE_INTEGER { /* convert it to uint32_t */
4020                                                unsigned long val;
4021
4022                                                val = strtoul(yyget_text(scanner), NULL, 10);
4023                                                if (val > UINT32_MAX) {
4024                                                    LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Converted number is very long.");
4025                                                    YYABORT;
4026                                                }
4027                                                $$ = (uint32_t) val;
4028                                             }
4029
4030non_negative_integer_value: ZERO { $$ = 0; }
4031  |  positive_integer_value { $$ = $1; }
4032  ;
4033
4034integer_value: ZERO { $$ = 0; }
4035  |  integer_value_convert { /* convert it to int32_t */
4036                             int64_t val;
4037
4038                             val = strtoll(yyget_text(scanner), NULL, 10);
4039                             if (val < INT32_MIN || val > INT32_MAX) {
4040                                 LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL,
4041                                        "The number is not in the correct range (INT32_MIN..INT32_MAX): \"%d\"",val);
4042                                 YYABORT;
4043                             }
4044                             $$ = (int32_t) val;
4045                           }
4046
4047integer_value_convert: INTEGER
4048  |  NON_NEGATIVE_INTEGER
4049
4050prefix_arg_str: string_1
4051  |  identifiers optsep;
4052
4053identifier_arg_str: identifiers optsep
4054  |  string_1 { if (lyp_check_identifier(trg->ctx, s, LY_IDENT_SIMPLE, trg, NULL)) {
4055                    free(s);
4056                    YYABORT;
4057                }
4058              }
4059
4060node_identifier: identifier
4061  |  IDENTIFIERPREFIX
4062  ;
4063
4064identifier_ref_arg_str: identifiers optsep
4065  | identifiers_ref optsep
4066  | string_1 { char *tmp;
4067
4068               if ((tmp = strchr(s, ':'))) {
4069                 *tmp = '\0';
4070                 /* check prefix */
4071                 if (lyp_check_identifier(trg->ctx, s, LY_IDENT_SIMPLE, trg, NULL)) {
4072                   free(s);
4073                   YYABORT;
4074                 }
4075                 /* check identifier */
4076                 if (lyp_check_identifier(trg->ctx, tmp + 1, LY_IDENT_SIMPLE, trg, NULL)) {
4077                   free(s);
4078                   YYABORT;
4079                 }
4080                 *tmp = ':';
4081               } else {
4082                 /* check identifier */
4083                 if (lyp_check_identifier(trg->ctx, s, LY_IDENT_SIMPLE, trg, NULL)) {
4084                   free(s);
4085                   YYABORT;
4086                 }
4087               }
4088             }
4089
4090stmtend: semicolom stmtsep { s = $1; }
4091  | curly_bracket_open stmtsep curly_bracket_close stmtsep { s = $1; }
4092
4093
4094semicolom: ';' { actual_type = backup_type;
4095                 backup_type = NODE;
4096                 $$ = s;
4097                 s = NULL;
4098               }
4099
4100curly_bracket_close: '}' { actual_type = backup_type;
4101                           backup_type = NODE;
4102                         }
4103
4104curly_bracket_open: '{' { $$ = s;
4105                          s = NULL;
4106                        }
4107
4108
4109stmtsep: @EMPTYDIR@
4110  | stmtsep sep_stmt
4111  | stmtsep unknown_statement
4112  ;
4113
4114unknown_statement: identifiers_ref string_opt unknown_statement_end
4115                   { actual_type = $2.token;
4116                     actual = $2.actual;
4117                   }
4118
4119string_opt: string_opt_part1 string_opt_part2 { $$.token = actual_type;
4120                                                $$.actual = actual;
4121                                                if (!(actual = yang_read_ext(trg, (actual) ? actual : trg, $1, s,
4122                                                                             actual_type, backup_type, is_ext_instance))) {
4123                                                  YYABORT;
4124                                                }
4125                                                s = NULL;
4126                                                actual_type = EXTENSION_INSTANCE;
4127                                              }
4128
4129string_opt_part1: optsep { $$ = s; s = NULL; }
4130
4131string_opt_part2: @EMPTYDIR@
4132  |  string
4133
4134unknown_string: @EMPTYDIR@
4135  |  sep unknown_string_part1
4136
4137unknown_string_part1: @EMPTYDIR@
4138  |  strings optsep
4139  |  STRING optsep unknown_string_part2
4140
4141unknown_string_part2: @EMPTYDIR@
4142  |  unknown_string_part2 '+' optsep STRING optsep
4143
4144unknown_statement_end: ';'
4145  |  '{' optsep unknown_statement2_opt '}'
4146
4147unknown_statement2_opt: @EMPTYDIR@
4148  |  unknown_statement2_opt unknown_statement2 optsep
4149
4150/* unknown_statement2 read yang statement or extension; yang statement is parsed later */
4151
4152unknown_statement2: unknown_statement
4153  |  unknown_statement2_yang_stmt unknown_string unknown_statement2_end
4154     {  struct yang_ext_substmt *substmt = ((struct lys_ext_instance *)actual)->parent;
4155        int32_t length = 0, old_length = 0;
4156        char *tmp_value;
4157
4158        if (!substmt) {
4159          substmt = calloc(1, sizeof *substmt);
4160          if (!substmt) {
4161            LOGMEM(trg->ctx);
4162            YYABORT;
4163          }
4164          ((struct lys_ext_instance *)actual)->parent = substmt;
4165        }
4166        length = strlen($1);
4167        old_length = (substmt->ext_substmt) ? strlen(substmt->ext_substmt) + 2 : 2;
4168        tmp_value = realloc(substmt->ext_substmt, old_length + length + 1);
4169        if (!tmp_value) {
4170          LOGMEM(trg->ctx);
4171          YYABORT;
4172        }
4173        substmt->ext_substmt = tmp_value;
4174        tmp_value += old_length - 2;
4175        memcpy(tmp_value, $1, length);
4176        tmp_value[length] = ' ';
4177        tmp_value[length + 1] = '\0';
4178        tmp_value[length + 2] = '\0';
4179      }
4180  |  unknown_statement2_module_stmt unknown_string unknown_statement2_end
4181     {  struct yang_ext_substmt *substmt = ((struct lys_ext_instance *)actual)->parent;
4182        int32_t length;
4183        char *tmp_value, **array;
4184        int i = 0;
4185
4186        if (!substmt) {
4187          substmt = calloc(1, sizeof *substmt);
4188          if (!substmt) {
4189            LOGMEM(trg->ctx);
4190            YYABORT;
4191          }
4192          ((struct lys_ext_instance *)actual)->parent = substmt;
4193        }
4194        length = strlen($1);
4195        if (!substmt->ext_modules) {
4196          array = malloc(2 * sizeof *substmt->ext_modules);
4197        } else {
4198          for (i = 0; substmt->ext_modules[i]; ++i);
4199          array = realloc(substmt->ext_modules, (i + 2) * sizeof *substmt->ext_modules);
4200        }
4201        if (!array) {
4202          LOGMEM(trg->ctx);
4203          YYABORT;
4204        }
4205        substmt->ext_modules = array;
4206        array[i + 1] = NULL;
4207        tmp_value = malloc(length + 2);
4208        if (!tmp_value) {
4209          LOGMEM(trg->ctx);
4210          YYABORT;
4211        }
4212        array[i] = tmp_value;
4213        memcpy(tmp_value, $1, length);
4214        tmp_value[length] = '\0';
4215        tmp_value[length + 1] = '\0';
4216      }
4217
4218unknown_statement2_end: ';'
4219  |  '{' optsep unknown_statement3_opt '}'
4220
4221unknown_statement2_yang_stmt: yang_stmt { $$ = yyget_text(scanner); }
4222
4223unknown_statement2_module_stmt: MODULE_KEYWORD { $$ = yyget_text(scanner); }
4224
4225unknown_statement3_opt: @EMPTYDIR@
4226  |  unknown_statement3_opt node_identifier unknown_string unknown_statement3_opt_end;
4227
4228unknown_statement3_opt_end: ';' optsep
4229  |  '{' optsep unknown_statement3_opt '}' optsep
4230
4231sep_stmt: WHITESPACE
4232  | EOL
4233  ;
4234
4235optsep: @EMPTYDIR@
4236  | optsep sep_stmt
4237  ;
4238
4239sep: sep_stmt optsep;
4240
4241whitespace_opt: @EMPTYDIR@
4242  | WHITESPACE
4243  ;
4244
4245string: strings { s = strdup(yyget_text(scanner));
4246                  if (!s) {
4247                    LOGMEM(trg->ctx);
4248                    YYABORT;
4249                  }
4250                }
4251        optsep
4252  |  string_1
4253
4254strings: STRINGS
4255  |  REVISION_DATE
4256  |  identifier
4257  |  IDENTIFIERPREFIX
4258  |  ZERO
4259  |  INTEGER
4260  |  NON_NEGATIVE_INTEGER
4261
4262identifier: MODULE_KEYWORD
4263  |  identifier1
4264  |  yang_stmt
4265
4266identifier1: IDENTIFIER
4267  |  CURRENT_KEYWORD
4268  |  DEPRECATED_KEYWORD
4269  |  FALSE_KEYWORD
4270  |  NOT_SUPPORTED_KEYWORD
4271  |  OBSOLETE_KEYWORD
4272  |  SYSTEM_KEYWORD
4273  |  TRUE_KEYWORD
4274  |  UNBOUNDED_KEYWORD
4275  |  USER_KEYWORD
4276
4277
4278yang_stmt: ANYXML_KEYWORD
4279  |  ARGUMENT_KEYWORD
4280  |  AUGMENT_KEYWORD
4281  |  BASE_KEYWORD
4282  |  BELONGS_TO_KEYWORD
4283  |  BIT_KEYWORD
4284  |  CASE_KEYWORD
4285  |  CHOICE_KEYWORD
4286  |  CONFIG_KEYWORD
4287  |  CONTACT_KEYWORD
4288  |  CONTAINER_KEYWORD
4289  |  DEFAULT_KEYWORD
4290  |  DESCRIPTION_KEYWORD
4291  |  ENUM_KEYWORD
4292  |  ERROR_APP_TAG_KEYWORD
4293  |  ERROR_MESSAGE_KEYWORD
4294  |  EXTENSION_KEYWORD
4295  |  DEVIATION_KEYWORD
4296  |  DEVIATE_KEYWORD
4297  |  FEATURE_KEYWORD
4298  |  FRACTION_DIGITS_KEYWORD
4299  |  GROUPING_KEYWORD
4300  |  IDENTITY_KEYWORD
4301  |  IF_FEATURE_KEYWORD
4302  |  IMPORT_KEYWORD
4303  |  INCLUDE_KEYWORD
4304  |  INPUT_KEYWORD
4305  |  KEY_KEYWORD
4306  |  LEAF_KEYWORD
4307  |  LEAF_LIST_KEYWORD
4308  |  LENGTH_KEYWORD
4309  |  LIST_KEYWORD
4310  |  MANDATORY_KEYWORD
4311  |  MAX_ELEMENTS_KEYWORD
4312  |  MIN_ELEMENTS_KEYWORD
4313  |  MUST_KEYWORD
4314  |  NAMESPACE_KEYWORD
4315  |  NOTIFICATION_KEYWORD
4316  |  ORDERED_BY_KEYWORD
4317  |  ORGANIZATION_KEYWORD
4318  |  OUTPUT_KEYWORD
4319  |  PATH_KEYWORD
4320  |  PATTERN_KEYWORD
4321  |  POSITION_KEYWORD
4322  |  PREFIX_KEYWORD
4323  |  PRESENCE_KEYWORD
4324  |  RANGE_KEYWORD
4325  |  REFERENCE_KEYWORD
4326  |  REFINE_KEYWORD
4327  |  REQUIRE_INSTANCE_KEYWORD
4328  |  REVISION_KEYWORD
4329  |  REVISION_DATE_KEYWORD
4330  |  RPC_KEYWORD
4331  |  STATUS_KEYWORD
4332  |  SUBMODULE_KEYWORD
4333  |  TYPE_KEYWORD
4334  |  TYPEDEF_KEYWORD
4335  |  UNIQUE_KEYWORD
4336  |  UNITS_KEYWORD
4337  |  USES_KEYWORD
4338  |  VALUE_KEYWORD
4339  |  WHEN_KEYWORD
4340  |  YANG_VERSION_KEYWORD
4341  |  YIN_ELEMENT_KEYWORD
4342  |  ADD_KEYWORD
4343  |  DELETE_KEYWORD
4344  |  REPLACE_KEYWORD
4345  |  ACTION_KEYWORD
4346  |  MODIFIER_KEYWORD
4347  |  ANYDATA_KEYWORD
4348
4349identifiers: identifier { s = strdup(yyget_text(scanner));
4350                          if (!s) {
4351                            LOGMEM(trg->ctx);
4352                            YYABORT;
4353                          }
4354                        }
4355
4356identifiers_ref: IDENTIFIERPREFIX { s = strdup(yyget_text(scanner));
4357                                    if (!s) {
4358                                      LOGMEM(trg->ctx);
4359                                      YYABORT;
4360                                    }
4361                                  }
4362
4363type_ext_alloc: @EMPTYDIR@ { struct lys_type **type;
4364
4365                             type = (struct lys_type **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4366                                                                                            "type", LY_STMT_TYPE);
4367                             if (!type) {
4368                               YYABORT;
4369                             }
4370                             /* allocate type structure */
4371                             (*type) = calloc(1, sizeof **type);
4372                             if (!*type) {
4373                               LOGMEM(trg->ctx);
4374                               YYABORT;
4375                             }
4376
4377                             /* HACK for unres */
4378                             (*type)->parent = (struct lys_tpdf *)ext_instance;
4379                             $$ = actual = *type;
4380                             is_ext_instance = 0;
4381                            }
4382
4383typedef_ext_alloc: @EMPTYDIR@ { struct lys_tpdf **tpdf;
4384
4385                                tpdf = (struct lys_tpdf **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4386                                                                                               "typedef", LY_STMT_TYPEDEF);
4387                                if (!tpdf) {
4388                                  YYABORT;
4389                                }
4390                                /* allocate typedef structure */
4391                                (*tpdf) = calloc(1, sizeof **tpdf);
4392                                if (!*tpdf) {
4393                                  LOGMEM(trg->ctx);
4394                                  YYABORT;
4395                                }
4396
4397                                $$ = actual = *tpdf;
4398                                is_ext_instance = 0;
4399                              }
4400
4401iffeature_ext_alloc: @EMPTYDIR@ { struct lys_iffeature **iffeature;
4402
4403                                 iffeature = (struct lys_iffeature **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4404                                                                                                          "if-feature", LY_STMT_IFFEATURE);
4405                                 if (!iffeature) {
4406                                   YYABORT;
4407                                 }
4408                                 /* allocate typedef structure */
4409                                 (*iffeature) = calloc(1, sizeof **iffeature);
4410                                 if (!*iffeature) {
4411                                   LOGMEM(trg->ctx);
4412                                   YYABORT;
4413                                 }
4414                                 $$ = actual = *iffeature;
4415                               }
4416
4417restriction_ext_alloc: @EMPTYDIR@ { struct lys_restr **restr;
4418                                    LY_STMT stmt;
4419
4420                                    s = yyget_text(scanner);
4421                                    if (!strcmp(s, "must")) {
4422                                      stmt = LY_STMT_MUST;
4423                                    } else if (!strcmp(s, "pattern")) {
4424                                      stmt = LY_STMT_PATTERN;
4425                                    } else if (!strcmp(s, "range")) {
4426                                      stmt = LY_STMT_RANGE;
4427                                    } else {
4428                                      stmt = LY_STMT_LENGTH;
4429                                    }
4430                                    restr = (struct lys_restr **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name, s, stmt);
4431                                    if (!restr) {
4432                                      YYABORT;
4433                                    }
4434                                    /* allocate structure for must */
4435                                    (*restr) = calloc(1, sizeof(struct lys_restr));
4436                                    if (!*restr) {
4437                                      LOGMEM(trg->ctx);
4438                                      YYABORT;
4439                                    }
4440                                    $$ = actual = *restr;
4441                                    s = NULL;
4442                                  }
4443
4444when_ext_alloc: @EMPTYDIR@ { actual = yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name, "when", LY_STMT_WHEN);
4445                             if (!actual) {
4446                               YYABORT;
4447                             }
4448                             $$ = actual;
4449                           }
4450
4451revision_ext_alloc: @EMPTYDIR@ { struct lys_revision **rev;
4452                                 int i;
4453
4454                                 rev = (struct lys_revision **)yang_getplace_for_extcomplex_struct(ext_instance, &i, ext_name,
4455                                                                                                   "revision", LY_STMT_REVISION);
4456                                 if (!rev) {
4457                                   YYABORT;
4458                                 }
4459                                 rev[i] = calloc(1, sizeof **rev);
4460                                 if (!rev[i]) {
4461                                   LOGMEM(trg->ctx);
4462                                   YYABORT;
4463                                 }
4464                                 actual = rev[i];
4465                                 $$.revision = rev;
4466                                 $$.index = i;
4467                               }
4468
4469datadef_ext_check: @EMPTYDIR@ { LY_STMT stmt;
4470
4471                                s = yyget_text(scanner);
4472                                if (!strcmp(s, "action")) {
4473                                  stmt = LY_STMT_ACTION;
4474                                } else if (!strcmp(s, "anydata")) {
4475                                  stmt = LY_STMT_ANYDATA;
4476                                } else if (!strcmp(s, "anyxml")) {
4477                                  stmt = LY_STMT_ANYXML;
4478                                } else if (!strcmp(s, "case")) {
4479                                  stmt = LY_STMT_CASE;
4480                                } else if (!strcmp(s, "choice")) {
4481                                  stmt = LY_STMT_CHOICE;
4482                                } else if (!strcmp(s, "container")) {
4483                                  stmt = LY_STMT_CONTAINER;
4484                                } else if (!strcmp(s, "grouping")) {
4485                                  stmt = LY_STMT_GROUPING;
4486                                } else if (!strcmp(s, "input")) {
4487                                  stmt = LY_STMT_INPUT;
4488                                } else if (!strcmp(s, "leaf")) {
4489                                  stmt = LY_STMT_LEAF;
4490                                } else if (!strcmp(s, "leaf-list")) {
4491                                  stmt = LY_STMT_LEAFLIST;
4492                                } else if (!strcmp(s, "list")) {
4493                                  stmt = LY_STMT_LIST;
4494                                } else if (!strcmp(s, "notification")) {
4495                                  stmt = LY_STMT_NOTIFICATION;
4496                                } else if (!strcmp(s, "output")) {
4497                                  stmt = LY_STMT_OUTPUT;
4498                                } else {
4499                                  stmt = LY_STMT_USES;
4500                                }
4501                                if (yang_extcomplex_node(ext_instance, ext_name, s, *param->node, stmt)) {
4502                                  YYABORT;
4503                                }
4504                                actual = NULL;
4505                                s = NULL;
4506                                is_ext_instance = 0;
4507                              }
4508
4509not_supported_ext_check: not_supported_ext { LOGERR(trg->ctx, ly_errno, "Extension's substatement \"%s\" not supported.", yyget_text(scanner)); }
4510
4511not_supported_ext: YANG_VERSION_KEYWORD
4512  |  YIN_ELEMENT_KEYWORD
4513  |  BIT_KEYWORD
4514  |  ENUM_KEYWORD
4515  |  AUGMENT_KEYWORD
4516  |  DEVIATION_KEYWORD
4517  |  DEVIATE_KEYWORD
4518  |  EXTENSION_KEYWORD
4519  |  FEATURE_KEYWORD
4520  |  IDENTITY_KEYWORD
4521  |  IMPORT_KEYWORD
4522  |  INCLUDE_KEYWORD
4523  |  SUBMODULE_EXT_KEYWORD
4524
4525datadef_ext_stmt: action_stmt
4526  |  anydata_stmt
4527  |  anyxml_stmt
4528  |  case_stmt
4529  |  choice_stmt
4530  |  container_stmt
4531  |  grouping_stmt
4532  |  input_stmt
4533  |  leaf_stmt
4534  |  leaf_list_stmt
4535  |  list_stmt
4536  |  notification_stmt
4537  |  output_stmt
4538  |  uses_stmt
4539
4540restriction_ext_stmt: must_stmt
4541  |  pattern_stmt
4542  |  range_stmt
4543  |  length_stmt
4544
4545ext_substatements: @EMPTYDIR@ { actual_type = EXTENSION_INSTANCE;
4546                                actual = ext_instance;
4547                                if (!is_ext_instance) {
4548                                  LOGVAL(trg->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yyget_text(scanner));
4549                                  YYABORT;
4550                                }
4551                                $$ = 0;
4552                              }
4553  |  ext_substatements belongs_to_stmt stmtsep
4554  |  ext_substatements prefix_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "prefix", ext_name, &s,
4555                                                                  0, LY_STMT_PREFIX)) {
4556                                       YYABORT;
4557                                     }
4558                                   }
4559  |  ext_substatements description_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "description", ext_name, &s,
4560                                                                       0, LY_STMT_DESCRIPTION)) {
4561                                            YYABORT;
4562                                          }
4563                                        }
4564  |  ext_substatements reference_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "reference", ext_name, &s,
4565                                                                     0, LY_STMT_REFERENCE)) {
4566                                          YYABORT;
4567                                        }
4568                                      }
4569  |  ext_substatements units_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "units", ext_name, &s,
4570                                                                     0, LY_STMT_UNITS)) {
4571                                      YYABORT;
4572                                    }
4573                                  }
4574  |  ext_substatements base_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "base", ext_name, &s,
4575                                                                0, LY_STMT_BASE)) {
4576                                     YYABORT;
4577                                   }
4578                                 }
4579  |  ext_substatements contact_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "contact", ext_name, &s,
4580                                                                     0, LY_STMT_CONTACT)) {
4581                                        YYABORT;
4582                                      }
4583                                    }
4584  |  ext_substatements default_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "default", ext_name, &s,
4585                                                                     0, LY_STMT_DEFAULT)) {
4586                                        YYABORT;
4587                                      }
4588                                    }
4589  |  ext_substatements error_message_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "error-message", ext_name, &s,
4590                                                                         0, LY_STMT_ERRMSG)) {
4591                                              YYABORT;
4592                                            }
4593                                          }
4594  |  ext_substatements error_app_tag_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "error-app-tag", ext_name, &s,
4595                                                                         0, LY_STMT_ERRTAG)) {
4596                                              YYABORT;
4597                                            }
4598                                          }
4599  |  ext_substatements key_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "key", ext_name, &s,
4600                                                               0, LY_STMT_KEY)) {
4601                                    YYABORT;
4602                                  }
4603                                }
4604  |  ext_substatements namespace_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "namespace", ext_name, &s,
4605                                                                     0, LY_STMT_NAMESPACE)) {
4606                                          YYABORT;
4607                                        }
4608                                      }
4609  |  ext_substatements organization_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "organization", ext_name, &s,
4610                                                                        0, LY_STMT_ORGANIZATION)) {
4611                                             YYABORT;
4612                                           }
4613                                         }
4614  |  ext_substatements path_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "path", ext_name, &s,
4615                                                                0, LY_STMT_PATH)) {
4616                                     YYABORT;
4617                                   }
4618                                 }
4619  |  ext_substatements presence_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "presence", ext_name, &s,
4620                                                                    0, LY_STMT_PRESENCE)) {
4621                                         YYABORT;
4622                                       }
4623                                     }
4624  |  ext_substatements revision_date_stmt { if (yang_read_extcomplex_str(trg, ext_instance, "revision-date", ext_name, &s,
4625                                                                         0, LY_STMT_REVISIONDATE)) {
4626                                              YYABORT;
4627                                            }
4628                                          }
4629  |  ext_substatements type_ext_alloc type_stmt stmtsep
4630     { struct lys_type *type = $2;
4631
4632       if (yang_fill_type(trg, type, (struct yang_type *)type->der, ext_instance, param->unres)) {
4633         yang_type_free(trg->ctx, type);
4634         YYABORT;
4635       }
4636       if (unres_schema_add_node(trg, param->unres, type, UNRES_TYPE_DER_EXT, NULL) == -1) {
4637         yang_type_free(trg->ctx, type);
4638         YYABORT;
4639       }
4640       actual = ext_instance;
4641       is_ext_instance = 1;
4642     }
4643  |  ext_substatements typedef_ext_alloc typedef_stmt stmtsep
4644     { struct lys_tpdf *tpdf = $2;
4645
4646       if (yang_fill_type(trg, &tpdf->type, (struct yang_type *)tpdf->type.der, tpdf, param->unres)) {
4647         yang_type_free(trg->ctx, &tpdf->type);
4648       }
4649       if (yang_check_ext_instance(trg, &tpdf->ext, &tpdf->ext_size, tpdf, param->unres)) {
4650         YYABORT;
4651       }
4652       if (unres_schema_add_node(trg, param->unres, &tpdf->type, UNRES_TYPE_DER_TPDF, (struct lys_node *)ext_instance) == -1) {
4653         yang_type_free(trg->ctx, &tpdf->type);
4654         YYABORT;
4655       }
4656       /* check default value*/
4657       if (unres_schema_add_node(trg, param->unres, &tpdf->type, UNRES_TYPE_DFLT, (struct lys_node *)(&tpdf->dflt)) == -1)  {
4658         YYABORT;
4659       }
4660       actual = ext_instance;
4661       is_ext_instance = 1;
4662     }
4663  |  ext_substatements status_stmt { if (yang_fill_extcomplex_flags(ext_instance, ext_name, "status", LY_STMT_STATUS,
4664                                                                    $2, LYS_STATUS_MASK)) {
4665                                       YYABORT;
4666                                     }
4667                                   }
4668  |  ext_substatements config_stmt { if (yang_fill_extcomplex_flags(ext_instance, ext_name, "config", LY_STMT_CONFIG,
4669                                                                    $2, LYS_CONFIG_MASK)) {
4670                                       YYABORT;
4671                                     }
4672                                   }
4673  |  ext_substatements mandatory_stmt { if (yang_fill_extcomplex_flags(ext_instance, ext_name, "mandatory", LY_STMT_MANDATORY,
4674                                                                       $2, LYS_MAND_MASK)) {
4675                                          YYABORT;
4676                                        }
4677                                      }
4678  |  ext_substatements ordered_by_stmt { if ($1 & LYS_ORDERED_MASK) {
4679                                            LOGVAL(trg->ctx, LYE_TOOMANY, LY_VLOG_NONE, NULL, "ordered by", ext_name);
4680                                            YYABORT;
4681                                         }
4682                                         if ($2 & LYS_USERORDERED) {
4683                                           if (yang_fill_extcomplex_flags(ext_instance, ext_name, "ordered-by", LY_STMT_ORDEREDBY,
4684                                                                          $2, LYS_USERORDERED)) {
4685                                             YYABORT;
4686                                           }
4687                                         }
4688                                         $1 |= $2;
4689                                         $$ = $1;
4690                                       }
4691  |  ext_substatements require_instance_stmt { if (yang_fill_extcomplex_uint8(ext_instance, ext_name, "require-instance",
4692                                                                              LY_STMT_REQINSTANCE, $2)) {
4693                                                 YYABORT;
4694                                               }
4695                                             }
4696  |  ext_substatements modifier_stmt { if (yang_fill_extcomplex_uint8(ext_instance, ext_name, "modifier", LY_STMT_MODIFIER, 0)) {
4697                                         YYABORT;
4698                                       }
4699                                     }
4700  |  ext_substatements fraction_digits_stmt
4701     { /* range check */
4702       if ($2 < 1 || $2 > 18) {
4703         LOGVAL(trg->ctx, LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", $2, "fraction-digits");
4704         YYABORT;
4705       }
4706       if (yang_fill_extcomplex_uint8(ext_instance, ext_name, "fraction-digits", LY_STMT_DIGITS, $2)) {
4707         YYABORT;
4708       }
4709     }
4710  |  ext_substatements min_elements_stmt { uint32_t **val;
4711
4712                                           val = (uint32_t **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4713                                                                                                  "min-elements", LY_STMT_MIN);
4714                                           if (!val) {
4715                                             YYABORT;
4716                                           }
4717                                           /* store the value */
4718                                           *val = malloc(sizeof(uint32_t));
4719                                           if (!*val) {
4720                                             LOGMEM(trg->ctx);
4721                                             YYABORT;
4722                                           }
4723                                           **val = $2;
4724                                         }
4725  |  ext_substatements max_elements_stmt { uint32_t **val;
4726
4727                                           val = (uint32_t **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4728                                                                                                  "max-elements", LY_STMT_MAX);
4729                                           if (!val) {
4730                                             YYABORT;
4731                                           }
4732                                           /* store the value */
4733                                           *val = malloc(sizeof(uint32_t));
4734                                           if (!*val) {
4735                                             LOGMEM(trg->ctx);
4736                                             YYABORT;
4737                                           }
4738                                           **val = $2;
4739                                         }
4740  |  ext_substatements position_stmt { uint32_t **val;
4741
4742                                       val = (uint32_t **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4743                                                                                              "position", LY_STMT_POSITION);
4744                                       if (!val) {
4745                                         YYABORT;
4746                                       }
4747                                       /* store the value */
4748                                       *val = malloc(sizeof(uint32_t));
4749                                       if (!*val) {
4750                                         LOGMEM(trg->ctx);
4751                                         YYABORT;
4752                                       }
4753                                       **val = $2;
4754                                     }
4755  |  ext_substatements value_stmt { int32_t **val;
4756
4757                                    val = (int32_t **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4758                                                                                          "value", LY_STMT_VALUE);
4759                                    if (!val) {
4760                                      YYABORT;
4761                                    }
4762                                    /* store the value */
4763                                    *val = malloc(sizeof(int32_t));
4764                                    if (!*val) {
4765                                      LOGMEM(trg->ctx);
4766                                      YYABORT;
4767                                    }
4768                                    **val = $2;
4769                                  }
4770  |  ext_substatements unique_stmt { struct lys_unique **unique;
4771                                     int rc;
4772
4773                                     unique = (struct lys_unique **)yang_getplace_for_extcomplex_struct(ext_instance, NULL, ext_name,
4774                                                                                                        "unique", LY_STMT_UNIQUE);
4775                                     if (!unique) {
4776                                       YYABORT;
4777                                     }
4778                                     *unique = calloc(1, sizeof(struct lys_unique));
4779                                     if (!*unique) {
4780                                       LOGMEM(trg->ctx);
4781                                       YYABORT;
4782                                     }
4783                                     rc = yang_fill_unique(trg, (struct lys_node_list *)ext_instance, *unique, s, param->unres);
4784                                     free(s);
4785                                     s = NULL;
4786                                     if (rc) {
4787                                       YYABORT;
4788                                     }
4789                                   }
4790  |  ext_substatements iffeature_ext_alloc if_feature_stmt stmtsep
4791     { struct lys_iffeature *iffeature;
4792
4793       iffeature = $2;
4794       s = (char *)iffeature->features;
4795       iffeature->features = NULL;
4796       if (yang_fill_iffeature(trg, iffeature, ext_instance, s, param->unres, 0)) {
4797         YYABORT;
4798       }
4799       if (yang_check_ext_instance(trg, &iffeature->ext, &iffeature->ext_size, iffeature, param->unres)) {
4800         YYABORT;
4801       }
4802       s = NULL;
4803       actual = ext_instance;
4804     }
4805  |  ext_substatements argument_stmt stmtsep
4806  |  ext_substatements restriction_ext_alloc restriction_ext_stmt stmtsep
4807     { if (yang_check_ext_instance(trg, &((struct lys_restr *)$2)->ext, &((struct lys_restr *)$2)->ext_size, $2, param->unres)) {
4808         YYABORT;
4809       }
4810       actual = ext_instance;
4811     }
4812  |  ext_substatements when_ext_alloc when_stmt stmtsep
4813     { if (yang_check_ext_instance(trg, &(*(struct lys_when **)$2)->ext, &(*(struct lys_when **)$2)->ext_size,
4814                                   *(struct lys_when **)$2, param->unres)) {
4815         YYABORT;
4816       }
4817       actual = ext_instance;
4818     }
4819  |  ext_substatements revision_ext_alloc revision_stmt stmtsep
4820     { int i;
4821
4822       for (i = 0; i < $2.index; ++i) {
4823         if (!strcmp($2.revision[i]->date, $2.revision[$2.index]->date)) {
4824           LOGWRN(trg->ctx, "Module's revisions are not unique (%s).", $2.revision[i]->date);
4825           break;
4826         }
4827       }
4828       if (yang_check_ext_instance(trg, &$2.revision[$2.index]->ext, &$2.revision[$2.index]->ext_size,
4829                                   &$2.revision[$2.index], param->unres)) {
4830         YYABORT;
4831       }
4832       actual = ext_instance;
4833     }
4834  |  ext_substatements datadef_ext_check datadef_ext_stmt stmtsep { actual = ext_instance;
4835                                                                    is_ext_instance = 1;
4836                                                                  }
4837  |  ext_substatements not_supported_ext_check unknown_string unknown_statement3_opt_end
4838
4839%%
4840
4841void
4842yyerror(YYLTYPE *yylloc, void *scanner, struct yang_parameter *param, ...)
4843{
4844  free(*param->value);
4845  *param->value = NULL;
4846  if (yylloc->first_line != -1) {
4847    if (*param->data_node && (*param->data_node) == (*param->actual_node)) {
4848      LOGVAL(param->module->ctx, LYE_INSTMT, LY_VLOG_LYS, *param->data_node, yyget_text(scanner));
4849    } else {
4850      LOGVAL(param->module->ctx, LYE_INSTMT, LY_VLOG_NONE, NULL, yyget_text(scanner));
4851    }
4852  }
4853}
4854