/** | |
* @file yang.y | |
* @author Pavol Vican | |
* @brief YANG parser for libyang (bison grammar) | |
* | |
* Copyright (c) 2015 CESNET, z.s.p.o. | |
* | |
* This source code is licensed under BSD 3-Clause License (the "License"). | |
* You may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* https://opensource.org/licenses/BSD-3-Clause | |
*/ | |
%define api.pure full | |
%locations | |
%parse-param {void *scanner} | |
%parse-param {struct lys_module *module} | |
%parse-param {struct lys_submodule *submodule} | |
%parse-param {struct unres_schema *unres} | |
%parse-param {struct lys_array_size *size_arrays} | |
%parse-param {int read_all} | |
%lex-param {void *scanner} | |
%{ | |
#include <stdio.h> | |
#include <stdarg.h> | |
#include <string.h> | |
#include <stdlib.h> | |
#include "context.h" | |
#include "resolve.h" | |
#include "common.h" | |
#include "parser_yang.h" | |
#include "parser_yang_lex.h" | |
#include "parser.h" | |
/* only syntax rules */ | |
#define EXTENSION_ARG 0x01 | |
#define EXTENSION_STA 0x02 | |
#define EXTENSION_DSC 0x04 | |
#define EXTENSION_REF 0x08 | |
#define DISABLE_INHERIT 0 | |
#define ENABLE_INHERIT 0x01 | |
void yyerror(YYLTYPE *yylloc, void *scanner, ...); | |
char *s, *tmp_s; | |
char rev[LY_REV_SIZE]; | |
struct lys_module *trg; | |
/* temporary pointer for the check extension nacm */ | |
struct lys_node *data_node; | |
/* pointer on the current parsed element*/ | |
void *actual; | |
int config_inherit; | |
int actual_type; | |
int64_t cnt_val; | |
%} | |
%union { | |
int32_t i; | |
uint32_t uint; | |
char *str; | |
void *v; | |
struct lys_module *inc; | |
union { | |
uint32_t index; | |
struct lys_node_container *container; | |
struct lys_node_anyxml *anyxml; | |
struct type_choice choice; | |
struct type_node node; | |
struct lys_node_case *cs; | |
struct lys_node_grp *grouping; | |
struct type_uses uses; | |
struct lys_refine *refine; | |
struct lys_node_notif *notif; | |
struct type_deviation *deviation; | |
} nodes; | |
} | |
%token UNION_KEYWORD | |
%token ANYXML_KEYWORD | |
%token WHITESPACE | |
%token ERROR | |
%token EOL | |
%token STRING | |
%token STRINGS | |
%token IDENTIFIER | |
%token IDENTIFIERPREFIX | |
%token REVISION_DATE | |
%token TAB | |
%token DOUBLEDOT | |
%token URI | |
%token INTEGER | |
%token NON_NEGATIVE_INTEGER | |
%token ZERO | |
%token DECIMAL | |
%token ARGUMENT_KEYWORD | |
%token AUGMENT_KEYWORD | |
%token BASE_KEYWORD | |
%token BELONGS_TO_KEYWORD | |
%token BIT_KEYWORD | |
%token CASE_KEYWORD | |
%token CHOICE_KEYWORD | |
%token CONFIG_KEYWORD | |
%token CONTACT_KEYWORD | |
%token CONTAINER_KEYWORD | |
%token DEFAULT_KEYWORD | |
%token DESCRIPTION_KEYWORD | |
%token ENUM_KEYWORD | |
%token ERROR_APP_TAG_KEYWORD | |
%token ERROR_MESSAGE_KEYWORD | |
%token EXTENSION_KEYWORD | |
%token DEVIATION_KEYWORD | |
%token DEVIATE_KEYWORD | |
%token FEATURE_KEYWORD | |
%token FRACTION_DIGITS_KEYWORD | |
%token GROUPING_KEYWORD | |
%token IDENTITY_KEYWORD | |
%token IF_FEATURE_KEYWORD | |
%token IMPORT_KEYWORD | |
%token INCLUDE_KEYWORD | |
%token INPUT_KEYWORD | |
%token KEY_KEYWORD | |
%token LEAF_KEYWORD | |
%token LEAF_LIST_KEYWORD | |
%token LENGTH_KEYWORD | |
%token LIST_KEYWORD | |
%token MANDATORY_KEYWORD | |
%token MAX_ELEMENTS_KEYWORD | |
%token MIN_ELEMENTS_KEYWORD | |
%token MODULE_KEYWORD | |
%token MUST_KEYWORD | |
%token NAMESPACE_KEYWORD | |
%token NOTIFICATION_KEYWORD | |
%token ORDERED_BY_KEYWORD | |
%token ORGANIZATION_KEYWORD | |
%token OUTPUT_KEYWORD | |
%token PATH_KEYWORD | |
%token PATTERN_KEYWORD | |
%token POSITION_KEYWORD | |
%token PREFIX_KEYWORD | |
%token PRESENCE_KEYWORD | |
%token RANGE_KEYWORD | |
%token REFERENCE_KEYWORD | |
%token REFINE_KEYWORD | |
%token REQUIRE_INSTANCE_KEYWORD | |
%token REVISION_KEYWORD | |
%token REVISION_DATE_KEYWORD | |
%token RPC_KEYWORD | |
%token STATUS_KEYWORD | |
%token SUBMODULE_KEYWORD | |
%token TYPE_KEYWORD | |
%token TYPEDEF_KEYWORD | |
%token UNIQUE_KEYWORD | |
%token UNITS_KEYWORD | |
%token USES_KEYWORD | |
%token VALUE_KEYWORD | |
%token WHEN_KEYWORD | |
%token YANG_VERSION_KEYWORD | |
%token YIN_ELEMENT_KEYWORD | |
%token ADD_KEYWORD | |
%token CURRENT_KEYWORD | |
%token DELETE_KEYWORD | |
%token DEPRECATED_KEYWORD | |
%token FALSE_KEYWORD | |
%token NOT_SUPPORTED_KEYWORD | |
%token OBSOLETE_KEYWORD | |
%token REPLACE_KEYWORD | |
%token SYSTEM_KEYWORD | |
%token TRUE_KEYWORD | |
%token UNBOUNDED_KEYWORD | |
%token USER_KEYWORD | |
%type <uint> positive_integer_value | |
%type <uint> non_negative_integer_value | |
%type <uint> max_value_arg_str | |
%type <uint> max_elements_stmt | |
%type <uint> min_value_arg_str | |
%type <uint> min_elements_stmt | |
%type <uint> decimal_string_restrictions | |
%type <uint> fraction_digits_arg_str | |
%type <uint> position_value_arg_str | |
%type <uint> extension_opt_stmt | |
%type <i> module_header_stmts | |
%type <i> submodule_header_stmts | |
%type <str> tmp_identifier_arg_str | |
%type <str> message_opt_stmt | |
%type <str> identity_opt_stmt | |
%type <i> status_stmt | |
%type <i> status_read_stmt | |
%type <i> status_arg_str | |
%type <i> config_stmt | |
%type <i> config_read_stmt | |
%type <i> config_arg_str | |
%type <i> mandatory_stmt | |
%type <i> mandatory_read_stmt | |
%type <i> mandatory_arg_str | |
%type <i> ordered_by_stmt | |
%type <i> ordered_by_arg_str | |
%type <i> integer_value_arg_str | |
%type <i> integer_value | |
%type <i> feature_opt_stmt | |
%type <v> length_arg_str | |
%type <v> pattern_arg_str | |
%type <v> range_arg_str | |
%type <v> enum_arg_str | |
%type <v> bit_arg_str | |
%type <v> union_spec | |
%type <v> typedef_arg_str | |
%type <nodes> container_opt_stmt | |
%type <nodes> anyxml_opt_stmt | |
%type <nodes> choice_opt_stmt | |
%type <nodes> case_opt_stmt | |
%type <nodes> grouping_opt_stmt | |
%type <nodes> leaf_opt_stmt | |
%type <nodes> leaf_list_opt_stmt | |
%type <nodes> list_opt_stmt | |
%type <nodes> type_opt_stmt | |
%type <nodes> uses_opt_stmt | |
%type <nodes> refine_body_opt_stmts | |
%type <nodes> augment_opt_stmt | |
%type <nodes> rpc_opt_stmt | |
%type <nodes> input_output_opt_stmt | |
%type <nodes> notification_opt_stmt | |
%type <nodes> deviation_opt_stmt | |
%type <nodes> deviate_add_opt_stmt | |
%type <nodes> deviate_delete_opt_stmt | |
%type <nodes> deviate_replace_opt_stmt | |
%type <inc> include_stmt | |
%type <inc> import_stmt | |
%destructor { free($$); } tmp_identifier_arg_str | |
%destructor { if (read_all && $$.choice.s) { free($$.choice.s); } } choice_opt_stmt | |
%destructor { if (read_all) { | |
free($$.deviation); | |
} | |
} deviation_opt_stmt | |
%% | |
/* to simplify code, store the module/submodule being processed as trg */ | |
start: module_stmt | |
| submodule_stmt { if (read_all && lyp_propagate_submodule(module, submodule)) { | |
YYERROR; | |
} | |
} | |
string_1: STRING { if (read_all) { | |
if (yyget_text(scanner)[0] == '"') { | |
s = yang_read_string(yyget_text(scanner) + 1, yyget_leng(scanner) - 2, yylloc.first_column); | |
if (!s) { | |
YYERROR; | |
} | |
} else { | |
s = calloc(1, yyget_leng(scanner) - 1); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
memcpy(s, yyget_text(scanner) + 1, yyget_leng(scanner) - 2); | |
} | |
} | |
} | |
optsep string_2 | |
string_2: @EMPTYDIR@ | |
| string_2 '+' optsep | |
STRING { if (read_all){ | |
char *temp; | |
if (yyget_text(scanner)[0] == '"') { | |
temp = yang_read_string(yyget_text(scanner) + 1, yyget_leng(scanner) - 2, yylloc.first_column); | |
if (!temp) { | |
YYERROR; | |
} | |
s = ly_realloc(s, strlen(temp) + strlen(s) + 1); | |
if (s) { | |
strcat(s, temp); | |
free(temp); | |
} else { | |
free(temp); | |
LOGMEM; | |
YYERROR; | |
} | |
} else { | |
int length = yyget_leng(scanner) - 2 + strlen(s) + 1; | |
s = ly_realloc(s, length); | |
if (s) { | |
memcpy(s + strlen(s), yyget_text(scanner) + 1, yyget_leng(scanner) - 2); | |
s[length - 1] = '\0'; | |
} else { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
} | |
optsep; | |
module_stmt: optsep MODULE_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (submodule) { | |
LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "module"); | |
YYERROR; | |
} | |
trg = module; | |
yang_read_common(trg,s,MODULE_KEYWORD); | |
s = NULL; | |
config_inherit = ENABLE_INHERIT; | |
} | |
} | |
'{' stmtsep | |
module_header_stmts { if (read_all && !module->ns) { LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "namespace", "module"); YYERROR; } | |
if (read_all && !module->prefix) { LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "prefix", "module"); YYERROR; } | |
} | |
linkage_stmts | |
meta_stmts | |
revision_stmts | |
body_stmts | |
'}' optsep | |
module_header_stmts: @EMPTYDIR@ { $$ = 0; } | |
| module_header_stmts yang_version_stmt { if ($1) { LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "module"); YYERROR; } $$ = 1; } | |
| module_header_stmts namespace_stmt { if (read_all && yang_read_common(module, s, NAMESPACE_KEYWORD)) {YYERROR;} s=NULL; } | |
| module_header_stmts prefix_stmt { if (read_all && yang_read_prefix(module, NULL, s, MODULE_KEYWORD)) {YYERROR;} s=NULL; } | |
; | |
submodule_stmt: optsep SUBMODULE_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!submodule) { | |
LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "submodule"); | |
YYERROR; | |
} | |
trg = (struct lys_module *)submodule; | |
yang_read_common(trg,s,MODULE_KEYWORD); | |
s = NULL; | |
config_inherit = ENABLE_INHERIT; | |
} | |
} | |
'{' stmtsep | |
submodule_header_stmts { if (read_all && !submodule->prefix) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "belongs-to", "submodule"); | |
YYERROR; | |
} | |
} | |
linkage_stmts | |
meta_stmts | |
revision_stmts | |
body_stmts | |
'}' optsep | |
submodule_header_stmts: @EMPTYDIR@ { $$ = 0; } | |
| submodule_header_stmts yang_version_stmt { if ($1) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "yang version", "submodule"); | |
YYERROR; | |
} | |
$$ = 1; | |
} | |
| submodule_header_stmts { if (read_all) { | |
if (submodule->prefix) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "belongs-to", "submodule"); | |
YYERROR; | |
} | |
} | |
} | |
belongs_to_stmt | |
yang_version_stmt: YANG_VERSION_KEYWORD sep yang_version_arg_str stmtend; | |
yang_version_arg_str: NON_NEGATIVE_INTEGER { if (strlen(yyget_text(scanner))!=1 || yyget_text(scanner)[0]!='1') { | |
YYERROR; | |
} | |
} optsep | |
| string_1 { if (read_all) { | |
if (strlen(s)!=1 || s[0]!='1') { | |
free(s); | |
YYERROR; | |
} | |
} | |
} | |
namespace_stmt: NAMESPACE_KEYWORD sep string stmtend; | |
linkage_stmts: @EMPTYDIR@ { if (read_all) { | |
if (size_arrays->imp) { | |
trg->imp = calloc(size_arrays->imp, sizeof *trg->imp); | |
if (!trg->imp) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->inc) { | |
trg->inc = calloc(size_arrays->inc, sizeof *trg->inc); | |
if (!trg->inc) { | |
LOGMEM; | |
YYERROR; | |
} | |
trg->inc_size = size_arrays->inc; | |
size_arrays->inc = 0; | |
/* trg->inc_size can be updated by the included submodules, | |
* so we will use size_arrays->inc here, trg->inc_size stores the | |
* target size of the array | |
*/ | |
} | |
} | |
} | |
| linkage_stmts import_stmt | |
| linkage_stmts include_stmt | |
; | |
import_stmt: IMPORT_KEYWORD sep tmp_identifier_arg_str { | |
if (!read_all) { | |
size_arrays->imp++; | |
} else { | |
actual = &trg->imp[trg->imp_size]; | |
} | |
} | |
'{' stmtsep | |
prefix_stmt { if (read_all) { | |
if (yang_read_prefix(trg, actual, s, IMPORT_KEYWORD)) {YYERROR;} | |
s=NULL; | |
actual_type=IMPORT_KEYWORD; | |
} | |
} | |
revision_date_opt | |
'}' stmtsep { if (read_all) { | |
$$ = trg; | |
if (yang_fill_import(trg, actual, $3)) { | |
YYERROR; | |
} | |
trg = $$; | |
config_inherit = ENABLE_INHERIT; | |
} | |
} | |
tmp_identifier_arg_str: identifier_arg_str { $$ = s; s = NULL; } | |
include_stmt: INCLUDE_KEYWORD sep identifier_arg_str { if (read_all) { | |
memset(rev, 0, LY_REV_SIZE); | |
actual_type = INCLUDE_KEYWORD; | |
} | |
else { | |
size_arrays->inc++; | |
} | |
} | |
include_end stmtsep { if (read_all) { | |
$$ = trg; | |
if (yang_fill_include(module, submodule, s, rev, size_arrays->inc, unres)) { | |
YYERROR; | |
} | |
size_arrays->inc++; | |
s = NULL; | |
trg = $$; | |
config_inherit = ENABLE_INHERIT; | |
} | |
} | |
include_end: ';' | |
| '{' stmtsep | |
revision_date_opt | |
'}' | |
revision_date_opt: @EMPTYDIR@ | |
| revision_date_stmt; | |
revision_date_stmt: REVISION_DATE_KEYWORD sep revision_date optsep stmtend; | |
revision_date: REVISION_DATE { if (read_all) { | |
if (actual_type==IMPORT_KEYWORD) { | |
memcpy(((struct lys_import *)actual)->rev, yyget_text(scanner), LY_REV_SIZE-1); | |
} else { // INCLUDE KEYWORD | |
memcpy(rev, yyget_text(scanner), LY_REV_SIZE - 1); | |
} | |
} | |
} | |
belongs_to_stmt: BELONGS_TO_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!ly_strequal(s, submodule->belongsto->name, 0)) { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "belongs-to"); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
'{' stmtsep | |
prefix_stmt { if (read_all) { | |
if (yang_read_prefix(trg, NULL, s, MODULE_KEYWORD)) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
} | |
'}' stmtsep | |
prefix_stmt: PREFIX_KEYWORD sep prefix_arg_str stmtend; | |
meta_stmts: @EMPTYDIR@ | |
| meta_stmts organization_stmt { if (read_all && yang_read_common(trg, s, ORGANIZATION_KEYWORD)) {YYERROR;} s=NULL; } | |
| meta_stmts contact_stmt { if (read_all && yang_read_common(trg, s, CONTACT_KEYWORD)) {YYERROR;} s=NULL; } | |
| meta_stmts description_stmt { if (read_all && yang_read_description(trg, NULL, s, NULL)) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| meta_stmts reference_stmt { if (read_all && yang_read_reference(trg, NULL, s, NULL)) { | |
YYERROR; | |
} | |
s=NULL; | |
} | |
organization_stmt: ORGANIZATION_KEYWORD sep string stmtend; | |
contact_stmt: CONTACT_KEYWORD sep string stmtend; | |
description_stmt: DESCRIPTION_KEYWORD sep string stmtend; | |
reference_stmt: REFERENCE_KEYWORD sep string stmtend; | |
revision_stmts: @EMPTYDIR@ { if (read_all && size_arrays->rev) { | |
trg->rev = calloc(size_arrays->rev, sizeof *trg->rev); | |
if (!trg->rev) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| revision_stmts revision_stmt stmtsep; | |
revision_stmt: REVISION_KEYWORD sep date_arg_str { if (read_all) { | |
if(!(actual=yang_read_revision(trg,s))) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->rev++; | |
} | |
} | |
revision_end; | |
revision_end: ';' | |
| '{' stmtsep { actual_type = REVISION_KEYWORD; } | |
revision_opt_stmt | |
'}' | |
; | |
revision_opt_stmt: @EMPTYDIR@ | |
| revision_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, "revision")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| revision_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, "revision")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
; | |
date_arg_str: REVISION_DATE { if (read_all) { | |
s = strdup(yyget_text(scanner)); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
optsep | |
| string_1 { if (read_all && lyp_check_date(s)) { | |
free(s); | |
YYERROR; | |
} | |
} | |
body_stmts: @EMPTYDIR@ { if (read_all) { | |
if (size_arrays->features) { | |
trg->features = calloc(size_arrays->features,sizeof *trg->features); | |
if (!trg->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->ident) { | |
trg->ident = calloc(size_arrays->ident,sizeof *trg->ident); | |
if (!trg->ident) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->augment) { | |
trg->augment = calloc(size_arrays->augment,sizeof *trg->augment); | |
if (!trg->augment) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->tpdf) { | |
trg->tpdf = calloc(size_arrays->tpdf, sizeof *trg->tpdf); | |
if (!trg->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->deviation) { | |
trg->deviation = calloc(size_arrays->deviation, sizeof *trg->deviation); | |
if (!trg->deviation) { | |
LOGMEM; | |
YYERROR; | |
} | |
/* module with deviation - must be implemented (description of /ietf-yang-library:modules-state/module/deviation) */ | |
module->implemented = 1; | |
} | |
actual = NULL; | |
} | |
} | |
| body_stmts body_stmt stmtsep { actual = NULL; } | |
body_stmt: extension_stmt | |
| feature_stmt | |
| identity_stmt | |
| typedef_stmt { if (!read_all) { size_arrays->tpdf++; } } | |
| grouping_stmt | |
| data_def_stmt | |
| augment_stmt { if (!read_all) { | |
size_arrays->augment++; | |
} else { | |
config_inherit = ENABLE_INHERIT; | |
} | |
} | |
| rpc_stmt | |
| notification_stmt | |
| deviation_stmt { if (!read_all) { size_arrays->deviation++; } } | |
extension_stmt: EXTENSION_KEYWORD sep identifier_arg_str { if (read_all) { | |
/* we have the following supported (hardcoded) extensions: */ | |
/* ietf-netconf's get-filter-element-attributes */ | |
if (!strcmp(module->ns, LY_NSNC) && !strcmp(s, "get-filter-element-attributes")) { | |
LOGDBG("NETCONF filter extension found"); | |
/* NACM's default-deny-write and default-deny-all */ | |
} else if (!strcmp(module->ns, LY_NSNACM) && | |
(!strcmp(s, "default-deny-write") || !strcmp(s, "default-deny-all"))) { | |
LOGDBG("NACM extension found"); | |
/* other extensions are not supported, so inform about such an extension */ | |
} else { | |
LOGWRN("Not supported \"%s\" extension statement found, ignoring.", s); | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
extension_end | |
extension_end: ';' | |
| '{' stmtsep | |
extension_opt_stmt | |
'}' | |
extension_opt_stmt: @EMPTYDIR@ { $$ = 0; } | |
| extension_opt_stmt argument_stmt { if ($1 & EXTENSION_ARG) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "argument", "extension"); | |
YYERROR; | |
} | |
$1 |= EXTENSION_ARG; | |
$$ = $1; | |
} | |
| extension_opt_stmt status_stmt { if ($1 & EXTENSION_STA) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "extension"); | |
YYERROR; | |
} | |
$1 |= EXTENSION_STA; | |
$$ = $1; | |
} | |
| extension_opt_stmt description_stmt { if (read_all) { | |
free(s); | |
s= NULL; | |
} | |
if ($1 & EXTENSION_DSC) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "description", "extension"); | |
YYERROR; | |
} | |
$1 |= EXTENSION_DSC; | |
$$ = $1; | |
} | |
| extension_opt_stmt reference_stmt { if (read_all) { | |
free(s); | |
s = NULL; | |
} | |
if ($1 & EXTENSION_REF) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "reference", "extension"); | |
YYERROR; | |
} | |
$1 |= EXTENSION_REF; | |
$$ = $1; | |
} | |
argument_stmt: ARGUMENT_KEYWORD sep identifier_arg_str { free(s); s = NULL; } argument_end stmtsep; | |
argument_end: ';' | |
| '{' stmtsep | |
yin_element_stmt | |
'}' | |
yin_element_stmt: YIN_ELEMENT_KEYWORD sep yin_element_arg_str stmtend; | |
yin_element_arg_str: TRUE_KEYWORD optsep | |
| FALSE_KEYWORD optsep | |
| string_1 { if (read_all) { | |
if (strcmp(s, "true") && strcmp(s, "false")) { | |
LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, s); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
status_stmt: STATUS_KEYWORD sep status_arg_str stmtend { $$ = $3; } | |
status_read_stmt: STATUS_KEYWORD sep { read_all = (read_all) ? LY_READ_ONLY_SIZE : LY_READ_ALL; } | |
status_arg_str { read_all = (read_all) ? LY_READ_ONLY_SIZE : LY_READ_ALL; } | |
stmtend { $$ = $4; } | |
status_arg_str: CURRENT_KEYWORD optsep { $$ = LYS_STATUS_CURR; } | |
| OBSOLETE_KEYWORD optsep { $$ = LYS_STATUS_OBSLT; } | |
| DEPRECATED_KEYWORD optsep { $$ = LYS_STATUS_DEPRC; } | |
| string_1 { if (read_all) { | |
if (!strcmp(s, "current")) { | |
$$ = LYS_STATUS_CURR; | |
} else if (!strcmp(s, "obsolete")) { | |
$$ = LYS_STATUS_OBSLT; | |
} else if (!strcmp(s, "deprecated")) { | |
$$ = LYS_STATUS_DEPRC; | |
} else { | |
LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, s); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
feature_stmt: FEATURE_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_feature(trg, s))) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->features++; | |
} | |
} | |
feature_end | |
feature_end: ';' | |
| '{' stmtsep | |
feature_opt_stmt | |
'}' | |
; | |
feature_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
if (size_arrays->node[size_arrays->next].if_features) { | |
((struct lys_feature*)actual)->features = calloc(size_arrays->node[size_arrays->next].if_features, | |
sizeof *((struct lys_feature*)actual)->features); | |
if (!((struct lys_feature*)actual)->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)actual, size_arrays->node[size_arrays->next].flags, 0); | |
size_arrays->next++; | |
} else { | |
$$ = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| feature_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, actual, s, unres, FEATURE_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1].if_features++; | |
} | |
} | |
| feature_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1].flags, LYS_STATUS_MASK, "status", "feature", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| feature_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, "feature")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| feature_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, "feature")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
if_feature_stmt: IF_FEATURE_KEYWORD sep identifier_ref_arg_str stmtend; | |
identity_stmt: IDENTITY_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_identity(trg,s))) {YYERROR;} | |
s = NULL; | |
} else { | |
size_arrays->ident++; | |
} | |
} | |
identity_end; | |
identity_end: ';' | |
| '{' stmtsep | |
identity_opt_stmt { if (read_all && yang_read_base(module, actual, $3, unres)) { | |
YYERROR; | |
} | |
} | |
'}' | |
; | |
identity_opt_stmt: @EMPTYDIR@ { $$ = NULL; } | |
| identity_opt_stmt base_stmt { if (read_all) { | |
if ($1) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "base", "identity"); | |
free(s); | |
free($1); | |
YYERROR; | |
} | |
$$ = s; | |
s = NULL; | |
} | |
} | |
| identity_opt_stmt status_stmt { if (read_all) { | |
if (yang_check_flags(&((struct lys_ident *)actual)->flags, LYS_STATUS_MASK, "status", "identity", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| identity_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, "identity")) { | |
free($1); | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| identity_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, "identity")) { | |
free($1); | |
YYERROR; | |
} | |
s = NULL; | |
} | |
base_stmt: BASE_KEYWORD sep identifier_ref_arg_str stmtend; | |
typedef_stmt: TYPEDEF_KEYWORD sep typedef_arg_str | |
'{' stmtsep | |
type_opt_stmt { if (read_all) { | |
if (!($6.node.flag & LYS_TYPE_DEF)) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "type", "typedef"); | |
YYERROR; | |
} | |
if (unres_schema_add_node(trg, unres, &$6.node.ptr_tpdf->type, UNRES_TYPE_DER,(struct lys_node *) $3)) { | |
YYERROR; | |
} | |
actual = $3; | |
/* check default value */ | |
if ($6.node.ptr_tpdf->dflt) { | |
if (unres_schema_add_str(trg, unres, &$6.node.ptr_tpdf->type, UNRES_TYPE_DFLT, $6.node.ptr_tpdf->dflt) == -1) { | |
YYERROR; | |
} | |
} | |
} | |
} | |
'}' ; | |
typedef_arg_str: identifier_arg_str { if (read_all) { | |
$$ = actual; | |
if (!(actual = yang_read_typedef(trg, actual, s))) { | |
YYERROR; | |
} | |
s = NULL; | |
actual_type = TYPEDEF_KEYWORD; | |
} | |
} | |
type_stmt: TYPE_KEYWORD sep identifier_ref_arg_str { if (read_all && !(actual = yang_read_type(trg, actual, s, actual_type))) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
type_end; | |
type_opt_stmt: @EMPTYDIR@ { $$.node.ptr_tpdf = actual; | |
$$.node.flag = 0; | |
} | |
| type_opt_stmt { if (read_all && ($1.node.flag & LYS_TYPE_DEF)) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, $1.node.ptr_tpdf, "type", "typedef"); | |
YYERROR; | |
} | |
} | |
type_stmt stmtsep { if (read_all) { | |
actual = $1.node.ptr_tpdf; | |
actual_type = TYPEDEF_KEYWORD; | |
$1.node.flag |= LYS_TYPE_DEF; | |
$$ = $1; | |
} | |
} | |
| type_opt_stmt units_stmt { if (read_all && yang_read_units(trg, $1.node.ptr_tpdf, s, TYPEDEF_KEYWORD)) {YYERROR;} s = NULL; } | |
| type_opt_stmt default_stmt { if (read_all && yang_read_default(trg, $1.node.ptr_tpdf, s, TYPEDEF_KEYWORD)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
| type_opt_stmt status_stmt { if (read_all) { | |
if (yang_check_flags(&$1.node.ptr_tpdf->flags, LYS_STATUS_MASK, "status", "typedef", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| type_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_tpdf, s, "typedef")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| type_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_tpdf, s, "typedef")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
type_end: ';' | |
| '{' stmtsep | |
type_body_stmts | |
'}' | |
; | |
type_body_stmts: decimal_string_restrictions | |
| enum_specification | |
| path_stmt { /*leafref_specification */ | |
if (read_all) { | |
((struct yang_type *)actual)->base = LY_TYPE_LEAFREF; | |
((struct yang_type *)actual)->type->info.lref.path = lydict_insert_zc(trg->ctx, s); | |
s = NULL; | |
} | |
} | |
| base_stmt { /*identityref_specification */ | |
if (read_all) { | |
((struct yang_type *)actual)->flags |= LYS_TYPE_BASE; | |
((struct yang_type *)actual)->base = LY_TYPE_LEAFREF; | |
((struct yang_type *)actual)->type->info.lref.path = lydict_insert_zc(trg->ctx, s); | |
s = NULL; | |
} | |
} | |
| require_instance_stmt { /*instance_identifier_specification */ | |
if (read_all) { | |
((struct yang_type *)actual)->base = LY_TYPE_INST; | |
} | |
} | |
| bits_specification | |
; | |
decimal_string_restrictions: @EMPTYDIR@ { if (read_all) { | |
if (size_arrays->node[size_arrays->next].uni && size_arrays->node[size_arrays->next].pattern) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid restriction in type \"%s\".", ((struct yang_type *)actual)->type->parent->name); | |
YYERROR; | |
} | |
if (size_arrays->node[size_arrays->next].pattern) { | |
((struct yang_type *)actual)->type->info.str.patterns = calloc(size_arrays->node[size_arrays->next].pattern, sizeof(struct lys_restr)); | |
if (!((struct yang_type *)actual)->type->info.str.patterns) { | |
LOGMEM; | |
YYERROR; | |
} | |
((struct yang_type *)actual)->base = LY_TYPE_STRING; | |
} | |
if (size_arrays->node[size_arrays->next].uni) { | |
((struct yang_type *)actual)->type->info.uni.types = calloc(size_arrays->node[size_arrays->next].uni, sizeof(struct lys_type)); | |
if (!((struct yang_type *)actual)->type->info.uni.types) { | |
LOGMEM; | |
YYERROR; | |
} | |
((struct yang_type *)actual)->base = LY_TYPE_UNION; | |
} | |
size_arrays->next++; | |
} else { | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
$$ = size_arrays->size-1; | |
} | |
} | |
| decimal_string_restrictions length_stmt | |
| decimal_string_restrictions pattern_stmt { if (!read_all) { | |
size_arrays->node[$1].pattern++; /* count of pattern*/ | |
} | |
} | |
| decimal_string_restrictions fraction_digits_stmt | |
| decimal_string_restrictions range_stmt stmtsep | |
| decimal_string_restrictions union_spec type_stmt stmtsep { if (read_all) { | |
actual = $2; | |
} else { | |
size_arrays->node[$1].uni++; /* count of union*/ | |
} | |
} | |
; | |
union_spec: @EMPTYDIR@ { if (read_all) { | |
struct yang_type *typ; | |
struct lys_type *type; | |
typ = (struct yang_type *)actual; | |
$$ = actual; | |
type = &typ->type->info.uni.types[typ->type->info.uni.count++]; | |
type->parent = typ->type->parent; | |
actual = type; | |
actual_type = UNION_KEYWORD; | |
} | |
} | |
fraction_digits_stmt: FRACTION_DIGITS_KEYWORD sep fraction_digits_arg_str | |
stmtend { if (read_all && yang_read_fraction(actual, $3)) { | |
YYERROR; | |
} | |
} | |
fraction_digits_arg_str: positive_integer_value optsep { $$ = $1; } | |
| string_1 { if (read_all) { | |
char *endptr = NULL; | |
unsigned long val; | |
val = strtoul(s, &endptr, 10); | |
if (*endptr || s[0] == '-' || val == 0 || val > UINT32_MAX) { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "fraction-digits"); | |
free(s); | |
s = NULL; | |
YYERROR; | |
} | |
$$ = (uint32_t) val; | |
free(s); | |
s =NULL; | |
} | |
} | |
; | |
length_stmt: LENGTH_KEYWORD sep length_arg_str length_end stmtsep { actual = $3; | |
actual_type = TYPE_KEYWORD; | |
} | |
length_arg_str: string { if (read_all) { | |
$$ = actual; | |
if (!(actual = yang_read_length(trg, actual, s))) { | |
YYERROR; | |
} | |
actual_type = LENGTH_KEYWORD; | |
s = NULL; | |
} | |
} | |
length_end: ';' | |
| '{' stmtsep | |
message_opt_stmt | |
'}' | |
; | |
message_opt_stmt: @EMPTYDIR@ { switch (actual_type) { | |
case MUST_KEYWORD: | |
$$ = "must"; | |
break; | |
case LENGTH_KEYWORD: | |
$$ = "length"; | |
break; | |
case PATTERN_KEYWORD: | |
$$ = "pattern"; | |
break; | |
case RANGE_KEYWORD: | |
$$ = "range"; | |
break; | |
} | |
} | |
| message_opt_stmt error_message_stmt { if (read_all && yang_read_message(trg, actual, s, $1, ERROR_MESSAGE_KEYWORD)) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| message_opt_stmt error_app_tag_stmt { if (yang_read_message(trg, actual, s, $1, ERROR_APP_TAG_KEYWORD)) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| message_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, $1)) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| message_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, $1)) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
pattern_stmt: PATTERN_KEYWORD sep pattern_arg_str pattern_end stmtsep { actual = $3; | |
actual_type = TYPE_KEYWORD; | |
} | |
pattern_arg_str: string { if (read_all) { | |
$$ = actual; | |
if (!(actual = yang_read_pattern(trg, actual, s))) { | |
YYERROR; | |
} | |
actual_type = PATTERN_KEYWORD; | |
s = NULL; | |
} | |
} | |
pattern_end: ';' | |
| '{' stmtsep | |
message_opt_stmt | |
'}' | |
; | |
enum_specification: { if (read_all) { | |
if (size_arrays->node[size_arrays->next].enm) { | |
((struct yang_type *)actual)->type->info.enums.enm = calloc(size_arrays->node[size_arrays->next++].enm, sizeof(struct lys_type_enum)); | |
if (!((struct yang_type *)actual)->type->info.enums.enm) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
((struct yang_type *)actual)->base = LY_TYPE_ENUM; | |
cnt_val = 0; | |
} else { | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} enum_stmt stmtsep enum_stmts; | |
enum_stmts: @EMPTYDIR@ | |
| enum_stmts enum_stmt stmtsep; | |
enum_stmt: ENUM_KEYWORD sep enum_arg_str enum_end | |
{ if (read_all) { | |
if (yang_check_enum($3, actual, &cnt_val, actual_type)) { | |
YYERROR; | |
} | |
actual = $3; | |
actual_type = TYPE_KEYWORD; | |
} else { | |
size_arrays->node[size_arrays->size-1].enm++; /* count of enum*/ | |
} | |
} | |
enum_arg_str: string { if (read_all) { | |
$$ = actual; | |
if (!(actual = yang_read_enum(trg, actual, s))) { | |
YYERROR; | |
} | |
s = NULL; | |
actual_type = 0; | |
} | |
} | |
enum_end: ';' | |
| '{' stmtsep | |
enum_opt_stmt | |
'}' | |
; | |
enum_opt_stmt: @EMPTYDIR@ | |
| enum_opt_stmt value_stmt { /* actual_type - it is used to check value of enum statement*/ | |
if (read_all) { | |
if (actual_type) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "value", "enum"); | |
YYERROR; | |
} | |
actual_type = 1; | |
} | |
} | |
| enum_opt_stmt status_stmt { if (read_all) { | |
if (yang_check_flags(&((struct lys_type_enum *)actual)->flags, LYS_STATUS_MASK, "status", "enum", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| enum_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, "enum")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| enum_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, "enum")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
value_stmt: VALUE_KEYWORD sep integer_value_arg_str | |
stmtend { if (read_all) { | |
((struct lys_type_enum *)actual)->value = $3; | |
/* keep the highest enum value for automatic increment */ | |
if ($3 > cnt_val) { | |
cnt_val = $3; | |
} | |
cnt_val++; | |
} | |
} | |
integer_value_arg_str: integer_value optsep { $$ = $1; } | |
| string_1 { if (read_all) { | |
/* convert it to int32_t */ | |
int64_t val; | |
char *endptr; | |
val = strtoll(s, &endptr, 10); | |
if (val < INT32_MIN || val > INT32_MAX || *endptr) { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "value"); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
$$ = (int32_t) val; | |
} | |
} | |
; | |
range_stmt: RANGE_KEYWORD sep range_arg_str range_end { actual = $3; | |
actual_type = RANGE_KEYWORD; | |
} | |
range_end: ';' | |
| '{' stmtsep | |
message_opt_stmt | |
'}' | |
; | |
path_stmt: PATH_KEYWORD sep path_arg_str stmtend; | |
require_instance_stmt: REQUIRE_INSTANCE_KEYWORD sep require_instance_arg_str stmtend; | |
require_instance_arg_str: TRUE_KEYWORD optsep { if (read_all) { | |
((struct yang_type *)actual)->type->info.inst.req = 1; | |
} | |
} | |
| FALSE_KEYWORD optsep { if (read_all) { | |
((struct yang_type *)actual)->type->info.inst.req = -1; | |
} | |
} | |
| string_1 { if (read_all) { | |
if (!strcmp(s,"true")) { | |
((struct yang_type *)actual)->type->info.inst.req = 1; | |
} else if (!strcmp(s,"false")) { | |
((struct yang_type *)actual)->type->info.inst.req = -1; | |
} else { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "require-instance"); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
} | |
} | |
; | |
bits_specification: { if (read_all) { | |
if (size_arrays->node[size_arrays->next].bit) { | |
((struct yang_type *)actual)->type->info.bits.bit = calloc(size_arrays->node[size_arrays->next++].bit, sizeof(struct lys_type_bit)); | |
if (!((struct yang_type *)actual)->type->info.bits.bit) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
((struct yang_type *)actual)->base = LY_TYPE_BITS; | |
cnt_val = 0; | |
} else { | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} bit_stmt bit_stmts | |
bit_stmts: @EMPTYDIR@ | |
| bit_stmts bit_stmt; | |
bit_stmt: BIT_KEYWORD sep bit_arg_str bit_end | |
stmtsep { if (read_all) { | |
if (yang_check_bit($3, actual, &cnt_val, actual_type)) { | |
YYERROR; | |
} | |
actual = $3; | |
} else { | |
size_arrays->node[size_arrays->size-1].bit++; /* count of bit*/ | |
} | |
} | |
bit_arg_str: identifier_arg_str { if (read_all) { | |
$$ = actual; | |
if (!(actual = yang_read_bit(trg, actual, s))) { | |
YYERROR; | |
} | |
s = NULL; | |
actual_type = 0; | |
} | |
} | |
bit_end: ';' | |
| '{' stmtsep | |
bit_opt_stmt | |
'}' | |
; | |
bit_opt_stmt: @EMPTYDIR@ | |
| bit_opt_stmt position_stmt { /* actual_type - it is used to check position of bit statement*/ | |
if (read_all) { | |
if (actual_type) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "position", "bit"); | |
YYERROR; | |
} | |
actual_type = 1; | |
} | |
} | |
| bit_opt_stmt status_stmt { if (read_all) { | |
if (yang_check_flags(&((struct lys_type_bit *)actual)->flags, LYS_STATUS_MASK, "status", "bit", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| bit_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, "bit")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| bit_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, "bit")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
position_stmt: POSITION_KEYWORD sep position_value_arg_str | |
stmtend { if (read_all) { | |
((struct lys_type_bit *)actual)->pos = $3; | |
/* keep the highest position value for automatic increment */ | |
if ($3 > cnt_val) { | |
cnt_val = $3; | |
} | |
cnt_val++; | |
} | |
} | |
position_value_arg_str: non_negative_integer_value optsep { $$ = $1; } | |
| string_1 { /* convert it to uint32_t */ | |
unsigned long val; | |
char *endptr; | |
val = strtoul(s, &endptr, 10); | |
if (val > UINT32_MAX || s[0] == '-' || *endptr) { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "position"); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
$$ = (uint32_t) val; | |
} | |
error_message_stmt: ERROR_MESSAGE_KEYWORD sep string stmtend; | |
error_app_tag_stmt: ERROR_APP_TAG_KEYWORD sep string stmtend; | |
units_stmt: UNITS_KEYWORD sep string stmtend; | |
default_stmt: DEFAULT_KEYWORD sep string stmtend; | |
grouping_stmt: GROUPING_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_GROUPING,sizeof(struct lys_node_grp)))) {YYERROR;} | |
s=NULL; | |
} | |
} | |
grouping_end; | |
grouping_end: ';' | |
| '{' stmtsep | |
grouping_opt_stmt | |
'}' | |
; | |
grouping_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.grouping = actual; | |
actual_type = GROUPING_KEYWORD; | |
if (size_arrays->node[size_arrays->next].tpdf) { | |
$$.grouping->tpdf = calloc(size_arrays->node[size_arrays->next].tpdf, sizeof *$$.grouping->tpdf); | |
if (!$$.grouping->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.grouping, size_arrays->node[size_arrays->next].flags, 0); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| grouping_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "grouping", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| grouping_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.grouping, s, "grouping")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| grouping_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.grouping, s, "grouping")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| grouping_opt_stmt grouping_stmt stmtsep { actual = $1.grouping; actual_type = GROUPING_KEYWORD; } | |
| grouping_opt_stmt typedef_stmt stmtsep { if (read_all) { | |
actual = $1.grouping; | |
actual_type = GROUPING_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].tpdf++; | |
} | |
} | |
| grouping_opt_stmt data_def_stmt stmtsep { actual = $1.grouping; actual_type = GROUPING_KEYWORD; } | |
; | |
data_def_stmt: container_stmt | |
| leaf_stmt | |
| leaf_list_stmt | |
| list_stmt | |
| choice_stmt | |
| anyxml_stmt | |
| uses_stmt | |
; | |
container_stmt: CONTAINER_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_CONTAINER,sizeof(struct lys_node_container)))) {YYERROR;} | |
data_node = actual; | |
s=NULL; | |
} | |
} | |
container_end ; | |
container_end: ';' | |
| '{' stmtsep | |
container_opt_stmt | |
'}' | |
; | |
container_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.container = actual; | |
actual_type = CONTAINER_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.container->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.container->features); | |
if (!$$.container->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].must) { | |
$$.container->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.container->must); | |
if (!$$.container->must) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].tpdf) { | |
$$.container->tpdf = calloc(size_arrays->node[size_arrays->next].tpdf, sizeof *$$.container->tpdf); | |
if (!$$.container->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.container, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| container_opt_stmt when_stmt { actual = $1.container; actual_type = CONTAINER_KEYWORD; } | |
stmtsep | |
| container_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.container, s, unres, CONTAINER_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| container_opt_stmt must_stmt { if (read_all) { | |
actual = $1.container; | |
actual_type = CONTAINER_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
stmtsep | |
| container_opt_stmt presence_stmt { if (read_all && yang_read_presence(trg, $1.container, s)) {YYERROR;} s=NULL; } | |
| container_opt_stmt config_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_CONFIG_MASK, "config", "container", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| container_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "container", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| container_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.container, s, "container")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| container_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.container, s, "container")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| container_opt_stmt grouping_stmt { actual = $1.container; | |
actual_type = CONTAINER_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
| container_opt_stmt typedef_stmt { if (read_all) { | |
actual = $1.container; | |
actual_type = CONTAINER_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].tpdf++; | |
} | |
} | |
stmtsep | |
| container_opt_stmt data_def_stmt { actual = $1.container; | |
actual_type = CONTAINER_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
; | |
leaf_stmt: LEAF_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_LEAF,sizeof(struct lys_node_leaf)))) {YYERROR;} | |
data_node = actual; | |
s=NULL; | |
} | |
} | |
'{' stmtsep | |
leaf_opt_stmt { if (read_all) { | |
if (!($7.node.flag & LYS_TYPE_DEF)) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, $7.node.ptr_leaf, "type", "leaf"); | |
YYERROR; | |
} else { | |
if (unres_schema_add_node(trg, unres, &$7.node.ptr_leaf->type, UNRES_TYPE_DER,(struct lys_node *) $7.node.ptr_leaf->parent)) { | |
$7.node.ptr_leaf->type.der = NULL; | |
YYERROR; | |
} | |
} | |
if ($7.node.ptr_leaf->dflt) { | |
if ($7.node.ptr_leaf->flags & LYS_MAND_TRUE) { | |
/* RFC 6020, 7.6.4 - default statement must not with mandatory true */ | |
LOGVAL(LYE_INCHILDSTMT, LY_VLOG_LYS, $7.node.ptr_leaf, "mandatory", "leaf"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"mandatory\" statement is forbidden on leaf with \"default\"."); | |
YYERROR; | |
} | |
if (unres_schema_add_str(trg, unres, &$7.node.ptr_leaf->type, UNRES_TYPE_DFLT, $7.node.ptr_leaf->dflt) == -1) { | |
YYERROR; | |
} | |
} | |
} | |
} | |
'}' ; | |
leaf_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.node.ptr_leaf = actual; | |
$$.node.flag = 0; | |
actual_type = LEAF_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.node.ptr_leaf->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaf->features); | |
if (!$$.node.ptr_leaf->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].must) { | |
$$.node.ptr_leaf->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.node.ptr_leaf->must); | |
if (!$$.node.ptr_leaf->must) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.node.ptr_leaf, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| leaf_opt_stmt when_stmt { actual = $1.node.ptr_leaf; actual_type = LEAF_KEYWORD; } | |
stmtsep | |
| leaf_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.node.ptr_leaf, s, unres, LEAF_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| leaf_opt_stmt { if (read_all && ($1.node.flag & LYS_TYPE_DEF)) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaf, "type", "leaf"); | |
YYERROR; | |
} | |
} | |
type_stmt { if (read_all) { | |
actual = $1.node.ptr_leaf; | |
actual_type = LEAF_KEYWORD; | |
$1.node.flag |= LYS_TYPE_DEF; | |
} | |
} | |
stmtsep { $$ = $1;} | |
| leaf_opt_stmt units_stmt { if (read_all && yang_read_units(trg, $1.node.ptr_leaf, s, LEAF_KEYWORD)) {YYERROR;} s = NULL; } | |
| leaf_opt_stmt must_stmt { if (read_all) { | |
actual = $1.node.ptr_leaf; | |
actual_type = LEAF_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
stmtsep | |
| leaf_opt_stmt default_stmt { if (read_all && yang_read_default(trg, $1.node.ptr_leaf, s, LEAF_KEYWORD)) {YYERROR;} | |
s = NULL; | |
} | |
| leaf_opt_stmt config_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_CONFIG_MASK, "config", "leaf", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| leaf_opt_stmt mandatory_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_MAND_MASK, "mandatory", "leaf", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| leaf_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "leaf", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| leaf_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_leaf, s, "leaf")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| leaf_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_leaf, s, "leaf")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
leaf_list_stmt: LEAF_LIST_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_LEAFLIST,sizeof(struct lys_node_leaflist)))) {YYERROR;} | |
data_node = actual; | |
s=NULL; | |
} | |
} | |
'{' stmtsep | |
leaf_list_opt_stmt { if (read_all) { | |
if ($7.node.ptr_leaflist->flags & LYS_CONFIG_R) { | |
/* RFC 6020, 7.7.5 - ignore ordering when the list represents state data | |
* ignore oredering MASK - 0x7F | |
*/ | |
$7.node.ptr_leaflist->flags &= 0x7F; | |
} | |
if ($7.node.ptr_leaflist->max && $7.node.ptr_leaflist->min > $7.node.ptr_leaflist->max) { | |
LOGVAL(LYE_SPEC, LY_VLOG_LYS, $7.node.ptr_leaflist, "\"min-elements\" is bigger than \"max-elements\"."); | |
YYERROR; | |
} | |
if (!($7.node.flag & LYS_TYPE_DEF)) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, $7.node.ptr_leaflist, "type", "leaf-list"); | |
YYERROR; | |
} else { | |
if (unres_schema_add_node(trg, unres, &$7.node.ptr_leaflist->type, UNRES_TYPE_DER, | |
(struct lys_node *) $7.node.ptr_leaflist->parent)) { | |
YYERROR; | |
} | |
} | |
} | |
} | |
'}' ; | |
leaf_list_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.node.ptr_leaflist = actual; | |
$$.node.flag = 0; | |
actual_type = LEAF_LIST_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.node.ptr_leaflist->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_leaflist->features); | |
if (!$$.node.ptr_leaflist->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].must) { | |
$$.node.ptr_leaflist->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.node.ptr_leaflist->must); | |
if (!$$.node.ptr_leaflist->must) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.node.ptr_leaflist, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| leaf_list_opt_stmt when_stmt { actual = $1.node.ptr_leaflist; actual_type = LEAF_LIST_KEYWORD; } | |
stmtsep | |
| leaf_list_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.node.ptr_leaflist, s, unres, LEAF_LIST_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| leaf_list_opt_stmt { if (read_all && ($1.node.flag & LYS_TYPE_DEF)) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "type", "leaf-list"); | |
YYERROR; | |
} | |
} | |
type_stmt { if (read_all) { | |
actual = $1.node.ptr_leaflist; | |
actual_type = LEAF_LIST_KEYWORD; | |
$1.node.flag |= LYS_TYPE_DEF; | |
} | |
} | |
stmtsep { $$ = $1; } | |
| leaf_list_opt_stmt units_stmt { if (read_all && yang_read_units(trg, $1.node.ptr_leaflist, s, LEAF_LIST_KEYWORD)) {YYERROR;} s = NULL; } | |
| leaf_list_opt_stmt must_stmt { if (read_all) { | |
actual = $1.node.ptr_leaflist; | |
actual_type = LEAF_LIST_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
stmtsep | |
| leaf_list_opt_stmt config_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_CONFIG_MASK, "config", "leaf-list", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| leaf_list_opt_stmt min_elements_stmt { if (read_all) { | |
if ($1.node.flag & LYS_MIN_ELEMENTS) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "min-elements", "leaf-list"); | |
YYERROR; | |
} | |
$1.node.ptr_leaflist->min = $2; | |
$1.node.flag |= LYS_MIN_ELEMENTS; | |
$$ = $1; | |
if ($1.node.ptr_leaflist->max && ($1.node.ptr_leaflist->min > $1.node.ptr_leaflist->max)) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", $2, "min-elements"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\"."); | |
} | |
} | |
} | |
| leaf_list_opt_stmt max_elements_stmt { if (read_all) { | |
if ($1.node.flag & LYS_MAX_ELEMENTS) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "max-elements", "leaf-list"); | |
YYERROR; | |
} | |
$1.node.ptr_leaflist->max = $2; | |
$1.node.flag |= LYS_MAX_ELEMENTS; | |
$$ = $1; | |
if ($1.node.ptr_leaflist->min > $1.node.ptr_leaflist->max) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", $2, "max-elements"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\"."); | |
} | |
} | |
} | |
| leaf_list_opt_stmt ordered_by_stmt { if (read_all) { | |
if ($1.node.flag & LYS_ORDERED_MASK) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_leaflist, "ordered by", "leaf-list"); | |
YYERROR; | |
} | |
if ($2 & LYS_USERORDERED) { | |
$1.node.ptr_leaflist->flags |= LYS_USERORDERED; | |
} | |
$1.node.flag |= $2; | |
$$ = $1; | |
} | |
} | |
| leaf_list_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "leaf-list", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| leaf_list_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_leaflist, s, "leaf-list")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| leaf_list_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_leaflist, s, "leaf-list")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
list_stmt: LIST_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_LIST,sizeof(struct lys_node_list)))) {YYERROR;} | |
data_node = actual; | |
s=NULL; | |
} | |
} | |
'{' stmtsep | |
list_opt_stmt { if (read_all) { | |
if ($7.node.ptr_list->flags & LYS_CONFIG_R) { | |
/* RFC 6020, 7.7.5 - ignore ordering when the list represents state data | |
* ignore oredering MASK - 0x7F | |
*/ | |
$7.node.ptr_list->flags &= 0x7F; | |
} | |
if (($7.node.ptr_list->flags & LYS_CONFIG_W) && !$7.node.ptr_list->keys) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_LYS, $7.node.ptr_list, "key", "list"); | |
YYERROR; | |
} | |
if ($7.node.ptr_list->keys && yang_read_key(trg, $7.node.ptr_list, unres)) { | |
YYERROR; | |
} | |
if (!($7.node.flag & LYS_DATADEF)) { | |
LOGVAL(LYE_SPEC, LY_VLOG_LYS, $7.node.ptr_list, "data-def statement missing."); | |
YYERROR; | |
} | |
if (yang_read_unique(trg, $7.node.ptr_list, unres)) { | |
YYERROR; | |
} | |
} | |
} | |
'}' ; | |
list_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.node.ptr_list = actual; | |
$$.node.flag = 0; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.node.ptr_list->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_list->features); | |
if (!$$.node.ptr_list->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].must) { | |
$$.node.ptr_list->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.node.ptr_list->must); | |
if (!$$.node.ptr_list->must) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].tpdf) { | |
$$.node.ptr_list->tpdf = calloc(size_arrays->node[size_arrays->next].tpdf, sizeof *$$.node.ptr_list->tpdf); | |
if (!$$.node.ptr_list->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].unique) { | |
$$.node.ptr_list->unique = calloc(size_arrays->node[size_arrays->next].unique, sizeof *$$.node.ptr_list->unique); | |
if (!$$.node.ptr_list->unique) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.node.ptr_list, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| list_opt_stmt when_stmt { actual = $1.node.ptr_list; actual_type = LIST_KEYWORD; } | |
stmtsep | |
| list_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.node.ptr_list, s, unres, LIST_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| list_opt_stmt must_stmt { if (read_all) { | |
actual = $1.node.ptr_list; | |
actual_type = LIST_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
stmtsep | |
| list_opt_stmt key_stmt { if (read_all) { | |
if ($1.node.ptr_list->keys) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "key", "list"); | |
YYERROR; | |
} | |
$1.node.ptr_list->keys = (struct lys_node_leaf **)s; | |
$$ = $1; | |
s=NULL; | |
} | |
} | |
| list_opt_stmt unique_stmt { if (read_all) { | |
$1.node.ptr_list->unique[$1.node.ptr_list->unique_size++].expr = (const char **)s; | |
$$ = $1; | |
s = NULL; | |
} else { | |
size_arrays->node[$1.index].unique++; | |
} | |
} | |
| list_opt_stmt config_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_CONFIG_MASK, "config", "list", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| list_opt_stmt min_elements_stmt { if (read_all) { | |
if ($1.node.flag & LYS_MIN_ELEMENTS) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "min-elements", "list"); | |
YYERROR; | |
} | |
$1.node.ptr_list->min = $2; | |
$1.node.flag |= LYS_MIN_ELEMENTS; | |
$$ = $1; | |
if ($1.node.ptr_list->max && ($1.node.ptr_list->min > $1.node.ptr_list->max)) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", $2, "min-elements"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\"."); | |
} | |
} | |
} | |
| list_opt_stmt max_elements_stmt { if (read_all) { | |
if ($1.node.flag & LYS_MAX_ELEMENTS) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "max-elements", "list"); | |
YYERROR; | |
} | |
$1.node.ptr_list->max = $2; | |
$1.node.flag |= LYS_MAX_ELEMENTS; | |
$$ = $1; | |
if ($1.node.ptr_list->min > $1.node.ptr_list->max) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid value \"%d\" of \"%s\".", $2, "min-elements"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "\"max-elements\" is smaller than \"min-elements\"."); | |
} | |
} | |
} | |
| list_opt_stmt ordered_by_stmt { if (read_all) { | |
if ($1.node.flag & LYS_ORDERED_MASK) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_list, "ordered by", "list"); | |
YYERROR; | |
} | |
if ($2 & LYS_USERORDERED) { | |
$1.node.ptr_list->flags |= LYS_USERORDERED; | |
} | |
$1.node.flag |= $2; | |
$$ = $1; | |
} | |
} | |
| list_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "list", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| list_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_list, s, "list")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| list_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_list, s, "list")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| list_opt_stmt typedef_stmt { if (read_all) { | |
actual = $1.node.ptr_list; | |
actual_type = LIST_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].tpdf++; | |
} | |
} | |
stmtsep | |
| list_opt_stmt grouping_stmt { actual = $1.node.ptr_list; | |
actual_type = LIST_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
| list_opt_stmt data_def_stmt { actual = $1.node.ptr_list; | |
actual_type = LIST_KEYWORD; | |
$1.node.flag |= LYS_DATADEF; | |
data_node = actual; | |
} | |
stmtsep { $$ = $1; } | |
; | |
choice_stmt: CHOICE_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_CHOICE,sizeof(struct lys_node_choice)))) {YYERROR;} | |
data_node = actual; | |
if (data_node->parent && (data_node->parent->nodetype == LYS_GROUPING)) { | |
data_node = NULL; | |
} | |
s=NULL; | |
} | |
} | |
choice_end; | |
choice_end: ';' | |
| '{' stmtsep | |
choice_opt_stmt { if (read_all) { | |
if ($3.choice.s && ($3.choice.ptr_choice->flags & LYS_MAND_TRUE)) { | |
LOGVAL(LYE_INCHILDSTMT, LY_VLOG_NONE, NULL, "default", "choice"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\"."); | |
YYERROR; | |
} | |
/* link default with the case */ | |
if ($3.choice.s) { | |
if (unres_schema_add_str(trg, unres, $3.choice.ptr_choice, UNRES_CHOICE_DFLT, $3.choice.s) == -1) { | |
YYERROR; | |
} | |
free($3.choice.s); | |
} | |
} | |
} | |
'}' ; | |
choice_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.choice.ptr_choice = actual; | |
$$.choice.s = NULL; | |
actual_type = CHOICE_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.choice.ptr_choice->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.choice.ptr_choice->features); | |
if (!$$.choice.ptr_choice->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.choice.ptr_choice, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| choice_opt_stmt when_stmt { actual = $1.choice.ptr_choice; actual_type = CHOICE_KEYWORD; } | |
stmtsep { $$ = $1; } | |
| choice_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.choice.ptr_choice,s, unres, CHOICE_KEYWORD)) { | |
if ($1.choice.s) { | |
free($1.choice.s); | |
} | |
YYERROR; | |
} | |
s=NULL; | |
$$ = $1; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| choice_opt_stmt default_stmt { if (read_all) { | |
if ($1.choice.s) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.choice.ptr_choice, "default", "choice"); | |
free($1.choice.s); | |
free(s); | |
YYERROR; | |
} | |
$1.choice.s = s; | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| choice_opt_stmt config_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_CONFIG_MASK, "config", "choice", $2)) { | |
YYERROR; | |
} | |
} else { | |
$$ = $1; | |
} | |
} | |
| choice_opt_stmt mandatory_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_MAND_MASK, "mandatory", "choice", $2)) { | |
YYERROR; | |
} | |
} else { | |
$$ = $1; | |
} | |
} | |
| choice_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "choice", $2)) { | |
YYERROR; | |
} | |
} else { | |
$$ = $1; | |
} | |
} | |
| choice_opt_stmt description_stmt { if (read_all) { | |
if (yang_read_description(trg, $1.choice.ptr_choice, s, "choice")) { | |
free($1.choice.s); | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| choice_opt_stmt reference_stmt { if (read_all) { | |
if (yang_read_reference(trg, $1.choice.ptr_choice, s, "choice")) { | |
free($1.choice.s); | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| choice_opt_stmt short_case_case_stmt { actual = $1.choice.ptr_choice; | |
actual_type = CHOICE_KEYWORD; | |
data_node = actual; | |
if (read_all && data_node->parent && (data_node->parent->nodetype == LYS_GROUPING)) { | |
data_node = NULL; | |
} | |
} | |
stmtsep { $$ = $1; } | |
; | |
short_case_case_stmt: short_case_stmt | |
| case_stmt | |
; | |
short_case_stmt: container_stmt | |
| leaf_stmt | |
| leaf_list_stmt | |
| list_stmt | |
| anyxml_stmt | |
; | |
case_stmt: CASE_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_CASE,sizeof(struct lys_node_case)))) {YYERROR;} | |
data_node = actual; | |
s=NULL; | |
} | |
} | |
case_end; | |
case_end: ';' | |
| '{' stmtsep | |
case_opt_stmt | |
'}' ; | |
case_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.cs = actual; | |
actual_type = CASE_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.cs->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.cs->features); | |
if (!$$.cs->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.cs, size_arrays->node[size_arrays->next].flags, 1); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| case_opt_stmt when_stmt { actual = $1.cs; actual_type = CASE_KEYWORD; } | |
stmtsep | |
| case_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.cs, s, unres, CASE_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| case_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "case", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| case_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.cs, s, "case")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| case_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.cs, s, "case")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| case_opt_stmt data_def_stmt { actual = $1.cs; | |
actual_type = CASE_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
; | |
anyxml_stmt: ANYXML_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_ANYXML,sizeof(struct lys_node_anyxml)))) {YYERROR;} | |
data_node = actual; | |
if (data_node->parent && (data_node->parent->nodetype == LYS_GROUPING)) { | |
data_node = NULL; | |
} | |
s=NULL; | |
} | |
} | |
anyxml_end; | |
anyxml_end: ';' | |
| '{' stmtsep | |
anyxml_opt_stmt | |
'}' ; | |
anyxml_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.anyxml = actual; | |
actual_type = ANYXML_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.anyxml->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.anyxml->features); | |
if (!$$.anyxml->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].must) { | |
$$.anyxml->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.anyxml->must); | |
if (!$$.anyxml->features || !$$.anyxml->must) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.anyxml, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| anyxml_opt_stmt when_stmt { actual = $1.anyxml; actual_type = ANYXML_KEYWORD; } | |
stmtsep | |
| anyxml_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.anyxml, s, unres, ANYXML_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| anyxml_opt_stmt must_stmt { if (read_all) { | |
actual = $1.anyxml; | |
actual_type = ANYXML_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
stmtsep | |
| anyxml_opt_stmt config_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_CONFIG_MASK, "config", "anyxml", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| anyxml_opt_stmt mandatory_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_MAND_MASK, "mandatory", "anyxml", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| anyxml_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "anyxml", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| anyxml_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.anyxml, s, "anyxml")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| anyxml_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.anyxml, s, "anyxml")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
uses_stmt: USES_KEYWORD sep identifier_ref_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg,actual,s,LYS_USES,sizeof(struct lys_node_uses)))) {YYERROR;} | |
data_node = actual; | |
if (data_node->parent && (data_node->parent->nodetype == LYS_GROUPING)) { | |
data_node = NULL; | |
} | |
s=NULL; | |
} | |
} | |
uses_end { if (read_all) { | |
if (unres_schema_add_node(trg, unres, actual, UNRES_USES, NULL) == -1) { | |
YYERROR; | |
} | |
} | |
} | |
uses_end: ';' | |
| '{' stmtsep | |
uses_opt_stmt | |
'}' ; | |
uses_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.uses.ptr_uses = actual; | |
$$.uses.config_inherit = config_inherit; | |
actual_type = USES_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.uses.ptr_uses->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.uses.ptr_uses->features); | |
if (!$$.uses.ptr_uses->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].refine) { | |
$$.uses.ptr_uses->refine = calloc(size_arrays->node[size_arrays->next].refine, sizeof *$$.uses.ptr_uses->refine); | |
if (!$$.uses.ptr_uses->refine) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].augment) { | |
$$.uses.ptr_uses->augment = calloc(size_arrays->node[size_arrays->next].augment, sizeof *$$.uses.ptr_uses->augment); | |
if (!$$.uses.ptr_uses->augment) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.uses.ptr_uses, size_arrays->node[size_arrays->next].flags, config_inherit); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| uses_opt_stmt when_stmt { actual = $1.uses.ptr_uses; actual_type = USES_KEYWORD; } | |
stmtsep | |
| uses_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.uses.ptr_uses, s, unres, USES_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| uses_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "uses", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| uses_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.uses.ptr_uses, s, "uses")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| uses_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.uses.ptr_uses, s, "uses")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| uses_opt_stmt refine_stmt { if (read_all) { | |
actual = $1.uses.ptr_uses; | |
actual_type = USES_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].refine++; | |
} | |
} | |
stmtsep | |
| uses_opt_stmt uses_augment_stmt { if (read_all) { | |
actual = $1.uses.ptr_uses; | |
actual_type = USES_KEYWORD; | |
data_node = actual; | |
if (data_node->parent && (data_node->parent->nodetype == LYS_GROUPING)) { | |
data_node = NULL; | |
} | |
config_inherit = $1.uses.config_inherit; | |
} else { | |
size_arrays->node[$1.index].augment++; | |
} | |
} | |
stmtsep | |
; | |
refine_stmt: REFINE_KEYWORD sep refine_arg_str { if (read_all) { | |
if (!(actual = yang_read_refine(trg, actual, s))) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
} | |
refine_end; | |
refine_end: ';' | |
| '{' stmtsep | |
refine_body_opt_stmts | |
'}' ; | |
refine_arg_str: descendant_schema_nodeid optsep | |
| string_1 | |
; | |
refine_body_opt_stmts: @EMPTYDIR@ { if (read_all) { | |
$$.refine = actual; | |
actual_type = REFINE_KEYWORD; | |
if (size_arrays->node[size_arrays->next].must) { | |
$$.refine->must = calloc(size_arrays->node[size_arrays->next].must, sizeof *$$.refine->must); | |
if (!$$.refine->must) { | |
LOGMEM; | |
YYERROR; | |
} | |
$$.refine->target_type = LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML; | |
} | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| refine_body_opt_stmts must_stmt stmtsep { if (read_all) { | |
actual = $1.refine; | |
actual_type = REFINE_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
| refine_body_opt_stmts presence_stmt { if (read_all) { | |
if ($1.refine->target_type) { | |
if ($1.refine->target_type & LYS_CONTAINER) { | |
if ($1.refine->mod.presence) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "presence", "refine"); | |
free(s); | |
YYERROR; | |
} | |
$1.refine->target_type = LYS_CONTAINER; | |
$1.refine->mod.presence = lydict_insert_zc(trg->ctx, s); | |
} else { | |
free(s); | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "presence", "refine"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements."); | |
YYERROR; | |
} | |
} else { | |
$1.refine->target_type = LYS_CONTAINER; | |
$1.refine->mod.presence = lydict_insert_zc(trg->ctx, s); | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| refine_body_opt_stmts default_stmt { if (read_all) { | |
if ($1.refine->target_type) { | |
if ($1.refine->target_type & (LYS_LEAF | LYS_CHOICE)) { | |
$1.refine->target_type &= (LYS_LEAF | LYS_CHOICE); | |
if ($1.refine->mod.dflt) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "default", "refine"); | |
free(s); | |
YYERROR; | |
} | |
$1.refine->mod.dflt = lydict_insert_zc(trg->ctx, s); | |
} else { | |
free(s); | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "default", "refine"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements."); | |
YYERROR; | |
} | |
} else { | |
$1.refine->target_type = LYS_LEAF | LYS_CHOICE; | |
$1.refine->mod.dflt = lydict_insert_zc(trg->ctx, s); | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| refine_body_opt_stmts config_stmt { if (read_all) { | |
if ($1.refine->target_type) { | |
if ($1.refine->target_type & (LYS_LEAF | LYS_CHOICE | LYS_LIST | LYS_CONTAINER | LYS_LEAFLIST)) { | |
$1.refine->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_LIST | LYS_CONTAINER | LYS_LEAFLIST); | |
if (yang_check_flags(&$1.refine->flags, LYS_CONFIG_MASK, "config", "refine", $2)) { | |
YYERROR; | |
} | |
} else { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "config", "refine"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements."); | |
YYERROR; | |
} | |
} else { | |
$1.refine->target_type = LYS_LEAF | LYS_CHOICE | LYS_LIST | LYS_CONTAINER | LYS_LEAFLIST; | |
$1.refine->flags |= $2; | |
} | |
$$ = $1; | |
} | |
} | |
| refine_body_opt_stmts mandatory_stmt { if (read_all) { | |
if ($1.refine->target_type) { | |
if ($1.refine->target_type & (LYS_LEAF | LYS_CHOICE | LYS_ANYXML)) { | |
$1.refine->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML); | |
if (yang_check_flags(&$1.refine->flags, LYS_MAND_MASK, "mandatory", "refine", $2)) { | |
YYERROR; | |
} | |
} else { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "mandatory", "refine"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements."); | |
YYERROR; | |
} | |
} else { | |
$1.refine->target_type = LYS_LEAF | LYS_CHOICE | LYS_ANYXML; | |
$1.refine->flags |= $2; | |
} | |
$$ = $1; | |
} | |
} | |
| refine_body_opt_stmts min_elements_stmt { if (read_all) { | |
if ($1.refine->target_type) { | |
if ($1.refine->target_type & (LYS_LIST | LYS_LEAFLIST)) { | |
$1.refine->target_type &= (LYS_LIST | LYS_LEAFLIST); | |
/* magic - bit 3 in flags means min set */ | |
if ($1.refine->flags & 0x04) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "min-elements", "refine"); | |
YYERROR; | |
} | |
$1.refine->flags |= 0x04; | |
$1.refine->mod.list.min = $2; | |
} else { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "min-elements", "refine"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements."); | |
YYERROR; | |
} | |
} else { | |
$1.refine->target_type = LYS_LIST | LYS_LEAFLIST; | |
/* magic - bit 3 in flags means min set */ | |
$1.refine->flags |= 0x04; | |
$1.refine->mod.list.min = $2; | |
} | |
$$ = $1; | |
} | |
} | |
| refine_body_opt_stmts max_elements_stmt { if (read_all) { | |
if ($1.refine->target_type) { | |
if ($1.refine->target_type & (LYS_LIST | LYS_LEAFLIST)) { | |
$1.refine->target_type &= (LYS_LIST | LYS_LEAFLIST); | |
/* magic - bit 4 in flags means max set */ | |
if ($1.refine->flags & 0x08) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "max-elements", "refine"); | |
YYERROR; | |
} | |
$1.refine->flags |= 0x08; | |
$1.refine->mod.list.max = $2; | |
} else { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "max-elements", "refine"); | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Invalid refine target nodetype for the substatements."); | |
YYERROR; | |
} | |
} else { | |
$1.refine->target_type = LYS_LIST | LYS_LEAFLIST; | |
/* magic - bit 4 in flags means max set */ | |
$1.refine->flags |= 0x08; | |
$1.refine->mod.list.max = $2; | |
} | |
$$ = $1; | |
} | |
} | |
| refine_body_opt_stmts description_stmt { if (read_all && yang_read_description(trg, $1.refine, s, "refine")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| refine_body_opt_stmts reference_stmt { if (read_all && yang_read_reference(trg, $1.refine, s, "refine")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
uses_augment_stmt: AUGMENT_KEYWORD sep uses_augment_arg_str { if (read_all) { | |
if (!(actual = yang_read_augment(trg, actual, s))) { | |
YYERROR; | |
} | |
data_node = actual; | |
s = NULL; | |
} | |
} | |
'{' stmtsep | |
augment_opt_stmt { if (read_all && !($7.node.flag & LYS_DATADEF)){ | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "data-def or case", "uses/augment"); | |
YYERROR; | |
} | |
} | |
'}' ; | |
uses_augment_arg_str: descendant_schema_nodeid optsep | |
| string_1 | |
; | |
augment_stmt: AUGMENT_KEYWORD sep augment_arg_str { if (read_all) { | |
if (!(actual = yang_read_augment(trg, NULL, s))) { | |
YYERROR; | |
} | |
data_node = actual; | |
s = NULL; | |
} | |
} | |
'{' stmtsep | |
augment_opt_stmt { if (read_all) { | |
if (!($7.node.flag & LYS_DATADEF)){ | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "data-def or case", "augment"); | |
YYERROR; | |
} | |
if (unres_schema_add_node(trg, unres, actual, UNRES_AUGMENT, NULL) == -1) { | |
YYERROR; | |
} | |
} | |
} | |
'}' ; | |
augment_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.node.ptr_augment = actual; | |
$$.node.flag = 0; | |
actual_type = AUGMENT_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.node.ptr_augment->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_augment->features); | |
if (!$$.node.ptr_augment->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
config_inherit = DISABLE_INHERIT; | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| augment_opt_stmt when_stmt { actual = $1.node.ptr_augment; actual_type = AUGMENT_KEYWORD; } | |
stmtsep | |
| augment_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.node.ptr_augment, s, unres, AUGMENT_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| augment_opt_stmt status_stmt { if (read_all) { | |
if (yang_check_flags(&$1.node.ptr_augment->flags, LYS_STATUS_MASK, "status", "augment", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| augment_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_augment, s, "augment")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| augment_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_augment, s, "augment")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| augment_opt_stmt data_def_stmt { if (read_all) { | |
actual = $1.node.ptr_augment; | |
actual_type = AUGMENT_KEYWORD; | |
$1.node.flag |= LYS_DATADEF; | |
data_node = actual; | |
} | |
} | |
stmtsep { $$ = $1; } | |
| augment_opt_stmt case_stmt { if (read_all) { | |
actual = $1.node.ptr_augment; | |
actual_type = AUGMENT_KEYWORD; | |
$1.node.flag |= LYS_DATADEF; | |
data_node = actual; | |
} | |
} | |
stmtsep { $$ = $1; } | |
; | |
augment_arg_str: absolute_schema_nodeids optsep | |
| string_1 | |
; | |
rpc_stmt: RPC_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg, NULL, s, LYS_RPC, sizeof(struct lys_node_rpc)))) { | |
YYERROR; | |
} | |
data_node = actual; | |
s = NULL; | |
} | |
config_inherit = DISABLE_INHERIT; | |
} | |
rpc_end { config_inherit = ENABLE_INHERIT; } | |
rpc_end: ';' | |
| '{' stmtsep | |
rpc_opt_stmt | |
'}' | |
rpc_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.node.ptr_rpc = actual; | |
$$.node.flag = 0; | |
actual_type = RPC_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.node.ptr_rpc->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_rpc->features); | |
if (!$$.node.ptr_rpc->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].tpdf) { | |
$$.node.ptr_rpc->tpdf = calloc(size_arrays->node[size_arrays->next].tpdf, sizeof *$$.node.ptr_rpc->tpdf); | |
if (!$$.node.ptr_rpc->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.node.ptr_rpc, size_arrays->node[size_arrays->next].flags, 0); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| rpc_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.node.ptr_rpc, s, unres, RPC_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| rpc_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "rpc", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| rpc_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_rpc, s, "rpc")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| rpc_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_rpc, s, "rpc")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| rpc_opt_stmt typedef_stmt { if (read_all) { | |
actual = $1.node.ptr_rpc; | |
actual_type = RPC_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].tpdf++; | |
} | |
} | |
stmtsep | |
| rpc_opt_stmt grouping_stmt { actual = $1.node.ptr_rpc; | |
actual_type = RPC_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
| rpc_opt_stmt input_stmt { if (read_all) { | |
if ($1.node.flag & LYS_RPC_INPUT) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_rpc, "input", "rpc"); | |
YYERROR; | |
} | |
$1.node.flag |= LYS_RPC_INPUT; | |
actual = $1.node.ptr_rpc; | |
actual_type = RPC_KEYWORD; | |
data_node = actual; | |
} | |
} | |
stmtsep { $$ = $1; } | |
| rpc_opt_stmt output_stmt { if (read_all) { | |
if ($1.node.flag & LYS_RPC_OUTPUT) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_LYS, $1.node.ptr_rpc, "output", "rpc"); | |
YYERROR; | |
} | |
$1.node.flag |= LYS_RPC_OUTPUT; | |
actual = $1.node.ptr_rpc; | |
actual_type = RPC_KEYWORD; | |
data_node = actual; | |
} | |
} | |
stmtsep { $$ = $1; } | |
input_stmt: INPUT_KEYWORD optsep { if (read_all) { | |
if (!(actual = yang_read_node(trg, actual, NULL, LYS_INPUT, sizeof(struct lys_node_rpc_inout)))) { | |
YYERROR; | |
} | |
data_node = actual; | |
} | |
} | |
'{' stmtsep | |
input_output_opt_stmt { if (read_all && !($6.node.flag & LYS_DATADEF)) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, "data-def", "input"); | |
YYERROR; | |
} | |
} | |
'}' | |
input_output_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.node.ptr_inout = actual; | |
$$.node.flag = 0; | |
actual_type = INPUT_KEYWORD; | |
if (size_arrays->node[size_arrays->next].tpdf) { | |
$$.node.ptr_inout->tpdf = calloc(size_arrays->node[size_arrays->next].tpdf, sizeof *$$.node.ptr_inout->tpdf); | |
if (!$$.node.ptr_inout->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| input_output_opt_stmt typedef_stmt { if (read_all) { | |
actual = $1.node.ptr_inout; | |
actual_type = INPUT_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].tpdf++; | |
} | |
} | |
stmtsep | |
| input_output_opt_stmt grouping_stmt { actual = $1.node.ptr_inout; | |
actual_type = INPUT_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
| input_output_opt_stmt data_def_stmt { if (read_all) { | |
actual = $1.node.ptr_inout; | |
actual_type = INPUT_KEYWORD; | |
$1.node.flag |= LYS_DATADEF; | |
data_node = actual; | |
} | |
} | |
stmtsep { $$ = $1; } | |
; | |
output_stmt: OUTPUT_KEYWORD optsep { if (read_all) { | |
if (!(actual = yang_read_node(trg, actual, NULL, LYS_OUTPUT, sizeof(struct lys_node_rpc_inout)))) { | |
YYERROR; | |
} | |
data_node = actual; | |
} | |
} | |
'{' stmtsep | |
input_output_opt_stmt { if (read_all && !($6.node.flag & LYS_DATADEF)) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, "data-def", "output"); | |
YYERROR; | |
} | |
} | |
'}' | |
notification_stmt: NOTIFICATION_KEYWORD sep identifier_arg_str { if (read_all) { | |
if (!(actual = yang_read_node(trg, NULL, s, LYS_NOTIF, sizeof(struct lys_node_notif)))) { | |
YYERROR; | |
} | |
data_node = actual; | |
} | |
config_inherit = DISABLE_INHERIT; | |
} | |
notification_end { config_inherit = ENABLE_INHERIT; } | |
notification_end: ';' { if (read_all) { | |
size_arrays->next++; | |
} | |
} | |
| '{' stmtsep | |
notification_opt_stmt | |
'}' ; | |
notification_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.notif = actual; | |
actual_type = NOTIFICATION_KEYWORD; | |
if (size_arrays->node[size_arrays->next].if_features) { | |
$$.notif->features = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.notif->features); | |
if (!$$.notif->features) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].tpdf) { | |
$$.notif->tpdf = calloc(size_arrays->node[size_arrays->next].tpdf, sizeof *$$.notif->tpdf); | |
if (!$$.notif->tpdf) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
store_flags((struct lys_node *)$$.notif, size_arrays->node[size_arrays->next].flags, 0); | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| notification_opt_stmt if_feature_stmt { if (read_all) { | |
if (yang_read_if_feature(trg, $1.notif, s, unres, NOTIFICATION_KEYWORD)) {YYERROR;} | |
s=NULL; | |
} else { | |
size_arrays->node[$1.index].if_features++; | |
} | |
} | |
| notification_opt_stmt status_read_stmt { if (!read_all) { | |
if (yang_check_flags(&size_arrays->node[$1.index].flags, LYS_STATUS_MASK, "status", "notification", $2)) { | |
YYERROR; | |
} | |
} | |
} | |
| notification_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.notif, s, "notification")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| notification_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.notif, s, "notification")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| notification_opt_stmt typedef_stmt { if (read_all) { | |
actual = $1.notif; | |
actual_type = NOTIFICATION_KEYWORD; | |
} else { | |
size_arrays->node[$1.index].tpdf++; | |
} | |
} | |
stmtsep | |
| notification_opt_stmt grouping_stmt { actual = $1.notif; | |
actual_type = NOTIFICATION_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
| notification_opt_stmt data_def_stmt { actual = $1.notif; | |
actual_type = NOTIFICATION_KEYWORD; | |
data_node = actual; | |
} | |
stmtsep | |
; | |
deviation_stmt: DEVIATION_KEYWORD sep deviation_arg_str { if (read_all) { | |
if (!(actual = yang_read_deviation(trg, s))) { | |
YYERROR; | |
} | |
s = NULL; | |
trg->deviation_size++; | |
} | |
} | |
'{' stmtsep | |
deviation_opt_stmt { if (read_all) { | |
if (actual_type == DEVIATION_KEYWORD) { | |
LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "deviate", "deviation"); | |
YYERROR; | |
} | |
if (yang_check_deviation(trg, actual, unres)) { | |
YYERROR; | |
} | |
free($7.deviation); | |
} | |
} | |
'}' | |
deviation_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.deviation = actual; | |
actual_type = DEVIATION_KEYWORD; | |
if (size_arrays->node[size_arrays->next].deviate) { | |
$$.deviation->deviation->deviate = calloc(size_arrays->node[size_arrays->next].deviate, sizeof *$$.deviation->deviation->deviate); | |
if (!$$.deviation->deviation->deviate) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| deviation_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.deviation->deviation, s, "deviation")) { | |
free($1.deviation); | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
| deviation_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.deviation->deviation, s, "deviation")) { | |
free($1.deviation); | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
| deviation_opt_stmt DEVIATE_KEYWORD sep deviate_body_stmt { if (read_all) { | |
actual = $1.deviation; | |
actual_type = DEVIATE_KEYWORD; | |
$$ = $1; | |
} else { | |
/* count of deviate statemenet */ | |
size_arrays->node[$1.index].deviate++; | |
} | |
} | |
deviation_arg_str: absolute_schema_nodeids optsep | |
| string_1 | |
deviate_body_stmt: deviate_not_supported_stmt | |
{ if (read_all && yang_read_deviate_unsupported(actual)) { | |
YYERROR; | |
} | |
} | |
| deviate_stmts optsep | |
deviate_stmts: deviate_add_stmt | |
| deviate_replace_stmt | |
| deviate_delete_stmt | |
; | |
deviate_not_supported_stmt: NOT_SUPPORTED_KEYWORD optsep stmtend; | |
deviate_add_stmt: ADD_KEYWORD optsep { if (read_all && yang_read_deviate(actual, LY_DEVIATE_ADD)) { | |
YYERROR; | |
} | |
} | |
deviate_add_end | |
deviate_add_end: ';' | |
| '{' stmtsep | |
deviate_add_opt_stmt | |
'}' | |
deviate_add_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.deviation = actual; | |
actual_type = ADD_KEYWORD; | |
if (size_arrays->node[size_arrays->next].must) { | |
if (yang_read_deviate_must(actual, size_arrays->node[size_arrays->next].must)) { | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].unique) { | |
if (yang_read_deviate_unique(actual, size_arrays->node[size_arrays->next].unique)) { | |
YYERROR; | |
} | |
} | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| deviate_add_opt_stmt units_stmt { if (read_all) { | |
if (yang_read_deviate_units(trg->ctx, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| deviate_add_opt_stmt must_stmt stmtsep { if (read_all) { | |
actual = $1.deviation; | |
actual_type = ADD_KEYWORD; | |
$$ = $1; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
| deviate_add_opt_stmt unique_stmt { if (read_all) { | |
struct lys_node_list *list; | |
list = (struct lys_node_list *)$1.deviation->target; | |
if (yang_fill_unique(trg, list, &list->unique[list->unique_size], s, NULL)) { | |
list->unique_size++; | |
YYERROR; | |
} | |
list->unique_size++; | |
free(s); | |
s = NULL; | |
$$ = $1; | |
} else { | |
size_arrays->node[$1.index].unique++; | |
} | |
} | |
| deviate_add_opt_stmt default_stmt { if (read_all) { | |
if (yang_read_deviate_default(trg->ctx, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| deviate_add_opt_stmt config_stmt { if (read_all) { | |
if (yang_read_deviate_config($1.deviation, $2)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
| deviate_add_opt_stmt mandatory_stmt { if (read_all) { | |
if (yang_read_deviate_mandatory($1.deviation, $2)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
| deviate_add_opt_stmt min_elements_stmt { if (read_all) { | |
if ($1.deviation->deviate->min_set) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "min-elements", "deviation"); | |
YYERROR; | |
} | |
if (yang_read_deviate_minmax($1.deviation, $2, 0)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
| deviate_add_opt_stmt max_elements_stmt { if (read_all) { | |
if ($1.deviation->deviate->max_set) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "max-elements", "deviation"); | |
YYERROR; | |
} | |
if (yang_read_deviate_minmax($1.deviation, $2, 1)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
deviate_delete_stmt: DELETE_KEYWORD optsep { if (read_all && yang_read_deviate(actual, LY_DEVIATE_DEL)) { | |
YYERROR; | |
} | |
} | |
deviate_delete_end | |
deviate_delete_end: ';' | |
| '{' stmtsep | |
deviate_delete_opt_stmt | |
'}' ; | |
deviate_delete_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.deviation = actual; | |
actual_type = DELETE_KEYWORD; | |
if (size_arrays->node[size_arrays->next].must) { | |
if (yang_read_deviate_must(actual, size_arrays->node[size_arrays->next].must)) { | |
YYERROR; | |
} | |
} | |
if (size_arrays->node[size_arrays->next].unique) { | |
if (yang_read_deviate_unique(actual, size_arrays->node[size_arrays->next].unique)) { | |
YYERROR; | |
} | |
} | |
size_arrays->next++; | |
} else { | |
$$.index = size_arrays->size; | |
if (yang_add_elem(&size_arrays->node, &size_arrays->size)) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
| deviate_delete_opt_stmt units_stmt { if (read_all) { | |
if (yang_read_deviate_units(trg->ctx, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| deviate_delete_opt_stmt must_stmt stmtsep { if (read_all) { | |
if (yang_check_deviate_must(trg->ctx, $1.deviation)) { | |
YYERROR; | |
} | |
actual = $1.deviation; | |
actual_type = DELETE_KEYWORD; | |
$$ = $1; | |
} else { | |
size_arrays->node[$1.index].must++; | |
} | |
} | |
| deviate_delete_opt_stmt unique_stmt { if (read_all) { | |
if (yang_check_deviate_unique(trg, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} else { | |
size_arrays->node[$1.index].unique++; | |
} | |
} | |
| deviate_delete_opt_stmt default_stmt { if (read_all) { | |
if (yang_read_deviate_default(trg->ctx, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
deviate_replace_stmt: REPLACE_KEYWORD optsep { if (read_all && yang_read_deviate(actual, LY_DEVIATE_RPL)) { | |
YYERROR; | |
} | |
} | |
deviate_replace_end | |
deviate_replace_end: ';' | |
| '{' stmtsep | |
deviate_replace_opt_stmt | |
'}' ; | |
deviate_replace_opt_stmt: @EMPTYDIR@ { if (read_all) { | |
$$.deviation = actual; | |
actual_type = REPLACE_KEYWORD; | |
} | |
} | |
| deviate_replace_opt_stmt type_stmt stmtsep { if (read_all) { | |
if (unres_schema_add_node(trg, unres, $1.deviation->deviate->type, UNRES_TYPE_DER, $1.deviation->target)) { | |
YYERROR; | |
} | |
} | |
} | |
| deviate_replace_opt_stmt units_stmt { if (read_all) { | |
if (yang_read_deviate_units(trg->ctx, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| deviate_replace_opt_stmt default_stmt { if (read_all) { | |
if (yang_read_deviate_default(trg->ctx, $1.deviation, s)) { | |
YYERROR; | |
} | |
s = NULL; | |
$$ = $1; | |
} | |
} | |
| deviate_replace_opt_stmt config_stmt { if (read_all) { | |
if (yang_read_deviate_config($1.deviation, $2)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
| deviate_replace_opt_stmt mandatory_stmt { if (read_all) { | |
if (yang_read_deviate_mandatory($1.deviation, $2)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
| deviate_replace_opt_stmt min_elements_stmt { if (read_all) { | |
if ($1.deviation->deviate->min_set) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "min-elements", "deviate"); | |
YYERROR; | |
} | |
if (yang_read_deviate_minmax($1.deviation, $2, 0)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
| deviate_replace_opt_stmt max_elements_stmt { if (read_all) { | |
if ($1.deviation->deviate->max_set) { | |
LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "max-elements", "deviate"); | |
YYERROR; | |
} | |
if (yang_read_deviate_minmax($1.deviation, $2, 1)) { | |
YYERROR; | |
} | |
$$ = $1; | |
} | |
} | |
when_stmt: WHEN_KEYWORD sep string { if (read_all && !(actual=yang_read_when(trg, actual, actual_type, s))) {YYERROR;} s=NULL; actual_type=WHEN_KEYWORD;} | |
when_end; | |
when_end: ';' | |
| '{' stmtsep | |
when_opt_stmt | |
'}' | |
when_opt_stmt: @EMPTYDIR@ | |
| when_opt_stmt description_stmt { if (read_all && yang_read_description(trg, actual, s, "when")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
| when_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, actual, s, "when")) { | |
YYERROR; | |
} | |
s = NULL; | |
} | |
config_stmt: CONFIG_KEYWORD sep config_arg_str stmtend { $$ = $3; } | |
config_read_stmt: CONFIG_KEYWORD sep { read_all = (read_all) ? LY_READ_ONLY_SIZE : LY_READ_ALL; } | |
config_arg_str { read_all = (read_all) ? LY_READ_ONLY_SIZE : LY_READ_ALL; } | |
stmtend { $$ = $4; } | |
config_arg_str: TRUE_KEYWORD optsep { $$ = LYS_CONFIG_W; } | |
| FALSE_KEYWORD optsep { $$ = LYS_CONFIG_R; } | |
| string_1 { if (read_all) { | |
if (!strcmp(s, "true")) { | |
$$ = LYS_CONFIG_W; | |
} else if (!strcmp(s, "false")) { | |
$$ = LYS_CONFIG_R; | |
} else { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "config"); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
mandatory_stmt: MANDATORY_KEYWORD sep mandatory_arg_str stmtend { $$ = $3; } | |
mandatory_read_stmt: MANDATORY_KEYWORD sep { read_all = (read_all) ? LY_READ_ONLY_SIZE : LY_READ_ALL; } | |
mandatory_arg_str { read_all = (read_all) ? LY_READ_ONLY_SIZE : LY_READ_ALL; } | |
stmtend { $$ = $4; } | |
mandatory_arg_str: TRUE_KEYWORD optsep { $$ = LYS_MAND_TRUE; } | |
| FALSE_KEYWORD optsep { $$ = LYS_MAND_FALSE; } | |
| string_1 { if (read_all) { | |
if (!strcmp(s, "true")) { | |
$$ = LYS_MAND_TRUE; | |
} else if (!strcmp(s, "false")) { | |
$$ = LYS_MAND_FALSE; | |
} else { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "mandatory"); | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
presence_stmt: PRESENCE_KEYWORD sep string stmtend; | |
min_elements_stmt: MIN_ELEMENTS_KEYWORD sep min_value_arg_str stmtend { $$ = $3; } | |
min_value_arg_str: non_negative_integer_value optsep { $$ = $1; } | |
| string_1 { if (read_all) { | |
if (strlen(s) == 1 && s[0] == '0') { | |
$$ = 0; | |
} else { | |
/* convert it to uint32_t */ | |
uint64_t val; | |
char *endptr; | |
val = strtoul(yyget_text(scanner), &endptr, 10); | |
if (val > UINT32_MAX || *endptr) { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "min-elements"); | |
free(s); | |
YYERROR; | |
} | |
$$ = (uint32_t) val; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
max_elements_stmt: MAX_ELEMENTS_KEYWORD sep max_value_arg_str stmtend { $$ = $3; } | |
max_value_arg_str: UNBOUNDED_KEYWORD optsep { $$ = 0; } | |
| positive_integer_value optsep { $$ = $1; } | |
| string_1 { if (read_all) { | |
if (!strcmp(s, "unbounded")) { | |
$$ = 0; | |
} else { | |
/* convert it to uint32_t */ | |
uint64_t val; | |
char *endptr; | |
val = strtoul(yyget_text(scanner), &endptr, 10); | |
if (val > UINT32_MAX || *endptr) { | |
LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, s, "max-elements"); | |
free(s); | |
YYERROR; | |
} | |
$$ = (uint32_t) val; | |
} | |
free(s); | |
s = NULL; | |
} | |
} | |
ordered_by_stmt: ORDERED_BY_KEYWORD sep ordered_by_arg_str stmtend { $$ = $3; } | |
ordered_by_arg_str: USER_KEYWORD optsep { $$ = LYS_USERORDERED; } | |
| SYSTEM_KEYWORD optsep { $$ = LYS_SYSTEMORDERED; } | |
| string_1 { if (!strcmp(s, "user")) { | |
$$ = LYS_USERORDERED; | |
} else if (!strcmp(s, "system")) { | |
$$ = LYS_SYSTEMORDERED; | |
} else { | |
free(s); | |
YYERROR; | |
} | |
free(s); | |
s=NULL; | |
} | |
must_stmt: MUST_KEYWORD sep string { if (read_all) { | |
if (!(actual=yang_read_must(trg, actual, s, actual_type))) {YYERROR;} | |
s=NULL; | |
actual_type=MUST_KEYWORD; | |
} | |
} | |
must_end; | |
must_end: ';' | |
| '{' stmtsep | |
message_opt_stmt | |
'}' | |
; | |
unique_stmt: UNIQUE_KEYWORD sep unique_arg_str; | |
unique_arg_str: descendant_schema_nodeid unique_arg | |
| string_1 stmtend; | |
unique_arg: sep descendant_schema_nodeid unique_arg | |
| stmtend; | |
key_stmt: KEY_KEYWORD sep key_arg_str; | |
key_arg_str: node_identifier { if (read_all){ | |
s = strdup(yyget_text(scanner)); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
key_opt | |
| string_1 stmtend | |
; | |
key_opt: sep node_identifier { if (read_all) { | |
s = ly_realloc(s,strlen(s) + yyget_leng(scanner) + 2); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
strcat(s," "); | |
strcat(s, yyget_text(scanner)); | |
} | |
} | |
key_opt | |
| stmtend | |
; | |
range_arg_str: string { if (read_all) { | |
$$ = actual; | |
if (!(actual = yang_read_range(trg, actual, s))) { | |
YYERROR; | |
} | |
actual_type = RANGE_KEYWORD; | |
s = NULL; | |
} | |
} | |
absolute_schema_nodeid: '/' node_identifier { if (read_all) { | |
if (s) { | |
s = ly_realloc(s,strlen(s) + yyget_leng(scanner) + 2); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
strcat(s,"/"); | |
strcat(s, yyget_text(scanner)); | |
} else { | |
s = malloc(yyget_leng(scanner) + 2); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
s[0]='/'; | |
memcpy(s + 1, yyget_text(scanner), yyget_leng(scanner) + 1); | |
} | |
} | |
} | |
absolute_schema_nodeids: absolute_schema_nodeid absolute_schema_nodeid_opt; | |
absolute_schema_nodeid_opt: @EMPTYDIR@ | |
| absolute_schema_nodeid_opt absolute_schema_nodeid | |
; | |
descendant_schema_nodeid: node_identifier { if (read_all) { | |
if (s) { | |
s = ly_realloc(s,strlen(s) + yyget_leng(scanner) + 1); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
strcat(s, yyget_text(scanner)); | |
} else { | |
s = strdup(yyget_text(scanner)); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
} | |
absolute_schema_nodeid_opt; | |
path_arg_str: { tmp_s = yyget_text(scanner); } absolute_paths { if (read_all) { | |
s = strdup(tmp_s); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
s[strlen(s) - 1] = '\0'; | |
} | |
} | |
| { tmp_s = yyget_text(scanner); } relative_path { if (read_all) { | |
s = strdup(tmp_s); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
s[strlen(s) - 1] = '\0'; | |
} | |
} | |
| string_1 | |
; | |
absolute_path: '/' node_identifier path_predicate | |
absolute_paths: absolute_path absolute_path_opt | |
absolute_path_opt: @EMPTYDIR@ | |
| absolute_path_opt absolute_path; | |
relative_path: relative_path_part1 relative_path_part1_opt descendant_path | |
relative_path_part1: DOUBLEDOT '/'; | |
relative_path_part1_opt: @EMPTYDIR@ | |
| relative_path_part1_opt relative_path_part1; | |
descendant_path: node_identifier descendant_path_opt | |
descendant_path_opt: @EMPTYDIR@ | |
| path_predicate absolute_paths; | |
path_predicate: @EMPTYDIR@ | |
| path_predicate '[' whitespace_opt path_equality_expr whitespace_opt ']' | |
path_equality_expr: node_identifier whitespace_opt '=' whitespace_opt path_key_expr | |
path_key_expr: current_function_invocation whitespace_opt '/' whitespace_opt | |
rel_path_keyexpr | |
rel_path_keyexpr: rel_path_keyexpr_part1 rel_path_keyexpr_part1_opt | |
node_identifier rel_path_keyexpr_part2 | |
node_identifier | |
rel_path_keyexpr_part1: DOUBLEDOT whitespace_opt '/' whitespace_opt; | |
rel_path_keyexpr_part1_opt: @EMPTYDIR@ | |
| rel_path_keyexpr_part1_opt rel_path_keyexpr_part1; | |
rel_path_keyexpr_part2: @EMPTYDIR@ | |
| rel_path_keyexpr_part2 whitespace_opt '/' whitespace_opt node_identifier; | |
current_function_invocation: CURRENT_KEYWORD whitespace_opt '(' whitespace_opt ')' | |
positive_integer_value: NON_NEGATIVE_INTEGER { /* convert it to uint32_t */ | |
unsigned long val; | |
val = strtoul(yyget_text(scanner), NULL, 10); | |
if (val > UINT32_MAX) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Converted number is very long."); | |
YYERROR; | |
} | |
$$ = (uint32_t) val; | |
} | |
non_negative_integer_value: ZERO { $$ = 0; } | |
| positive_integer_value { $$ = $1; } | |
; | |
integer_value: ZERO { $$ = 0; } | |
| integer_value_convert { /* convert it to int32_t */ | |
int64_t val; | |
val = strtoll(yyget_text(scanner), NULL, 10); | |
if (val < INT32_MIN || val > INT32_MAX) { | |
LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "The number is not in the correct range (INT32_MIN..INT32_MAX): \"%d\"",val); | |
YYERROR; | |
} | |
$$ = (int32_t) val; | |
} | |
; | |
integer_value_convert: INTEGER | |
| NON_NEGATIVE_INTEGER | |
prefix_arg_str: string_1 | |
| identifiers optsep; | |
identifier_arg_str: identifiers optsep | |
| string_1 { if (read_all && lyp_check_identifier(s, LY_IDENT_SIMPLE, trg, NULL)) { | |
free(s); | |
YYERROR; | |
} | |
} | |
node_identifier: identifier | |
| IDENTIFIERPREFIX | |
; | |
identifier_ref_arg_str: identifiers optsep | |
| identifiers_ref optsep | |
| string_1 { if (read_all) { | |
char *tmp; | |
if ((tmp = strchr(s, ':'))) { | |
*tmp = '\0'; | |
/* check prefix */ | |
if (lyp_check_identifier(s, LY_IDENT_SIMPLE, trg, NULL)) { | |
free(s); | |
YYERROR; | |
} | |
/* check identifier */ | |
if (lyp_check_identifier(tmp + 1, LY_IDENT_SIMPLE, trg, NULL)) { | |
free(s); | |
YYERROR; | |
} | |
*tmp = ':'; | |
} else { | |
/* check identifier */ | |
if (lyp_check_identifier(s, LY_IDENT_SIMPLE, trg, NULL)) { | |
free(s); | |
YYERROR; | |
} | |
} | |
} | |
} | |
stmtend: ';' stmtsep | |
| '{' stmtsep '}' stmtsep | |
; | |
stmtsep: @EMPTYDIR@ | |
| stmtsep sep_stmt | |
| stmtsep unknown_statement | |
; | |
unknown_statement: IDENTIFIERPREFIX { if (read_all ) { | |
if (yang_use_extension(trg, data_node, actual, yyget_text(scanner))) { | |
YYERROR; | |
} | |
} | |
} | |
string_opt unknown_statement_end | |
string_opt: string_opt_part1 string_opt_part2 | |
string_opt_part1: @EMPTYDIR@ | |
| sep | |
string_opt_part2: @EMPTYDIR@ | |
| STRING optsep string_opt_part3 | |
string_opt_part3: @EMPTYDIR@ | |
| string_opt_part3 '+' optsep STRING optsep | |
unknown_statement_end: ';' | |
| '{' optsep unknown_statement2_opt '}' | |
unknown_statement2_opt: @EMPTYDIR@ | |
| node_identifier string_opt unknown_statement2_end; | |
unknown_statement2_end: ';' optsep | |
| '{' optsep unknown_statement2_opt '}' optsep | |
sep_stmt: WHITESPACE | |
| EOL | |
; | |
optsep: @EMPTYDIR@ | |
| optsep sep_stmt | |
; | |
sep: sep_stmt optsep; | |
whitespace_opt: @EMPTYDIR@ | |
| WHITESPACE | |
; | |
string: strings { if (read_all){ | |
s = strdup(yyget_text(scanner)); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
optsep | |
| string_1 | |
strings: STRINGS | |
| REVISION_DATE | |
| identifier | |
| IDENTIFIERPREFIX | |
| ZERO | |
| INTEGER | |
| NON_NEGATIVE_INTEGER | |
identifier: IDENTIFIER | |
| ANYXML_KEYWORD | |
| ARGUMENT_KEYWORD | |
| AUGMENT_KEYWORD | |
| BASE_KEYWORD | |
| BELONGS_TO_KEYWORD | |
| BIT_KEYWORD | |
| CASE_KEYWORD | |
| CHOICE_KEYWORD | |
| CONFIG_KEYWORD | |
| CONTACT_KEYWORD | |
| CONTAINER_KEYWORD | |
| DEFAULT_KEYWORD | |
| DESCRIPTION_KEYWORD | |
| ENUM_KEYWORD | |
| ERROR_APP_TAG_KEYWORD | |
| ERROR_MESSAGE_KEYWORD | |
| EXTENSION_KEYWORD | |
| DEVIATION_KEYWORD | |
| DEVIATE_KEYWORD | |
| FEATURE_KEYWORD | |
| FRACTION_DIGITS_KEYWORD | |
| GROUPING_KEYWORD | |
| IDENTITY_KEYWORD | |
| IF_FEATURE_KEYWORD | |
| IMPORT_KEYWORD | |
| INCLUDE_KEYWORD | |
| INPUT_KEYWORD | |
| KEY_KEYWORD | |
| LEAF_KEYWORD | |
| LEAF_LIST_KEYWORD | |
| LENGTH_KEYWORD | |
| LIST_KEYWORD | |
| MANDATORY_KEYWORD | |
| MAX_ELEMENTS_KEYWORD | |
| MIN_ELEMENTS_KEYWORD | |
| MODULE_KEYWORD | |
| MUST_KEYWORD | |
| NAMESPACE_KEYWORD | |
| NOTIFICATION_KEYWORD | |
| ORDERED_BY_KEYWORD | |
| ORGANIZATION_KEYWORD | |
| OUTPUT_KEYWORD | |
| PATH_KEYWORD | |
| PATTERN_KEYWORD | |
| POSITION_KEYWORD | |
| PREFIX_KEYWORD | |
| PRESENCE_KEYWORD | |
| RANGE_KEYWORD | |
| REFERENCE_KEYWORD | |
| REFINE_KEYWORD | |
| REQUIRE_INSTANCE_KEYWORD | |
| REVISION_KEYWORD | |
| REVISION_DATE_KEYWORD | |
| RPC_KEYWORD | |
| STATUS_KEYWORD | |
| SUBMODULE_KEYWORD | |
| TYPE_KEYWORD | |
| TYPEDEF_KEYWORD | |
| UNIQUE_KEYWORD | |
| UNITS_KEYWORD | |
| USES_KEYWORD | |
| VALUE_KEYWORD | |
| WHEN_KEYWORD | |
| YANG_VERSION_KEYWORD | |
| YIN_ELEMENT_KEYWORD | |
| ADD_KEYWORD | |
| CURRENT_KEYWORD | |
| DELETE_KEYWORD | |
| DEPRECATED_KEYWORD | |
| FALSE_KEYWORD | |
| NOT_SUPPORTED_KEYWORD | |
| OBSOLETE_KEYWORD | |
| REPLACE_KEYWORD | |
| SYSTEM_KEYWORD | |
| TRUE_KEYWORD | |
| UNBOUNDED_KEYWORD | |
| USER_KEYWORD | |
; | |
identifiers: identifier { if (read_all) { | |
s = strdup(yyget_text(scanner)); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
identifiers_ref: IDENTIFIERPREFIX { if (read_all) { | |
s = strdup(yyget_text(scanner)); | |
if (!s) { | |
LOGMEM; | |
YYERROR; | |
} | |
} | |
} | |
%% | |
void yyerror(YYLTYPE *yylloc, void *scanner, ...){ | |
(void)yylloc; /* unused */ | |
LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, yyget_text(scanner)); | |
} |