blob: 960b461a74e7f09065bfa132c8efb4449d76c7c6 [file] [log] [blame]
Radek Krejci86d106e2018-10-18 09:53:19 +02001/**
2 * @file tree_schema_helpers.c
3 * @author Radek Krejci <rkrejci@cesnet.cz>
4 * @brief Parsing and validation helper functions
5 *
6 * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14#define _XOPEN_SOURCE
15
16#include <ctype.h>
17#include <limits.h>
18#include <time.h>
19
20#include "libyang.h"
21#include "common.h"
22#include "tree_schema_internal.h"
23
24LY_ERR
25lysp_check_prefix(struct ly_parser_ctx *ctx, struct lysp_module *module, const char **value)
26{
27 struct lysp_import *i;
28
29 if (module->prefix && &module->prefix != value && !strcmp(module->prefix, *value)) {
30 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
31 "Prefix \"%s\" already used as module prefix.", *value);
32 return LY_EEXIST;
33 }
34 if (module->imports) {
35 LY_ARRAY_FOR(module->imports, struct lysp_import, i) {
36 if (i->prefix && &i->prefix != value && !strcmp(i->prefix, *value)) {
37 LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
38 "Prefix \"%s\" already used to import \"%s\" module.", *value, i->name);
39 return LY_EEXIST;
40 }
41 }
42 }
43 return LY_SUCCESS;
44}
45
46LY_ERR
47lysp_check_date(struct ly_ctx *ctx, const char *date, int date_len, const char *stmt)
48{
49 int i;
50 struct tm tm, tm_;
51 char *r;
52
53 LY_CHECK_ARG_RET(ctx, date, LY_EINVAL);
54 LY_CHECK_ERR_RET(date_len != LY_REV_SIZE - 1, LOGARG(ctx, date_len), LY_EINVAL);
55
56 /* check format */
57 for (i = 0; i < date_len; i++) {
58 if (i == 4 || i == 7) {
59 if (date[i] != '-') {
60 goto error;
61 }
62 } else if (!isdigit(date[i])) {
63 goto error;
64 }
65 }
66
67 /* check content, e.g. 2018-02-31 */
68 memset(&tm, 0, sizeof tm);
69 r = strptime(date, "%Y-%m-%d", &tm);
70 if (!r || r != &date[LY_REV_SIZE - 1]) {
71 goto error;
72 }
73 memcpy(&tm_, &tm, sizeof tm);
74 mktime(&tm_); /* mktime modifies tm_ if it refers invalid date */
75 if (tm.tm_mday != tm_.tm_mday) { /* e.g 2018-02-29 -> 2018-03-01 */
76 /* checking days is enough, since other errors
77 * have been checked by strptime() */
78 goto error;
79 }
80
81 return LY_SUCCESS;
82
83error:
84 LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_INVAL, date_len, date, stmt);
85 return LY_EINVAL;
86}
87
88void
89lysp_sort_revisions(struct lysp_revision *revs)
90{
91 uint8_t i, r;
92 struct lysp_revision rev;
93
94 for (i = 1, r = 0; revs && i < LY_ARRAY_SIZE(revs); i++) {
Radek Krejci2c4e7172018-10-19 15:56:26 +020095 if (strcmp(revs[i].rev, revs[r].rev) > 0) {
Radek Krejci86d106e2018-10-18 09:53:19 +020096 r = i;
97 }
98 }
99
100 if (r) {
101 /* the newest revision is not on position 0, switch them */
Radek Krejci2c4e7172018-10-19 15:56:26 +0200102 memcpy(&rev, &revs[0], sizeof rev);
103 memcpy(&revs[0], &revs[r], sizeof rev);
104 memcpy(&revs[r], &rev, sizeof rev);
Radek Krejci86d106e2018-10-18 09:53:19 +0200105 }
106}
Radek Krejci151a5b72018-10-19 14:21:44 +0200107
108struct lysc_module *
109lysc_module_find_prefix(struct lysc_module *mod, const char *prefix, size_t len)
110{
111 struct lysc_import *imp;
112
113 assert(mod);
114
115 if (!strncmp(mod->prefix, prefix, len) && mod->prefix[len] == '\0') {
116 /* it is the prefix of the module itself */
117 return mod;
118 }
119
120 /* search in imports */
121 LY_ARRAY_FOR(mod->imports, struct lysc_import, imp) {
122 if (!strncmp(imp->prefix, prefix, len) && mod->prefix[len] == '\0') {
123 return imp->module;
124 }
125 }
126
127 return NULL;
128}
David Sedlák23a59a62018-10-26 13:08:02 +0200129
130#define MOVE_INPUT(DATA, COUNT) (data)+=COUNT;
131#define IF_KW(STR, LEN, STMT) if (!strncmp((data), STR, LEN)) {MOVE_INPUT(data, LEN);kw=STMT;}
132#define IF_KW_PREFIX(STR, LEN) if (!strncmp((data), STR, LEN)) {MOVE_INPUT(data, LEN);
133#define IF_KW_PREFIX_END }
134
135enum yang_keyword
136match_keyword(char *data)
137{
138 enum yang_keyword kw = YANG_NONE;
139 /* read the keyword itself */
140 switch (*data) {
141 case 'a':
142 MOVE_INPUT(data, 1);
143 IF_KW("rgument", 7, YANG_ARGUMENT)
144 else IF_KW("ugment", 6, YANG_AUGMENT)
145 else IF_KW("ction", 5, YANG_ACTION)
146 else IF_KW_PREFIX("ny", 2)
147 IF_KW("data", 4, YANG_ANYDATA)
148 else IF_KW("xml", 3, YANG_ANYXML)
149 IF_KW_PREFIX_END
150 break;
151 case 'b':
152 MOVE_INPUT(data, 1);
153 IF_KW("ase", 3, YANG_BASE)
154 else IF_KW("elongs-to", 9, YANG_BELONGS_TO)
155 else IF_KW("it", 2, YANG_BIT)
156 break;
157 case 'c':
158 MOVE_INPUT(data, 1);
159 IF_KW("ase", 3, YANG_CASE)
160 else IF_KW("hoice", 5, YANG_CHOICE)
161 else IF_KW_PREFIX("on", 2)
162 IF_KW("fig", 3, YANG_CONFIG)
163 else IF_KW_PREFIX("ta", 2)
164 IF_KW("ct", 2, YANG_CONTACT)
165 else IF_KW("iner", 4, YANG_CONTAINER)
166 IF_KW_PREFIX_END
167 IF_KW_PREFIX_END
168 break;
169 case 'd':
170 MOVE_INPUT(data, 1);
171 IF_KW_PREFIX("e", 1)
172 IF_KW("fault", 5, YANG_DEFAULT)
173 else IF_KW("scription", 9, YANG_DESCRIPTION)
174 else IF_KW_PREFIX("viat", 4)
175 IF_KW("e", 1, YANG_DEVIATE)
176 else IF_KW("ion", 3, YANG_DEVIATION)
177 IF_KW_PREFIX_END
178 IF_KW_PREFIX_END
179 break;
180 case 'e':
181 MOVE_INPUT(data, 1);
182 IF_KW("num", 3, YANG_ENUM)
183 else IF_KW_PREFIX("rror-", 5)
184 IF_KW("app-tag", 7, YANG_ERROR_APP_TAG)
185 else IF_KW("message", 7, YANG_ERROR_MESSAGE)
186 IF_KW_PREFIX_END
187 else IF_KW("xtension", 8, YANG_EXTENSION)
188 break;
189 case 'f':
190 MOVE_INPUT(data, 1);
191 IF_KW("eature", 6, YANG_FEATURE)
192 else IF_KW("raction-digits", 14, YANG_FRACTION_DIGITS)
193 break;
194 case 'g':
195 MOVE_INPUT(data, 1);
196 IF_KW("rouping", 7, YANG_GROUPING)
197 break;
198 case 'i':
199 MOVE_INPUT(data, 1);
200 IF_KW("dentity", 7, YANG_IDENTITY)
201 else IF_KW("f-feature", 9, YANG_IF_FEATURE)
202 else IF_KW("mport", 5, YANG_IMPORT)
203 else IF_KW_PREFIX("n", 1)
204 IF_KW("clude", 5, YANG_INCLUDE)
205 else IF_KW("put", 3, YANG_INPUT)
206 IF_KW_PREFIX_END
207 break;
208 case 'k':
209 MOVE_INPUT(data, 1);
210 IF_KW("ey", 2, YANG_KEY)
211 break;
212 case 'l':
213 MOVE_INPUT(data, 1);
214 IF_KW_PREFIX("e", 1)
215 IF_KW("af-list", 7, YANG_LEAF_LIST)
216 else IF_KW("af", 2, YANG_LEAF)
217 else IF_KW("ngth", 4, YANG_LENGTH)
218 IF_KW_PREFIX_END
219 else IF_KW("ist", 3, YANG_LIST)
220 break;
221 case 'm':
222 MOVE_INPUT(data, 1);
223 IF_KW_PREFIX("a", 1)
224 IF_KW("ndatory", 7, YANG_MANDATORY)
225 else IF_KW("x-elements", 10, YANG_MAX_ELEMENTS)
226 IF_KW_PREFIX_END
227 else IF_KW("in-elements", 11, YANG_MIN_ELEMENTS)
228 else IF_KW("ust", 3, YANG_MUST)
229 else IF_KW_PREFIX("od", 2)
230 IF_KW("ule", 3, YANG_MODULE)
231 else IF_KW("ifier", 5, YANG_MODIFIER)
232 IF_KW_PREFIX_END
233 break;
234 case 'n':
235 MOVE_INPUT(data, 1);
236 IF_KW("amespace", 8, YANG_NAMESPACE)
237 else IF_KW("otification", 11, YANG_NOTIFICATION)
238 break;
239 case 'o':
240 MOVE_INPUT(data, 1);
241 IF_KW_PREFIX("r", 1)
242 IF_KW("dered-by", 8, YANG_ORDERED_BY)
243 else IF_KW("ganization", 10, YANG_ORGANIZATION)
244 IF_KW_PREFIX_END
245 else IF_KW("utput", 5, YANG_OUTPUT)
246 break;
247 case 'p':
248 MOVE_INPUT(data, 1);
249 IF_KW("ath", 3, YANG_PATH)
250 else IF_KW("attern", 6, YANG_PATTERN)
251 else IF_KW("osition", 7, YANG_POSITION)
252 else IF_KW_PREFIX("re", 2)
253 IF_KW("fix", 3, YANG_PREFIX)
254 else IF_KW("sence", 5, YANG_PRESENCE)
255 IF_KW_PREFIX_END
256 break;
257 case 'r':
258 MOVE_INPUT(data, 1);
259 IF_KW("ange", 4, YANG_RANGE)
260 else IF_KW_PREFIX("e", 1)
261 IF_KW_PREFIX("f", 1)
262 IF_KW("erence", 6, YANG_REFERENCE)
263 else IF_KW("ine", 3, YANG_REFINE)
264 IF_KW_PREFIX_END
265 else IF_KW("quire-instance", 14, YANG_REQUIRE_INSTANCE)
266 else IF_KW("vision-date", 11, YANG_REVISION_DATE)
267 else IF_KW("vision", 6, YANG_REVISION)
268 IF_KW_PREFIX_END
269 else IF_KW("pc", 2, YANG_RPC)
270 break;
271 case 's':
272 MOVE_INPUT(data, 1);
273 IF_KW("tatus", 5, YANG_STATUS)
274 else IF_KW("ubmodule", 8, YANG_SUBMODULE)
275 break;
276 case 't':
277 MOVE_INPUT(data, 1);
278 IF_KW("ypedef", 6, YANG_TYPEDEF)
279 else IF_KW("ype", 3, YANG_TYPE)
280 break;
281 case 'u':
282 MOVE_INPUT(data, 1);
283 IF_KW_PREFIX("ni", 2)
284 IF_KW("que", 3, YANG_UNIQUE)
285 else IF_KW("ts", 2, YANG_UNITS)
286 IF_KW_PREFIX_END
287 else IF_KW("ses", 3, YANG_USES)
288 break;
289 case 'v':
290 MOVE_INPUT(data, 1);
291 IF_KW("alue", 4, YANG_VALUE)
292 break;
293 case 'w':
294 MOVE_INPUT(data, 1);
295 IF_KW("hen", 3, YANG_WHEN)
296 break;
297 case 'y':
298 MOVE_INPUT(data, 1);
299 IF_KW("ang-version", 11, YANG_YANG_VERSION)
300 else IF_KW("in-element", 10, YANG_YIN_ELEMENT)
301 break;
302 case ';':
303 MOVE_INPUT(data, 1);
304 kw = YANG_SEMICOLON;
305 //goto success;
306 break;
307 case '{':
308 MOVE_INPUT(data, 1);
309 kw = YANG_LEFT_BRACE;
310 //goto success;
311 break;
312 case '}':
313 MOVE_INPUT(data, 1);
314 kw = YANG_RIGHT_BRACE;
315 //goto success;
316 break;
317 default:
318 break;
319 }
320
321 return kw;
322}