Dedicated xml,json,yang and xsl parser utility programs added
Sanity check of stdarg (...) added Cleanup of error messages.
This commit is contained in:
parent
1306174071
commit
85c4782e36
56 changed files with 1004 additions and 379 deletions
|
|
@ -85,7 +85,11 @@ extern char clicon_err_reason[ERR_STRLEN];
|
|||
* Prototypes
|
||||
*/
|
||||
int clicon_err_reset(void);
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...) __attribute__ ((format (printf, 5, 6)));
|
||||
#else
|
||||
int clicon_err_fn(const char *fn, const int line, int level, int err, char *format, ...);
|
||||
#endif
|
||||
char *clicon_strerror(int err);
|
||||
void *clicon_err_save(void);
|
||||
int clicon_err_restore(void *handle);
|
||||
|
|
|
|||
|
|
@ -62,10 +62,16 @@ extern int debug;
|
|||
int clicon_log_init(char *ident, int upto, int flags);
|
||||
int clicon_get_logflags(void);
|
||||
int clicon_log_str(int level, char *msg);
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
int clicon_log(int level, char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
int clicon_debug(int dbglevel, char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
#else
|
||||
int clicon_log(int level, char *format, ...);
|
||||
int clicon_debug(int dbglevel, char *format, ...);
|
||||
#endif
|
||||
clicon_log_notify_t *clicon_log_register_callback(clicon_log_notify_t *cb, void *arg);
|
||||
int clicon_debug_init(int dbglevel, FILE *f);
|
||||
int clicon_debug(int dbglevel, char *format, ...);
|
||||
|
||||
char *mon2name(int md);
|
||||
|
||||
#endif /* _CLIXON_LOG_H_ */
|
||||
|
|
|
|||
|
|
@ -61,7 +61,11 @@ struct clicon_msg {
|
|||
char *format_int2str(enum format_enum showas);
|
||||
enum format_enum format_str2int(char *str);
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
struct clicon_msg *clicon_msg_encode(char *format, ...) __attribute__ ((format (printf, 1, 2)));
|
||||
#else
|
||||
struct clicon_msg *clicon_msg_encode(char *format, ...);
|
||||
#endif
|
||||
int clicon_msg_decode(struct clicon_msg *msg, cxobj **xml);
|
||||
|
||||
int clicon_connect_unix(char *sockpath);
|
||||
|
|
|
|||
|
|
@ -39,10 +39,17 @@
|
|||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
#if defined(__GNUC__) && __GNUC__ >= 3
|
||||
cxobj *xpath_first(cxobj *cxtop, char *format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
int xpath_vec(cxobj *cxtop, char *format, cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 2, 5)));
|
||||
int xpath_vec_flag(cxobj *cxtop, char *format, uint16_t flags,
|
||||
cxobj ***vec, size_t *veclen, ...) __attribute__ ((format (printf, 2, 6)));
|
||||
#else
|
||||
cxobj *xpath_first(cxobj *cxtop, char *format, ...);
|
||||
cxobj *xpath_each(cxobj *xn_top, char *xpath, cxobj *prev);
|
||||
int xpath_vec(cxobj *cxtop, char *format, cxobj ***vec, size_t *veclen, ...);
|
||||
int xpath_vec_flag(cxobj *cxtop, char *xpath, uint16_t flags,
|
||||
cxobj ***vec, size_t *veclen, ...);
|
||||
#endif
|
||||
cxobj *xpath_each(cxobj *xn_top, char *xpath, cxobj *prev);
|
||||
|
||||
#endif /* _CLIXON_XSL_H */
|
||||
|
|
|
|||
|
|
@ -257,6 +257,7 @@ char *yang_find_myprefix(yang_stmt *ys);
|
|||
int yang_order(yang_stmt *y);
|
||||
int yang_print(FILE *f, yang_node *yn);
|
||||
int yang_print_cbuf(cbuf *cb, yang_node *yn, int marginal);
|
||||
yang_stmt *yang_parse_file(int fd, const char *name, yang_spec *ysp);
|
||||
int yang_parse(clicon_handle h, const char *yang_dir,
|
||||
const char *module, const char *revision, yang_spec *ysp);
|
||||
int yang_apply(yang_node *yn, enum rfc_6020 key, yang_applyfn_t fn,
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ sysconfdir = @sysconfdir@
|
|||
HOST_VENDOR = @host_vendor@
|
||||
|
||||
SH_SUFFIX = @SH_SUFFIX@
|
||||
|
||||
CLIXON_VERSION = @CLIXON_VERSION@
|
||||
CLIXON_MAJOR = @CLIXON_VERSION_MAJOR@
|
||||
CLIXON_MINOR = @CLIXON_VERSION_MINOR@
|
||||
|
|
@ -78,6 +79,14 @@ YACCOBJS := lex.clixon_xml_parse.o clixon_xml_parse.tab.o \
|
|||
lex.clixon_json_parse.o clixon_json_parse.tab.o
|
||||
|
||||
|
||||
# Extra applications. Utilities, unit testings. Not installed.
|
||||
APPSRC = clixon_util_xml.c
|
||||
APPSRC += clixon_util_json.c
|
||||
APPSRC += clixon_util_yang.c
|
||||
APPSRC += clixon_util_xsl.c
|
||||
|
||||
APPS = $(APPSRC:.c=)
|
||||
|
||||
# Generated src
|
||||
GENSRC = build.c
|
||||
|
||||
|
|
@ -91,10 +100,10 @@ MYLIB = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR).$(CLIXON_MINOR)
|
|||
MYLIBSO = libclixon$(SH_SUFFIX).$(CLIXON_MAJOR)
|
||||
MYLIBLINK = libclixon$(SH_SUFFIX)
|
||||
|
||||
all: $(MYLIB) $(MYLIBLINK)
|
||||
all: $(MYLIB) $(MYLIBLINK) $(APPS)
|
||||
|
||||
clean:
|
||||
rm -f $(OBJS) $(MYLIB) $(MYLIBLINK) $(GENOBJS) $(GENSRC) *.core
|
||||
rm -f $(OBJS) $(MYLIB) $(APPS) $(MYLIBLINK) $(GENOBJS) $(GENSRC) *.core
|
||||
rm -f clixon_xml_parse.tab.[ch] clixon_xml_parse.yy.[co]
|
||||
rm -f clixon_yang_parse.tab.[ch] clixon_yang_parse.[co]
|
||||
rm -f clixon_json_parse.tab.[ch] clixon_json_parse.[co]
|
||||
|
|
@ -150,6 +159,19 @@ clixon_json_parse.tab.c clixon_json_parse.tab.h: clixon_json_parse.y
|
|||
lex.clixon_json_parse.o : lex.clixon_json_parse.c clixon_json_parse.tab.h
|
||||
$(CC) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) -Wno-error -c $<
|
||||
|
||||
# APPS
|
||||
clixon_util_xml: clixon_util_xml.c $(MYLIB)
|
||||
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
|
||||
|
||||
clixon_util_json: clixon_util_json.c $(MYLIB)
|
||||
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
|
||||
|
||||
clixon_util_yang: clixon_util_yang.c $(MYLIB)
|
||||
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
|
||||
|
||||
clixon_util_xsl: clixon_util_xsl.c $(MYLIB)
|
||||
$(CC) $(INCLUDES) $(CPPFLAGS) @CFLAGS@ $^ $(LIBS) -o $@
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile *~ .depend
|
||||
|
||||
|
|
@ -164,7 +186,6 @@ build.c:
|
|||
date +"const char CLIXON_BUILDSTR[64]=\"%Y.%m.%d %H:%M by `whoami` on `hostname`"\"\; > build.c;
|
||||
echo "const char CLIXON_VERSION[64]=\"$(CLIXON_VERSION)\""\; >> build.c;
|
||||
|
||||
|
||||
$(MYLIB) : $(GENOBJS) $(OBJS)
|
||||
ifeq ($(HOST_VENDOR),apple)
|
||||
$(CC) $(LDFLAGS) -shared -o $@ $(GENOBJS) $(OBJS) $(LIBS) -undefined dynamic_lookup -o $@
|
||||
|
|
|
|||
|
|
@ -135,11 +135,11 @@ clicon_err_reset(void)
|
|||
* - Set global reason string clicon_err_reason
|
||||
* @note: err direction (syslog and/or stderr) controlled by clicon_log_init()
|
||||
*
|
||||
* @param fn Inline function name (when called from clicon_err() macro)
|
||||
* @param line Inline file line number (when called from clicon_err() macro)
|
||||
* @param err Error number, typically errno
|
||||
* @param suberr Sub-error number
|
||||
* @param reason Error string, format with argv
|
||||
* @param[in] fn Inline function name (when called from clicon_err() macro)
|
||||
* @param[in] line Inline file line number (when called from clicon_err() macro)
|
||||
* @param[in] err Error number, typically errno
|
||||
* @param[in] suberr Sub-error number
|
||||
* @param[in] reason Error string, format with argv
|
||||
*/
|
||||
int
|
||||
clicon_err_fn(const char *fn,
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ event_poll(int fd)
|
|||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
if ((retval = select(FD_SETSIZE, &fdset, NULL, NULL, &tnull)) < 0)
|
||||
clicon_err(OE_EVENTS, errno, "%s select1: %s", __FUNCTION__, strerror(errno));
|
||||
clicon_err(OE_EVENTS, errno, "select");
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
|
@ -307,18 +307,18 @@ event_loop(void)
|
|||
if (n == -1) {
|
||||
if (errno == EINTR){
|
||||
clicon_debug(1, "%s select: %s", __FUNCTION__, strerror(errno));
|
||||
clicon_err(OE_EVENTS, errno, "%s select1: %s", __FUNCTION__, strerror(errno));
|
||||
clicon_err(OE_EVENTS, errno, "select");
|
||||
retval = 0;
|
||||
}
|
||||
else
|
||||
clicon_err(OE_EVENTS, errno, "%s select2", __FUNCTION__);
|
||||
clicon_err(OE_EVENTS, errno, "select");
|
||||
goto err;
|
||||
}
|
||||
if (n==0){ /* Timeout */
|
||||
e = ee_timers;
|
||||
ee_timers = ee_timers->e_next;
|
||||
clicon_debug(2, "%s timeout: %s[%x]",
|
||||
__FUNCTION__, e->e_string, e->e_arg);
|
||||
__FUNCTION__, e->e_string, (int)e->e_arg);
|
||||
if ((*e->e_fn)(0, e->e_arg) < 0){
|
||||
free(e);
|
||||
goto err;
|
||||
|
|
@ -332,7 +332,7 @@ event_loop(void)
|
|||
e_next = e->e_next;
|
||||
if(e->e_type == EVENT_FD && FD_ISSET(e->e_fd, &fdset)){
|
||||
clicon_debug(2, "%s: FD_ISSET: %s[%x]",
|
||||
__FUNCTION__, e->e_string, e->e_arg);
|
||||
__FUNCTION__, e->e_string, (int)e->e_arg);
|
||||
if ((*e->e_fn)(e->e_fd, e->e_arg) < 0){
|
||||
clicon_debug(1, "%s Error in: %s", __FUNCTION__, e->e_string);
|
||||
goto err;
|
||||
|
|
|
|||
|
|
@ -241,12 +241,11 @@ group_name2gid(char *name,
|
|||
gr = &g0;
|
||||
/* This leaks memory in ubuntu */
|
||||
if (getgrnam_r(name, gr, buf, sizeof(buf), >mp) < 0){
|
||||
clicon_err(OE_UNIX, errno, "%s: getgrnam_r(%s): %s",
|
||||
__FUNCTION__, name, strerror(errno));
|
||||
clicon_err(OE_UNIX, errno, "getgrnam_r(%s)", name);
|
||||
return -1;
|
||||
}
|
||||
if (gtmp == NULL){
|
||||
clicon_err(OE_UNIX, 0, "%s: No such group: %s", __FUNCTION__, name);
|
||||
clicon_err(OE_UNIX, 0, "No such group: %s", name);
|
||||
fprintf(stderr, "No such group %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -730,16 +730,14 @@ json_parse_file(int fd,
|
|||
int len = 0;
|
||||
|
||||
if ((jsonbuf = malloc(jsonbuflen)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: malloc", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(jsonbuf, 0, jsonbuflen);
|
||||
ptr = jsonbuf;
|
||||
while (1){
|
||||
if ((ret = read(fd, &ch, 1)) < 0){
|
||||
clicon_err(OE_XML, errno, "%s: read: [pid:%d]\n",
|
||||
__FUNCTION__,
|
||||
(int)getpid());
|
||||
clicon_err(OE_XML, errno, "read");
|
||||
break;
|
||||
}
|
||||
if (ret != 0)
|
||||
|
|
@ -756,7 +754,7 @@ json_parse_file(int fd,
|
|||
oldjsonbuflen = jsonbuflen;
|
||||
jsonbuflen *= 2;
|
||||
if ((jsonbuf = realloc(jsonbuf, jsonbuflen)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: realloc", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "realloc");
|
||||
goto done;
|
||||
}
|
||||
memset(jsonbuf+oldjsonbuflen, 0, jsonbuflen-oldjsonbuflen);
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ clicon_option_readfile_xml(clicon_hash_t *copt,
|
|||
clicon_err(OE_UNIX, errno, "configure file: %s", filename);
|
||||
return -1;
|
||||
}
|
||||
clicon_debug(2, "Reading config file %s", __FUNCTION__, filename);
|
||||
clicon_debug(2, "%s: Reading config file %s", __FUNCTION__, filename);
|
||||
fd = fileno(f);
|
||||
if (xml_parse_file(fd, "</clicon>", yspec, &xt) < 0)
|
||||
goto done;
|
||||
|
|
@ -290,10 +290,10 @@ clicon_option_str_set(clicon_handle h,
|
|||
|
||||
/*! Get options as integer but stored as string
|
||||
*
|
||||
* @param h clicon handle
|
||||
* @param name name of option
|
||||
* @retval int An integer as aresult of atoi
|
||||
* @retval -1 If option does not exist
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] name name of option
|
||||
* @retval int An integer as aresult of atoi
|
||||
* @retval -1 If option does not exist
|
||||
* @code
|
||||
* if (clicon_option_exists(h, "X")
|
||||
* return clicon_option_int(h, "X");
|
||||
|
|
@ -331,10 +331,10 @@ clicon_option_int_set(clicon_handle h,
|
|||
|
||||
/*! Get options as bool but stored as string
|
||||
*
|
||||
* @param h clicon handle
|
||||
* @param name name of option
|
||||
* @retval 0 false, or does not exist, or does not have a boolean value
|
||||
* @retval 1 true
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] name name of option
|
||||
* @retval 0 false, or does not exist, or does not have a boolean value
|
||||
* @retval 1 true
|
||||
* @code
|
||||
* if (clicon_option_exists(h, "X")
|
||||
* return clicon_option_bool(h, "X");
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ plugin_load_one(clicon_handle h,
|
|||
dlerror(); /* Clear any existing error */
|
||||
if ((handle = dlopen(file, dlflags)) == NULL) {
|
||||
error = (char*)dlerror();
|
||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s", error ? error : "Unknown error");
|
||||
goto done;
|
||||
}
|
||||
/* call plugin_init() if defined, eg CLIXON_PLUGIN_INIT or CLIXON_BACKEND_INIT */
|
||||
|
|
@ -342,7 +342,7 @@ clixon_plugin_exit(clicon_handle h)
|
|||
}
|
||||
if (dlclose(cp->cp_handle) != 0) {
|
||||
error = (char*)dlerror();
|
||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
|
||||
}
|
||||
}
|
||||
if (_clixon_plugins){
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ clicon_connect_unix(char *sockpath)
|
|||
clicon_debug(2, "%s: connecting to %s", __FUNCTION__, addr.sun_path);
|
||||
if (connect(s, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0){
|
||||
if (errno == EACCES)
|
||||
clicon_err(OE_CFG, errno, "connecting unix socket: %s.\n"
|
||||
clicon_err(OE_CFG, errno, "connecting unix socket: %s."
|
||||
"Client should be member of group $CLICON_SOCK_GROUP: ",
|
||||
sockpath);
|
||||
else
|
||||
|
|
@ -273,7 +273,7 @@ msg_dump(struct clicon_msg *msg)
|
|||
for (i=0; i<ntohl(msg->op_len); i++){
|
||||
snprintf(buf, sizeof(buf), "%s%02x", buf2, ((char*)msg)[i]&0xff);
|
||||
if ((i+1)%32==0){
|
||||
clicon_debug(2, buf);
|
||||
clicon_debug(2, "%s", buf);
|
||||
snprintf(buf, sizeof(buf), "%s:", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
|
|
@ -282,7 +282,7 @@ msg_dump(struct clicon_msg *msg)
|
|||
strncpy(buf2, buf, sizeof(buf2));
|
||||
}
|
||||
if (i%32)
|
||||
clicon_debug(2, buf);
|
||||
clicon_debug(2, "%s", buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -302,7 +302,7 @@ clicon_msg_send(int s,
|
|||
msg_dump(msg);
|
||||
if (atomicio((ssize_t (*)(int, void *, size_t))write,
|
||||
s, msg, ntohl(msg->op_len)) < 0){
|
||||
clicon_err(OE_CFG, errno, "%s", __FUNCTION__);
|
||||
clicon_err(OE_CFG, errno, "atomicio");
|
||||
clicon_log(LOG_WARNING, "%s: write: %s len:%u msg:%s", __FUNCTION__,
|
||||
strerror(errno), ntohs(msg->op_len), msg->op_body);
|
||||
goto done;
|
||||
|
|
@ -344,7 +344,7 @@ clicon_msg_rcv(int s,
|
|||
set_signal(SIGINT, atomicio_sig_handler, &oldhandler);
|
||||
|
||||
if ((hlen = atomicio(read, s, &hdr, sizeof(hdr))) < 0){
|
||||
clicon_err(OE_CFG, errno, "%s", __FUNCTION__);
|
||||
clicon_err(OE_CFG, errno, "atomicio");
|
||||
goto done;
|
||||
}
|
||||
if (hlen == 0){
|
||||
|
|
@ -353,7 +353,7 @@ clicon_msg_rcv(int s,
|
|||
goto done;
|
||||
}
|
||||
if (hlen != sizeof(hdr)){
|
||||
clicon_err(OE_CFG, errno, "%s: header too short (%d)", __FUNCTION__, hlen);
|
||||
clicon_err(OE_CFG, errno, "header too short (%d)", hlen);
|
||||
goto done;
|
||||
}
|
||||
mlen = ntohl(hdr.op_len);
|
||||
|
|
@ -365,11 +365,11 @@ clicon_msg_rcv(int s,
|
|||
}
|
||||
memcpy(*msg, &hdr, hlen);
|
||||
if ((len2 = atomicio(read, s, (*msg)->op_body, mlen - sizeof(hdr))) < 0){
|
||||
clicon_err(OE_CFG, errno, "%s: read", __FUNCTION__);
|
||||
clicon_err(OE_CFG, errno, "read");
|
||||
goto done;
|
||||
}
|
||||
if (len2 != mlen - sizeof(hdr)){
|
||||
clicon_err(OE_CFG, errno, "%s: body too short", __FUNCTION__);
|
||||
clicon_err(OE_CFG, errno, "body too short");
|
||||
goto done;
|
||||
}
|
||||
if (debug > 1)
|
||||
|
|
@ -504,7 +504,7 @@ clicon_rpc(int s,
|
|||
if (clicon_msg_rcv(s, &reply, &eof) < 0)
|
||||
goto done;
|
||||
if (eof){
|
||||
clicon_err(OE_PROTO, ESHUTDOWN, "%s: Socket unexpected close", __FUNCTION__);
|
||||
clicon_err(OE_PROTO, ESHUTDOWN, "Socket unexpected close");
|
||||
close(s);
|
||||
errno = ESHUTDOWN;
|
||||
goto done;
|
||||
|
|
|
|||
102
lib/src/clixon_util_json.c
Normal file
102
lib/src/clixon_util_json.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
* JSON support functions.
|
||||
* JSON syntax is according to:
|
||||
* http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdint.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clixon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
/*
|
||||
* Turn this on to get a json parse and pretty print test program
|
||||
* Usage: xpath
|
||||
* read json from input
|
||||
* Example compile:
|
||||
gcc -g -o json -I. -I../clixon ./clixon_json.c -lclixon -lcligen
|
||||
* Example run:
|
||||
echo '{"foo": -23}' | ./json
|
||||
*/
|
||||
static int
|
||||
usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "usage:%s.\n\tInput on stdin\n", argv0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc,
|
||||
char **argv)
|
||||
{
|
||||
cxobj *xt = NULL;
|
||||
cxobj *xc;
|
||||
cbuf *cb = cbuf_new();
|
||||
|
||||
if (argc != 1){
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
clicon_log_init(__FILE__, LOG_INFO, CLICON_LOG_STDERR);
|
||||
if (json_parse_file(0, NULL, &xt) < 0)
|
||||
goto done;
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
|
||||
clicon_xml2cbuf(cb, xc, 0, 0); /* print xml */
|
||||
fprintf(stdout, "%s", cbuf_get(cb));
|
||||
done:
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return 0;
|
||||
}
|
||||
107
lib/src/clixon_util_xml.c
Normal file
107
lib/src/clixon_util_xml.c
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
* XML support functions.
|
||||
* @see https://www.w3.org/TR/2008/REC-xml-20081126
|
||||
* https://www.w3.org/TR/2009/REC-xml-names-20091208
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clixon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
/*
|
||||
* Turn this on to get a xml parse and pretty print test program
|
||||
* Usage: xpath
|
||||
* read xml from input
|
||||
* Example compile:
|
||||
gcc -g -o xml -I. -I../clixon ./clixon_xml.c -lclixon -lcligen
|
||||
* Example run:
|
||||
echo "<a><b/></a>" | xml
|
||||
*/
|
||||
static int
|
||||
usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "usage:%s.\n\tInput on stdin\n", argv0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
cxobj *xt = NULL;
|
||||
cxobj *xc;
|
||||
cbuf *cb = cbuf_new();
|
||||
|
||||
if (argc != 1){
|
||||
usage(argv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (xml_parse_file(0, "</config>", NULL, &xt) < 0){
|
||||
fprintf(stderr, "xml parse error %s\n", clicon_err_reason);
|
||||
goto done;
|
||||
}
|
||||
xc = NULL;
|
||||
while ((xc = xml_child_each(xt, xc, -1)) != NULL)
|
||||
clicon_xml2cbuf(cb, xc, 0, 0); /* print xml */
|
||||
fprintf(stdout, "%s\n", cbuf_get(cb));
|
||||
#if 0
|
||||
cbuf_reset(cb);
|
||||
xmltree2cbuf(cb, xt, 0); /* dump data structures */
|
||||
fprintf(stderr, "%s\n", cbuf_get(cb));
|
||||
#endif
|
||||
done:
|
||||
if (xt)
|
||||
xml_free(xt);
|
||||
if (cb)
|
||||
cbuf_free(cb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
141
lib/src/clixon_util_xsl.c
Normal file
141
lib/src/clixon_util_xsl.c
Normal file
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
See https://www.w3.org/TR/xpath/
|
||||
|
||||
* Turn this on to get an xpath test program
|
||||
* Usage: xpath [<xpath>]
|
||||
* read xpath on first line and xml on rest of lines from input
|
||||
* Example compile:
|
||||
gcc -g -o xpath -I. -I../clixon ./clixon_xsl.c -lclixon -lcligen
|
||||
* Example run:
|
||||
echo "a\n<a><b/></a>" | xpath
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <fnmatch.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <syslog.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clixon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
|
||||
static int
|
||||
usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "usage:%s <xpath>.\n\tInput on stdin\n", argv0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int retval = -1;
|
||||
int i;
|
||||
cxobj **xv;
|
||||
cxobj *x;
|
||||
cxobj *xn;
|
||||
size_t xlen = 0;
|
||||
int c;
|
||||
int len;
|
||||
char *buf = NULL;
|
||||
int ret;
|
||||
|
||||
if (argc != 1){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
/* First read xpath */
|
||||
len = 1024; /* any number is fine */
|
||||
if ((buf = malloc(len)) == NULL){
|
||||
perror("pt_file malloc");
|
||||
return -1;
|
||||
}
|
||||
memset(buf, 0, len);
|
||||
i = 0;
|
||||
while (1){
|
||||
if ((ret = read(0, &c, 1)) < 0){
|
||||
perror("read");
|
||||
goto done;
|
||||
}
|
||||
if (ret == 0)
|
||||
break;
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (len==i){
|
||||
if ((buf = realloc(buf, 2*len)) == NULL){
|
||||
fprintf(stderr, "%s: realloc: %s\n", __FUNCTION__, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
memset(buf+len, 0, len);
|
||||
len *= 2;
|
||||
}
|
||||
buf[i++] = (char)(c&0xff);
|
||||
}
|
||||
x = NULL;
|
||||
if (xml_parse_file(0, "</clicon>", NULL, &x) < 0){
|
||||
fprintf(stderr, "Error: parsing: %s\n", clicon_err_reason);
|
||||
return -1;
|
||||
}
|
||||
if (xpath_vec(x, "%s", &xv, &xlen, buf) < 0)
|
||||
return -1;
|
||||
if (xv){
|
||||
for (i=0; i<xlen; i++){
|
||||
xn = xv[i];
|
||||
fprintf(stdout, "%d:", i);
|
||||
clicon_xml2file(stdout, xn, 0, 0);
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
free(xv);
|
||||
}
|
||||
retval = 0;
|
||||
done:
|
||||
if (x)
|
||||
xml_free(x);
|
||||
return retval;
|
||||
}
|
||||
93
lib/src/clixon_util_yang.c
Normal file
93
lib/src/clixon_util_yang.c
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
*
|
||||
***** BEGIN LICENSE BLOCK *****
|
||||
|
||||
Copyright (C) 2009-2018 Olof Hagsand and Benny Holmgren
|
||||
|
||||
This file is part of CLIXON.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Alternatively, the contents of this file may be used under the terms of
|
||||
the GNU General Public License Version 3 or later (the "GPL"),
|
||||
in which case the provisions of the GPL are applicable instead
|
||||
of those above. If you wish to allow use of your version of this file only
|
||||
under the terms of the GPL, and not to allow others to
|
||||
use your version of this file under the terms of Apache License version 2,
|
||||
indicate your decision by deleting the provisions above and replace them with
|
||||
the notice and other provisions required by the GPL. If you do not delete
|
||||
the provisions above, a recipient may use your version of this file under
|
||||
the terms of any one of the Apache License version 2 or the GPL.
|
||||
|
||||
***** END LICENSE BLOCK *****
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#define __USE_GNU /* strverscmp */
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <regex.h>
|
||||
#include <dirent.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include <libgen.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
|
||||
/* cligen */
|
||||
#include <cligen/cligen.h>
|
||||
|
||||
/* clixon */
|
||||
#include <clixon/clixon.h>
|
||||
|
||||
/*
|
||||
*/
|
||||
static int
|
||||
usage(char *argv0)
|
||||
{
|
||||
fprintf(stderr, "usage:%s.\n\tInput on stdin\n", argv0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
yang_spec *yspec = NULL;
|
||||
|
||||
if (argc != 1){
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if ((yspec = yspec_new()) == NULL)
|
||||
goto done;
|
||||
if (yang_parse_file(0, "yang test", yspec) < 0){
|
||||
fprintf(stderr, "xml parse error %s\n", clicon_err_reason);
|
||||
return -1;
|
||||
}
|
||||
yang_print(stdout, (yang_node*)yspec);
|
||||
done:
|
||||
if (yspec)
|
||||
yspec_free(yspec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1391,7 +1391,7 @@ xml_parse_file(int fd,
|
|||
ptr = xmlbuf;
|
||||
while (1){
|
||||
if ((ret = read(fd, &ch, 1)) < 0){
|
||||
clicon_err(OE_XML, errno, "read: [pid:%d]\n",
|
||||
clicon_err(OE_XML, errno, "read: [pid:%d]",
|
||||
(int)getpid());
|
||||
break;
|
||||
}
|
||||
|
|
@ -1806,7 +1806,7 @@ xml_body_parse(cxobj *xb,
|
|||
goto done;
|
||||
}
|
||||
if (cvret == 0){ /* parsing failed */
|
||||
clicon_err(OE_XML, errno, "Parsing CV: %s", &reason);
|
||||
clicon_err(OE_XML, errno, "Parsing CV: %s", reason);
|
||||
if (reason)
|
||||
free(reason);
|
||||
}
|
||||
|
|
@ -1939,7 +1939,7 @@ xml_operation2str(enum operation_type op)
|
|||
* Example run:
|
||||
echo "<a><b/></a>" | xml
|
||||
*/
|
||||
#if 0 /* Test program */
|
||||
#if 1 /* Test program */
|
||||
|
||||
static int
|
||||
usage(char *argv0)
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ xmldb_plugin_load(clicon_handle h,
|
|||
dlerror(); /* Clear any existing error */
|
||||
if ((handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL)) == NULL) {
|
||||
error = (char*)dlerror();
|
||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s\n", error ? error : "Unknown error");
|
||||
clicon_err(OE_PLUGIN, errno, "dlopen: %s", error ? error : "Unknown error");
|
||||
goto done;
|
||||
}
|
||||
/* Try v1 */
|
||||
|
|
@ -162,7 +162,7 @@ xmldb_plugin_unload(clicon_handle h)
|
|||
dlerror(); /* Clear any existing error */
|
||||
if (dlclose(handle) != 0) {
|
||||
error = (char*)dlerror();
|
||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s\n", error ? error : "Unknown error");
|
||||
clicon_err(OE_PLUGIN, errno, "dlclose: %s", error ? error : "Unknown error");
|
||||
/* Just report no -1 return*/
|
||||
}
|
||||
retval = 0;
|
||||
|
|
|
|||
|
|
@ -249,7 +249,7 @@ validate_leafref(cxobj *xt,
|
|||
clicon_err(OE_DB, 0, "Leafref %s requires path statement", ytype->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
if (xpath_vec(xt, ypath->ys_argument, &xvec, &xlen) < 0)
|
||||
if (xpath_vec(xt, "%s", &xvec, &xlen, ypath->ys_argument) < 0)
|
||||
goto done;
|
||||
for (i = 0; i < xlen; i++) {
|
||||
x = xvec[i];
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ int clixon_xml_parsewrap(void)
|
|||
<AMPERSAND>"lt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "<"; return CHARDATA;}
|
||||
<AMPERSAND>"gt; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = ">"; return CHARDATA;}
|
||||
<AMPERSAND>"apos; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;}
|
||||
<AMPERSAND>"aquot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "'"; return CHARDATA;}
|
||||
<AMPERSAND>"quot; " {BEGIN(_YA->ya_lex_state); clixon_xml_parselval.string = "\""; return CHARDATA;}
|
||||
|
||||
<CDATA>. { clixon_xml_parselval.string = yytext; return CHARDATA;}
|
||||
<CDATA>\n { clixon_xml_parselval.string = yytext;_YA->ya_linenum++; return (CHARDATA);}
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ xpath_parse_predicate(struct xpath_element *xe,
|
|||
}
|
||||
memset(xp, 0, sizeof(*xp));
|
||||
if ((xp->xp_expr = strdup(s)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
xp->xp_next = xe->xe_predicate;
|
||||
|
|
@ -236,7 +236,7 @@ xpath_element_new(enum axis_type atype,
|
|||
xe->xe_type = atype;
|
||||
if (str){
|
||||
if ((str1 = strdup(str)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (xpath_split(str1, &pred) < 0) /* Can be more predicates */
|
||||
|
|
@ -247,20 +247,20 @@ xpath_element_new(enum axis_type atype,
|
|||
*local = '\0';
|
||||
local++;
|
||||
if ((xe->xe_prefix = strdup(str1)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else
|
||||
local = str1;
|
||||
if ((xe->xe_str = strdup(local)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if ((xe->xe_str = strdup("*")) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -326,7 +326,7 @@ xpath_parse(char *xpath,
|
|||
int esc = 0;
|
||||
|
||||
if ((s0 = strdup(xpath)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
s = s0;
|
||||
|
|
@ -502,8 +502,7 @@ xpath_expr(cxobj *xcur,
|
|||
e_v=e;
|
||||
e_a = strsep(&e_v, "=");
|
||||
if (e_a == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: malformed expression: [@%s]",
|
||||
__FUNCTION__, e);
|
||||
clicon_err(OE_XML, errno, "malformed expression: [@%s]", e);
|
||||
goto done;
|
||||
}
|
||||
for (i=0; i<*vec0len; i++){
|
||||
|
|
@ -534,15 +533,13 @@ xpath_expr(cxobj *xcur,
|
|||
}
|
||||
}
|
||||
else{
|
||||
clicon_err(OE_XML, errno, "%s: malformed expression: [%s]",
|
||||
__FUNCTION__, e);
|
||||
clicon_err(OE_XML, errno, "malformed expression: [%s]", e);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
else{ /* name = expr */
|
||||
if ((tag = strsep(&e, "=")) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: malformed expression: [%s]",
|
||||
__FUNCTION__, e);
|
||||
clicon_err(OE_XML, errno, "malformed expression: [%s]", e);
|
||||
goto done;
|
||||
}
|
||||
/* Strip trailing spaces */
|
||||
|
|
@ -782,7 +779,7 @@ xpath_split(char *xpathstr,
|
|||
}
|
||||
}
|
||||
if (pe==NULL){
|
||||
clicon_err(OE_XML, errno, "%s: mismatched []: %s", __FUNCTION__, xpathstr);
|
||||
clicon_err(OE_XML, errno, "mismatched []: %s", xpathstr);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -859,7 +856,7 @@ xpath_choice(cxobj *xcur,
|
|||
size_t vec0len = 0;
|
||||
|
||||
if ((s0 = strdup(xpath0)) == NULL){
|
||||
clicon_err(OE_XML, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_XML, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
s2 = s1 = s0;
|
||||
|
|
|
|||
|
|
@ -45,11 +45,14 @@
|
|||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#define __USE_GNU /* strverscmp */
|
||||
#include <string.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <regex.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <syslog.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -74,6 +77,8 @@
|
|||
#include "clixon_yang_type.h"
|
||||
#include "clixon_yang_parse.h"
|
||||
|
||||
/* Size of json read buffer when reading from file*/
|
||||
#define BUFLEN 1024
|
||||
|
||||
/* Mapping between yang keyword string <--> clicon constants */
|
||||
static const map_str2int ykmap[] = {
|
||||
|
|
@ -158,7 +163,7 @@ yspec_new(void)
|
|||
yang_spec *yspec;
|
||||
|
||||
if ((yspec = malloc(sizeof(*yspec))) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: malloc", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "malloc");
|
||||
return NULL;
|
||||
}
|
||||
memset(yspec, 0, sizeof(*yspec));
|
||||
|
|
@ -176,7 +181,7 @@ ys_new(enum rfc_6020 keyw)
|
|||
yang_stmt *ys;
|
||||
|
||||
if ((ys = malloc(sizeof(*ys))) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: malloc", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "malloc");
|
||||
return NULL;
|
||||
}
|
||||
memset(ys, 0, sizeof(*ys));
|
||||
|
|
@ -184,7 +189,7 @@ ys_new(enum rfc_6020 keyw)
|
|||
/* The cvec contains stmt-specific variables. Only few stmts need variables so the
|
||||
cvec could be lazily created to save some heap and cycles. */
|
||||
if ((ys->ys_cvec = cvec_new(0)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cvec_new", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cvec_new");
|
||||
return NULL;
|
||||
}
|
||||
return ys;
|
||||
|
|
@ -247,7 +252,7 @@ yn_realloc(yang_node *yn)
|
|||
yn->yn_len++;
|
||||
|
||||
if ((yn->yn_stmt = realloc(yn->yn_stmt, (yn->yn_len)*sizeof(yang_stmt *))) == 0){
|
||||
clicon_err(OE_YANG, errno, "%s: realloc", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "realloc");
|
||||
return -1;
|
||||
}
|
||||
yn->yn_stmt[yn->yn_len - 1] = NULL; /* init field */
|
||||
|
|
@ -276,22 +281,22 @@ ys_cp(yang_stmt *ynew,
|
|||
ynew->ys_parent = NULL;
|
||||
if (yold->ys_stmt)
|
||||
if ((ynew->ys_stmt = calloc(yold->ys_len, sizeof(yang_stmt *))) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: calloc", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "calloc");
|
||||
goto done;
|
||||
}
|
||||
if (yold->ys_argument)
|
||||
if ((ynew->ys_argument = strdup(yold->ys_argument)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
if (yold->ys_cv)
|
||||
if ((ynew->ys_cv = cv_dup(yold->ys_cv)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cv_dup", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cv_dup");
|
||||
goto done;
|
||||
}
|
||||
if (yold->ys_cvec)
|
||||
if ((ynew->ys_cvec = cvec_dup(yold->ys_cvec)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cvec_dup", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cvec_dup");
|
||||
goto done;
|
||||
}
|
||||
if (yold->ys_typecache){
|
||||
|
|
@ -902,7 +907,7 @@ yang_print(FILE *f,
|
|||
cbuf *cb = NULL;
|
||||
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cbuf_new", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (yang_print_cbuf(cb, yn, 0) < 0)
|
||||
|
|
@ -998,14 +1003,14 @@ ys_populate_leaf(yang_stmt *ys,
|
|||
goto done;
|
||||
/* 2. Create the CV using cvtype and name it */
|
||||
if ((cv = cv_new(cvtype)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cv_new");
|
||||
goto done;
|
||||
}
|
||||
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64) /* XXX: Seems misplaced? / too specific */
|
||||
cv_dec64_n_set(cv, fraction_digits);
|
||||
|
||||
if (cv_name_set(cv, ys->ys_argument) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cv_new_set", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cv_new_set");
|
||||
goto done;
|
||||
}
|
||||
/* 3. Check if default value. Here we parse the string in the default-stmt
|
||||
|
|
@ -1083,7 +1088,7 @@ ys_populate_range(yang_stmt *ys,
|
|||
|
||||
yparent = ys->ys_parent; /* Find parent: type */
|
||||
if (yparent->yn_keyword != Y_TYPE){
|
||||
clicon_err(OE_YANG, 0, "%s: parent should be type", __FUNCTION__);
|
||||
clicon_err(OE_YANG, 0, "parent should be type");
|
||||
goto done;
|
||||
}
|
||||
if (yang_type_resolve(ys, (yang_stmt*)yparent, &yrestype,
|
||||
|
|
@ -1103,7 +1108,8 @@ ys_populate_range(yang_stmt *ys,
|
|||
}
|
||||
if ((maxstr = strstr(minstr, "..")) != NULL){
|
||||
if (strlen(maxstr) < 2){
|
||||
clicon_err(OE_YANG, 0, "range statement: %s not on the form: <int>..<int>");
|
||||
clicon_err(OE_YANG, 0, "range statement: %s not on the form: <int>..<int>",
|
||||
ys->ys_argument);
|
||||
goto done;
|
||||
}
|
||||
minstr[maxstr-minstr] = '\0';
|
||||
|
|
@ -1499,7 +1505,7 @@ yang_expand(yang_node *yn)
|
|||
size = (yn->yn_len - i - 1)*sizeof(struct yang_stmt *);
|
||||
yn->yn_len += glen - 1;
|
||||
if (glen && (yn->yn_stmt = realloc(yn->yn_stmt, (yn->yn_len)*sizeof(yang_stmt *))) == 0){
|
||||
clicon_err(OE_YANG, errno, "%s: realloc", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "realloc");
|
||||
return -1;
|
||||
}
|
||||
/* Then move all existing elements up from i+1 (not uses-stmt) */
|
||||
|
|
@ -1540,10 +1546,10 @@ yang_expand(yang_node *yn)
|
|||
* Syntax parsing. A string is input and a syntax-tree is returned (or error).
|
||||
* A variable record is also returned containing a list of (global) variable values.
|
||||
* (cloned from cligen)
|
||||
* @param h CLICON handle
|
||||
* @param str String of yang statements
|
||||
* @param name Log string, typically filename
|
||||
* @param ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] str String of yang statements
|
||||
* @param[in] name Log string, typically filename
|
||||
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @retval ymod Top-level yang (sub)module
|
||||
* @retval NULL Error encountered
|
||||
* Calling order:
|
||||
|
|
@ -1554,15 +1560,17 @@ yang_expand(yang_node *yn)
|
|||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||
*/
|
||||
static yang_stmt *
|
||||
yang_parse_str(clicon_handle h,
|
||||
char *str,
|
||||
yang_parse_str(char *str,
|
||||
const char *name, /* just for errs */
|
||||
yang_spec *yspec)
|
||||
{
|
||||
struct clicon_yang_yacc_arg yy = {0,};
|
||||
yang_stmt *ymod = NULL;
|
||||
|
||||
yy.yy_handle = h;
|
||||
if (yspec == NULL){
|
||||
clicon_err(OE_YANG, 0, "Yang parse need top level yang spec");
|
||||
goto done;
|
||||
}
|
||||
yy.yy_name = (char*)name;
|
||||
yy.yy_linenum = 1;
|
||||
yy.yy_parse_string = str;
|
||||
|
|
@ -1595,15 +1603,66 @@ yang_parse_str(clicon_handle h,
|
|||
return ymod; /* top-level (sub)module */
|
||||
}
|
||||
|
||||
/*! Read an opened file into a string and call yang string parsing
|
||||
/*! Parse yang spec from an open file descriptor
|
||||
* @param[in] fd File descriptor containing the YANG file as ASCII characters
|
||||
* @param[in] name For debug, eg filename
|
||||
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @retval ymod Top-level yang (sub)module
|
||||
* @retval NULL Error
|
||||
*/
|
||||
yang_stmt *
|
||||
yang_parse_file(int fd,
|
||||
const char *name,
|
||||
yang_spec *ysp)
|
||||
{
|
||||
char *buf = NULL;
|
||||
int i;
|
||||
int c;
|
||||
int len;
|
||||
yang_stmt *ymod = NULL;
|
||||
int ret;
|
||||
|
||||
len = BUFLEN; /* any number is fine */
|
||||
if ((buf = malloc(len)) == NULL){
|
||||
perror("pt_file malloc");
|
||||
return NULL;
|
||||
}
|
||||
memset(buf, 0, len);
|
||||
i = 0; /* position in buf */
|
||||
while (1){ /* read the whole file */
|
||||
if ((ret = read(fd, &c, 1)) < 0){
|
||||
clicon_err(OE_XML, errno, "read");
|
||||
break;
|
||||
}
|
||||
if (ret == 0)
|
||||
break; /* eof */
|
||||
if (len==i){
|
||||
if ((buf = realloc(buf, 2*len)) == NULL){
|
||||
clicon_err(OE_XML, errno, "realloc");
|
||||
goto done;
|
||||
}
|
||||
memset(buf+len, 0, len);
|
||||
len *= 2;
|
||||
}
|
||||
buf[i++] = (char)(c&0xff);
|
||||
} /* read a line */
|
||||
if ((ymod = yang_parse_str(buf, name, ysp)) < 0)
|
||||
goto done;
|
||||
done:
|
||||
if (buf)
|
||||
free(buf);
|
||||
return ymod; /* top-level (sub)module */
|
||||
}
|
||||
|
||||
/*! Open a file, read into a string and invoke yang parsing
|
||||
*
|
||||
* Similar to clicon_yang_str(), just read a file first
|
||||
* (cloned from cligen)
|
||||
* @param h CLICON handle
|
||||
* @param filename Name of file
|
||||
* @param ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @retval ymod Top-level yang (sub)module
|
||||
* @retval NULL Error encountered
|
||||
* @param[in] h CLICON handle
|
||||
* @param[in] filename Name of file
|
||||
* @param[in] ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @retval ymod Top-level yang (sub)module
|
||||
* @retval NULL Error encountered
|
||||
|
||||
* The database symbols are inserted in alphabetical order.
|
||||
* Calling order:
|
||||
|
|
@ -1614,57 +1673,27 @@ yang_parse_str(clicon_handle h,
|
|||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||
*/
|
||||
static yang_stmt *
|
||||
yang_parse_file(clicon_handle h,
|
||||
const char *filename,
|
||||
yang_spec *ysp
|
||||
)
|
||||
yang_parse_filename(const char *filename,
|
||||
yang_spec *ysp)
|
||||
{
|
||||
char *buf = NULL;
|
||||
int i;
|
||||
int c;
|
||||
int len;
|
||||
yang_stmt *ymod = NULL;
|
||||
FILE *f = NULL;
|
||||
struct stat st;
|
||||
int fd = -1;
|
||||
struct stat st;
|
||||
|
||||
clicon_log(LOG_DEBUG, "Parsing yang file: %s", filename);
|
||||
if (stat(filename, &st) < 0){
|
||||
clicon_err(OE_YANG, errno, "%s not found", filename);
|
||||
goto done;
|
||||
}
|
||||
if ((f = fopen(filename, "r")) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "fopen(%s)", filename);
|
||||
if ((fd = open(filename, O_RDONLY)) < 0){
|
||||
clicon_err(OE_YANG, errno, "open(%s)", filename);
|
||||
goto done;
|
||||
}
|
||||
|
||||
len = 1024; /* any number is fine */
|
||||
if ((buf = malloc(len)) == NULL){
|
||||
perror("pt_file malloc");
|
||||
return NULL;
|
||||
}
|
||||
memset(buf, 0, len);
|
||||
|
||||
i = 0; /* position in buf */
|
||||
while (1){ /* read the whole file */
|
||||
if ((c = fgetc(f)) == EOF)
|
||||
break;
|
||||
if (len==i){
|
||||
if ((buf = realloc(buf, 2*len)) == NULL){
|
||||
fprintf(stderr, "%s: realloc: %s\n", __FUNCTION__, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
memset(buf+len, 0, len);
|
||||
len *= 2;
|
||||
}
|
||||
buf[i++] = (char)(c&0xff);
|
||||
} /* read a line */
|
||||
if ((ymod = yang_parse_str(h, buf, filename, ysp)) < 0)
|
||||
if ((ymod = yang_parse_file(fd, filename, ysp)) < 0)
|
||||
goto done;
|
||||
done:
|
||||
if (f)
|
||||
fclose(f);
|
||||
if (buf)
|
||||
free(buf);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return ymod; /* top-level (sub)module */
|
||||
}
|
||||
|
||||
|
|
@ -1679,8 +1708,7 @@ yang_parse_file(clicon_handle h,
|
|||
* @retval -1 Error
|
||||
*/
|
||||
static int
|
||||
yang_parse_find_match(clicon_handle h,
|
||||
const char *yang_dir,
|
||||
yang_parse_find_match(const char *yang_dir,
|
||||
const char *module,
|
||||
cbuf *fbuf)
|
||||
{
|
||||
|
|
@ -1724,7 +1752,7 @@ yang_parse_find_match(clicon_handle h,
|
|||
* @param[in] h CLICON handle
|
||||
* @param[in] yang_dir Directory where all YANG module files reside
|
||||
* @param[in] module Name of main YANG module. Or absolute file name.
|
||||
* @param[in] revision Optional module revision date
|
||||
* @param[in] revision Module revision date or NULL
|
||||
* @param[in] ysp Yang specification. Should have been created by caller using yspec_new
|
||||
* @retval ymod Top-level yang (sub)module
|
||||
* @retval NULL Error encountered
|
||||
|
|
@ -1737,8 +1765,7 @@ yang_parse_find_match(clicon_handle h,
|
|||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||
*/
|
||||
static yang_stmt *
|
||||
yang_parse_recurse(clicon_handle h,
|
||||
const char *yang_dir,
|
||||
yang_parse_recurse(const char *yang_dir,
|
||||
const char *module,
|
||||
const char *revision,
|
||||
yang_spec *ysp)
|
||||
|
|
@ -1752,26 +1779,26 @@ yang_parse_recurse(clicon_handle h,
|
|||
int nr;
|
||||
|
||||
if (module[0] == '/'){
|
||||
if ((ymod = yang_parse_file(h, module, ysp)) == NULL)
|
||||
if ((ymod = yang_parse_filename(module, ysp)) == NULL)
|
||||
goto done;
|
||||
}
|
||||
else {
|
||||
if ((fbuf = cbuf_new()) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cbuf_new", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
if (revision)
|
||||
cprintf(fbuf, "%s/%s@%s.yang", yang_dir, module, revision);
|
||||
else{
|
||||
/* No specific revision, Match a yang file */
|
||||
if ((nr = yang_parse_find_match(h, yang_dir, module, fbuf)) < 0)
|
||||
if ((nr = yang_parse_find_match(yang_dir, module, fbuf)) < 0)
|
||||
goto done;
|
||||
if (nr == 0){
|
||||
clicon_err(OE_YANG, errno, "No matching %s yang files found (expected module name or absolute filename)", module);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if ((ymod = yang_parse_file(h, cbuf_get(fbuf), ysp)) == NULL)
|
||||
if ((ymod = yang_parse_filename(cbuf_get(fbuf), ysp)) == NULL)
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
@ -1786,7 +1813,7 @@ yang_parse_recurse(clicon_handle h,
|
|||
subrevision = NULL;
|
||||
if (yang_find((yang_node*)ysp, Y_MODULE, modname) == NULL)
|
||||
/* recursive call */
|
||||
if (yang_parse_recurse(h, yang_dir, modname, subrevision, ysp) == NULL){
|
||||
if (yang_parse_recurse(yang_dir, modname, subrevision, ysp) == NULL){
|
||||
ymod = NULL;
|
||||
goto done;
|
||||
}
|
||||
|
|
@ -1845,7 +1872,7 @@ ys_schemanode_check(yang_stmt *ys,
|
|||
* @param[in] h CLICON handle
|
||||
* @param[in] yang_dir Directory where all YANG module files reside (except mainfile)
|
||||
* @param[in] mainmod Name of main YANG module. Or absolute file name.
|
||||
* @param[in] revision Optional main module revision date.
|
||||
* @param[in] revision Main module revision date string or NULL
|
||||
* @param[out] ysp Yang specification. Should ave been created by caller using yspec_new
|
||||
* @retval 0 Everything OK
|
||||
* @retval -1 Error encountered
|
||||
|
|
@ -1854,7 +1881,8 @@ ys_schemanode_check(yang_stmt *ys,
|
|||
* @note if mainmod is filename, revision is not considered.
|
||||
* Calling order:
|
||||
* yang_parse # Parse top-level yang module. Expand and populate yang tree
|
||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules, parse them and then recursively parse them
|
||||
* yang_parse_recurse # Parse one yang module, go through its (sub)modules,
|
||||
* parse them and then recursively parse them
|
||||
* yang_parse_file # Read yang file into a string
|
||||
* yang_parse_str # Set up yacc parser and call it given a string
|
||||
* clixon_yang_parseparse # Actual yang parsing using yacc
|
||||
|
|
@ -1870,7 +1898,7 @@ yang_parse(clicon_handle h,
|
|||
yang_stmt *ymod; /* Top-level yang (sub)module */
|
||||
|
||||
/* Step 1: parse from text to yang parse-tree. */
|
||||
if ((ymod = yang_parse_recurse(h, yang_dir, mainmodule, revision, ysp)) == NULL)
|
||||
if ((ymod = yang_parse_recurse(yang_dir, mainmodule, revision, ysp)) == NULL)
|
||||
goto done;
|
||||
/* Add top module name as dbspec-name */
|
||||
clicon_dbspec_name_set(h, ymod->ys_argument);
|
||||
|
|
@ -2080,13 +2108,13 @@ yang_abs_schema_nodeid(yang_spec *yspec,
|
|||
goto done;
|
||||
}
|
||||
if ((vec = clicon_strsep(schema_nodeid, "/", &nvec)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: strsep", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "strsep");
|
||||
goto done;
|
||||
}
|
||||
/* Assume schema nodeid looks like: "/prefix:id[/prefix:id]*" */
|
||||
if (nvec < 2){
|
||||
clicon_err(OE_YANG, 0, "%s: NULL or truncated path: %s",
|
||||
__FUNCTION__, schema_nodeid);
|
||||
clicon_err(OE_YANG, 0, "NULL or truncated path: %s",
|
||||
schema_nodeid);
|
||||
goto done;
|
||||
}
|
||||
/* split <prefix>:<id> */
|
||||
|
|
@ -2095,7 +2123,7 @@ yang_abs_schema_nodeid(yang_spec *yspec,
|
|||
goto ok;
|
||||
}
|
||||
if ((prefix = strdup(vec[1])) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "%s: strdup", __FUNCTION__);
|
||||
clicon_err(OE_UNIX, errno, "strdup");
|
||||
goto done;
|
||||
}
|
||||
prefix[id-vec[1]] = '\0';
|
||||
|
|
@ -2183,7 +2211,7 @@ ys_parse(yang_stmt *ys,
|
|||
|
||||
assert(ys->ys_cv == NULL); /* Cv:s are parsed in different places, difficult to separate */
|
||||
if ((ys->ys_cv = cv_new(cvtype)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cv_new");
|
||||
goto done;
|
||||
}
|
||||
if ((cvret = cv_parse1(ys->ys_argument, ys->ys_cv, &reason)) < 0){ /* error */
|
||||
|
|
@ -2252,7 +2280,7 @@ ys_parse_sub(yang_stmt *ys,
|
|||
goto done;
|
||||
}
|
||||
if ((ys->ys_cv = cv_new(CGV_STRING)) == NULL){
|
||||
clicon_err(OE_YANG, errno, "%s: cv_new", __FUNCTION__);
|
||||
clicon_err(OE_YANG, errno, "cv_new");
|
||||
goto done;
|
||||
}
|
||||
if ((cvret = cv_parse1(extra, ys->ys_cv, &reason)) < 0){ /* error */
|
||||
|
|
@ -2334,9 +2362,9 @@ yang_spec_netconf(clicon_handle h)
|
|||
}
|
||||
|
||||
/*! Read, parse and save application yang specification as option
|
||||
* @param h clicon handle
|
||||
* @param f file to print to (if printspec enabled)
|
||||
* @param printspec print database (YANG) specification as read from file
|
||||
* @param[in] h clicon handle
|
||||
* @param[in] f file to print to (if printspec enabled)
|
||||
* @param[in] printspec print database (YANG) specification as read from file
|
||||
*/
|
||||
yang_spec*
|
||||
yang_spec_main(clicon_handle h)
|
||||
|
|
@ -2346,7 +2374,7 @@ yang_spec_main(clicon_handle h)
|
|||
char *yang_module;
|
||||
char *yang_revision;
|
||||
|
||||
if ((yang_dir = clicon_yang_dir(h)) == NULL){
|
||||
if ((yang_dir = clicon_yang_dir(h)) == NULL){
|
||||
clicon_err(OE_FATAL, 0, "CLICON_YANG_DIR option not set");
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ struct ys_stack{
|
|||
};
|
||||
|
||||
struct clicon_yang_yacc_arg{ /* XXX: mostly unrelevant */
|
||||
clicon_handle yy_handle; /* cligen_handle */
|
||||
char *yy_name; /* Name of syntax (for error string) */
|
||||
int yy_linenum; /* Number of \n in parsed buffer */
|
||||
char *yy_parse_string; /* original (copy of) parse string */
|
||||
|
|
|
|||
|
|
@ -260,7 +260,7 @@ ysp_add(struct clicon_yang_yacc_arg *yy,
|
|||
clicon_err(OE_YANG, errno, "No stack");
|
||||
goto err;
|
||||
}
|
||||
yn = ystack->ys_node;
|
||||
assert(yn = ystack->ys_node);
|
||||
if ((ys = ys_new(keyword)) == NULL)
|
||||
goto err;
|
||||
/* NOTE: does not make a copy of string, ie argument is 'consumed' here */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#define __USE_GNU /* strverscmp */
|
||||
|
|
@ -354,7 +355,7 @@ clicon_type2cv(char *origtype,
|
|||
if (restype != NULL){
|
||||
yang2cv_type(restype, cvtype);
|
||||
if (*cvtype == CGV_ERR){
|
||||
clicon_err(OE_DB, 0, "%s: \"%s\" type not translated", __FUNCTION__, restype);
|
||||
clicon_err(OE_DB, 0, "\"%s\" type not translated", restype);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -365,7 +366,7 @@ clicon_type2cv(char *origtype,
|
|||
*/
|
||||
yang2cv_type(origtype, cvtype);
|
||||
if (*cvtype == CGV_ERR){
|
||||
clicon_err(OE_DB, 0, "%s: \"%s\": type not resolved", __FUNCTION__, origtype);
|
||||
clicon_err(OE_DB, 0, "\"%s\": type not resolved", origtype);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -399,8 +400,8 @@ cv_validate1(cg_var *cv,
|
|||
int retval = 1; /* OK */
|
||||
int retval2;
|
||||
yang_stmt *yi = NULL;
|
||||
uint64_t u = 0;
|
||||
int64_t i = 0;
|
||||
unsigned int u = 0;
|
||||
int i = 0;
|
||||
char *str;
|
||||
int found;
|
||||
char **vec = NULL;
|
||||
|
|
@ -417,7 +418,7 @@ cv_validate1(cg_var *cv,
|
|||
i = cv_int8_get(cv);
|
||||
if (range_check(i, range_min, range_max, int8)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %ld", i);
|
||||
*reason = cligen_reason("Number out of range: %d", i);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -428,7 +429,7 @@ cv_validate1(cg_var *cv,
|
|||
i = cv_int16_get(cv);
|
||||
if (range_check(i, range_min, range_max, int16)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %ld", i);
|
||||
*reason = cligen_reason("Number out of range: %d", i);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -439,29 +440,31 @@ cv_validate1(cg_var *cv,
|
|||
i = cv_int32_get(cv);
|
||||
if (range_check(i, range_min, range_max, int32)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %ld", i);
|
||||
*reason = cligen_reason("Number out of range: %d", i);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CGV_INT64:
|
||||
case CGV_INT64:{
|
||||
int64_t i64;
|
||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
||||
i = cv_int64_get(cv);
|
||||
i64 = cv_int64_get(cv);
|
||||
if (range_check(i, range_min, range_max, int64)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %ld", i);
|
||||
*reason = cligen_reason("Number out of range: %" PRId64, i64);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CGV_UINT8:
|
||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
||||
u = cv_uint8_get(cv);
|
||||
if (range_check(u, range_min, range_max, uint8)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %lu", u);
|
||||
*reason = cligen_reason("Number out of range: %u", u);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -472,7 +475,7 @@ cv_validate1(cg_var *cv,
|
|||
u = cv_uint16_get(cv);
|
||||
if (range_check(u, range_min, range_max, uint16)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %lu", u);
|
||||
*reason = cligen_reason("Number out of range: %u", u);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -483,29 +486,31 @@ cv_validate1(cg_var *cv,
|
|||
u = cv_uint32_get(cv);
|
||||
if (range_check(u, range_min, range_max, uint32)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %lu", u);
|
||||
*reason = cligen_reason("Number out of range: %u", u);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CGV_UINT64:
|
||||
case CGV_UINT64:{
|
||||
uint64_t u64;
|
||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
||||
u = cv_uint64_get(cv);
|
||||
u64 = cv_uint64_get(cv);
|
||||
if (range_check(u, range_min, range_max, uint64)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %lu", u);
|
||||
*reason = cligen_reason("Number out of range: %" PRIu64, u64);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CGV_DEC64:
|
||||
if ((options & YANG_OPTIONS_RANGE) != 0){
|
||||
i = cv_int64_get(cv);
|
||||
if (range_check(i, range_min, range_max, int64)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("Number out of range: %ld", i);
|
||||
*reason = cligen_reason("Number out of range: %d", i);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -565,7 +570,7 @@ cv_validate1(cg_var *cv,
|
|||
u = strlen(str);
|
||||
if (range_check(u, range_min, range_max, uint64)){
|
||||
if (reason)
|
||||
*reason = cligen_reason("string length out of range: %lu", u);
|
||||
*reason = cligen_reason("string length out of range: %u", u);
|
||||
retval = 0;
|
||||
break;
|
||||
}
|
||||
|
|
@ -748,8 +753,8 @@ ys_cv_validate(cg_var *cv,
|
|||
if (cvtype == CGV_STRING && cv_type_get(ycv) == CGV_REST)
|
||||
;
|
||||
else {
|
||||
clicon_err(OE_DB, 0, "%s: Type mismatch data:%s != yang:%s",
|
||||
__FUNCTION__, cv_type2str(cvtype), cv_type2str(cv_type_get(ycv)));
|
||||
clicon_err(OE_DB, 0, "Type mismatch data:%s != yang:%s",
|
||||
cv_type2str(cvtype), cv_type2str(cv_type_get(ycv)));
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
|
@ -904,14 +909,14 @@ resolve_restrictions(yang_stmt *yrange,
|
|||
}
|
||||
|
||||
/*! Recursively resolve a yang type to built-in type with optional restrictions
|
||||
* @param [in] ys yang-stmt from where the current search is based
|
||||
* @param [in] ytype yang-stmt object containing currently resolving type
|
||||
* @param [out] yrestype resolved type. return built-in type or NULL. mandatory
|
||||
* @param [out] options pointer to flags field of optional values. optional
|
||||
* @param [out] mincv pointer to cv with min range or length. If options&YANG_OPTIONS_RANGE
|
||||
* @param [out] maxcv pointer to cv with max range or length. If options&YANG_OPTIONS_RANGE
|
||||
* @param [out] pattern pointer to static string of yang string pattern. optional
|
||||
* @param [out] fraction for decimal64, how many digits after period
|
||||
* @param[in] ys yang-stmt from where the current search is based
|
||||
* @param[in] ytype yang-stmt object containing currently resolving type
|
||||
* @param[out] yrestype resolved type. return built-in type or NULL. mandatory
|
||||
* @param[out] options pointer to flags field of optional values. optional
|
||||
* @param[out] mincv pointer to cv with min range or length. If options&YANG_OPTIONS_RANGE
|
||||
* @param[out] maxcv pointer to cv with max range or length. If options&YANG_OPTIONS_RANGE
|
||||
* @param[out] pattern pointer to static string of yang string pattern. optional
|
||||
* @param[out] fraction for decimal64, how many digits after period
|
||||
* @retval 0 OK. Note yrestype may still be NULL.
|
||||
* @retval -1 Error, clicon_err handles errors
|
||||
* The setting of the options argument has the following semantics:
|
||||
|
|
@ -996,7 +1001,7 @@ yang_type_resolve(yang_stmt *ys,
|
|||
if (rytypedef != NULL){ /* We have found a typedef */
|
||||
/* Find associated type statement */
|
||||
if ((rytype = yang_find((yang_node*)rytypedef, Y_TYPE, NULL)) == NULL){
|
||||
clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__);
|
||||
clicon_err(OE_DB, 0, "mandatory type object is not found");
|
||||
goto done;
|
||||
}
|
||||
/* recursively resolve this new type */
|
||||
|
|
@ -1034,14 +1039,14 @@ yang_type_resolve(yang_stmt *ys,
|
|||
* if (options & YANG_OPTIONS_PATTERN != 0)
|
||||
* printf("regexp: %s\n", pattern);
|
||||
* @endcode
|
||||
* @param [in] ys yang-stmt, leaf or leaf-list
|
||||
* @param [out] origtype original type may be derived or built-in
|
||||
* @param [out] yrestype pointer to resolved type stmt. should be built-in or NULL
|
||||
* @param [out] options pointer to flags field of optional values
|
||||
* @param [out] mincv pointer to cv of min range or length. optional
|
||||
* @param [out] maxcv pointer to cv of max range or length. optional
|
||||
* @param [out] pattern pointer to static string of yang string pattern. optional
|
||||
* @param [out] fraction for decimal64, how many digits after period
|
||||
* @param[in] ys yang-stmt, leaf or leaf-list
|
||||
* @param[out] origtype original type may be derived or built-in
|
||||
* @param[out] yrestype pointer to resolved type stmt. should be built-in or NULL
|
||||
* @param[out] options pointer to flags field of optional values
|
||||
* @param[out] mincv pointer to cv of min range or length. optional
|
||||
* @param[out] maxcv pointer to cv of max range or length. optional
|
||||
* @param[out] pattern pointer to static string of yang string pattern. optional
|
||||
* @param[out] fraction for decimal64, how many digits after period
|
||||
* @retval 0 OK, but note that restype==NULL means not resolved.
|
||||
* @retval -1 Error, clicon_err handles errors
|
||||
* The setting of the options argument has the following semantics:
|
||||
|
|
@ -1071,7 +1076,7 @@ yang_type_get(yang_stmt *ys,
|
|||
*options = 0x0;
|
||||
/* Find mandatory type */
|
||||
if ((ytype = yang_find((yang_node*)ys, Y_TYPE, NULL)) == NULL){
|
||||
clicon_err(OE_DB, 0, "%s: mandatory type object is not found", __FUNCTION__);
|
||||
clicon_err(OE_DB, 0, "mandatory type object is not found");
|
||||
goto done;
|
||||
}
|
||||
/* XXX: here we seem to have some problems if type is union */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue